Fossil SCM

Update autosetup to the latest version

steveb 2014-08-08 02:26 trunk
Commit 93fb7c774fed669e68266ce50342083db6da5bb7
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -925,11 +925,11 @@
925925
}
926926
927927
# Load module source in the global scope by executing the given command
928928
proc automf_load {args} {
929929
if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
930
- autosetup-full-error [error-dump $msg $opts]
930
+ autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
931931
}
932932
}
933933
934934
# Initial settings
935935
set autosetup(exe) $::argv0
@@ -1706,18 +1706,35 @@
17061706
return $msg
17071707
}
17081708
17091709
# Given the return from [catch {...} msg opts], returns an appropriate
17101710
# error message. A nice one for Jim and a less-nice one for Tcl.
1711
+# If 'fulltrace' is set, a full stack trace is provided.
1712
+# Otherwise a simple message is provided.
17111713
#
1712
-# This is designed for developer errors, e.g. in module code
1714
+# This is designed for developer errors, e.g. in module code or auto.def code
1715
+#
17131716
#
1714
-proc error-dump {msg opts} {
1717
+proc error-dump {msg opts fulltrace} {
17151718
if {$::autosetup(istcl)} {
1716
- return "Error: [dict get $opts -errorinfo]"
1719
+ if {$fulltrace} {
1720
+ return "Error: [dict get $opts -errorinfo]"
1721
+ } else {
1722
+ return "Error: $msg"
1723
+ }
17171724
} else {
1718
- return "Error: $msg\n[stackdump $opts(-errorinfo)]"
1725
+ lassign $opts(-errorinfo) p f l
1726
+ if {$f ne ""} {
1727
+ set result "$f:$l: Error: "
1728
+ }
1729
+ append result "$msg\n"
1730
+ if {$fulltrace} {
1731
+ append result [stackdump $opts(-errorinfo)]
1732
+ }
1733
+
1734
+ # Remove the trailing newline
1735
+ string trim $result
17191736
}
17201737
}
17211738
}
17221739
17231740
# ----- module text-formatting -----
@@ -1886,13 +1903,13 @@
18861903
# Entry/Exit
18871904
#
18881905
if {$autosetup(debug)} {
18891906
main $argv
18901907
}
1891
-if {[catch {main $argv} msg] == 1} {
1908
+if {[catch {main $argv} msg opts] == 1} {
18921909
show-notices
1893
- puts stderr [error-stacktrace $msg]
1894
- if {!$autosetup(debug) && !$autosetup(istcl)} {
1910
+ autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
1911
+ if {!$autosetup(debug)} {
18951912
puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
18961913
}
18971914
exit 1
18981915
}
18991916
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -925,11 +925,11 @@
925 }
926
927 # Load module source in the global scope by executing the given command
928 proc automf_load {args} {
929 if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
930 autosetup-full-error [error-dump $msg $opts]
931 }
932 }
933
934 # Initial settings
935 set autosetup(exe) $::argv0
@@ -1706,18 +1706,35 @@
1706 return $msg
1707 }
1708
1709 # Given the return from [catch {...} msg opts], returns an appropriate
1710 # error message. A nice one for Jim and a less-nice one for Tcl.
 
 
1711 #
1712 # This is designed for developer errors, e.g. in module code
 
1713 #
1714 proc error-dump {msg opts} {
1715 if {$::autosetup(istcl)} {
1716 return "Error: [dict get $opts -errorinfo]"
 
 
 
 
1717 } else {
1718 return "Error: $msg\n[stackdump $opts(-errorinfo)]"
 
 
 
 
 
 
 
 
 
 
1719 }
1720 }
1721 }
1722
1723 # ----- module text-formatting -----
@@ -1886,13 +1903,13 @@
1886 # Entry/Exit
1887 #
1888 if {$autosetup(debug)} {
1889 main $argv
1890 }
1891 if {[catch {main $argv} msg] == 1} {
1892 show-notices
1893 puts stderr [error-stacktrace $msg]
1894 if {!$autosetup(debug) && !$autosetup(istcl)} {
1895 puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
1896 }
1897 exit 1
1898 }
1899
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -925,11 +925,11 @@
925 }
926
927 # Load module source in the global scope by executing the given command
928 proc automf_load {args} {
929 if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
930 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
931 }
932 }
933
934 # Initial settings
935 set autosetup(exe) $::argv0
@@ -1706,18 +1706,35 @@
1706 return $msg
1707 }
1708
1709 # Given the return from [catch {...} msg opts], returns an appropriate
1710 # error message. A nice one for Jim and a less-nice one for Tcl.
1711 # If 'fulltrace' is set, a full stack trace is provided.
1712 # Otherwise a simple message is provided.
1713 #
1714 # This is designed for developer errors, e.g. in module code or auto.def code
1715 #
1716 #
1717 proc error-dump {msg opts fulltrace} {
1718 if {$::autosetup(istcl)} {
1719 if {$fulltrace} {
1720 return "Error: [dict get $opts -errorinfo]"
1721 } else {
1722 return "Error: $msg"
1723 }
1724 } else {
1725 lassign $opts(-errorinfo) p f l
1726 if {$f ne ""} {
1727 set result "$f:$l: Error: "
1728 }
1729 append result "$msg\n"
1730 if {$fulltrace} {
1731 append result [stackdump $opts(-errorinfo)]
1732 }
1733
1734 # Remove the trailing newline
1735 string trim $result
1736 }
1737 }
1738 }
1739
1740 # ----- module text-formatting -----
@@ -1886,13 +1903,13 @@
1903 # Entry/Exit
1904 #
1905 if {$autosetup(debug)} {
1906 main $argv
1907 }
1908 if {[catch {main $argv} msg opts] == 1} {
1909 show-notices
1910 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
1911 if {!$autosetup(debug)} {
1912 puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
1913 }
1914 exit 1
1915 }
1916
--- autosetup/cc-shared.tcl
+++ autosetup/cc-shared.tcl
@@ -94,10 +94,19 @@
9494
define SHOBJ_LDFLAGS -b
9595
define SH_CFLAGS +z
9696
define SH_LINKFLAGS -Wl,+s
9797
define LD_LIBRARY_PATH SHLIB_PATH
9898
}
99
+ *-*-haiku {
100
+ define SHOBJ_CFLAGS ""
101
+ define SHOBJ_LDFLAGS -shared
102
+ define SH_CFLAGS ""
103
+ define SH_LDFLAGS -shared
104
+ define SH_LINKFLAGS ""
105
+ define SH_SOPREFIX ""
106
+ define LD_LIBRARY_PATH LIBRARY_PATH
107
+ }
99108
}
100109
101110
if {![is-defined SHOBJ_LDFLAGS_R]} {
102111
define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
103112
}
104113
--- autosetup/cc-shared.tcl
+++ autosetup/cc-shared.tcl
@@ -94,10 +94,19 @@
94 define SHOBJ_LDFLAGS -b
95 define SH_CFLAGS +z
96 define SH_LINKFLAGS -Wl,+s
97 define LD_LIBRARY_PATH SHLIB_PATH
98 }
 
 
 
 
 
 
 
 
 
99 }
100
101 if {![is-defined SHOBJ_LDFLAGS_R]} {
102 define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
103 }
104
--- autosetup/cc-shared.tcl
+++ autosetup/cc-shared.tcl
@@ -94,10 +94,19 @@
94 define SHOBJ_LDFLAGS -b
95 define SH_CFLAGS +z
96 define SH_LINKFLAGS -Wl,+s
97 define LD_LIBRARY_PATH SHLIB_PATH
98 }
99 *-*-haiku {
100 define SHOBJ_CFLAGS ""
101 define SHOBJ_LDFLAGS -shared
102 define SH_CFLAGS ""
103 define SH_LDFLAGS -shared
104 define SH_LINKFLAGS ""
105 define SH_SOPREFIX ""
106 define LD_LIBRARY_PATH LIBRARY_PATH
107 }
108 }
109
110 if {![is-defined SHOBJ_LDFLAGS_R]} {
111 define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
112 }
113
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -333,11 +333,11 @@
333333
}
334334
-libs {
335335
# Note that new libraries are added before previous libraries
336336
set new($name) [list {*}$value {*}$new($name)]
337337
}
338
- -link - -lang {
338
+ -link - -lang - -nooutput {
339339
set new($name) $value
340340
}
341341
-source - -sourcefile - -code {
342342
# XXX: These probably are only valid directly from cctest
343343
set new($name) $value
@@ -428,10 +428,11 @@
428428
## -lang c|c++ Use the C (default) or C++ compiler
429429
## -libs liblist List of libraries to link, e.g. {-ldl -lm}
430430
## -code code Code to compile in the body of main()
431431
## -source code Compile a complete program. Ignore -includes, -declare and -code
432432
## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
433
+## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
433434
#
434435
# Unless -source or -sourcefile is specified, the C program looks like:
435436
#
436437
## #include <firstinclude> /* same for remaining includes in the list */
437438
##
@@ -521,11 +522,12 @@
521522
}
522523
523524
writefile $src $lines\n
524525
525526
set ok 1
526
- if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} {
527
+ set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
528
+ if {$err || ($opts(-nooutput) && [string length $result])} {
527529
configlog "Failed: [join $cmdline]"
528530
configlog $result
529531
configlog "============"
530532
configlog "The failed code was:"
531533
configlog $lines
@@ -671,27 +673,27 @@
671673
}
672674
673675
define CCACHE [find-an-executable [get-env CCACHE ccache]]
674676
675677
# Initial cctest settings
676
-cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}}
678
+cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
677679
set autosetup(cc-include-deps) {}
678680
679681
msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
680682
if {[get-define CXX] ne "false"} {
681683
msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]"
682684
}
683685
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
684686
685
-# On Darwin, we prefer to use -gstabs to avoid creating .dSYM directories
686
-# but some compilers don't support -gstabs, so test for it here.
687
+# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
688
+# but some compilers may not support it, so test here.
687689
switch -glob -- [get-define host] {
688690
*-*-darwin* {
689
- if {[cctest -cflags {-gstabs}]} {
690
- define cc-default-debug -gstabs
691
+ if {[cctest -cflags {-g0}]} {
692
+ define cc-default-debug -g0
691693
}
692694
}
693695
}
694696
695697
if {![cc-check-includes stdlib.h]} {
696698
user-error "Compiler does not work. See config.log"
697699
}
698700
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -333,11 +333,11 @@
333 }
334 -libs {
335 # Note that new libraries are added before previous libraries
336 set new($name) [list {*}$value {*}$new($name)]
337 }
338 -link - -lang {
339 set new($name) $value
340 }
341 -source - -sourcefile - -code {
342 # XXX: These probably are only valid directly from cctest
343 set new($name) $value
@@ -428,10 +428,11 @@
428 ## -lang c|c++ Use the C (default) or C++ compiler
429 ## -libs liblist List of libraries to link, e.g. {-ldl -lm}
430 ## -code code Code to compile in the body of main()
431 ## -source code Compile a complete program. Ignore -includes, -declare and -code
432 ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
 
433 #
434 # Unless -source or -sourcefile is specified, the C program looks like:
435 #
436 ## #include <firstinclude> /* same for remaining includes in the list */
437 ##
@@ -521,11 +522,12 @@
521 }
522
523 writefile $src $lines\n
524
525 set ok 1
526 if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} {
 
527 configlog "Failed: [join $cmdline]"
528 configlog $result
529 configlog "============"
530 configlog "The failed code was:"
531 configlog $lines
@@ -671,27 +673,27 @@
671 }
672
673 define CCACHE [find-an-executable [get-env CCACHE ccache]]
674
675 # Initial cctest settings
676 cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}}
677 set autosetup(cc-include-deps) {}
678
679 msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
680 if {[get-define CXX] ne "false"} {
681 msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]"
682 }
683 msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
684
685 # On Darwin, we prefer to use -gstabs to avoid creating .dSYM directories
686 # but some compilers don't support -gstabs, so test for it here.
687 switch -glob -- [get-define host] {
688 *-*-darwin* {
689 if {[cctest -cflags {-gstabs}]} {
690 define cc-default-debug -gstabs
691 }
692 }
693 }
694
695 if {![cc-check-includes stdlib.h]} {
696 user-error "Compiler does not work. See config.log"
697 }
698
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -333,11 +333,11 @@
333 }
334 -libs {
335 # Note that new libraries are added before previous libraries
336 set new($name) [list {*}$value {*}$new($name)]
337 }
338 -link - -lang - -nooutput {
339 set new($name) $value
340 }
341 -source - -sourcefile - -code {
342 # XXX: These probably are only valid directly from cctest
343 set new($name) $value
@@ -428,10 +428,11 @@
428 ## -lang c|c++ Use the C (default) or C++ compiler
429 ## -libs liblist List of libraries to link, e.g. {-ldl -lm}
430 ## -code code Code to compile in the body of main()
431 ## -source code Compile a complete program. Ignore -includes, -declare and -code
432 ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
433 ## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
434 #
435 # Unless -source or -sourcefile is specified, the C program looks like:
436 #
437 ## #include <firstinclude> /* same for remaining includes in the list */
438 ##
@@ -521,11 +522,12 @@
522 }
523
524 writefile $src $lines\n
525
526 set ok 1
527 set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
528 if {$err || ($opts(-nooutput) && [string length $result])} {
529 configlog "Failed: [join $cmdline]"
530 configlog $result
531 configlog "============"
532 configlog "The failed code was:"
533 configlog $lines
@@ -671,27 +673,27 @@
673 }
674
675 define CCACHE [find-an-executable [get-env CCACHE ccache]]
676
677 # Initial cctest settings
678 cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
679 set autosetup(cc-include-deps) {}
680
681 msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
682 if {[get-define CXX] ne "false"} {
683 msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]"
684 }
685 msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
686
687 # On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
688 # but some compilers may not support it, so test here.
689 switch -glob -- [get-define host] {
690 *-*-darwin* {
691 if {[cctest -cflags {-g0}]} {
692 define cc-default-debug -g0
693 }
694 }
695 }
696
697 if {![cc-check-includes stdlib.h]} {
698 user-error "Compiler does not work. See config.log"
699 }
700
+1914 -1579
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1
-/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
1
+/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
22
#define _GNU_SOURCE
33
#define JIM_TCL_COMPAT
44
#define JIM_REFERENCES
55
#define JIM_ANSIC
66
#define JIM_REGEXP
@@ -42,14 +42,19 @@
4242
#define HAVE_ISATTY
4343
#define HAVE_SYS_TIME_H
4444
#define HAVE_DIRENT_H
4545
#define HAVE_UNISTD_H
4646
#endif
47
+#define JIM_VERSION 75
4748
#ifndef JIM_WIN32COMPAT_H
4849
#define JIM_WIN32COMPAT_H
4950
5051
52
+
53
+#ifdef __cplusplus
54
+extern "C" {
55
+#endif
5156
5257
5358
#if defined(_WIN32) || defined(WIN32)
5459
5560
#define HAVE_DLOPEN
@@ -105,17 +110,31 @@
105110
} DIR;
106111
107112
DIR *opendir(const char *name);
108113
int closedir(DIR *dir);
109114
struct dirent *readdir(DIR *dir);
110
-#endif
115
+
116
+#elif defined(__MINGW32__)
117
+
118
+#define strtod __strtod
119
+
120
+#endif
111121
112122
#endif
123
+
124
+#ifdef __cplusplus
125
+}
126
+#endif
113127
114128
#endif
115129
#ifndef UTF8_UTIL_H
116130
#define UTF8_UTIL_H
131
+
132
+#ifdef __cplusplus
133
+extern "C" {
134
+#endif
135
+
117136
118137
119138
#define MAX_UTF8_LEN 4
120139
121140
int utf8_fromunicode(char *p, unsigned uc);
@@ -124,10 +143,11 @@
124143
#include <ctype.h>
125144
126145
127146
#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
128147
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
148
+#define utf8_getchars(CP, C) (*(CP) = (C), 1)
129149
#define utf8_upper(C) toupper(C)
130150
#define utf8_title(C) toupper(C)
131151
#define utf8_lower(C) tolower(C)
132152
#define utf8_index(C, I) (I)
133153
#define utf8_charlen(C) 1
@@ -134,10 +154,14 @@
134154
#define utf8_prev_len(S, L) 1
135155
136156
#else
137157
138158
#endif
159
+
160
+#ifdef __cplusplus
161
+}
162
+#endif
139163
140164
#endif
141165
142166
#ifndef __JIM__H
143167
#define __JIM__H
@@ -185,12 +209,10 @@
185209
#endif
186210
187211
#define UCHAR(c) ((unsigned char)(c))
188212
189213
190
-#define JIM_VERSION 73
191
-
192214
#define JIM_OK 0
193215
#define JIM_ERR 1
194216
#define JIM_RETURN 2
195217
#define JIM_BREAK 3
196218
#define JIM_CONTINUE 4
@@ -200,44 +222,34 @@
200222
#define JIM_EVAL 7
201223
202224
#define JIM_MAX_CALLFRAME_DEPTH 1000
203225
#define JIM_MAX_EVAL_DEPTH 2000
204226
205
-#define JIM_NONE 0
206
-#define JIM_ERRMSG 1
207
-
208
-#define JIM_UNSHARED 4
209
-#define JIM_MUSTEXIST 8
210
-
211
-
212
-#define JIM_GLOBAL_ONLY 0x100
227
+
228
+#define JIM_PRIV_FLAG_SHIFT 20
229
+
230
+#define JIM_NONE 0
231
+#define JIM_ERRMSG 1
232
+#define JIM_ENUM_ABBREV 2
233
+#define JIM_UNSHARED 4
234
+#define JIM_MUSTEXIST 8
213235
214236
215237
#define JIM_SUBST_NOVAR 1
216238
#define JIM_SUBST_NOCMD 2
217239
#define JIM_SUBST_NOESC 4
218240
#define JIM_SUBST_FLAG 128
219241
220
-
221
-#define JIM_NOTUSED(V) ((void) V)
222
-
223
-
224
-#define JIM_ENUM_ABBREV 2
225
-
226242
227243
#define JIM_CASESENS 0
228244
#define JIM_NOCASE 1
229245
230246
231247
#define JIM_PATH_LEN 1024
232248
233249
234
-#ifdef JIM_CRLF
235
-#define JIM_NL "\r\n"
236
-#else
237
-#define JIM_NL "\n"
238
-#endif
250
+#define JIM_NOTUSED(V) ((void) V)
239251
240252
#define JIM_LIBPATH "auto_path"
241253
#define JIM_INTERACTIVE "tcl_interactive"
242254
243255
@@ -267,21 +279,22 @@
267279
} Jim_HashTableType;
268280
269281
typedef struct Jim_HashTable {
270282
Jim_HashEntry **table;
271283
const Jim_HashTableType *type;
284
+ void *privdata;
272285
unsigned int size;
273286
unsigned int sizemask;
274287
unsigned int used;
275288
unsigned int collisions;
276
- void *privdata;
289
+ unsigned int uniq;
277290
} Jim_HashTable;
278291
279292
typedef struct Jim_HashTableIterator {
280293
Jim_HashTable *ht;
281
- int index;
282294
Jim_HashEntry *entry, *nextEntry;
295
+ int index;
283296
} Jim_HashTableIterator;
284297
285298
286299
#define JIM_HT_INITIAL_SIZE 16
287300
@@ -290,45 +303,45 @@
290303
if ((ht)->type->valDestructor) \
291304
(ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
292305
293306
#define Jim_SetHashVal(ht, entry, _val_) do { \
294307
if ((ht)->type->valDup) \
295
- entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
308
+ (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
296309
else \
297
- entry->u.val = (_val_); \
310
+ (entry)->u.val = (_val_); \
298311
} while(0)
299312
300313
#define Jim_FreeEntryKey(ht, entry) \
301314
if ((ht)->type->keyDestructor) \
302315
(ht)->type->keyDestructor((ht)->privdata, (entry)->key)
303316
304317
#define Jim_SetHashKey(ht, entry, _key_) do { \
305318
if ((ht)->type->keyDup) \
306
- entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
319
+ (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
307320
else \
308
- entry->key = (void *)(_key_); \
321
+ (entry)->key = (void *)(_key_); \
309322
} while(0)
310323
311324
#define Jim_CompareHashKeys(ht, key1, key2) \
312325
(((ht)->type->keyCompare) ? \
313
- (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
326
+ (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
314327
(key1) == (key2))
315328
316
-#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
329
+#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
317330
318331
#define Jim_GetHashEntryKey(he) ((he)->key)
319
-#define Jim_GetHashEntryVal(he) ((he)->val)
332
+#define Jim_GetHashEntryVal(he) ((he)->u.val)
320333
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
321334
#define Jim_GetHashTableSize(ht) ((ht)->size)
322335
#define Jim_GetHashTableUsed(ht) ((ht)->used)
323336
324337
325338
typedef struct Jim_Obj {
326
- int refCount;
327339
char *bytes;
328
- int length;
329340
const struct Jim_ObjType *typePtr;
341
+ int refCount;
342
+ int length;
330343
331344
union {
332345
333346
jim_wide wideValue;
334347
@@ -342,19 +355,19 @@
342355
void *ptr1;
343356
void *ptr2;
344357
} twoPtrValue;
345358
346359
struct {
347
- unsigned long callFrameId;
348360
struct Jim_Var *varPtr;
361
+ unsigned long callFrameId;
349362
int global;
350363
} varValue;
351364
352365
struct {
353
- unsigned long procEpoch;
354366
struct Jim_Obj *nsObj;
355367
struct Jim_Cmd *cmdPtr;
368
+ unsigned long procEpoch;
356369
} cmdValue;
357370
358371
struct {
359372
struct Jim_Obj **ele;
360373
int len;
@@ -380,12 +393,12 @@
380393
struct Jim_Obj *varNameObjPtr;
381394
struct Jim_Obj *indexObjPtr;
382395
} dictSubstValue;
383396
384397
struct {
385
- unsigned flags;
386398
void *compre;
399
+ unsigned flags;
387400
} regexpValue;
388401
struct {
389402
int line;
390403
int argc;
391404
} scriptLineValue;
@@ -454,21 +467,24 @@
454467
struct Jim_CallFrame *next;
455468
Jim_Obj *nsObj;
456469
Jim_Obj *fileNameObj;
457470
int line;
458471
Jim_Stack *localCommands;
472
+ int tailcall;
473
+ struct Jim_Obj *tailcallObj;
474
+ struct Jim_Cmd *tailcallCmd;
459475
} Jim_CallFrame;
460476
461477
typedef struct Jim_Var {
462478
Jim_Obj *objPtr;
463479
struct Jim_CallFrame *linkFramePtr;
464480
} Jim_Var;
465481
466482
467
-typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
483
+typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
468484
Jim_Obj *const *argv);
469
-typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
485
+typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
470486
471487
472488
473489
typedef struct Jim_Cmd {
474490
int inUse;
@@ -475,12 +491,12 @@
475491
int isproc;
476492
struct Jim_Cmd *prevCmd;
477493
union {
478494
struct {
479495
480
- Jim_CmdProc cmdProc;
481
- Jim_DelCmdProc delProc;
496
+ Jim_CmdProc *cmdProc;
497
+ Jim_DelCmdProc *delProc;
482498
void *privData;
483499
} native;
484500
struct {
485501
486502
Jim_Obj *argListObjPtr;
@@ -590,15 +606,11 @@
590606
Jim_Obj *finalizerCmdNamePtr;
591607
char tag[JIM_REFERENCE_TAGLEN+1];
592608
} Jim_Reference;
593609
594610
595
-
596611
#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
597
-
598
-
599
-
600612
#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
601613
602614
#define JIM_EXPORT
603615
604616
@@ -609,10 +621,11 @@
609621
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
610622
611623
612624
JIM_EXPORT char **Jim_GetEnviron(void);
613625
JIM_EXPORT void Jim_SetEnviron(char **env);
626
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
614627
615628
616629
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
617630
618631
@@ -665,12 +678,10 @@
665678
666679
667680
JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
668681
JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
669682
JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
670
-JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes,
671
- int length);
672683
JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
673684
Jim_Obj *objPtr);
674685
JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
675686
int *lenPtr);
676687
JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -742,13 +753,12 @@
742753
JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
743754
const char *name, const char *val);
744755
JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
745756
Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
746757
Jim_CallFrame *targetCallFrame);
747
-JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
748
- Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
749
-JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
758
+JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
759
+ Jim_Obj *nameObjPtr);
750760
JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
751761
Jim_Obj *nameObjPtr, int flags);
752762
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
753763
Jim_Obj *nameObjPtr, int flags);
754764
JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -807,10 +817,11 @@
807817
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
808818
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
809819
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
810820
JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
811821
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
822
+JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
812823
813824
814825
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
815826
int *intPtr);
816827
@@ -834,16 +845,10 @@
834845
double *doublePtr);
835846
JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
836847
double doubleValue);
837848
JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
838849
839
-
840
-JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
841
- const char *str);
842
-JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp,
843
- const char *str);
844
-
845850
846851
JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
847852
Jim_Obj *const *argv, const char *msg);
848853
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
849854
const char * const *tablePtr, int *indexPtr, const char *name, int flags);
@@ -877,18 +882,20 @@
877882
JIM_EXPORT void Jim_HistoryShow(void);
878883
879884
880885
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
881886
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
887
+JIM_EXPORT int Jim_IsBigEndian(void);
888
+
889
+#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
882890
883891
884892
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
885893
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
886894
887895
888896
JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
889
-
890897
891898
892899
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
893900
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
894901
@@ -910,16 +917,16 @@
910917
#define JIM_MODFLAG_HIDDEN 0x0001
911918
#define JIM_MODFLAG_FULLARGV 0x0002
912919
913920
914921
915
-typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
922
+typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
916923
917924
typedef struct {
918925
const char *cmd;
919926
const char *args;
920
- tclmod_cmd_function *function;
927
+ jim_subcmd_function *function;
921928
short minargs;
922929
short maxargs;
923930
unsigned short flags;
924931
} jim_subcmd_type;
925932
@@ -936,22 +943,16 @@
936943
937944
#endif
938945
#ifndef JIMREGEXP_H
939946
#define JIMREGEXP_H
940947
941
-#ifndef _JIMAUTOCONF_H
942
-#error Need jimautoconf.h
948
+
949
+#ifdef __cplusplus
950
+extern "C" {
943951
#endif
944952
945
-#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
946
-
947
-#include <regex.h>
948
-
949
-#else
950
-
951953
#include <stdlib.h>
952
-
953954
954955
typedef struct {
955956
int rm_so;
956957
int rm_eo;
957958
} regmatch_t;
@@ -1020,10 +1021,12 @@
10201021
int regcomp(regex_t *preg, const char *regex, int cflags);
10211022
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
10221023
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
10231024
void regfree(regex_t *preg);
10241025
1026
+#ifdef __cplusplus
1027
+}
10251028
#endif
10261029
10271030
#endif
10281031
int Jim_bootstrapInit(Jim_Interp *interp)
10291032
{
@@ -1086,10 +1089,15 @@
10861089
"\n"
10871090
"package require readdir\n"
10881091
"\n"
10891092
"\n"
10901093
"proc glob.globdir {dir pattern} {\n"
1094
+" if {[file exists $dir/$pattern]} {\n"
1095
+"\n"
1096
+" return $pattern\n"
1097
+" }\n"
1098
+"\n"
10911099
" set result {}\n"
10921100
" set files [readdir $dir]\n"
10931101
" lappend files . ..\n"
10941102
"\n"
10951103
" foreach name $files {\n"
@@ -1268,10 +1276,12 @@
12681276
{
12691277
if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
12701278
return JIM_ERR;
12711279
12721280
return Jim_EvalSource(interp, "stdlib.tcl", 1,
1281
+"\n"
1282
+"\n"
12731283
"\n"
12741284
"proc lambda {arglist args} {\n"
12751285
" tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
12761286
"}\n"
12771287
"\n"
@@ -1297,46 +1307,48 @@
12971307
"}\n"
12981308
"\n"
12991309
"\n"
13001310
"\n"
13011311
"\n"
1302
-"proc stacktrace {} {\n"
1312
+"proc stacktrace {{skip 0}} {\n"
13031313
" set trace {}\n"
1304
-" foreach level [range 1 [info level]] {\n"
1305
-" lassign [info frame -$level] p f l\n"
1306
-" lappend trace $p $f $l\n"
1314
+" incr skip\n"
1315
+" foreach level [range $skip [info level]] {\n"
1316
+" lappend trace {*}[info frame -$level]\n"
13071317
" }\n"
13081318
" return $trace\n"
13091319
"}\n"
13101320
"\n"
13111321
"\n"
13121322
"proc stackdump {stacktrace} {\n"
1313
-" set result {}\n"
1314
-" set count 0\n"
1323
+" set lines {}\n"
13151324
" foreach {l f p} [lreverse $stacktrace] {\n"
1316
-" if {$count} {\n"
1317
-" append result \\n\n"
1318
-" }\n"
1319
-" incr count\n"
1325
+" set line {}\n"
13201326
" if {$p ne \"\"} {\n"
1321
-" append result \"in procedure '$p' \"\n"
1327
+" append line \"in procedure '$p' \"\n"
13221328
" if {$f ne \"\"} {\n"
1323
-" append result \"called \"\n"
1329
+" append line \"called \"\n"
13241330
" }\n"
13251331
" }\n"
13261332
" if {$f ne \"\"} {\n"
1327
-" append result \"at file \\\"$f\\\", line $l\"\n"
1333
+" append line \"at file \\\"$f\\\", line $l\"\n"
1334
+" }\n"
1335
+" if {$line ne \"\"} {\n"
1336
+" lappend lines $line\n"
13281337
" }\n"
13291338
" }\n"
1330
-" return $result\n"
1339
+" join $lines \\n\n"
13311340
"}\n"
13321341
"\n"
13331342
"\n"
13341343
"\n"
13351344
"proc errorInfo {msg {stacktrace \"\"}} {\n"
13361345
" if {$stacktrace eq \"\"} {\n"
1346
+"\n"
13371347
" set stacktrace [info stacktrace]\n"
1348
+"\n"
1349
+" lappend stacktrace {*}[stacktrace 1]\n"
13381350
" }\n"
13391351
" lassign $stacktrace p f l\n"
13401352
" if {$f ne \"\"} {\n"
13411353
" set result \"Runtime Error: $f:$l: \"\n"
13421354
" }\n"
@@ -1363,25 +1375,46 @@
13631375
" }\n"
13641376
" return \"\"\n"
13651377
"}\n"
13661378
"\n"
13671379
"\n"
1368
-"proc {dict with} {dictVar args script} {\n"
1369
-" upvar $dictVar dict\n"
1380
+"proc {dict with} {&dictVar {args key} script} {\n"
13701381
" set keys {}\n"
1371
-" foreach {n v} [dict get $dict {*}$args] {\n"
1382
+" foreach {n v} [dict get $dictVar {*}$key] {\n"
13721383
" upvar $n var_$n\n"
13731384
" set var_$n $v\n"
13741385
" lappend keys $n\n"
13751386
" }\n"
13761387
" catch {uplevel 1 $script} msg opts\n"
1377
-" if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1388
+" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
13781389
" foreach n $keys {\n"
13791390
" if {[info exists var_$n]} {\n"
1380
-" dict set dict {*}$args $n [set var_$n]\n"
1391
+" dict set dictVar {*}$key $n [set var_$n]\n"
1392
+" } else {\n"
1393
+" dict unset dictVar {*}$key $n\n"
1394
+" }\n"
1395
+" }\n"
1396
+" }\n"
1397
+" return {*}$opts $msg\n"
1398
+"}\n"
1399
+"\n"
1400
+"\n"
1401
+"proc {dict update} {&varName args script} {\n"
1402
+" set keys {}\n"
1403
+" foreach {n v} $args {\n"
1404
+" upvar $v var_$v\n"
1405
+" if {[dict exists $varName $n]} {\n"
1406
+" set var_$v [dict get $varName $n]\n"
1407
+" }\n"
1408
+" }\n"
1409
+" catch {uplevel 1 $script} msg opts\n"
1410
+" if {[info exists varName]} {\n"
1411
+" foreach {n v} $args {\n"
1412
+" if {[info exists var_$v]} {\n"
1413
+" dict set varName $n [set var_$v]\n"
13811414
" } else {\n"
1382
-" dict unset dict {*}$args $n\n"
1415
+" dict unset varName $n\n"
13831416
" }\n"
13841417
" }\n"
13851418
" }\n"
13861419
" return {*}$opts $msg\n"
13871420
"}\n"
@@ -1396,10 +1429,69 @@
13961429
" dict set dict $k $v\n"
13971430
" }\n"
13981431
" }\n"
13991432
" return $dict\n"
14001433
"}\n"
1434
+"\n"
1435
+"proc {dict replace} {dictionary {args {key value}}} {\n"
1436
+" if {[llength ${key value}] % 2} {\n"
1437
+" tailcall {dict replace}\n"
1438
+" }\n"
1439
+" tailcall dict merge $dictionary ${key value}\n"
1440
+"}\n"
1441
+"\n"
1442
+"\n"
1443
+"proc {dict lappend} {varName key {args value}} {\n"
1444
+" upvar $varName dict\n"
1445
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1446
+" set list [dict get $dict $key]\n"
1447
+" }\n"
1448
+" lappend list {*}$value\n"
1449
+" dict set dict $key $list\n"
1450
+"}\n"
1451
+"\n"
1452
+"\n"
1453
+"proc {dict append} {varName key {args value}} {\n"
1454
+" upvar $varName dict\n"
1455
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1456
+" set str [dict get $dict $key]\n"
1457
+" }\n"
1458
+" append str {*}$value\n"
1459
+" dict set dict $key $str\n"
1460
+"}\n"
1461
+"\n"
1462
+"\n"
1463
+"proc {dict incr} {varName key {increment 1}} {\n"
1464
+" upvar $varName dict\n"
1465
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1466
+" set value [dict get $dict $key]\n"
1467
+" }\n"
1468
+" incr value $increment\n"
1469
+" dict set dict $key $value\n"
1470
+"}\n"
1471
+"\n"
1472
+"\n"
1473
+"proc {dict remove} {dictionary {args key}} {\n"
1474
+" foreach k $key {\n"
1475
+" dict unset dictionary $k\n"
1476
+" }\n"
1477
+" return $dictionary\n"
1478
+"}\n"
1479
+"\n"
1480
+"\n"
1481
+"proc {dict values} {dictionary {pattern *}} {\n"
1482
+" dict keys [lreverse $dictionary] $pattern\n"
1483
+"}\n"
1484
+"\n"
1485
+"\n"
1486
+"proc {dict for} {vars dictionary script} {\n"
1487
+" if {[llength $vars] != 2} {\n"
1488
+" return -code error \"must have exactly two variable names\"\n"
1489
+" }\n"
1490
+" dict size $dictionary\n"
1491
+" tailcall foreach $vars $dictionary $script\n"
1492
+"}\n"
14011493
);
14021494
}
14031495
int Jim_tclcompatInit(Jim_Interp *interp)
14041496
{
14051497
if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1410,12 +1502,14 @@
14101502
"\n"
14111503
"\n"
14121504
"\n"
14131505
"\n"
14141506
"\n"
1507
+"\n"
14151508
"\n"
14161509
"set env [env]\n"
1510
+"\n"
14171511
"\n"
14181512
"if {[info commands stdout] ne \"\"} {\n"
14191513
"\n"
14201514
" foreach p {gets flush close eof seek tell} {\n"
14211515
" proc $p {chan args} {p} {\n"
@@ -1462,51 +1556,10 @@
14621556
" }\n"
14631557
" }\n"
14641558
" }\n"
14651559
"}\n"
14661560
"\n"
1467
-"\n"
1468
-"proc case {var args} {\n"
1469
-"\n"
1470
-" if {[lindex $args 0] eq \"in\"} {\n"
1471
-" set args [lrange $args 1 end]\n"
1472
-" }\n"
1473
-"\n"
1474
-"\n"
1475
-" if {[llength $args] == 1} {\n"
1476
-" set args [lindex $args 0]\n"
1477
-" }\n"
1478
-"\n"
1479
-"\n"
1480
-" if {[llength $args] % 2 != 0} {\n"
1481
-" return -code error \"extra case pattern with no body\"\n"
1482
-" }\n"
1483
-"\n"
1484
-"\n"
1485
-" local proc case.checker {value pattern} {\n"
1486
-" string match $pattern $value\n"
1487
-" }\n"
1488
-"\n"
1489
-" foreach {value action} $args {\n"
1490
-" if {$value eq \"default\"} {\n"
1491
-" set do_action $action\n"
1492
-" continue\n"
1493
-" } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1494
-" set do_action $action\n"
1495
-" break\n"
1496
-" }\n"
1497
-" }\n"
1498
-"\n"
1499
-" if {[info exists do_action]} {\n"
1500
-" set rc [catch [list uplevel 1 $do_action] result opts]\n"
1501
-" if {$rc} {\n"
1502
-" incr opts(-level)\n"
1503
-" }\n"
1504
-" return {*}$opts $result\n"
1505
-" }\n"
1506
-"}\n"
1507
-"\n"
15081561
"\n"
15091562
"proc fileevent {args} {\n"
15101563
" tailcall {*}$args\n"
15111564
"}\n"
15121565
"\n"
@@ -1536,13 +1589,25 @@
15361589
" error \"bad option \\\"$force\\\": should be -force\"\n"
15371590
" }\n"
15381591
"\n"
15391592
" set in [open $source]\n"
15401593
"\n"
1541
-" if {$force eq \"\" && [file exists $target]} {\n"
1542
-" $in close\n"
1543
-" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1594
+" if {[file exists $target]} {\n"
1595
+" if {$force eq \"\"} {\n"
1596
+" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1597
+" }\n"
1598
+"\n"
1599
+" if {$source eq $target} {\n"
1600
+" return\n"
1601
+" }\n"
1602
+"\n"
1603
+"\n"
1604
+" file stat $source ss\n"
1605
+" file stat $target ts\n"
1606
+" if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n"
1607
+" return\n"
1608
+" }\n"
15441609
" }\n"
15451610
" set out [open $target w]\n"
15461611
" $in copyto $out\n"
15471612
" $out close\n"
15481613
" } on error {msg opts} {\n"
@@ -1587,18 +1652,18 @@
15871652
" error $error\n"
15881653
" }\n"
15891654
"}\n"
15901655
"\n"
15911656
"\n"
1592
-"local proc pid {{chan {}}} {\n"
1593
-" if {$chan eq \"\"} {\n"
1657
+"local proc pid {{channelId {}}} {\n"
1658
+" if {$channelId eq \"\"} {\n"
15941659
" tailcall upcall pid\n"
15951660
" }\n"
1596
-" if {[catch {$chan tell}]} {\n"
1597
-" return -code error \"can not find channel named \\\"$chan\\\"\"\n"
1661
+" if {[catch {$channelId tell}]} {\n"
1662
+" return -code error \"can not find channel named \\\"$channelId\\\"\"\n"
15981663
" }\n"
1599
-" if {[catch {$chan pid} pids]} {\n"
1664
+" if {[catch {$channelId pid} pids]} {\n"
16001665
" return \"\"\n"
16011666
" }\n"
16021667
" return $pids\n"
16031668
"}\n"
16041669
"\n"
@@ -1687,23 +1752,25 @@
16871752
"}\n"
16881753
);
16891754
}
16901755
16911756
1692
-
16931757
#include <stdio.h>
16941758
#include <string.h>
16951759
#include <errno.h>
16961760
#include <fcntl.h>
1761
+#ifdef HAVE_UNISTD_H
1762
+#include <unistd.h>
1763
+#include <sys/stat.h>
1764
+#endif
16971765
16981766
16991767
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
17001768
#include <sys/socket.h>
17011769
#include <netinet/in.h>
17021770
#include <arpa/inet.h>
17031771
#include <netdb.h>
1704
-#include <unistd.h>
17051772
#ifdef HAVE_SYS_UN_H
17061773
#include <sys/un.h>
17071774
#endif
17081775
#else
17091776
#define JIM_ANSIC
@@ -1735,15 +1802,12 @@
17351802
typedef struct AioFile
17361803
{
17371804
FILE *fp;
17381805
Jim_Obj *filename;
17391806
int type;
1740
- int OpenFlags;
1807
+ int openFlags;
17411808
int fd;
1742
-#ifdef O_NDELAY
1743
- int flags;
1744
-#endif
17451809
Jim_Obj *rEvent;
17461810
Jim_Obj *wEvent;
17471811
Jim_Obj *eEvent;
17481812
int addr_family;
17491813
} AioFile;
@@ -1767,28 +1831,21 @@
17671831
{
17681832
AioFile *af = privData;
17691833
17701834
JIM_NOTUSED(interp);
17711835
1772
- if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1773
- fclose(af->fp);
1774
- }
1775
-
17761836
Jim_DecrRefCount(interp, af->filename);
17771837
17781838
#ifdef jim_ext_eventloop
17791839
1780
- if (af->rEvent) {
1781
- Jim_DeleteFileHandler(interp, af->fp);
1782
- }
1783
- if (af->wEvent) {
1784
- Jim_DeleteFileHandler(interp, af->fp);
1785
- }
1786
- if (af->eEvent) {
1787
- Jim_DeleteFileHandler(interp, af->fp);
1788
- }
1789
-#endif
1840
+ Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1841
+#endif
1842
+
1843
+ if (!(af->openFlags & AIO_KEEPOPEN)) {
1844
+ fclose(af->fp);
1845
+ }
1846
+
17901847
Jim_Free(af);
17911848
}
17921849
17931850
static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
17941851
{
@@ -2035,12 +2092,31 @@
20352092
return JIM_OK;
20362093
}
20372094
20382095
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20392096
{
2040
- Jim_DeleteCommand(interp, Jim_String(argv[0]));
2041
- return JIM_OK;
2097
+ if (argc == 3) {
2098
+#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2099
+ static const char * const options[] = { "r", "w", NULL };
2100
+ enum { OPT_R, OPT_W, };
2101
+ int option;
2102
+ AioFile *af = Jim_CmdPrivData(interp);
2103
+
2104
+ if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
2105
+ return JIM_ERR;
2106
+ }
2107
+ if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
2108
+ return JIM_OK;
2109
+ }
2110
+ JimAioSetError(interp, NULL);
2111
+#else
2112
+ Jim_SetResultString(interp, "async close not supported", -1);
2113
+#endif
2114
+ return JIM_ERR;
2115
+ }
2116
+
2117
+ return Jim_DeleteCommand(interp, Jim_String(argv[0]));
20422118
}
20432119
20442120
static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20452121
{
20462122
AioFile *af = Jim_CmdPrivData(interp);
@@ -2087,11 +2163,11 @@
20872163
#ifdef O_NDELAY
20882164
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20892165
{
20902166
AioFile *af = Jim_CmdPrivData(interp);
20912167
2092
- int fmode = af->flags;
2168
+ int fmode = fcntl(af->fd, F_GETFL);
20932169
20942170
if (argc) {
20952171
long nb;
20962172
20972173
if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2101,12 +2177,11 @@
21012177
fmode |= O_NDELAY;
21022178
}
21032179
else {
21042180
fmode &= ~O_NDELAY;
21052181
}
2106
- fcntl(af->fd, F_SETFL, fmode);
2107
- af->flags = fmode;
2182
+ (void)fcntl(af->fd, F_SETFL, fmode);
21082183
}
21092184
Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
21102185
return JIM_OK;
21112186
}
21122187
#endif
@@ -2147,27 +2222,26 @@
21472222
}
21482223
21492224
#ifdef jim_ext_eventloop
21502225
static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
21512226
{
2152
- Jim_Obj *objPtr = clientData;
2227
+ Jim_Obj **objPtrPtr = clientData;
21532228
2154
- Jim_DecrRefCount(interp, objPtr);
2229
+ Jim_DecrRefCount(interp, *objPtrPtr);
2230
+ *objPtrPtr = NULL;
21552231
}
21562232
21572233
static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
21582234
{
2159
- Jim_Obj *objPtr = clientData;
2235
+ Jim_Obj **objPtrPtr = clientData;
21602236
2161
- return Jim_EvalObjBackground(interp, objPtr);
2237
+ return Jim_EvalObjBackground(interp, *objPtrPtr);
21622238
}
21632239
21642240
static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
21652241
int argc, Jim_Obj * const *argv)
21662242
{
2167
- int scriptlen = 0;
2168
-
21692243
if (argc == 0) {
21702244
21712245
if (*scriptHandlerObj) {
21722246
Jim_SetResult(interp, *scriptHandlerObj);
21732247
}
@@ -2174,27 +2248,25 @@
21742248
return JIM_OK;
21752249
}
21762250
21772251
if (*scriptHandlerObj) {
21782252
2179
- Jim_DeleteFileHandler(interp, af->fp);
2180
- *scriptHandlerObj = NULL;
2253
+ Jim_DeleteFileHandler(interp, af->fp, mask);
21812254
}
21822255
21832256
2184
- Jim_GetString(argv[0], &scriptlen);
2185
- if (scriptlen == 0) {
2257
+ if (Jim_Length(argv[0]) == 0) {
21862258
21872259
return JIM_OK;
21882260
}
21892261
21902262
21912263
Jim_IncrRefCount(argv[0]);
21922264
*scriptHandlerObj = argv[0];
21932265
21942266
Jim_CreateFileHandler(interp, af->fp, mask,
2195
- JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer);
2267
+ JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
21962268
21972269
return JIM_OK;
21982270
}
21992271
22002272
static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -2213,11 +2285,11 @@
22132285
22142286
static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
22152287
{
22162288
AioFile *af = Jim_CmdPrivData(interp);
22172289
2218
- return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
2290
+ return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
22192291
}
22202292
#endif
22212293
22222294
static const jim_subcmd_type aio_command_table[] = {
22232295
{ "read",
@@ -2268,14 +2340,14 @@
22682340
0,
22692341
0,
22702342
22712343
},
22722344
{ "close",
2273
- NULL,
2345
+ "?r(ead)|w(rite)?",
22742346
aio_cmd_close,
22752347
0,
2276
- 0,
2348
+ 1,
22772349
JIM_MODFLAG_FULLARGV,
22782350
22792351
},
22802352
{ "seek",
22812353
"offset ?start|current|end",
@@ -2347,30 +2419,32 @@
23472419
23482420
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
23492421
Jim_Obj *const *argv)
23502422
{
23512423
const char *mode;
2352
- const char *filename;
23532424
23542425
if (argc != 2 && argc != 3) {
23552426
Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
23562427
return JIM_ERR;
23572428
}
23582429
23592430
mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2360
- filename = Jim_String(argv[1]);
23612431
23622432
#ifdef jim_ext_tclcompat
2363
-
2364
- if (*filename == '|') {
2365
- Jim_Obj *evalObj[3];
2366
-
2367
- evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2368
- evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2369
- evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2370
-
2371
- return Jim_EvalObjVector(interp, 3, evalObj);
2433
+ {
2434
+ const char *filename = Jim_String(argv[1]);
2435
+
2436
+
2437
+ if (*filename == '|') {
2438
+ Jim_Obj *evalObj[3];
2439
+
2440
+ evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2441
+ evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2442
+ evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2443
+
2444
+ return Jim_EvalObjVector(interp, 3, evalObj);
2445
+ }
23722446
}
23732447
#endif
23742448
return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
23752449
}
23762450
@@ -2377,70 +2451,129 @@
23772451
static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
23782452
const char *hdlfmt, int family, const char *mode)
23792453
{
23802454
AioFile *af;
23812455
char buf[AIO_CMD_LEN];
2382
- int OpenFlags = 0;
2456
+ int openFlags = 0;
23832457
2384
- if (filename == NULL) {
2458
+ if (fh) {
23852459
filename = Jim_NewStringObj(interp, hdlfmt, -1);
2460
+ openFlags = AIO_KEEPOPEN;
23862461
}
23872462
23882463
Jim_IncrRefCount(filename);
23892464
23902465
if (fh == NULL) {
2391
- if (fd < 0) {
2392
- fh = fopen(Jim_String(filename), mode);
2393
- }
2394
- else {
2466
+#if !defined(JIM_ANSIC)
2467
+ if (fd >= 0) {
23952468
fh = fdopen(fd, mode);
23962469
}
2397
- }
2398
- else {
2399
- OpenFlags = AIO_KEEPOPEN;
2400
- }
2470
+ else
2471
+#endif
2472
+ fh = fopen(Jim_String(filename), mode);
24012473
2402
- if (fh == NULL) {
2403
- JimAioSetError(interp, filename);
2474
+ if (fh == NULL) {
2475
+ JimAioSetError(interp, filename);
24042476
#if !defined(JIM_ANSIC)
2405
- if (fd >= 0) {
2406
- close(fd);
2477
+ if (fd >= 0) {
2478
+ close(fd);
2479
+ }
2480
+#endif
2481
+ Jim_DecrRefCount(interp, filename);
2482
+ return JIM_ERR;
24072483
}
2408
-#endif
2409
- Jim_DecrRefCount(interp, filename);
2410
- return JIM_ERR;
24112484
}
24122485
24132486
24142487
af = Jim_Alloc(sizeof(*af));
24152488
memset(af, 0, sizeof(*af));
24162489
af->fp = fh;
24172490
af->fd = fileno(fh);
24182491
af->filename = filename;
24192492
#ifdef FD_CLOEXEC
2420
- if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2421
- fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2493
+ if ((openFlags & AIO_KEEPOPEN) == 0) {
2494
+ (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
24222495
}
24232496
#endif
2424
- af->OpenFlags = OpenFlags;
2425
-#ifdef O_NDELAY
2426
- af->flags = fcntl(af->fd, F_GETFL);
2427
-#endif
2497
+ af->openFlags = openFlags;
24282498
af->addr_family = family;
24292499
snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
24302500
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
24312501
2432
- Jim_SetResultString(interp, buf, -1);
2502
+ Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
24332503
24342504
return JIM_OK;
24352505
}
24362506
2507
+static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
2508
+ const char *hdlfmt, int family, const char *mode[2])
2509
+{
2510
+ if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
2511
+ Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2512
+ Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2513
+
2514
+ if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
2515
+ Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2516
+ Jim_SetResult(interp, objPtr);
2517
+ return JIM_OK;
2518
+ }
2519
+ }
2520
+
2521
+
2522
+ close(p[0]);
2523
+ close(p[1]);
2524
+ JimAioSetError(interp, NULL);
2525
+ return JIM_ERR;
2526
+}
2527
+
2528
+
2529
+int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2530
+{
2531
+#ifdef HAVE_MKSTEMP
2532
+ int fd;
2533
+ mode_t mask;
2534
+ Jim_Obj *filenameObj;
2535
+
2536
+ if (template == NULL) {
2537
+ const char *tmpdir = getenv("TMPDIR");
2538
+ if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2539
+ tmpdir = "/tmp/";
2540
+ }
2541
+ filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2542
+ if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2543
+ Jim_AppendString(interp, filenameObj, "/", 1);
2544
+ }
2545
+ Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2546
+ }
2547
+ else {
2548
+ filenameObj = Jim_NewStringObj(interp, template, -1);
2549
+ }
2550
+
2551
+ mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2552
+
2553
+
2554
+ fd = mkstemp(filenameObj->bytes);
2555
+ umask(mask);
2556
+ if (fd < 0) {
2557
+ Jim_SetResultString(interp, "Failed to create tempfile", -1);
2558
+ Jim_FreeNewObj(interp, filenameObj);
2559
+ return -1;
2560
+ }
2561
+
2562
+ Jim_SetResult(interp, filenameObj);
2563
+ return fd;
2564
+#else
2565
+ Jim_SetResultString(interp, "tempfile not supported", -1);
2566
+ return -1;
2567
+#endif
2568
+}
24372569
24382570
FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
24392571
{
24402572
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
24412573
2574
+
24422575
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
24432576
return ((AioFile *) cmdPtr->u.native.privData)->fp;
24442577
}
24452578
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
24462579
return NULL;
@@ -2461,11 +2594,10 @@
24612594
JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
24622595
JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
24632596
24642597
return JIM_OK;
24652598
}
2466
-
24672599
24682600
#include <errno.h>
24692601
#include <stdio.h>
24702602
#include <string.h>
24712603
@@ -2497,28 +2629,29 @@
24972629
return JIM_OK;
24982630
}
24992631
Jim_SetResultString(interp, strerror(errno), -1);
25002632
return JIM_ERR;
25012633
}
2502
- Jim_SetResultString(interp, strerror(errno), -1);
2503
-
2504
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2505
-
2506
- while ((entryPtr = readdir(dirPtr)) != NULL) {
2507
- if (entryPtr->d_name[0] == '.') {
2508
- if (entryPtr->d_name[1] == '\0') {
2509
- continue;
2510
- }
2511
- if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2512
- continue;
2513
- }
2514
- Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2515
- entryPtr->d_name, -1));
2516
- }
2517
- closedir(dirPtr);
2518
-
2519
- return JIM_OK;
2634
+ else {
2635
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2636
+
2637
+ while ((entryPtr = readdir(dirPtr)) != NULL) {
2638
+ if (entryPtr->d_name[0] == '.') {
2639
+ if (entryPtr->d_name[1] == '\0') {
2640
+ continue;
2641
+ }
2642
+ if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2643
+ continue;
2644
+ }
2645
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));
2646
+ }
2647
+ closedir(dirPtr);
2648
+
2649
+ Jim_SetResult(interp, listObj);
2650
+
2651
+ return JIM_OK;
2652
+ }
25202653
}
25212654
25222655
int Jim_readdirInit(Jim_Interp *interp)
25232656
{
25242657
if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2529,10 +2662,14 @@
25292662
}
25302663
25312664
#include <stdlib.h>
25322665
#include <string.h>
25332666
2667
+#if defined(JIM_REGEXP)
2668
+#else
2669
+ #include <regex.h>
2670
+#endif
25342671
25352672
static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
25362673
{
25372674
regfree(objPtr->internalRep.regexpValue.compre);
25382675
Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3076,58 +3213,61 @@
30763213
}
30773214
#endif
30783215
return "unknown";
30793216
}
30803217
3081
-
3082
-static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3083
- jim_wide value)
3084
-{
3085
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3086
- Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3087
-
3088
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3089
- Jim_FreeObj(interp, nameobj);
3090
- Jim_FreeObj(interp, valobj);
3091
- return JIM_ERR;
3092
- }
3093
- return JIM_OK;
3094
-}
3095
-
3096
-static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3097
- const char *value)
3098
-{
3099
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3100
- Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3101
-
3102
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3103
- Jim_FreeObj(interp, nameobj);
3104
- Jim_FreeObj(interp, valobj);
3105
- return JIM_ERR;
3106
- }
3107
- return JIM_OK;
3218
+static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)
3219
+{
3220
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));
3221
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
31083222
}
31093223
31103224
static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
31113225
{
3112
- if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3113
- Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3114
- return JIM_ERR;
3115
- }
3116
- set_array_int_value(interp, varName, "ino", sb->st_ino);
3117
- set_array_int_value(interp, varName, "mode", sb->st_mode);
3118
- set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3119
- set_array_int_value(interp, varName, "uid", sb->st_uid);
3120
- set_array_int_value(interp, varName, "gid", sb->st_gid);
3121
- set_array_int_value(interp, varName, "size", sb->st_size);
3122
- set_array_int_value(interp, varName, "atime", sb->st_atime);
3123
- set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3124
- set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3125
- set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3126
-
3127
-
3128
- Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
3226
+
3227
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3228
+
3229
+ AppendStatElement(interp, listObj, "dev", sb->st_dev);
3230
+ AppendStatElement(interp, listObj, "ino", sb->st_ino);
3231
+ AppendStatElement(interp, listObj, "mode", sb->st_mode);
3232
+ AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
3233
+ AppendStatElement(interp, listObj, "uid", sb->st_uid);
3234
+ AppendStatElement(interp, listObj, "gid", sb->st_gid);
3235
+ AppendStatElement(interp, listObj, "size", sb->st_size);
3236
+ AppendStatElement(interp, listObj, "atime", sb->st_atime);
3237
+ AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3238
+ AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3239
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3240
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3241
+
3242
+
3243
+ if (varName) {
3244
+ Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3245
+ if (objPtr) {
3246
+ if (Jim_DictSize(interp, objPtr) < 0) {
3247
+
3248
+ Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3249
+ Jim_FreeNewObj(interp, listObj);
3250
+ return JIM_ERR;
3251
+ }
3252
+
3253
+ if (Jim_IsShared(objPtr))
3254
+ objPtr = Jim_DuplicateObj(interp, objPtr);
3255
+
3256
+
3257
+ Jim_ListAppendList(interp, objPtr, listObj);
3258
+ Jim_DictSize(interp, objPtr);
3259
+ Jim_InvalidateStringRep(objPtr);
3260
+
3261
+ Jim_FreeNewObj(interp, listObj);
3262
+ listObj = objPtr;
3263
+ }
3264
+ Jim_SetVariable(interp, varName, listObj);
3265
+ }
3266
+
3267
+
3268
+ Jim_SetResult(interp, listObj);
31293269
31303270
return JIM_OK;
31313271
}
31323272
31333273
static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3282,14 +3422,11 @@
32823422
return JIM_OK;
32833423
}
32843424
32853425
static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
32863426
{
3287
- const char *path = Jim_String(filename);
3288
- int rc = access(path, mode);
3289
-
3290
- Jim_SetResultBool(interp, rc != -1);
3427
+ Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
32913428
32923429
return JIM_OK;
32933430
}
32943431
32953432
static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3305,10 +3442,11 @@
33053442
static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
33063443
{
33073444
#ifdef X_OK
33083445
return file_access(interp, argv[0], X_OK);
33093446
#else
3447
+
33103448
Jim_SetResultBool(interp, 1);
33113449
return JIM_OK;
33123450
#endif
33133451
}
33143452
@@ -3409,33 +3547,21 @@
34093547
argv++;
34103548
}
34113549
return JIM_OK;
34123550
}
34133551
3414
-#ifdef HAVE_MKSTEMP
34153552
static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34163553
{
3417
- int fd;
3418
- char *filename;
3419
- const char *template = "/tmp/tcl.tmp.XXXXXX";
3420
-
3421
- if (argc >= 1) {
3422
- template = Jim_String(argv[0]);
3423
- }
3424
- filename = Jim_StrDup(template);
3425
-
3426
- fd = mkstemp(filename);
3427
- if (fd < 0) {
3428
- Jim_SetResultString(interp, "Failed to create tempfile", -1);
3554
+ int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3555
+
3556
+ if (fd < 0) {
34293557
return JIM_ERR;
34303558
}
34313559
close(fd);
34323560
3433
- Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
34343561
return JIM_OK;
34353562
}
3436
-#endif
34373563
34383564
static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34393565
{
34403566
const char *source;
34413567
const char *dest;
@@ -3477,14 +3603,11 @@
34773603
return JIM_ERR;
34783604
}
34793605
return JIM_OK;
34803606
}
34813607
3482
-#ifndef HAVE_LSTAT
3483
-#define lstat stat
3484
-#endif
3485
-
3608
+#ifdef HAVE_LSTAT
34863609
static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
34873610
{
34883611
const char *path = Jim_String(filename);
34893612
34903613
if (lstat(path, sb) == -1) {
@@ -3491,10 +3614,13 @@
34913614
Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
34923615
return JIM_ERR;
34933616
}
34943617
return JIM_OK;
34953618
}
3619
+#else
3620
+#define file_lstat file_stat
3621
+#endif
34963622
34973623
static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34983624
{
34993625
struct stat sb;
35003626
@@ -3619,28 +3745,32 @@
36193745
}
36203746
Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
36213747
return JIM_OK;
36223748
}
36233749
3750
+#ifdef HAVE_LSTAT
36243751
static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36253752
{
36263753
struct stat sb;
36273754
36283755
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
36293756
return JIM_ERR;
36303757
}
3631
- return StoreStatData(interp, argv[1], &sb);
3758
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36323759
}
3760
+#else
3761
+#define file_cmd_lstat file_cmd_stat
3762
+#endif
36333763
36343764
static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36353765
{
36363766
struct stat sb;
36373767
36383768
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
36393769
return JIM_ERR;
36403770
}
3641
- return StoreStatData(interp, argv[1], &sb);
3771
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36423772
}
36433773
36443774
static const jim_subcmd_type file_command_table[] = {
36453775
{ "atime",
36463776
"name",
@@ -3745,19 +3875,17 @@
37453875
file_cmd_mkdir,
37463876
1,
37473877
-1,
37483878
37493879
},
3750
-#ifdef HAVE_MKSTEMP
37513880
{ "tempfile",
37523881
"?template?",
37533882
file_cmd_tempfile,
37543883
0,
37553884
1,
37563885
37573886
},
3758
-#endif
37593887
{ "rename",
37603888
"?-force? source dest",
37613889
file_cmd_rename,
37623890
2,
37633891
3,
@@ -3778,20 +3906,20 @@
37783906
1,
37793907
1,
37803908
37813909
},
37823910
{ "stat",
3783
- "name var",
3911
+ "name ?var?",
37843912
file_cmd_stat,
3785
- 2,
3913
+ 1,
37863914
2,
37873915
37883916
},
37893917
{ "lstat",
3790
- "name var",
3918
+ "name ?var?",
37913919
file_cmd_lstat,
3792
- 2,
3920
+ 1,
37933921
2,
37943922
37953923
},
37963924
{ "type",
37973925
"name",
@@ -3847,15 +3975,15 @@
38473975
return JIM_OK;
38483976
}
38493977
38503978
static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
38513979
{
3852
- const int cwd_len = 2048;
3853
- char *cwd = malloc(cwd_len);
3980
+ char *cwd = Jim_Alloc(MAXPATHLEN);
38543981
3855
- if (getcwd(cwd, cwd_len) == NULL) {
3982
+ if (getcwd(cwd, MAXPATHLEN) == NULL) {
38563983
Jim_SetResultString(interp, "Failed to get pwd", -1);
3984
+ Jim_Free(cwd);
38573985
return JIM_ERR;
38583986
}
38593987
#if defined(__MINGW32__) || defined(_MSC_VER)
38603988
{
38613989
@@ -3866,11 +3994,11 @@
38663994
}
38673995
#endif
38683996
38693997
Jim_SetResultString(interp, cwd, -1);
38703998
3871
- free(cwd);
3999
+ Jim_Free(cwd);
38724000
return JIM_OK;
38734001
}
38744002
38754003
int Jim_fileInit(Jim_Interp *interp)
38764004
{
@@ -3935,10 +4063,11 @@
39354063
39364064
int Jim_execInit(Jim_Interp *interp)
39374065
{
39384066
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
39394067
return JIM_ERR;
4068
+
39404069
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
39414070
return JIM_OK;
39424071
}
39434072
#else
39444073
@@ -3978,10 +4107,11 @@
39784107
static int JimErrno(void);
39794108
#else
39804109
#include <unistd.h>
39814110
#include <fcntl.h>
39824111
#include <sys/wait.h>
4112
+ #include <sys/stat.h>
39834113
39844114
typedef int fdtype;
39854115
typedef int pidtype;
39864116
#define JimPipe pipe
39874117
#define JimErrno() errno
@@ -4005,11 +4135,11 @@
40054135
static void JimRestoreEnv(char **env);
40064136
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
40074137
pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
40084138
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
40094139
static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
4010
-static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents);
4140
+static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
40114141
static fdtype JimOpenForWrite(const char *filename, int append);
40124142
static int JimRewindFd(fdtype fd);
40134143
40144144
static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
40154145
{
@@ -4052,23 +4182,12 @@
40524182
Jim_RemoveTrailingNewline(strObj);
40534183
fclose(fh);
40544184
return JIM_OK;
40554185
}
40564186
4057
-static void JimTrimTrailingNewline(Jim_Interp *interp)
4058
-{
4059
- int len;
4060
- const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4061
-
4062
- if (len > 0 && p[len - 1] == '\n') {
4063
- Jim_SetResultString(interp, p, len - 1);
4064
- }
4065
-}
4066
-
40674187
static char **JimBuildEnv(Jim_Interp *interp)
40684188
{
4069
-#if defined(jim_ext_tclcompat)
40704189
int i;
40714190
int size;
40724191
int num;
40734192
int n;
40744193
char **envptr;
@@ -4082,10 +4201,11 @@
40824201
40834202
40844203
40854204
num = Jim_ListLength(interp, objPtr);
40864205
if (num % 2) {
4206
+
40874207
num--;
40884208
}
40894209
size = Jim_Length(objPtr) + 2;
40904210
40914211
envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4108,22 +4228,17 @@
41084228
}
41094229
envptr[n] = NULL;
41104230
*envdata = 0;
41114231
41124232
return envptr;
4113
-#else
4114
- return Jim_GetEnviron();
4115
-#endif
41164233
}
41174234
41184235
static void JimFreeEnv(char **env, char **original_environ)
41194236
{
4120
-#ifdef jim_ext_tclcompat
41214237
if (env != original_environ) {
41224238
Jim_Free(env);
41234239
}
4124
-#endif
41254240
}
41264241
41274242
static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
41284243
{
41294244
Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4172,19 +4287,19 @@
41724287
}
41734288
41744289
41754290
struct WaitInfo
41764291
{
4177
- pidtype pid;
4292
+ pidtype pid;
41784293
int status;
41794294
int flags;
41804295
};
41814296
41824297
struct WaitInfoTable {
4183
- struct WaitInfo *info;
4184
- int size;
4185
- int used;
4298
+ struct WaitInfo *info;
4299
+ int size;
4300
+ int used;
41864301
};
41874302
41884303
41894304
#define WI_DETACHED 2
41904305
@@ -4207,14 +4322,12 @@
42074322
return table;
42084323
}
42094324
42104325
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
42114326
{
4212
- fdtype outputId; /* File id for output pipe. -1
4213
- * means command overrode. */
4214
- fdtype errorId; /* File id for temporary file
4215
- * containing error output. */
4327
+ fdtype outputId;
4328
+ fdtype errorId;
42164329
pidtype *pidPtr;
42174330
int numPids, result;
42184331
42194332
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
42204333
Jim_Obj *listObj;
@@ -4261,26 +4374,32 @@
42614374
42624375
static void JimReapDetachedPids(struct WaitInfoTable *table)
42634376
{
42644377
struct WaitInfo *waitPtr;
42654378
int count;
4379
+ int dest;
42664380
42674381
if (!table) {
42684382
return;
42694383
}
42704384
4271
- for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
4385
+ waitPtr = table->info;
4386
+ dest = 0;
4387
+ for (count = table->used; count > 0; waitPtr++, count--) {
42724388
if (waitPtr->flags & WI_DETACHED) {
42734389
int status;
42744390
pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4275
- if (pid != JIM_BAD_PID) {
4276
- if (waitPtr != &table->info[table->used - 1]) {
4277
- *waitPtr = table->info[table->used - 1];
4278
- }
4391
+ if (pid == waitPtr->pid) {
4392
+
42794393
table->used--;
4394
+ continue;
42804395
}
42814396
}
4397
+ if (waitPtr != &table->info[dest]) {
4398
+ table->info[dest] = *waitPtr;
4399
+ }
4400
+ dest++;
42824401
}
42834402
}
42844403
42854404
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
42864405
{
@@ -4302,11 +4421,10 @@
43024421
}
43034422
43044423
43054424
return JIM_BAD_PID;
43064425
}
4307
-
43084426
43094427
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
43104428
{
43114429
int j;
43124430
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4347,10 +4465,11 @@
43474465
int cmdCount; /* Count of number of distinct commands
43484466
* found in argc/argv. */
43494467
const char *input = NULL; /* Describes input for pipeline, depending
43504468
* on "inputFile". NULL means take input
43514469
* from stdin/pipe. */
4470
+ int input_len = 0;
43524471
43534472
#define FILE_NAME 0
43544473
#define FILE_APPEND 1
43554474
#define FILE_HANDLE 2
43564475
#define FILE_TEXT 3
@@ -4412,19 +4531,20 @@
44124531
if (arg[0] == '<') {
44134532
inputFile = FILE_NAME;
44144533
input = arg + 1;
44154534
if (*input == '<') {
44164535
inputFile = FILE_TEXT;
4536
+ input_len = Jim_Length(argv[i]) - 2;
44174537
input++;
44184538
}
44194539
else if (*input == '@') {
44204540
inputFile = FILE_HANDLE;
44214541
input++;
44224542
}
44234543
44244544
if (!*input && ++i < argc) {
4425
- input = Jim_String(argv[i]);
4545
+ input = Jim_GetString(argv[i], &input_len);
44264546
}
44274547
}
44284548
else if (arg[0] == '>') {
44294549
int dup_error = 0;
44304550
@@ -4498,11 +4618,11 @@
44984618
44994619
save_environ = JimSaveEnv(JimBuildEnv(interp));
45004620
45014621
if (input != NULL) {
45024622
if (inputFile == FILE_TEXT) {
4503
- inputId = JimCreateTemp(interp, input);
4623
+ inputId = JimCreateTemp(interp, input, input_len);
45044624
if (inputId == JIM_BAD_FD) {
45054625
goto error;
45064626
}
45074627
}
45084628
else if (inputFile == FILE_HANDLE) {
@@ -4587,11 +4707,11 @@
45874707
goto error;
45884708
}
45894709
}
45904710
}
45914711
else if (errFilePtr != NULL) {
4592
- errorId = JimCreateTemp(interp, NULL);
4712
+ errorId = JimCreateTemp(interp, NULL, 0);
45934713
if (errorId == JIM_BAD_FD) {
45944714
goto error;
45954715
}
45964716
*errFilePtr = JimDupFd(errorId);
45974717
}
@@ -4625,27 +4745,23 @@
46254745
}
46264746
outputId = pipeIds[1];
46274747
}
46284748
46294749
4750
+ if (pipe_dup_err) {
4751
+ errorId = outputId;
4752
+ }
4753
+
4754
+
46304755
46314756
#ifdef __MINGW32__
46324757
pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
46334758
if (pid == JIM_BAD_PID) {
46344759
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
46354760
goto error;
46364761
}
46374762
#else
4638
- if (table->info == NULL) {
4639
- (void)signal(SIGPIPE, SIG_IGN);
4640
- }
4641
-
4642
-
4643
- if (pipe_dup_err) {
4644
- errorId = outputId;
4645
- }
4646
-
46474763
pid = vfork();
46484764
if (pid < 0) {
46494765
Jim_SetResultErrno(interp, "couldn't fork child process");
46504766
goto error;
46514767
}
@@ -4658,14 +4774,17 @@
46584774
46594775
for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
46604776
close(i);
46614777
}
46624778
4779
+
4780
+ (void)signal(SIGPIPE, SIG_DFL);
4781
+
46634782
execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
46644783
46654784
4666
- fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4785
+ fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
46674786
_exit(127);
46684787
}
46694788
#endif
46704789
46714790
@@ -4767,19 +4886,24 @@
47674886
if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
47684887
result = JIM_ERR;
47694888
}
47704889
}
47714890
4772
- JimTrimTrailingNewline(interp);
4891
+ Jim_RemoveTrailingNewline(Jim_GetResult(interp));
47734892
47744893
return result;
47754894
}
47764895
47774896
int Jim_execInit(Jim_Interp *interp)
47784897
{
47794898
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
47804899
return JIM_ERR;
4900
+
4901
+#ifdef SIGPIPE
4902
+ (void)signal(SIGPIPE, SIG_IGN);
4903
+#endif
4904
+
47814905
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
47824906
return JIM_OK;
47834907
}
47844908
47854909
#if defined(__MINGW32__)
@@ -4953,11 +5077,11 @@
49535077
*status = ret;
49545078
CloseHandle(pid);
49555079
return pid;
49565080
}
49575081
4958
-static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
5082
+static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
49595083
{
49605084
char name[MAX_PATH];
49615085
HANDLE handle;
49625086
49635087
if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
@@ -4977,11 +5101,11 @@
49775101
FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
49785102
if (fh == NULL) {
49795103
goto error;
49805104
}
49815105
4982
- if (fwrite(contents, strlen(contents), 1, fh) != 1) {
5106
+ if (fwrite(contents, len, 1, fh) != 1) {
49835107
fclose(fh);
49845108
goto error;
49855109
}
49865110
fseek(fh, 0, SEEK_SET);
49875111
fclose(fh);
@@ -5104,28 +5228,26 @@
51045228
{
51055229
STARTUPINFO startInfo;
51065230
PROCESS_INFORMATION procInfo;
51075231
HANDLE hProcess, h;
51085232
char execPath[MAX_PATH];
5109
- char *originalName;
51105233
pidtype pid = JIM_BAD_PID;
51115234
Jim_Obj *cmdLineObj;
51125235
51135236
if (JimWinFindExecutable(argv[0], execPath) < 0) {
51145237
return JIM_BAD_PID;
51155238
}
5116
- originalName = argv[0];
51175239
argv[0] = execPath;
51185240
51195241
hProcess = GetCurrentProcess();
51205242
cmdLineObj = JimWinBuildCommandLine(interp, argv);
51215243
51225244
51235245
ZeroMemory(&startInfo, sizeof(startInfo));
51245246
startInfo.cb = sizeof(startInfo);
51255247
startInfo.dwFlags = STARTF_USESTDHANDLES;
5126
- startInfo.hStdInput = INVALID_HANDLE_VALUE;
5248
+ startInfo.hStdInput = INVALID_HANDLE_VALUE;
51275249
startInfo.hStdOutput= INVALID_HANDLE_VALUE;
51285250
startInfo.hStdError = INVALID_HANDLE_VALUE;
51295251
51305252
if (inputId == JIM_BAD_FD) {
51315253
if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5196,23 +5318,21 @@
51965318
static int JimRewindFd(int fd)
51975319
{
51985320
return lseek(fd, 0L, SEEK_SET);
51995321
}
52005322
5201
-static int JimCreateTemp(Jim_Interp *interp, const char *contents)
5323
+static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
52025324
{
5203
- char inName[] = "/tmp/tcl.tmp.XXXXXX";
5325
+ int fd = Jim_MakeTempFile(interp, NULL);
52045326
5205
- int fd = mkstemp(inName);
52065327
if (fd == JIM_BAD_FD) {
52075328
Jim_SetResultErrno(interp, "couldn't create temp file");
52085329
return -1;
52095330
}
5210
- unlink(inName);
5331
+ unlink(Jim_String(Jim_GetResult(interp)));
52115332
if (contents) {
5212
- int length = strlen(contents);
5213
- if (write(fd, contents, length) != length) {
5333
+ if (write(fd, contents, len) != len) {
52145334
Jim_SetResultErrno(interp, "couldn't write temp file");
52155335
close(fd);
52165336
return -1;
52175337
}
52185338
lseek(fd, 0L, SEEK_SET);
@@ -5234,11 +5354,10 @@
52345354
}
52355355
#endif
52365356
#endif
52375357
52385358
5239
-
52405359
#ifndef _XOPEN_SOURCE
52415360
#define _XOPEN_SOURCE 500
52425361
#endif
52435362
52445363
#include <stdlib.h>
@@ -5256,11 +5375,11 @@
52565375
52575376
char buf[100];
52585377
time_t t;
52595378
long seconds;
52605379
5261
- const char *format = "%a %b %d %H:%M:%S %Z %Y";
5380
+ const char *format = "%a %b %d %H:%M:%S %Z %Y";
52625381
52635382
if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
52645383
return -1;
52655384
}
52665385
@@ -5271,11 +5390,14 @@
52715390
if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
52725391
return JIM_ERR;
52735392
}
52745393
t = seconds;
52755394
5276
- strftime(buf, sizeof(buf), format, localtime(&t));
5395
+ if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5396
+ Jim_SetResultString(interp, "format string too long", -1);
5397
+ return JIM_ERR;
5398
+ }
52775399
52785400
Jim_SetResultString(interp, buf, -1);
52795401
52805402
return JIM_OK;
52815403
}
@@ -5391,11 +5513,10 @@
53915513
53925514
Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
53935515
return JIM_OK;
53945516
}
53955517
5396
-
53975518
#include <limits.h>
53985519
#include <stdlib.h>
53995520
#include <string.h>
54005521
#include <stdio.h>
54015522
#include <errno.h>
@@ -5409,33 +5530,29 @@
54095530
}
54105531
54115532
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54125533
{
54135534
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5535
+ Jim_Obj *patternObj;
54145536
54155537
if (!objPtr) {
54165538
return JIM_OK;
54175539
}
54185540
5419
- if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5420
-
5421
- if (Jim_IsList(objPtr)) {
5422
- if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5423
-
5424
- return JIM_ERR;
5425
- }
5426
- }
5427
- else if (Jim_DictSize(interp, objPtr) < 0) {
5428
-
5429
- return JIM_ERR;
5430
- }
5431
- Jim_SetResult(interp, objPtr);
5432
- return JIM_OK;
5541
+ patternObj = (argc == 1) ? NULL : argv[1];
5542
+
5543
+
5544
+ if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5545
+ if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5546
+
5547
+ Jim_SetResult(interp, objPtr);
5548
+ return JIM_OK;
5549
+ }
54335550
}
54345551
54355552
5436
- return Jim_DictValues(interp, objPtr, argv[1]);
5553
+ return Jim_DictValues(interp, objPtr, patternObj);
54375554
}
54385555
54395556
static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54405557
{
54415558
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5460,10 +5577,15 @@
54605577
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
54615578
return JIM_OK;
54625579
}
54635580
54645581
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5582
+
5583
+ if (objPtr == NULL) {
5584
+
5585
+ return JIM_OK;
5586
+ }
54655587
54665588
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
54675589
return JIM_ERR;
54685590
}
54695591
@@ -5497,10 +5619,20 @@
54975619
54985620
Jim_SetResultInt(interp, len);
54995621
55005622
return JIM_OK;
55015623
}
5624
+
5625
+static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5626
+{
5627
+ Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5628
+ if (objPtr) {
5629
+ return Jim_DictInfo(interp, objPtr);
5630
+ }
5631
+ Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
5632
+ return JIM_ERR;
5633
+}
55025634
55035635
static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
55045636
{
55055637
int i;
55065638
int len;
@@ -5515,10 +5647,13 @@
55155647
55165648
dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
55175649
if (!dictObj) {
55185650
55195651
return Jim_SetVariable(interp, argv[0], listObj);
5652
+ }
5653
+ else if (Jim_DictSize(interp, dictObj) < 0) {
5654
+ return JIM_ERR;
55205655
}
55215656
55225657
if (Jim_IsShared(dictObj)) {
55235658
dictObj = Jim_DuplicateObj(interp, dictObj);
55245659
}
@@ -5568,10 +5703,17 @@
55685703
"arrayName",
55695704
array_cmd_size,
55705705
1,
55715706
1,
55725707
5708
+ },
5709
+ { "stat",
5710
+ "arrayName",
5711
+ array_cmd_stat,
5712
+ 1,
5713
+ 1,
5714
+
55735715
},
55745716
{ "unset",
55755717
"arrayName ?pattern?",
55765718
array_cmd_unset,
55775719
1,
@@ -5614,11 +5756,10 @@
56145756
Jim_arrayInit(interp);
56155757
Jim_stdlibInit(interp);
56165758
Jim_tclcompatInit(interp);
56175759
return JIM_OK;
56185760
}
5619
-
56205761
#define JIM_OPTIMIZATION
56215762
56225763
#include <stdio.h>
56235764
#include <stdlib.h>
56245765
@@ -5671,29 +5812,33 @@
56715812
#ifdef JIM_MAINTAINER
56725813
#define JIM_DEBUG_COMMAND
56735814
#define JIM_DEBUG_PANIC
56745815
#endif
56755816
5817
+
5818
+
5819
+#define JIM_INTEGER_SPACE 24
5820
+
56765821
const char *jim_tt_name(int type);
56775822
56785823
#ifdef JIM_DEBUG_PANIC
5679
-static void JimPanicDump(int panic_condition, const char *fmt, ...);
5824
+static void JimPanicDump(int fail_condition, const char *fmt, ...);
56805825
#define JimPanic(X) JimPanicDump X
56815826
#else
56825827
#define JimPanic(X)
56835828
#endif
56845829
56855830
56865831
static char JimEmptyStringRep[] = "";
56875832
5688
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5689
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5833
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
56905834
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
56915835
int flags);
56925836
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
56935837
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
56945838
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
5839
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
56955840
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
56965841
const char *prefix, const char *const *tablePtr, const char *name);
56975842
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
56985843
static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
56995844
static int JimSign(jim_wide w);
@@ -5934,17 +6079,10 @@
59346079
}
59356080
return n;
59366081
}
59376082
#endif
59386083
5939
-int Jim_WideToString(char *buf, jim_wide wideValue)
5940
-{
5941
- const char *fmt = "%" JIM_WIDE_MODIFIER;
5942
-
5943
- return sprintf(buf, fmt, wideValue);
5944
-}
5945
-
59466084
static int JimCheckConversion(const char *str, const char *endptr)
59476085
{
59486086
if (str[0] == '\0' || str == endptr) {
59496087
return JIM_ERR;
59506088
}
@@ -5998,11 +6136,12 @@
59986136
if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
59996137
60006138
return i;
60016139
}
60026140
6003
- return 10;
6141
+ *base = 10;
6142
+ return 0;
60046143
}
60056144
60066145
static long jim_strtol(const char *str, char **endptr)
60076146
{
60086147
int sign;
@@ -6054,46 +6193,10 @@
60546193
}
60556194
60566195
return JimCheckConversion(str, endptr);
60576196
}
60586197
6059
-int Jim_DoubleToString(char *buf, double doubleValue)
6060
-{
6061
- int len;
6062
- int i;
6063
-
6064
- len = sprintf(buf, "%.12g", doubleValue);
6065
-
6066
-
6067
- for (i = 0; i < len; i++) {
6068
- if (buf[i] == '.' || buf[i] == 'e') {
6069
-#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6070
- char *e = strchr(buf, 'e');
6071
- if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6072
-
6073
- e += 2;
6074
- memmove(e, e + 1, len - (e - buf));
6075
- return len - 1;
6076
- }
6077
-#endif
6078
- return len;
6079
- }
6080
-
6081
- if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6082
- buf[i] = toupper(UCHAR(buf[i]));
6083
- buf[i + 3] = 0;
6084
- return i + 3;
6085
- }
6086
- }
6087
-
6088
- buf[i++] = '.';
6089
- buf[i++] = '0';
6090
- buf[i] = '\0';
6091
-
6092
- return i;
6093
-}
6094
-
60956198
int Jim_StringToDouble(const char *str, double *doublePtr)
60966199
{
60976200
char *endptr;
60986201
60996202
@@ -6115,23 +6218,23 @@
61156218
}
61166219
return res;
61176220
}
61186221
61196222
#ifdef JIM_DEBUG_PANIC
6120
-void JimPanicDump(int condition, const char *fmt, ...)
6223
+static void JimPanicDump(int condition, const char *fmt, ...)
61216224
{
61226225
va_list ap;
61236226
61246227
if (!condition) {
61256228
return;
61266229
}
61276230
61286231
va_start(ap, fmt);
61296232
6130
- fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6233
+ fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
61316234
vfprintf(stderr, fmt, ap);
6132
- fprintf(stderr, JIM_NL JIM_NL);
6235
+ fprintf(stderr, "\n\n");
61336236
va_end(ap);
61346237
61356238
#ifdef HAVE_BACKTRACE
61366239
{
61376240
void *array[40];
@@ -6139,13 +6242,13 @@
61396242
char **strings;
61406243
61416244
size = backtrace(array, 40);
61426245
strings = backtrace_symbols(array, size);
61436246
for (i = 0; i < size; i++)
6144
- fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6145
- fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6146
- fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
6247
+ fprintf(stderr, "[backtrace] %s\n", strings[i]);
6248
+ fprintf(stderr, "[backtrace] Include the above lines and the output\n");
6249
+ fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
61476250
}
61486251
#endif
61496252
61506253
exit(1);
61516254
}
@@ -6219,18 +6322,32 @@
62196322
h += (h << 3) + *buf++;
62206323
return h;
62216324
}
62226325
62236326
6327
+
62246328
62256329
static void JimResetHashTable(Jim_HashTable *ht)
62266330
{
62276331
ht->table = NULL;
62286332
ht->size = 0;
62296333
ht->sizemask = 0;
62306334
ht->used = 0;
62316335
ht->collisions = 0;
6336
+#ifdef JIM_RANDOMISE_HASH
6337
+ ht->uniq = (rand() ^ time(NULL) ^ clock());
6338
+#else
6339
+ ht->uniq = 0;
6340
+#endif
6341
+}
6342
+
6343
+static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6344
+{
6345
+ iter->ht = ht;
6346
+ iter->index = -1;
6347
+ iter->entry = NULL;
6348
+ iter->nextEntry = NULL;
62326349
}
62336350
62346351
62356352
int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
62366353
{
@@ -6260,10 +6377,12 @@
62606377
62616378
Jim_InitHashTable(&n, ht->type, ht->privdata);
62626379
n.size = realsize;
62636380
n.sizemask = realsize - 1;
62646381
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6382
+
6383
+ n.uniq = ht->uniq;
62656384
62666385
62676386
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
62686387
62696388
n.used = ht->used;
@@ -6316,20 +6435,27 @@
63166435
int existed;
63176436
Jim_HashEntry *entry;
63186437
63196438
entry = JimInsertHashEntry(ht, key, 1);
63206439
if (entry->key) {
6321
-
6322
- Jim_FreeEntryVal(ht, entry);
6440
+ if (ht->type->valDestructor && ht->type->valDup) {
6441
+ void *newval = ht->type->valDup(ht->privdata, val);
6442
+ ht->type->valDestructor(ht->privdata, entry->u.val);
6443
+ entry->u.val = newval;
6444
+ }
6445
+ else {
6446
+ Jim_FreeEntryVal(ht, entry);
6447
+ Jim_SetHashVal(ht, entry, val);
6448
+ }
63236449
existed = 1;
63246450
}
63256451
else {
63266452
63276453
Jim_SetHashKey(ht, entry, key);
6454
+ Jim_SetHashVal(ht, entry, val);
63286455
existed = 0;
63296456
}
6330
- Jim_SetHashVal(ht, entry, val);
63316457
63326458
return existed;
63336459
}
63346460
63356461
@@ -6408,15 +6534,11 @@
64086534
}
64096535
64106536
Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
64116537
{
64126538
Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6413
-
6414
- iter->ht = ht;
6415
- iter->index = -1;
6416
- iter->entry = NULL;
6417
- iter->nextEntry = NULL;
6539
+ JimInitHashTableIterator(ht, iter);
64186540
return iter;
64196541
}
64206542
64216543
Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
64226544
{
@@ -6498,11 +6620,11 @@
64986620
return Jim_GenHashFunction(key, strlen(key));
64996621
}
65006622
65016623
static void *JimStringCopyHTDup(void *privdata, const void *key)
65026624
{
6503
- return strdup(key);
6625
+ return Jim_StrDup(key);
65046626
}
65056627
65066628
static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
65076629
{
65086630
return strcmp(key1, key2) == 0;
@@ -6598,11 +6720,11 @@
65986720
freeFunc(stack->vector[i]);
65996721
}
66006722
66016723
66026724
6603
-#define JIM_TT_NONE 0
6725
+#define JIM_TT_NONE 0
66046726
#define JIM_TT_STR 1
66056727
#define JIM_TT_ESC 2
66066728
#define JIM_TT_VAR 3
66076729
#define JIM_TT_DICTSUGAR 4
66086730
#define JIM_TT_CMD 5
@@ -6630,10 +6752,15 @@
66306752
66316753
66326754
#define JIM_PS_DEF 0
66336755
#define JIM_PS_QUOTE 1
66346756
#define JIM_PS_DICTSUGAR 2
6757
+
6758
+struct JimParseMissing {
6759
+ int ch;
6760
+ int line;
6761
+};
66356762
66366763
struct JimParserCtx
66376764
{
66386765
const char *p;
66396766
int len;
@@ -6643,17 +6770,11 @@
66436770
int tline;
66446771
int tt;
66456772
int eof;
66466773
int state;
66476774
int comment;
6648
- char missing;
6649
- int missingline;
6650
-};
6651
-
6652
-struct JimParseResult {
6653
- char missing;
6654
- int line;
6775
+ struct JimParseMissing missing;
66556776
};
66566777
66576778
static int JimParseScript(struct JimParserCtx *pc);
66586779
static int JimParseSep(struct JimParserCtx *pc);
66596780
static int JimParseEol(struct JimParserCtx *pc);
@@ -6663,11 +6784,10 @@
66636784
static int JimParseBrace(struct JimParserCtx *pc);
66646785
static int JimParseStr(struct JimParserCtx *pc);
66656786
static int JimParseComment(struct JimParserCtx *pc);
66666787
static void JimParseSubCmd(struct JimParserCtx *pc);
66676788
static int JimParseSubQuote(struct JimParserCtx *pc);
6668
-static void JimParseSubCmd(struct JimParserCtx *pc);
66696789
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
66706790
66716791
static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
66726792
{
66736793
pc->p = prg;
@@ -6678,12 +6798,12 @@
66786798
pc->tt = JIM_TT_NONE;
66796799
pc->eof = 0;
66806800
pc->state = JIM_PS_DEF;
66816801
pc->linenr = linenr;
66826802
pc->comment = 1;
6683
- pc->missing = ' ';
6684
- pc->missingline = linenr;
6803
+ pc->missing.ch = ' ';
6804
+ pc->missing.line = linenr;
66856805
}
66866806
66876807
static int JimParseScript(struct JimParserCtx *pc)
66886808
{
66896809
while (1) {
@@ -6815,12 +6935,12 @@
68156935
break;
68166936
}
68176937
pc->p++;
68186938
pc->len--;
68196939
}
6820
- pc->missing = '{';
6821
- pc->missingline = pc->tline;
6940
+ pc->missing.ch = '{';
6941
+ pc->missing.line = pc->tline;
68226942
pc->tend = pc->p - 1;
68236943
}
68246944
68256945
static int JimParseSubQuote(struct JimParserCtx *pc)
68266946
{
@@ -6862,12 +6982,12 @@
68626982
break;
68636983
}
68646984
pc->p++;
68656985
pc->len--;
68666986
}
6867
- pc->missing = '"';
6868
- pc->missingline = line;
6987
+ pc->missing.ch = '"';
6988
+ pc->missing.line = line;
68696989
pc->tend = pc->p - 1;
68706990
return tt;
68716991
}
68726992
68736993
static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6921,12 +7041,12 @@
69217041
}
69227042
startofword = isspace(UCHAR(*pc->p));
69237043
pc->p++;
69247044
pc->len--;
69257045
}
6926
- pc->missing = '[';
6927
- pc->missingline = line;
7046
+ pc->missing.ch = '[';
7047
+ pc->missing.line = line;
69287048
pc->tend = pc->p - 1;
69297049
}
69307050
69317051
static int JimParseBrace(struct JimParserCtx *pc)
69327052
{
@@ -7066,19 +7186,19 @@
70667186
if (*pc->p == '"') {
70677187
pc->state = JIM_PS_QUOTE;
70687188
pc->p++;
70697189
pc->len--;
70707190
7071
- pc->missingline = pc->tline;
7191
+ pc->missing.line = pc->tline;
70727192
}
70737193
}
70747194
pc->tstart = pc->p;
70757195
pc->tline = pc->linenr;
70767196
while (1) {
70777197
if (pc->len == 0) {
70787198
if (pc->state == JIM_PS_QUOTE) {
7079
- pc->missing = '"';
7199
+ pc->missing.ch = '"';
70807200
}
70817201
pc->tend = pc->p - 1;
70827202
pc->tt = JIM_TT_ESC;
70837203
return JIM_OK;
70847204
}
@@ -7094,10 +7214,14 @@
70947214
pc->linenr++;
70957215
}
70967216
pc->p++;
70977217
pc->len--;
70987218
}
7219
+ else if (pc->len == 1) {
7220
+
7221
+ pc->missing.ch = '\\';
7222
+ }
70997223
break;
71007224
case '(':
71017225
71027226
if (pc->len > 1 && pc->p[1] != '$') {
71037227
break;
@@ -7154,17 +7278,26 @@
71547278
}
71557279
71567280
static int JimParseComment(struct JimParserCtx *pc)
71577281
{
71587282
while (*pc->p) {
7159
- if (*pc->p == '\n') {
7283
+ if (*pc->p == '\\') {
7284
+ pc->p++;
7285
+ pc->len--;
7286
+ if (pc->len == 0) {
7287
+ pc->missing.ch = '\\';
7288
+ return JIM_OK;
7289
+ }
7290
+ if (*pc->p == '\n') {
7291
+ pc->linenr++;
7292
+ }
7293
+ }
7294
+ else if (*pc->p == '\n') {
7295
+ pc->p++;
7296
+ pc->len--;
71607297
pc->linenr++;
7161
- if (*(pc->p - 1) != '\\') {
7162
- pc->p++;
7163
- pc->len--;
7164
- return JIM_OK;
7165
- }
7298
+ break;
71667299
}
71677300
pc->p++;
71687301
pc->len--;
71697302
}
71707303
return JIM_OK;
@@ -7382,13 +7515,13 @@
73827515
JimParserInit(&parser, s, len, 1);
73837516
while (!parser.eof) {
73847517
JimParseScript(&parser);
73857518
}
73867519
if (stateCharPtr) {
7387
- *stateCharPtr = parser.missing;
7520
+ *stateCharPtr = parser.missing.ch;
73887521
}
7389
- return parser.missing == ' ';
7522
+ return parser.missing.ch == ' ';
73907523
}
73917524
73927525
static int JimParseListSep(struct JimParserCtx *pc);
73937526
static int JimParseListStr(struct JimParserCtx *pc);
73947527
static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7546,17 +7679,21 @@
75467679
objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
75477680
if (objPtr->nextObjPtr)
75487681
objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
75497682
if (interp->liveList == objPtr)
75507683
interp->liveList = objPtr->nextObjPtr;
7684
+#ifdef JIM_DISABLE_OBJECT_POOL
7685
+ Jim_Free(objPtr);
7686
+#else
75517687
75527688
objPtr->prevObjPtr = NULL;
75537689
objPtr->nextObjPtr = interp->freeList;
75547690
if (interp->freeList)
75557691
interp->freeList->prevObjPtr = objPtr;
75567692
interp->freeList = objPtr;
75577693
objPtr->refCount = -1;
7694
+#endif
75587695
}
75597696
75607697
75617698
void Jim_InvalidateStringRep(Jim_Obj *objPtr)
75627699
{
@@ -7636,10 +7773,16 @@
76367773
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
76377774
objPtr->typePtr->updateStringProc(objPtr);
76387775
}
76397776
return objPtr->bytes;
76407777
}
7778
+
7779
+static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
7780
+{
7781
+ objPtr->bytes = Jim_StrDup(str);
7782
+ objPtr->length = strlen(str);
7783
+}
76417784
76427785
static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
76437786
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
76447787
76457788
static const Jim_ObjType dictSubstObjType = {
@@ -7677,11 +7820,10 @@
76777820
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
76787821
{
76797822
JIM_NOTUSED(interp);
76807823
76817824
dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7682
-
76837825
dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
76847826
}
76857827
76867828
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
76877829
{
@@ -7726,18 +7868,17 @@
77267868
if (len == -1)
77277869
len = strlen(s);
77287870
77297871
if (len == 0) {
77307872
objPtr->bytes = JimEmptyStringRep;
7731
- objPtr->length = 0;
77327873
}
77337874
else {
77347875
objPtr->bytes = Jim_Alloc(len + 1);
7735
- objPtr->length = len;
77367876
memcpy(objPtr->bytes, s, len);
77377877
objPtr->bytes[len] = '\0';
77387878
}
7879
+ objPtr->length = len;
77397880
77407881
77417882
objPtr->typePtr = NULL;
77427883
return objPtr;
77437884
}
@@ -7765,11 +7906,11 @@
77657906
Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
77667907
{
77677908
Jim_Obj *objPtr = Jim_NewObj(interp);
77687909
77697910
objPtr->bytes = s;
7770
- objPtr->length = len == -1 ? strlen(s) : len;
7911
+ objPtr->length = (len == -1) ? strlen(s) : len;
77717912
objPtr->typePtr = NULL;
77727913
return objPtr;
77737914
}
77747915
77757916
static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7794,17 +7935,17 @@
77947935
}
77957936
objPtr->internalRep.strValue.maxLength = needlen;
77967937
}
77977938
memcpy(objPtr->bytes + objPtr->length, str, len);
77987939
objPtr->bytes[objPtr->length + len] = '\0';
7940
+
77997941
if (objPtr->internalRep.strValue.charLength >= 0) {
78007942
78017943
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
78027944
}
78037945
objPtr->length += len;
78047946
}
7805
-
78067947
78077948
void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
78087949
{
78097950
JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
78107951
SetStringFromAny(interp, objPtr);
@@ -7812,13 +7953,11 @@
78127953
}
78137954
78147955
void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
78157956
{
78167957
int len;
7817
- const char *str;
7818
-
7819
- str = Jim_GetString(appendObjPtr, &len);
7958
+ const char *str = Jim_GetString(appendObjPtr, &len);
78207959
Jim_AppendString(interp, objPtr, str, len);
78217960
}
78227961
78237962
void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
78247963
{
@@ -7825,11 +7964,11 @@
78257964
va_list ap;
78267965
78277966
SetStringFromAny(interp, objPtr);
78287967
va_start(ap, objPtr);
78297968
while (1) {
7830
- char *s = va_arg(ap, char *);
7969
+ const char *s = va_arg(ap, const char *);
78317970
78327971
if (s == NULL)
78337972
break;
78347973
Jim_AppendString(interp, objPtr, s, -1);
78357974
}
@@ -7836,20 +7975,20 @@
78367975
va_end(ap);
78377976
}
78387977
78397978
int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
78407979
{
7841
- const char *aStr, *bStr;
7842
- int aLen, bLen;
7843
-
7844
- if (aObjPtr == bObjPtr)
7980
+ if (aObjPtr == bObjPtr) {
78457981
return 1;
7846
- aStr = Jim_GetString(aObjPtr, &aLen);
7847
- bStr = Jim_GetString(bObjPtr, &bLen);
7848
- if (aLen != bLen)
7849
- return 0;
7850
- return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
7982
+ }
7983
+ else {
7984
+ int Alen, Blen;
7985
+ const char *sA = Jim_GetString(aObjPtr, &Alen);
7986
+ const char *sB = Jim_GetString(bObjPtr, &Blen);
7987
+
7988
+ return Alen == Blen && memcmp(sA, sB, Alen) == 0;
7989
+ }
78517990
}
78527991
78537992
int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
78547993
{
78557994
return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8010,11 +8149,11 @@
80108149
static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
80118150
{
80128151
while (*str) {
80138152
int c;
80148153
str += utf8_tounicode(str, &c);
8015
- dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8154
+ dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
80168155
}
80178156
*dest = 0;
80188157
}
80198158
80208159
static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8070,11 +8209,11 @@
80708209
len *= 2;
80718210
#endif
80728211
buf = p = Jim_Alloc(len + 1);
80738212
80748213
str += utf8_tounicode(str, &c);
8075
- p += utf8_fromunicode(p, utf8_title(c));
8214
+ p += utf8_getchars(p, utf8_title(c));
80768215
80778216
JimStrCopyUpperLower(p, str, 0);
80788217
80798218
return Jim_NewStringObjNoAlloc(interp, buf, -1);
80808219
}
@@ -8177,10 +8316,11 @@
81778316
if (nontrim == NULL) {
81788317
81798318
return Jim_NewEmptyStringObj(interp);
81808319
}
81818320
if (nontrim == strObjPtr->bytes + len) {
8321
+
81828322
return strObjPtr;
81838323
}
81848324
81858325
if (Jim_IsShared(strObjPtr)) {
81868326
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8200,19 +8340,28 @@
82008340
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
82018341
82028342
82038343
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
82048344
8205
- if (objPtr != strObjPtr) {
8345
+
8346
+ if (objPtr != strObjPtr && objPtr->refCount == 0) {
82068347
8207
- Jim_IncrRefCount(objPtr);
8208
- Jim_DecrRefCount(interp, objPtr);
8348
+ Jim_FreeNewObj(interp, objPtr);
82098349
}
82108350
82118351
return strObjPtr;
82128352
}
82138353
8354
+
8355
+#ifdef HAVE_ISASCII
8356
+#define jim_isascii isascii
8357
+#else
8358
+static int jim_isascii(int c)
8359
+{
8360
+ return !(c & ~0x7f);
8361
+}
8362
+#endif
82148363
82158364
static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
82168365
{
82178366
static const char * const strclassnames[] = {
82188367
"integer", "alpha", "alnum", "ascii", "digit",
@@ -8235,32 +8384,32 @@
82358384
return JIM_ERR;
82368385
}
82378386
82388387
str = Jim_GetString(strObjPtr, &len);
82398388
if (len == 0) {
8240
- Jim_SetResultInt(interp, !strict);
8389
+ Jim_SetResultBool(interp, !strict);
82418390
return JIM_OK;
82428391
}
82438392
82448393
switch (strclass) {
82458394
case STR_IS_INTEGER:
82468395
{
82478396
jim_wide w;
8248
- Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8397
+ Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
82498398
return JIM_OK;
82508399
}
82518400
82528401
case STR_IS_DOUBLE:
82538402
{
82548403
double d;
8255
- Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8404
+ Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
82568405
return JIM_OK;
82578406
}
82588407
82598408
case STR_IS_ALPHA: isclassfunc = isalpha; break;
82608409
case STR_IS_ALNUM: isclassfunc = isalnum; break;
8261
- case STR_IS_ASCII: isclassfunc = isascii; break;
8410
+ case STR_IS_ASCII: isclassfunc = jim_isascii; break;
82628411
case STR_IS_DIGIT: isclassfunc = isdigit; break;
82638412
case STR_IS_LOWER: isclassfunc = islower; break;
82648413
case STR_IS_UPPER: isclassfunc = isupper; break;
82658414
case STR_IS_SPACE: isclassfunc = isspace; break;
82668415
case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
@@ -8272,15 +8421,15 @@
82728421
return JIM_ERR;
82738422
}
82748423
82758424
for (i = 0; i < len; i++) {
82768425
if (!isclassfunc(str[i])) {
8277
- Jim_SetResultInt(interp, 0);
8426
+ Jim_SetResultBool(interp, 0);
82788427
return JIM_OK;
82798428
}
82808429
}
8281
- Jim_SetResultInt(interp, 1);
8430
+ Jim_SetResultBool(interp, 1);
82828431
return JIM_OK;
82838432
}
82848433
82858434
82868435
@@ -8292,17 +8441,19 @@
82928441
JIM_TYPE_REFERENCES,
82938442
};
82948443
82958444
int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
82968445
{
8297
- if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8446
+ if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
82988447
return 1;
8448
+ }
82998449
else {
83008450
const char *objStr = Jim_String(objPtr);
83018451
83028452
if (strcmp(str, objStr) != 0)
83038453
return 0;
8454
+
83048455
if (objPtr->typePtr != &comparedStringObjType) {
83058456
Jim_FreeIntRep(interp, objPtr);
83068457
objPtr->typePtr = &comparedStringObjType;
83078458
}
83088459
objPtr->internalRep.ptr = (char *)str;
@@ -8344,24 +8495,23 @@
83448495
83458496
static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
83468497
Jim_Obj *fileNameObj, int lineNumber)
83478498
{
83488499
JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8349
- JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8500
+ JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
83508501
Jim_IncrRefCount(fileNameObj);
83518502
objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
83528503
objPtr->internalRep.sourceValue.lineNumber = lineNumber;
83538504
objPtr->typePtr = &sourceObjType;
83548505
}
83558506
8356
-
83578507
static const Jim_ObjType scriptLineObjType = {
83588508
"scriptline",
83598509
NULL,
83608510
NULL,
83618511
NULL,
8362
- 0,
8512
+ JIM_NONE,
83638513
};
83648514
83658515
static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
83668516
{
83678517
Jim_Obj *objPtr;
@@ -8378,15 +8528,14 @@
83788528
objPtr->internalRep.scriptLineValue.line = line;
83798529
83808530
return objPtr;
83818531
}
83828532
8383
-#define JIM_CMDSTRUCT_EXPAND -1
8384
-
83858533
static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
83868534
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8387
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
8535
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8536
+static int JimParseCheckMissing(Jim_Interp *interp, int ch);
83888537
83898538
static const Jim_ObjType scriptObjType = {
83908539
"script",
83918540
FreeScriptInternalRep,
83928541
DupScriptInternalRep,
@@ -8394,34 +8543,33 @@
83948543
JIM_TYPE_REFERENCES,
83958544
};
83968545
83978546
typedef struct ScriptToken
83988547
{
8399
- int type;
84008548
Jim_Obj *objPtr;
8549
+ int type;
84018550
} ScriptToken;
84028551
84038552
typedef struct ScriptObj
84048553
{
8405
- int len;
84068554
ScriptToken *token;
8555
+ Jim_Obj *fileNameObj;
8556
+ int len;
84078557
int substFlags;
84088558
int inUse; /* Used to share a ScriptObj. Currently
84098559
only used by Jim_EvalObj() as protection against
84108560
shimmering of the currently evaluated object. */
8411
- Jim_Obj *fileNameObj;
84128561
int firstline;
84138562
int linenr;
84148563
} ScriptObj;
84158564
84168565
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
84178566
{
84188567
int i;
84198568
struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
84208569
8421
- script->inUse--;
8422
- if (script->inUse != 0)
8570
+ if (--script->inUse != 0)
84238571
return;
84248572
for (i = 0; i < script->len; i++) {
84258573
Jim_DecrRefCount(interp, script->token[i].objPtr);
84268574
}
84278575
Jim_Free(script->token);
@@ -8432,11 +8580,10 @@
84328580
void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
84338581
{
84348582
JIM_NOTUSED(interp);
84358583
JIM_NOTUSED(srcPtr);
84368584
8437
-
84388585
dupPtr->typePtr = NULL;
84398586
}
84408587
84418588
typedef struct
84428589
{
@@ -8631,11 +8778,11 @@
86318778
token--;
86328779
}
86338780
86348781
script->len = token - script->token;
86358782
8636
- assert(script->len < count);
8783
+ JimPanic((script->len >= count, "allocated script array is too short"));
86378784
86388785
#ifdef DEBUG_SHOW_SCRIPT
86398786
printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
86408787
for (i = 0; i < script->len; i++) {
86418788
const ScriptToken *t = &script->token[i];
@@ -8642,10 +8789,35 @@
86428789
printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
86438790
}
86448791
#endif
86458792
86468793
}
8794
+
8795
+static int JimParseCheckMissing(Jim_Interp *interp, int ch)
8796
+{
8797
+ const char *msg;
8798
+
8799
+ switch (ch) {
8800
+ case '\\':
8801
+ case ' ':
8802
+ return JIM_OK;
8803
+
8804
+ case '[':
8805
+ msg = "unmatched \"[\"";
8806
+ break;
8807
+ case '{':
8808
+ msg = "missing close-brace";
8809
+ break;
8810
+ case '"':
8811
+ default:
8812
+ msg = "missing quote";
8813
+ break;
8814
+ }
8815
+
8816
+ Jim_SetResultString(interp, msg, -1);
8817
+ return JIM_ERR;
8818
+}
86478819
86488820
static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
86498821
ParseTokenList *tokenlist)
86508822
{
86518823
int i;
@@ -8664,18 +8836,19 @@
86648836
}
86658837
86668838
script->len = i;
86678839
}
86688840
8669
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8841
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
86708842
{
86718843
int scriptTextLen;
86728844
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
86738845
struct JimParserCtx parser;
86748846
struct ScriptObj *script;
86758847
ParseTokenList tokenlist;
86768848
int line = 1;
8849
+ int retcode = JIM_OK;
86778850
86788851
86798852
if (objPtr->typePtr == &sourceObjType) {
86808853
line = objPtr->internalRep.sourceValue.lineNumber;
86818854
}
@@ -8687,16 +8860,12 @@
86878860
while (!parser.eof) {
86888861
JimParseScript(&parser);
86898862
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
86908863
parser.tline);
86918864
}
8692
- if (result && parser.missing != ' ') {
8693
- ScriptTokenListFree(&tokenlist);
8694
- result->missing = parser.missing;
8695
- result->line = parser.missingline;
8696
- return JIM_ERR;
8697
- }
8865
+
8866
+ retcode = JimParseCheckMissing(interp, parser.missing.ch);
86988867
86998868
87008869
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
87018870
87028871
@@ -8707,10 +8876,11 @@
87078876
script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
87088877
}
87098878
else {
87108879
script->fileNameObj = interp->emptyObj;
87118880
}
8881
+ script->linenr = parser.missing.line;
87128882
Jim_IncrRefCount(script->fileNameObj);
87138883
87148884
ScriptObjAddTokens(interp, script, &tokenlist);
87158885
87168886
@@ -8719,11 +8889,11 @@
87198889
87208890
Jim_FreeIntRep(interp, objPtr);
87218891
Jim_SetIntRepPtr(objPtr, script);
87228892
objPtr->typePtr = &scriptObjType;
87238893
8724
- return JIM_OK;
8894
+ return retcode;
87258895
}
87268896
87278897
ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
87288898
{
87298899
if (objPtr == interp->emptyObj) {
@@ -8730,11 +8900,13 @@
87308900
87318901
objPtr = interp->nullScriptObj;
87328902
}
87338903
87348904
if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8735
- SetScriptFromAny(interp, objPtr, NULL);
8905
+ if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
8906
+ return NULL;
8907
+ }
87368908
}
87378909
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
87388910
}
87398911
87408912
static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8815,10 +8987,26 @@
88158987
nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
88168988
Jim_AppendStrings(interp, nsObj, "::", name, NULL);
88178989
}
88188990
return nsObj;
88198991
}
8992
+
8993
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
8994
+{
8995
+ Jim_Obj *resultObj;
8996
+
8997
+ const char *name = Jim_String(nameObjPtr);
8998
+ if (name[0] == ':' && name[1] == ':') {
8999
+ return nameObjPtr;
9000
+ }
9001
+ Jim_IncrRefCount(nameObjPtr);
9002
+ resultObj = Jim_NewStringObj(interp, "::", -1);
9003
+ Jim_AppendObj(interp, resultObj, nameObjPtr);
9004
+ Jim_DecrRefCount(interp, nameObjPtr);
9005
+
9006
+ return resultObj;
9007
+}
88209008
88219009
static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
88229010
{
88239011
Jim_Obj *objPtr = interp->emptyObj;
88249012
@@ -8842,10 +9030,15 @@
88429030
88439031
#else
88449032
88459033
#define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
88469034
#define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9035
+
9036
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9037
+{
9038
+ return nameObjPtr;
9039
+}
88479040
#endif
88489041
88499042
static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
88509043
{
88519044
Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8854,12 +9047,12 @@
88549047
Jim_InterpIncrProcEpoch(interp);
88559048
}
88569049
88579050
if (he && interp->local) {
88589051
8859
- cmd->prevCmd = he->u.val;
8860
- he->u.val = cmd;
9052
+ cmd->prevCmd = Jim_GetHashEntryVal(he);
9053
+ Jim_SetHashVal(&interp->commands, he, cmd);
88619054
}
88629055
else {
88639056
if (he) {
88649057
88659058
Jim_DeleteHashEntry(&interp->commands, name);
@@ -8898,19 +9091,19 @@
88989091
}
88999092
89009093
cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
89019094
Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
89029095
for (i = 0; i < len; i++) {
8903
- Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
9096
+ Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
89049097
Jim_Var *varPtr;
89059098
int subLen;
89069099
8907
- Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
9100
+ objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
89089101
89099102
subLen = Jim_ListLength(interp, objPtr);
89109103
if (subLen == 1 || subLen == 2) {
8911
- Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
9104
+ nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
89129105
if (subLen == 1) {
89139106
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
89149107
if (initObjPtr == NULL) {
89159108
Jim_SetResultFormatted(interp,
89169109
"variable for initialization of static \"%#s\" not found in the local context",
@@ -8917,11 +9110,11 @@
89179110
nameObjPtr);
89189111
return JIM_ERR;
89199112
}
89209113
}
89219114
else {
8922
- Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
9115
+ initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
89239116
}
89249117
if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
89259118
return JIM_ERR;
89269119
}
89279120
@@ -9003,11 +9196,11 @@
90039196
Jim_Obj *nameObjPtr;
90049197
Jim_Obj *defaultObjPtr;
90059198
int len;
90069199
90079200
9008
- Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9201
+ argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
90099202
len = Jim_ListLength(interp, argPtr);
90109203
if (len == 0) {
90119204
Jim_SetResultString(interp, "argument with no name", -1);
90129205
err:
90139206
JimDecrCmdRefCount(interp, cmdPtr);
@@ -9018,12 +9211,12 @@
90189211
goto err;
90199212
}
90209213
90219214
if (len == 2) {
90229215
9023
- Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9024
- Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9216
+ nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9217
+ defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
90259218
}
90269219
else {
90279220
90289221
nameObjPtr = argPtr;
90299222
defaultObjPtr = NULL;
@@ -9097,11 +9290,11 @@
90979290
else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
90989291
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
90999292
}
91009293
else {
91019294
9102
- cmdPtr = he->u.val;
9295
+ cmdPtr = Jim_GetHashEntryVal(he);
91039296
JimIncrCmdRefCount(cmdPtr);
91049297
JimUpdateProcNamespace(interp, cmdPtr, fqnew);
91059298
Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
91069299
91079300
@@ -9182,11 +9375,11 @@
91829375
return NULL;
91839376
}
91849377
#ifdef jim_ext_namespace
91859378
found:
91869379
#endif
9187
- cmd = (Jim_Cmd *)he->u.val;
9380
+ cmd = Jim_GetHashEntryVal(he);
91889381
91899382
91909383
Jim_FreeIntRep(interp, objPtr);
91919384
objPtr->typePtr = &commandObjType;
91929385
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9288,11 +9481,11 @@
92889481
92899482
92909483
Jim_FreeIntRep(interp, objPtr);
92919484
objPtr->typePtr = &variableObjType;
92929485
objPtr->internalRep.varValue.callFrameId = framePtr->id;
9293
- objPtr->internalRep.varValue.varPtr = he->u.val;
9486
+ objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
92949487
objPtr->internalRep.varValue.global = global;
92959488
return JIM_OK;
92969489
}
92979490
92989491
@@ -9606,11 +9799,11 @@
96069799
}
96079800
96089801
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
96099802
if (retval == JIM_OK) {
96109803
9611
- JimChangeCallFrameId(interp, framePtr);
9804
+ framePtr->id = interp->callFrameEpoch++;
96129805
}
96139806
}
96149807
}
96159808
if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
96169809
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9690,28 +9883,17 @@
96909883
return NULL;
96919884
}
96929885
96939886
ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
96949887
if (ret != JIM_OK) {
9695
- resObjPtr = NULL;
9696
- if (ret < 0) {
9697
- Jim_SetResultFormatted(interp,
9698
- "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9699
- }
9700
- else {
9701
- Jim_SetResultFormatted(interp,
9702
- "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9703
- }
9888
+ Jim_SetResultFormatted(interp,
9889
+ "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
9890
+ ret < 0 ? "variable isn't" : "no such element in");
97049891
}
97059892
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9706
- dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9707
- if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9708
-
9709
- JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9710
- }
97119893
9712
- Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9894
+ Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
97139895
}
97149896
97159897
return resObjPtr;
97169898
}
97179899
@@ -9808,68 +9990,67 @@
98089990
Jim_CallFrame *cf;
98099991
98109992
if (interp->freeFramesList) {
98119993
cf = interp->freeFramesList;
98129994
interp->freeFramesList = cf->next;
9995
+
9996
+ cf->argv = NULL;
9997
+ cf->argc = 0;
9998
+ cf->procArgsObjPtr = NULL;
9999
+ cf->procBodyObjPtr = NULL;
10000
+ cf->next = NULL;
10001
+ cf->staticVars = NULL;
10002
+ cf->localCommands = NULL;
10003
+ cf->tailcall = 0;
10004
+ cf->tailcallObj = NULL;
10005
+ cf->tailcallCmd = NULL;
981310006
}
981410007
else {
981510008
cf = Jim_Alloc(sizeof(*cf));
9816
- cf->vars.table = NULL;
10009
+ memset(cf, 0, sizeof(*cf));
10010
+
10011
+ Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
981710012
}
981810013
981910014
cf->id = interp->callFrameEpoch++;
982010015
cf->parent = parent;
982110016
cf->level = parent ? parent->level + 1 : 0;
9822
- cf->argv = NULL;
9823
- cf->argc = 0;
9824
- cf->procArgsObjPtr = NULL;
9825
- cf->procBodyObjPtr = NULL;
9826
- cf->next = NULL;
9827
- cf->staticVars = NULL;
9828
- cf->localCommands = NULL;
9829
-
983010017
cf->nsObj = nsObj;
983110018
Jim_IncrRefCount(nsObj);
9832
- if (cf->vars.table == NULL)
9833
- Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
10019
+
983410020
return cf;
983510021
}
983610022
9837
-
9838
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9839
-{
9840
- cf->id = interp->callFrameEpoch++;
9841
-}
9842
-
984310023
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
984410024
{
984510025
984610026
if (localCommands) {
984710027
Jim_Obj *cmdNameObj;
984810028
984910029
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
985010030
Jim_HashEntry *he;
985110031
Jim_Obj *fqObjName;
10032
+ Jim_HashTable *ht = &interp->commands;
985210033
985310034
const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
985410035
9855
- he = Jim_FindHashEntry(&interp->commands, fqname);
10036
+ he = Jim_FindHashEntry(ht, fqname);
985610037
985710038
if (he) {
9858
- Jim_Cmd *cmd = he->u.val;
10039
+ Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
985910040
if (cmd->prevCmd) {
986010041
Jim_Cmd *prevCmd = cmd->prevCmd;
986110042
cmd->prevCmd = NULL;
986210043
986310044
986410045
JimDecrCmdRefCount(interp, cmd);
986510046
986610047
9867
- he->u.val = prevCmd;
10048
+ Jim_SetHashVal(ht, he, prevCmd);
986810049
}
986910050
else {
9870
- Jim_DeleteHashEntry(&interp->commands, fqname);
10051
+ Jim_DeleteHashEntry(ht, fqname);
987110052
Jim_InterpIncrProcEpoch(interp);
987210053
}
987310054
}
987410055
Jim_DecrRefCount(interp, cmdNameObj);
987510056
JimFreeQualifiedName(interp, fqObjName);
@@ -9879,47 +10060,45 @@
987910060
}
988010061
return JIM_OK;
988110062
}
988210063
988310064
9884
-#define JIM_FCF_NONE 0
9885
-#define JIM_FCF_NOHT 1
9886
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9887
-{
10065
+#define JIM_FCF_FULL 0
10066
+#define JIM_FCF_REUSE 1
10067
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10068
+ {
10069
+ JimDeleteLocalProcs(interp, cf->localCommands);
10070
+
988810071
if (cf->procArgsObjPtr)
988910072
Jim_DecrRefCount(interp, cf->procArgsObjPtr);
989010073
if (cf->procBodyObjPtr)
989110074
Jim_DecrRefCount(interp, cf->procBodyObjPtr);
989210075
Jim_DecrRefCount(interp, cf->nsObj);
9893
- if (!(flags & JIM_FCF_NOHT))
10076
+ if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
989410077
Jim_FreeHashTable(&cf->vars);
989510078
else {
989610079
int i;
989710080
Jim_HashEntry **table = cf->vars.table, *he;
989810081
989910082
for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
990010083
he = table[i];
990110084
while (he != NULL) {
990210085
Jim_HashEntry *nextEntry = he->next;
9903
- Jim_Var *varPtr = (void *)he->u.val;
10086
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
990410087
990510088
Jim_DecrRefCount(interp, varPtr->objPtr);
9906
- Jim_Free(he->u.val);
9907
- Jim_Free((void *)he->key);
10089
+ Jim_Free(Jim_GetHashEntryKey(he));
10090
+ Jim_Free(varPtr);
990810091
Jim_Free(he);
990910092
table[i] = NULL;
991010093
he = nextEntry;
991110094
}
991210095
}
991310096
cf->vars.used = 0;
991410097
}
9915
-
9916
- JimDeleteLocalProcs(interp, cf->localCommands);
9917
-
991810098
cf->next = interp->freeFramesList;
991910099
interp->freeFramesList = cf;
9920
-
992110100
}
992210101
992310102
992410103
#ifdef JIM_REFERENCES
992510104
@@ -9996,21 +10175,16 @@
999610175
NULL,
999710176
UpdateStringOfReference,
999810177
JIM_TYPE_REFERENCES,
999910178
};
1000010179
10001
-void UpdateStringOfReference(struct Jim_Obj *objPtr)
10180
+static void UpdateStringOfReference(struct Jim_Obj *objPtr)
1000210181
{
10003
- int len;
1000410182
char buf[JIM_REFERENCE_SPACE + 1];
10005
- Jim_Reference *refPtr;
1000610183
10007
- refPtr = objPtr->internalRep.refValue.refPtr;
10008
- len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10009
- objPtr->bytes = Jim_Alloc(len + 1);
10010
- memcpy(objPtr->bytes, buf, len + 1);
10011
- objPtr->length = len;
10184
+ JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10185
+ JimSetStringBytes(objPtr, buf);
1001210186
}
1001310187
1001410188
static int isrefchar(int c)
1001510189
{
1001610190
return (c == '_' || isalnum(c));
@@ -10061,11 +10235,11 @@
1006110235
he = Jim_FindHashEntry(&interp->references, &value);
1006210236
if (he == NULL) {
1006310237
Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
1006410238
return JIM_ERR;
1006510239
}
10066
- refPtr = he->u.val;
10240
+ refPtr = Jim_GetHashEntryVal(he);
1006710241
1006810242
Jim_FreeIntRep(interp, objPtr);
1006910243
objPtr->typePtr = &referenceObjType;
1007010244
objPtr->internalRep.refValue.id = value;
1007110245
objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10178,11 +10352,11 @@
1017810352
Jim_Collect(interp);
1017910353
}
1018010354
}
1018110355
#endif
1018210356
10183
-static int JimIsBigEndian(void)
10357
+int Jim_IsBigEndian(void)
1018410358
{
1018510359
union {
1018610360
unsigned short s;
1018710361
unsigned char c[2];
1018810362
} uval = {0x0102};
@@ -10234,23 +10408,30 @@
1023410408
Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
1023510409
1023610410
Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
1023710411
Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
1023810412
Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
10239
- Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian");
10413
+ Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
1024010414
Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
1024110415
Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
1024210416
Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
1024310417
1024410418
return i;
1024510419
}
1024610420
1024710421
void Jim_FreeInterp(Jim_Interp *i)
1024810422
{
10249
- Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
10423
+ Jim_CallFrame *cf, *cfx;
10424
+
1025010425
Jim_Obj *objPtr, *nextObjPtr;
1025110426
10427
+
10428
+ for (cf = i->framePtr; cf; cf = cfx) {
10429
+ cfx = cf->parent;
10430
+ JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10431
+ }
10432
+
1025210433
Jim_DecrRefCount(i, i->emptyObj);
1025310434
Jim_DecrRefCount(i, i->trueObj);
1025410435
Jim_DecrRefCount(i, i->falseObj);
1025510436
Jim_DecrRefCount(i, i->result);
1025610437
Jim_DecrRefCount(i, i->stackTrace);
@@ -10265,61 +10446,54 @@
1026510446
#endif
1026610447
Jim_FreeHashTable(&i->packages);
1026710448
Jim_Free(i->prngState);
1026810449
Jim_FreeHashTable(&i->assocData);
1026910450
10270
-
10271
- while (cf) {
10272
- prevcf = cf->parent;
10273
- JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10274
- cf = prevcf;
10275
- }
10451
+#ifdef JIM_MAINTAINER
1027610452
if (i->liveList != NULL) {
1027710453
objPtr = i->liveList;
1027810454
10279
- printf(JIM_NL "-------------------------------------" JIM_NL);
10280
- printf("Objects still in the free list:" JIM_NL);
10455
+ printf("\n-------------------------------------\n");
10456
+ printf("Objects still in the free list:\n");
1028110457
while (objPtr) {
1028210458
const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
1028310459
1028410460
if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10285
- printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10461
+ printf("%p (%d) %-10s: '%.20s...'\n",
1028610462
(void *)objPtr, objPtr->refCount, type, objPtr->bytes);
1028710463
}
1028810464
else {
10289
- printf("%p (%d) %-10s: '%s'" JIM_NL,
10465
+ printf("%p (%d) %-10s: '%s'\n",
1029010466
(void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
1029110467
}
1029210468
if (objPtr->typePtr == &sourceObjType) {
10293
- printf("FILE %s LINE %d" JIM_NL,
10469
+ printf("FILE %s LINE %d\n",
1029410470
Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
1029510471
objPtr->internalRep.sourceValue.lineNumber);
1029610472
}
1029710473
objPtr = objPtr->nextObjPtr;
1029810474
}
10299
- printf("-------------------------------------" JIM_NL JIM_NL);
10475
+ printf("-------------------------------------\n\n");
1030010476
JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
1030110477
}
10478
+#endif
10479
+
1030210480
1030310481
objPtr = i->freeList;
1030410482
while (objPtr) {
1030510483
nextObjPtr = objPtr->nextObjPtr;
1030610484
Jim_Free(objPtr);
1030710485
objPtr = nextObjPtr;
1030810486
}
10487
+
1030910488
10310
- cf = i->freeFramesList;
10311
- while (cf) {
10312
- nextcf = cf->next;
10313
- if (cf->vars.table != NULL)
10314
- Jim_Free(cf->vars.table);
10489
+ for (cf = i->freeFramesList; cf; cf = cfx) {
10490
+ cfx = cf->next;
10491
+ if (cf->vars.table)
10492
+ Jim_FreeHashTable(&cf->vars);
1031510493
Jim_Free(cf);
10316
- cf = nextcf;
1031710494
}
10318
-#ifdef jim_ext_load
10319
- Jim_FreeLoadHandles(i);
10320
-#endif
1032110495
1032210496
1032310497
Jim_Free(i);
1032410498
}
1032510499
@@ -10414,22 +10588,15 @@
1041410588
interp->stackTrace = stackTraceObj;
1041510589
interp->errorFlag = 1;
1041610590
1041710591
len = Jim_ListLength(interp, interp->stackTrace);
1041810592
if (len >= 3) {
10419
- Jim_Obj *filenameObj;
10420
-
10421
- Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE);
10422
-
10423
- Jim_GetString(filenameObj, &len);
10424
-
10425
- if (!Jim_Length(filenameObj)) {
10593
+ if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
1042610594
interp->addStackTrace = 1;
1042710595
}
1042810596
}
1042910597
}
10430
-
1043110598
1043210599
static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
1043310600
Jim_Obj *fileNameObj, int linenr)
1043410601
{
1043510602
if (strcmp(procname, "unknown") == 0) {
@@ -10450,14 +10617,15 @@
1045010617
if (!*procname && Jim_Length(fileNameObj)) {
1045110618
1045210619
int len = Jim_ListLength(interp, interp->stackTrace);
1045310620
1045410621
if (len >= 3) {
10455
- Jim_Obj *objPtr;
10456
- if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) {
10622
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10623
+ if (Jim_Length(objPtr)) {
1045710624
10458
- if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) {
10625
+ objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10626
+ if (Jim_Length(objPtr) == 0) {
1045910627
1046010628
ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
1046110629
ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
1046210630
return;
1046310631
}
@@ -10483,12 +10651,11 @@
1048310651
void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
1048410652
{
1048510653
Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
1048610654
1048710655
if (entryPtr != NULL) {
10488
- AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10489
-
10656
+ AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
1049010657
return assocEntryPtr->data;
1049110658
}
1049210659
return NULL;
1049310660
}
1049410661
@@ -10500,12 +10667,10 @@
1050010667
int Jim_GetExitCode(Jim_Interp *interp)
1050110668
{
1050210669
return interp->exitCode;
1050310670
}
1050410671
10505
-#define JIM_INTEGER_SPACE 24
10506
-
1050710672
static void UpdateStringOfInt(struct Jim_Obj *objPtr);
1050810673
static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
1050910674
1051010675
static const Jim_ObjType intObjType = {
1051110676
"int",
@@ -10522,22 +10687,46 @@
1052210687
UpdateStringOfInt,
1052310688
JIM_TYPE_NONE,
1052410689
};
1052510690
1052610691
10527
-void UpdateStringOfInt(struct Jim_Obj *objPtr)
10692
+static void UpdateStringOfInt(struct Jim_Obj *objPtr)
1052810693
{
10529
- int len;
1053010694
char buf[JIM_INTEGER_SPACE + 1];
10695
+ jim_wide wideValue = JimWideValue(objPtr);
10696
+ int pos = 0;
1053110697
10532
- len = Jim_WideToString(buf, JimWideValue(objPtr));
10533
- objPtr->bytes = Jim_Alloc(len + 1);
10534
- memcpy(objPtr->bytes, buf, len + 1);
10535
- objPtr->length = len;
10698
+ if (wideValue == 0) {
10699
+ buf[pos++] = '0';
10700
+ }
10701
+ else {
10702
+ char tmp[JIM_INTEGER_SPACE];
10703
+ int num = 0;
10704
+ int i;
10705
+
10706
+ if (wideValue < 0) {
10707
+ buf[pos++] = '-';
10708
+ i = wideValue % 10;
10709
+ tmp[num++] = (i > 0) ? (10 - i) : -i;
10710
+ wideValue /= -10;
10711
+ }
10712
+
10713
+ while (wideValue) {
10714
+ tmp[num++] = wideValue % 10;
10715
+ wideValue /= 10;
10716
+ }
10717
+
10718
+ for (i = 0; i < num; i++) {
10719
+ buf[pos++] = '0' + tmp[num - i - 1];
10720
+ }
10721
+ }
10722
+ buf[pos] = 0;
10723
+
10724
+ JimSetStringBytes(objPtr, buf);
1053610725
}
1053710726
10538
-int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10727
+static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
1053910728
{
1054010729
jim_wide wideValue;
1054110730
const char *str;
1054210731
1054310732
if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10625,22 +10814,65 @@
1062510814
NULL,
1062610815
UpdateStringOfDouble,
1062710816
JIM_TYPE_NONE,
1062810817
};
1062910818
10630
-void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10631
-{
10632
- int len;
10633
- char buf[JIM_DOUBLE_SPACE + 1];
10634
-
10635
- len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10636
- objPtr->bytes = Jim_Alloc(len + 1);
10637
- memcpy(objPtr->bytes, buf, len + 1);
10638
- objPtr->length = len;
10819
+#ifndef HAVE_ISNAN
10820
+#undef isnan
10821
+#define isnan(X) ((X) != (X))
10822
+#endif
10823
+#ifndef HAVE_ISINF
10824
+#undef isinf
10825
+#define isinf(X) (1.0 / (X) == 0.0)
10826
+#endif
10827
+
10828
+static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10829
+{
10830
+ double value = objPtr->internalRep.doubleValue;
10831
+
10832
+ if (isnan(value)) {
10833
+ JimSetStringBytes(objPtr, "NaN");
10834
+ return;
10835
+ }
10836
+ if (isinf(value)) {
10837
+ if (value < 0) {
10838
+ JimSetStringBytes(objPtr, "-Inf");
10839
+ }
10840
+ else {
10841
+ JimSetStringBytes(objPtr, "Inf");
10842
+ }
10843
+ return;
10844
+ }
10845
+ {
10846
+ char buf[JIM_DOUBLE_SPACE + 1];
10847
+ int i;
10848
+ int len = sprintf(buf, "%.12g", value);
10849
+
10850
+
10851
+ for (i = 0; i < len; i++) {
10852
+ if (buf[i] == '.' || buf[i] == 'e') {
10853
+#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10854
+ char *e = strchr(buf, 'e');
10855
+ if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10856
+
10857
+ e += 2;
10858
+ memmove(e, e + 1, len - (e - buf));
10859
+ }
10860
+#endif
10861
+ break;
10862
+ }
10863
+ }
10864
+ if (buf[i] == '\0') {
10865
+ buf[i++] = '.';
10866
+ buf[i++] = '0';
10867
+ buf[i] = '\0';
10868
+ }
10869
+ JimSetStringBytes(objPtr, buf);
10870
+ }
1063910871
}
1064010872
10641
-int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10873
+static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1064210874
{
1064310875
double doubleValue;
1064410876
jim_wide wideValue;
1064510877
const char *str;
1064610878
@@ -10755,11 +10987,11 @@
1075510987
}
1075610988
1075710989
#define JIM_ELESTR_SIMPLE 0
1075810990
#define JIM_ELESTR_BRACE 1
1075910991
#define JIM_ELESTR_QUOTE 2
10760
-static int ListElementQuotingType(const char *s, int len)
10992
+static unsigned char ListElementQuotingType(const char *s, int len)
1076110993
{
1076210994
int i, level, blevel, trySimple = 1;
1076310995
1076410996
1076510997
if (len == 0)
@@ -10848,15 +11080,15 @@
1084811080
return JIM_ELESTR_SIMPLE;
1084911081
}
1085011082
return JIM_ELESTR_QUOTE;
1085111083
}
1085211084
10853
-static int BackslashQuoteString(const char *s, char *q)
11085
+static int BackslashQuoteString(const char *s, int len, char *q)
1085411086
{
1085511087
char *p = q;
1085611088
10857
- while (*s) {
11089
+ while (len--) {
1085811090
switch (*s) {
1085911091
case ' ':
1086011092
case '$':
1086111093
case '"':
1086211094
case '[':
@@ -10903,17 +11135,23 @@
1090311135
return p - q;
1090411136
}
1090511137
1090611138
static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
1090711139
{
11140
+ #define STATIC_QUOTING_LEN 32
1090811141
int i, bufLen, realLength;
1090911142
const char *strRep;
1091011143
char *p;
10911
- int *quotingType;
11144
+ unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
1091211145
1091311146
10914
- quotingType = Jim_Alloc(sizeof(int) * objc + 1);
11147
+ if (objc > STATIC_QUOTING_LEN) {
11148
+ quotingType = Jim_Alloc(objc);
11149
+ }
11150
+ else {
11151
+ quotingType = staticQuoting;
11152
+ }
1091511153
bufLen = 0;
1091611154
for (i = 0; i < objc; i++) {
1091711155
int len;
1091811156
1091911157
strRep = Jim_GetString(objv[i], &len);
@@ -10962,11 +11200,11 @@
1096211200
case JIM_ELESTR_QUOTE:
1096311201
if (i == 0 && strRep[0] == '#') {
1096411202
*p++ = '\\';
1096511203
realLength++;
1096611204
}
10967
- qlen = BackslashQuoteString(strRep, p);
11205
+ qlen = BackslashQuoteString(strRep, len, p);
1096811206
p += qlen;
1096911207
realLength += qlen;
1097011208
break;
1097111209
}
1097211210
@@ -10975,11 +11213,14 @@
1097511213
realLength++;
1097611214
}
1097711215
}
1097811216
*p = '\0';
1097911217
objPtr->length = realLength;
10980
- Jim_Free(quotingType);
11218
+
11219
+ if (quotingType != staticQuoting) {
11220
+ Jim_Free(quotingType);
11221
+ }
1098111222
}
1098211223
1098311224
static void UpdateStringOfList(struct Jim_Obj *objPtr)
1098411225
{
1098511226
JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -10995,16 +11236,16 @@
1099511236
1099611237
if (objPtr->typePtr == &listObjType) {
1099711238
return JIM_OK;
1099811239
}
1099911240
11000
- if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11241
+ if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
1100111242
Jim_Obj **listObjPtrPtr;
1100211243
int len;
1100311244
int i;
1100411245
11005
- Jim_DictPairs(interp, objPtr, &listObjPtrPtr, &len);
11246
+ listObjPtrPtr = JimDictPairs(objPtr, &len);
1100611247
for (i = 0; i < len; i++) {
1100711248
Jim_IncrRefCount(listObjPtrPtr[i]);
1100811249
}
1100911250
1101011251
@@ -11099,15 +11340,17 @@
1109911340
Jim_Interp *interp;
1110011341
enum {
1110111342
JIM_LSORT_ASCII,
1110211343
JIM_LSORT_NOCASE,
1110311344
JIM_LSORT_INTEGER,
11345
+ JIM_LSORT_REAL,
1110411346
JIM_LSORT_COMMAND
1110511347
} type;
1110611348
int order;
1110711349
int index;
1110811350
int indexed;
11351
+ int unique;
1110911352
int (*subfn)(Jim_Obj **, Jim_Obj **);
1111011353
};
1111111354
1111211355
static struct lsort_info *sort_info;
1111311356
@@ -11142,10 +11385,27 @@
1114211385
longjmp(sort_info->jmpbuf, JIM_ERR);
1114311386
}
1114411387
1114511388
return JimSign(lhs - rhs) * sort_info->order;
1114611389
}
11390
+
11391
+static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11392
+{
11393
+ double lhs = 0, rhs = 0;
11394
+
11395
+ if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
11396
+ Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
11397
+ longjmp(sort_info->jmpbuf, JIM_ERR);
11398
+ }
11399
+ if (lhs == rhs) {
11400
+ return 0;
11401
+ }
11402
+ if (lhs > rhs) {
11403
+ return sort_info->order;
11404
+ }
11405
+ return -sort_info->order;
11406
+}
1114711407
1114811408
static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
1114911409
{
1115011410
Jim_Obj *compare_script;
1115111411
int rc;
@@ -11164,10 +11424,34 @@
1116411424
}
1116511425
1116611426
return JimSign(ret) * sort_info->order;
1116711427
}
1116811428
11429
+static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
11430
+{
11431
+ int src;
11432
+ int dst = 0;
11433
+ Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11434
+
11435
+ for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11436
+ if (comp(&ele[dst], &ele[src]) == 0) {
11437
+
11438
+ Jim_DecrRefCount(sort_info->interp, ele[dst]);
11439
+ }
11440
+ else {
11441
+
11442
+ dst++;
11443
+ }
11444
+ ele[dst] = ele[src];
11445
+ }
11446
+
11447
+ ele[++dst] = ele[src];
11448
+
11449
+
11450
+ listObjPtr->internalRep.listValue.len = dst;
11451
+}
11452
+
1116911453
1117011454
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
1117111455
{
1117211456
struct lsort_info *prev_info;
1117311457
@@ -11175,11 +11459,11 @@
1117511459
int (*fn) (Jim_Obj **, Jim_Obj **);
1117611460
Jim_Obj **vector;
1117711461
int len;
1117811462
int rc;
1117911463
11180
- JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11464
+ JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
1118111465
SetListFromAny(interp, listObjPtr);
1118211466
1118311467
1118411468
prev_info = sort_info;
1118511469
sort_info = info;
@@ -11194,10 +11478,13 @@
1119411478
fn = ListSortStringNoCase;
1119511479
break;
1119611480
case JIM_LSORT_INTEGER:
1119711481
fn = ListSortInteger;
1119811482
break;
11483
+ case JIM_LSORT_REAL:
11484
+ fn = ListSortReal;
11485
+ break;
1119911486
case JIM_LSORT_COMMAND:
1120011487
fn = ListSortCommand;
1120111488
break;
1120211489
default:
1120311490
fn = NULL;
@@ -11210,12 +11497,17 @@
1121011497
fn = ListSortIndexHelper;
1121111498
}
1121211499
1121311500
if ((rc = setjmp(info->jmpbuf)) == 0) {
1121411501
qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
11502
+
11503
+ if (info->unique && len > 1) {
11504
+ ListRemoveDuplicates(listObjPtr, fn);
11505
+ }
11506
+
11507
+ Jim_InvalidateStringRep(listObjPtr);
1121511508
}
11216
- Jim_InvalidateStringRep(listObjPtr);
1121711509
sort_info = prev_info;
1121811510
1121911511
return rc;
1122011512
}
1122111513
@@ -11225,14 +11517,22 @@
1122511517
int requiredLen = currentLen + elemc;
1122611518
int i;
1122711519
Jim_Obj **point;
1122811520
1122911521
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11230
- listPtr->internalRep.listValue.maxLen = requiredLen * 2;
11522
+ if (requiredLen < 2) {
11523
+
11524
+ requiredLen = 4;
11525
+ }
11526
+ else {
11527
+ requiredLen *= 2;
11528
+ }
1123111529
1123211530
listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11233
- sizeof(Jim_Obj *) * listPtr->internalRep.listValue.maxLen);
11531
+ sizeof(Jim_Obj *) * requiredLen);
11532
+
11533
+ listPtr->internalRep.listValue.maxLen = requiredLen;
1123411534
}
1123511535
if (idx < 0) {
1123611536
idx = currentLen;
1123711537
}
1123811538
point = listPtr->internalRep.listValue.ele + idx;
@@ -11332,11 +11632,11 @@
1133211632
listPtr->internalRep.listValue.ele[idx] = newObjPtr;
1133311633
Jim_IncrRefCount(newObjPtr);
1133411634
return JIM_OK;
1133511635
}
1133611636
11337
-int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11637
+int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
1133811638
Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
1133911639
{
1134011640
Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
1134111641
int shared, i, idx;
1134211642
@@ -11380,14 +11680,11 @@
1138011680
int i;
1138111681
int listLen = Jim_ListLength(interp, listObjPtr);
1138211682
Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
1138311683
1138411684
for (i = 0; i < listLen; ) {
11385
- Jim_Obj *objPtr;
11386
-
11387
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11388
- Jim_AppendObj(interp, resObjPtr, objPtr);
11685
+ Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
1138911686
if (++i != listLen) {
1139011687
Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
1139111688
}
1139211689
}
1139311690
return resObjPtr;
@@ -11413,43 +11710,42 @@
1141311710
int len = 0, objLen;
1141411711
char *bytes, *p;
1141511712
1141611713
1141711714
for (i = 0; i < objc; i++) {
11418
- Jim_GetString(objv[i], &objLen);
11419
- len += objLen;
11715
+ len += Jim_Length(objv[i]);
1142011716
}
1142111717
if (objc)
1142211718
len += objc - 1;
1142311719
1142411720
p = bytes = Jim_Alloc(len + 1);
1142511721
for (i = 0; i < objc; i++) {
1142611722
const char *s = Jim_GetString(objv[i], &objLen);
1142711723
1142811724
11429
- while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11725
+ while (objLen && isspace(UCHAR(*s))) {
1143011726
s++;
1143111727
objLen--;
1143211728
len--;
1143311729
}
1143411730
11435
- while (objLen && (s[objLen - 1] == ' ' ||
11436
- s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11731
+ while (objLen && isspace(UCHAR(s[objLen - 1]))) {
1143711732
1143811733
if (objLen > 1 && s[objLen - 2] == '\\') {
1143911734
break;
1144011735
}
1144111736
objLen--;
1144211737
len--;
1144311738
}
1144411739
memcpy(p, s, objLen);
1144511740
p += objLen;
11446
- if (objLen && i + 1 != objc) {
11447
- *p++ = ' ';
11448
- }
11449
- else if (i + 1 != objc) {
11450
- len--;
11741
+ if (i + 1 != objc) {
11742
+ if (objLen)
11743
+ *p++ = ' ';
11744
+ else {
11745
+ len--;
11746
+ }
1145111747
}
1145211748
}
1145311749
*p = '\0';
1145411750
return Jim_NewStringObjNoAlloc(interp, bytes, len);
1145511751
}
@@ -11489,20 +11785,26 @@
1148911785
1149011786
static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
1149111787
{
1149211788
return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
1149311789
}
11790
+
11791
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
11792
+{
11793
+ Jim_IncrRefCount((Jim_Obj *)val);
11794
+ return (void *)val;
11795
+}
1149411796
1149511797
static void JimObjectHTKeyValDestructor(void *interp, void *val)
1149611798
{
1149711799
Jim_DecrRefCount(interp, (Jim_Obj *)val);
1149811800
}
1149911801
1150011802
static const Jim_HashTableType JimDictHashTableType = {
1150111803
JimObjectHTHashFunction,
11502
- NULL,
11503
- NULL,
11804
+ JimObjectHTKeyValDup,
11805
+ JimObjectHTKeyValDup,
1150411806
JimObjectHTKeyCompare,
1150511807
JimObjectHTKeyValDestructor,
1150611808
JimObjectHTKeyValDestructor
1150711809
};
1150811810
@@ -11523,64 +11825,58 @@
1152311825
}
1152411826
1152511827
void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
1152611828
{
1152711829
Jim_HashTable *ht, *dupHt;
11528
- Jim_HashTableIterator *htiter;
11830
+ Jim_HashTableIterator htiter;
1152911831
Jim_HashEntry *he;
1153011832
1153111833
1153211834
ht = srcPtr->internalRep.ptr;
1153311835
dupHt = Jim_Alloc(sizeof(*dupHt));
1153411836
Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
1153511837
if (ht->size != 0)
1153611838
Jim_ExpandHashTable(dupHt, ht->size);
1153711839
11538
- htiter = Jim_GetHashTableIterator(ht);
11539
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11540
- const Jim_Obj *keyObjPtr = he->key;
11541
- Jim_Obj *valObjPtr = he->u.val;
11542
-
11543
- Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11544
- Jim_IncrRefCount(valObjPtr);
11545
- Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11546
- }
11547
- Jim_FreeHashTableIterator(htiter);
11840
+ JimInitHashTableIterator(ht, &htiter);
11841
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11842
+ Jim_AddHashEntry(dupHt, he->key, he->u.val);
11843
+ }
1154811844
1154911845
dupPtr->internalRep.ptr = dupHt;
1155011846
dupPtr->typePtr = &dictObjType;
1155111847
}
1155211848
1155311849
static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
1155411850
{
1155511851
Jim_HashTable *ht;
11556
- Jim_HashTableIterator *htiter;
11852
+ Jim_HashTableIterator htiter;
1155711853
Jim_HashEntry *he;
1155811854
Jim_Obj **objv;
1155911855
int i;
1156011856
1156111857
ht = dictPtr->internalRep.ptr;
1156211858
1156311859
1156411860
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11565
- htiter = Jim_GetHashTableIterator(ht);
11861
+ JimInitHashTableIterator(ht, &htiter);
1156611862
i = 0;
11567
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11568
- objv[i++] = (Jim_Obj *)he->key;
11569
- objv[i++] = he->u.val;
11863
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11864
+ objv[i++] = Jim_GetHashEntryKey(he);
11865
+ objv[i++] = Jim_GetHashEntryVal(he);
1157011866
}
1157111867
*len = i;
11572
- Jim_FreeHashTableIterator(htiter);
1157311868
return objv;
1157411869
}
1157511870
1157611871
static void UpdateStringOfDict(struct Jim_Obj *objPtr)
1157711872
{
1157811873
1157911874
int len;
1158011875
Jim_Obj **objv = JimDictPairs(objPtr, &len);
1158111876
11877
+
1158211878
JimMakeListStringRep(objPtr, objv, len);
1158311879
1158411880
Jim_Free(objv);
1158511881
}
1158611882
@@ -11590,11 +11886,13 @@
1159011886
1159111887
if (objPtr->typePtr == &dictObjType) {
1159211888
return JIM_OK;
1159311889
}
1159411890
11595
- Jim_String(objPtr);
11891
+ if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11892
+ Jim_String(objPtr);
11893
+ }
1159611894
1159711895
1159811896
listlen = Jim_ListLength(interp, objPtr);
1159911897
if (listlen % 2) {
1160011898
Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11607,28 +11905,14 @@
1160711905
1160811906
ht = Jim_Alloc(sizeof(*ht));
1160911907
Jim_InitHashTable(ht, &JimDictHashTableType, interp);
1161011908
1161111909
for (i = 0; i < listlen; i += 2) {
11612
- Jim_Obj *keyObjPtr;
11613
- Jim_Obj *valObjPtr;
11614
-
11615
- Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11616
- Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11617
-
11618
- Jim_IncrRefCount(keyObjPtr);
11619
- Jim_IncrRefCount(valObjPtr);
11620
-
11621
- if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11622
- Jim_HashEntry *he;
11623
-
11624
- he = Jim_FindHashEntry(ht, keyObjPtr);
11625
- Jim_DecrRefCount(interp, keyObjPtr);
11626
-
11627
- Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11628
- he->u.val = valObjPtr;
11629
- }
11910
+ Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
11911
+ Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
11912
+
11913
+ Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
1163011914
}
1163111915
1163211916
Jim_FreeIntRep(interp, objPtr);
1163311917
objPtr->typePtr = &dictObjType;
1163411918
objPtr->internalRep.ptr = ht;
@@ -11645,31 +11929,23 @@
1164511929
Jim_HashTable *ht = objPtr->internalRep.ptr;
1164611930
1164711931
if (valueObjPtr == NULL) {
1164811932
return Jim_DeleteHashEntry(ht, keyObjPtr);
1164911933
}
11650
- Jim_IncrRefCount(keyObjPtr);
11651
- Jim_IncrRefCount(valueObjPtr);
11652
- if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11653
-
11654
- Jim_DecrRefCount(interp, keyObjPtr);
11655
- }
11934
+ Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
1165611935
return JIM_OK;
1165711936
}
1165811937
1165911938
int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
1166011939
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
1166111940
{
11662
- int retcode;
11663
-
1166411941
JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
1166511942
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1166611943
return JIM_ERR;
1166711944
}
11668
- retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1166911945
Jim_InvalidateStringRep(objPtr);
11670
- return retcode;
11946
+ return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1167111947
}
1167211948
1167311949
Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
1167411950
{
1167511951
Jim_Obj *objPtr;
@@ -11796,10 +12072,11 @@
1179612072
}
1179712073
objPtr = Jim_NewDictObj(interp, NULL, 0);
1179812074
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
1179912075
}
1180012076
}
12077
+
1180112078
Jim_InvalidateStringRep(objPtr);
1180212079
Jim_InvalidateStringRep(varObjPtr);
1180312080
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
1180412081
goto err;
1180512082
}
@@ -11821,28 +12098,29 @@
1182112098
NULL,
1182212099
UpdateStringOfIndex,
1182312100
JIM_TYPE_NONE,
1182412101
};
1182512102
11826
-void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11827
-{
11828
- int len;
11829
- char buf[JIM_INTEGER_SPACE + 1];
11830
-
11831
- if (objPtr->internalRep.intValue >= 0)
11832
- len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11833
- else if (objPtr->internalRep.intValue == -1)
11834
- len = sprintf(buf, "end");
12103
+static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
12104
+{
12105
+ if (objPtr->internalRep.intValue == -1) {
12106
+ JimSetStringBytes(objPtr, "end");
12107
+ }
1183512108
else {
11836
- len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12109
+ char buf[JIM_INTEGER_SPACE + 1];
12110
+ if (objPtr->internalRep.intValue >= 0) {
12111
+ sprintf(buf, "%d", objPtr->internalRep.intValue);
12112
+ }
12113
+ else {
12114
+
12115
+ sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12116
+ }
12117
+ JimSetStringBytes(objPtr, buf);
1183712118
}
11838
- objPtr->bytes = Jim_Alloc(len + 1);
11839
- memcpy(objPtr->bytes, buf, len + 1);
11840
- objPtr->length = len;
1184112119
}
1184212120
11843
-int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12121
+static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1184412122
{
1184512123
int idx, end = 0;
1184612124
const char *str;
1184712125
char *endptr;
1184812126
@@ -11910,14 +12188,17 @@
1191012188
{
1191112189
1191212190
if (objPtr->typePtr == &intObjType) {
1191312191
jim_wide val = JimWideValue(objPtr);
1191412192
11915
- if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11916
- *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11917
- return JIM_OK;
11918
- }
12193
+ if (val < 0)
12194
+ *indexPtr = -INT_MAX;
12195
+ else if (val > INT_MAX)
12196
+ *indexPtr = INT_MAX;
12197
+ else
12198
+ *indexPtr = (int)val;
12199
+ return JIM_OK;
1191912200
}
1192012201
if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
1192112202
return JIM_ERR;
1192212203
*indexPtr = objPtr->internalRep.intValue;
1192312204
return JIM_OK;
@@ -11937,12 +12218,10 @@
1193712218
NULL
1193812219
};
1193912220
1194012221
#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
1194112222
11942
-static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11943
-
1194412223
static const Jim_ObjType returnCodeObjType = {
1194512224
"return-code",
1194612225
NULL,
1194712226
NULL,
1194812227
NULL,
@@ -11957,11 +12236,11 @@
1195712236
else {
1195812237
return jimReturnCodes[code];
1195912238
}
1196012239
}
1196112240
11962
-int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12241
+static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1196312242
{
1196412243
int returnCode;
1196512244
jim_wide wideValue;
1196612245
1196712246
@@ -12089,14 +12368,15 @@
1208912368
1209012369
1209112370
typedef struct Jim_ExprOperator
1209212371
{
1209312372
const char *name;
12094
- int precedence;
12095
- int arity;
1209612373
int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12097
- int lazy;
12374
+ unsigned char precedence;
12375
+ unsigned char arity;
12376
+ unsigned char lazy;
12377
+ unsigned char namelen;
1209812378
} Jim_ExprOperator;
1209912379
1210012380
static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
1210112381
{
1210212382
Jim_IncrRefCount(obj);
@@ -12108,24 +12388,21 @@
1210812388
return e->stack[--e->stacklen];
1210912389
}
1211012390
1211112391
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
1211212392
{
12113
- int intresult = 0;
12393
+ int intresult = 1;
1211412394
int rc = JIM_OK;
1211512395
Jim_Obj *A = ExprPop(e);
1211612396
double dA, dC = 0;
1211712397
jim_wide wA, wC = 0;
1211812398
1211912399
if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12120
- intresult = 1;
12121
-
1212212400
switch (e->opcode) {
1212312401
case JIM_EXPROP_FUNC_INT:
12124
- wC = wA;
12125
- break;
1212612402
case JIM_EXPROP_FUNC_ROUND:
12403
+ case JIM_EXPROP_UNARYPLUS:
1212712404
wC = wA;
1212812405
break;
1212912406
case JIM_EXPROP_FUNC_DOUBLE:
1213012407
dC = wA;
1213112408
intresult = 0;
@@ -12134,13 +12411,10 @@
1213412411
wC = wA >= 0 ? wA : -wA;
1213512412
break;
1213612413
case JIM_EXPROP_UNARYMINUS:
1213712414
wC = -wA;
1213812415
break;
12139
- case JIM_EXPROP_UNARYPLUS:
12140
- wC = wA;
12141
- break;
1214212416
case JIM_EXPROP_NOT:
1214312417
wC = !wA;
1214412418
break;
1214512419
default:
1214612420
abort();
@@ -12148,31 +12422,29 @@
1214812422
}
1214912423
else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
1215012424
switch (e->opcode) {
1215112425
case JIM_EXPROP_FUNC_INT:
1215212426
wC = dA;
12153
- intresult = 1;
1215412427
break;
1215512428
case JIM_EXPROP_FUNC_ROUND:
1215612429
wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12157
- intresult = 1;
1215812430
break;
1215912431
case JIM_EXPROP_FUNC_DOUBLE:
12432
+ case JIM_EXPROP_UNARYPLUS:
1216012433
dC = dA;
12434
+ intresult = 0;
1216112435
break;
1216212436
case JIM_EXPROP_FUNC_ABS:
1216312437
dC = dA >= 0 ? dA : -dA;
12438
+ intresult = 0;
1216412439
break;
1216512440
case JIM_EXPROP_UNARYMINUS:
1216612441
dC = -dA;
12167
- break;
12168
- case JIM_EXPROP_UNARYPLUS:
12169
- dC = dA;
12442
+ intresult = 0;
1217012443
break;
1217112444
case JIM_EXPROP_NOT:
1217212445
wC = !dA;
12173
- intresult = 1;
1217412446
break;
1217512447
default:
1217612448
abort();
1217712449
}
1217812450
}
@@ -12383,11 +12655,11 @@
1238312655
1238412656
1238512657
1238612658
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
1238712659
{
12388
- int intresult = 0;
12660
+ int intresult = 1;
1238912661
int rc = JIM_OK;
1239012662
double dA, dB, dC = 0;
1239112663
jim_wide wA, wB, wC = 0;
1239212664
1239312665
Jim_Obj *B = ExprPop(e);
@@ -12397,12 +12669,10 @@
1239712669
(B->typePtr != &doubleObjType || B->bytes) &&
1239812670
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
1239912671
1240012672
1240112673
12402
- intresult = 1;
12403
-
1240412674
switch (e->opcode) {
1240512675
case JIM_EXPROP_POW:
1240612676
case JIM_EXPROP_FUNC_POW:
1240712677
wC = JimPowWide(wA, wB);
1240812678
break;
@@ -12452,10 +12722,11 @@
1245212722
default:
1245312723
abort();
1245412724
}
1245512725
}
1245612726
else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12727
+ intresult = 0;
1245712728
switch (e->opcode) {
1245812729
case JIM_EXPROP_POW:
1245912730
case JIM_EXPROP_FUNC_POW:
1246012731
#ifdef JIM_MATH_FUNCTIONS
1246112732
dC = pow(dA, dB);
@@ -12517,12 +12788,10 @@
1251712788
1251812789
1251912790
1252012791
int i = Jim_StringCompareObj(interp, A, B, 0);
1252112792
12522
- intresult = 1;
12523
-
1252412793
switch (e->opcode) {
1252512794
case JIM_EXPROP_LT:
1252612795
wC = i < 0;
1252712796
break;
1252812797
case JIM_EXPROP_GT:
@@ -12566,15 +12835,11 @@
1256612835
int listlen;
1256712836
int i;
1256812837
1256912838
listlen = Jim_ListLength(interp, listObjPtr);
1257012839
for (i = 0; i < listlen; i++) {
12571
- Jim_Obj *objPtr;
12572
-
12573
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12574
-
12575
- if (Jim_StringEqObj(objPtr, valObj)) {
12840
+ if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
1257612841
return 1;
1257712842
}
1257812843
}
1257912844
return 0;
1258012845
}
@@ -12586,23 +12851,16 @@
1258612851
1258712852
jim_wide wC;
1258812853
1258912854
switch (e->opcode) {
1259012855
case JIM_EXPROP_STREQ:
12591
- case JIM_EXPROP_STRNE: {
12592
- int Alen, Blen;
12593
- const char *sA = Jim_GetString(A, &Alen);
12594
- const char *sB = Jim_GetString(B, &Blen);
12595
-
12596
- if (e->opcode == JIM_EXPROP_STREQ) {
12597
- wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12598
- }
12599
- else {
12600
- wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
12856
+ case JIM_EXPROP_STRNE:
12857
+ wC = Jim_StringEqObj(A, B);
12858
+ if (e->opcode == JIM_EXPROP_STRNE) {
12859
+ wC = !wC;
1260112860
}
1260212861
break;
12603
- }
1260412862
case JIM_EXPROP_STRIN:
1260512863
wC = JimSearchList(interp, B, A);
1260612864
break;
1260712865
case JIM_EXPROP_STRNI:
1260812866
wC = !JimSearchList(interp, B, A);
@@ -12774,93 +13032,98 @@
1277413032
LAZY_OP,
1277513033
LAZY_LEFT,
1277613034
LAZY_RIGHT
1277713035
};
1277813036
13037
+#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13038
+#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13039
+
1277913040
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12780
- {"*", 200, 2, JimExprOpBin, LAZY_NONE},
12781
- {"/", 200, 2, JimExprOpBin, LAZY_NONE},
12782
- {"%", 200, 2, JimExprOpIntBin, LAZY_NONE},
12783
-
12784
- {"-", 100, 2, JimExprOpBin, LAZY_NONE},
12785
- {"+", 100, 2, JimExprOpBin, LAZY_NONE},
12786
-
12787
- {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12788
- {">>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12789
-
12790
- {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12791
- {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12792
-
12793
- {"<", 80, 2, JimExprOpBin, LAZY_NONE},
12794
- {">", 80, 2, JimExprOpBin, LAZY_NONE},
12795
- {"<=", 80, 2, JimExprOpBin, LAZY_NONE},
12796
- {">=", 80, 2, JimExprOpBin, LAZY_NONE},
12797
-
12798
- {"==", 70, 2, JimExprOpBin, LAZY_NONE},
12799
- {"!=", 70, 2, JimExprOpBin, LAZY_NONE},
12800
-
12801
- {"&", 50, 2, JimExprOpIntBin, LAZY_NONE},
12802
- {"^", 49, 2, JimExprOpIntBin, LAZY_NONE},
12803
- {"|", 48, 2, JimExprOpIntBin, LAZY_NONE},
12804
-
12805
- {"&&", 10, 2, NULL, LAZY_OP},
12806
- {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT},
12807
- {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12808
-
12809
- {"||", 9, 2, NULL, LAZY_OP},
12810
- {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT},
12811
- {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12812
-
12813
- {"?", 5, 2, JimExprOpNull, LAZY_OP},
12814
- {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
12815
- {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12816
-
12817
- {":", 5, 2, JimExprOpNull, LAZY_OP},
12818
- {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
12819
- {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12820
-
12821
- {"**", 250, 2, JimExprOpBin, LAZY_NONE},
12822
-
12823
- {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE},
12824
- {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE},
12825
-
12826
- {"in", 55, 2, JimExprOpStrBin, LAZY_NONE},
12827
- {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE},
12828
-
12829
- {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE},
12830
- {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE},
12831
- {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12832
- {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12833
-
12834
-
12835
-
12836
- {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12837
- {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12838
- {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12839
- {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12840
- {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
12841
- {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
13041
+ OPRINIT("*", 110, 2, JimExprOpBin),
13042
+ OPRINIT("/", 110, 2, JimExprOpBin),
13043
+ OPRINIT("%", 110, 2, JimExprOpIntBin),
13044
+
13045
+ OPRINIT("-", 100, 2, JimExprOpBin),
13046
+ OPRINIT("+", 100, 2, JimExprOpBin),
13047
+
13048
+ OPRINIT("<<", 90, 2, JimExprOpIntBin),
13049
+ OPRINIT(">>", 90, 2, JimExprOpIntBin),
13050
+
13051
+ OPRINIT("<<<", 90, 2, JimExprOpIntBin),
13052
+ OPRINIT(">>>", 90, 2, JimExprOpIntBin),
13053
+
13054
+ OPRINIT("<", 80, 2, JimExprOpBin),
13055
+ OPRINIT(">", 80, 2, JimExprOpBin),
13056
+ OPRINIT("<=", 80, 2, JimExprOpBin),
13057
+ OPRINIT(">=", 80, 2, JimExprOpBin),
13058
+
13059
+ OPRINIT("==", 70, 2, JimExprOpBin),
13060
+ OPRINIT("!=", 70, 2, JimExprOpBin),
13061
+
13062
+ OPRINIT("&", 50, 2, JimExprOpIntBin),
13063
+ OPRINIT("^", 49, 2, JimExprOpIntBin),
13064
+ OPRINIT("|", 48, 2, JimExprOpIntBin),
13065
+
13066
+ OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13067
+ OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13068
+ OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13069
+
13070
+ OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13071
+ OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13072
+ OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13073
+
13074
+ OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13075
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13076
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13077
+
13078
+ OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13079
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13080
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13081
+
13082
+ OPRINIT("**", 250, 2, JimExprOpBin),
13083
+
13084
+ OPRINIT("eq", 60, 2, JimExprOpStrBin),
13085
+ OPRINIT("ne", 60, 2, JimExprOpStrBin),
13086
+
13087
+ OPRINIT("in", 55, 2, JimExprOpStrBin),
13088
+ OPRINIT("ni", 55, 2, JimExprOpStrBin),
13089
+
13090
+ OPRINIT("!", 150, 1, JimExprOpNumUnary),
13091
+ OPRINIT("~", 150, 1, JimExprOpIntUnary),
13092
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13093
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13094
+
13095
+
13096
+
13097
+ OPRINIT("int", 200, 1, JimExprOpNumUnary),
13098
+ OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13099
+ OPRINIT("double", 200, 1, JimExprOpNumUnary),
13100
+ OPRINIT("round", 200, 1, JimExprOpNumUnary),
13101
+ OPRINIT("rand", 200, 0, JimExprOpNone),
13102
+ OPRINIT("srand", 200, 1, JimExprOpIntUnary),
1284213103
1284313104
#ifdef JIM_MATH_FUNCTIONS
12844
- {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12845
- {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12846
- {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12847
- {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12848
- {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12849
- {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12850
- {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12851
- {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12852
- {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12853
- {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12854
- {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12855
- {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12856
- {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12857
- {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12858
- {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12859
- {"pow", 400, 2, JimExprOpBin, LAZY_NONE},
13105
+ OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13106
+ OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13107
+ OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13108
+ OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13109
+ OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13110
+ OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13111
+ OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13112
+ OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13113
+ OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13114
+ OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13115
+ OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13116
+ OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13117
+ OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13118
+ OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13119
+ OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13120
+ OPRINIT("pow", 200, 2, JimExprOpBin),
1286013121
#endif
1286113122
};
13123
+#undef OPRINIT
13124
+#undef OPRINIT_LAZY
1286213125
1286313126
#define JIM_EXPR_OPERATORS_NUM \
1286413127
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1286513128
1286613129
static int JimParseExpression(struct JimParserCtx *pc)
@@ -12872,13 +13135,16 @@
1287213135
}
1287313136
pc->p++;
1287413137
pc->len--;
1287513138
}
1287613139
13140
+
13141
+ pc->tline = pc->linenr;
13142
+ pc->tstart = pc->p;
13143
+
1287713144
if (pc->len == 0) {
12878
- pc->tstart = pc->tend = pc->p;
12879
- pc->tline = pc->linenr;
13145
+ pc->tend = pc->p;
1288013146
pc->tt = JIM_TT_EOL;
1288113147
pc->eof = 1;
1288213148
return JIM_OK;
1288313149
}
1288413150
switch (*(pc->p)) {
@@ -12889,12 +13155,11 @@
1288913155
pc->tt = JIM_TT_SUBEXPR_END;
1289013156
goto singlechar;
1289113157
case ',':
1289213158
pc->tt = JIM_TT_SUBEXPR_COMMA;
1289313159
singlechar:
12894
- pc->tstart = pc->tend = pc->p;
12895
- pc->tline = pc->linenr;
13160
+ pc->tend = pc->p;
1289613161
pc->p++;
1289713162
pc->len--;
1289813163
break;
1289913164
case '[':
1290013165
return JimParseCmd(pc);
@@ -12940,82 +13205,44 @@
1294013205
return JIM_OK;
1294113206
}
1294213207
1294313208
static int JimParseExprNumber(struct JimParserCtx *pc)
1294413209
{
12945
- int allowdot = 1;
12946
- int base = 10;
13210
+ char *end;
1294713211
1294813212
1294913213
pc->tt = JIM_TT_EXPR_INT;
12950
- pc->tstart = pc->p;
12951
- pc->tline = pc->linenr;
12952
-
12953
-
12954
- if (pc->p[0] == '0') {
12955
- switch (pc->p[1]) {
12956
- case 'x':
12957
- case 'X':
12958
- base = 16;
12959
- allowdot = 0;
12960
- pc->p += 2;
12961
- pc->len -= 2;
12962
- break;
12963
- case 'o':
12964
- case 'O':
12965
- base = 8;
12966
- allowdot = 0;
12967
- pc->p += 2;
12968
- pc->len -= 2;
12969
- break;
12970
- case 'b':
12971
- case 'B':
12972
- base = 2;
12973
- allowdot = 0;
12974
- pc->p += 2;
12975
- pc->len -= 2;
12976
- break;
12977
- }
12978
- }
12979
-
12980
- while (isdigit(UCHAR(*pc->p))
12981
- || (base == 16 && isxdigit(UCHAR(*pc->p)))
12982
- || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
12983
- || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
12984
- || (allowdot && *pc->p == '.')
12985
- ) {
12986
- if (*pc->p == '.') {
12987
- allowdot = 0;
12988
- pc->tt = JIM_TT_EXPR_DOUBLE;
12989
- }
12990
- pc->p++;
12991
- pc->len--;
12992
- if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
12993
- || isdigit(UCHAR(pc->p[1])))) {
12994
- pc->p += 2;
12995
- pc->len -= 2;
12996
- pc->tt = JIM_TT_EXPR_DOUBLE;
13214
+
13215
+ jim_strtoull(pc->p, (char **)&pc->p);
13216
+
13217
+ if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13218
+ if (strtod(pc->tstart, &end)) { }
13219
+ if (end == pc->tstart)
13220
+ return JIM_ERR;
13221
+ if (end > pc->p) {
13222
+
13223
+ pc->tt = JIM_TT_EXPR_DOUBLE;
13224
+ pc->p = end;
1299713225
}
1299813226
}
1299913227
pc->tend = pc->p - 1;
13228
+ pc->len -= (pc->p - pc->tstart);
1300013229
return JIM_OK;
1300113230
}
1300213231
1300313232
static int JimParseExprIrrational(struct JimParserCtx *pc)
1300413233
{
13005
- const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13006
- const char **token;
13007
-
13008
- for (token = Tokens; *token != NULL; token++) {
13009
- int len = strlen(*token);
13010
-
13011
- if (strncmp(*token, pc->p, len) == 0) {
13012
- pc->tstart = pc->p;
13013
- pc->tend = pc->p + len - 1;
13014
- pc->p += len;
13015
- pc->len -= len;
13016
- pc->tline = pc->linenr;
13234
+ const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13235
+ int i;
13236
+
13237
+ for (i = 0; irrationals[i]; i++) {
13238
+ const char *irr = irrationals[i];
13239
+
13240
+ if (strncmp(irr, pc->p, 3) == 0) {
13241
+ pc->p += 3;
13242
+ pc->len -= 3;
13243
+ pc->tend = pc->p - 1;
1301713244
pc->tt = JIM_TT_EXPR_DOUBLE;
1301813245
return JIM_OK;
1301913246
}
1302013247
}
1302113248
return JIM_ERR;
@@ -13026,20 +13253,18 @@
1302613253
int i;
1302713254
int bestIdx = -1, bestLen = 0;
1302813255
1302913256
1303013257
for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13031
- const char *opname;
13032
- int oplen;
13258
+ const char * const opname = Jim_ExprOperators[i].name;
13259
+ const int oplen = Jim_ExprOperators[i].namelen;
1303313260
13034
- opname = Jim_ExprOperators[i].name;
13035
- if (opname == NULL) {
13261
+ if (opname == NULL || opname[0] != pc->p[0]) {
1303613262
continue;
1303713263
}
13038
- oplen = strlen(opname);
1303913264
13040
- if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) {
13265
+ if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
1304113266
bestIdx = i + JIM_TT_EXPR_OP;
1304213267
bestLen = oplen;
1304313268
}
1304413269
}
1304513270
if (bestIdx == -1) {
@@ -13057,15 +13282,13 @@
1305713282
}
1305813283
if (*p != '(') {
1305913284
return JIM_ERR;
1306013285
}
1306113286
}
13062
- pc->tstart = pc->p;
1306313287
pc->tend = pc->p + bestLen - 1;
1306413288
pc->p += bestLen;
1306513289
pc->len -= bestLen;
13066
- pc->tline = pc->linenr;
1306713290
1306813291
pc->tt = bestIdx;
1306913292
return JIM_OK;
1307013293
}
1307113294
@@ -13111,12 +13334,12 @@
1311113334
};
1311213335
1311313336
1311413337
typedef struct ExprByteCode
1311513338
{
13116
- int len;
1311713339
ScriptToken *token;
13340
+ int len;
1311813341
int inUse;
1311913342
} ExprByteCode;
1312013343
1312113344
static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
1312213345
{
@@ -13563,17 +13786,23 @@
1356313786
}
1356413787
1356513788
#ifdef DEBUG_SHOW_EXPR_TOKENS
1356613789
{
1356713790
int i;
13568
- printf("==== Expr Tokens ====\n");
13791
+ printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
1356913792
for (i = 0; i < tokenlist.count; i++) {
1357013793
printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
1357113794
tokenlist.list[i].len, tokenlist.list[i].token);
1357213795
}
1357313796
}
1357413797
#endif
13798
+
13799
+ if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
13800
+ ScriptTokenListFree(&tokenlist);
13801
+ Jim_DecrRefCount(interp, fileNameObj);
13802
+ return JIM_ERR;
13803
+ }
1357513804
1357613805
1357713806
expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
1357813807
1357913808
@@ -13620,10 +13849,24 @@
1362013849
return NULL;
1362113850
}
1362213851
}
1362313852
return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
1362413853
}
13854
+
13855
+#ifdef JIM_OPTIMIZATION
13856
+static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
13857
+{
13858
+ if (token->type == JIM_TT_EXPR_INT)
13859
+ return token->objPtr;
13860
+ else if (token->type == JIM_TT_VAR)
13861
+ return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
13862
+ else if (token->type == JIM_TT_DICTSUGAR)
13863
+ return JimExpandDictSugar(interp, token->objPtr);
13864
+ else
13865
+ return NULL;
13866
+}
13867
+#endif
1362513868
1362613869
#define JIM_EE_STATICSTACK_LEN 10
1362713870
1362813871
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
1362913872
{
@@ -13643,102 +13886,69 @@
1364313886
Jim_Obj *objPtr;
1364413887
1364513888
1364613889
switch (expr->len) {
1364713890
case 1:
13648
- if (expr->token[0].type == JIM_TT_EXPR_INT) {
13649
- *exprResultPtrPtr = expr->token[0].objPtr;
13650
- Jim_IncrRefCount(*exprResultPtrPtr);
13651
- return JIM_OK;
13652
- }
13653
- if (expr->token[0].type == JIM_TT_VAR) {
13654
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13655
- if (objPtr) {
13656
- *exprResultPtrPtr = objPtr;
13657
- Jim_IncrRefCount(*exprResultPtrPtr);
13658
- return JIM_OK;
13659
- }
13891
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13892
+ if (objPtr) {
13893
+ Jim_IncrRefCount(objPtr);
13894
+ *exprResultPtrPtr = objPtr;
13895
+ return JIM_OK;
1366013896
}
1366113897
break;
1366213898
1366313899
case 2:
13664
- if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13665
- jim_wide wideValue;
13900
+ if (expr->token[1].type == JIM_EXPROP_NOT) {
13901
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
1366613902
13667
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13668
- if (objPtr && JimIsWide(objPtr)
13669
- && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13670
- *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13903
+ if (objPtr && JimIsWide(objPtr)) {
13904
+ *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
1367113905
Jim_IncrRefCount(*exprResultPtrPtr);
1367213906
return JIM_OK;
1367313907
}
1367413908
}
1367513909
break;
1367613910
1367713911
case 3:
13678
- if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13679
- || expr->token[1].type == JIM_TT_VAR)) {
13680
- switch (expr->token[2].type) {
13681
- case JIM_EXPROP_LT:
13682
- case JIM_EXPROP_LTE:
13683
- case JIM_EXPROP_GT:
13684
- case JIM_EXPROP_GTE:
13685
- case JIM_EXPROP_NUMEQ:
13686
- case JIM_EXPROP_NUMNE:{
13687
-
13688
- jim_wide wideValueA;
13689
- jim_wide wideValueB;
13690
-
13691
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13692
- if (objPtr && JimIsWide(objPtr)
13693
- && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13694
- if (expr->token[1].type == JIM_TT_VAR) {
13695
- objPtr =
13696
- Jim_GetVariable(interp, expr->token[1].objPtr,
13697
- JIM_NONE);
13698
- }
13699
- else {
13700
- objPtr = expr->token[1].objPtr;
13701
- }
13702
- if (objPtr && JimIsWide(objPtr)
13703
- && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13704
- int cmpRes;
13705
-
13706
- switch (expr->token[2].type) {
13707
- case JIM_EXPROP_LT:
13708
- cmpRes = wideValueA < wideValueB;
13709
- break;
13710
- case JIM_EXPROP_LTE:
13711
- cmpRes = wideValueA <= wideValueB;
13712
- break;
13713
- case JIM_EXPROP_GT:
13714
- cmpRes = wideValueA > wideValueB;
13715
- break;
13716
- case JIM_EXPROP_GTE:
13717
- cmpRes = wideValueA >= wideValueB;
13718
- break;
13719
- case JIM_EXPROP_NUMEQ:
13720
- cmpRes = wideValueA == wideValueB;
13721
- break;
13722
- case JIM_EXPROP_NUMNE:
13723
- cmpRes = wideValueA != wideValueB;
13724
- break;
13725
- default:
13726
- cmpRes = 0;
13727
- }
13728
- *exprResultPtrPtr =
13729
- cmpRes ? interp->trueObj : interp->falseObj;
13730
- Jim_IncrRefCount(*exprResultPtrPtr);
13731
- return JIM_OK;
13732
- }
13733
- }
13734
- }
13735
- }
13736
- }
13737
- break;
13738
- }
13739
- }
13912
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13913
+ if (objPtr && JimIsWide(objPtr)) {
13914
+ Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
13915
+ if (objPtr2 && JimIsWide(objPtr2)) {
13916
+ jim_wide wideValueA = JimWideValue(objPtr);
13917
+ jim_wide wideValueB = JimWideValue(objPtr2);
13918
+ int cmpRes;
13919
+ switch (expr->token[2].type) {
13920
+ case JIM_EXPROP_LT:
13921
+ cmpRes = wideValueA < wideValueB;
13922
+ break;
13923
+ case JIM_EXPROP_LTE:
13924
+ cmpRes = wideValueA <= wideValueB;
13925
+ break;
13926
+ case JIM_EXPROP_GT:
13927
+ cmpRes = wideValueA > wideValueB;
13928
+ break;
13929
+ case JIM_EXPROP_GTE:
13930
+ cmpRes = wideValueA >= wideValueB;
13931
+ break;
13932
+ case JIM_EXPROP_NUMEQ:
13933
+ cmpRes = wideValueA == wideValueB;
13934
+ break;
13935
+ case JIM_EXPROP_NUMNE:
13936
+ cmpRes = wideValueA != wideValueB;
13937
+ break;
13938
+ default:
13939
+ goto noopt;
13940
+ }
13941
+ *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
13942
+ Jim_IncrRefCount(*exprResultPtrPtr);
13943
+ return JIM_OK;
13944
+ }
13945
+ }
13946
+ break;
13947
+ }
13948
+ }
13949
+noopt:
1374013950
#endif
1374113951
1374213952
expr->inUse++;
1374313953
1374413954
@@ -13855,16 +14065,16 @@
1385514065
1385614066
1385714067
1385814068
typedef struct ScanFmtPartDescr
1385914069
{
13860
- char type;
13861
- char modifier;
14070
+ char *arg;
14071
+ char *prefix;
1386214072
size_t width;
1386314073
int pos;
13864
- char *arg;
13865
- char *prefix;
14074
+ char type;
14075
+ char modifier;
1386614076
} ScanFmtPartDescr;
1386714077
1386814078
1386914079
typedef struct ScanFmtStringObj
1387014080
{
@@ -13907,16 +14117,13 @@
1390714117
memcpy(newVec, srcPtr->internalRep.ptr, size);
1390814118
dupPtr->internalRep.ptr = newVec;
1390914119
dupPtr->typePtr = &scanFmtStringObjType;
1391014120
}
1391114121
13912
-void UpdateStringOfScanFmt(Jim_Obj *objPtr)
14122
+static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
1391314123
{
13914
- char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13915
-
13916
- objPtr->bytes = Jim_StrDup(bytes);
13917
- objPtr->length = strlen(bytes);
14124
+ JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
1391814125
}
1391914126
1392014127
1392114128
static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1392214129
{
@@ -14126,11 +14333,10 @@
1412614333
Jim_Obj *tmpObj = NULL;
1412714334
1412814335
1412914336
*valObjPtr = 0;
1413014337
if (descr->prefix) {
14131
-
1413214338
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
1413314339
1413414340
if (isspace(UCHAR(descr->prefix[i])))
1413514341
while (pos < strLen && isspace(UCHAR(str[pos])))
1413614342
++pos;
@@ -14467,34 +14673,55 @@
1446714673
}
1446814674
1446914675
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1447014676
{
1447114677
int retcode;
14472
- Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14678
+ Jim_Cmd *cmdPtr;
1447314679
14474
- if (cmdPtr == NULL) {
14475
- return JimUnknown(interp, objc, objv);
14680
+#if 0
14681
+ printf("invoke");
14682
+ int j;
14683
+ for (j = 0; j < objc; j++) {
14684
+ printf(" '%s'", Jim_String(objv[j]));
1447614685
}
14686
+ printf("\n");
14687
+#endif
14688
+
14689
+ if (interp->framePtr->tailcallCmd) {
14690
+
14691
+ cmdPtr = interp->framePtr->tailcallCmd;
14692
+ interp->framePtr->tailcallCmd = NULL;
14693
+ }
14694
+ else {
14695
+ cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14696
+ if (cmdPtr == NULL) {
14697
+ return JimUnknown(interp, objc, objv);
14698
+ }
14699
+ JimIncrCmdRefCount(cmdPtr);
14700
+ }
14701
+
1447714702
if (interp->evalDepth == interp->maxEvalDepth) {
1447814703
Jim_SetResultString(interp, "Infinite eval recursion", -1);
14479
- return JIM_ERR;
14704
+ retcode = JIM_ERR;
14705
+ goto out;
1448014706
}
1448114707
interp->evalDepth++;
1448214708
1448314709
14484
- JimIncrCmdRefCount(cmdPtr);
1448514710
Jim_SetEmptyResult(interp);
1448614711
if (cmdPtr->isproc) {
1448714712
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
1448814713
}
1448914714
else {
1449014715
interp->cmdPrivData = cmdPtr->u.native.privData;
1449114716
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
1449214717
}
14493
- JimDecrCmdRefCount(interp, cmdPtr);
1449414718
interp->evalDepth--;
1449514719
14720
+out:
14721
+ JimDecrCmdRefCount(interp, cmdPtr);
14722
+
1449614723
return retcode;
1449714724
}
1449814725
1449914726
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1450014727
{
@@ -14672,10 +14899,15 @@
1467214899
objPtr->typePtr = &interpolatedObjType;
1467314900
objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
1467414901
objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
1467514902
Jim_IncrRefCount(intv[2]);
1467614903
}
14904
+ else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
14905
+
14906
+ JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
14907
+ }
14908
+
1467714909
1467814910
s = objPtr->bytes = Jim_Alloc(totlen + 1);
1467914911
objPtr->length = totlen;
1468014912
for (i = 0; i < tokens; i++) {
1468114913
if (intv[i]) {
@@ -14727,10 +14959,14 @@
1472714959
return JimEvalObjList(interp, scriptObjPtr);
1472814960
}
1472914961
1473014962
Jim_IncrRefCount(scriptObjPtr);
1473114963
script = Jim_GetScript(interp, scriptObjPtr);
14964
+ if (script == NULL) {
14965
+ Jim_DecrRefCount(interp, scriptObjPtr);
14966
+ return JIM_ERR;
14967
+ }
1473214968
1473314969
Jim_SetEmptyResult(interp);
1473414970
1473514971
token = script->token;
1473614972
@@ -14871,12 +15107,12 @@
1487115107
}
1487215108
1487315109
if (retcode == JIM_OK && argc) {
1487415110
1487515111
retcode = JimInvokeCommand(interp, argc, argv);
14876
- if (interp->signal_level && interp->sigmask) {
14877
-
15112
+
15113
+ if (Jim_CheckSignal(interp)) {
1487815114
retcode = JIM_SIGNAL;
1487915115
}
1488015116
}
1488115117
1488215118
@@ -15001,26 +15237,20 @@
1500115237
retcode = Jim_EvalObj(interp, scriptObj);
1500215238
}
1500315239
1500415240
1500515241
interp->framePtr = interp->framePtr->parent;
15006
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15007
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15008
- }
15009
- else {
15010
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15011
- }
15242
+ JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1501215243
1501315244
return retcode;
1501415245
}
1501515246
#endif
1501615247
1501715248
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
1501815249
{
1501915250
Jim_CallFrame *callFramePtr;
1502015251
int i, d, retcode, optargs;
15021
- Jim_Stack *localCommands;
1502215252
ScriptObj *script;
1502315253
1502415254
1502515255
if (argc - 1 < cmd->u.proc.reqArity ||
1502615256
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15100,37 +15330,42 @@
1510015330
1510115331
1510215332
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
1510315333
1510415334
badargset:
15335
+
1510515336
15106
-
15107
- localCommands = callFramePtr->localCommands;
15108
- callFramePtr->localCommands = NULL;
15109
-
1511015337
interp->framePtr = interp->framePtr->parent;
15111
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15112
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15113
- }
15114
- else {
15115
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15116
- }
15117
-
15118
-
15119
- while (retcode == JIM_EVAL) {
15120
- Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15121
-
15122
- Jim_IncrRefCount(resultScriptObjPtr);
15123
-
15124
- JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15125
-
15126
- retcode = JimEvalObjList(interp, resultScriptObjPtr);
15127
- if (retcode == JIM_RETURN) {
15128
- interp->returnLevel++;
15129
- }
15130
- Jim_DecrRefCount(interp, resultScriptObjPtr);
15131
- }
15338
+ JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15339
+
15340
+ if (interp->framePtr->tailcallObj) {
15341
+
15342
+ if (interp->framePtr->tailcall++ == 0) {
15343
+
15344
+ do {
15345
+ Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15346
+
15347
+ interp->framePtr->tailcallObj = NULL;
15348
+
15349
+ if (retcode == JIM_EVAL) {
15350
+ retcode = Jim_EvalObjList(interp, tailcallObj);
15351
+ if (retcode == JIM_RETURN) {
15352
+ interp->returnLevel++;
15353
+ }
15354
+ }
15355
+ Jim_DecrRefCount(interp, tailcallObj);
15356
+ } while (interp->framePtr->tailcallObj);
15357
+
15358
+
15359
+ if (interp->framePtr->tailcallCmd) {
15360
+ JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15361
+ interp->framePtr->tailcallCmd = NULL;
15362
+ }
15363
+ }
15364
+ interp->framePtr->tailcall--;
15365
+ }
15366
+
1513215367
1513315368
if (retcode == JIM_RETURN) {
1513415369
if (--interp->returnLevel <= 0) {
1513515370
retcode = interp->returnCode;
1513615371
interp->returnCode = JIM_OK;
@@ -15142,13 +15377,10 @@
1514215377
Jim_DecrRefCount(interp, interp->errorProc);
1514315378
interp->errorProc = argv[0];
1514415379
Jim_IncrRefCount(interp->errorProc);
1514515380
}
1514615381
15147
-
15148
- JimDeleteLocalProcs(interp, localCommands);
15149
-
1515015382
return retcode;
1515115383
}
1515215384
1515315385
int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
1515415386
{
@@ -15216,11 +15448,10 @@
1521615448
Jim_Obj *scriptObjPtr;
1521715449
Jim_Obj *prevScriptObj;
1521815450
struct stat sb;
1521915451
int retcode;
1522015452
int readlen;
15221
- struct JimParseResult result;
1522215453
1522315454
if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
1522415455
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
1522515456
return JIM_ERR;
1522615457
}
@@ -15243,31 +15474,13 @@
1524315474
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
1524415475
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
1524515476
Jim_IncrRefCount(scriptObjPtr);
1524615477
1524715478
15248
- if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15249
- const char *msg;
15250
- char linebuf[20];
15251
-
15252
- switch (result.missing) {
15253
- case '[':
15254
- msg = "unmatched \"[\"";
15255
- break;
15256
- case '{':
15257
- msg = "missing close-brace";
15258
- break;
15259
- case '"':
15260
- default:
15261
- msg = "missing quote";
15262
- break;
15263
- }
15264
-
15265
- snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15266
-
15267
- Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15268
- msg, filename, linebuf);
15479
+ if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
15480
+
15481
+ JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
1526915482
Jim_DecrRefCount(interp, scriptObjPtr);
1527015483
return JIM_ERR;
1527115484
}
1527215485
1527315486
prevScriptObj = interp->currentScriptObj;
@@ -15430,11 +15643,11 @@
1543015643
}
1543115644
1543215645
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
1543315646
Jim_HashEntry *he, int type);
1543415647
15435
-#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15648
+#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
1543615649
1543715650
static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1543815651
JimHashtableIteratorCallbackType *callback, int type)
1543915652
{
1544015653
Jim_HashEntry *he;
@@ -15446,17 +15659,17 @@
1544615659
if (he) {
1544715660
callback(interp, listObjPtr, he, type);
1544815661
}
1544915662
}
1545015663
else {
15451
- Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
15452
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
15664
+ Jim_HashTableIterator htiter;
15665
+ JimInitHashTableIterator(ht, &htiter);
15666
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1545315667
if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
1545415668
callback(interp, listObjPtr, he, type);
1545515669
}
1545615670
}
15457
- Jim_FreeHashTableIterator(htiter);
1545815671
}
1545915672
return listObjPtr;
1546015673
}
1546115674
1546215675
@@ -15465,11 +15678,11 @@
1546515678
#define JIM_CMDLIST_CHANNELS 2
1546615679
1546715680
static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1546815681
Jim_HashEntry *he, int type)
1546915682
{
15470
- Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15683
+ Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
1547115684
Jim_Obj *objPtr;
1547215685
1547315686
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
1547415687
1547515688
return;
@@ -15498,11 +15711,11 @@
1549815711
#define JIM_VARLIST_VALUES 0x1000
1549915712
1550015713
static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1550115714
Jim_HashEntry *he, int type)
1550215715
{
15503
- Jim_Var *varPtr = (Jim_Var *)he->u.val;
15716
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
1550415717
1550515718
if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
1550615719
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
1550715720
if (type & JIM_VARLIST_VALUES) {
1550815721
Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15820,11 +16033,11 @@
1582016033
1582116034
expr = JimGetExpression(interp, argv[2]);
1582216035
incrScript = Jim_GetScript(interp, argv[3]);
1582316036
1582416037
15825
- if (incrScript->len != 3 || !expr || expr->len != 3) {
16038
+ if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
1582616039
goto evalstart;
1582716040
}
1582816041
1582916042
if (incrScript->token[1].type != JIM_TT_ESC ||
1583016043
expr->token[0].type != JIM_TT_VAR ||
@@ -16043,11 +16256,11 @@
1604316256
}
1604416257
1604516258
1604616259
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
1604716260
{
16048
- int result = JIM_ERR;
16261
+ int result = JIM_OK;
1604916262
int i, numargs;
1605016263
Jim_ListIter twoiters[2];
1605116264
Jim_ListIter *iters;
1605216265
Jim_Obj *script;
1605316266
Jim_Obj *resultObj;
@@ -16066,13 +16279,16 @@
1606616279
iters = Jim_Alloc(numargs * sizeof(*iters));
1606716280
}
1606816281
for (i = 0; i < numargs; i++) {
1606916282
JimListIterInit(&iters[i], argv[i + 1]);
1607016283
if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16071
- Jim_SetResultString(interp, "foreach varlist is empty", -1);
16072
- return JIM_ERR;
16284
+ result = JIM_ERR;
1607316285
}
16286
+ }
16287
+ if (result != JIM_OK) {
16288
+ Jim_SetResultString(interp, "foreach varlist is empty", -1);
16289
+ return result;
1607416290
}
1607516291
1607616292
if (doMap) {
1607716293
resultObj = Jim_NewListObj(interp, NULL, 0);
1607816294
}
@@ -16385,12 +16601,12 @@
1638516601
{
1638616602
Jim_Obj *objPtr, *listObjPtr;
1638716603
int i;
1638816604
int idx;
1638916605
16390
- if (argc < 3) {
16391
- Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16606
+ if (argc < 2) {
16607
+ Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
1639216608
return JIM_ERR;
1639316609
}
1639416610
objPtr = argv[1];
1639516611
Jim_IncrRefCount(objPtr);
1639616612
for (i = 2; i < argc; i++) {
@@ -16502,14 +16718,13 @@
1650216718
Jim_IncrRefCount(commandObj);
1650316719
}
1650416720
1650516721
listlen = Jim_ListLength(interp, argv[0]);
1650616722
for (i = 0; i < listlen; i++) {
16507
- Jim_Obj *objPtr;
1650816723
int eq = 0;
16724
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
1650916725
16510
- Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
1651116726
switch (opt_match) {
1651216727
case OPT_EXACT:
1651316728
eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
1651416729
break;
1651516730
@@ -16699,29 +16914,27 @@
1669916914
if (argc < 3) {
1670016915
Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
1670116916
return JIM_ERR;
1670216917
}
1670316918
else if (argc == 3) {
16919
+
1670416920
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1670516921
return JIM_ERR;
1670616922
Jim_SetResult(interp, argv[2]);
1670716923
return JIM_OK;
1670816924
}
16709
- if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16710
- == JIM_ERR)
16711
- return JIM_ERR;
16712
- return JIM_OK;
16925
+ return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
1671316926
}
1671416927
1671516928
1671616929
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
1671716930
{
1671816931
static const char * const options[] = {
16719
- "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16932
+ "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
1672016933
};
1672116934
enum
16722
- { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
16935
+ { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
1672316936
Jim_Obj *resObj;
1672416937
int i;
1672516938
int retCode;
1672616939
1672716940
struct lsort_info info;
@@ -16732,17 +16945,18 @@
1673216945
}
1673316946
1673416947
info.type = JIM_LSORT_ASCII;
1673516948
info.order = 1;
1673616949
info.indexed = 0;
16950
+ info.unique = 0;
1673716951
info.command = NULL;
1673816952
info.interp = interp;
1673916953
1674016954
for (i = 1; i < (argc - 1); i++) {
1674116955
int option;
1674216956
16743
- if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
16957
+ if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
1674416958
!= JIM_OK)
1674516959
return JIM_ERR;
1674616960
switch (option) {
1674716961
case OPT_ASCII:
1674816962
info.type = JIM_LSORT_ASCII;
@@ -16751,16 +16965,22 @@
1675116965
info.type = JIM_LSORT_NOCASE;
1675216966
break;
1675316967
case OPT_INTEGER:
1675416968
info.type = JIM_LSORT_INTEGER;
1675516969
break;
16970
+ case OPT_REAL:
16971
+ info.type = JIM_LSORT_REAL;
16972
+ break;
1675616973
case OPT_INCREASING:
1675716974
info.order = 1;
1675816975
break;
1675916976
case OPT_DECREASING:
1676016977
info.order = -1;
1676116978
break;
16979
+ case OPT_UNIQUE:
16980
+ info.unique = 1;
16981
+ break;
1676216982
case OPT_COMMAND:
1676316983
if (i >= (argc - 2)) {
1676416984
Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
1676516985
return JIM_ERR;
1676616986
}
@@ -16870,20 +17090,20 @@
1687017090
static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1687117091
{
1687217092
if (argc >= 2) {
1687317093
int retcode;
1687417094
Jim_CallFrame *savedCallFrame, *targetCallFrame;
16875
- Jim_Obj *objPtr;
17095
+ int savedTailcall;
1687617096
const char *str;
1687717097
1687817098
1687917099
savedCallFrame = interp->framePtr;
1688017100
1688117101
1688217102
str = Jim_String(argv[1]);
1688317103
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16884
- targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
17104
+ targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1688517105
argc--;
1688617106
argv++;
1688717107
}
1688817108
else {
1688917109
targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16890,25 +17110,25 @@
1689017110
}
1689117111
if (targetCallFrame == NULL) {
1689217112
return JIM_ERR;
1689317113
}
1689417114
if (argc < 2) {
16895
- argv--;
16896
- Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
17115
+ Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
1689717116
return JIM_ERR;
1689817117
}
1689917118
1690017119
interp->framePtr = targetCallFrame;
17120
+
17121
+ savedTailcall = interp->framePtr->tailcall;
17122
+ interp->framePtr->tailcall = 0;
1690117123
if (argc == 2) {
1690217124
retcode = Jim_EvalObj(interp, argv[1]);
1690317125
}
1690417126
else {
16905
- objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16906
- Jim_IncrRefCount(objPtr);
16907
- retcode = Jim_EvalObj(interp, objPtr);
16908
- Jim_DecrRefCount(interp, objPtr);
17127
+ retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1690917128
}
17129
+ interp->framePtr->tailcall = savedTailcall;
1691017130
interp->framePtr = savedCallFrame;
1691117131
return retcode;
1691217132
}
1691317133
else {
1691417134
Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17019,12 +17239,39 @@
1701917239
}
1702017240
1702117241
1702217242
static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1702317243
{
17024
- Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17025
- return JIM_EVAL;
17244
+ if (interp->framePtr->level == 0) {
17245
+ Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17246
+ return JIM_ERR;
17247
+ }
17248
+ else if (argc >= 2) {
17249
+
17250
+ Jim_CallFrame *cf = interp->framePtr->parent;
17251
+
17252
+ Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17253
+ if (cmdPtr == NULL) {
17254
+ return JIM_ERR;
17255
+ }
17256
+
17257
+ JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17258
+
17259
+
17260
+ JimIncrCmdRefCount(cmdPtr);
17261
+ cf->tailcallCmd = cmdPtr;
17262
+
17263
+
17264
+ JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17265
+
17266
+ cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17267
+ Jim_IncrRefCount(cf->tailcallObj);
17268
+
17269
+
17270
+ return JIM_EVAL;
17271
+ }
17272
+ return JIM_OK;
1702617273
}
1702717274
1702817275
static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1702917276
{
1703017277
Jim_Obj *cmdList;
@@ -17108,10 +17355,15 @@
1710817355
1710917356
1711017357
static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1711117358
{
1711217359
int retcode;
17360
+
17361
+ if (argc < 2) {
17362
+ Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17363
+ return JIM_ERR;
17364
+ }
1711317365
1711417366
1711517367
interp->local++;
1711617368
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
1711717369
interp->local--;
@@ -17304,11 +17556,11 @@
1730417556
for (i = 0; i < numMaps; i += 2) {
1730517557
Jim_Obj *objPtr;
1730617558
const char *k;
1730717559
int kl;
1730817560
17309
- Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17561
+ objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
1731017562
k = Jim_String(objPtr);
1731117563
kl = Jim_Utf8Length(interp, objPtr);
1731217564
1731317565
if (strLen >= kl && kl) {
1731417566
int rc;
@@ -17316,12 +17568,11 @@
1731617568
if (rc == 0) {
1731717569
if (noMatchStart) {
1731817570
Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
1731917571
noMatchStart = NULL;
1732017572
}
17321
- Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17322
- Jim_AppendObj(interp, resultObjPtr, objPtr);
17573
+ Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
1732317574
str += utf8_index(str, kl);
1732417575
strLen -= kl;
1732517576
break;
1732617577
}
1732717578
}
@@ -17795,21 +18046,23 @@
1779518046
if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
1779618047
sig++;
1779718048
}
1779818049
1779918050
interp->signal_level += sig;
17800
- if (interp->signal_level && interp->sigmask) {
18051
+ if (Jim_CheckSignal(interp)) {
1780118052
1780218053
exitCode = JIM_SIGNAL;
1780318054
}
1780418055
else {
1780518056
exitCode = Jim_EvalObj(interp, argv[0]);
18057
+
18058
+ interp->errorFlag = 0;
1780618059
}
1780718060
interp->signal_level -= sig;
1780818061
1780918062
17810
- if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
18063
+ if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
1781118064
1781218065
return exitCode;
1781318066
}
1781418067
1781518068
if (sig && exitCode == JIM_SIGNAL) {
@@ -17951,25 +18204,24 @@
1795118204
1795218205
1795318206
static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1795418207
{
1795518208
Jim_Obj *listObjPtr;
17956
- Jim_HashTableIterator *htiter;
18209
+ Jim_HashTableIterator htiter;
1795718210
Jim_HashEntry *he;
1795818211
1795918212
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1796018213
17961
- htiter = Jim_GetHashTableIterator(&interp->references);
17962
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
18214
+ JimInitHashTableIterator(&interp->references, &htiter);
18215
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1796318216
char buf[JIM_REFERENCE_SPACE + 1];
17964
- Jim_Reference *refPtr = he->u.val;
18217
+ Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
1796518218
const unsigned long *refId = he->key;
1796618219
1796718220
JimFormatReference(buf, refPtr, *refId);
1796818221
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
1796918222
}
17970
- Jim_FreeHashTableIterator(htiter);
1797118223
Jim_SetResult(interp, listObjPtr);
1797218224
return JIM_OK;
1797318225
}
1797418226
#endif
1797518227
@@ -17994,11 +18246,11 @@
1799418246
1799518247
static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
1799618248
{
1799718249
Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
1799818250
if (type & JIM_DICTMATCH_VALUES) {
17999
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18251
+ Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
1800018252
}
1800118253
}
1800218254
1800318255
static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1800418256
JimDictMatchCallbackType *callback, int type)
@@ -18005,17 +18257,17 @@
1800518257
{
1800618258
Jim_HashEntry *he;
1800718259
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
1800818260
1800918261
18010
- Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
18011
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
18262
+ Jim_HashTableIterator htiter;
18263
+ JimInitHashTableIterator(ht, &htiter);
18264
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1801218265
if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
1801318266
callback(interp, listObjPtr, he, type);
1801418267
}
1801518268
}
18016
- Jim_FreeHashTableIterator(htiter);
1801718269
1801818270
return listObjPtr;
1801918271
}
1802018272
1802118273
@@ -18043,21 +18295,65 @@
1804318295
return -1;
1804418296
}
1804518297
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
1804618298
}
1804718299
18300
+int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18301
+{
18302
+ Jim_HashTable *ht;
18303
+ unsigned int i;
18304
+
18305
+ if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18306
+ return JIM_ERR;
18307
+ }
18308
+
18309
+ ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18310
+
18311
+
18312
+ printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18313
+
18314
+ for (i = 0; i < ht->size; i++) {
18315
+ Jim_HashEntry *he = ht->table[i];
18316
+
18317
+ if (he) {
18318
+ printf("%d: ", i);
18319
+
18320
+ while (he) {
18321
+ printf(" %s", Jim_String(he->key));
18322
+ he = he->next;
18323
+ }
18324
+ printf("\n");
18325
+ }
18326
+ }
18327
+ return JIM_OK;
18328
+}
18329
+
18330
+static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18331
+{
18332
+ Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
18333
+
18334
+ Jim_AppendString(interp, prefixObj, " ", 1);
18335
+ Jim_AppendString(interp, prefixObj, subcmd, -1);
18336
+
18337
+ return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18338
+}
18339
+
1804818340
1804918341
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1805018342
{
1805118343
Jim_Obj *objPtr;
1805218344
int option;
1805318345
static const char * const options[] = {
18054
- "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
18346
+ "create", "get", "set", "unset", "exists", "keys", "size", "info",
18347
+ "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18348
+ "replace", "update", NULL
1805518349
};
1805618350
enum
1805718351
{
18058
- OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
18352
+ OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
18353
+ OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
18354
+ OPT_REPLACE, OPT_UPDATE,
1805918355
};
1806018356
1806118357
if (argc < 2) {
1806218358
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
1806318359
return JIM_ERR;
@@ -18068,11 +18364,11 @@
1806818364
}
1806918365
1807018366
switch (option) {
1807118367
case OPT_GET:
1807218368
if (argc < 3) {
18073
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18369
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
1807418370
return JIM_ERR;
1807518371
}
1807618372
if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
1807718373
JIM_ERRMSG) != JIM_OK) {
1807818374
return JIM_ERR;
@@ -18085,82 +18381,87 @@
1808518381
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
1808618382
return JIM_ERR;
1808718383
}
1808818384
return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
1808918385
18090
- case OPT_EXIST:
18091
- if (argc < 3) {
18092
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18386
+ case OPT_EXISTS:
18387
+ if (argc < 4) {
18388
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
1809318389
return JIM_ERR;
1809418390
}
18095
- Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18096
- &objPtr, JIM_ERRMSG) == JIM_OK);
18097
- return JIM_OK;
18391
+ else {
18392
+ int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
18393
+ if (rc < 0) {
18394
+ return JIM_ERR;
18395
+ }
18396
+ Jim_SetResultBool(interp, rc == JIM_OK);
18397
+ return JIM_OK;
18398
+ }
1809818399
1809918400
case OPT_UNSET:
1810018401
if (argc < 4) {
1810118402
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
1810218403
return JIM_ERR;
1810318404
}
18104
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
18405
+ if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18406
+ return JIM_ERR;
18407
+ }
18408
+ return JIM_OK;
1810518409
1810618410
case OPT_KEYS:
1810718411
if (argc != 3 && argc != 4) {
18108
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18412
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
1810918413
return JIM_ERR;
1811018414
}
1811118415
return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
1811218416
18113
- case OPT_SIZE: {
18114
- int size;
18115
-
18417
+ case OPT_SIZE:
1811618418
if (argc != 3) {
18117
- Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18419
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1811818420
return JIM_ERR;
1811918421
}
18120
-
18121
- size = Jim_DictSize(interp, argv[2]);
18122
- if (size < 0) {
18422
+ else if (Jim_DictSize(interp, argv[2]) < 0) {
1812318423
return JIM_ERR;
1812418424
}
18125
- Jim_SetResultInt(interp, size);
18425
+ Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
1812618426
return JIM_OK;
18127
- }
1812818427
1812918428
case OPT_MERGE:
1813018429
if (argc == 2) {
1813118430
return JIM_OK;
1813218431
}
18133
- else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18134
- return JIM_ERR;
18135
- }
18136
- else {
18137
- return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18138
- }
18139
-
18140
- case OPT_WITH:
18141
- if (argc < 4) {
18142
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18143
- return JIM_ERR;
18144
- }
18145
- else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18146
- return JIM_ERR;
18147
- }
18148
- else {
18149
- return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18150
- }
18432
+ if (Jim_DictSize(interp, argv[2]) < 0) {
18433
+ return JIM_ERR;
18434
+ }
18435
+
18436
+ break;
18437
+
18438
+ case OPT_UPDATE:
18439
+ if (argc < 6 || argc % 2) {
18440
+
18441
+ argc = 2;
18442
+ }
18443
+ break;
1815118444
1815218445
case OPT_CREATE:
1815318446
if (argc % 2) {
1815418447
Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
1815518448
return JIM_ERR;
1815618449
}
1815718450
objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
1815818451
Jim_SetResult(interp, objPtr);
1815918452
return JIM_OK;
18453
+
18454
+ case OPT_INFO:
18455
+ if (argc != 3) {
18456
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18457
+ return JIM_ERR;
18458
+ }
18459
+ return Jim_DictInfo(interp, argv[2]);
1816018460
}
18161
- return JIM_ERR;
18461
+
18462
+ return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
1816218463
}
1816318464
1816418465
1816518466
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1816618467
{
@@ -18218,11 +18519,11 @@
1821818519
};
1821918520
enum
1822018521
{ INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
1822118522
INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
1822218523
INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18223
- INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18524
+ INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
1822418525
};
1822518526
1822618527
#ifdef jim_ext_namespace
1822718528
int nons = 0;
1822818529
@@ -18998,11 +19299,11 @@
1899819299
}
1899919300
}
1900019301
1900119302
static const struct {
1900219303
const char *name;
19003
- Jim_CmdProc cmdProc;
19304
+ Jim_CmdProc *cmdProc;
1900419305
} Jim_CoreCommandsTable[] = {
1900519306
{"alias", Jim_AliasCoreCommand},
1900619307
{"set", Jim_SetCoreCommand},
1900719308
{"unset", Jim_UnsetCoreCommand},
1900819309
{"puts", Jim_PutsCoreCommand},
@@ -19230,10 +19531,12 @@
1923019531
}
1923119532
1923219533
len += extra;
1923319534
buf = Jim_Alloc(len + 1);
1923419535
len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19536
+
19537
+ va_end(args);
1923519538
1923619539
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
1923719540
}
1923819541
1923919542
@@ -19481,344 +19784,373 @@
1948119784
1948219785
#include <ctype.h>
1948319786
#include <string.h>
1948419787
1948519788
19486
-#define JIM_UTF_MAX 3
1948719789
#define JIM_INTEGER_SPACE 24
1948819790
#define MAX_FLOAT_WIDTH 320
1948919791
1949019792
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
1949119793
{
1949219794
const char *span, *format, *formatEnd, *msg;
1949319795
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
1949419796
static const char * const mixedXPG =
19495
- "cannot mix \"%\" and \"%n$\" conversion specifiers";
19797
+ "cannot mix \"%\" and \"%n$\" conversion specifiers";
1949619798
static const char * const badIndex[2] = {
19497
- "not enough arguments for all format specifiers",
19498
- "\"%n$\" argument index out of range"
19799
+ "not enough arguments for all format specifiers",
19800
+ "\"%n$\" argument index out of range"
1949919801
};
1950019802
int formatLen;
1950119803
Jim_Obj *resultPtr;
1950219804
1950319805
char *num_buffer = NULL;
1950419806
int num_buffer_size = 0;
1950519807
1950619808
span = format = Jim_GetString(fmtObjPtr, &formatLen);
1950719809
formatEnd = format + formatLen;
19508
- resultPtr = Jim_NewStringObj(interp, "", 0);
19810
+ resultPtr = Jim_NewEmptyStringObj(interp);
1950919811
1951019812
while (format != formatEnd) {
19511
- char *end;
19512
- int gotMinus, sawFlag;
19513
- int gotPrecision, useShort;
19514
- long width, precision;
19515
- int newXpg;
19516
- int ch;
19517
- int step;
19518
- int doubleType;
19519
- char pad = ' ';
19520
- char spec[2*JIM_INTEGER_SPACE + 12];
19521
- char *p;
19522
-
19523
- int formatted_chars;
19524
- int formatted_bytes;
19525
- const char *formatted_buf;
19526
-
19527
- step = utf8_tounicode(format, &ch);
19528
- format += step;
19529
- if (ch != '%') {
19530
- numBytes += step;
19531
- continue;
19532
- }
19533
- if (numBytes) {
19534
- Jim_AppendString(interp, resultPtr, span, numBytes);
19535
- numBytes = 0;
19536
- }
19537
-
19538
-
19539
- step = utf8_tounicode(format, &ch);
19540
- if (ch == '%') {
19541
- span = format;
19542
- numBytes = step;
19543
- format += step;
19544
- continue;
19545
- }
19546
-
19547
-
19548
- newXpg = 0;
19549
- if (isdigit(ch)) {
19550
- int position = strtoul(format, &end, 10);
19551
- if (*end == '$') {
19552
- newXpg = 1;
19553
- objIndex = position - 1;
19554
- format = end + 1;
19555
- step = utf8_tounicode(format, &ch);
19556
- }
19557
- }
19558
- if (newXpg) {
19559
- if (gotSequential) {
19560
- msg = mixedXPG;
19561
- goto errorMsg;
19562
- }
19563
- gotXpg = 1;
19564
- } else {
19565
- if (gotXpg) {
19566
- msg = mixedXPG;
19567
- goto errorMsg;
19568
- }
19569
- gotSequential = 1;
19570
- }
19571
- if ((objIndex < 0) || (objIndex >= objc)) {
19572
- msg = badIndex[gotXpg];
19573
- goto errorMsg;
19574
- }
19575
-
19576
- p = spec;
19577
- *p++ = '%';
19578
-
19579
- gotMinus = 0;
19580
- sawFlag = 1;
19581
- do {
19582
- switch (ch) {
19583
- case '-':
19584
- gotMinus = 1;
19585
- break;
19586
- case '0':
19587
- pad = ch;
19588
- break;
19589
- case ' ':
19590
- case '+':
19591
- case '#':
19592
- break;
19593
- default:
19594
- sawFlag = 0;
19595
- continue;
19596
- }
19597
- *p++ = ch;
19598
- format += step;
19599
- step = utf8_tounicode(format, &ch);
19600
- } while (sawFlag);
19601
-
19602
-
19603
- width = 0;
19604
- if (isdigit(ch)) {
19605
- width = strtoul(format, &end, 10);
19606
- format = end;
19607
- step = utf8_tounicode(format, &ch);
19608
- } else if (ch == '*') {
19609
- if (objIndex >= objc - 1) {
19610
- msg = badIndex[gotXpg];
19611
- goto errorMsg;
19612
- }
19613
- if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19614
- goto error;
19615
- }
19616
- if (width < 0) {
19617
- width = -width;
19618
- if (!gotMinus) {
19619
- *p++ = '-';
19620
- gotMinus = 1;
19621
- }
19622
- }
19623
- objIndex++;
19624
- format += step;
19625
- step = utf8_tounicode(format, &ch);
19626
- }
19627
-
19628
-
19629
- gotPrecision = precision = 0;
19630
- if (ch == '.') {
19631
- gotPrecision = 1;
19632
- format += step;
19633
- step = utf8_tounicode(format, &ch);
19634
- }
19635
- if (isdigit(ch)) {
19636
- precision = strtoul(format, &end, 10);
19637
- format = end;
19638
- step = utf8_tounicode(format, &ch);
19639
- } else if (ch == '*') {
19640
- if (objIndex >= objc - 1) {
19641
- msg = badIndex[gotXpg];
19642
- goto errorMsg;
19643
- }
19644
- if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19645
- goto error;
19646
- }
19647
-
19648
-
19649
- if (precision < 0) {
19650
- precision = 0;
19651
- }
19652
- objIndex++;
19653
- format += step;
19654
- step = utf8_tounicode(format, &ch);
19655
- }
19656
-
19657
-
19658
- useShort = 0;
19659
- if (ch == 'h') {
19660
- useShort = 1;
19661
- format += step;
19662
- step = utf8_tounicode(format, &ch);
19663
- } else if (ch == 'l') {
19664
-
19665
- format += step;
19666
- step = utf8_tounicode(format, &ch);
19667
- if (ch == 'l') {
19668
- format += step;
19669
- step = utf8_tounicode(format, &ch);
19670
- }
19671
- }
19672
-
19673
- format += step;
19674
- span = format;
19675
-
19676
-
19677
- if (ch == 'i') {
19678
- ch = 'd';
19679
- }
19680
-
19681
- doubleType = 0;
19682
-
19683
- switch (ch) {
19684
- case '\0':
19685
- msg = "format string ended in middle of field specifier";
19686
- goto errorMsg;
19687
- case 's': {
19688
- formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19689
- formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19690
- if (gotPrecision && (precision < formatted_chars)) {
19691
-
19692
- formatted_chars = precision;
19693
- formatted_bytes = utf8_index(formatted_buf, precision);
19694
- }
19695
- break;
19696
- }
19697
- case 'c': {
19698
- jim_wide code;
19699
-
19700
- if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19701
- goto error;
19702
- }
19703
-
19704
- formatted_bytes = utf8_fromunicode(spec, code);
19705
- formatted_buf = spec;
19706
- formatted_chars = 1;
19707
- break;
19708
- }
19709
-
19710
- case 'e':
19711
- case 'E':
19712
- case 'f':
19713
- case 'g':
19714
- case 'G':
19715
- doubleType = 1;
19716
-
19717
- case 'd':
19718
- case 'u':
19719
- case 'o':
19720
- case 'x':
19721
- case 'X': {
19722
- jim_wide w;
19723
- double d;
19724
- int length;
19725
-
19726
-
19727
- if (width) {
19728
- p += sprintf(p, "%ld", width);
19729
- }
19730
- if (gotPrecision) {
19731
- p += sprintf(p, ".%ld", precision);
19732
- }
19733
-
19734
-
19735
- if (doubleType) {
19736
- if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19737
- goto error;
19738
- }
19739
- length = MAX_FLOAT_WIDTH;
19740
- }
19741
- else {
19742
- if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19743
- goto error;
19744
- }
19745
- length = JIM_INTEGER_SPACE;
19746
- if (useShort) {
19747
- *p++ = 'h';
19748
- if (ch == 'd') {
19749
- w = (short)w;
19750
- }
19751
- else {
19752
- w = (unsigned short)w;
19753
- }
19754
- }
19755
- else {
19756
- *p++ = 'l';
19757
-#ifdef HAVE_LONG_LONG
19758
- if (sizeof(long long) == sizeof(jim_wide)) {
19759
- *p++ = 'l';
19760
- }
19761
-#endif
19762
- }
19763
- }
19764
-
19765
- *p++ = (char) ch;
19766
- *p = '\0';
19767
-
19768
-
19769
- if (width > length) {
19770
- length = width;
19771
- }
19772
- if (gotPrecision) {
19773
- length += precision;
19774
- }
19775
-
19776
-
19777
- if (num_buffer_size < length + 1) {
19778
- num_buffer_size = length + 1;
19779
- num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19780
- }
19781
-
19782
- if (doubleType) {
19783
- snprintf(num_buffer, length + 1, spec, d);
19784
- }
19785
- else {
19786
- formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19787
- }
19788
- formatted_chars = formatted_bytes = strlen(num_buffer);
19789
- formatted_buf = num_buffer;
19790
- break;
19791
- }
19792
-
19793
- default: {
19794
-
19795
- spec[0] = ch;
19796
- spec[1] = '\0';
19797
- Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19798
- goto error;
19799
- }
19800
- }
19801
-
19802
- if (!gotMinus) {
19803
- while (formatted_chars < width) {
19804
- Jim_AppendString(interp, resultPtr, &pad, 1);
19805
- formatted_chars++;
19806
- }
19807
- }
19808
-
19809
- Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19810
-
19811
- while (formatted_chars < width) {
19812
- Jim_AppendString(interp, resultPtr, &pad, 1);
19813
- formatted_chars++;
19814
- }
19815
-
19816
- objIndex += gotSequential;
19817
- }
19818
- if (numBytes) {
19819
- Jim_AppendString(interp, resultPtr, span, numBytes);
19813
+ char *end;
19814
+ int gotMinus, sawFlag;
19815
+ int gotPrecision, useShort;
19816
+ long width, precision;
19817
+ int newXpg;
19818
+ int ch;
19819
+ int step;
19820
+ int doubleType;
19821
+ char pad = ' ';
19822
+ char spec[2*JIM_INTEGER_SPACE + 12];
19823
+ char *p;
19824
+
19825
+ int formatted_chars;
19826
+ int formatted_bytes;
19827
+ const char *formatted_buf;
19828
+
19829
+ step = utf8_tounicode(format, &ch);
19830
+ format += step;
19831
+ if (ch != '%') {
19832
+ numBytes += step;
19833
+ continue;
19834
+ }
19835
+ if (numBytes) {
19836
+ Jim_AppendString(interp, resultPtr, span, numBytes);
19837
+ numBytes = 0;
19838
+ }
19839
+
19840
+
19841
+ step = utf8_tounicode(format, &ch);
19842
+ if (ch == '%') {
19843
+ span = format;
19844
+ numBytes = step;
19845
+ format += step;
19846
+ continue;
19847
+ }
19848
+
19849
+
19850
+ newXpg = 0;
19851
+ if (isdigit(ch)) {
19852
+ int position = strtoul(format, &end, 10);
19853
+ if (*end == '$') {
19854
+ newXpg = 1;
19855
+ objIndex = position - 1;
19856
+ format = end + 1;
19857
+ step = utf8_tounicode(format, &ch);
19858
+ }
19859
+ }
19860
+ if (newXpg) {
19861
+ if (gotSequential) {
19862
+ msg = mixedXPG;
19863
+ goto errorMsg;
19864
+ }
19865
+ gotXpg = 1;
19866
+ } else {
19867
+ if (gotXpg) {
19868
+ msg = mixedXPG;
19869
+ goto errorMsg;
19870
+ }
19871
+ gotSequential = 1;
19872
+ }
19873
+ if ((objIndex < 0) || (objIndex >= objc)) {
19874
+ msg = badIndex[gotXpg];
19875
+ goto errorMsg;
19876
+ }
19877
+
19878
+ p = spec;
19879
+ *p++ = '%';
19880
+
19881
+ gotMinus = 0;
19882
+ sawFlag = 1;
19883
+ do {
19884
+ switch (ch) {
19885
+ case '-':
19886
+ gotMinus = 1;
19887
+ break;
19888
+ case '0':
19889
+ pad = ch;
19890
+ break;
19891
+ case ' ':
19892
+ case '+':
19893
+ case '#':
19894
+ break;
19895
+ default:
19896
+ sawFlag = 0;
19897
+ continue;
19898
+ }
19899
+ *p++ = ch;
19900
+ format += step;
19901
+ step = utf8_tounicode(format, &ch);
19902
+ } while (sawFlag);
19903
+
19904
+
19905
+ width = 0;
19906
+ if (isdigit(ch)) {
19907
+ width = strtoul(format, &end, 10);
19908
+ format = end;
19909
+ step = utf8_tounicode(format, &ch);
19910
+ } else if (ch == '*') {
19911
+ if (objIndex >= objc - 1) {
19912
+ msg = badIndex[gotXpg];
19913
+ goto errorMsg;
19914
+ }
19915
+ if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19916
+ goto error;
19917
+ }
19918
+ if (width < 0) {
19919
+ width = -width;
19920
+ if (!gotMinus) {
19921
+ *p++ = '-';
19922
+ gotMinus = 1;
19923
+ }
19924
+ }
19925
+ objIndex++;
19926
+ format += step;
19927
+ step = utf8_tounicode(format, &ch);
19928
+ }
19929
+
19930
+
19931
+ gotPrecision = precision = 0;
19932
+ if (ch == '.') {
19933
+ gotPrecision = 1;
19934
+ format += step;
19935
+ step = utf8_tounicode(format, &ch);
19936
+ }
19937
+ if (isdigit(ch)) {
19938
+ precision = strtoul(format, &end, 10);
19939
+ format = end;
19940
+ step = utf8_tounicode(format, &ch);
19941
+ } else if (ch == '*') {
19942
+ if (objIndex >= objc - 1) {
19943
+ msg = badIndex[gotXpg];
19944
+ goto errorMsg;
19945
+ }
19946
+ if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19947
+ goto error;
19948
+ }
19949
+
19950
+
19951
+ if (precision < 0) {
19952
+ precision = 0;
19953
+ }
19954
+ objIndex++;
19955
+ format += step;
19956
+ step = utf8_tounicode(format, &ch);
19957
+ }
19958
+
19959
+
19960
+ useShort = 0;
19961
+ if (ch == 'h') {
19962
+ useShort = 1;
19963
+ format += step;
19964
+ step = utf8_tounicode(format, &ch);
19965
+ } else if (ch == 'l') {
19966
+
19967
+ format += step;
19968
+ step = utf8_tounicode(format, &ch);
19969
+ if (ch == 'l') {
19970
+ format += step;
19971
+ step = utf8_tounicode(format, &ch);
19972
+ }
19973
+ }
19974
+
19975
+ format += step;
19976
+ span = format;
19977
+
19978
+
19979
+ if (ch == 'i') {
19980
+ ch = 'd';
19981
+ }
19982
+
19983
+ doubleType = 0;
19984
+
19985
+ switch (ch) {
19986
+ case '\0':
19987
+ msg = "format string ended in middle of field specifier";
19988
+ goto errorMsg;
19989
+ case 's': {
19990
+ formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19991
+ formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19992
+ if (gotPrecision && (precision < formatted_chars)) {
19993
+
19994
+ formatted_chars = precision;
19995
+ formatted_bytes = utf8_index(formatted_buf, precision);
19996
+ }
19997
+ break;
19998
+ }
19999
+ case 'c': {
20000
+ jim_wide code;
20001
+
20002
+ if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20003
+ goto error;
20004
+ }
20005
+
20006
+ formatted_bytes = utf8_getchars(spec, code);
20007
+ formatted_buf = spec;
20008
+ formatted_chars = 1;
20009
+ break;
20010
+ }
20011
+ case 'b': {
20012
+ unsigned jim_wide w;
20013
+ int length;
20014
+ int i;
20015
+ int j;
20016
+
20017
+ if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
20018
+ goto error;
20019
+ }
20020
+ length = sizeof(w) * 8;
20021
+
20022
+
20023
+
20024
+ if (num_buffer_size < length + 1) {
20025
+ num_buffer_size = length + 1;
20026
+ num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20027
+ }
20028
+
20029
+ j = 0;
20030
+ for (i = length; i > 0; ) {
20031
+ i--;
20032
+ if (w & ((unsigned jim_wide)1 << i)) {
20033
+ num_buffer[j++] = '1';
20034
+ }
20035
+ else if (j || i == 0) {
20036
+ num_buffer[j++] = '0';
20037
+ }
20038
+ }
20039
+ num_buffer[j] = 0;
20040
+ formatted_chars = formatted_bytes = j;
20041
+ formatted_buf = num_buffer;
20042
+ break;
20043
+ }
20044
+
20045
+ case 'e':
20046
+ case 'E':
20047
+ case 'f':
20048
+ case 'g':
20049
+ case 'G':
20050
+ doubleType = 1;
20051
+
20052
+ case 'd':
20053
+ case 'u':
20054
+ case 'o':
20055
+ case 'x':
20056
+ case 'X': {
20057
+ jim_wide w;
20058
+ double d;
20059
+ int length;
20060
+
20061
+
20062
+ if (width) {
20063
+ p += sprintf(p, "%ld", width);
20064
+ }
20065
+ if (gotPrecision) {
20066
+ p += sprintf(p, ".%ld", precision);
20067
+ }
20068
+
20069
+
20070
+ if (doubleType) {
20071
+ if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20072
+ goto error;
20073
+ }
20074
+ length = MAX_FLOAT_WIDTH;
20075
+ }
20076
+ else {
20077
+ if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
20078
+ goto error;
20079
+ }
20080
+ length = JIM_INTEGER_SPACE;
20081
+ if (useShort) {
20082
+ if (ch == 'd') {
20083
+ w = (short)w;
20084
+ }
20085
+ else {
20086
+ w = (unsigned short)w;
20087
+ }
20088
+ }
20089
+ *p++ = 'l';
20090
+#ifdef HAVE_LONG_LONG
20091
+ if (sizeof(long long) == sizeof(jim_wide)) {
20092
+ *p++ = 'l';
20093
+ }
20094
+#endif
20095
+ }
20096
+
20097
+ *p++ = (char) ch;
20098
+ *p = '\0';
20099
+
20100
+
20101
+ if (width > length) {
20102
+ length = width;
20103
+ }
20104
+ if (gotPrecision) {
20105
+ length += precision;
20106
+ }
20107
+
20108
+
20109
+ if (num_buffer_size < length + 1) {
20110
+ num_buffer_size = length + 1;
20111
+ num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20112
+ }
20113
+
20114
+ if (doubleType) {
20115
+ snprintf(num_buffer, length + 1, spec, d);
20116
+ }
20117
+ else {
20118
+ formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
20119
+ }
20120
+ formatted_chars = formatted_bytes = strlen(num_buffer);
20121
+ formatted_buf = num_buffer;
20122
+ break;
20123
+ }
20124
+
20125
+ default: {
20126
+
20127
+ spec[0] = ch;
20128
+ spec[1] = '\0';
20129
+ Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20130
+ goto error;
20131
+ }
20132
+ }
20133
+
20134
+ if (!gotMinus) {
20135
+ while (formatted_chars < width) {
20136
+ Jim_AppendString(interp, resultPtr, &pad, 1);
20137
+ formatted_chars++;
20138
+ }
20139
+ }
20140
+
20141
+ Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
20142
+
20143
+ while (formatted_chars < width) {
20144
+ Jim_AppendString(interp, resultPtr, &pad, 1);
20145
+ formatted_chars++;
20146
+ }
20147
+
20148
+ objIndex += gotSequential;
20149
+ }
20150
+ if (numBytes) {
20151
+ Jim_AppendString(interp, resultPtr, span, numBytes);
1982020152
}
1982120153
1982220154
Jim_Free(num_buffer);
1982320155
return resultPtr;
1982420156
@@ -19827,21 +20159,22 @@
1982720159
error:
1982820160
Jim_FreeNewObj(interp, resultPtr);
1982920161
Jim_Free(num_buffer);
1983020162
return NULL;
1983120163
}
20164
+
20165
+
20166
+#if defined(JIM_REGEXP)
1983220167
#include <stdio.h>
1983320168
#include <ctype.h>
1983420169
#include <stdlib.h>
1983520170
#include <string.h>
1983620171
19837
-
19838
-#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19839
-
1984020172
1984120173
1984220174
#define REG_MAX_PAREN 100
20175
+
1984320176
1984420177
1984520178
#define END 0
1984620179
#define BOL 1
1984720180
#define EOL 2
@@ -19850,23 +20183,27 @@
1985020183
#define ANYBUT 5
1985120184
#define BRANCH 6
1985220185
#define BACK 7
1985320186
#define EXACTLY 8
1985420187
#define NOTHING 9
19855
-#define REP 10
20188
+#define REP 10
1985620189
#define REPMIN 11
1985720190
#define REPX 12
1985820191
#define REPXMIN 13
1985920192
1986020193
#define WORDA 15
1986120194
#define WORDZ 16
19862
-#define OPENNC 19
19863
-#define OPEN 20
20195
+
20196
+#define OPENNC 1000
20197
+#define OPEN 1001
1986420198
19865
-#define CLOSE (OPEN+REG_MAX_PAREN+1)
20199
+
20200
+
20201
+
20202
+#define CLOSENC 2000
20203
+#define CLOSE 2001
1986620204
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
19867
-#define CLOSENC (CLOSE-1)
1986820205
1986920206
#define REG_MAGIC 0xFADED00D
1987020207
1987120208
1987220209
#define OP(preg, p) (preg->program[p])
@@ -19876,15 +20213,15 @@
1987620213
1987720214
1987820215
1987920216
#define FAIL(R,M) { (R)->err = (M); return (M); }
1988020217
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19881
-#define META "^$.[()|?{+*"
20218
+#define META "^$.[()|?{+*"
1988220219
19883
-#define HASWIDTH 01
19884
-#define SIMPLE 02
19885
-#define SPSTART 04
20220
+#define HASWIDTH 1
20221
+#define SIMPLE 2
20222
+#define SPSTART 4
1988620223
#define WORST 0
1988720224
1988820225
#define MAX_REP_COUNT 1000000
1988920226
1989020227
static int reg(regex_t *preg, int paren , int *flagp );
@@ -19893,13 +20230,13 @@
1989320230
static int regatom(regex_t *preg, int *flagp );
1989420231
static int regnode(regex_t *preg, int op );
1989520232
static int regnext(regex_t *preg, int p );
1989620233
static void regc(regex_t *preg, int b );
1989720234
static int reginsert(regex_t *preg, int op, int size, int opnd );
19898
-static void regtail_(regex_t *preg, int p, int val, int line );
20235
+static void regtail(regex_t *preg, int p, int val);
1989920236
static void regoptail(regex_t *preg, int p, int val );
19900
-#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
20237
+static int regopsize(regex_t *preg, int p );
1990120238
1990220239
static int reg_range_find(const int *string, int c);
1990320240
static const char *str_find(const char *string, int c, int nocase);
1990420241
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
1990520242
@@ -19936,13 +20273,10 @@
1993620273
FAIL(preg, REG_ERR_NULL_ARGUMENT);
1993720274
1993820275
1993920276
preg->cflags = cflags;
1994020277
preg->regparse = exp;
19941
-
19942
- preg->program = NULL;
19943
- preg->proglen = 0;
1994420278
1994520279
1994620280
preg->proglen = (strlen(exp) + 1) * 5;
1994720281
preg->program = malloc(preg->proglen * sizeof(int));
1994820282
if (preg->program == NULL)
@@ -20103,11 +20437,10 @@
2010320437
{
2010420438
int ret;
2010520439
char op;
2010620440
int next;
2010720441
int flags;
20108
- int chain = 0;
2010920442
int min;
2011020443
int max;
2011120444
2011220445
ret = regatom(preg, &flags);
2011320446
if (ret == 0)
@@ -20186,11 +20519,11 @@
2018620519
if (ISMULT(*preg->regparse)) {
2018720520
preg->err = REG_ERR_NESTED_COUNT;
2018820521
return 0;
2018920522
}
2019020523
20191
- return chain ? chain : ret;
20524
+ return ret;
2019220525
}
2019320526
2019420527
static void reg_addrange(regex_t *preg, int lower, int upper)
2019520528
{
2019620529
if (lower > upper) {
@@ -20280,10 +20613,11 @@
2028020613
break;
2028120614
case 'U':
2028220615
if ((n = parse_hex(s, 8, ch)) > 0) {
2028320616
s += n;
2028420617
}
20618
+ break;
2028520619
case 'x':
2028620620
if ((n = parse_hex(s, 2, ch)) > 0) {
2028720621
s += n;
2028820622
}
2028920623
break;
@@ -20528,10 +20862,11 @@
2052820862
2052920863
static int regnode(regex_t *preg, int op)
2053020864
{
2053120865
reg_grow(preg, 2);
2053220866
20867
+
2053320868
preg->program[preg->p++] = op;
2053420869
preg->program[preg->p++] = 0;
2053520870
2053620871
2053720872
return preg->p - 2;
@@ -20557,11 +20892,11 @@
2055720892
preg->p += size;
2055820893
2055920894
return opnd + size;
2056020895
}
2056120896
20562
-static void regtail_(regex_t *preg, int p, int val, int line )
20897
+static void regtail(regex_t *preg, int p, int val)
2056320898
{
2056420899
int scan;
2056520900
int temp;
2056620901
int offset;
2056720902
@@ -20620,36 +20955,16 @@
2062020955
preg->pmatch = pmatch;
2062120956
preg->nmatch = nmatch;
2062220957
preg->start = string;
2062320958
2062420959
20625
- for (scan = OPERAND(1); scan != 0; ) {
20626
- switch (OP(preg, scan)) {
20627
- case REP:
20628
- case REPMIN:
20629
- case REPX:
20630
- case REPXMIN:
20631
- preg->program[scan + 4] = 0;
20632
- scan += 5;
20633
- break;
20634
-
20635
- case ANYOF:
20636
- case ANYBUT:
20637
- case EXACTLY:
20638
- scan += 2;
20639
- while (preg->program[scan++]) {
20640
- }
20641
- break;
20642
-
20643
- case END:
20644
- scan = 0;
20645
- break;
20646
-
20647
- default:
20648
- scan += 2;
20649
- break;
20650
- }
20960
+ for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
20961
+ int op = OP(preg, scan);
20962
+ if (op == END)
20963
+ break;
20964
+ if (op == REPX || op == REPXMIN)
20965
+ preg->program[scan + 4] = 0;
2065120966
}
2065220967
2065320968
2065420969
if (preg->regmust != 0) {
2065520970
s = string;
@@ -20901,10 +21216,11 @@
2090121216
2090221217
static int regmatch(regex_t *preg, int prog)
2090321218
{
2090421219
int scan;
2090521220
int next;
21221
+ const char *save;
2090621222
2090721223
scan = prog;
2090821224
2090921225
#ifdef DEBUG
2091021226
if (scan != 0 && regnarrate)
@@ -20989,27 +21305,24 @@
2098921305
break;
2099021306
case NOTHING:
2099121307
break;
2099221308
case BACK:
2099321309
break;
20994
- case BRANCH: {
20995
- const char *save;
20996
-
20997
- if (OP(preg, next) != BRANCH)
20998
- next = OPERAND(scan);
20999
- else {
21000
- do {
21001
- save = preg->reginput;
21002
- if (regmatch(preg, OPERAND(scan))) {
21003
- return(1);
21004
- }
21005
- preg->reginput = save;
21006
- scan = regnext(preg, scan);
21007
- } while (scan != 0 && OP(preg, scan) == BRANCH);
21008
- return(0);
21009
-
21010
- }
21310
+ case BRANCH:
21311
+ if (OP(preg, next) != BRANCH)
21312
+ next = OPERAND(scan);
21313
+ else {
21314
+ do {
21315
+ save = preg->reginput;
21316
+ if (regmatch(preg, OPERAND(scan))) {
21317
+ return(1);
21318
+ }
21319
+ preg->reginput = save;
21320
+ scan = regnext(preg, scan);
21321
+ } while (scan != 0 && OP(preg, scan) == BRANCH);
21322
+ return(0);
21323
+
2101121324
}
2101221325
break;
2101321326
case REP:
2101421327
case REPMIN:
2101521328
return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21017,43 +21330,35 @@
2101721330
case REPX:
2101821331
case REPXMIN:
2101921332
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
2102021333
2102121334
case END:
21022
- return(1);
21023
- break;
21335
+ return 1;
2102421336
2102521337
case OPENNC:
2102621338
case CLOSENC:
21027
- if (regmatch(preg, next)) {
21028
- return 1;
21029
- }
21030
- return 0;
21339
+ return regmatch(preg, next);
2103121340
2103221341
default:
2103321342
if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21034
- const char *save;
21035
-
2103621343
save = preg->reginput;
21037
-
2103821344
if (regmatch(preg, next)) {
21039
- int no;
2104021345
if (OP(preg, scan) < CLOSE) {
21041
- no = OP(preg, scan) - OPEN;
21346
+ int no = OP(preg, scan) - OPEN;
2104221347
if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
2104321348
preg->pmatch[no].rm_so = save - preg->start;
2104421349
}
2104521350
}
2104621351
else {
21047
- no = OP(preg, scan) - CLOSE;
21352
+ int no = OP(preg, scan) - CLOSE;
2104821353
if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
2104921354
preg->pmatch[no].rm_eo = save - preg->start;
2105021355
}
2105121356
}
2105221357
return(1);
21053
- } else
21054
- return(0);
21358
+ }
21359
+ return(0);
2105521360
}
2105621361
return REG_ERR_INTERNAL;
2105721362
}
2105821363
2105921364
scan = next;
@@ -21132,10 +21437,32 @@
2113221437
if (OP(preg, p) == BACK)
2113321438
return(p-offset);
2113421439
else
2113521440
return(p+offset);
2113621441
}
21442
+
21443
+static int regopsize(regex_t *preg, int p )
21444
+{
21445
+
21446
+ switch (OP(preg, p)) {
21447
+ case REP:
21448
+ case REPMIN:
21449
+ case REPX:
21450
+ case REPXMIN:
21451
+ return 5;
21452
+
21453
+ case ANYOF:
21454
+ case ANYBUT:
21455
+ case EXACTLY: {
21456
+ int s = p + 2;
21457
+ while (preg->program[s++]) {
21458
+ }
21459
+ return s - p;
21460
+ }
21461
+ }
21462
+ return 2;
21463
+}
2113721464
2113821465
2113921466
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
2114021467
{
2114121468
static const char *error_strings[] = {
@@ -21310,19 +21637,24 @@
2131021637
char *Jim_HistoryGetline(const char *prompt)
2131121638
{
2131221639
#ifdef USE_LINENOISE
2131321640
return linenoise(prompt);
2131421641
#else
21642
+ int len;
2131521643
char *line = malloc(MAX_LINE_LEN);
2131621644
2131721645
fputs(prompt, stdout);
2131821646
fflush(stdout);
2131921647
2132021648
if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
2132121649
free(line);
2132221650
return NULL;
2132321651
}
21652
+ len = strlen(line);
21653
+ if (len && line[len - 1] == '\n') {
21654
+ line[len - 1] = '\0';
21655
+ }
2132421656
return line;
2132521657
#endif
2132621658
}
2132721659
2132821660
void Jim_HistoryLoad(const char *filename)
@@ -21373,11 +21705,11 @@
2137321705
snprintf(history_file, history_len, "%s/.jim_history", home);
2137421706
Jim_HistoryLoad(history_file);
2137521707
}
2137621708
#endif
2137721709
21378
- printf("Welcome to Jim version %d.%d" JIM_NL,
21710
+ printf("Welcome to Jim version %d.%d\n",
2137921711
JIM_VERSION / 100, JIM_VERSION % 100);
2138021712
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
2138121713
2138221714
while (1) {
2138321715
Jim_Obj *scriptObjPtr;
@@ -21485,10 +21817,16 @@
2148521817
}
2148621818
2148721819
Jim_SetVariableStr(interp, "argv", listObj);
2148821820
Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
2148921821
}
21822
+
21823
+static void JimPrintErrorMessage(Jim_Interp *interp)
21824
+{
21825
+ Jim_MakeErrorMessage(interp);
21826
+ fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21827
+}
2149021828
2149121829
int main(int argc, char *const argv[])
2149221830
{
2149321831
int retcode;
2149421832
Jim_Interp *interp;
@@ -21502,22 +21840,20 @@
2150221840
interp = Jim_CreateInterp();
2150321841
Jim_RegisterCoreCommands(interp);
2150421842
2150521843
2150621844
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21507
- Jim_MakeErrorMessage(interp);
21508
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21845
+ JimPrintErrorMessage(interp);
2150921846
}
2151021847
2151121848
Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
2151221849
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
2151321850
retcode = Jim_initjimshInit(interp);
2151421851
2151521852
if (argc == 1) {
2151621853
if (retcode == JIM_ERR) {
21517
- Jim_MakeErrorMessage(interp);
21518
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21854
+ JimPrintErrorMessage(interp);
2151921855
}
2152021856
if (retcode != JIM_EXIT) {
2152121857
JimSetArgv(interp, 0, NULL);
2152221858
retcode = Jim_InteractivePrompt(interp);
2152321859
}
@@ -21534,12 +21870,11 @@
2153421870
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
2153521871
JimSetArgv(interp, argc - 2, argv + 2);
2153621872
retcode = Jim_EvalFile(interp, argv[1]);
2153721873
}
2153821874
if (retcode == JIM_ERR) {
21539
- Jim_MakeErrorMessage(interp);
21540
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21875
+ JimPrintErrorMessage(interp);
2154121876
}
2154221877
}
2154321878
if (retcode == JIM_EXIT) {
2154421879
retcode = Jim_GetExitCode(interp);
2154521880
}
2154621881
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
2 #define _GNU_SOURCE
3 #define JIM_TCL_COMPAT
4 #define JIM_REFERENCES
5 #define JIM_ANSIC
6 #define JIM_REGEXP
@@ -42,14 +42,19 @@
42 #define HAVE_ISATTY
43 #define HAVE_SYS_TIME_H
44 #define HAVE_DIRENT_H
45 #define HAVE_UNISTD_H
46 #endif
 
47 #ifndef JIM_WIN32COMPAT_H
48 #define JIM_WIN32COMPAT_H
49
50
 
 
 
 
51
52
53 #if defined(_WIN32) || defined(WIN32)
54
55 #define HAVE_DLOPEN
@@ -105,17 +110,31 @@
105 } DIR;
106
107 DIR *opendir(const char *name);
108 int closedir(DIR *dir);
109 struct dirent *readdir(DIR *dir);
110 #endif
 
 
 
 
 
111
112 #endif
 
 
 
 
113
114 #endif
115 #ifndef UTF8_UTIL_H
116 #define UTF8_UTIL_H
 
 
 
 
 
117
118
119 #define MAX_UTF8_LEN 4
120
121 int utf8_fromunicode(char *p, unsigned uc);
@@ -124,10 +143,11 @@
124 #include <ctype.h>
125
126
127 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
128 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
 
129 #define utf8_upper(C) toupper(C)
130 #define utf8_title(C) toupper(C)
131 #define utf8_lower(C) tolower(C)
132 #define utf8_index(C, I) (I)
133 #define utf8_charlen(C) 1
@@ -134,10 +154,14 @@
134 #define utf8_prev_len(S, L) 1
135
136 #else
137
138 #endif
 
 
 
 
139
140 #endif
141
142 #ifndef __JIM__H
143 #define __JIM__H
@@ -185,12 +209,10 @@
185 #endif
186
187 #define UCHAR(c) ((unsigned char)(c))
188
189
190 #define JIM_VERSION 73
191
192 #define JIM_OK 0
193 #define JIM_ERR 1
194 #define JIM_RETURN 2
195 #define JIM_BREAK 3
196 #define JIM_CONTINUE 4
@@ -200,44 +222,34 @@
200 #define JIM_EVAL 7
201
202 #define JIM_MAX_CALLFRAME_DEPTH 1000
203 #define JIM_MAX_EVAL_DEPTH 2000
204
205 #define JIM_NONE 0
206 #define JIM_ERRMSG 1
207
208 #define JIM_UNSHARED 4
209 #define JIM_MUSTEXIST 8
210
211
212 #define JIM_GLOBAL_ONLY 0x100
213
214
215 #define JIM_SUBST_NOVAR 1
216 #define JIM_SUBST_NOCMD 2
217 #define JIM_SUBST_NOESC 4
218 #define JIM_SUBST_FLAG 128
219
220
221 #define JIM_NOTUSED(V) ((void) V)
222
223
224 #define JIM_ENUM_ABBREV 2
225
226
227 #define JIM_CASESENS 0
228 #define JIM_NOCASE 1
229
230
231 #define JIM_PATH_LEN 1024
232
233
234 #ifdef JIM_CRLF
235 #define JIM_NL "\r\n"
236 #else
237 #define JIM_NL "\n"
238 #endif
239
240 #define JIM_LIBPATH "auto_path"
241 #define JIM_INTERACTIVE "tcl_interactive"
242
243
@@ -267,21 +279,22 @@
267 } Jim_HashTableType;
268
269 typedef struct Jim_HashTable {
270 Jim_HashEntry **table;
271 const Jim_HashTableType *type;
 
272 unsigned int size;
273 unsigned int sizemask;
274 unsigned int used;
275 unsigned int collisions;
276 void *privdata;
277 } Jim_HashTable;
278
279 typedef struct Jim_HashTableIterator {
280 Jim_HashTable *ht;
281 int index;
282 Jim_HashEntry *entry, *nextEntry;
 
283 } Jim_HashTableIterator;
284
285
286 #define JIM_HT_INITIAL_SIZE 16
287
@@ -290,45 +303,45 @@
290 if ((ht)->type->valDestructor) \
291 (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
292
293 #define Jim_SetHashVal(ht, entry, _val_) do { \
294 if ((ht)->type->valDup) \
295 entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
296 else \
297 entry->u.val = (_val_); \
298 } while(0)
299
300 #define Jim_FreeEntryKey(ht, entry) \
301 if ((ht)->type->keyDestructor) \
302 (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
303
304 #define Jim_SetHashKey(ht, entry, _key_) do { \
305 if ((ht)->type->keyDup) \
306 entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
307 else \
308 entry->key = (void *)(_key_); \
309 } while(0)
310
311 #define Jim_CompareHashKeys(ht, key1, key2) \
312 (((ht)->type->keyCompare) ? \
313 (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
314 (key1) == (key2))
315
316 #define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
317
318 #define Jim_GetHashEntryKey(he) ((he)->key)
319 #define Jim_GetHashEntryVal(he) ((he)->val)
320 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
321 #define Jim_GetHashTableSize(ht) ((ht)->size)
322 #define Jim_GetHashTableUsed(ht) ((ht)->used)
323
324
325 typedef struct Jim_Obj {
326 int refCount;
327 char *bytes;
328 int length;
329 const struct Jim_ObjType *typePtr;
 
 
330
331 union {
332
333 jim_wide wideValue;
334
@@ -342,19 +355,19 @@
342 void *ptr1;
343 void *ptr2;
344 } twoPtrValue;
345
346 struct {
347 unsigned long callFrameId;
348 struct Jim_Var *varPtr;
 
349 int global;
350 } varValue;
351
352 struct {
353 unsigned long procEpoch;
354 struct Jim_Obj *nsObj;
355 struct Jim_Cmd *cmdPtr;
 
356 } cmdValue;
357
358 struct {
359 struct Jim_Obj **ele;
360 int len;
@@ -380,12 +393,12 @@
380 struct Jim_Obj *varNameObjPtr;
381 struct Jim_Obj *indexObjPtr;
382 } dictSubstValue;
383
384 struct {
385 unsigned flags;
386 void *compre;
 
387 } regexpValue;
388 struct {
389 int line;
390 int argc;
391 } scriptLineValue;
@@ -454,21 +467,24 @@
454 struct Jim_CallFrame *next;
455 Jim_Obj *nsObj;
456 Jim_Obj *fileNameObj;
457 int line;
458 Jim_Stack *localCommands;
 
 
 
459 } Jim_CallFrame;
460
461 typedef struct Jim_Var {
462 Jim_Obj *objPtr;
463 struct Jim_CallFrame *linkFramePtr;
464 } Jim_Var;
465
466
467 typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
468 Jim_Obj *const *argv);
469 typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
470
471
472
473 typedef struct Jim_Cmd {
474 int inUse;
@@ -475,12 +491,12 @@
475 int isproc;
476 struct Jim_Cmd *prevCmd;
477 union {
478 struct {
479
480 Jim_CmdProc cmdProc;
481 Jim_DelCmdProc delProc;
482 void *privData;
483 } native;
484 struct {
485
486 Jim_Obj *argListObjPtr;
@@ -590,15 +606,11 @@
590 Jim_Obj *finalizerCmdNamePtr;
591 char tag[JIM_REFERENCE_TAGLEN+1];
592 } Jim_Reference;
593
594
595
596 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
597
598
599
600 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
601
602 #define JIM_EXPORT
603
604
@@ -609,10 +621,11 @@
609 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
610
611
612 JIM_EXPORT char **Jim_GetEnviron(void);
613 JIM_EXPORT void Jim_SetEnviron(char **env);
 
614
615
616 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
617
618
@@ -665,12 +678,10 @@
665
666
667 JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
668 JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
669 JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
670 JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes,
671 int length);
672 JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
673 Jim_Obj *objPtr);
674 JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
675 int *lenPtr);
676 JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -742,13 +753,12 @@
742 JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
743 const char *name, const char *val);
744 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
745 Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
746 Jim_CallFrame *targetCallFrame);
747 JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
748 Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
749 JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
750 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
751 Jim_Obj *nameObjPtr, int flags);
752 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
753 Jim_Obj *nameObjPtr, int flags);
754 JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -807,10 +817,11 @@
807 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
808 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
809 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
810 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
811 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
 
812
813
814 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
815 int *intPtr);
816
@@ -834,16 +845,10 @@
834 double *doublePtr);
835 JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
836 double doubleValue);
837 JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
838
839
840 JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
841 const char *str);
842 JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp,
843 const char *str);
844
845
846 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
847 Jim_Obj *const *argv, const char *msg);
848 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
849 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
@@ -877,18 +882,20 @@
877 JIM_EXPORT void Jim_HistoryShow(void);
878
879
880 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
881 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
 
 
 
882
883
884 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
885 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
886
887
888 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
889
890
891
892 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
893 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
894
@@ -910,16 +917,16 @@
910 #define JIM_MODFLAG_HIDDEN 0x0001
911 #define JIM_MODFLAG_FULLARGV 0x0002
912
913
914
915 typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
916
917 typedef struct {
918 const char *cmd;
919 const char *args;
920 tclmod_cmd_function *function;
921 short minargs;
922 short maxargs;
923 unsigned short flags;
924 } jim_subcmd_type;
925
@@ -936,22 +943,16 @@
936
937 #endif
938 #ifndef JIMREGEXP_H
939 #define JIMREGEXP_H
940
941 #ifndef _JIMAUTOCONF_H
942 #error Need jimautoconf.h
 
943 #endif
944
945 #if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
946
947 #include <regex.h>
948
949 #else
950
951 #include <stdlib.h>
952
953
954 typedef struct {
955 int rm_so;
956 int rm_eo;
957 } regmatch_t;
@@ -1020,10 +1021,12 @@
1020 int regcomp(regex_t *preg, const char *regex, int cflags);
1021 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
1022 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
1023 void regfree(regex_t *preg);
1024
 
 
1025 #endif
1026
1027 #endif
1028 int Jim_bootstrapInit(Jim_Interp *interp)
1029 {
@@ -1086,10 +1089,15 @@
1086 "\n"
1087 "package require readdir\n"
1088 "\n"
1089 "\n"
1090 "proc glob.globdir {dir pattern} {\n"
 
 
 
 
 
1091 " set result {}\n"
1092 " set files [readdir $dir]\n"
1093 " lappend files . ..\n"
1094 "\n"
1095 " foreach name $files {\n"
@@ -1268,10 +1276,12 @@
1268 {
1269 if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
1270 return JIM_ERR;
1271
1272 return Jim_EvalSource(interp, "stdlib.tcl", 1,
 
 
1273 "\n"
1274 "proc lambda {arglist args} {\n"
1275 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1276 "}\n"
1277 "\n"
@@ -1297,46 +1307,48 @@
1297 "}\n"
1298 "\n"
1299 "\n"
1300 "\n"
1301 "\n"
1302 "proc stacktrace {} {\n"
1303 " set trace {}\n"
1304 " foreach level [range 1 [info level]] {\n"
1305 " lassign [info frame -$level] p f l\n"
1306 " lappend trace $p $f $l\n"
1307 " }\n"
1308 " return $trace\n"
1309 "}\n"
1310 "\n"
1311 "\n"
1312 "proc stackdump {stacktrace} {\n"
1313 " set result {}\n"
1314 " set count 0\n"
1315 " foreach {l f p} [lreverse $stacktrace] {\n"
1316 " if {$count} {\n"
1317 " append result \\n\n"
1318 " }\n"
1319 " incr count\n"
1320 " if {$p ne \"\"} {\n"
1321 " append result \"in procedure '$p' \"\n"
1322 " if {$f ne \"\"} {\n"
1323 " append result \"called \"\n"
1324 " }\n"
1325 " }\n"
1326 " if {$f ne \"\"} {\n"
1327 " append result \"at file \\\"$f\\\", line $l\"\n"
 
 
 
1328 " }\n"
1329 " }\n"
1330 " return $result\n"
1331 "}\n"
1332 "\n"
1333 "\n"
1334 "\n"
1335 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1336 " if {$stacktrace eq \"\"} {\n"
 
1337 " set stacktrace [info stacktrace]\n"
 
 
1338 " }\n"
1339 " lassign $stacktrace p f l\n"
1340 " if {$f ne \"\"} {\n"
1341 " set result \"Runtime Error: $f:$l: \"\n"
1342 " }\n"
@@ -1363,25 +1375,46 @@
1363 " }\n"
1364 " return \"\"\n"
1365 "}\n"
1366 "\n"
1367 "\n"
1368 "proc {dict with} {dictVar args script} {\n"
1369 " upvar $dictVar dict\n"
1370 " set keys {}\n"
1371 " foreach {n v} [dict get $dict {*}$args] {\n"
1372 " upvar $n var_$n\n"
1373 " set var_$n $v\n"
1374 " lappend keys $n\n"
1375 " }\n"
1376 " catch {uplevel 1 $script} msg opts\n"
1377 " if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1378 " foreach n $keys {\n"
1379 " if {[info exists var_$n]} {\n"
1380 " dict set dict {*}$args $n [set var_$n]\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1381 " } else {\n"
1382 " dict unset dict {*}$args $n\n"
1383 " }\n"
1384 " }\n"
1385 " }\n"
1386 " return {*}$opts $msg\n"
1387 "}\n"
@@ -1396,10 +1429,69 @@
1396 " dict set dict $k $v\n"
1397 " }\n"
1398 " }\n"
1399 " return $dict\n"
1400 "}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1401 );
1402 }
1403 int Jim_tclcompatInit(Jim_Interp *interp)
1404 {
1405 if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1410,12 +1502,14 @@
1410 "\n"
1411 "\n"
1412 "\n"
1413 "\n"
1414 "\n"
 
1415 "\n"
1416 "set env [env]\n"
 
1417 "\n"
1418 "if {[info commands stdout] ne \"\"} {\n"
1419 "\n"
1420 " foreach p {gets flush close eof seek tell} {\n"
1421 " proc $p {chan args} {p} {\n"
@@ -1462,51 +1556,10 @@
1462 " }\n"
1463 " }\n"
1464 " }\n"
1465 "}\n"
1466 "\n"
1467 "\n"
1468 "proc case {var args} {\n"
1469 "\n"
1470 " if {[lindex $args 0] eq \"in\"} {\n"
1471 " set args [lrange $args 1 end]\n"
1472 " }\n"
1473 "\n"
1474 "\n"
1475 " if {[llength $args] == 1} {\n"
1476 " set args [lindex $args 0]\n"
1477 " }\n"
1478 "\n"
1479 "\n"
1480 " if {[llength $args] % 2 != 0} {\n"
1481 " return -code error \"extra case pattern with no body\"\n"
1482 " }\n"
1483 "\n"
1484 "\n"
1485 " local proc case.checker {value pattern} {\n"
1486 " string match $pattern $value\n"
1487 " }\n"
1488 "\n"
1489 " foreach {value action} $args {\n"
1490 " if {$value eq \"default\"} {\n"
1491 " set do_action $action\n"
1492 " continue\n"
1493 " } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1494 " set do_action $action\n"
1495 " break\n"
1496 " }\n"
1497 " }\n"
1498 "\n"
1499 " if {[info exists do_action]} {\n"
1500 " set rc [catch [list uplevel 1 $do_action] result opts]\n"
1501 " if {$rc} {\n"
1502 " incr opts(-level)\n"
1503 " }\n"
1504 " return {*}$opts $result\n"
1505 " }\n"
1506 "}\n"
1507 "\n"
1508 "\n"
1509 "proc fileevent {args} {\n"
1510 " tailcall {*}$args\n"
1511 "}\n"
1512 "\n"
@@ -1536,13 +1589,25 @@
1536 " error \"bad option \\\"$force\\\": should be -force\"\n"
1537 " }\n"
1538 "\n"
1539 " set in [open $source]\n"
1540 "\n"
1541 " if {$force eq \"\" && [file exists $target]} {\n"
1542 " $in close\n"
1543 " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
 
 
 
 
 
 
 
 
 
 
 
 
1544 " }\n"
1545 " set out [open $target w]\n"
1546 " $in copyto $out\n"
1547 " $out close\n"
1548 " } on error {msg opts} {\n"
@@ -1587,18 +1652,18 @@
1587 " error $error\n"
1588 " }\n"
1589 "}\n"
1590 "\n"
1591 "\n"
1592 "local proc pid {{chan {}}} {\n"
1593 " if {$chan eq \"\"} {\n"
1594 " tailcall upcall pid\n"
1595 " }\n"
1596 " if {[catch {$chan tell}]} {\n"
1597 " return -code error \"can not find channel named \\\"$chan\\\"\"\n"
1598 " }\n"
1599 " if {[catch {$chan pid} pids]} {\n"
1600 " return \"\"\n"
1601 " }\n"
1602 " return $pids\n"
1603 "}\n"
1604 "\n"
@@ -1687,23 +1752,25 @@
1687 "}\n"
1688 );
1689 }
1690
1691
1692
1693 #include <stdio.h>
1694 #include <string.h>
1695 #include <errno.h>
1696 #include <fcntl.h>
 
 
 
 
1697
1698
1699 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1700 #include <sys/socket.h>
1701 #include <netinet/in.h>
1702 #include <arpa/inet.h>
1703 #include <netdb.h>
1704 #include <unistd.h>
1705 #ifdef HAVE_SYS_UN_H
1706 #include <sys/un.h>
1707 #endif
1708 #else
1709 #define JIM_ANSIC
@@ -1735,15 +1802,12 @@
1735 typedef struct AioFile
1736 {
1737 FILE *fp;
1738 Jim_Obj *filename;
1739 int type;
1740 int OpenFlags;
1741 int fd;
1742 #ifdef O_NDELAY
1743 int flags;
1744 #endif
1745 Jim_Obj *rEvent;
1746 Jim_Obj *wEvent;
1747 Jim_Obj *eEvent;
1748 int addr_family;
1749 } AioFile;
@@ -1767,28 +1831,21 @@
1767 {
1768 AioFile *af = privData;
1769
1770 JIM_NOTUSED(interp);
1771
1772 if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1773 fclose(af->fp);
1774 }
1775
1776 Jim_DecrRefCount(interp, af->filename);
1777
1778 #ifdef jim_ext_eventloop
1779
1780 if (af->rEvent) {
1781 Jim_DeleteFileHandler(interp, af->fp);
1782 }
1783 if (af->wEvent) {
1784 Jim_DeleteFileHandler(interp, af->fp);
1785 }
1786 if (af->eEvent) {
1787 Jim_DeleteFileHandler(interp, af->fp);
1788 }
1789 #endif
1790 Jim_Free(af);
1791 }
1792
1793 static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
1794 {
@@ -2035,12 +2092,31 @@
2035 return JIM_OK;
2036 }
2037
2038 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2039 {
2040 Jim_DeleteCommand(interp, Jim_String(argv[0]));
2041 return JIM_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2042 }
2043
2044 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2045 {
2046 AioFile *af = Jim_CmdPrivData(interp);
@@ -2087,11 +2163,11 @@
2087 #ifdef O_NDELAY
2088 static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2089 {
2090 AioFile *af = Jim_CmdPrivData(interp);
2091
2092 int fmode = af->flags;
2093
2094 if (argc) {
2095 long nb;
2096
2097 if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2101,12 +2177,11 @@
2101 fmode |= O_NDELAY;
2102 }
2103 else {
2104 fmode &= ~O_NDELAY;
2105 }
2106 fcntl(af->fd, F_SETFL, fmode);
2107 af->flags = fmode;
2108 }
2109 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2110 return JIM_OK;
2111 }
2112 #endif
@@ -2147,27 +2222,26 @@
2147 }
2148
2149 #ifdef jim_ext_eventloop
2150 static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
2151 {
2152 Jim_Obj *objPtr = clientData;
2153
2154 Jim_DecrRefCount(interp, objPtr);
 
2155 }
2156
2157 static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
2158 {
2159 Jim_Obj *objPtr = clientData;
2160
2161 return Jim_EvalObjBackground(interp, objPtr);
2162 }
2163
2164 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2165 int argc, Jim_Obj * const *argv)
2166 {
2167 int scriptlen = 0;
2168
2169 if (argc == 0) {
2170
2171 if (*scriptHandlerObj) {
2172 Jim_SetResult(interp, *scriptHandlerObj);
2173 }
@@ -2174,27 +2248,25 @@
2174 return JIM_OK;
2175 }
2176
2177 if (*scriptHandlerObj) {
2178
2179 Jim_DeleteFileHandler(interp, af->fp);
2180 *scriptHandlerObj = NULL;
2181 }
2182
2183
2184 Jim_GetString(argv[0], &scriptlen);
2185 if (scriptlen == 0) {
2186
2187 return JIM_OK;
2188 }
2189
2190
2191 Jim_IncrRefCount(argv[0]);
2192 *scriptHandlerObj = argv[0];
2193
2194 Jim_CreateFileHandler(interp, af->fp, mask,
2195 JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer);
2196
2197 return JIM_OK;
2198 }
2199
2200 static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -2213,11 +2285,11 @@
2213
2214 static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2215 {
2216 AioFile *af = Jim_CmdPrivData(interp);
2217
2218 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
2219 }
2220 #endif
2221
2222 static const jim_subcmd_type aio_command_table[] = {
2223 { "read",
@@ -2268,14 +2340,14 @@
2268 0,
2269 0,
2270
2271 },
2272 { "close",
2273 NULL,
2274 aio_cmd_close,
2275 0,
2276 0,
2277 JIM_MODFLAG_FULLARGV,
2278
2279 },
2280 { "seek",
2281 "offset ?start|current|end",
@@ -2347,30 +2419,32 @@
2347
2348 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
2349 Jim_Obj *const *argv)
2350 {
2351 const char *mode;
2352 const char *filename;
2353
2354 if (argc != 2 && argc != 3) {
2355 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
2356 return JIM_ERR;
2357 }
2358
2359 mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2360 filename = Jim_String(argv[1]);
2361
2362 #ifdef jim_ext_tclcompat
2363
2364 if (*filename == '|') {
2365 Jim_Obj *evalObj[3];
2366
2367 evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2368 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2369 evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2370
2371 return Jim_EvalObjVector(interp, 3, evalObj);
 
 
 
 
2372 }
2373 #endif
2374 return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
2375 }
2376
@@ -2377,70 +2451,129 @@
2377 static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
2378 const char *hdlfmt, int family, const char *mode)
2379 {
2380 AioFile *af;
2381 char buf[AIO_CMD_LEN];
2382 int OpenFlags = 0;
2383
2384 if (filename == NULL) {
2385 filename = Jim_NewStringObj(interp, hdlfmt, -1);
 
2386 }
2387
2388 Jim_IncrRefCount(filename);
2389
2390 if (fh == NULL) {
2391 if (fd < 0) {
2392 fh = fopen(Jim_String(filename), mode);
2393 }
2394 else {
2395 fh = fdopen(fd, mode);
2396 }
2397 }
2398 else {
2399 OpenFlags = AIO_KEEPOPEN;
2400 }
2401
2402 if (fh == NULL) {
2403 JimAioSetError(interp, filename);
2404 #if !defined(JIM_ANSIC)
2405 if (fd >= 0) {
2406 close(fd);
 
 
 
 
2407 }
2408 #endif
2409 Jim_DecrRefCount(interp, filename);
2410 return JIM_ERR;
2411 }
2412
2413
2414 af = Jim_Alloc(sizeof(*af));
2415 memset(af, 0, sizeof(*af));
2416 af->fp = fh;
2417 af->fd = fileno(fh);
2418 af->filename = filename;
2419 #ifdef FD_CLOEXEC
2420 if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2421 fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2422 }
2423 #endif
2424 af->OpenFlags = OpenFlags;
2425 #ifdef O_NDELAY
2426 af->flags = fcntl(af->fd, F_GETFL);
2427 #endif
2428 af->addr_family = family;
2429 snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
2430 Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
2431
2432 Jim_SetResultString(interp, buf, -1);
2433
2434 return JIM_OK;
2435 }
2436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2437
2438 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
2439 {
2440 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2441
 
2442 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2443 return ((AioFile *) cmdPtr->u.native.privData)->fp;
2444 }
2445 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2446 return NULL;
@@ -2461,11 +2594,10 @@
2461 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2462 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2463
2464 return JIM_OK;
2465 }
2466
2467
2468 #include <errno.h>
2469 #include <stdio.h>
2470 #include <string.h>
2471
@@ -2497,28 +2629,29 @@
2497 return JIM_OK;
2498 }
2499 Jim_SetResultString(interp, strerror(errno), -1);
2500 return JIM_ERR;
2501 }
2502 Jim_SetResultString(interp, strerror(errno), -1);
2503
2504 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2505
2506 while ((entryPtr = readdir(dirPtr)) != NULL) {
2507 if (entryPtr->d_name[0] == '.') {
2508 if (entryPtr->d_name[1] == '\0') {
2509 continue;
2510 }
2511 if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2512 continue;
2513 }
2514 Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2515 entryPtr->d_name, -1));
2516 }
2517 closedir(dirPtr);
2518
2519 return JIM_OK;
 
2520 }
2521
2522 int Jim_readdirInit(Jim_Interp *interp)
2523 {
2524 if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2529,10 +2662,14 @@
2529 }
2530
2531 #include <stdlib.h>
2532 #include <string.h>
2533
 
 
 
 
2534
2535 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2536 {
2537 regfree(objPtr->internalRep.regexpValue.compre);
2538 Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3076,58 +3213,61 @@
3076 }
3077 #endif
3078 return "unknown";
3079 }
3080
3081
3082 static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3083 jim_wide value)
3084 {
3085 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3086 Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3087
3088 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3089 Jim_FreeObj(interp, nameobj);
3090 Jim_FreeObj(interp, valobj);
3091 return JIM_ERR;
3092 }
3093 return JIM_OK;
3094 }
3095
3096 static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3097 const char *value)
3098 {
3099 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3100 Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3101
3102 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3103 Jim_FreeObj(interp, nameobj);
3104 Jim_FreeObj(interp, valobj);
3105 return JIM_ERR;
3106 }
3107 return JIM_OK;
3108 }
3109
3110 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3111 {
3112 if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3113 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3114 return JIM_ERR;
3115 }
3116 set_array_int_value(interp, varName, "ino", sb->st_ino);
3117 set_array_int_value(interp, varName, "mode", sb->st_mode);
3118 set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3119 set_array_int_value(interp, varName, "uid", sb->st_uid);
3120 set_array_int_value(interp, varName, "gid", sb->st_gid);
3121 set_array_int_value(interp, varName, "size", sb->st_size);
3122 set_array_int_value(interp, varName, "atime", sb->st_atime);
3123 set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3124 set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3125 set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3126
3127
3128 Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3129
3130 return JIM_OK;
3131 }
3132
3133 static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3282,14 +3422,11 @@
3282 return JIM_OK;
3283 }
3284
3285 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
3286 {
3287 const char *path = Jim_String(filename);
3288 int rc = access(path, mode);
3289
3290 Jim_SetResultBool(interp, rc != -1);
3291
3292 return JIM_OK;
3293 }
3294
3295 static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3305,10 +3442,11 @@
3305 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3306 {
3307 #ifdef X_OK
3308 return file_access(interp, argv[0], X_OK);
3309 #else
 
3310 Jim_SetResultBool(interp, 1);
3311 return JIM_OK;
3312 #endif
3313 }
3314
@@ -3409,33 +3547,21 @@
3409 argv++;
3410 }
3411 return JIM_OK;
3412 }
3413
3414 #ifdef HAVE_MKSTEMP
3415 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3416 {
3417 int fd;
3418 char *filename;
3419 const char *template = "/tmp/tcl.tmp.XXXXXX";
3420
3421 if (argc >= 1) {
3422 template = Jim_String(argv[0]);
3423 }
3424 filename = Jim_StrDup(template);
3425
3426 fd = mkstemp(filename);
3427 if (fd < 0) {
3428 Jim_SetResultString(interp, "Failed to create tempfile", -1);
3429 return JIM_ERR;
3430 }
3431 close(fd);
3432
3433 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
3434 return JIM_OK;
3435 }
3436 #endif
3437
3438 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3439 {
3440 const char *source;
3441 const char *dest;
@@ -3477,14 +3603,11 @@
3477 return JIM_ERR;
3478 }
3479 return JIM_OK;
3480 }
3481
3482 #ifndef HAVE_LSTAT
3483 #define lstat stat
3484 #endif
3485
3486 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
3487 {
3488 const char *path = Jim_String(filename);
3489
3490 if (lstat(path, sb) == -1) {
@@ -3491,10 +3614,13 @@
3491 Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
3492 return JIM_ERR;
3493 }
3494 return JIM_OK;
3495 }
 
 
 
3496
3497 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3498 {
3499 struct stat sb;
3500
@@ -3619,28 +3745,32 @@
3619 }
3620 Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
3621 return JIM_OK;
3622 }
3623
 
3624 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3625 {
3626 struct stat sb;
3627
3628 if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
3629 return JIM_ERR;
3630 }
3631 return StoreStatData(interp, argv[1], &sb);
3632 }
 
 
 
3633
3634 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3635 {
3636 struct stat sb;
3637
3638 if (file_stat(interp, argv[0], &sb) != JIM_OK) {
3639 return JIM_ERR;
3640 }
3641 return StoreStatData(interp, argv[1], &sb);
3642 }
3643
3644 static const jim_subcmd_type file_command_table[] = {
3645 { "atime",
3646 "name",
@@ -3745,19 +3875,17 @@
3745 file_cmd_mkdir,
3746 1,
3747 -1,
3748
3749 },
3750 #ifdef HAVE_MKSTEMP
3751 { "tempfile",
3752 "?template?",
3753 file_cmd_tempfile,
3754 0,
3755 1,
3756
3757 },
3758 #endif
3759 { "rename",
3760 "?-force? source dest",
3761 file_cmd_rename,
3762 2,
3763 3,
@@ -3778,20 +3906,20 @@
3778 1,
3779 1,
3780
3781 },
3782 { "stat",
3783 "name var",
3784 file_cmd_stat,
3785 2,
3786 2,
3787
3788 },
3789 { "lstat",
3790 "name var",
3791 file_cmd_lstat,
3792 2,
3793 2,
3794
3795 },
3796 { "type",
3797 "name",
@@ -3847,15 +3975,15 @@
3847 return JIM_OK;
3848 }
3849
3850 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3851 {
3852 const int cwd_len = 2048;
3853 char *cwd = malloc(cwd_len);
3854
3855 if (getcwd(cwd, cwd_len) == NULL) {
3856 Jim_SetResultString(interp, "Failed to get pwd", -1);
 
3857 return JIM_ERR;
3858 }
3859 #if defined(__MINGW32__) || defined(_MSC_VER)
3860 {
3861
@@ -3866,11 +3994,11 @@
3866 }
3867 #endif
3868
3869 Jim_SetResultString(interp, cwd, -1);
3870
3871 free(cwd);
3872 return JIM_OK;
3873 }
3874
3875 int Jim_fileInit(Jim_Interp *interp)
3876 {
@@ -3935,10 +4063,11 @@
3935
3936 int Jim_execInit(Jim_Interp *interp)
3937 {
3938 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
3939 return JIM_ERR;
 
3940 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
3941 return JIM_OK;
3942 }
3943 #else
3944
@@ -3978,10 +4107,11 @@
3978 static int JimErrno(void);
3979 #else
3980 #include <unistd.h>
3981 #include <fcntl.h>
3982 #include <sys/wait.h>
 
3983
3984 typedef int fdtype;
3985 typedef int pidtype;
3986 #define JimPipe pipe
3987 #define JimErrno() errno
@@ -4005,11 +4135,11 @@
4005 static void JimRestoreEnv(char **env);
4006 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4007 pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4008 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
4009 static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
4010 static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents);
4011 static fdtype JimOpenForWrite(const char *filename, int append);
4012 static int JimRewindFd(fdtype fd);
4013
4014 static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
4015 {
@@ -4052,23 +4182,12 @@
4052 Jim_RemoveTrailingNewline(strObj);
4053 fclose(fh);
4054 return JIM_OK;
4055 }
4056
4057 static void JimTrimTrailingNewline(Jim_Interp *interp)
4058 {
4059 int len;
4060 const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4061
4062 if (len > 0 && p[len - 1] == '\n') {
4063 Jim_SetResultString(interp, p, len - 1);
4064 }
4065 }
4066
4067 static char **JimBuildEnv(Jim_Interp *interp)
4068 {
4069 #if defined(jim_ext_tclcompat)
4070 int i;
4071 int size;
4072 int num;
4073 int n;
4074 char **envptr;
@@ -4082,10 +4201,11 @@
4082
4083
4084
4085 num = Jim_ListLength(interp, objPtr);
4086 if (num % 2) {
 
4087 num--;
4088 }
4089 size = Jim_Length(objPtr) + 2;
4090
4091 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4108,22 +4228,17 @@
4108 }
4109 envptr[n] = NULL;
4110 *envdata = 0;
4111
4112 return envptr;
4113 #else
4114 return Jim_GetEnviron();
4115 #endif
4116 }
4117
4118 static void JimFreeEnv(char **env, char **original_environ)
4119 {
4120 #ifdef jim_ext_tclcompat
4121 if (env != original_environ) {
4122 Jim_Free(env);
4123 }
4124 #endif
4125 }
4126
4127 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
4128 {
4129 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4172,19 +4287,19 @@
4172 }
4173
4174
4175 struct WaitInfo
4176 {
4177 pidtype pid;
4178 int status;
4179 int flags;
4180 };
4181
4182 struct WaitInfoTable {
4183 struct WaitInfo *info;
4184 int size;
4185 int used;
4186 };
4187
4188
4189 #define WI_DETACHED 2
4190
@@ -4207,14 +4322,12 @@
4207 return table;
4208 }
4209
4210 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4211 {
4212 fdtype outputId; /* File id for output pipe. -1
4213 * means command overrode. */
4214 fdtype errorId; /* File id for temporary file
4215 * containing error output. */
4216 pidtype *pidPtr;
4217 int numPids, result;
4218
4219 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4220 Jim_Obj *listObj;
@@ -4261,26 +4374,32 @@
4261
4262 static void JimReapDetachedPids(struct WaitInfoTable *table)
4263 {
4264 struct WaitInfo *waitPtr;
4265 int count;
 
4266
4267 if (!table) {
4268 return;
4269 }
4270
4271 for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
 
 
4272 if (waitPtr->flags & WI_DETACHED) {
4273 int status;
4274 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4275 if (pid != JIM_BAD_PID) {
4276 if (waitPtr != &table->info[table->used - 1]) {
4277 *waitPtr = table->info[table->used - 1];
4278 }
4279 table->used--;
 
4280 }
4281 }
 
 
 
 
4282 }
4283 }
4284
4285 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4286 {
@@ -4302,11 +4421,10 @@
4302 }
4303
4304
4305 return JIM_BAD_PID;
4306 }
4307
4308
4309 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4310 {
4311 int j;
4312 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4347,10 +4465,11 @@
4347 int cmdCount; /* Count of number of distinct commands
4348 * found in argc/argv. */
4349 const char *input = NULL; /* Describes input for pipeline, depending
4350 * on "inputFile". NULL means take input
4351 * from stdin/pipe. */
 
4352
4353 #define FILE_NAME 0
4354 #define FILE_APPEND 1
4355 #define FILE_HANDLE 2
4356 #define FILE_TEXT 3
@@ -4412,19 +4531,20 @@
4412 if (arg[0] == '<') {
4413 inputFile = FILE_NAME;
4414 input = arg + 1;
4415 if (*input == '<') {
4416 inputFile = FILE_TEXT;
 
4417 input++;
4418 }
4419 else if (*input == '@') {
4420 inputFile = FILE_HANDLE;
4421 input++;
4422 }
4423
4424 if (!*input && ++i < argc) {
4425 input = Jim_String(argv[i]);
4426 }
4427 }
4428 else if (arg[0] == '>') {
4429 int dup_error = 0;
4430
@@ -4498,11 +4618,11 @@
4498
4499 save_environ = JimSaveEnv(JimBuildEnv(interp));
4500
4501 if (input != NULL) {
4502 if (inputFile == FILE_TEXT) {
4503 inputId = JimCreateTemp(interp, input);
4504 if (inputId == JIM_BAD_FD) {
4505 goto error;
4506 }
4507 }
4508 else if (inputFile == FILE_HANDLE) {
@@ -4587,11 +4707,11 @@
4587 goto error;
4588 }
4589 }
4590 }
4591 else if (errFilePtr != NULL) {
4592 errorId = JimCreateTemp(interp, NULL);
4593 if (errorId == JIM_BAD_FD) {
4594 goto error;
4595 }
4596 *errFilePtr = JimDupFd(errorId);
4597 }
@@ -4625,27 +4745,23 @@
4625 }
4626 outputId = pipeIds[1];
4627 }
4628
4629
 
 
 
 
 
4630
4631 #ifdef __MINGW32__
4632 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
4633 if (pid == JIM_BAD_PID) {
4634 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
4635 goto error;
4636 }
4637 #else
4638 if (table->info == NULL) {
4639 (void)signal(SIGPIPE, SIG_IGN);
4640 }
4641
4642
4643 if (pipe_dup_err) {
4644 errorId = outputId;
4645 }
4646
4647 pid = vfork();
4648 if (pid < 0) {
4649 Jim_SetResultErrno(interp, "couldn't fork child process");
4650 goto error;
4651 }
@@ -4658,14 +4774,17 @@
4658
4659 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
4660 close(i);
4661 }
4662
 
 
 
4663 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
4664
4665
4666 fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4667 _exit(127);
4668 }
4669 #endif
4670
4671
@@ -4767,19 +4886,24 @@
4767 if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
4768 result = JIM_ERR;
4769 }
4770 }
4771
4772 JimTrimTrailingNewline(interp);
4773
4774 return result;
4775 }
4776
4777 int Jim_execInit(Jim_Interp *interp)
4778 {
4779 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4780 return JIM_ERR;
 
 
 
 
 
4781 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
4782 return JIM_OK;
4783 }
4784
4785 #if defined(__MINGW32__)
@@ -4953,11 +5077,11 @@
4953 *status = ret;
4954 CloseHandle(pid);
4955 return pid;
4956 }
4957
4958 static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
4959 {
4960 char name[MAX_PATH];
4961 HANDLE handle;
4962
4963 if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
@@ -4977,11 +5101,11 @@
4977 FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
4978 if (fh == NULL) {
4979 goto error;
4980 }
4981
4982 if (fwrite(contents, strlen(contents), 1, fh) != 1) {
4983 fclose(fh);
4984 goto error;
4985 }
4986 fseek(fh, 0, SEEK_SET);
4987 fclose(fh);
@@ -5104,28 +5228,26 @@
5104 {
5105 STARTUPINFO startInfo;
5106 PROCESS_INFORMATION procInfo;
5107 HANDLE hProcess, h;
5108 char execPath[MAX_PATH];
5109 char *originalName;
5110 pidtype pid = JIM_BAD_PID;
5111 Jim_Obj *cmdLineObj;
5112
5113 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5114 return JIM_BAD_PID;
5115 }
5116 originalName = argv[0];
5117 argv[0] = execPath;
5118
5119 hProcess = GetCurrentProcess();
5120 cmdLineObj = JimWinBuildCommandLine(interp, argv);
5121
5122
5123 ZeroMemory(&startInfo, sizeof(startInfo));
5124 startInfo.cb = sizeof(startInfo);
5125 startInfo.dwFlags = STARTF_USESTDHANDLES;
5126 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5127 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5128 startInfo.hStdError = INVALID_HANDLE_VALUE;
5129
5130 if (inputId == JIM_BAD_FD) {
5131 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5196,23 +5318,21 @@
5196 static int JimRewindFd(int fd)
5197 {
5198 return lseek(fd, 0L, SEEK_SET);
5199 }
5200
5201 static int JimCreateTemp(Jim_Interp *interp, const char *contents)
5202 {
5203 char inName[] = "/tmp/tcl.tmp.XXXXXX";
5204
5205 int fd = mkstemp(inName);
5206 if (fd == JIM_BAD_FD) {
5207 Jim_SetResultErrno(interp, "couldn't create temp file");
5208 return -1;
5209 }
5210 unlink(inName);
5211 if (contents) {
5212 int length = strlen(contents);
5213 if (write(fd, contents, length) != length) {
5214 Jim_SetResultErrno(interp, "couldn't write temp file");
5215 close(fd);
5216 return -1;
5217 }
5218 lseek(fd, 0L, SEEK_SET);
@@ -5234,11 +5354,10 @@
5234 }
5235 #endif
5236 #endif
5237
5238
5239
5240 #ifndef _XOPEN_SOURCE
5241 #define _XOPEN_SOURCE 500
5242 #endif
5243
5244 #include <stdlib.h>
@@ -5256,11 +5375,11 @@
5256
5257 char buf[100];
5258 time_t t;
5259 long seconds;
5260
5261 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5262
5263 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5264 return -1;
5265 }
5266
@@ -5271,11 +5390,14 @@
5271 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5272 return JIM_ERR;
5273 }
5274 t = seconds;
5275
5276 strftime(buf, sizeof(buf), format, localtime(&t));
 
 
 
5277
5278 Jim_SetResultString(interp, buf, -1);
5279
5280 return JIM_OK;
5281 }
@@ -5391,11 +5513,10 @@
5391
5392 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
5393 return JIM_OK;
5394 }
5395
5396
5397 #include <limits.h>
5398 #include <stdlib.h>
5399 #include <string.h>
5400 #include <stdio.h>
5401 #include <errno.h>
@@ -5409,33 +5530,29 @@
5409 }
5410
5411 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5412 {
5413 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
5414
5415 if (!objPtr) {
5416 return JIM_OK;
5417 }
5418
5419 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5420
5421 if (Jim_IsList(objPtr)) {
5422 if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5423
5424 return JIM_ERR;
5425 }
5426 }
5427 else if (Jim_DictSize(interp, objPtr) < 0) {
5428
5429 return JIM_ERR;
5430 }
5431 Jim_SetResult(interp, objPtr);
5432 return JIM_OK;
5433 }
5434
5435
5436 return Jim_DictValues(interp, objPtr, argv[1]);
5437 }
5438
5439 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5440 {
5441 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5460,10 +5577,15 @@
5460 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5461 return JIM_OK;
5462 }
5463
5464 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
 
 
 
 
5465
5466 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5467 return JIM_ERR;
5468 }
5469
@@ -5497,10 +5619,20 @@
5497
5498 Jim_SetResultInt(interp, len);
5499
5500 return JIM_OK;
5501 }
 
 
 
 
 
 
 
 
 
 
5502
5503 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5504 {
5505 int i;
5506 int len;
@@ -5515,10 +5647,13 @@
5515
5516 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5517 if (!dictObj) {
5518
5519 return Jim_SetVariable(interp, argv[0], listObj);
 
 
 
5520 }
5521
5522 if (Jim_IsShared(dictObj)) {
5523 dictObj = Jim_DuplicateObj(interp, dictObj);
5524 }
@@ -5568,10 +5703,17 @@
5568 "arrayName",
5569 array_cmd_size,
5570 1,
5571 1,
5572
 
 
 
 
 
 
 
5573 },
5574 { "unset",
5575 "arrayName ?pattern?",
5576 array_cmd_unset,
5577 1,
@@ -5614,11 +5756,10 @@
5614 Jim_arrayInit(interp);
5615 Jim_stdlibInit(interp);
5616 Jim_tclcompatInit(interp);
5617 return JIM_OK;
5618 }
5619
5620 #define JIM_OPTIMIZATION
5621
5622 #include <stdio.h>
5623 #include <stdlib.h>
5624
@@ -5671,29 +5812,33 @@
5671 #ifdef JIM_MAINTAINER
5672 #define JIM_DEBUG_COMMAND
5673 #define JIM_DEBUG_PANIC
5674 #endif
5675
 
 
 
 
5676 const char *jim_tt_name(int type);
5677
5678 #ifdef JIM_DEBUG_PANIC
5679 static void JimPanicDump(int panic_condition, const char *fmt, ...);
5680 #define JimPanic(X) JimPanicDump X
5681 #else
5682 #define JimPanic(X)
5683 #endif
5684
5685
5686 static char JimEmptyStringRep[] = "";
5687
5688 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5689 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5690 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5691 int flags);
5692 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5693 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5694 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
 
5695 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
5696 const char *prefix, const char *const *tablePtr, const char *name);
5697 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
5698 static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
5699 static int JimSign(jim_wide w);
@@ -5934,17 +6079,10 @@
5934 }
5935 return n;
5936 }
5937 #endif
5938
5939 int Jim_WideToString(char *buf, jim_wide wideValue)
5940 {
5941 const char *fmt = "%" JIM_WIDE_MODIFIER;
5942
5943 return sprintf(buf, fmt, wideValue);
5944 }
5945
5946 static int JimCheckConversion(const char *str, const char *endptr)
5947 {
5948 if (str[0] == '\0' || str == endptr) {
5949 return JIM_ERR;
5950 }
@@ -5998,11 +6136,12 @@
5998 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
5999
6000 return i;
6001 }
6002
6003 return 10;
 
6004 }
6005
6006 static long jim_strtol(const char *str, char **endptr)
6007 {
6008 int sign;
@@ -6054,46 +6193,10 @@
6054 }
6055
6056 return JimCheckConversion(str, endptr);
6057 }
6058
6059 int Jim_DoubleToString(char *buf, double doubleValue)
6060 {
6061 int len;
6062 int i;
6063
6064 len = sprintf(buf, "%.12g", doubleValue);
6065
6066
6067 for (i = 0; i < len; i++) {
6068 if (buf[i] == '.' || buf[i] == 'e') {
6069 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6070 char *e = strchr(buf, 'e');
6071 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6072
6073 e += 2;
6074 memmove(e, e + 1, len - (e - buf));
6075 return len - 1;
6076 }
6077 #endif
6078 return len;
6079 }
6080
6081 if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6082 buf[i] = toupper(UCHAR(buf[i]));
6083 buf[i + 3] = 0;
6084 return i + 3;
6085 }
6086 }
6087
6088 buf[i++] = '.';
6089 buf[i++] = '0';
6090 buf[i] = '\0';
6091
6092 return i;
6093 }
6094
6095 int Jim_StringToDouble(const char *str, double *doublePtr)
6096 {
6097 char *endptr;
6098
6099
@@ -6115,23 +6218,23 @@
6115 }
6116 return res;
6117 }
6118
6119 #ifdef JIM_DEBUG_PANIC
6120 void JimPanicDump(int condition, const char *fmt, ...)
6121 {
6122 va_list ap;
6123
6124 if (!condition) {
6125 return;
6126 }
6127
6128 va_start(ap, fmt);
6129
6130 fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6131 vfprintf(stderr, fmt, ap);
6132 fprintf(stderr, JIM_NL JIM_NL);
6133 va_end(ap);
6134
6135 #ifdef HAVE_BACKTRACE
6136 {
6137 void *array[40];
@@ -6139,13 +6242,13 @@
6139 char **strings;
6140
6141 size = backtrace(array, 40);
6142 strings = backtrace_symbols(array, size);
6143 for (i = 0; i < size; i++)
6144 fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6145 fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6146 fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
6147 }
6148 #endif
6149
6150 exit(1);
6151 }
@@ -6219,18 +6322,32 @@
6219 h += (h << 3) + *buf++;
6220 return h;
6221 }
6222
6223
 
6224
6225 static void JimResetHashTable(Jim_HashTable *ht)
6226 {
6227 ht->table = NULL;
6228 ht->size = 0;
6229 ht->sizemask = 0;
6230 ht->used = 0;
6231 ht->collisions = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
6232 }
6233
6234
6235 int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
6236 {
@@ -6260,10 +6377,12 @@
6260
6261 Jim_InitHashTable(&n, ht->type, ht->privdata);
6262 n.size = realsize;
6263 n.sizemask = realsize - 1;
6264 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
 
 
6265
6266
6267 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6268
6269 n.used = ht->used;
@@ -6316,20 +6435,27 @@
6316 int existed;
6317 Jim_HashEntry *entry;
6318
6319 entry = JimInsertHashEntry(ht, key, 1);
6320 if (entry->key) {
6321
6322 Jim_FreeEntryVal(ht, entry);
 
 
 
 
 
 
 
6323 existed = 1;
6324 }
6325 else {
6326
6327 Jim_SetHashKey(ht, entry, key);
 
6328 existed = 0;
6329 }
6330 Jim_SetHashVal(ht, entry, val);
6331
6332 return existed;
6333 }
6334
6335
@@ -6408,15 +6534,11 @@
6408 }
6409
6410 Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
6411 {
6412 Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6413
6414 iter->ht = ht;
6415 iter->index = -1;
6416 iter->entry = NULL;
6417 iter->nextEntry = NULL;
6418 return iter;
6419 }
6420
6421 Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
6422 {
@@ -6498,11 +6620,11 @@
6498 return Jim_GenHashFunction(key, strlen(key));
6499 }
6500
6501 static void *JimStringCopyHTDup(void *privdata, const void *key)
6502 {
6503 return strdup(key);
6504 }
6505
6506 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
6507 {
6508 return strcmp(key1, key2) == 0;
@@ -6598,11 +6720,11 @@
6598 freeFunc(stack->vector[i]);
6599 }
6600
6601
6602
6603 #define JIM_TT_NONE 0
6604 #define JIM_TT_STR 1
6605 #define JIM_TT_ESC 2
6606 #define JIM_TT_VAR 3
6607 #define JIM_TT_DICTSUGAR 4
6608 #define JIM_TT_CMD 5
@@ -6630,10 +6752,15 @@
6630
6631
6632 #define JIM_PS_DEF 0
6633 #define JIM_PS_QUOTE 1
6634 #define JIM_PS_DICTSUGAR 2
 
 
 
 
 
6635
6636 struct JimParserCtx
6637 {
6638 const char *p;
6639 int len;
@@ -6643,17 +6770,11 @@
6643 int tline;
6644 int tt;
6645 int eof;
6646 int state;
6647 int comment;
6648 char missing;
6649 int missingline;
6650 };
6651
6652 struct JimParseResult {
6653 char missing;
6654 int line;
6655 };
6656
6657 static int JimParseScript(struct JimParserCtx *pc);
6658 static int JimParseSep(struct JimParserCtx *pc);
6659 static int JimParseEol(struct JimParserCtx *pc);
@@ -6663,11 +6784,10 @@
6663 static int JimParseBrace(struct JimParserCtx *pc);
6664 static int JimParseStr(struct JimParserCtx *pc);
6665 static int JimParseComment(struct JimParserCtx *pc);
6666 static void JimParseSubCmd(struct JimParserCtx *pc);
6667 static int JimParseSubQuote(struct JimParserCtx *pc);
6668 static void JimParseSubCmd(struct JimParserCtx *pc);
6669 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
6670
6671 static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
6672 {
6673 pc->p = prg;
@@ -6678,12 +6798,12 @@
6678 pc->tt = JIM_TT_NONE;
6679 pc->eof = 0;
6680 pc->state = JIM_PS_DEF;
6681 pc->linenr = linenr;
6682 pc->comment = 1;
6683 pc->missing = ' ';
6684 pc->missingline = linenr;
6685 }
6686
6687 static int JimParseScript(struct JimParserCtx *pc)
6688 {
6689 while (1) {
@@ -6815,12 +6935,12 @@
6815 break;
6816 }
6817 pc->p++;
6818 pc->len--;
6819 }
6820 pc->missing = '{';
6821 pc->missingline = pc->tline;
6822 pc->tend = pc->p - 1;
6823 }
6824
6825 static int JimParseSubQuote(struct JimParserCtx *pc)
6826 {
@@ -6862,12 +6982,12 @@
6862 break;
6863 }
6864 pc->p++;
6865 pc->len--;
6866 }
6867 pc->missing = '"';
6868 pc->missingline = line;
6869 pc->tend = pc->p - 1;
6870 return tt;
6871 }
6872
6873 static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6921,12 +7041,12 @@
6921 }
6922 startofword = isspace(UCHAR(*pc->p));
6923 pc->p++;
6924 pc->len--;
6925 }
6926 pc->missing = '[';
6927 pc->missingline = line;
6928 pc->tend = pc->p - 1;
6929 }
6930
6931 static int JimParseBrace(struct JimParserCtx *pc)
6932 {
@@ -7066,19 +7186,19 @@
7066 if (*pc->p == '"') {
7067 pc->state = JIM_PS_QUOTE;
7068 pc->p++;
7069 pc->len--;
7070
7071 pc->missingline = pc->tline;
7072 }
7073 }
7074 pc->tstart = pc->p;
7075 pc->tline = pc->linenr;
7076 while (1) {
7077 if (pc->len == 0) {
7078 if (pc->state == JIM_PS_QUOTE) {
7079 pc->missing = '"';
7080 }
7081 pc->tend = pc->p - 1;
7082 pc->tt = JIM_TT_ESC;
7083 return JIM_OK;
7084 }
@@ -7094,10 +7214,14 @@
7094 pc->linenr++;
7095 }
7096 pc->p++;
7097 pc->len--;
7098 }
 
 
 
 
7099 break;
7100 case '(':
7101
7102 if (pc->len > 1 && pc->p[1] != '$') {
7103 break;
@@ -7154,17 +7278,26 @@
7154 }
7155
7156 static int JimParseComment(struct JimParserCtx *pc)
7157 {
7158 while (*pc->p) {
7159 if (*pc->p == '\n') {
 
 
 
 
 
 
 
 
 
 
 
 
 
7160 pc->linenr++;
7161 if (*(pc->p - 1) != '\\') {
7162 pc->p++;
7163 pc->len--;
7164 return JIM_OK;
7165 }
7166 }
7167 pc->p++;
7168 pc->len--;
7169 }
7170 return JIM_OK;
@@ -7382,13 +7515,13 @@
7382 JimParserInit(&parser, s, len, 1);
7383 while (!parser.eof) {
7384 JimParseScript(&parser);
7385 }
7386 if (stateCharPtr) {
7387 *stateCharPtr = parser.missing;
7388 }
7389 return parser.missing == ' ';
7390 }
7391
7392 static int JimParseListSep(struct JimParserCtx *pc);
7393 static int JimParseListStr(struct JimParserCtx *pc);
7394 static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7546,17 +7679,21 @@
7546 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7547 if (objPtr->nextObjPtr)
7548 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7549 if (interp->liveList == objPtr)
7550 interp->liveList = objPtr->nextObjPtr;
 
 
 
7551
7552 objPtr->prevObjPtr = NULL;
7553 objPtr->nextObjPtr = interp->freeList;
7554 if (interp->freeList)
7555 interp->freeList->prevObjPtr = objPtr;
7556 interp->freeList = objPtr;
7557 objPtr->refCount = -1;
 
7558 }
7559
7560
7561 void Jim_InvalidateStringRep(Jim_Obj *objPtr)
7562 {
@@ -7636,10 +7773,16 @@
7636 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7637 objPtr->typePtr->updateStringProc(objPtr);
7638 }
7639 return objPtr->bytes;
7640 }
 
 
 
 
 
 
7641
7642 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
7643 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
7644
7645 static const Jim_ObjType dictSubstObjType = {
@@ -7677,11 +7820,10 @@
7677 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
7678 {
7679 JIM_NOTUSED(interp);
7680
7681 dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7682
7683 dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
7684 }
7685
7686 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
7687 {
@@ -7726,18 +7868,17 @@
7726 if (len == -1)
7727 len = strlen(s);
7728
7729 if (len == 0) {
7730 objPtr->bytes = JimEmptyStringRep;
7731 objPtr->length = 0;
7732 }
7733 else {
7734 objPtr->bytes = Jim_Alloc(len + 1);
7735 objPtr->length = len;
7736 memcpy(objPtr->bytes, s, len);
7737 objPtr->bytes[len] = '\0';
7738 }
 
7739
7740
7741 objPtr->typePtr = NULL;
7742 return objPtr;
7743 }
@@ -7765,11 +7906,11 @@
7765 Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
7766 {
7767 Jim_Obj *objPtr = Jim_NewObj(interp);
7768
7769 objPtr->bytes = s;
7770 objPtr->length = len == -1 ? strlen(s) : len;
7771 objPtr->typePtr = NULL;
7772 return objPtr;
7773 }
7774
7775 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7794,17 +7935,17 @@
7794 }
7795 objPtr->internalRep.strValue.maxLength = needlen;
7796 }
7797 memcpy(objPtr->bytes + objPtr->length, str, len);
7798 objPtr->bytes[objPtr->length + len] = '\0';
 
7799 if (objPtr->internalRep.strValue.charLength >= 0) {
7800
7801 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
7802 }
7803 objPtr->length += len;
7804 }
7805
7806
7807 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
7808 {
7809 JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
7810 SetStringFromAny(interp, objPtr);
@@ -7812,13 +7953,11 @@
7812 }
7813
7814 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
7815 {
7816 int len;
7817 const char *str;
7818
7819 str = Jim_GetString(appendObjPtr, &len);
7820 Jim_AppendString(interp, objPtr, str, len);
7821 }
7822
7823 void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
7824 {
@@ -7825,11 +7964,11 @@
7825 va_list ap;
7826
7827 SetStringFromAny(interp, objPtr);
7828 va_start(ap, objPtr);
7829 while (1) {
7830 char *s = va_arg(ap, char *);
7831
7832 if (s == NULL)
7833 break;
7834 Jim_AppendString(interp, objPtr, s, -1);
7835 }
@@ -7836,20 +7975,20 @@
7836 va_end(ap);
7837 }
7838
7839 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
7840 {
7841 const char *aStr, *bStr;
7842 int aLen, bLen;
7843
7844 if (aObjPtr == bObjPtr)
7845 return 1;
7846 aStr = Jim_GetString(aObjPtr, &aLen);
7847 bStr = Jim_GetString(bObjPtr, &bLen);
7848 if (aLen != bLen)
7849 return 0;
7850 return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
 
 
 
7851 }
7852
7853 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
7854 {
7855 return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8010,11 +8149,11 @@
8010 static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
8011 {
8012 while (*str) {
8013 int c;
8014 str += utf8_tounicode(str, &c);
8015 dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8016 }
8017 *dest = 0;
8018 }
8019
8020 static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8070,11 +8209,11 @@
8070 len *= 2;
8071 #endif
8072 buf = p = Jim_Alloc(len + 1);
8073
8074 str += utf8_tounicode(str, &c);
8075 p += utf8_fromunicode(p, utf8_title(c));
8076
8077 JimStrCopyUpperLower(p, str, 0);
8078
8079 return Jim_NewStringObjNoAlloc(interp, buf, -1);
8080 }
@@ -8177,10 +8316,11 @@
8177 if (nontrim == NULL) {
8178
8179 return Jim_NewEmptyStringObj(interp);
8180 }
8181 if (nontrim == strObjPtr->bytes + len) {
 
8182 return strObjPtr;
8183 }
8184
8185 if (Jim_IsShared(strObjPtr)) {
8186 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8200,19 +8340,28 @@
8200 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8201
8202
8203 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8204
8205 if (objPtr != strObjPtr) {
 
8206
8207 Jim_IncrRefCount(objPtr);
8208 Jim_DecrRefCount(interp, objPtr);
8209 }
8210
8211 return strObjPtr;
8212 }
8213
 
 
 
 
 
 
 
 
 
8214
8215 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8216 {
8217 static const char * const strclassnames[] = {
8218 "integer", "alpha", "alnum", "ascii", "digit",
@@ -8235,32 +8384,32 @@
8235 return JIM_ERR;
8236 }
8237
8238 str = Jim_GetString(strObjPtr, &len);
8239 if (len == 0) {
8240 Jim_SetResultInt(interp, !strict);
8241 return JIM_OK;
8242 }
8243
8244 switch (strclass) {
8245 case STR_IS_INTEGER:
8246 {
8247 jim_wide w;
8248 Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8249 return JIM_OK;
8250 }
8251
8252 case STR_IS_DOUBLE:
8253 {
8254 double d;
8255 Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8256 return JIM_OK;
8257 }
8258
8259 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8260 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8261 case STR_IS_ASCII: isclassfunc = isascii; break;
8262 case STR_IS_DIGIT: isclassfunc = isdigit; break;
8263 case STR_IS_LOWER: isclassfunc = islower; break;
8264 case STR_IS_UPPER: isclassfunc = isupper; break;
8265 case STR_IS_SPACE: isclassfunc = isspace; break;
8266 case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
@@ -8272,15 +8421,15 @@
8272 return JIM_ERR;
8273 }
8274
8275 for (i = 0; i < len; i++) {
8276 if (!isclassfunc(str[i])) {
8277 Jim_SetResultInt(interp, 0);
8278 return JIM_OK;
8279 }
8280 }
8281 Jim_SetResultInt(interp, 1);
8282 return JIM_OK;
8283 }
8284
8285
8286
@@ -8292,17 +8441,19 @@
8292 JIM_TYPE_REFERENCES,
8293 };
8294
8295 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
8296 {
8297 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8298 return 1;
 
8299 else {
8300 const char *objStr = Jim_String(objPtr);
8301
8302 if (strcmp(str, objStr) != 0)
8303 return 0;
 
8304 if (objPtr->typePtr != &comparedStringObjType) {
8305 Jim_FreeIntRep(interp, objPtr);
8306 objPtr->typePtr = &comparedStringObjType;
8307 }
8308 objPtr->internalRep.ptr = (char *)str;
@@ -8344,24 +8495,23 @@
8344
8345 static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
8346 Jim_Obj *fileNameObj, int lineNumber)
8347 {
8348 JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8349 JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8350 Jim_IncrRefCount(fileNameObj);
8351 objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
8352 objPtr->internalRep.sourceValue.lineNumber = lineNumber;
8353 objPtr->typePtr = &sourceObjType;
8354 }
8355
8356
8357 static const Jim_ObjType scriptLineObjType = {
8358 "scriptline",
8359 NULL,
8360 NULL,
8361 NULL,
8362 0,
8363 };
8364
8365 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
8366 {
8367 Jim_Obj *objPtr;
@@ -8378,15 +8528,14 @@
8378 objPtr->internalRep.scriptLineValue.line = line;
8379
8380 return objPtr;
8381 }
8382
8383 #define JIM_CMDSTRUCT_EXPAND -1
8384
8385 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8386 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8387 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
 
8388
8389 static const Jim_ObjType scriptObjType = {
8390 "script",
8391 FreeScriptInternalRep,
8392 DupScriptInternalRep,
@@ -8394,34 +8543,33 @@
8394 JIM_TYPE_REFERENCES,
8395 };
8396
8397 typedef struct ScriptToken
8398 {
8399 int type;
8400 Jim_Obj *objPtr;
 
8401 } ScriptToken;
8402
8403 typedef struct ScriptObj
8404 {
8405 int len;
8406 ScriptToken *token;
 
 
8407 int substFlags;
8408 int inUse; /* Used to share a ScriptObj. Currently
8409 only used by Jim_EvalObj() as protection against
8410 shimmering of the currently evaluated object. */
8411 Jim_Obj *fileNameObj;
8412 int firstline;
8413 int linenr;
8414 } ScriptObj;
8415
8416 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8417 {
8418 int i;
8419 struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
8420
8421 script->inUse--;
8422 if (script->inUse != 0)
8423 return;
8424 for (i = 0; i < script->len; i++) {
8425 Jim_DecrRefCount(interp, script->token[i].objPtr);
8426 }
8427 Jim_Free(script->token);
@@ -8432,11 +8580,10 @@
8432 void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8433 {
8434 JIM_NOTUSED(interp);
8435 JIM_NOTUSED(srcPtr);
8436
8437
8438 dupPtr->typePtr = NULL;
8439 }
8440
8441 typedef struct
8442 {
@@ -8631,11 +8778,11 @@
8631 token--;
8632 }
8633
8634 script->len = token - script->token;
8635
8636 assert(script->len < count);
8637
8638 #ifdef DEBUG_SHOW_SCRIPT
8639 printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
8640 for (i = 0; i < script->len; i++) {
8641 const ScriptToken *t = &script->token[i];
@@ -8642,10 +8789,35 @@
8642 printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
8643 }
8644 #endif
8645
8646 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8647
8648 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8649 ParseTokenList *tokenlist)
8650 {
8651 int i;
@@ -8664,18 +8836,19 @@
8664 }
8665
8666 script->len = i;
8667 }
8668
8669 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8670 {
8671 int scriptTextLen;
8672 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
8673 struct JimParserCtx parser;
8674 struct ScriptObj *script;
8675 ParseTokenList tokenlist;
8676 int line = 1;
 
8677
8678
8679 if (objPtr->typePtr == &sourceObjType) {
8680 line = objPtr->internalRep.sourceValue.lineNumber;
8681 }
@@ -8687,16 +8860,12 @@
8687 while (!parser.eof) {
8688 JimParseScript(&parser);
8689 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
8690 parser.tline);
8691 }
8692 if (result && parser.missing != ' ') {
8693 ScriptTokenListFree(&tokenlist);
8694 result->missing = parser.missing;
8695 result->line = parser.missingline;
8696 return JIM_ERR;
8697 }
8698
8699
8700 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
8701
8702
@@ -8707,10 +8876,11 @@
8707 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
8708 }
8709 else {
8710 script->fileNameObj = interp->emptyObj;
8711 }
 
8712 Jim_IncrRefCount(script->fileNameObj);
8713
8714 ScriptObjAddTokens(interp, script, &tokenlist);
8715
8716
@@ -8719,11 +8889,11 @@
8719
8720 Jim_FreeIntRep(interp, objPtr);
8721 Jim_SetIntRepPtr(objPtr, script);
8722 objPtr->typePtr = &scriptObjType;
8723
8724 return JIM_OK;
8725 }
8726
8727 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
8728 {
8729 if (objPtr == interp->emptyObj) {
@@ -8730,11 +8900,13 @@
8730
8731 objPtr = interp->nullScriptObj;
8732 }
8733
8734 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8735 SetScriptFromAny(interp, objPtr, NULL);
 
 
8736 }
8737 return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
8738 }
8739
8740 static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8815,10 +8987,26 @@
8815 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
8816 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
8817 }
8818 return nsObj;
8819 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8820
8821 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
8822 {
8823 Jim_Obj *objPtr = interp->emptyObj;
8824
@@ -8842,10 +9030,15 @@
8842
8843 #else
8844
8845 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
8846 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
 
 
 
 
 
8847 #endif
8848
8849 static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
8850 {
8851 Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8854,12 +9047,12 @@
8854 Jim_InterpIncrProcEpoch(interp);
8855 }
8856
8857 if (he && interp->local) {
8858
8859 cmd->prevCmd = he->u.val;
8860 he->u.val = cmd;
8861 }
8862 else {
8863 if (he) {
8864
8865 Jim_DeleteHashEntry(&interp->commands, name);
@@ -8898,19 +9091,19 @@
8898 }
8899
8900 cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
8901 Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
8902 for (i = 0; i < len; i++) {
8903 Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
8904 Jim_Var *varPtr;
8905 int subLen;
8906
8907 Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
8908
8909 subLen = Jim_ListLength(interp, objPtr);
8910 if (subLen == 1 || subLen == 2) {
8911 Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
8912 if (subLen == 1) {
8913 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
8914 if (initObjPtr == NULL) {
8915 Jim_SetResultFormatted(interp,
8916 "variable for initialization of static \"%#s\" not found in the local context",
@@ -8917,11 +9110,11 @@
8917 nameObjPtr);
8918 return JIM_ERR;
8919 }
8920 }
8921 else {
8922 Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
8923 }
8924 if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
8925 return JIM_ERR;
8926 }
8927
@@ -9003,11 +9196,11 @@
9003 Jim_Obj *nameObjPtr;
9004 Jim_Obj *defaultObjPtr;
9005 int len;
9006
9007
9008 Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9009 len = Jim_ListLength(interp, argPtr);
9010 if (len == 0) {
9011 Jim_SetResultString(interp, "argument with no name", -1);
9012 err:
9013 JimDecrCmdRefCount(interp, cmdPtr);
@@ -9018,12 +9211,12 @@
9018 goto err;
9019 }
9020
9021 if (len == 2) {
9022
9023 Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9024 Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9025 }
9026 else {
9027
9028 nameObjPtr = argPtr;
9029 defaultObjPtr = NULL;
@@ -9097,11 +9290,11 @@
9097 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9098 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9099 }
9100 else {
9101
9102 cmdPtr = he->u.val;
9103 JimIncrCmdRefCount(cmdPtr);
9104 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9105 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9106
9107
@@ -9182,11 +9375,11 @@
9182 return NULL;
9183 }
9184 #ifdef jim_ext_namespace
9185 found:
9186 #endif
9187 cmd = (Jim_Cmd *)he->u.val;
9188
9189
9190 Jim_FreeIntRep(interp, objPtr);
9191 objPtr->typePtr = &commandObjType;
9192 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9288,11 +9481,11 @@
9288
9289
9290 Jim_FreeIntRep(interp, objPtr);
9291 objPtr->typePtr = &variableObjType;
9292 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9293 objPtr->internalRep.varValue.varPtr = he->u.val;
9294 objPtr->internalRep.varValue.global = global;
9295 return JIM_OK;
9296 }
9297
9298
@@ -9606,11 +9799,11 @@
9606 }
9607
9608 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
9609 if (retval == JIM_OK) {
9610
9611 JimChangeCallFrameId(interp, framePtr);
9612 }
9613 }
9614 }
9615 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
9616 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9690,28 +9883,17 @@
9690 return NULL;
9691 }
9692
9693 ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9694 if (ret != JIM_OK) {
9695 resObjPtr = NULL;
9696 if (ret < 0) {
9697 Jim_SetResultFormatted(interp,
9698 "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9699 }
9700 else {
9701 Jim_SetResultFormatted(interp,
9702 "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9703 }
9704 }
9705 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9706 dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9707 if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9708
9709 JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9710 }
9711
9712 Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9713 }
9714
9715 return resObjPtr;
9716 }
9717
@@ -9808,68 +9990,67 @@
9808 Jim_CallFrame *cf;
9809
9810 if (interp->freeFramesList) {
9811 cf = interp->freeFramesList;
9812 interp->freeFramesList = cf->next;
 
 
 
 
 
 
 
 
 
 
 
9813 }
9814 else {
9815 cf = Jim_Alloc(sizeof(*cf));
9816 cf->vars.table = NULL;
 
 
9817 }
9818
9819 cf->id = interp->callFrameEpoch++;
9820 cf->parent = parent;
9821 cf->level = parent ? parent->level + 1 : 0;
9822 cf->argv = NULL;
9823 cf->argc = 0;
9824 cf->procArgsObjPtr = NULL;
9825 cf->procBodyObjPtr = NULL;
9826 cf->next = NULL;
9827 cf->staticVars = NULL;
9828 cf->localCommands = NULL;
9829
9830 cf->nsObj = nsObj;
9831 Jim_IncrRefCount(nsObj);
9832 if (cf->vars.table == NULL)
9833 Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
9834 return cf;
9835 }
9836
9837
9838 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9839 {
9840 cf->id = interp->callFrameEpoch++;
9841 }
9842
9843 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
9844 {
9845
9846 if (localCommands) {
9847 Jim_Obj *cmdNameObj;
9848
9849 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
9850 Jim_HashEntry *he;
9851 Jim_Obj *fqObjName;
 
9852
9853 const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
9854
9855 he = Jim_FindHashEntry(&interp->commands, fqname);
9856
9857 if (he) {
9858 Jim_Cmd *cmd = he->u.val;
9859 if (cmd->prevCmd) {
9860 Jim_Cmd *prevCmd = cmd->prevCmd;
9861 cmd->prevCmd = NULL;
9862
9863
9864 JimDecrCmdRefCount(interp, cmd);
9865
9866
9867 he->u.val = prevCmd;
9868 }
9869 else {
9870 Jim_DeleteHashEntry(&interp->commands, fqname);
9871 Jim_InterpIncrProcEpoch(interp);
9872 }
9873 }
9874 Jim_DecrRefCount(interp, cmdNameObj);
9875 JimFreeQualifiedName(interp, fqObjName);
@@ -9879,47 +10060,45 @@
9879 }
9880 return JIM_OK;
9881 }
9882
9883
9884 #define JIM_FCF_NONE 0
9885 #define JIM_FCF_NOHT 1
9886 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9887 {
 
 
9888 if (cf->procArgsObjPtr)
9889 Jim_DecrRefCount(interp, cf->procArgsObjPtr);
9890 if (cf->procBodyObjPtr)
9891 Jim_DecrRefCount(interp, cf->procBodyObjPtr);
9892 Jim_DecrRefCount(interp, cf->nsObj);
9893 if (!(flags & JIM_FCF_NOHT))
9894 Jim_FreeHashTable(&cf->vars);
9895 else {
9896 int i;
9897 Jim_HashEntry **table = cf->vars.table, *he;
9898
9899 for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
9900 he = table[i];
9901 while (he != NULL) {
9902 Jim_HashEntry *nextEntry = he->next;
9903 Jim_Var *varPtr = (void *)he->u.val;
9904
9905 Jim_DecrRefCount(interp, varPtr->objPtr);
9906 Jim_Free(he->u.val);
9907 Jim_Free((void *)he->key);
9908 Jim_Free(he);
9909 table[i] = NULL;
9910 he = nextEntry;
9911 }
9912 }
9913 cf->vars.used = 0;
9914 }
9915
9916 JimDeleteLocalProcs(interp, cf->localCommands);
9917
9918 cf->next = interp->freeFramesList;
9919 interp->freeFramesList = cf;
9920
9921 }
9922
9923
9924 #ifdef JIM_REFERENCES
9925
@@ -9996,21 +10175,16 @@
9996 NULL,
9997 UpdateStringOfReference,
9998 JIM_TYPE_REFERENCES,
9999 };
10000
10001 void UpdateStringOfReference(struct Jim_Obj *objPtr)
10002 {
10003 int len;
10004 char buf[JIM_REFERENCE_SPACE + 1];
10005 Jim_Reference *refPtr;
10006
10007 refPtr = objPtr->internalRep.refValue.refPtr;
10008 len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10009 objPtr->bytes = Jim_Alloc(len + 1);
10010 memcpy(objPtr->bytes, buf, len + 1);
10011 objPtr->length = len;
10012 }
10013
10014 static int isrefchar(int c)
10015 {
10016 return (c == '_' || isalnum(c));
@@ -10061,11 +10235,11 @@
10061 he = Jim_FindHashEntry(&interp->references, &value);
10062 if (he == NULL) {
10063 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10064 return JIM_ERR;
10065 }
10066 refPtr = he->u.val;
10067
10068 Jim_FreeIntRep(interp, objPtr);
10069 objPtr->typePtr = &referenceObjType;
10070 objPtr->internalRep.refValue.id = value;
10071 objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10178,11 +10352,11 @@
10178 Jim_Collect(interp);
10179 }
10180 }
10181 #endif
10182
10183 static int JimIsBigEndian(void)
10184 {
10185 union {
10186 unsigned short s;
10187 unsigned char c[2];
10188 } uval = {0x0102};
@@ -10234,23 +10408,30 @@
10234 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10235
10236 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
10237 Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
10238 Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
10239 Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian");
10240 Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
10241 Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
10242 Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
10243
10244 return i;
10245 }
10246
10247 void Jim_FreeInterp(Jim_Interp *i)
10248 {
10249 Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
 
10250 Jim_Obj *objPtr, *nextObjPtr;
10251
 
 
 
 
 
 
10252 Jim_DecrRefCount(i, i->emptyObj);
10253 Jim_DecrRefCount(i, i->trueObj);
10254 Jim_DecrRefCount(i, i->falseObj);
10255 Jim_DecrRefCount(i, i->result);
10256 Jim_DecrRefCount(i, i->stackTrace);
@@ -10265,61 +10446,54 @@
10265 #endif
10266 Jim_FreeHashTable(&i->packages);
10267 Jim_Free(i->prngState);
10268 Jim_FreeHashTable(&i->assocData);
10269
10270
10271 while (cf) {
10272 prevcf = cf->parent;
10273 JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10274 cf = prevcf;
10275 }
10276 if (i->liveList != NULL) {
10277 objPtr = i->liveList;
10278
10279 printf(JIM_NL "-------------------------------------" JIM_NL);
10280 printf("Objects still in the free list:" JIM_NL);
10281 while (objPtr) {
10282 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10283
10284 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10285 printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10286 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10287 }
10288 else {
10289 printf("%p (%d) %-10s: '%s'" JIM_NL,
10290 (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
10291 }
10292 if (objPtr->typePtr == &sourceObjType) {
10293 printf("FILE %s LINE %d" JIM_NL,
10294 Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
10295 objPtr->internalRep.sourceValue.lineNumber);
10296 }
10297 objPtr = objPtr->nextObjPtr;
10298 }
10299 printf("-------------------------------------" JIM_NL JIM_NL);
10300 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10301 }
 
 
10302
10303 objPtr = i->freeList;
10304 while (objPtr) {
10305 nextObjPtr = objPtr->nextObjPtr;
10306 Jim_Free(objPtr);
10307 objPtr = nextObjPtr;
10308 }
 
10309
10310 cf = i->freeFramesList;
10311 while (cf) {
10312 nextcf = cf->next;
10313 if (cf->vars.table != NULL)
10314 Jim_Free(cf->vars.table);
10315 Jim_Free(cf);
10316 cf = nextcf;
10317 }
10318 #ifdef jim_ext_load
10319 Jim_FreeLoadHandles(i);
10320 #endif
10321
10322
10323 Jim_Free(i);
10324 }
10325
@@ -10414,22 +10588,15 @@
10414 interp->stackTrace = stackTraceObj;
10415 interp->errorFlag = 1;
10416
10417 len = Jim_ListLength(interp, interp->stackTrace);
10418 if (len >= 3) {
10419 Jim_Obj *filenameObj;
10420
10421 Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE);
10422
10423 Jim_GetString(filenameObj, &len);
10424
10425 if (!Jim_Length(filenameObj)) {
10426 interp->addStackTrace = 1;
10427 }
10428 }
10429 }
10430
10431
10432 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
10433 Jim_Obj *fileNameObj, int linenr)
10434 {
10435 if (strcmp(procname, "unknown") == 0) {
@@ -10450,14 +10617,15 @@
10450 if (!*procname && Jim_Length(fileNameObj)) {
10451
10452 int len = Jim_ListLength(interp, interp->stackTrace);
10453
10454 if (len >= 3) {
10455 Jim_Obj *objPtr;
10456 if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) {
10457
10458 if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) {
 
10459
10460 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10461 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10462 return;
10463 }
@@ -10483,12 +10651,11 @@
10483 void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
10484 {
10485 Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
10486
10487 if (entryPtr != NULL) {
10488 AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10489
10490 return assocEntryPtr->data;
10491 }
10492 return NULL;
10493 }
10494
@@ -10500,12 +10667,10 @@
10500 int Jim_GetExitCode(Jim_Interp *interp)
10501 {
10502 return interp->exitCode;
10503 }
10504
10505 #define JIM_INTEGER_SPACE 24
10506
10507 static void UpdateStringOfInt(struct Jim_Obj *objPtr);
10508 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10509
10510 static const Jim_ObjType intObjType = {
10511 "int",
@@ -10522,22 +10687,46 @@
10522 UpdateStringOfInt,
10523 JIM_TYPE_NONE,
10524 };
10525
10526
10527 void UpdateStringOfInt(struct Jim_Obj *objPtr)
10528 {
10529 int len;
10530 char buf[JIM_INTEGER_SPACE + 1];
 
 
10531
10532 len = Jim_WideToString(buf, JimWideValue(objPtr));
10533 objPtr->bytes = Jim_Alloc(len + 1);
10534 memcpy(objPtr->bytes, buf, len + 1);
10535 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10536 }
10537
10538 int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10539 {
10540 jim_wide wideValue;
10541 const char *str;
10542
10543 if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10625,22 +10814,65 @@
10625 NULL,
10626 UpdateStringOfDouble,
10627 JIM_TYPE_NONE,
10628 };
10629
10630 void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10631 {
10632 int len;
10633 char buf[JIM_DOUBLE_SPACE + 1];
10634
10635 len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10636 objPtr->bytes = Jim_Alloc(len + 1);
10637 memcpy(objPtr->bytes, buf, len + 1);
10638 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10639 }
10640
10641 int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10642 {
10643 double doubleValue;
10644 jim_wide wideValue;
10645 const char *str;
10646
@@ -10755,11 +10987,11 @@
10755 }
10756
10757 #define JIM_ELESTR_SIMPLE 0
10758 #define JIM_ELESTR_BRACE 1
10759 #define JIM_ELESTR_QUOTE 2
10760 static int ListElementQuotingType(const char *s, int len)
10761 {
10762 int i, level, blevel, trySimple = 1;
10763
10764
10765 if (len == 0)
@@ -10848,15 +11080,15 @@
10848 return JIM_ELESTR_SIMPLE;
10849 }
10850 return JIM_ELESTR_QUOTE;
10851 }
10852
10853 static int BackslashQuoteString(const char *s, char *q)
10854 {
10855 char *p = q;
10856
10857 while (*s) {
10858 switch (*s) {
10859 case ' ':
10860 case '$':
10861 case '"':
10862 case '[':
@@ -10903,17 +11135,23 @@
10903 return p - q;
10904 }
10905
10906 static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
10907 {
 
10908 int i, bufLen, realLength;
10909 const char *strRep;
10910 char *p;
10911 int *quotingType;
10912
10913
10914 quotingType = Jim_Alloc(sizeof(int) * objc + 1);
 
 
 
 
 
10915 bufLen = 0;
10916 for (i = 0; i < objc; i++) {
10917 int len;
10918
10919 strRep = Jim_GetString(objv[i], &len);
@@ -10962,11 +11200,11 @@
10962 case JIM_ELESTR_QUOTE:
10963 if (i == 0 && strRep[0] == '#') {
10964 *p++ = '\\';
10965 realLength++;
10966 }
10967 qlen = BackslashQuoteString(strRep, p);
10968 p += qlen;
10969 realLength += qlen;
10970 break;
10971 }
10972
@@ -10975,11 +11213,14 @@
10975 realLength++;
10976 }
10977 }
10978 *p = '\0';
10979 objPtr->length = realLength;
10980 Jim_Free(quotingType);
 
 
 
10981 }
10982
10983 static void UpdateStringOfList(struct Jim_Obj *objPtr)
10984 {
10985 JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -10995,16 +11236,16 @@
10995
10996 if (objPtr->typePtr == &listObjType) {
10997 return JIM_OK;
10998 }
10999
11000 if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11001 Jim_Obj **listObjPtrPtr;
11002 int len;
11003 int i;
11004
11005 Jim_DictPairs(interp, objPtr, &listObjPtrPtr, &len);
11006 for (i = 0; i < len; i++) {
11007 Jim_IncrRefCount(listObjPtrPtr[i]);
11008 }
11009
11010
@@ -11099,15 +11340,17 @@
11099 Jim_Interp *interp;
11100 enum {
11101 JIM_LSORT_ASCII,
11102 JIM_LSORT_NOCASE,
11103 JIM_LSORT_INTEGER,
 
11104 JIM_LSORT_COMMAND
11105 } type;
11106 int order;
11107 int index;
11108 int indexed;
 
11109 int (*subfn)(Jim_Obj **, Jim_Obj **);
11110 };
11111
11112 static struct lsort_info *sort_info;
11113
@@ -11142,10 +11385,27 @@
11142 longjmp(sort_info->jmpbuf, JIM_ERR);
11143 }
11144
11145 return JimSign(lhs - rhs) * sort_info->order;
11146 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11147
11148 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11149 {
11150 Jim_Obj *compare_script;
11151 int rc;
@@ -11164,10 +11424,34 @@
11164 }
11165
11166 return JimSign(ret) * sort_info->order;
11167 }
11168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11169
11170 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
11171 {
11172 struct lsort_info *prev_info;
11173
@@ -11175,11 +11459,11 @@
11175 int (*fn) (Jim_Obj **, Jim_Obj **);
11176 Jim_Obj **vector;
11177 int len;
11178 int rc;
11179
11180 JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11181 SetListFromAny(interp, listObjPtr);
11182
11183
11184 prev_info = sort_info;
11185 sort_info = info;
@@ -11194,10 +11478,13 @@
11194 fn = ListSortStringNoCase;
11195 break;
11196 case JIM_LSORT_INTEGER:
11197 fn = ListSortInteger;
11198 break;
 
 
 
11199 case JIM_LSORT_COMMAND:
11200 fn = ListSortCommand;
11201 break;
11202 default:
11203 fn = NULL;
@@ -11210,12 +11497,17 @@
11210 fn = ListSortIndexHelper;
11211 }
11212
11213 if ((rc = setjmp(info->jmpbuf)) == 0) {
11214 qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
 
 
 
 
 
 
11215 }
11216 Jim_InvalidateStringRep(listObjPtr);
11217 sort_info = prev_info;
11218
11219 return rc;
11220 }
11221
@@ -11225,14 +11517,22 @@
11225 int requiredLen = currentLen + elemc;
11226 int i;
11227 Jim_Obj **point;
11228
11229 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11230 listPtr->internalRep.listValue.maxLen = requiredLen * 2;
 
 
 
 
 
 
11231
11232 listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11233 sizeof(Jim_Obj *) * listPtr->internalRep.listValue.maxLen);
 
 
11234 }
11235 if (idx < 0) {
11236 idx = currentLen;
11237 }
11238 point = listPtr->internalRep.listValue.ele + idx;
@@ -11332,11 +11632,11 @@
11332 listPtr->internalRep.listValue.ele[idx] = newObjPtr;
11333 Jim_IncrRefCount(newObjPtr);
11334 return JIM_OK;
11335 }
11336
11337 int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11338 Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
11339 {
11340 Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
11341 int shared, i, idx;
11342
@@ -11380,14 +11680,11 @@
11380 int i;
11381 int listLen = Jim_ListLength(interp, listObjPtr);
11382 Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
11383
11384 for (i = 0; i < listLen; ) {
11385 Jim_Obj *objPtr;
11386
11387 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11388 Jim_AppendObj(interp, resObjPtr, objPtr);
11389 if (++i != listLen) {
11390 Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
11391 }
11392 }
11393 return resObjPtr;
@@ -11413,43 +11710,42 @@
11413 int len = 0, objLen;
11414 char *bytes, *p;
11415
11416
11417 for (i = 0; i < objc; i++) {
11418 Jim_GetString(objv[i], &objLen);
11419 len += objLen;
11420 }
11421 if (objc)
11422 len += objc - 1;
11423
11424 p = bytes = Jim_Alloc(len + 1);
11425 for (i = 0; i < objc; i++) {
11426 const char *s = Jim_GetString(objv[i], &objLen);
11427
11428
11429 while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11430 s++;
11431 objLen--;
11432 len--;
11433 }
11434
11435 while (objLen && (s[objLen - 1] == ' ' ||
11436 s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11437
11438 if (objLen > 1 && s[objLen - 2] == '\\') {
11439 break;
11440 }
11441 objLen--;
11442 len--;
11443 }
11444 memcpy(p, s, objLen);
11445 p += objLen;
11446 if (objLen && i + 1 != objc) {
11447 *p++ = ' ';
11448 }
11449 else if (i + 1 != objc) {
11450 len--;
 
11451 }
11452 }
11453 *p = '\0';
11454 return Jim_NewStringObjNoAlloc(interp, bytes, len);
11455 }
@@ -11489,20 +11785,26 @@
11489
11490 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
11491 {
11492 return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
11493 }
 
 
 
 
 
 
11494
11495 static void JimObjectHTKeyValDestructor(void *interp, void *val)
11496 {
11497 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11498 }
11499
11500 static const Jim_HashTableType JimDictHashTableType = {
11501 JimObjectHTHashFunction,
11502 NULL,
11503 NULL,
11504 JimObjectHTKeyCompare,
11505 JimObjectHTKeyValDestructor,
11506 JimObjectHTKeyValDestructor
11507 };
11508
@@ -11523,64 +11825,58 @@
11523 }
11524
11525 void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
11526 {
11527 Jim_HashTable *ht, *dupHt;
11528 Jim_HashTableIterator *htiter;
11529 Jim_HashEntry *he;
11530
11531
11532 ht = srcPtr->internalRep.ptr;
11533 dupHt = Jim_Alloc(sizeof(*dupHt));
11534 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11535 if (ht->size != 0)
11536 Jim_ExpandHashTable(dupHt, ht->size);
11537
11538 htiter = Jim_GetHashTableIterator(ht);
11539 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11540 const Jim_Obj *keyObjPtr = he->key;
11541 Jim_Obj *valObjPtr = he->u.val;
11542
11543 Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11544 Jim_IncrRefCount(valObjPtr);
11545 Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11546 }
11547 Jim_FreeHashTableIterator(htiter);
11548
11549 dupPtr->internalRep.ptr = dupHt;
11550 dupPtr->typePtr = &dictObjType;
11551 }
11552
11553 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
11554 {
11555 Jim_HashTable *ht;
11556 Jim_HashTableIterator *htiter;
11557 Jim_HashEntry *he;
11558 Jim_Obj **objv;
11559 int i;
11560
11561 ht = dictPtr->internalRep.ptr;
11562
11563
11564 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11565 htiter = Jim_GetHashTableIterator(ht);
11566 i = 0;
11567 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11568 objv[i++] = (Jim_Obj *)he->key;
11569 objv[i++] = he->u.val;
11570 }
11571 *len = i;
11572 Jim_FreeHashTableIterator(htiter);
11573 return objv;
11574 }
11575
11576 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11577 {
11578
11579 int len;
11580 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11581
 
11582 JimMakeListStringRep(objPtr, objv, len);
11583
11584 Jim_Free(objv);
11585 }
11586
@@ -11590,11 +11886,13 @@
11590
11591 if (objPtr->typePtr == &dictObjType) {
11592 return JIM_OK;
11593 }
11594
11595 Jim_String(objPtr);
 
 
11596
11597
11598 listlen = Jim_ListLength(interp, objPtr);
11599 if (listlen % 2) {
11600 Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11607,28 +11905,14 @@
11607
11608 ht = Jim_Alloc(sizeof(*ht));
11609 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
11610
11611 for (i = 0; i < listlen; i += 2) {
11612 Jim_Obj *keyObjPtr;
11613 Jim_Obj *valObjPtr;
11614
11615 Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11616 Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11617
11618 Jim_IncrRefCount(keyObjPtr);
11619 Jim_IncrRefCount(valObjPtr);
11620
11621 if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11622 Jim_HashEntry *he;
11623
11624 he = Jim_FindHashEntry(ht, keyObjPtr);
11625 Jim_DecrRefCount(interp, keyObjPtr);
11626
11627 Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11628 he->u.val = valObjPtr;
11629 }
11630 }
11631
11632 Jim_FreeIntRep(interp, objPtr);
11633 objPtr->typePtr = &dictObjType;
11634 objPtr->internalRep.ptr = ht;
@@ -11645,31 +11929,23 @@
11645 Jim_HashTable *ht = objPtr->internalRep.ptr;
11646
11647 if (valueObjPtr == NULL) {
11648 return Jim_DeleteHashEntry(ht, keyObjPtr);
11649 }
11650 Jim_IncrRefCount(keyObjPtr);
11651 Jim_IncrRefCount(valueObjPtr);
11652 if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11653
11654 Jim_DecrRefCount(interp, keyObjPtr);
11655 }
11656 return JIM_OK;
11657 }
11658
11659 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
11660 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
11661 {
11662 int retcode;
11663
11664 JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
11665 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
11666 return JIM_ERR;
11667 }
11668 retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
11669 Jim_InvalidateStringRep(objPtr);
11670 return retcode;
11671 }
11672
11673 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
11674 {
11675 Jim_Obj *objPtr;
@@ -11796,10 +12072,11 @@
11796 }
11797 objPtr = Jim_NewDictObj(interp, NULL, 0);
11798 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
11799 }
11800 }
 
11801 Jim_InvalidateStringRep(objPtr);
11802 Jim_InvalidateStringRep(varObjPtr);
11803 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
11804 goto err;
11805 }
@@ -11821,28 +12098,29 @@
11821 NULL,
11822 UpdateStringOfIndex,
11823 JIM_TYPE_NONE,
11824 };
11825
11826 void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11827 {
11828 int len;
11829 char buf[JIM_INTEGER_SPACE + 1];
11830
11831 if (objPtr->internalRep.intValue >= 0)
11832 len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11833 else if (objPtr->internalRep.intValue == -1)
11834 len = sprintf(buf, "end");
11835 else {
11836 len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
 
 
 
 
 
 
 
 
11837 }
11838 objPtr->bytes = Jim_Alloc(len + 1);
11839 memcpy(objPtr->bytes, buf, len + 1);
11840 objPtr->length = len;
11841 }
11842
11843 int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
11844 {
11845 int idx, end = 0;
11846 const char *str;
11847 char *endptr;
11848
@@ -11910,14 +12188,17 @@
11910 {
11911
11912 if (objPtr->typePtr == &intObjType) {
11913 jim_wide val = JimWideValue(objPtr);
11914
11915 if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11916 *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11917 return JIM_OK;
11918 }
 
 
 
11919 }
11920 if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
11921 return JIM_ERR;
11922 *indexPtr = objPtr->internalRep.intValue;
11923 return JIM_OK;
@@ -11937,12 +12218,10 @@
11937 NULL
11938 };
11939
11940 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
11941
11942 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11943
11944 static const Jim_ObjType returnCodeObjType = {
11945 "return-code",
11946 NULL,
11947 NULL,
11948 NULL,
@@ -11957,11 +12236,11 @@
11957 else {
11958 return jimReturnCodes[code];
11959 }
11960 }
11961
11962 int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
11963 {
11964 int returnCode;
11965 jim_wide wideValue;
11966
11967
@@ -12089,14 +12368,15 @@
12089
12090
12091 typedef struct Jim_ExprOperator
12092 {
12093 const char *name;
12094 int precedence;
12095 int arity;
12096 int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12097 int lazy;
 
 
 
12098 } Jim_ExprOperator;
12099
12100 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12101 {
12102 Jim_IncrRefCount(obj);
@@ -12108,24 +12388,21 @@
12108 return e->stack[--e->stacklen];
12109 }
12110
12111 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12112 {
12113 int intresult = 0;
12114 int rc = JIM_OK;
12115 Jim_Obj *A = ExprPop(e);
12116 double dA, dC = 0;
12117 jim_wide wA, wC = 0;
12118
12119 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12120 intresult = 1;
12121
12122 switch (e->opcode) {
12123 case JIM_EXPROP_FUNC_INT:
12124 wC = wA;
12125 break;
12126 case JIM_EXPROP_FUNC_ROUND:
 
12127 wC = wA;
12128 break;
12129 case JIM_EXPROP_FUNC_DOUBLE:
12130 dC = wA;
12131 intresult = 0;
@@ -12134,13 +12411,10 @@
12134 wC = wA >= 0 ? wA : -wA;
12135 break;
12136 case JIM_EXPROP_UNARYMINUS:
12137 wC = -wA;
12138 break;
12139 case JIM_EXPROP_UNARYPLUS:
12140 wC = wA;
12141 break;
12142 case JIM_EXPROP_NOT:
12143 wC = !wA;
12144 break;
12145 default:
12146 abort();
@@ -12148,31 +12422,29 @@
12148 }
12149 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12150 switch (e->opcode) {
12151 case JIM_EXPROP_FUNC_INT:
12152 wC = dA;
12153 intresult = 1;
12154 break;
12155 case JIM_EXPROP_FUNC_ROUND:
12156 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12157 intresult = 1;
12158 break;
12159 case JIM_EXPROP_FUNC_DOUBLE:
 
12160 dC = dA;
 
12161 break;
12162 case JIM_EXPROP_FUNC_ABS:
12163 dC = dA >= 0 ? dA : -dA;
 
12164 break;
12165 case JIM_EXPROP_UNARYMINUS:
12166 dC = -dA;
12167 break;
12168 case JIM_EXPROP_UNARYPLUS:
12169 dC = dA;
12170 break;
12171 case JIM_EXPROP_NOT:
12172 wC = !dA;
12173 intresult = 1;
12174 break;
12175 default:
12176 abort();
12177 }
12178 }
@@ -12383,11 +12655,11 @@
12383
12384
12385
12386 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12387 {
12388 int intresult = 0;
12389 int rc = JIM_OK;
12390 double dA, dB, dC = 0;
12391 jim_wide wA, wB, wC = 0;
12392
12393 Jim_Obj *B = ExprPop(e);
@@ -12397,12 +12669,10 @@
12397 (B->typePtr != &doubleObjType || B->bytes) &&
12398 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12399
12400
12401
12402 intresult = 1;
12403
12404 switch (e->opcode) {
12405 case JIM_EXPROP_POW:
12406 case JIM_EXPROP_FUNC_POW:
12407 wC = JimPowWide(wA, wB);
12408 break;
@@ -12452,10 +12722,11 @@
12452 default:
12453 abort();
12454 }
12455 }
12456 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
 
12457 switch (e->opcode) {
12458 case JIM_EXPROP_POW:
12459 case JIM_EXPROP_FUNC_POW:
12460 #ifdef JIM_MATH_FUNCTIONS
12461 dC = pow(dA, dB);
@@ -12517,12 +12788,10 @@
12517
12518
12519
12520 int i = Jim_StringCompareObj(interp, A, B, 0);
12521
12522 intresult = 1;
12523
12524 switch (e->opcode) {
12525 case JIM_EXPROP_LT:
12526 wC = i < 0;
12527 break;
12528 case JIM_EXPROP_GT:
@@ -12566,15 +12835,11 @@
12566 int listlen;
12567 int i;
12568
12569 listlen = Jim_ListLength(interp, listObjPtr);
12570 for (i = 0; i < listlen; i++) {
12571 Jim_Obj *objPtr;
12572
12573 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12574
12575 if (Jim_StringEqObj(objPtr, valObj)) {
12576 return 1;
12577 }
12578 }
12579 return 0;
12580 }
@@ -12586,23 +12851,16 @@
12586
12587 jim_wide wC;
12588
12589 switch (e->opcode) {
12590 case JIM_EXPROP_STREQ:
12591 case JIM_EXPROP_STRNE: {
12592 int Alen, Blen;
12593 const char *sA = Jim_GetString(A, &Alen);
12594 const char *sB = Jim_GetString(B, &Blen);
12595
12596 if (e->opcode == JIM_EXPROP_STREQ) {
12597 wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12598 }
12599 else {
12600 wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
12601 }
12602 break;
12603 }
12604 case JIM_EXPROP_STRIN:
12605 wC = JimSearchList(interp, B, A);
12606 break;
12607 case JIM_EXPROP_STRNI:
12608 wC = !JimSearchList(interp, B, A);
@@ -12774,93 +13032,98 @@
12774 LAZY_OP,
12775 LAZY_LEFT,
12776 LAZY_RIGHT
12777 };
12778
 
 
 
12779 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12780 {"*", 200, 2, JimExprOpBin, LAZY_NONE},
12781 {"/", 200, 2, JimExprOpBin, LAZY_NONE},
12782 {"%", 200, 2, JimExprOpIntBin, LAZY_NONE},
12783
12784 {"-", 100, 2, JimExprOpBin, LAZY_NONE},
12785 {"+", 100, 2, JimExprOpBin, LAZY_NONE},
12786
12787 {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12788 {">>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12789
12790 {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12791 {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12792
12793 {"<", 80, 2, JimExprOpBin, LAZY_NONE},
12794 {">", 80, 2, JimExprOpBin, LAZY_NONE},
12795 {"<=", 80, 2, JimExprOpBin, LAZY_NONE},
12796 {">=", 80, 2, JimExprOpBin, LAZY_NONE},
12797
12798 {"==", 70, 2, JimExprOpBin, LAZY_NONE},
12799 {"!=", 70, 2, JimExprOpBin, LAZY_NONE},
12800
12801 {"&", 50, 2, JimExprOpIntBin, LAZY_NONE},
12802 {"^", 49, 2, JimExprOpIntBin, LAZY_NONE},
12803 {"|", 48, 2, JimExprOpIntBin, LAZY_NONE},
12804
12805 {"&&", 10, 2, NULL, LAZY_OP},
12806 {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT},
12807 {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12808
12809 {"||", 9, 2, NULL, LAZY_OP},
12810 {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT},
12811 {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12812
12813 {"?", 5, 2, JimExprOpNull, LAZY_OP},
12814 {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
12815 {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12816
12817 {":", 5, 2, JimExprOpNull, LAZY_OP},
12818 {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
12819 {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12820
12821 {"**", 250, 2, JimExprOpBin, LAZY_NONE},
12822
12823 {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE},
12824 {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE},
12825
12826 {"in", 55, 2, JimExprOpStrBin, LAZY_NONE},
12827 {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE},
12828
12829 {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE},
12830 {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE},
12831 {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12832 {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12833
12834
12835
12836 {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12837 {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12838 {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12839 {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12840 {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
12841 {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
12842
12843 #ifdef JIM_MATH_FUNCTIONS
12844 {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12845 {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12846 {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12847 {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12848 {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12849 {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12850 {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12851 {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12852 {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12853 {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12854 {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12855 {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12856 {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12857 {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12858 {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12859 {"pow", 400, 2, JimExprOpBin, LAZY_NONE},
12860 #endif
12861 };
 
 
12862
12863 #define JIM_EXPR_OPERATORS_NUM \
12864 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
12865
12866 static int JimParseExpression(struct JimParserCtx *pc)
@@ -12872,13 +13135,16 @@
12872 }
12873 pc->p++;
12874 pc->len--;
12875 }
12876
 
 
 
 
12877 if (pc->len == 0) {
12878 pc->tstart = pc->tend = pc->p;
12879 pc->tline = pc->linenr;
12880 pc->tt = JIM_TT_EOL;
12881 pc->eof = 1;
12882 return JIM_OK;
12883 }
12884 switch (*(pc->p)) {
@@ -12889,12 +13155,11 @@
12889 pc->tt = JIM_TT_SUBEXPR_END;
12890 goto singlechar;
12891 case ',':
12892 pc->tt = JIM_TT_SUBEXPR_COMMA;
12893 singlechar:
12894 pc->tstart = pc->tend = pc->p;
12895 pc->tline = pc->linenr;
12896 pc->p++;
12897 pc->len--;
12898 break;
12899 case '[':
12900 return JimParseCmd(pc);
@@ -12940,82 +13205,44 @@
12940 return JIM_OK;
12941 }
12942
12943 static int JimParseExprNumber(struct JimParserCtx *pc)
12944 {
12945 int allowdot = 1;
12946 int base = 10;
12947
12948
12949 pc->tt = JIM_TT_EXPR_INT;
12950 pc->tstart = pc->p;
12951 pc->tline = pc->linenr;
12952
12953
12954 if (pc->p[0] == '0') {
12955 switch (pc->p[1]) {
12956 case 'x':
12957 case 'X':
12958 base = 16;
12959 allowdot = 0;
12960 pc->p += 2;
12961 pc->len -= 2;
12962 break;
12963 case 'o':
12964 case 'O':
12965 base = 8;
12966 allowdot = 0;
12967 pc->p += 2;
12968 pc->len -= 2;
12969 break;
12970 case 'b':
12971 case 'B':
12972 base = 2;
12973 allowdot = 0;
12974 pc->p += 2;
12975 pc->len -= 2;
12976 break;
12977 }
12978 }
12979
12980 while (isdigit(UCHAR(*pc->p))
12981 || (base == 16 && isxdigit(UCHAR(*pc->p)))
12982 || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
12983 || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
12984 || (allowdot && *pc->p == '.')
12985 ) {
12986 if (*pc->p == '.') {
12987 allowdot = 0;
12988 pc->tt = JIM_TT_EXPR_DOUBLE;
12989 }
12990 pc->p++;
12991 pc->len--;
12992 if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
12993 || isdigit(UCHAR(pc->p[1])))) {
12994 pc->p += 2;
12995 pc->len -= 2;
12996 pc->tt = JIM_TT_EXPR_DOUBLE;
12997 }
12998 }
12999 pc->tend = pc->p - 1;
 
13000 return JIM_OK;
13001 }
13002
13003 static int JimParseExprIrrational(struct JimParserCtx *pc)
13004 {
13005 const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13006 const char **token;
13007
13008 for (token = Tokens; *token != NULL; token++) {
13009 int len = strlen(*token);
13010
13011 if (strncmp(*token, pc->p, len) == 0) {
13012 pc->tstart = pc->p;
13013 pc->tend = pc->p + len - 1;
13014 pc->p += len;
13015 pc->len -= len;
13016 pc->tline = pc->linenr;
13017 pc->tt = JIM_TT_EXPR_DOUBLE;
13018 return JIM_OK;
13019 }
13020 }
13021 return JIM_ERR;
@@ -13026,20 +13253,18 @@
13026 int i;
13027 int bestIdx = -1, bestLen = 0;
13028
13029
13030 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13031 const char *opname;
13032 int oplen;
13033
13034 opname = Jim_ExprOperators[i].name;
13035 if (opname == NULL) {
13036 continue;
13037 }
13038 oplen = strlen(opname);
13039
13040 if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) {
13041 bestIdx = i + JIM_TT_EXPR_OP;
13042 bestLen = oplen;
13043 }
13044 }
13045 if (bestIdx == -1) {
@@ -13057,15 +13282,13 @@
13057 }
13058 if (*p != '(') {
13059 return JIM_ERR;
13060 }
13061 }
13062 pc->tstart = pc->p;
13063 pc->tend = pc->p + bestLen - 1;
13064 pc->p += bestLen;
13065 pc->len -= bestLen;
13066 pc->tline = pc->linenr;
13067
13068 pc->tt = bestIdx;
13069 return JIM_OK;
13070 }
13071
@@ -13111,12 +13334,12 @@
13111 };
13112
13113
13114 typedef struct ExprByteCode
13115 {
13116 int len;
13117 ScriptToken *token;
 
13118 int inUse;
13119 } ExprByteCode;
13120
13121 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13122 {
@@ -13563,17 +13786,23 @@
13563 }
13564
13565 #ifdef DEBUG_SHOW_EXPR_TOKENS
13566 {
13567 int i;
13568 printf("==== Expr Tokens ====\n");
13569 for (i = 0; i < tokenlist.count; i++) {
13570 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
13571 tokenlist.list[i].len, tokenlist.list[i].token);
13572 }
13573 }
13574 #endif
 
 
 
 
 
 
13575
13576
13577 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
13578
13579
@@ -13620,10 +13849,24 @@
13620 return NULL;
13621 }
13622 }
13623 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13624 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13625
13626 #define JIM_EE_STATICSTACK_LEN 10
13627
13628 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
13629 {
@@ -13643,102 +13886,69 @@
13643 Jim_Obj *objPtr;
13644
13645
13646 switch (expr->len) {
13647 case 1:
13648 if (expr->token[0].type == JIM_TT_EXPR_INT) {
13649 *exprResultPtrPtr = expr->token[0].objPtr;
13650 Jim_IncrRefCount(*exprResultPtrPtr);
13651 return JIM_OK;
13652 }
13653 if (expr->token[0].type == JIM_TT_VAR) {
13654 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13655 if (objPtr) {
13656 *exprResultPtrPtr = objPtr;
13657 Jim_IncrRefCount(*exprResultPtrPtr);
13658 return JIM_OK;
13659 }
13660 }
13661 break;
13662
13663 case 2:
13664 if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13665 jim_wide wideValue;
13666
13667 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13668 if (objPtr && JimIsWide(objPtr)
13669 && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13670 *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13671 Jim_IncrRefCount(*exprResultPtrPtr);
13672 return JIM_OK;
13673 }
13674 }
13675 break;
13676
13677 case 3:
13678 if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13679 || expr->token[1].type == JIM_TT_VAR)) {
13680 switch (expr->token[2].type) {
13681 case JIM_EXPROP_LT:
13682 case JIM_EXPROP_LTE:
13683 case JIM_EXPROP_GT:
13684 case JIM_EXPROP_GTE:
13685 case JIM_EXPROP_NUMEQ:
13686 case JIM_EXPROP_NUMNE:{
13687
13688 jim_wide wideValueA;
13689 jim_wide wideValueB;
13690
13691 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13692 if (objPtr && JimIsWide(objPtr)
13693 && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13694 if (expr->token[1].type == JIM_TT_VAR) {
13695 objPtr =
13696 Jim_GetVariable(interp, expr->token[1].objPtr,
13697 JIM_NONE);
13698 }
13699 else {
13700 objPtr = expr->token[1].objPtr;
13701 }
13702 if (objPtr && JimIsWide(objPtr)
13703 && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13704 int cmpRes;
13705
13706 switch (expr->token[2].type) {
13707 case JIM_EXPROP_LT:
13708 cmpRes = wideValueA < wideValueB;
13709 break;
13710 case JIM_EXPROP_LTE:
13711 cmpRes = wideValueA <= wideValueB;
13712 break;
13713 case JIM_EXPROP_GT:
13714 cmpRes = wideValueA > wideValueB;
13715 break;
13716 case JIM_EXPROP_GTE:
13717 cmpRes = wideValueA >= wideValueB;
13718 break;
13719 case JIM_EXPROP_NUMEQ:
13720 cmpRes = wideValueA == wideValueB;
13721 break;
13722 case JIM_EXPROP_NUMNE:
13723 cmpRes = wideValueA != wideValueB;
13724 break;
13725 default:
13726 cmpRes = 0;
13727 }
13728 *exprResultPtrPtr =
13729 cmpRes ? interp->trueObj : interp->falseObj;
13730 Jim_IncrRefCount(*exprResultPtrPtr);
13731 return JIM_OK;
13732 }
13733 }
13734 }
13735 }
13736 }
13737 break;
13738 }
13739 }
13740 #endif
13741
13742 expr->inUse++;
13743
13744
@@ -13855,16 +14065,16 @@
13855
13856
13857
13858 typedef struct ScanFmtPartDescr
13859 {
13860 char type;
13861 char modifier;
13862 size_t width;
13863 int pos;
13864 char *arg;
13865 char *prefix;
13866 } ScanFmtPartDescr;
13867
13868
13869 typedef struct ScanFmtStringObj
13870 {
@@ -13907,16 +14117,13 @@
13907 memcpy(newVec, srcPtr->internalRep.ptr, size);
13908 dupPtr->internalRep.ptr = newVec;
13909 dupPtr->typePtr = &scanFmtStringObjType;
13910 }
13911
13912 void UpdateStringOfScanFmt(Jim_Obj *objPtr)
13913 {
13914 char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13915
13916 objPtr->bytes = Jim_StrDup(bytes);
13917 objPtr->length = strlen(bytes);
13918 }
13919
13920
13921 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
13922 {
@@ -14126,11 +14333,10 @@
14126 Jim_Obj *tmpObj = NULL;
14127
14128
14129 *valObjPtr = 0;
14130 if (descr->prefix) {
14131
14132 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14133
14134 if (isspace(UCHAR(descr->prefix[i])))
14135 while (pos < strLen && isspace(UCHAR(str[pos])))
14136 ++pos;
@@ -14467,34 +14673,55 @@
14467 }
14468
14469 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14470 {
14471 int retcode;
14472 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14473
14474 if (cmdPtr == NULL) {
14475 return JimUnknown(interp, objc, objv);
 
 
 
14476 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14477 if (interp->evalDepth == interp->maxEvalDepth) {
14478 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14479 return JIM_ERR;
 
14480 }
14481 interp->evalDepth++;
14482
14483
14484 JimIncrCmdRefCount(cmdPtr);
14485 Jim_SetEmptyResult(interp);
14486 if (cmdPtr->isproc) {
14487 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14488 }
14489 else {
14490 interp->cmdPrivData = cmdPtr->u.native.privData;
14491 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14492 }
14493 JimDecrCmdRefCount(interp, cmdPtr);
14494 interp->evalDepth--;
14495
 
 
 
14496 return retcode;
14497 }
14498
14499 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14500 {
@@ -14672,10 +14899,15 @@
14672 objPtr->typePtr = &interpolatedObjType;
14673 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14674 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14675 Jim_IncrRefCount(intv[2]);
14676 }
 
 
 
 
 
14677
14678 s = objPtr->bytes = Jim_Alloc(totlen + 1);
14679 objPtr->length = totlen;
14680 for (i = 0; i < tokens; i++) {
14681 if (intv[i]) {
@@ -14727,10 +14959,14 @@
14727 return JimEvalObjList(interp, scriptObjPtr);
14728 }
14729
14730 Jim_IncrRefCount(scriptObjPtr);
14731 script = Jim_GetScript(interp, scriptObjPtr);
 
 
 
 
14732
14733 Jim_SetEmptyResult(interp);
14734
14735 token = script->token;
14736
@@ -14871,12 +15107,12 @@
14871 }
14872
14873 if (retcode == JIM_OK && argc) {
14874
14875 retcode = JimInvokeCommand(interp, argc, argv);
14876 if (interp->signal_level && interp->sigmask) {
14877
14878 retcode = JIM_SIGNAL;
14879 }
14880 }
14881
14882
@@ -15001,26 +15237,20 @@
15001 retcode = Jim_EvalObj(interp, scriptObj);
15002 }
15003
15004
15005 interp->framePtr = interp->framePtr->parent;
15006 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15007 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15008 }
15009 else {
15010 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15011 }
15012
15013 return retcode;
15014 }
15015 #endif
15016
15017 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
15018 {
15019 Jim_CallFrame *callFramePtr;
15020 int i, d, retcode, optargs;
15021 Jim_Stack *localCommands;
15022 ScriptObj *script;
15023
15024
15025 if (argc - 1 < cmd->u.proc.reqArity ||
15026 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15100,37 +15330,42 @@
15100
15101
15102 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15103
15104 badargset:
 
15105
15106
15107 localCommands = callFramePtr->localCommands;
15108 callFramePtr->localCommands = NULL;
15109
15110 interp->framePtr = interp->framePtr->parent;
15111 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15112 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15113 }
15114 else {
15115 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15116 }
15117
15118
15119 while (retcode == JIM_EVAL) {
15120 Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15121
15122 Jim_IncrRefCount(resultScriptObjPtr);
15123
15124 JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15125
15126 retcode = JimEvalObjList(interp, resultScriptObjPtr);
15127 if (retcode == JIM_RETURN) {
15128 interp->returnLevel++;
15129 }
15130 Jim_DecrRefCount(interp, resultScriptObjPtr);
15131 }
 
 
 
 
 
 
 
 
15132
15133 if (retcode == JIM_RETURN) {
15134 if (--interp->returnLevel <= 0) {
15135 retcode = interp->returnCode;
15136 interp->returnCode = JIM_OK;
@@ -15142,13 +15377,10 @@
15142 Jim_DecrRefCount(interp, interp->errorProc);
15143 interp->errorProc = argv[0];
15144 Jim_IncrRefCount(interp->errorProc);
15145 }
15146
15147
15148 JimDeleteLocalProcs(interp, localCommands);
15149
15150 return retcode;
15151 }
15152
15153 int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
15154 {
@@ -15216,11 +15448,10 @@
15216 Jim_Obj *scriptObjPtr;
15217 Jim_Obj *prevScriptObj;
15218 struct stat sb;
15219 int retcode;
15220 int readlen;
15221 struct JimParseResult result;
15222
15223 if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
15224 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
15225 return JIM_ERR;
15226 }
@@ -15243,31 +15474,13 @@
15243 scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
15244 JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
15245 Jim_IncrRefCount(scriptObjPtr);
15246
15247
15248 if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15249 const char *msg;
15250 char linebuf[20];
15251
15252 switch (result.missing) {
15253 case '[':
15254 msg = "unmatched \"[\"";
15255 break;
15256 case '{':
15257 msg = "missing close-brace";
15258 break;
15259 case '"':
15260 default:
15261 msg = "missing quote";
15262 break;
15263 }
15264
15265 snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15266
15267 Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15268 msg, filename, linebuf);
15269 Jim_DecrRefCount(interp, scriptObjPtr);
15270 return JIM_ERR;
15271 }
15272
15273 prevScriptObj = interp->currentScriptObj;
@@ -15430,11 +15643,11 @@
15430 }
15431
15432 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15433 Jim_HashEntry *he, int type);
15434
15435 #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15436
15437 static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
15438 JimHashtableIteratorCallbackType *callback, int type)
15439 {
15440 Jim_HashEntry *he;
@@ -15446,17 +15659,17 @@
15446 if (he) {
15447 callback(interp, listObjPtr, he, type);
15448 }
15449 }
15450 else {
15451 Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
15452 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
 
15453 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
15454 callback(interp, listObjPtr, he, type);
15455 }
15456 }
15457 Jim_FreeHashTableIterator(htiter);
15458 }
15459 return listObjPtr;
15460 }
15461
15462
@@ -15465,11 +15678,11 @@
15465 #define JIM_CMDLIST_CHANNELS 2
15466
15467 static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15468 Jim_HashEntry *he, int type)
15469 {
15470 Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15471 Jim_Obj *objPtr;
15472
15473 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15474
15475 return;
@@ -15498,11 +15711,11 @@
15498 #define JIM_VARLIST_VALUES 0x1000
15499
15500 static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15501 Jim_HashEntry *he, int type)
15502 {
15503 Jim_Var *varPtr = (Jim_Var *)he->u.val;
15504
15505 if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
15506 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
15507 if (type & JIM_VARLIST_VALUES) {
15508 Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15820,11 +16033,11 @@
15820
15821 expr = JimGetExpression(interp, argv[2]);
15822 incrScript = Jim_GetScript(interp, argv[3]);
15823
15824
15825 if (incrScript->len != 3 || !expr || expr->len != 3) {
15826 goto evalstart;
15827 }
15828
15829 if (incrScript->token[1].type != JIM_TT_ESC ||
15830 expr->token[0].type != JIM_TT_VAR ||
@@ -16043,11 +16256,11 @@
16043 }
16044
16045
16046 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16047 {
16048 int result = JIM_ERR;
16049 int i, numargs;
16050 Jim_ListIter twoiters[2];
16051 Jim_ListIter *iters;
16052 Jim_Obj *script;
16053 Jim_Obj *resultObj;
@@ -16066,13 +16279,16 @@
16066 iters = Jim_Alloc(numargs * sizeof(*iters));
16067 }
16068 for (i = 0; i < numargs; i++) {
16069 JimListIterInit(&iters[i], argv[i + 1]);
16070 if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16071 Jim_SetResultString(interp, "foreach varlist is empty", -1);
16072 return JIM_ERR;
16073 }
 
 
 
 
16074 }
16075
16076 if (doMap) {
16077 resultObj = Jim_NewListObj(interp, NULL, 0);
16078 }
@@ -16385,12 +16601,12 @@
16385 {
16386 Jim_Obj *objPtr, *listObjPtr;
16387 int i;
16388 int idx;
16389
16390 if (argc < 3) {
16391 Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16392 return JIM_ERR;
16393 }
16394 objPtr = argv[1];
16395 Jim_IncrRefCount(objPtr);
16396 for (i = 2; i < argc; i++) {
@@ -16502,14 +16718,13 @@
16502 Jim_IncrRefCount(commandObj);
16503 }
16504
16505 listlen = Jim_ListLength(interp, argv[0]);
16506 for (i = 0; i < listlen; i++) {
16507 Jim_Obj *objPtr;
16508 int eq = 0;
 
16509
16510 Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
16511 switch (opt_match) {
16512 case OPT_EXACT:
16513 eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
16514 break;
16515
@@ -16699,29 +16914,27 @@
16699 if (argc < 3) {
16700 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16701 return JIM_ERR;
16702 }
16703 else if (argc == 3) {
 
16704 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16705 return JIM_ERR;
16706 Jim_SetResult(interp, argv[2]);
16707 return JIM_OK;
16708 }
16709 if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16710 == JIM_ERR)
16711 return JIM_ERR;
16712 return JIM_OK;
16713 }
16714
16715
16716 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
16717 {
16718 static const char * const options[] = {
16719 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16720 };
16721 enum
16722 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
16723 Jim_Obj *resObj;
16724 int i;
16725 int retCode;
16726
16727 struct lsort_info info;
@@ -16732,17 +16945,18 @@
16732 }
16733
16734 info.type = JIM_LSORT_ASCII;
16735 info.order = 1;
16736 info.indexed = 0;
 
16737 info.command = NULL;
16738 info.interp = interp;
16739
16740 for (i = 1; i < (argc - 1); i++) {
16741 int option;
16742
16743 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
16744 != JIM_OK)
16745 return JIM_ERR;
16746 switch (option) {
16747 case OPT_ASCII:
16748 info.type = JIM_LSORT_ASCII;
@@ -16751,16 +16965,22 @@
16751 info.type = JIM_LSORT_NOCASE;
16752 break;
16753 case OPT_INTEGER:
16754 info.type = JIM_LSORT_INTEGER;
16755 break;
 
 
 
16756 case OPT_INCREASING:
16757 info.order = 1;
16758 break;
16759 case OPT_DECREASING:
16760 info.order = -1;
16761 break;
 
 
 
16762 case OPT_COMMAND:
16763 if (i >= (argc - 2)) {
16764 Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
16765 return JIM_ERR;
16766 }
@@ -16870,20 +17090,20 @@
16870 static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
16871 {
16872 if (argc >= 2) {
16873 int retcode;
16874 Jim_CallFrame *savedCallFrame, *targetCallFrame;
16875 Jim_Obj *objPtr;
16876 const char *str;
16877
16878
16879 savedCallFrame = interp->framePtr;
16880
16881
16882 str = Jim_String(argv[1]);
16883 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16884 targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
16885 argc--;
16886 argv++;
16887 }
16888 else {
16889 targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16890,25 +17110,25 @@
16890 }
16891 if (targetCallFrame == NULL) {
16892 return JIM_ERR;
16893 }
16894 if (argc < 2) {
16895 argv--;
16896 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
16897 return JIM_ERR;
16898 }
16899
16900 interp->framePtr = targetCallFrame;
 
 
 
16901 if (argc == 2) {
16902 retcode = Jim_EvalObj(interp, argv[1]);
16903 }
16904 else {
16905 objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16906 Jim_IncrRefCount(objPtr);
16907 retcode = Jim_EvalObj(interp, objPtr);
16908 Jim_DecrRefCount(interp, objPtr);
16909 }
 
16910 interp->framePtr = savedCallFrame;
16911 return retcode;
16912 }
16913 else {
16914 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17019,12 +17239,39 @@
17019 }
17020
17021
17022 static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17023 {
17024 Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17025 return JIM_EVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17026 }
17027
17028 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17029 {
17030 Jim_Obj *cmdList;
@@ -17108,10 +17355,15 @@
17108
17109
17110 static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17111 {
17112 int retcode;
 
 
 
 
 
17113
17114
17115 interp->local++;
17116 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17117 interp->local--;
@@ -17304,11 +17556,11 @@
17304 for (i = 0; i < numMaps; i += 2) {
17305 Jim_Obj *objPtr;
17306 const char *k;
17307 int kl;
17308
17309 Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17310 k = Jim_String(objPtr);
17311 kl = Jim_Utf8Length(interp, objPtr);
17312
17313 if (strLen >= kl && kl) {
17314 int rc;
@@ -17316,12 +17568,11 @@
17316 if (rc == 0) {
17317 if (noMatchStart) {
17318 Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
17319 noMatchStart = NULL;
17320 }
17321 Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17322 Jim_AppendObj(interp, resultObjPtr, objPtr);
17323 str += utf8_index(str, kl);
17324 strLen -= kl;
17325 break;
17326 }
17327 }
@@ -17795,21 +18046,23 @@
17795 if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
17796 sig++;
17797 }
17798
17799 interp->signal_level += sig;
17800 if (interp->signal_level && interp->sigmask) {
17801
17802 exitCode = JIM_SIGNAL;
17803 }
17804 else {
17805 exitCode = Jim_EvalObj(interp, argv[0]);
 
 
17806 }
17807 interp->signal_level -= sig;
17808
17809
17810 if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
17811
17812 return exitCode;
17813 }
17814
17815 if (sig && exitCode == JIM_SIGNAL) {
@@ -17951,25 +18204,24 @@
17951
17952
17953 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17954 {
17955 Jim_Obj *listObjPtr;
17956 Jim_HashTableIterator *htiter;
17957 Jim_HashEntry *he;
17958
17959 listObjPtr = Jim_NewListObj(interp, NULL, 0);
17960
17961 htiter = Jim_GetHashTableIterator(&interp->references);
17962 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
17963 char buf[JIM_REFERENCE_SPACE + 1];
17964 Jim_Reference *refPtr = he->u.val;
17965 const unsigned long *refId = he->key;
17966
17967 JimFormatReference(buf, refPtr, *refId);
17968 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
17969 }
17970 Jim_FreeHashTableIterator(htiter);
17971 Jim_SetResult(interp, listObjPtr);
17972 return JIM_OK;
17973 }
17974 #endif
17975
@@ -17994,11 +18246,11 @@
17994
17995 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
17996 {
17997 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
17998 if (type & JIM_DICTMATCH_VALUES) {
17999 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18000 }
18001 }
18002
18003 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18004 JimDictMatchCallbackType *callback, int type)
@@ -18005,17 +18257,17 @@
18005 {
18006 Jim_HashEntry *he;
18007 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18008
18009
18010 Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
18011 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
 
18012 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18013 callback(interp, listObjPtr, he, type);
18014 }
18015 }
18016 Jim_FreeHashTableIterator(htiter);
18017
18018 return listObjPtr;
18019 }
18020
18021
@@ -18043,21 +18295,65 @@
18043 return -1;
18044 }
18045 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18046 }
18047
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18048
18049 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18050 {
18051 Jim_Obj *objPtr;
18052 int option;
18053 static const char * const options[] = {
18054 "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
 
 
18055 };
18056 enum
18057 {
18058 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
 
 
18059 };
18060
18061 if (argc < 2) {
18062 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18063 return JIM_ERR;
@@ -18068,11 +18364,11 @@
18068 }
18069
18070 switch (option) {
18071 case OPT_GET:
18072 if (argc < 3) {
18073 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18074 return JIM_ERR;
18075 }
18076 if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
18077 JIM_ERRMSG) != JIM_OK) {
18078 return JIM_ERR;
@@ -18085,82 +18381,87 @@
18085 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
18086 return JIM_ERR;
18087 }
18088 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
18089
18090 case OPT_EXIST:
18091 if (argc < 3) {
18092 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18093 return JIM_ERR;
18094 }
18095 Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18096 &objPtr, JIM_ERRMSG) == JIM_OK);
18097 return JIM_OK;
 
 
 
 
 
18098
18099 case OPT_UNSET:
18100 if (argc < 4) {
18101 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
18102 return JIM_ERR;
18103 }
18104 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
 
 
 
18105
18106 case OPT_KEYS:
18107 if (argc != 3 && argc != 4) {
18108 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18109 return JIM_ERR;
18110 }
18111 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18112
18113 case OPT_SIZE: {
18114 int size;
18115
18116 if (argc != 3) {
18117 Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18118 return JIM_ERR;
18119 }
18120
18121 size = Jim_DictSize(interp, argv[2]);
18122 if (size < 0) {
18123 return JIM_ERR;
18124 }
18125 Jim_SetResultInt(interp, size);
18126 return JIM_OK;
18127 }
18128
18129 case OPT_MERGE:
18130 if (argc == 2) {
18131 return JIM_OK;
18132 }
18133 else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18134 return JIM_ERR;
18135 }
18136 else {
18137 return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18138 }
18139
18140 case OPT_WITH:
18141 if (argc < 4) {
18142 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18143 return JIM_ERR;
18144 }
18145 else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18146 return JIM_ERR;
18147 }
18148 else {
18149 return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18150 }
18151
18152 case OPT_CREATE:
18153 if (argc % 2) {
18154 Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
18155 return JIM_ERR;
18156 }
18157 objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
18158 Jim_SetResult(interp, objPtr);
18159 return JIM_OK;
 
 
 
 
 
 
 
18160 }
18161 return JIM_ERR;
 
18162 }
18163
18164
18165 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18166 {
@@ -18218,11 +18519,11 @@
18218 };
18219 enum
18220 { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
18221 INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
18222 INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18223 INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18224 };
18225
18226 #ifdef jim_ext_namespace
18227 int nons = 0;
18228
@@ -18998,11 +19299,11 @@
18998 }
18999 }
19000
19001 static const struct {
19002 const char *name;
19003 Jim_CmdProc cmdProc;
19004 } Jim_CoreCommandsTable[] = {
19005 {"alias", Jim_AliasCoreCommand},
19006 {"set", Jim_SetCoreCommand},
19007 {"unset", Jim_UnsetCoreCommand},
19008 {"puts", Jim_PutsCoreCommand},
@@ -19230,10 +19531,12 @@
19230 }
19231
19232 len += extra;
19233 buf = Jim_Alloc(len + 1);
19234 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
 
 
19235
19236 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19237 }
19238
19239
@@ -19481,344 +19784,373 @@
19481
19482 #include <ctype.h>
19483 #include <string.h>
19484
19485
19486 #define JIM_UTF_MAX 3
19487 #define JIM_INTEGER_SPACE 24
19488 #define MAX_FLOAT_WIDTH 320
19489
19490 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
19491 {
19492 const char *span, *format, *formatEnd, *msg;
19493 int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
19494 static const char * const mixedXPG =
19495 "cannot mix \"%\" and \"%n$\" conversion specifiers";
19496 static const char * const badIndex[2] = {
19497 "not enough arguments for all format specifiers",
19498 "\"%n$\" argument index out of range"
19499 };
19500 int formatLen;
19501 Jim_Obj *resultPtr;
19502
19503 char *num_buffer = NULL;
19504 int num_buffer_size = 0;
19505
19506 span = format = Jim_GetString(fmtObjPtr, &formatLen);
19507 formatEnd = format + formatLen;
19508 resultPtr = Jim_NewStringObj(interp, "", 0);
19509
19510 while (format != formatEnd) {
19511 char *end;
19512 int gotMinus, sawFlag;
19513 int gotPrecision, useShort;
19514 long width, precision;
19515 int newXpg;
19516 int ch;
19517 int step;
19518 int doubleType;
19519 char pad = ' ';
19520 char spec[2*JIM_INTEGER_SPACE + 12];
19521 char *p;
19522
19523 int formatted_chars;
19524 int formatted_bytes;
19525 const char *formatted_buf;
19526
19527 step = utf8_tounicode(format, &ch);
19528 format += step;
19529 if (ch != '%') {
19530 numBytes += step;
19531 continue;
19532 }
19533 if (numBytes) {
19534 Jim_AppendString(interp, resultPtr, span, numBytes);
19535 numBytes = 0;
19536 }
19537
19538
19539 step = utf8_tounicode(format, &ch);
19540 if (ch == '%') {
19541 span = format;
19542 numBytes = step;
19543 format += step;
19544 continue;
19545 }
19546
19547
19548 newXpg = 0;
19549 if (isdigit(ch)) {
19550 int position = strtoul(format, &end, 10);
19551 if (*end == '$') {
19552 newXpg = 1;
19553 objIndex = position - 1;
19554 format = end + 1;
19555 step = utf8_tounicode(format, &ch);
19556 }
19557 }
19558 if (newXpg) {
19559 if (gotSequential) {
19560 msg = mixedXPG;
19561 goto errorMsg;
19562 }
19563 gotXpg = 1;
19564 } else {
19565 if (gotXpg) {
19566 msg = mixedXPG;
19567 goto errorMsg;
19568 }
19569 gotSequential = 1;
19570 }
19571 if ((objIndex < 0) || (objIndex >= objc)) {
19572 msg = badIndex[gotXpg];
19573 goto errorMsg;
19574 }
19575
19576 p = spec;
19577 *p++ = '%';
19578
19579 gotMinus = 0;
19580 sawFlag = 1;
19581 do {
19582 switch (ch) {
19583 case '-':
19584 gotMinus = 1;
19585 break;
19586 case '0':
19587 pad = ch;
19588 break;
19589 case ' ':
19590 case '+':
19591 case '#':
19592 break;
19593 default:
19594 sawFlag = 0;
19595 continue;
19596 }
19597 *p++ = ch;
19598 format += step;
19599 step = utf8_tounicode(format, &ch);
19600 } while (sawFlag);
19601
19602
19603 width = 0;
19604 if (isdigit(ch)) {
19605 width = strtoul(format, &end, 10);
19606 format = end;
19607 step = utf8_tounicode(format, &ch);
19608 } else if (ch == '*') {
19609 if (objIndex >= objc - 1) {
19610 msg = badIndex[gotXpg];
19611 goto errorMsg;
19612 }
19613 if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19614 goto error;
19615 }
19616 if (width < 0) {
19617 width = -width;
19618 if (!gotMinus) {
19619 *p++ = '-';
19620 gotMinus = 1;
19621 }
19622 }
19623 objIndex++;
19624 format += step;
19625 step = utf8_tounicode(format, &ch);
19626 }
19627
19628
19629 gotPrecision = precision = 0;
19630 if (ch == '.') {
19631 gotPrecision = 1;
19632 format += step;
19633 step = utf8_tounicode(format, &ch);
19634 }
19635 if (isdigit(ch)) {
19636 precision = strtoul(format, &end, 10);
19637 format = end;
19638 step = utf8_tounicode(format, &ch);
19639 } else if (ch == '*') {
19640 if (objIndex >= objc - 1) {
19641 msg = badIndex[gotXpg];
19642 goto errorMsg;
19643 }
19644 if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19645 goto error;
19646 }
19647
19648
19649 if (precision < 0) {
19650 precision = 0;
19651 }
19652 objIndex++;
19653 format += step;
19654 step = utf8_tounicode(format, &ch);
19655 }
19656
19657
19658 useShort = 0;
19659 if (ch == 'h') {
19660 useShort = 1;
19661 format += step;
19662 step = utf8_tounicode(format, &ch);
19663 } else if (ch == 'l') {
19664
19665 format += step;
19666 step = utf8_tounicode(format, &ch);
19667 if (ch == 'l') {
19668 format += step;
19669 step = utf8_tounicode(format, &ch);
19670 }
19671 }
19672
19673 format += step;
19674 span = format;
19675
19676
19677 if (ch == 'i') {
19678 ch = 'd';
19679 }
19680
19681 doubleType = 0;
19682
19683 switch (ch) {
19684 case '\0':
19685 msg = "format string ended in middle of field specifier";
19686 goto errorMsg;
19687 case 's': {
19688 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19689 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19690 if (gotPrecision && (precision < formatted_chars)) {
19691
19692 formatted_chars = precision;
19693 formatted_bytes = utf8_index(formatted_buf, precision);
19694 }
19695 break;
19696 }
19697 case 'c': {
19698 jim_wide code;
19699
19700 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19701 goto error;
19702 }
19703
19704 formatted_bytes = utf8_fromunicode(spec, code);
19705 formatted_buf = spec;
19706 formatted_chars = 1;
19707 break;
19708 }
19709
19710 case 'e':
19711 case 'E':
19712 case 'f':
19713 case 'g':
19714 case 'G':
19715 doubleType = 1;
19716
19717 case 'd':
19718 case 'u':
19719 case 'o':
19720 case 'x':
19721 case 'X': {
19722 jim_wide w;
19723 double d;
19724 int length;
19725
19726
19727 if (width) {
19728 p += sprintf(p, "%ld", width);
19729 }
19730 if (gotPrecision) {
19731 p += sprintf(p, ".%ld", precision);
19732 }
19733
19734
19735 if (doubleType) {
19736 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19737 goto error;
19738 }
19739 length = MAX_FLOAT_WIDTH;
19740 }
19741 else {
19742 if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19743 goto error;
19744 }
19745 length = JIM_INTEGER_SPACE;
19746 if (useShort) {
19747 *p++ = 'h';
19748 if (ch == 'd') {
19749 w = (short)w;
19750 }
19751 else {
19752 w = (unsigned short)w;
19753 }
19754 }
19755 else {
19756 *p++ = 'l';
19757 #ifdef HAVE_LONG_LONG
19758 if (sizeof(long long) == sizeof(jim_wide)) {
19759 *p++ = 'l';
19760 }
19761 #endif
19762 }
19763 }
19764
19765 *p++ = (char) ch;
19766 *p = '\0';
19767
19768
19769 if (width > length) {
19770 length = width;
19771 }
19772 if (gotPrecision) {
19773 length += precision;
19774 }
19775
19776
19777 if (num_buffer_size < length + 1) {
19778 num_buffer_size = length + 1;
19779 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19780 }
19781
19782 if (doubleType) {
19783 snprintf(num_buffer, length + 1, spec, d);
19784 }
19785 else {
19786 formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19787 }
19788 formatted_chars = formatted_bytes = strlen(num_buffer);
19789 formatted_buf = num_buffer;
19790 break;
19791 }
19792
19793 default: {
19794
19795 spec[0] = ch;
19796 spec[1] = '\0';
19797 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19798 goto error;
19799 }
19800 }
19801
19802 if (!gotMinus) {
19803 while (formatted_chars < width) {
19804 Jim_AppendString(interp, resultPtr, &pad, 1);
19805 formatted_chars++;
19806 }
19807 }
19808
19809 Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19810
19811 while (formatted_chars < width) {
19812 Jim_AppendString(interp, resultPtr, &pad, 1);
19813 formatted_chars++;
19814 }
19815
19816 objIndex += gotSequential;
19817 }
19818 if (numBytes) {
19819 Jim_AppendString(interp, resultPtr, span, numBytes);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19820 }
19821
19822 Jim_Free(num_buffer);
19823 return resultPtr;
19824
@@ -19827,21 +20159,22 @@
19827 error:
19828 Jim_FreeNewObj(interp, resultPtr);
19829 Jim_Free(num_buffer);
19830 return NULL;
19831 }
 
 
 
19832 #include <stdio.h>
19833 #include <ctype.h>
19834 #include <stdlib.h>
19835 #include <string.h>
19836
19837
19838 #if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19839
19840
19841
19842 #define REG_MAX_PAREN 100
 
19843
19844
19845 #define END 0
19846 #define BOL 1
19847 #define EOL 2
@@ -19850,23 +20183,27 @@
19850 #define ANYBUT 5
19851 #define BRANCH 6
19852 #define BACK 7
19853 #define EXACTLY 8
19854 #define NOTHING 9
19855 #define REP 10
19856 #define REPMIN 11
19857 #define REPX 12
19858 #define REPXMIN 13
19859
19860 #define WORDA 15
19861 #define WORDZ 16
19862 #define OPENNC 19
19863 #define OPEN 20
 
19864
19865 #define CLOSE (OPEN+REG_MAX_PAREN+1)
 
 
 
 
19866 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
19867 #define CLOSENC (CLOSE-1)
19868
19869 #define REG_MAGIC 0xFADED00D
19870
19871
19872 #define OP(preg, p) (preg->program[p])
@@ -19876,15 +20213,15 @@
19876
19877
19878
19879 #define FAIL(R,M) { (R)->err = (M); return (M); }
19880 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19881 #define META "^$.[()|?{+*"
19882
19883 #define HASWIDTH 01
19884 #define SIMPLE 02
19885 #define SPSTART 04
19886 #define WORST 0
19887
19888 #define MAX_REP_COUNT 1000000
19889
19890 static int reg(regex_t *preg, int paren , int *flagp );
@@ -19893,13 +20230,13 @@
19893 static int regatom(regex_t *preg, int *flagp );
19894 static int regnode(regex_t *preg, int op );
19895 static int regnext(regex_t *preg, int p );
19896 static void regc(regex_t *preg, int b );
19897 static int reginsert(regex_t *preg, int op, int size, int opnd );
19898 static void regtail_(regex_t *preg, int p, int val, int line );
19899 static void regoptail(regex_t *preg, int p, int val );
19900 #define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
19901
19902 static int reg_range_find(const int *string, int c);
19903 static const char *str_find(const char *string, int c, int nocase);
19904 static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
19905
@@ -19936,13 +20273,10 @@
19936 FAIL(preg, REG_ERR_NULL_ARGUMENT);
19937
19938
19939 preg->cflags = cflags;
19940 preg->regparse = exp;
19941
19942 preg->program = NULL;
19943 preg->proglen = 0;
19944
19945
19946 preg->proglen = (strlen(exp) + 1) * 5;
19947 preg->program = malloc(preg->proglen * sizeof(int));
19948 if (preg->program == NULL)
@@ -20103,11 +20437,10 @@
20103 {
20104 int ret;
20105 char op;
20106 int next;
20107 int flags;
20108 int chain = 0;
20109 int min;
20110 int max;
20111
20112 ret = regatom(preg, &flags);
20113 if (ret == 0)
@@ -20186,11 +20519,11 @@
20186 if (ISMULT(*preg->regparse)) {
20187 preg->err = REG_ERR_NESTED_COUNT;
20188 return 0;
20189 }
20190
20191 return chain ? chain : ret;
20192 }
20193
20194 static void reg_addrange(regex_t *preg, int lower, int upper)
20195 {
20196 if (lower > upper) {
@@ -20280,10 +20613,11 @@
20280 break;
20281 case 'U':
20282 if ((n = parse_hex(s, 8, ch)) > 0) {
20283 s += n;
20284 }
 
20285 case 'x':
20286 if ((n = parse_hex(s, 2, ch)) > 0) {
20287 s += n;
20288 }
20289 break;
@@ -20528,10 +20862,11 @@
20528
20529 static int regnode(regex_t *preg, int op)
20530 {
20531 reg_grow(preg, 2);
20532
 
20533 preg->program[preg->p++] = op;
20534 preg->program[preg->p++] = 0;
20535
20536
20537 return preg->p - 2;
@@ -20557,11 +20892,11 @@
20557 preg->p += size;
20558
20559 return opnd + size;
20560 }
20561
20562 static void regtail_(regex_t *preg, int p, int val, int line )
20563 {
20564 int scan;
20565 int temp;
20566 int offset;
20567
@@ -20620,36 +20955,16 @@
20620 preg->pmatch = pmatch;
20621 preg->nmatch = nmatch;
20622 preg->start = string;
20623
20624
20625 for (scan = OPERAND(1); scan != 0; ) {
20626 switch (OP(preg, scan)) {
20627 case REP:
20628 case REPMIN:
20629 case REPX:
20630 case REPXMIN:
20631 preg->program[scan + 4] = 0;
20632 scan += 5;
20633 break;
20634
20635 case ANYOF:
20636 case ANYBUT:
20637 case EXACTLY:
20638 scan += 2;
20639 while (preg->program[scan++]) {
20640 }
20641 break;
20642
20643 case END:
20644 scan = 0;
20645 break;
20646
20647 default:
20648 scan += 2;
20649 break;
20650 }
20651 }
20652
20653
20654 if (preg->regmust != 0) {
20655 s = string;
@@ -20901,10 +21216,11 @@
20901
20902 static int regmatch(regex_t *preg, int prog)
20903 {
20904 int scan;
20905 int next;
 
20906
20907 scan = prog;
20908
20909 #ifdef DEBUG
20910 if (scan != 0 && regnarrate)
@@ -20989,27 +21305,24 @@
20989 break;
20990 case NOTHING:
20991 break;
20992 case BACK:
20993 break;
20994 case BRANCH: {
20995 const char *save;
20996
20997 if (OP(preg, next) != BRANCH)
20998 next = OPERAND(scan);
20999 else {
21000 do {
21001 save = preg->reginput;
21002 if (regmatch(preg, OPERAND(scan))) {
21003 return(1);
21004 }
21005 preg->reginput = save;
21006 scan = regnext(preg, scan);
21007 } while (scan != 0 && OP(preg, scan) == BRANCH);
21008 return(0);
21009
21010 }
21011 }
21012 break;
21013 case REP:
21014 case REPMIN:
21015 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21017,43 +21330,35 @@
21017 case REPX:
21018 case REPXMIN:
21019 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21020
21021 case END:
21022 return(1);
21023 break;
21024
21025 case OPENNC:
21026 case CLOSENC:
21027 if (regmatch(preg, next)) {
21028 return 1;
21029 }
21030 return 0;
21031
21032 default:
21033 if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21034 const char *save;
21035
21036 save = preg->reginput;
21037
21038 if (regmatch(preg, next)) {
21039 int no;
21040 if (OP(preg, scan) < CLOSE) {
21041 no = OP(preg, scan) - OPEN;
21042 if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
21043 preg->pmatch[no].rm_so = save - preg->start;
21044 }
21045 }
21046 else {
21047 no = OP(preg, scan) - CLOSE;
21048 if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
21049 preg->pmatch[no].rm_eo = save - preg->start;
21050 }
21051 }
21052 return(1);
21053 } else
21054 return(0);
21055 }
21056 return REG_ERR_INTERNAL;
21057 }
21058
21059 scan = next;
@@ -21132,10 +21437,32 @@
21132 if (OP(preg, p) == BACK)
21133 return(p-offset);
21134 else
21135 return(p+offset);
21136 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21137
21138
21139 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
21140 {
21141 static const char *error_strings[] = {
@@ -21310,19 +21637,24 @@
21310 char *Jim_HistoryGetline(const char *prompt)
21311 {
21312 #ifdef USE_LINENOISE
21313 return linenoise(prompt);
21314 #else
 
21315 char *line = malloc(MAX_LINE_LEN);
21316
21317 fputs(prompt, stdout);
21318 fflush(stdout);
21319
21320 if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
21321 free(line);
21322 return NULL;
21323 }
 
 
 
 
21324 return line;
21325 #endif
21326 }
21327
21328 void Jim_HistoryLoad(const char *filename)
@@ -21373,11 +21705,11 @@
21373 snprintf(history_file, history_len, "%s/.jim_history", home);
21374 Jim_HistoryLoad(history_file);
21375 }
21376 #endif
21377
21378 printf("Welcome to Jim version %d.%d" JIM_NL,
21379 JIM_VERSION / 100, JIM_VERSION % 100);
21380 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
21381
21382 while (1) {
21383 Jim_Obj *scriptObjPtr;
@@ -21485,10 +21817,16 @@
21485 }
21486
21487 Jim_SetVariableStr(interp, "argv", listObj);
21488 Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
21489 }
 
 
 
 
 
 
21490
21491 int main(int argc, char *const argv[])
21492 {
21493 int retcode;
21494 Jim_Interp *interp;
@@ -21502,22 +21840,20 @@
21502 interp = Jim_CreateInterp();
21503 Jim_RegisterCoreCommands(interp);
21504
21505
21506 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21507 Jim_MakeErrorMessage(interp);
21508 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21509 }
21510
21511 Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
21512 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
21513 retcode = Jim_initjimshInit(interp);
21514
21515 if (argc == 1) {
21516 if (retcode == JIM_ERR) {
21517 Jim_MakeErrorMessage(interp);
21518 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21519 }
21520 if (retcode != JIM_EXIT) {
21521 JimSetArgv(interp, 0, NULL);
21522 retcode = Jim_InteractivePrompt(interp);
21523 }
@@ -21534,12 +21870,11 @@
21534 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
21535 JimSetArgv(interp, argc - 2, argv + 2);
21536 retcode = Jim_EvalFile(interp, argv[1]);
21537 }
21538 if (retcode == JIM_ERR) {
21539 Jim_MakeErrorMessage(interp);
21540 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21541 }
21542 }
21543 if (retcode == JIM_EXIT) {
21544 retcode = Jim_GetExitCode(interp);
21545 }
21546
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
2 #define _GNU_SOURCE
3 #define JIM_TCL_COMPAT
4 #define JIM_REFERENCES
5 #define JIM_ANSIC
6 #define JIM_REGEXP
@@ -42,14 +42,19 @@
42 #define HAVE_ISATTY
43 #define HAVE_SYS_TIME_H
44 #define HAVE_DIRENT_H
45 #define HAVE_UNISTD_H
46 #endif
47 #define JIM_VERSION 75
48 #ifndef JIM_WIN32COMPAT_H
49 #define JIM_WIN32COMPAT_H
50
51
52
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56
57
58 #if defined(_WIN32) || defined(WIN32)
59
60 #define HAVE_DLOPEN
@@ -105,17 +110,31 @@
110 } DIR;
111
112 DIR *opendir(const char *name);
113 int closedir(DIR *dir);
114 struct dirent *readdir(DIR *dir);
115
116 #elif defined(__MINGW32__)
117
118 #define strtod __strtod
119
120 #endif
121
122 #endif
123
124 #ifdef __cplusplus
125 }
126 #endif
127
128 #endif
129 #ifndef UTF8_UTIL_H
130 #define UTF8_UTIL_H
131
132 #ifdef __cplusplus
133 extern "C" {
134 #endif
135
136
137
138 #define MAX_UTF8_LEN 4
139
140 int utf8_fromunicode(char *p, unsigned uc);
@@ -124,10 +143,11 @@
143 #include <ctype.h>
144
145
146 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
147 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
148 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
149 #define utf8_upper(C) toupper(C)
150 #define utf8_title(C) toupper(C)
151 #define utf8_lower(C) tolower(C)
152 #define utf8_index(C, I) (I)
153 #define utf8_charlen(C) 1
@@ -134,10 +154,14 @@
154 #define utf8_prev_len(S, L) 1
155
156 #else
157
158 #endif
159
160 #ifdef __cplusplus
161 }
162 #endif
163
164 #endif
165
166 #ifndef __JIM__H
167 #define __JIM__H
@@ -185,12 +209,10 @@
209 #endif
210
211 #define UCHAR(c) ((unsigned char)(c))
212
213
 
 
214 #define JIM_OK 0
215 #define JIM_ERR 1
216 #define JIM_RETURN 2
217 #define JIM_BREAK 3
218 #define JIM_CONTINUE 4
@@ -200,44 +222,34 @@
222 #define JIM_EVAL 7
223
224 #define JIM_MAX_CALLFRAME_DEPTH 1000
225 #define JIM_MAX_EVAL_DEPTH 2000
226
227
228 #define JIM_PRIV_FLAG_SHIFT 20
229
230 #define JIM_NONE 0
231 #define JIM_ERRMSG 1
232 #define JIM_ENUM_ABBREV 2
233 #define JIM_UNSHARED 4
234 #define JIM_MUSTEXIST 8
235
236
237 #define JIM_SUBST_NOVAR 1
238 #define JIM_SUBST_NOCMD 2
239 #define JIM_SUBST_NOESC 4
240 #define JIM_SUBST_FLAG 128
241
 
 
 
 
 
 
242
243 #define JIM_CASESENS 0
244 #define JIM_NOCASE 1
245
246
247 #define JIM_PATH_LEN 1024
248
249
250 #define JIM_NOTUSED(V) ((void) V)
 
 
 
 
251
252 #define JIM_LIBPATH "auto_path"
253 #define JIM_INTERACTIVE "tcl_interactive"
254
255
@@ -267,21 +279,22 @@
279 } Jim_HashTableType;
280
281 typedef struct Jim_HashTable {
282 Jim_HashEntry **table;
283 const Jim_HashTableType *type;
284 void *privdata;
285 unsigned int size;
286 unsigned int sizemask;
287 unsigned int used;
288 unsigned int collisions;
289 unsigned int uniq;
290 } Jim_HashTable;
291
292 typedef struct Jim_HashTableIterator {
293 Jim_HashTable *ht;
 
294 Jim_HashEntry *entry, *nextEntry;
295 int index;
296 } Jim_HashTableIterator;
297
298
299 #define JIM_HT_INITIAL_SIZE 16
300
@@ -290,45 +303,45 @@
303 if ((ht)->type->valDestructor) \
304 (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
305
306 #define Jim_SetHashVal(ht, entry, _val_) do { \
307 if ((ht)->type->valDup) \
308 (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
309 else \
310 (entry)->u.val = (_val_); \
311 } while(0)
312
313 #define Jim_FreeEntryKey(ht, entry) \
314 if ((ht)->type->keyDestructor) \
315 (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
316
317 #define Jim_SetHashKey(ht, entry, _key_) do { \
318 if ((ht)->type->keyDup) \
319 (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
320 else \
321 (entry)->key = (void *)(_key_); \
322 } while(0)
323
324 #define Jim_CompareHashKeys(ht, key1, key2) \
325 (((ht)->type->keyCompare) ? \
326 (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
327 (key1) == (key2))
328
329 #define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
330
331 #define Jim_GetHashEntryKey(he) ((he)->key)
332 #define Jim_GetHashEntryVal(he) ((he)->u.val)
333 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
334 #define Jim_GetHashTableSize(ht) ((ht)->size)
335 #define Jim_GetHashTableUsed(ht) ((ht)->used)
336
337
338 typedef struct Jim_Obj {
 
339 char *bytes;
 
340 const struct Jim_ObjType *typePtr;
341 int refCount;
342 int length;
343
344 union {
345
346 jim_wide wideValue;
347
@@ -342,19 +355,19 @@
355 void *ptr1;
356 void *ptr2;
357 } twoPtrValue;
358
359 struct {
 
360 struct Jim_Var *varPtr;
361 unsigned long callFrameId;
362 int global;
363 } varValue;
364
365 struct {
 
366 struct Jim_Obj *nsObj;
367 struct Jim_Cmd *cmdPtr;
368 unsigned long procEpoch;
369 } cmdValue;
370
371 struct {
372 struct Jim_Obj **ele;
373 int len;
@@ -380,12 +393,12 @@
393 struct Jim_Obj *varNameObjPtr;
394 struct Jim_Obj *indexObjPtr;
395 } dictSubstValue;
396
397 struct {
 
398 void *compre;
399 unsigned flags;
400 } regexpValue;
401 struct {
402 int line;
403 int argc;
404 } scriptLineValue;
@@ -454,21 +467,24 @@
467 struct Jim_CallFrame *next;
468 Jim_Obj *nsObj;
469 Jim_Obj *fileNameObj;
470 int line;
471 Jim_Stack *localCommands;
472 int tailcall;
473 struct Jim_Obj *tailcallObj;
474 struct Jim_Cmd *tailcallCmd;
475 } Jim_CallFrame;
476
477 typedef struct Jim_Var {
478 Jim_Obj *objPtr;
479 struct Jim_CallFrame *linkFramePtr;
480 } Jim_Var;
481
482
483 typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
484 Jim_Obj *const *argv);
485 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
486
487
488
489 typedef struct Jim_Cmd {
490 int inUse;
@@ -475,12 +491,12 @@
491 int isproc;
492 struct Jim_Cmd *prevCmd;
493 union {
494 struct {
495
496 Jim_CmdProc *cmdProc;
497 Jim_DelCmdProc *delProc;
498 void *privData;
499 } native;
500 struct {
501
502 Jim_Obj *argListObjPtr;
@@ -590,15 +606,11 @@
606 Jim_Obj *finalizerCmdNamePtr;
607 char tag[JIM_REFERENCE_TAGLEN+1];
608 } Jim_Reference;
609
610
 
611 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
 
 
 
612 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
613
614 #define JIM_EXPORT
615
616
@@ -609,10 +621,11 @@
621 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
622
623
624 JIM_EXPORT char **Jim_GetEnviron(void);
625 JIM_EXPORT void Jim_SetEnviron(char **env);
626 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
627
628
629 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
630
631
@@ -665,12 +678,10 @@
678
679
680 JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
681 JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
682 JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
 
 
683 JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
684 Jim_Obj *objPtr);
685 JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
686 int *lenPtr);
687 JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -742,13 +753,12 @@
753 JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
754 const char *name, const char *val);
755 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
756 Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
757 Jim_CallFrame *targetCallFrame);
758 JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
759 Jim_Obj *nameObjPtr);
 
760 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
761 Jim_Obj *nameObjPtr, int flags);
762 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
763 Jim_Obj *nameObjPtr, int flags);
764 JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -807,10 +817,11 @@
817 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
818 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
819 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
820 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
821 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
822 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
823
824
825 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
826 int *intPtr);
827
@@ -834,16 +845,10 @@
845 double *doublePtr);
846 JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
847 double doubleValue);
848 JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
849
 
 
 
 
 
 
850
851 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
852 Jim_Obj *const *argv, const char *msg);
853 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
854 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
@@ -877,18 +882,20 @@
882 JIM_EXPORT void Jim_HistoryShow(void);
883
884
885 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
886 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
887 JIM_EXPORT int Jim_IsBigEndian(void);
888
889 #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
890
891
892 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
893 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
894
895
896 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
 
897
898
899 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
900 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
901
@@ -910,16 +917,16 @@
917 #define JIM_MODFLAG_HIDDEN 0x0001
918 #define JIM_MODFLAG_FULLARGV 0x0002
919
920
921
922 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
923
924 typedef struct {
925 const char *cmd;
926 const char *args;
927 jim_subcmd_function *function;
928 short minargs;
929 short maxargs;
930 unsigned short flags;
931 } jim_subcmd_type;
932
@@ -936,22 +943,16 @@
943
944 #endif
945 #ifndef JIMREGEXP_H
946 #define JIMREGEXP_H
947
948
949 #ifdef __cplusplus
950 extern "C" {
951 #endif
952
 
 
 
 
 
 
953 #include <stdlib.h>
 
954
955 typedef struct {
956 int rm_so;
957 int rm_eo;
958 } regmatch_t;
@@ -1020,10 +1021,12 @@
1021 int regcomp(regex_t *preg, const char *regex, int cflags);
1022 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
1023 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
1024 void regfree(regex_t *preg);
1025
1026 #ifdef __cplusplus
1027 }
1028 #endif
1029
1030 #endif
1031 int Jim_bootstrapInit(Jim_Interp *interp)
1032 {
@@ -1086,10 +1089,15 @@
1089 "\n"
1090 "package require readdir\n"
1091 "\n"
1092 "\n"
1093 "proc glob.globdir {dir pattern} {\n"
1094 " if {[file exists $dir/$pattern]} {\n"
1095 "\n"
1096 " return $pattern\n"
1097 " }\n"
1098 "\n"
1099 " set result {}\n"
1100 " set files [readdir $dir]\n"
1101 " lappend files . ..\n"
1102 "\n"
1103 " foreach name $files {\n"
@@ -1268,10 +1276,12 @@
1276 {
1277 if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
1278 return JIM_ERR;
1279
1280 return Jim_EvalSource(interp, "stdlib.tcl", 1,
1281 "\n"
1282 "\n"
1283 "\n"
1284 "proc lambda {arglist args} {\n"
1285 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1286 "}\n"
1287 "\n"
@@ -1297,46 +1307,48 @@
1307 "}\n"
1308 "\n"
1309 "\n"
1310 "\n"
1311 "\n"
1312 "proc stacktrace {{skip 0}} {\n"
1313 " set trace {}\n"
1314 " incr skip\n"
1315 " foreach level [range $skip [info level]] {\n"
1316 " lappend trace {*}[info frame -$level]\n"
1317 " }\n"
1318 " return $trace\n"
1319 "}\n"
1320 "\n"
1321 "\n"
1322 "proc stackdump {stacktrace} {\n"
1323 " set lines {}\n"
 
1324 " foreach {l f p} [lreverse $stacktrace] {\n"
1325 " set line {}\n"
 
 
 
1326 " if {$p ne \"\"} {\n"
1327 " append line \"in procedure '$p' \"\n"
1328 " if {$f ne \"\"} {\n"
1329 " append line \"called \"\n"
1330 " }\n"
1331 " }\n"
1332 " if {$f ne \"\"} {\n"
1333 " append line \"at file \\\"$f\\\", line $l\"\n"
1334 " }\n"
1335 " if {$line ne \"\"} {\n"
1336 " lappend lines $line\n"
1337 " }\n"
1338 " }\n"
1339 " join $lines \\n\n"
1340 "}\n"
1341 "\n"
1342 "\n"
1343 "\n"
1344 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1345 " if {$stacktrace eq \"\"} {\n"
1346 "\n"
1347 " set stacktrace [info stacktrace]\n"
1348 "\n"
1349 " lappend stacktrace {*}[stacktrace 1]\n"
1350 " }\n"
1351 " lassign $stacktrace p f l\n"
1352 " if {$f ne \"\"} {\n"
1353 " set result \"Runtime Error: $f:$l: \"\n"
1354 " }\n"
@@ -1363,25 +1375,46 @@
1375 " }\n"
1376 " return \"\"\n"
1377 "}\n"
1378 "\n"
1379 "\n"
1380 "proc {dict with} {&dictVar {args key} script} {\n"
 
1381 " set keys {}\n"
1382 " foreach {n v} [dict get $dictVar {*}$key] {\n"
1383 " upvar $n var_$n\n"
1384 " set var_$n $v\n"
1385 " lappend keys $n\n"
1386 " }\n"
1387 " catch {uplevel 1 $script} msg opts\n"
1388 " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1389 " foreach n $keys {\n"
1390 " if {[info exists var_$n]} {\n"
1391 " dict set dictVar {*}$key $n [set var_$n]\n"
1392 " } else {\n"
1393 " dict unset dictVar {*}$key $n\n"
1394 " }\n"
1395 " }\n"
1396 " }\n"
1397 " return {*}$opts $msg\n"
1398 "}\n"
1399 "\n"
1400 "\n"
1401 "proc {dict update} {&varName args script} {\n"
1402 " set keys {}\n"
1403 " foreach {n v} $args {\n"
1404 " upvar $v var_$v\n"
1405 " if {[dict exists $varName $n]} {\n"
1406 " set var_$v [dict get $varName $n]\n"
1407 " }\n"
1408 " }\n"
1409 " catch {uplevel 1 $script} msg opts\n"
1410 " if {[info exists varName]} {\n"
1411 " foreach {n v} $args {\n"
1412 " if {[info exists var_$v]} {\n"
1413 " dict set varName $n [set var_$v]\n"
1414 " } else {\n"
1415 " dict unset varName $n\n"
1416 " }\n"
1417 " }\n"
1418 " }\n"
1419 " return {*}$opts $msg\n"
1420 "}\n"
@@ -1396,10 +1429,69 @@
1429 " dict set dict $k $v\n"
1430 " }\n"
1431 " }\n"
1432 " return $dict\n"
1433 "}\n"
1434 "\n"
1435 "proc {dict replace} {dictionary {args {key value}}} {\n"
1436 " if {[llength ${key value}] % 2} {\n"
1437 " tailcall {dict replace}\n"
1438 " }\n"
1439 " tailcall dict merge $dictionary ${key value}\n"
1440 "}\n"
1441 "\n"
1442 "\n"
1443 "proc {dict lappend} {varName key {args value}} {\n"
1444 " upvar $varName dict\n"
1445 " if {[exists dict] && [dict exists $dict $key]} {\n"
1446 " set list [dict get $dict $key]\n"
1447 " }\n"
1448 " lappend list {*}$value\n"
1449 " dict set dict $key $list\n"
1450 "}\n"
1451 "\n"
1452 "\n"
1453 "proc {dict append} {varName key {args value}} {\n"
1454 " upvar $varName dict\n"
1455 " if {[exists dict] && [dict exists $dict $key]} {\n"
1456 " set str [dict get $dict $key]\n"
1457 " }\n"
1458 " append str {*}$value\n"
1459 " dict set dict $key $str\n"
1460 "}\n"
1461 "\n"
1462 "\n"
1463 "proc {dict incr} {varName key {increment 1}} {\n"
1464 " upvar $varName dict\n"
1465 " if {[exists dict] && [dict exists $dict $key]} {\n"
1466 " set value [dict get $dict $key]\n"
1467 " }\n"
1468 " incr value $increment\n"
1469 " dict set dict $key $value\n"
1470 "}\n"
1471 "\n"
1472 "\n"
1473 "proc {dict remove} {dictionary {args key}} {\n"
1474 " foreach k $key {\n"
1475 " dict unset dictionary $k\n"
1476 " }\n"
1477 " return $dictionary\n"
1478 "}\n"
1479 "\n"
1480 "\n"
1481 "proc {dict values} {dictionary {pattern *}} {\n"
1482 " dict keys [lreverse $dictionary] $pattern\n"
1483 "}\n"
1484 "\n"
1485 "\n"
1486 "proc {dict for} {vars dictionary script} {\n"
1487 " if {[llength $vars] != 2} {\n"
1488 " return -code error \"must have exactly two variable names\"\n"
1489 " }\n"
1490 " dict size $dictionary\n"
1491 " tailcall foreach $vars $dictionary $script\n"
1492 "}\n"
1493 );
1494 }
1495 int Jim_tclcompatInit(Jim_Interp *interp)
1496 {
1497 if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1410,12 +1502,14 @@
1502 "\n"
1503 "\n"
1504 "\n"
1505 "\n"
1506 "\n"
1507 "\n"
1508 "\n"
1509 "set env [env]\n"
1510 "\n"
1511 "\n"
1512 "if {[info commands stdout] ne \"\"} {\n"
1513 "\n"
1514 " foreach p {gets flush close eof seek tell} {\n"
1515 " proc $p {chan args} {p} {\n"
@@ -1462,51 +1556,10 @@
1556 " }\n"
1557 " }\n"
1558 " }\n"
1559 "}\n"
1560 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1561 "\n"
1562 "proc fileevent {args} {\n"
1563 " tailcall {*}$args\n"
1564 "}\n"
1565 "\n"
@@ -1536,13 +1589,25 @@
1589 " error \"bad option \\\"$force\\\": should be -force\"\n"
1590 " }\n"
1591 "\n"
1592 " set in [open $source]\n"
1593 "\n"
1594 " if {[file exists $target]} {\n"
1595 " if {$force eq \"\"} {\n"
1596 " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1597 " }\n"
1598 "\n"
1599 " if {$source eq $target} {\n"
1600 " return\n"
1601 " }\n"
1602 "\n"
1603 "\n"
1604 " file stat $source ss\n"
1605 " file stat $target ts\n"
1606 " if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n"
1607 " return\n"
1608 " }\n"
1609 " }\n"
1610 " set out [open $target w]\n"
1611 " $in copyto $out\n"
1612 " $out close\n"
1613 " } on error {msg opts} {\n"
@@ -1587,18 +1652,18 @@
1652 " error $error\n"
1653 " }\n"
1654 "}\n"
1655 "\n"
1656 "\n"
1657 "local proc pid {{channelId {}}} {\n"
1658 " if {$channelId eq \"\"} {\n"
1659 " tailcall upcall pid\n"
1660 " }\n"
1661 " if {[catch {$channelId tell}]} {\n"
1662 " return -code error \"can not find channel named \\\"$channelId\\\"\"\n"
1663 " }\n"
1664 " if {[catch {$channelId pid} pids]} {\n"
1665 " return \"\"\n"
1666 " }\n"
1667 " return $pids\n"
1668 "}\n"
1669 "\n"
@@ -1687,23 +1752,25 @@
1752 "}\n"
1753 );
1754 }
1755
1756
 
1757 #include <stdio.h>
1758 #include <string.h>
1759 #include <errno.h>
1760 #include <fcntl.h>
1761 #ifdef HAVE_UNISTD_H
1762 #include <unistd.h>
1763 #include <sys/stat.h>
1764 #endif
1765
1766
1767 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1768 #include <sys/socket.h>
1769 #include <netinet/in.h>
1770 #include <arpa/inet.h>
1771 #include <netdb.h>
 
1772 #ifdef HAVE_SYS_UN_H
1773 #include <sys/un.h>
1774 #endif
1775 #else
1776 #define JIM_ANSIC
@@ -1735,15 +1802,12 @@
1802 typedef struct AioFile
1803 {
1804 FILE *fp;
1805 Jim_Obj *filename;
1806 int type;
1807 int openFlags;
1808 int fd;
 
 
 
1809 Jim_Obj *rEvent;
1810 Jim_Obj *wEvent;
1811 Jim_Obj *eEvent;
1812 int addr_family;
1813 } AioFile;
@@ -1767,28 +1831,21 @@
1831 {
1832 AioFile *af = privData;
1833
1834 JIM_NOTUSED(interp);
1835
 
 
 
 
1836 Jim_DecrRefCount(interp, af->filename);
1837
1838 #ifdef jim_ext_eventloop
1839
1840 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1841 #endif
1842
1843 if (!(af->openFlags & AIO_KEEPOPEN)) {
1844 fclose(af->fp);
1845 }
1846
 
 
 
1847 Jim_Free(af);
1848 }
1849
1850 static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
1851 {
@@ -2035,12 +2092,31 @@
2092 return JIM_OK;
2093 }
2094
2095 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2096 {
2097 if (argc == 3) {
2098 #if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2099 static const char * const options[] = { "r", "w", NULL };
2100 enum { OPT_R, OPT_W, };
2101 int option;
2102 AioFile *af = Jim_CmdPrivData(interp);
2103
2104 if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
2105 return JIM_ERR;
2106 }
2107 if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
2108 return JIM_OK;
2109 }
2110 JimAioSetError(interp, NULL);
2111 #else
2112 Jim_SetResultString(interp, "async close not supported", -1);
2113 #endif
2114 return JIM_ERR;
2115 }
2116
2117 return Jim_DeleteCommand(interp, Jim_String(argv[0]));
2118 }
2119
2120 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2121 {
2122 AioFile *af = Jim_CmdPrivData(interp);
@@ -2087,11 +2163,11 @@
2163 #ifdef O_NDELAY
2164 static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2165 {
2166 AioFile *af = Jim_CmdPrivData(interp);
2167
2168 int fmode = fcntl(af->fd, F_GETFL);
2169
2170 if (argc) {
2171 long nb;
2172
2173 if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2101,12 +2177,11 @@
2177 fmode |= O_NDELAY;
2178 }
2179 else {
2180 fmode &= ~O_NDELAY;
2181 }
2182 (void)fcntl(af->fd, F_SETFL, fmode);
 
2183 }
2184 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2185 return JIM_OK;
2186 }
2187 #endif
@@ -2147,27 +2222,26 @@
2222 }
2223
2224 #ifdef jim_ext_eventloop
2225 static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
2226 {
2227 Jim_Obj **objPtrPtr = clientData;
2228
2229 Jim_DecrRefCount(interp, *objPtrPtr);
2230 *objPtrPtr = NULL;
2231 }
2232
2233 static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
2234 {
2235 Jim_Obj **objPtrPtr = clientData;
2236
2237 return Jim_EvalObjBackground(interp, *objPtrPtr);
2238 }
2239
2240 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2241 int argc, Jim_Obj * const *argv)
2242 {
 
 
2243 if (argc == 0) {
2244
2245 if (*scriptHandlerObj) {
2246 Jim_SetResult(interp, *scriptHandlerObj);
2247 }
@@ -2174,27 +2248,25 @@
2248 return JIM_OK;
2249 }
2250
2251 if (*scriptHandlerObj) {
2252
2253 Jim_DeleteFileHandler(interp, af->fp, mask);
 
2254 }
2255
2256
2257 if (Jim_Length(argv[0]) == 0) {
 
2258
2259 return JIM_OK;
2260 }
2261
2262
2263 Jim_IncrRefCount(argv[0]);
2264 *scriptHandlerObj = argv[0];
2265
2266 Jim_CreateFileHandler(interp, af->fp, mask,
2267 JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
2268
2269 return JIM_OK;
2270 }
2271
2272 static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -2213,11 +2285,11 @@
2285
2286 static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2287 {
2288 AioFile *af = Jim_CmdPrivData(interp);
2289
2290 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2291 }
2292 #endif
2293
2294 static const jim_subcmd_type aio_command_table[] = {
2295 { "read",
@@ -2268,14 +2340,14 @@
2340 0,
2341 0,
2342
2343 },
2344 { "close",
2345 "?r(ead)|w(rite)?",
2346 aio_cmd_close,
2347 0,
2348 1,
2349 JIM_MODFLAG_FULLARGV,
2350
2351 },
2352 { "seek",
2353 "offset ?start|current|end",
@@ -2347,30 +2419,32 @@
2419
2420 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
2421 Jim_Obj *const *argv)
2422 {
2423 const char *mode;
 
2424
2425 if (argc != 2 && argc != 3) {
2426 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
2427 return JIM_ERR;
2428 }
2429
2430 mode = (argc == 3) ? Jim_String(argv[2]) : "r";
 
2431
2432 #ifdef jim_ext_tclcompat
2433 {
2434 const char *filename = Jim_String(argv[1]);
2435
2436
2437 if (*filename == '|') {
2438 Jim_Obj *evalObj[3];
2439
2440 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2441 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2442 evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2443
2444 return Jim_EvalObjVector(interp, 3, evalObj);
2445 }
2446 }
2447 #endif
2448 return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
2449 }
2450
@@ -2377,70 +2451,129 @@
2451 static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
2452 const char *hdlfmt, int family, const char *mode)
2453 {
2454 AioFile *af;
2455 char buf[AIO_CMD_LEN];
2456 int openFlags = 0;
2457
2458 if (fh) {
2459 filename = Jim_NewStringObj(interp, hdlfmt, -1);
2460 openFlags = AIO_KEEPOPEN;
2461 }
2462
2463 Jim_IncrRefCount(filename);
2464
2465 if (fh == NULL) {
2466 #if !defined(JIM_ANSIC)
2467 if (fd >= 0) {
 
 
2468 fh = fdopen(fd, mode);
2469 }
2470 else
2471 #endif
2472 fh = fopen(Jim_String(filename), mode);
 
2473
2474 if (fh == NULL) {
2475 JimAioSetError(interp, filename);
2476 #if !defined(JIM_ANSIC)
2477 if (fd >= 0) {
2478 close(fd);
2479 }
2480 #endif
2481 Jim_DecrRefCount(interp, filename);
2482 return JIM_ERR;
2483 }
 
 
 
2484 }
2485
2486
2487 af = Jim_Alloc(sizeof(*af));
2488 memset(af, 0, sizeof(*af));
2489 af->fp = fh;
2490 af->fd = fileno(fh);
2491 af->filename = filename;
2492 #ifdef FD_CLOEXEC
2493 if ((openFlags & AIO_KEEPOPEN) == 0) {
2494 (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2495 }
2496 #endif
2497 af->openFlags = openFlags;
 
 
 
2498 af->addr_family = family;
2499 snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
2500 Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
2501
2502 Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
2503
2504 return JIM_OK;
2505 }
2506
2507 static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
2508 const char *hdlfmt, int family, const char *mode[2])
2509 {
2510 if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
2511 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2512 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2513
2514 if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
2515 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2516 Jim_SetResult(interp, objPtr);
2517 return JIM_OK;
2518 }
2519 }
2520
2521
2522 close(p[0]);
2523 close(p[1]);
2524 JimAioSetError(interp, NULL);
2525 return JIM_ERR;
2526 }
2527
2528
2529 int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2530 {
2531 #ifdef HAVE_MKSTEMP
2532 int fd;
2533 mode_t mask;
2534 Jim_Obj *filenameObj;
2535
2536 if (template == NULL) {
2537 const char *tmpdir = getenv("TMPDIR");
2538 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2539 tmpdir = "/tmp/";
2540 }
2541 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2542 if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2543 Jim_AppendString(interp, filenameObj, "/", 1);
2544 }
2545 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2546 }
2547 else {
2548 filenameObj = Jim_NewStringObj(interp, template, -1);
2549 }
2550
2551 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2552
2553
2554 fd = mkstemp(filenameObj->bytes);
2555 umask(mask);
2556 if (fd < 0) {
2557 Jim_SetResultString(interp, "Failed to create tempfile", -1);
2558 Jim_FreeNewObj(interp, filenameObj);
2559 return -1;
2560 }
2561
2562 Jim_SetResult(interp, filenameObj);
2563 return fd;
2564 #else
2565 Jim_SetResultString(interp, "tempfile not supported", -1);
2566 return -1;
2567 #endif
2568 }
2569
2570 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
2571 {
2572 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2573
2574
2575 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2576 return ((AioFile *) cmdPtr->u.native.privData)->fp;
2577 }
2578 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2579 return NULL;
@@ -2461,11 +2594,10 @@
2594 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2595 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2596
2597 return JIM_OK;
2598 }
 
2599
2600 #include <errno.h>
2601 #include <stdio.h>
2602 #include <string.h>
2603
@@ -2497,28 +2629,29 @@
2629 return JIM_OK;
2630 }
2631 Jim_SetResultString(interp, strerror(errno), -1);
2632 return JIM_ERR;
2633 }
2634 else {
2635 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2636
2637 while ((entryPtr = readdir(dirPtr)) != NULL) {
2638 if (entryPtr->d_name[0] == '.') {
2639 if (entryPtr->d_name[1] == '\0') {
2640 continue;
2641 }
2642 if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2643 continue;
2644 }
2645 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));
2646 }
2647 closedir(dirPtr);
2648
2649 Jim_SetResult(interp, listObj);
2650
2651 return JIM_OK;
2652 }
2653 }
2654
2655 int Jim_readdirInit(Jim_Interp *interp)
2656 {
2657 if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2529,10 +2662,14 @@
2662 }
2663
2664 #include <stdlib.h>
2665 #include <string.h>
2666
2667 #if defined(JIM_REGEXP)
2668 #else
2669 #include <regex.h>
2670 #endif
2671
2672 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2673 {
2674 regfree(objPtr->internalRep.regexpValue.compre);
2675 Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3076,58 +3213,61 @@
3213 }
3214 #endif
3215 return "unknown";
3216 }
3217
3218 static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)
3219 {
3220 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));
3221 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3222 }
3223
3224 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3225 {
3226
3227 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3228
3229 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3230 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3231 AppendStatElement(interp, listObj, "mode", sb->st_mode);
3232 AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
3233 AppendStatElement(interp, listObj, "uid", sb->st_uid);
3234 AppendStatElement(interp, listObj, "gid", sb->st_gid);
3235 AppendStatElement(interp, listObj, "size", sb->st_size);
3236 AppendStatElement(interp, listObj, "atime", sb->st_atime);
3237 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3238 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3239 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3240 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3241
3242
3243 if (varName) {
3244 Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3245 if (objPtr) {
3246 if (Jim_DictSize(interp, objPtr) < 0) {
3247
3248 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3249 Jim_FreeNewObj(interp, listObj);
3250 return JIM_ERR;
3251 }
3252
3253 if (Jim_IsShared(objPtr))
3254 objPtr = Jim_DuplicateObj(interp, objPtr);
3255
3256
3257 Jim_ListAppendList(interp, objPtr, listObj);
3258 Jim_DictSize(interp, objPtr);
3259 Jim_InvalidateStringRep(objPtr);
3260
3261 Jim_FreeNewObj(interp, listObj);
3262 listObj = objPtr;
3263 }
3264 Jim_SetVariable(interp, varName, listObj);
3265 }
3266
3267
3268 Jim_SetResult(interp, listObj);
3269
3270 return JIM_OK;
3271 }
3272
3273 static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3282,14 +3422,11 @@
3422 return JIM_OK;
3423 }
3424
3425 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
3426 {
3427 Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
 
 
 
3428
3429 return JIM_OK;
3430 }
3431
3432 static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3305,10 +3442,11 @@
3442 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3443 {
3444 #ifdef X_OK
3445 return file_access(interp, argv[0], X_OK);
3446 #else
3447
3448 Jim_SetResultBool(interp, 1);
3449 return JIM_OK;
3450 #endif
3451 }
3452
@@ -3409,33 +3547,21 @@
3547 argv++;
3548 }
3549 return JIM_OK;
3550 }
3551
 
3552 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3553 {
3554 int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3555
3556 if (fd < 0) {
 
 
 
 
 
 
 
 
 
3557 return JIM_ERR;
3558 }
3559 close(fd);
3560
 
3561 return JIM_OK;
3562 }
 
3563
3564 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3565 {
3566 const char *source;
3567 const char *dest;
@@ -3477,14 +3603,11 @@
3603 return JIM_ERR;
3604 }
3605 return JIM_OK;
3606 }
3607
3608 #ifdef HAVE_LSTAT
 
 
 
3609 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
3610 {
3611 const char *path = Jim_String(filename);
3612
3613 if (lstat(path, sb) == -1) {
@@ -3491,10 +3614,13 @@
3614 Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
3615 return JIM_ERR;
3616 }
3617 return JIM_OK;
3618 }
3619 #else
3620 #define file_lstat file_stat
3621 #endif
3622
3623 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3624 {
3625 struct stat sb;
3626
@@ -3619,28 +3745,32 @@
3745 }
3746 Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
3747 return JIM_OK;
3748 }
3749
3750 #ifdef HAVE_LSTAT
3751 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3752 {
3753 struct stat sb;
3754
3755 if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
3756 return JIM_ERR;
3757 }
3758 return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
3759 }
3760 #else
3761 #define file_cmd_lstat file_cmd_stat
3762 #endif
3763
3764 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3765 {
3766 struct stat sb;
3767
3768 if (file_stat(interp, argv[0], &sb) != JIM_OK) {
3769 return JIM_ERR;
3770 }
3771 return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
3772 }
3773
3774 static const jim_subcmd_type file_command_table[] = {
3775 { "atime",
3776 "name",
@@ -3745,19 +3875,17 @@
3875 file_cmd_mkdir,
3876 1,
3877 -1,
3878
3879 },
 
3880 { "tempfile",
3881 "?template?",
3882 file_cmd_tempfile,
3883 0,
3884 1,
3885
3886 },
 
3887 { "rename",
3888 "?-force? source dest",
3889 file_cmd_rename,
3890 2,
3891 3,
@@ -3778,20 +3906,20 @@
3906 1,
3907 1,
3908
3909 },
3910 { "stat",
3911 "name ?var?",
3912 file_cmd_stat,
3913 1,
3914 2,
3915
3916 },
3917 { "lstat",
3918 "name ?var?",
3919 file_cmd_lstat,
3920 1,
3921 2,
3922
3923 },
3924 { "type",
3925 "name",
@@ -3847,15 +3975,15 @@
3975 return JIM_OK;
3976 }
3977
3978 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3979 {
3980 char *cwd = Jim_Alloc(MAXPATHLEN);
 
3981
3982 if (getcwd(cwd, MAXPATHLEN) == NULL) {
3983 Jim_SetResultString(interp, "Failed to get pwd", -1);
3984 Jim_Free(cwd);
3985 return JIM_ERR;
3986 }
3987 #if defined(__MINGW32__) || defined(_MSC_VER)
3988 {
3989
@@ -3866,11 +3994,11 @@
3994 }
3995 #endif
3996
3997 Jim_SetResultString(interp, cwd, -1);
3998
3999 Jim_Free(cwd);
4000 return JIM_OK;
4001 }
4002
4003 int Jim_fileInit(Jim_Interp *interp)
4004 {
@@ -3935,10 +4063,11 @@
4063
4064 int Jim_execInit(Jim_Interp *interp)
4065 {
4066 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4067 return JIM_ERR;
4068
4069 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
4070 return JIM_OK;
4071 }
4072 #else
4073
@@ -3978,10 +4107,11 @@
4107 static int JimErrno(void);
4108 #else
4109 #include <unistd.h>
4110 #include <fcntl.h>
4111 #include <sys/wait.h>
4112 #include <sys/stat.h>
4113
4114 typedef int fdtype;
4115 typedef int pidtype;
4116 #define JimPipe pipe
4117 #define JimErrno() errno
@@ -4005,11 +4135,11 @@
4135 static void JimRestoreEnv(char **env);
4136 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4137 pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4138 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
4139 static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
4140 static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
4141 static fdtype JimOpenForWrite(const char *filename, int append);
4142 static int JimRewindFd(fdtype fd);
4143
4144 static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
4145 {
@@ -4052,23 +4182,12 @@
4182 Jim_RemoveTrailingNewline(strObj);
4183 fclose(fh);
4184 return JIM_OK;
4185 }
4186
 
 
 
 
 
 
 
 
 
 
4187 static char **JimBuildEnv(Jim_Interp *interp)
4188 {
 
4189 int i;
4190 int size;
4191 int num;
4192 int n;
4193 char **envptr;
@@ -4082,10 +4201,11 @@
4201
4202
4203
4204 num = Jim_ListLength(interp, objPtr);
4205 if (num % 2) {
4206
4207 num--;
4208 }
4209 size = Jim_Length(objPtr) + 2;
4210
4211 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4108,22 +4228,17 @@
4228 }
4229 envptr[n] = NULL;
4230 *envdata = 0;
4231
4232 return envptr;
 
 
 
4233 }
4234
4235 static void JimFreeEnv(char **env, char **original_environ)
4236 {
 
4237 if (env != original_environ) {
4238 Jim_Free(env);
4239 }
 
4240 }
4241
4242 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
4243 {
4244 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4172,19 +4287,19 @@
4287 }
4288
4289
4290 struct WaitInfo
4291 {
4292 pidtype pid;
4293 int status;
4294 int flags;
4295 };
4296
4297 struct WaitInfoTable {
4298 struct WaitInfo *info;
4299 int size;
4300 int used;
4301 };
4302
4303
4304 #define WI_DETACHED 2
4305
@@ -4207,14 +4322,12 @@
4322 return table;
4323 }
4324
4325 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4326 {
4327 fdtype outputId;
4328 fdtype errorId;
 
 
4329 pidtype *pidPtr;
4330 int numPids, result;
4331
4332 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4333 Jim_Obj *listObj;
@@ -4261,26 +4374,32 @@
4374
4375 static void JimReapDetachedPids(struct WaitInfoTable *table)
4376 {
4377 struct WaitInfo *waitPtr;
4378 int count;
4379 int dest;
4380
4381 if (!table) {
4382 return;
4383 }
4384
4385 waitPtr = table->info;
4386 dest = 0;
4387 for (count = table->used; count > 0; waitPtr++, count--) {
4388 if (waitPtr->flags & WI_DETACHED) {
4389 int status;
4390 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4391 if (pid == waitPtr->pid) {
4392
 
 
4393 table->used--;
4394 continue;
4395 }
4396 }
4397 if (waitPtr != &table->info[dest]) {
4398 table->info[dest] = *waitPtr;
4399 }
4400 dest++;
4401 }
4402 }
4403
4404 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4405 {
@@ -4302,11 +4421,10 @@
4421 }
4422
4423
4424 return JIM_BAD_PID;
4425 }
 
4426
4427 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4428 {
4429 int j;
4430 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4347,10 +4465,11 @@
4465 int cmdCount; /* Count of number of distinct commands
4466 * found in argc/argv. */
4467 const char *input = NULL; /* Describes input for pipeline, depending
4468 * on "inputFile". NULL means take input
4469 * from stdin/pipe. */
4470 int input_len = 0;
4471
4472 #define FILE_NAME 0
4473 #define FILE_APPEND 1
4474 #define FILE_HANDLE 2
4475 #define FILE_TEXT 3
@@ -4412,19 +4531,20 @@
4531 if (arg[0] == '<') {
4532 inputFile = FILE_NAME;
4533 input = arg + 1;
4534 if (*input == '<') {
4535 inputFile = FILE_TEXT;
4536 input_len = Jim_Length(argv[i]) - 2;
4537 input++;
4538 }
4539 else if (*input == '@') {
4540 inputFile = FILE_HANDLE;
4541 input++;
4542 }
4543
4544 if (!*input && ++i < argc) {
4545 input = Jim_GetString(argv[i], &input_len);
4546 }
4547 }
4548 else if (arg[0] == '>') {
4549 int dup_error = 0;
4550
@@ -4498,11 +4618,11 @@
4618
4619 save_environ = JimSaveEnv(JimBuildEnv(interp));
4620
4621 if (input != NULL) {
4622 if (inputFile == FILE_TEXT) {
4623 inputId = JimCreateTemp(interp, input, input_len);
4624 if (inputId == JIM_BAD_FD) {
4625 goto error;
4626 }
4627 }
4628 else if (inputFile == FILE_HANDLE) {
@@ -4587,11 +4707,11 @@
4707 goto error;
4708 }
4709 }
4710 }
4711 else if (errFilePtr != NULL) {
4712 errorId = JimCreateTemp(interp, NULL, 0);
4713 if (errorId == JIM_BAD_FD) {
4714 goto error;
4715 }
4716 *errFilePtr = JimDupFd(errorId);
4717 }
@@ -4625,27 +4745,23 @@
4745 }
4746 outputId = pipeIds[1];
4747 }
4748
4749
4750 if (pipe_dup_err) {
4751 errorId = outputId;
4752 }
4753
4754
4755
4756 #ifdef __MINGW32__
4757 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
4758 if (pid == JIM_BAD_PID) {
4759 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
4760 goto error;
4761 }
4762 #else
 
 
 
 
 
 
 
 
 
4763 pid = vfork();
4764 if (pid < 0) {
4765 Jim_SetResultErrno(interp, "couldn't fork child process");
4766 goto error;
4767 }
@@ -4658,14 +4774,17 @@
4774
4775 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
4776 close(i);
4777 }
4778
4779
4780 (void)signal(SIGPIPE, SIG_DFL);
4781
4782 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
4783
4784
4785 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
4786 _exit(127);
4787 }
4788 #endif
4789
4790
@@ -4767,19 +4886,24 @@
4886 if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
4887 result = JIM_ERR;
4888 }
4889 }
4890
4891 Jim_RemoveTrailingNewline(Jim_GetResult(interp));
4892
4893 return result;
4894 }
4895
4896 int Jim_execInit(Jim_Interp *interp)
4897 {
4898 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4899 return JIM_ERR;
4900
4901 #ifdef SIGPIPE
4902 (void)signal(SIGPIPE, SIG_IGN);
4903 #endif
4904
4905 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
4906 return JIM_OK;
4907 }
4908
4909 #if defined(__MINGW32__)
@@ -4953,11 +5077,11 @@
5077 *status = ret;
5078 CloseHandle(pid);
5079 return pid;
5080 }
5081
5082 static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5083 {
5084 char name[MAX_PATH];
5085 HANDLE handle;
5086
5087 if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
@@ -4977,11 +5101,11 @@
5101 FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
5102 if (fh == NULL) {
5103 goto error;
5104 }
5105
5106 if (fwrite(contents, len, 1, fh) != 1) {
5107 fclose(fh);
5108 goto error;
5109 }
5110 fseek(fh, 0, SEEK_SET);
5111 fclose(fh);
@@ -5104,28 +5228,26 @@
5228 {
5229 STARTUPINFO startInfo;
5230 PROCESS_INFORMATION procInfo;
5231 HANDLE hProcess, h;
5232 char execPath[MAX_PATH];
 
5233 pidtype pid = JIM_BAD_PID;
5234 Jim_Obj *cmdLineObj;
5235
5236 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5237 return JIM_BAD_PID;
5238 }
 
5239 argv[0] = execPath;
5240
5241 hProcess = GetCurrentProcess();
5242 cmdLineObj = JimWinBuildCommandLine(interp, argv);
5243
5244
5245 ZeroMemory(&startInfo, sizeof(startInfo));
5246 startInfo.cb = sizeof(startInfo);
5247 startInfo.dwFlags = STARTF_USESTDHANDLES;
5248 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5249 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5250 startInfo.hStdError = INVALID_HANDLE_VALUE;
5251
5252 if (inputId == JIM_BAD_FD) {
5253 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5196,23 +5318,21 @@
5318 static int JimRewindFd(int fd)
5319 {
5320 return lseek(fd, 0L, SEEK_SET);
5321 }
5322
5323 static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5324 {
5325 int fd = Jim_MakeTempFile(interp, NULL);
5326
 
5327 if (fd == JIM_BAD_FD) {
5328 Jim_SetResultErrno(interp, "couldn't create temp file");
5329 return -1;
5330 }
5331 unlink(Jim_String(Jim_GetResult(interp)));
5332 if (contents) {
5333 if (write(fd, contents, len) != len) {
 
5334 Jim_SetResultErrno(interp, "couldn't write temp file");
5335 close(fd);
5336 return -1;
5337 }
5338 lseek(fd, 0L, SEEK_SET);
@@ -5234,11 +5354,10 @@
5354 }
5355 #endif
5356 #endif
5357
5358
 
5359 #ifndef _XOPEN_SOURCE
5360 #define _XOPEN_SOURCE 500
5361 #endif
5362
5363 #include <stdlib.h>
@@ -5256,11 +5375,11 @@
5375
5376 char buf[100];
5377 time_t t;
5378 long seconds;
5379
5380 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5381
5382 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5383 return -1;
5384 }
5385
@@ -5271,11 +5390,14 @@
5390 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5391 return JIM_ERR;
5392 }
5393 t = seconds;
5394
5395 if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5396 Jim_SetResultString(interp, "format string too long", -1);
5397 return JIM_ERR;
5398 }
5399
5400 Jim_SetResultString(interp, buf, -1);
5401
5402 return JIM_OK;
5403 }
@@ -5391,11 +5513,10 @@
5513
5514 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
5515 return JIM_OK;
5516 }
5517
 
5518 #include <limits.h>
5519 #include <stdlib.h>
5520 #include <string.h>
5521 #include <stdio.h>
5522 #include <errno.h>
@@ -5409,33 +5530,29 @@
5530 }
5531
5532 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5533 {
5534 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5535 Jim_Obj *patternObj;
5536
5537 if (!objPtr) {
5538 return JIM_OK;
5539 }
5540
5541 patternObj = (argc == 1) ? NULL : argv[1];
5542
5543
5544 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5545 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5546
5547 Jim_SetResult(interp, objPtr);
5548 return JIM_OK;
5549 }
 
 
 
 
 
5550 }
5551
5552
5553 return Jim_DictValues(interp, objPtr, patternObj);
5554 }
5555
5556 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5557 {
5558 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5460,10 +5577,15 @@
5577 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5578 return JIM_OK;
5579 }
5580
5581 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5582
5583 if (objPtr == NULL) {
5584
5585 return JIM_OK;
5586 }
5587
5588 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5589 return JIM_ERR;
5590 }
5591
@@ -5497,10 +5619,20 @@
5619
5620 Jim_SetResultInt(interp, len);
5621
5622 return JIM_OK;
5623 }
5624
5625 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5626 {
5627 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5628 if (objPtr) {
5629 return Jim_DictInfo(interp, objPtr);
5630 }
5631 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
5632 return JIM_ERR;
5633 }
5634
5635 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5636 {
5637 int i;
5638 int len;
@@ -5515,10 +5647,13 @@
5647
5648 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5649 if (!dictObj) {
5650
5651 return Jim_SetVariable(interp, argv[0], listObj);
5652 }
5653 else if (Jim_DictSize(interp, dictObj) < 0) {
5654 return JIM_ERR;
5655 }
5656
5657 if (Jim_IsShared(dictObj)) {
5658 dictObj = Jim_DuplicateObj(interp, dictObj);
5659 }
@@ -5568,10 +5703,17 @@
5703 "arrayName",
5704 array_cmd_size,
5705 1,
5706 1,
5707
5708 },
5709 { "stat",
5710 "arrayName",
5711 array_cmd_stat,
5712 1,
5713 1,
5714
5715 },
5716 { "unset",
5717 "arrayName ?pattern?",
5718 array_cmd_unset,
5719 1,
@@ -5614,11 +5756,10 @@
5756 Jim_arrayInit(interp);
5757 Jim_stdlibInit(interp);
5758 Jim_tclcompatInit(interp);
5759 return JIM_OK;
5760 }
 
5761 #define JIM_OPTIMIZATION
5762
5763 #include <stdio.h>
5764 #include <stdlib.h>
5765
@@ -5671,29 +5812,33 @@
5812 #ifdef JIM_MAINTAINER
5813 #define JIM_DEBUG_COMMAND
5814 #define JIM_DEBUG_PANIC
5815 #endif
5816
5817
5818
5819 #define JIM_INTEGER_SPACE 24
5820
5821 const char *jim_tt_name(int type);
5822
5823 #ifdef JIM_DEBUG_PANIC
5824 static void JimPanicDump(int fail_condition, const char *fmt, ...);
5825 #define JimPanic(X) JimPanicDump X
5826 #else
5827 #define JimPanic(X)
5828 #endif
5829
5830
5831 static char JimEmptyStringRep[] = "";
5832
5833 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
 
5834 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5835 int flags);
5836 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5837 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5838 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
5839 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
5840 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
5841 const char *prefix, const char *const *tablePtr, const char *name);
5842 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
5843 static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
5844 static int JimSign(jim_wide w);
@@ -5934,17 +6079,10 @@
6079 }
6080 return n;
6081 }
6082 #endif
6083
 
 
 
 
 
 
 
6084 static int JimCheckConversion(const char *str, const char *endptr)
6085 {
6086 if (str[0] == '\0' || str == endptr) {
6087 return JIM_ERR;
6088 }
@@ -5998,11 +6136,12 @@
6136 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6137
6138 return i;
6139 }
6140
6141 *base = 10;
6142 return 0;
6143 }
6144
6145 static long jim_strtol(const char *str, char **endptr)
6146 {
6147 int sign;
@@ -6054,46 +6193,10 @@
6193 }
6194
6195 return JimCheckConversion(str, endptr);
6196 }
6197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6198 int Jim_StringToDouble(const char *str, double *doublePtr)
6199 {
6200 char *endptr;
6201
6202
@@ -6115,23 +6218,23 @@
6218 }
6219 return res;
6220 }
6221
6222 #ifdef JIM_DEBUG_PANIC
6223 static void JimPanicDump(int condition, const char *fmt, ...)
6224 {
6225 va_list ap;
6226
6227 if (!condition) {
6228 return;
6229 }
6230
6231 va_start(ap, fmt);
6232
6233 fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
6234 vfprintf(stderr, fmt, ap);
6235 fprintf(stderr, "\n\n");
6236 va_end(ap);
6237
6238 #ifdef HAVE_BACKTRACE
6239 {
6240 void *array[40];
@@ -6139,13 +6242,13 @@
6242 char **strings;
6243
6244 size = backtrace(array, 40);
6245 strings = backtrace_symbols(array, size);
6246 for (i = 0; i < size; i++)
6247 fprintf(stderr, "[backtrace] %s\n", strings[i]);
6248 fprintf(stderr, "[backtrace] Include the above lines and the output\n");
6249 fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
6250 }
6251 #endif
6252
6253 exit(1);
6254 }
@@ -6219,18 +6322,32 @@
6322 h += (h << 3) + *buf++;
6323 return h;
6324 }
6325
6326
6327
6328
6329 static void JimResetHashTable(Jim_HashTable *ht)
6330 {
6331 ht->table = NULL;
6332 ht->size = 0;
6333 ht->sizemask = 0;
6334 ht->used = 0;
6335 ht->collisions = 0;
6336 #ifdef JIM_RANDOMISE_HASH
6337 ht->uniq = (rand() ^ time(NULL) ^ clock());
6338 #else
6339 ht->uniq = 0;
6340 #endif
6341 }
6342
6343 static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6344 {
6345 iter->ht = ht;
6346 iter->index = -1;
6347 iter->entry = NULL;
6348 iter->nextEntry = NULL;
6349 }
6350
6351
6352 int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
6353 {
@@ -6260,10 +6377,12 @@
6377
6378 Jim_InitHashTable(&n, ht->type, ht->privdata);
6379 n.size = realsize;
6380 n.sizemask = realsize - 1;
6381 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6382
6383 n.uniq = ht->uniq;
6384
6385
6386 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6387
6388 n.used = ht->used;
@@ -6316,20 +6435,27 @@
6435 int existed;
6436 Jim_HashEntry *entry;
6437
6438 entry = JimInsertHashEntry(ht, key, 1);
6439 if (entry->key) {
6440 if (ht->type->valDestructor && ht->type->valDup) {
6441 void *newval = ht->type->valDup(ht->privdata, val);
6442 ht->type->valDestructor(ht->privdata, entry->u.val);
6443 entry->u.val = newval;
6444 }
6445 else {
6446 Jim_FreeEntryVal(ht, entry);
6447 Jim_SetHashVal(ht, entry, val);
6448 }
6449 existed = 1;
6450 }
6451 else {
6452
6453 Jim_SetHashKey(ht, entry, key);
6454 Jim_SetHashVal(ht, entry, val);
6455 existed = 0;
6456 }
 
6457
6458 return existed;
6459 }
6460
6461
@@ -6408,15 +6534,11 @@
6534 }
6535
6536 Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
6537 {
6538 Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6539 JimInitHashTableIterator(ht, iter);
 
 
 
 
6540 return iter;
6541 }
6542
6543 Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
6544 {
@@ -6498,11 +6620,11 @@
6620 return Jim_GenHashFunction(key, strlen(key));
6621 }
6622
6623 static void *JimStringCopyHTDup(void *privdata, const void *key)
6624 {
6625 return Jim_StrDup(key);
6626 }
6627
6628 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
6629 {
6630 return strcmp(key1, key2) == 0;
@@ -6598,11 +6720,11 @@
6720 freeFunc(stack->vector[i]);
6721 }
6722
6723
6724
6725 #define JIM_TT_NONE 0
6726 #define JIM_TT_STR 1
6727 #define JIM_TT_ESC 2
6728 #define JIM_TT_VAR 3
6729 #define JIM_TT_DICTSUGAR 4
6730 #define JIM_TT_CMD 5
@@ -6630,10 +6752,15 @@
6752
6753
6754 #define JIM_PS_DEF 0
6755 #define JIM_PS_QUOTE 1
6756 #define JIM_PS_DICTSUGAR 2
6757
6758 struct JimParseMissing {
6759 int ch;
6760 int line;
6761 };
6762
6763 struct JimParserCtx
6764 {
6765 const char *p;
6766 int len;
@@ -6643,17 +6770,11 @@
6770 int tline;
6771 int tt;
6772 int eof;
6773 int state;
6774 int comment;
6775 struct JimParseMissing missing;
 
 
 
 
 
 
6776 };
6777
6778 static int JimParseScript(struct JimParserCtx *pc);
6779 static int JimParseSep(struct JimParserCtx *pc);
6780 static int JimParseEol(struct JimParserCtx *pc);
@@ -6663,11 +6784,10 @@
6784 static int JimParseBrace(struct JimParserCtx *pc);
6785 static int JimParseStr(struct JimParserCtx *pc);
6786 static int JimParseComment(struct JimParserCtx *pc);
6787 static void JimParseSubCmd(struct JimParserCtx *pc);
6788 static int JimParseSubQuote(struct JimParserCtx *pc);
 
6789 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
6790
6791 static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
6792 {
6793 pc->p = prg;
@@ -6678,12 +6798,12 @@
6798 pc->tt = JIM_TT_NONE;
6799 pc->eof = 0;
6800 pc->state = JIM_PS_DEF;
6801 pc->linenr = linenr;
6802 pc->comment = 1;
6803 pc->missing.ch = ' ';
6804 pc->missing.line = linenr;
6805 }
6806
6807 static int JimParseScript(struct JimParserCtx *pc)
6808 {
6809 while (1) {
@@ -6815,12 +6935,12 @@
6935 break;
6936 }
6937 pc->p++;
6938 pc->len--;
6939 }
6940 pc->missing.ch = '{';
6941 pc->missing.line = pc->tline;
6942 pc->tend = pc->p - 1;
6943 }
6944
6945 static int JimParseSubQuote(struct JimParserCtx *pc)
6946 {
@@ -6862,12 +6982,12 @@
6982 break;
6983 }
6984 pc->p++;
6985 pc->len--;
6986 }
6987 pc->missing.ch = '"';
6988 pc->missing.line = line;
6989 pc->tend = pc->p - 1;
6990 return tt;
6991 }
6992
6993 static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6921,12 +7041,12 @@
7041 }
7042 startofword = isspace(UCHAR(*pc->p));
7043 pc->p++;
7044 pc->len--;
7045 }
7046 pc->missing.ch = '[';
7047 pc->missing.line = line;
7048 pc->tend = pc->p - 1;
7049 }
7050
7051 static int JimParseBrace(struct JimParserCtx *pc)
7052 {
@@ -7066,19 +7186,19 @@
7186 if (*pc->p == '"') {
7187 pc->state = JIM_PS_QUOTE;
7188 pc->p++;
7189 pc->len--;
7190
7191 pc->missing.line = pc->tline;
7192 }
7193 }
7194 pc->tstart = pc->p;
7195 pc->tline = pc->linenr;
7196 while (1) {
7197 if (pc->len == 0) {
7198 if (pc->state == JIM_PS_QUOTE) {
7199 pc->missing.ch = '"';
7200 }
7201 pc->tend = pc->p - 1;
7202 pc->tt = JIM_TT_ESC;
7203 return JIM_OK;
7204 }
@@ -7094,10 +7214,14 @@
7214 pc->linenr++;
7215 }
7216 pc->p++;
7217 pc->len--;
7218 }
7219 else if (pc->len == 1) {
7220
7221 pc->missing.ch = '\\';
7222 }
7223 break;
7224 case '(':
7225
7226 if (pc->len > 1 && pc->p[1] != '$') {
7227 break;
@@ -7154,17 +7278,26 @@
7278 }
7279
7280 static int JimParseComment(struct JimParserCtx *pc)
7281 {
7282 while (*pc->p) {
7283 if (*pc->p == '\\') {
7284 pc->p++;
7285 pc->len--;
7286 if (pc->len == 0) {
7287 pc->missing.ch = '\\';
7288 return JIM_OK;
7289 }
7290 if (*pc->p == '\n') {
7291 pc->linenr++;
7292 }
7293 }
7294 else if (*pc->p == '\n') {
7295 pc->p++;
7296 pc->len--;
7297 pc->linenr++;
7298 break;
 
 
 
 
7299 }
7300 pc->p++;
7301 pc->len--;
7302 }
7303 return JIM_OK;
@@ -7382,13 +7515,13 @@
7515 JimParserInit(&parser, s, len, 1);
7516 while (!parser.eof) {
7517 JimParseScript(&parser);
7518 }
7519 if (stateCharPtr) {
7520 *stateCharPtr = parser.missing.ch;
7521 }
7522 return parser.missing.ch == ' ';
7523 }
7524
7525 static int JimParseListSep(struct JimParserCtx *pc);
7526 static int JimParseListStr(struct JimParserCtx *pc);
7527 static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7546,17 +7679,21 @@
7679 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7680 if (objPtr->nextObjPtr)
7681 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7682 if (interp->liveList == objPtr)
7683 interp->liveList = objPtr->nextObjPtr;
7684 #ifdef JIM_DISABLE_OBJECT_POOL
7685 Jim_Free(objPtr);
7686 #else
7687
7688 objPtr->prevObjPtr = NULL;
7689 objPtr->nextObjPtr = interp->freeList;
7690 if (interp->freeList)
7691 interp->freeList->prevObjPtr = objPtr;
7692 interp->freeList = objPtr;
7693 objPtr->refCount = -1;
7694 #endif
7695 }
7696
7697
7698 void Jim_InvalidateStringRep(Jim_Obj *objPtr)
7699 {
@@ -7636,10 +7773,16 @@
7773 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7774 objPtr->typePtr->updateStringProc(objPtr);
7775 }
7776 return objPtr->bytes;
7777 }
7778
7779 static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
7780 {
7781 objPtr->bytes = Jim_StrDup(str);
7782 objPtr->length = strlen(str);
7783 }
7784
7785 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
7786 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
7787
7788 static const Jim_ObjType dictSubstObjType = {
@@ -7677,11 +7820,10 @@
7820 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
7821 {
7822 JIM_NOTUSED(interp);
7823
7824 dupPtr->internalRep.strValue.maxLength = srcPtr->length;
 
7825 dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
7826 }
7827
7828 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
7829 {
@@ -7726,18 +7868,17 @@
7868 if (len == -1)
7869 len = strlen(s);
7870
7871 if (len == 0) {
7872 objPtr->bytes = JimEmptyStringRep;
 
7873 }
7874 else {
7875 objPtr->bytes = Jim_Alloc(len + 1);
 
7876 memcpy(objPtr->bytes, s, len);
7877 objPtr->bytes[len] = '\0';
7878 }
7879 objPtr->length = len;
7880
7881
7882 objPtr->typePtr = NULL;
7883 return objPtr;
7884 }
@@ -7765,11 +7906,11 @@
7906 Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
7907 {
7908 Jim_Obj *objPtr = Jim_NewObj(interp);
7909
7910 objPtr->bytes = s;
7911 objPtr->length = (len == -1) ? strlen(s) : len;
7912 objPtr->typePtr = NULL;
7913 return objPtr;
7914 }
7915
7916 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7794,17 +7935,17 @@
7935 }
7936 objPtr->internalRep.strValue.maxLength = needlen;
7937 }
7938 memcpy(objPtr->bytes + objPtr->length, str, len);
7939 objPtr->bytes[objPtr->length + len] = '\0';
7940
7941 if (objPtr->internalRep.strValue.charLength >= 0) {
7942
7943 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
7944 }
7945 objPtr->length += len;
7946 }
 
7947
7948 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
7949 {
7950 JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
7951 SetStringFromAny(interp, objPtr);
@@ -7812,13 +7953,11 @@
7953 }
7954
7955 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
7956 {
7957 int len;
7958 const char *str = Jim_GetString(appendObjPtr, &len);
 
 
7959 Jim_AppendString(interp, objPtr, str, len);
7960 }
7961
7962 void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
7963 {
@@ -7825,11 +7964,11 @@
7964 va_list ap;
7965
7966 SetStringFromAny(interp, objPtr);
7967 va_start(ap, objPtr);
7968 while (1) {
7969 const char *s = va_arg(ap, const char *);
7970
7971 if (s == NULL)
7972 break;
7973 Jim_AppendString(interp, objPtr, s, -1);
7974 }
@@ -7836,20 +7975,20 @@
7975 va_end(ap);
7976 }
7977
7978 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
7979 {
7980 if (aObjPtr == bObjPtr) {
 
 
 
7981 return 1;
7982 }
7983 else {
7984 int Alen, Blen;
7985 const char *sA = Jim_GetString(aObjPtr, &Alen);
7986 const char *sB = Jim_GetString(bObjPtr, &Blen);
7987
7988 return Alen == Blen && memcmp(sA, sB, Alen) == 0;
7989 }
7990 }
7991
7992 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
7993 {
7994 return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8010,11 +8149,11 @@
8149 static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
8150 {
8151 while (*str) {
8152 int c;
8153 str += utf8_tounicode(str, &c);
8154 dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
8155 }
8156 *dest = 0;
8157 }
8158
8159 static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8070,11 +8209,11 @@
8209 len *= 2;
8210 #endif
8211 buf = p = Jim_Alloc(len + 1);
8212
8213 str += utf8_tounicode(str, &c);
8214 p += utf8_getchars(p, utf8_title(c));
8215
8216 JimStrCopyUpperLower(p, str, 0);
8217
8218 return Jim_NewStringObjNoAlloc(interp, buf, -1);
8219 }
@@ -8177,10 +8316,11 @@
8316 if (nontrim == NULL) {
8317
8318 return Jim_NewEmptyStringObj(interp);
8319 }
8320 if (nontrim == strObjPtr->bytes + len) {
8321
8322 return strObjPtr;
8323 }
8324
8325 if (Jim_IsShared(strObjPtr)) {
8326 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8200,19 +8340,28 @@
8340 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8341
8342
8343 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8344
8345
8346 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8347
8348 Jim_FreeNewObj(interp, objPtr);
 
8349 }
8350
8351 return strObjPtr;
8352 }
8353
8354
8355 #ifdef HAVE_ISASCII
8356 #define jim_isascii isascii
8357 #else
8358 static int jim_isascii(int c)
8359 {
8360 return !(c & ~0x7f);
8361 }
8362 #endif
8363
8364 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8365 {
8366 static const char * const strclassnames[] = {
8367 "integer", "alpha", "alnum", "ascii", "digit",
@@ -8235,32 +8384,32 @@
8384 return JIM_ERR;
8385 }
8386
8387 str = Jim_GetString(strObjPtr, &len);
8388 if (len == 0) {
8389 Jim_SetResultBool(interp, !strict);
8390 return JIM_OK;
8391 }
8392
8393 switch (strclass) {
8394 case STR_IS_INTEGER:
8395 {
8396 jim_wide w;
8397 Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8398 return JIM_OK;
8399 }
8400
8401 case STR_IS_DOUBLE:
8402 {
8403 double d;
8404 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8405 return JIM_OK;
8406 }
8407
8408 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8409 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8410 case STR_IS_ASCII: isclassfunc = jim_isascii; break;
8411 case STR_IS_DIGIT: isclassfunc = isdigit; break;
8412 case STR_IS_LOWER: isclassfunc = islower; break;
8413 case STR_IS_UPPER: isclassfunc = isupper; break;
8414 case STR_IS_SPACE: isclassfunc = isspace; break;
8415 case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
@@ -8272,15 +8421,15 @@
8421 return JIM_ERR;
8422 }
8423
8424 for (i = 0; i < len; i++) {
8425 if (!isclassfunc(str[i])) {
8426 Jim_SetResultBool(interp, 0);
8427 return JIM_OK;
8428 }
8429 }
8430 Jim_SetResultBool(interp, 1);
8431 return JIM_OK;
8432 }
8433
8434
8435
@@ -8292,17 +8441,19 @@
8441 JIM_TYPE_REFERENCES,
8442 };
8443
8444 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
8445 {
8446 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
8447 return 1;
8448 }
8449 else {
8450 const char *objStr = Jim_String(objPtr);
8451
8452 if (strcmp(str, objStr) != 0)
8453 return 0;
8454
8455 if (objPtr->typePtr != &comparedStringObjType) {
8456 Jim_FreeIntRep(interp, objPtr);
8457 objPtr->typePtr = &comparedStringObjType;
8458 }
8459 objPtr->internalRep.ptr = (char *)str;
@@ -8344,24 +8495,23 @@
8495
8496 static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
8497 Jim_Obj *fileNameObj, int lineNumber)
8498 {
8499 JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8500 JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
8501 Jim_IncrRefCount(fileNameObj);
8502 objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
8503 objPtr->internalRep.sourceValue.lineNumber = lineNumber;
8504 objPtr->typePtr = &sourceObjType;
8505 }
8506
 
8507 static const Jim_ObjType scriptLineObjType = {
8508 "scriptline",
8509 NULL,
8510 NULL,
8511 NULL,
8512 JIM_NONE,
8513 };
8514
8515 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
8516 {
8517 Jim_Obj *objPtr;
@@ -8378,15 +8528,14 @@
8528 objPtr->internalRep.scriptLineValue.line = line;
8529
8530 return objPtr;
8531 }
8532
 
 
8533 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8534 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8535 static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8536 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8537
8538 static const Jim_ObjType scriptObjType = {
8539 "script",
8540 FreeScriptInternalRep,
8541 DupScriptInternalRep,
@@ -8394,34 +8543,33 @@
8543 JIM_TYPE_REFERENCES,
8544 };
8545
8546 typedef struct ScriptToken
8547 {
 
8548 Jim_Obj *objPtr;
8549 int type;
8550 } ScriptToken;
8551
8552 typedef struct ScriptObj
8553 {
 
8554 ScriptToken *token;
8555 Jim_Obj *fileNameObj;
8556 int len;
8557 int substFlags;
8558 int inUse; /* Used to share a ScriptObj. Currently
8559 only used by Jim_EvalObj() as protection against
8560 shimmering of the currently evaluated object. */
 
8561 int firstline;
8562 int linenr;
8563 } ScriptObj;
8564
8565 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8566 {
8567 int i;
8568 struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
8569
8570 if (--script->inUse != 0)
 
8571 return;
8572 for (i = 0; i < script->len; i++) {
8573 Jim_DecrRefCount(interp, script->token[i].objPtr);
8574 }
8575 Jim_Free(script->token);
@@ -8432,11 +8580,10 @@
8580 void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8581 {
8582 JIM_NOTUSED(interp);
8583 JIM_NOTUSED(srcPtr);
8584
 
8585 dupPtr->typePtr = NULL;
8586 }
8587
8588 typedef struct
8589 {
@@ -8631,11 +8778,11 @@
8778 token--;
8779 }
8780
8781 script->len = token - script->token;
8782
8783 JimPanic((script->len >= count, "allocated script array is too short"));
8784
8785 #ifdef DEBUG_SHOW_SCRIPT
8786 printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
8787 for (i = 0; i < script->len; i++) {
8788 const ScriptToken *t = &script->token[i];
@@ -8642,10 +8789,35 @@
8789 printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
8790 }
8791 #endif
8792
8793 }
8794
8795 static int JimParseCheckMissing(Jim_Interp *interp, int ch)
8796 {
8797 const char *msg;
8798
8799 switch (ch) {
8800 case '\\':
8801 case ' ':
8802 return JIM_OK;
8803
8804 case '[':
8805 msg = "unmatched \"[\"";
8806 break;
8807 case '{':
8808 msg = "missing close-brace";
8809 break;
8810 case '"':
8811 default:
8812 msg = "missing quote";
8813 break;
8814 }
8815
8816 Jim_SetResultString(interp, msg, -1);
8817 return JIM_ERR;
8818 }
8819
8820 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8821 ParseTokenList *tokenlist)
8822 {
8823 int i;
@@ -8664,18 +8836,19 @@
8836 }
8837
8838 script->len = i;
8839 }
8840
8841 static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
8842 {
8843 int scriptTextLen;
8844 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
8845 struct JimParserCtx parser;
8846 struct ScriptObj *script;
8847 ParseTokenList tokenlist;
8848 int line = 1;
8849 int retcode = JIM_OK;
8850
8851
8852 if (objPtr->typePtr == &sourceObjType) {
8853 line = objPtr->internalRep.sourceValue.lineNumber;
8854 }
@@ -8687,16 +8860,12 @@
8860 while (!parser.eof) {
8861 JimParseScript(&parser);
8862 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
8863 parser.tline);
8864 }
8865
8866 retcode = JimParseCheckMissing(interp, parser.missing.ch);
 
 
 
 
8867
8868
8869 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
8870
8871
@@ -8707,10 +8876,11 @@
8876 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
8877 }
8878 else {
8879 script->fileNameObj = interp->emptyObj;
8880 }
8881 script->linenr = parser.missing.line;
8882 Jim_IncrRefCount(script->fileNameObj);
8883
8884 ScriptObjAddTokens(interp, script, &tokenlist);
8885
8886
@@ -8719,11 +8889,11 @@
8889
8890 Jim_FreeIntRep(interp, objPtr);
8891 Jim_SetIntRepPtr(objPtr, script);
8892 objPtr->typePtr = &scriptObjType;
8893
8894 return retcode;
8895 }
8896
8897 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
8898 {
8899 if (objPtr == interp->emptyObj) {
@@ -8730,11 +8900,13 @@
8900
8901 objPtr = interp->nullScriptObj;
8902 }
8903
8904 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8905 if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
8906 return NULL;
8907 }
8908 }
8909 return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
8910 }
8911
8912 static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8815,10 +8987,26 @@
8987 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
8988 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
8989 }
8990 return nsObj;
8991 }
8992
8993 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
8994 {
8995 Jim_Obj *resultObj;
8996
8997 const char *name = Jim_String(nameObjPtr);
8998 if (name[0] == ':' && name[1] == ':') {
8999 return nameObjPtr;
9000 }
9001 Jim_IncrRefCount(nameObjPtr);
9002 resultObj = Jim_NewStringObj(interp, "::", -1);
9003 Jim_AppendObj(interp, resultObj, nameObjPtr);
9004 Jim_DecrRefCount(interp, nameObjPtr);
9005
9006 return resultObj;
9007 }
9008
9009 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9010 {
9011 Jim_Obj *objPtr = interp->emptyObj;
9012
@@ -8842,10 +9030,15 @@
9030
9031 #else
9032
9033 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9034 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9035
9036 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9037 {
9038 return nameObjPtr;
9039 }
9040 #endif
9041
9042 static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
9043 {
9044 Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8854,12 +9047,12 @@
9047 Jim_InterpIncrProcEpoch(interp);
9048 }
9049
9050 if (he && interp->local) {
9051
9052 cmd->prevCmd = Jim_GetHashEntryVal(he);
9053 Jim_SetHashVal(&interp->commands, he, cmd);
9054 }
9055 else {
9056 if (he) {
9057
9058 Jim_DeleteHashEntry(&interp->commands, name);
@@ -8898,19 +9091,19 @@
9091 }
9092
9093 cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
9094 Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
9095 for (i = 0; i < len; i++) {
9096 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9097 Jim_Var *varPtr;
9098 int subLen;
9099
9100 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9101
9102 subLen = Jim_ListLength(interp, objPtr);
9103 if (subLen == 1 || subLen == 2) {
9104 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9105 if (subLen == 1) {
9106 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
9107 if (initObjPtr == NULL) {
9108 Jim_SetResultFormatted(interp,
9109 "variable for initialization of static \"%#s\" not found in the local context",
@@ -8917,11 +9110,11 @@
9110 nameObjPtr);
9111 return JIM_ERR;
9112 }
9113 }
9114 else {
9115 initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
9116 }
9117 if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
9118 return JIM_ERR;
9119 }
9120
@@ -9003,11 +9196,11 @@
9196 Jim_Obj *nameObjPtr;
9197 Jim_Obj *defaultObjPtr;
9198 int len;
9199
9200
9201 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9202 len = Jim_ListLength(interp, argPtr);
9203 if (len == 0) {
9204 Jim_SetResultString(interp, "argument with no name", -1);
9205 err:
9206 JimDecrCmdRefCount(interp, cmdPtr);
@@ -9018,12 +9211,12 @@
9211 goto err;
9212 }
9213
9214 if (len == 2) {
9215
9216 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9217 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9218 }
9219 else {
9220
9221 nameObjPtr = argPtr;
9222 defaultObjPtr = NULL;
@@ -9097,11 +9290,11 @@
9290 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9291 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9292 }
9293 else {
9294
9295 cmdPtr = Jim_GetHashEntryVal(he);
9296 JimIncrCmdRefCount(cmdPtr);
9297 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9298 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9299
9300
@@ -9182,11 +9375,11 @@
9375 return NULL;
9376 }
9377 #ifdef jim_ext_namespace
9378 found:
9379 #endif
9380 cmd = Jim_GetHashEntryVal(he);
9381
9382
9383 Jim_FreeIntRep(interp, objPtr);
9384 objPtr->typePtr = &commandObjType;
9385 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9288,11 +9481,11 @@
9481
9482
9483 Jim_FreeIntRep(interp, objPtr);
9484 objPtr->typePtr = &variableObjType;
9485 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9486 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9487 objPtr->internalRep.varValue.global = global;
9488 return JIM_OK;
9489 }
9490
9491
@@ -9606,11 +9799,11 @@
9799 }
9800
9801 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
9802 if (retval == JIM_OK) {
9803
9804 framePtr->id = interp->callFrameEpoch++;
9805 }
9806 }
9807 }
9808 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
9809 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9690,28 +9883,17 @@
9883 return NULL;
9884 }
9885
9886 ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9887 if (ret != JIM_OK) {
9888 Jim_SetResultFormatted(interp,
9889 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
9890 ret < 0 ? "variable isn't" : "no such element in");
 
 
 
 
 
 
9891 }
9892 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
 
 
 
 
 
9893
9894 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
9895 }
9896
9897 return resObjPtr;
9898 }
9899
@@ -9808,68 +9990,67 @@
9990 Jim_CallFrame *cf;
9991
9992 if (interp->freeFramesList) {
9993 cf = interp->freeFramesList;
9994 interp->freeFramesList = cf->next;
9995
9996 cf->argv = NULL;
9997 cf->argc = 0;
9998 cf->procArgsObjPtr = NULL;
9999 cf->procBodyObjPtr = NULL;
10000 cf->next = NULL;
10001 cf->staticVars = NULL;
10002 cf->localCommands = NULL;
10003 cf->tailcall = 0;
10004 cf->tailcallObj = NULL;
10005 cf->tailcallCmd = NULL;
10006 }
10007 else {
10008 cf = Jim_Alloc(sizeof(*cf));
10009 memset(cf, 0, sizeof(*cf));
10010
10011 Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
10012 }
10013
10014 cf->id = interp->callFrameEpoch++;
10015 cf->parent = parent;
10016 cf->level = parent ? parent->level + 1 : 0;
 
 
 
 
 
 
 
 
10017 cf->nsObj = nsObj;
10018 Jim_IncrRefCount(nsObj);
10019
 
10020 return cf;
10021 }
10022
 
 
 
 
 
 
10023 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10024 {
10025
10026 if (localCommands) {
10027 Jim_Obj *cmdNameObj;
10028
10029 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10030 Jim_HashEntry *he;
10031 Jim_Obj *fqObjName;
10032 Jim_HashTable *ht = &interp->commands;
10033
10034 const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
10035
10036 he = Jim_FindHashEntry(ht, fqname);
10037
10038 if (he) {
10039 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10040 if (cmd->prevCmd) {
10041 Jim_Cmd *prevCmd = cmd->prevCmd;
10042 cmd->prevCmd = NULL;
10043
10044
10045 JimDecrCmdRefCount(interp, cmd);
10046
10047
10048 Jim_SetHashVal(ht, he, prevCmd);
10049 }
10050 else {
10051 Jim_DeleteHashEntry(ht, fqname);
10052 Jim_InterpIncrProcEpoch(interp);
10053 }
10054 }
10055 Jim_DecrRefCount(interp, cmdNameObj);
10056 JimFreeQualifiedName(interp, fqObjName);
@@ -9879,47 +10060,45 @@
10060 }
10061 return JIM_OK;
10062 }
10063
10064
10065 #define JIM_FCF_FULL 0
10066 #define JIM_FCF_REUSE 1
10067 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10068 {
10069 JimDeleteLocalProcs(interp, cf->localCommands);
10070
10071 if (cf->procArgsObjPtr)
10072 Jim_DecrRefCount(interp, cf->procArgsObjPtr);
10073 if (cf->procBodyObjPtr)
10074 Jim_DecrRefCount(interp, cf->procBodyObjPtr);
10075 Jim_DecrRefCount(interp, cf->nsObj);
10076 if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
10077 Jim_FreeHashTable(&cf->vars);
10078 else {
10079 int i;
10080 Jim_HashEntry **table = cf->vars.table, *he;
10081
10082 for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
10083 he = table[i];
10084 while (he != NULL) {
10085 Jim_HashEntry *nextEntry = he->next;
10086 Jim_Var *varPtr = Jim_GetHashEntryVal(he);
10087
10088 Jim_DecrRefCount(interp, varPtr->objPtr);
10089 Jim_Free(Jim_GetHashEntryKey(he));
10090 Jim_Free(varPtr);
10091 Jim_Free(he);
10092 table[i] = NULL;
10093 he = nextEntry;
10094 }
10095 }
10096 cf->vars.used = 0;
10097 }
 
 
 
10098 cf->next = interp->freeFramesList;
10099 interp->freeFramesList = cf;
 
10100 }
10101
10102
10103 #ifdef JIM_REFERENCES
10104
@@ -9996,21 +10175,16 @@
10175 NULL,
10176 UpdateStringOfReference,
10177 JIM_TYPE_REFERENCES,
10178 };
10179
10180 static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10181 {
 
10182 char buf[JIM_REFERENCE_SPACE + 1];
 
10183
10184 JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10185 JimSetStringBytes(objPtr, buf);
 
 
 
10186 }
10187
10188 static int isrefchar(int c)
10189 {
10190 return (c == '_' || isalnum(c));
@@ -10061,11 +10235,11 @@
10235 he = Jim_FindHashEntry(&interp->references, &value);
10236 if (he == NULL) {
10237 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10238 return JIM_ERR;
10239 }
10240 refPtr = Jim_GetHashEntryVal(he);
10241
10242 Jim_FreeIntRep(interp, objPtr);
10243 objPtr->typePtr = &referenceObjType;
10244 objPtr->internalRep.refValue.id = value;
10245 objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10178,11 +10352,11 @@
10352 Jim_Collect(interp);
10353 }
10354 }
10355 #endif
10356
10357 int Jim_IsBigEndian(void)
10358 {
10359 union {
10360 unsigned short s;
10361 unsigned char c[2];
10362 } uval = {0x0102};
@@ -10234,23 +10408,30 @@
10408 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10409
10410 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
10411 Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
10412 Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
10413 Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
10414 Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
10415 Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
10416 Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
10417
10418 return i;
10419 }
10420
10421 void Jim_FreeInterp(Jim_Interp *i)
10422 {
10423 Jim_CallFrame *cf, *cfx;
10424
10425 Jim_Obj *objPtr, *nextObjPtr;
10426
10427
10428 for (cf = i->framePtr; cf; cf = cfx) {
10429 cfx = cf->parent;
10430 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10431 }
10432
10433 Jim_DecrRefCount(i, i->emptyObj);
10434 Jim_DecrRefCount(i, i->trueObj);
10435 Jim_DecrRefCount(i, i->falseObj);
10436 Jim_DecrRefCount(i, i->result);
10437 Jim_DecrRefCount(i, i->stackTrace);
@@ -10265,61 +10446,54 @@
10446 #endif
10447 Jim_FreeHashTable(&i->packages);
10448 Jim_Free(i->prngState);
10449 Jim_FreeHashTable(&i->assocData);
10450
10451 #ifdef JIM_MAINTAINER
 
 
 
 
 
10452 if (i->liveList != NULL) {
10453 objPtr = i->liveList;
10454
10455 printf("\n-------------------------------------\n");
10456 printf("Objects still in the free list:\n");
10457 while (objPtr) {
10458 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10459
10460 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10461 printf("%p (%d) %-10s: '%.20s...'\n",
10462 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10463 }
10464 else {
10465 printf("%p (%d) %-10s: '%s'\n",
10466 (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
10467 }
10468 if (objPtr->typePtr == &sourceObjType) {
10469 printf("FILE %s LINE %d\n",
10470 Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
10471 objPtr->internalRep.sourceValue.lineNumber);
10472 }
10473 objPtr = objPtr->nextObjPtr;
10474 }
10475 printf("-------------------------------------\n\n");
10476 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10477 }
10478 #endif
10479
10480
10481 objPtr = i->freeList;
10482 while (objPtr) {
10483 nextObjPtr = objPtr->nextObjPtr;
10484 Jim_Free(objPtr);
10485 objPtr = nextObjPtr;
10486 }
10487
10488
10489 for (cf = i->freeFramesList; cf; cf = cfx) {
10490 cfx = cf->next;
10491 if (cf->vars.table)
10492 Jim_FreeHashTable(&cf->vars);
 
10493 Jim_Free(cf);
 
10494 }
 
 
 
10495
10496
10497 Jim_Free(i);
10498 }
10499
@@ -10414,22 +10588,15 @@
10588 interp->stackTrace = stackTraceObj;
10589 interp->errorFlag = 1;
10590
10591 len = Jim_ListLength(interp, interp->stackTrace);
10592 if (len >= 3) {
10593 if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
 
 
 
 
 
 
10594 interp->addStackTrace = 1;
10595 }
10596 }
10597 }
 
10598
10599 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
10600 Jim_Obj *fileNameObj, int linenr)
10601 {
10602 if (strcmp(procname, "unknown") == 0) {
@@ -10450,14 +10617,15 @@
10617 if (!*procname && Jim_Length(fileNameObj)) {
10618
10619 int len = Jim_ListLength(interp, interp->stackTrace);
10620
10621 if (len >= 3) {
10622 Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10623 if (Jim_Length(objPtr)) {
10624
10625 objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10626 if (Jim_Length(objPtr) == 0) {
10627
10628 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10629 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10630 return;
10631 }
@@ -10483,12 +10651,11 @@
10651 void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
10652 {
10653 Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
10654
10655 if (entryPtr != NULL) {
10656 AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
 
10657 return assocEntryPtr->data;
10658 }
10659 return NULL;
10660 }
10661
@@ -10500,12 +10667,10 @@
10667 int Jim_GetExitCode(Jim_Interp *interp)
10668 {
10669 return interp->exitCode;
10670 }
10671
 
 
10672 static void UpdateStringOfInt(struct Jim_Obj *objPtr);
10673 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10674
10675 static const Jim_ObjType intObjType = {
10676 "int",
@@ -10522,22 +10687,46 @@
10687 UpdateStringOfInt,
10688 JIM_TYPE_NONE,
10689 };
10690
10691
10692 static void UpdateStringOfInt(struct Jim_Obj *objPtr)
10693 {
 
10694 char buf[JIM_INTEGER_SPACE + 1];
10695 jim_wide wideValue = JimWideValue(objPtr);
10696 int pos = 0;
10697
10698 if (wideValue == 0) {
10699 buf[pos++] = '0';
10700 }
10701 else {
10702 char tmp[JIM_INTEGER_SPACE];
10703 int num = 0;
10704 int i;
10705
10706 if (wideValue < 0) {
10707 buf[pos++] = '-';
10708 i = wideValue % 10;
10709 tmp[num++] = (i > 0) ? (10 - i) : -i;
10710 wideValue /= -10;
10711 }
10712
10713 while (wideValue) {
10714 tmp[num++] = wideValue % 10;
10715 wideValue /= 10;
10716 }
10717
10718 for (i = 0; i < num; i++) {
10719 buf[pos++] = '0' + tmp[num - i - 1];
10720 }
10721 }
10722 buf[pos] = 0;
10723
10724 JimSetStringBytes(objPtr, buf);
10725 }
10726
10727 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10728 {
10729 jim_wide wideValue;
10730 const char *str;
10731
10732 if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10625,22 +10814,65 @@
10814 NULL,
10815 UpdateStringOfDouble,
10816 JIM_TYPE_NONE,
10817 };
10818
10819 #ifndef HAVE_ISNAN
10820 #undef isnan
10821 #define isnan(X) ((X) != (X))
10822 #endif
10823 #ifndef HAVE_ISINF
10824 #undef isinf
10825 #define isinf(X) (1.0 / (X) == 0.0)
10826 #endif
10827
10828 static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10829 {
10830 double value = objPtr->internalRep.doubleValue;
10831
10832 if (isnan(value)) {
10833 JimSetStringBytes(objPtr, "NaN");
10834 return;
10835 }
10836 if (isinf(value)) {
10837 if (value < 0) {
10838 JimSetStringBytes(objPtr, "-Inf");
10839 }
10840 else {
10841 JimSetStringBytes(objPtr, "Inf");
10842 }
10843 return;
10844 }
10845 {
10846 char buf[JIM_DOUBLE_SPACE + 1];
10847 int i;
10848 int len = sprintf(buf, "%.12g", value);
10849
10850
10851 for (i = 0; i < len; i++) {
10852 if (buf[i] == '.' || buf[i] == 'e') {
10853 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10854 char *e = strchr(buf, 'e');
10855 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10856
10857 e += 2;
10858 memmove(e, e + 1, len - (e - buf));
10859 }
10860 #endif
10861 break;
10862 }
10863 }
10864 if (buf[i] == '\0') {
10865 buf[i++] = '.';
10866 buf[i++] = '0';
10867 buf[i] = '\0';
10868 }
10869 JimSetStringBytes(objPtr, buf);
10870 }
10871 }
10872
10873 static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10874 {
10875 double doubleValue;
10876 jim_wide wideValue;
10877 const char *str;
10878
@@ -10755,11 +10987,11 @@
10987 }
10988
10989 #define JIM_ELESTR_SIMPLE 0
10990 #define JIM_ELESTR_BRACE 1
10991 #define JIM_ELESTR_QUOTE 2
10992 static unsigned char ListElementQuotingType(const char *s, int len)
10993 {
10994 int i, level, blevel, trySimple = 1;
10995
10996
10997 if (len == 0)
@@ -10848,15 +11080,15 @@
11080 return JIM_ELESTR_SIMPLE;
11081 }
11082 return JIM_ELESTR_QUOTE;
11083 }
11084
11085 static int BackslashQuoteString(const char *s, int len, char *q)
11086 {
11087 char *p = q;
11088
11089 while (len--) {
11090 switch (*s) {
11091 case ' ':
11092 case '$':
11093 case '"':
11094 case '[':
@@ -10903,17 +11135,23 @@
11135 return p - q;
11136 }
11137
11138 static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
11139 {
11140 #define STATIC_QUOTING_LEN 32
11141 int i, bufLen, realLength;
11142 const char *strRep;
11143 char *p;
11144 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
11145
11146
11147 if (objc > STATIC_QUOTING_LEN) {
11148 quotingType = Jim_Alloc(objc);
11149 }
11150 else {
11151 quotingType = staticQuoting;
11152 }
11153 bufLen = 0;
11154 for (i = 0; i < objc; i++) {
11155 int len;
11156
11157 strRep = Jim_GetString(objv[i], &len);
@@ -10962,11 +11200,11 @@
11200 case JIM_ELESTR_QUOTE:
11201 if (i == 0 && strRep[0] == '#') {
11202 *p++ = '\\';
11203 realLength++;
11204 }
11205 qlen = BackslashQuoteString(strRep, len, p);
11206 p += qlen;
11207 realLength += qlen;
11208 break;
11209 }
11210
@@ -10975,11 +11213,14 @@
11213 realLength++;
11214 }
11215 }
11216 *p = '\0';
11217 objPtr->length = realLength;
11218
11219 if (quotingType != staticQuoting) {
11220 Jim_Free(quotingType);
11221 }
11222 }
11223
11224 static void UpdateStringOfList(struct Jim_Obj *objPtr)
11225 {
11226 JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -10995,16 +11236,16 @@
11236
11237 if (objPtr->typePtr == &listObjType) {
11238 return JIM_OK;
11239 }
11240
11241 if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
11242 Jim_Obj **listObjPtrPtr;
11243 int len;
11244 int i;
11245
11246 listObjPtrPtr = JimDictPairs(objPtr, &len);
11247 for (i = 0; i < len; i++) {
11248 Jim_IncrRefCount(listObjPtrPtr[i]);
11249 }
11250
11251
@@ -11099,15 +11340,17 @@
11340 Jim_Interp *interp;
11341 enum {
11342 JIM_LSORT_ASCII,
11343 JIM_LSORT_NOCASE,
11344 JIM_LSORT_INTEGER,
11345 JIM_LSORT_REAL,
11346 JIM_LSORT_COMMAND
11347 } type;
11348 int order;
11349 int index;
11350 int indexed;
11351 int unique;
11352 int (*subfn)(Jim_Obj **, Jim_Obj **);
11353 };
11354
11355 static struct lsort_info *sort_info;
11356
@@ -11142,10 +11385,27 @@
11385 longjmp(sort_info->jmpbuf, JIM_ERR);
11386 }
11387
11388 return JimSign(lhs - rhs) * sort_info->order;
11389 }
11390
11391 static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11392 {
11393 double lhs = 0, rhs = 0;
11394
11395 if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
11396 Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
11397 longjmp(sort_info->jmpbuf, JIM_ERR);
11398 }
11399 if (lhs == rhs) {
11400 return 0;
11401 }
11402 if (lhs > rhs) {
11403 return sort_info->order;
11404 }
11405 return -sort_info->order;
11406 }
11407
11408 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11409 {
11410 Jim_Obj *compare_script;
11411 int rc;
@@ -11164,10 +11424,34 @@
11424 }
11425
11426 return JimSign(ret) * sort_info->order;
11427 }
11428
11429 static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
11430 {
11431 int src;
11432 int dst = 0;
11433 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11434
11435 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11436 if (comp(&ele[dst], &ele[src]) == 0) {
11437
11438 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11439 }
11440 else {
11441
11442 dst++;
11443 }
11444 ele[dst] = ele[src];
11445 }
11446
11447 ele[++dst] = ele[src];
11448
11449
11450 listObjPtr->internalRep.listValue.len = dst;
11451 }
11452
11453
11454 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
11455 {
11456 struct lsort_info *prev_info;
11457
@@ -11175,11 +11459,11 @@
11459 int (*fn) (Jim_Obj **, Jim_Obj **);
11460 Jim_Obj **vector;
11461 int len;
11462 int rc;
11463
11464 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11465 SetListFromAny(interp, listObjPtr);
11466
11467
11468 prev_info = sort_info;
11469 sort_info = info;
@@ -11194,10 +11478,13 @@
11478 fn = ListSortStringNoCase;
11479 break;
11480 case JIM_LSORT_INTEGER:
11481 fn = ListSortInteger;
11482 break;
11483 case JIM_LSORT_REAL:
11484 fn = ListSortReal;
11485 break;
11486 case JIM_LSORT_COMMAND:
11487 fn = ListSortCommand;
11488 break;
11489 default:
11490 fn = NULL;
@@ -11210,12 +11497,17 @@
11497 fn = ListSortIndexHelper;
11498 }
11499
11500 if ((rc = setjmp(info->jmpbuf)) == 0) {
11501 qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
11502
11503 if (info->unique && len > 1) {
11504 ListRemoveDuplicates(listObjPtr, fn);
11505 }
11506
11507 Jim_InvalidateStringRep(listObjPtr);
11508 }
 
11509 sort_info = prev_info;
11510
11511 return rc;
11512 }
11513
@@ -11225,14 +11517,22 @@
11517 int requiredLen = currentLen + elemc;
11518 int i;
11519 Jim_Obj **point;
11520
11521 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11522 if (requiredLen < 2) {
11523
11524 requiredLen = 4;
11525 }
11526 else {
11527 requiredLen *= 2;
11528 }
11529
11530 listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11531 sizeof(Jim_Obj *) * requiredLen);
11532
11533 listPtr->internalRep.listValue.maxLen = requiredLen;
11534 }
11535 if (idx < 0) {
11536 idx = currentLen;
11537 }
11538 point = listPtr->internalRep.listValue.ele + idx;
@@ -11332,11 +11632,11 @@
11632 listPtr->internalRep.listValue.ele[idx] = newObjPtr;
11633 Jim_IncrRefCount(newObjPtr);
11634 return JIM_OK;
11635 }
11636
11637 int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11638 Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
11639 {
11640 Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
11641 int shared, i, idx;
11642
@@ -11380,14 +11680,11 @@
11680 int i;
11681 int listLen = Jim_ListLength(interp, listObjPtr);
11682 Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
11683
11684 for (i = 0; i < listLen; ) {
11685 Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
 
 
 
11686 if (++i != listLen) {
11687 Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
11688 }
11689 }
11690 return resObjPtr;
@@ -11413,43 +11710,42 @@
11710 int len = 0, objLen;
11711 char *bytes, *p;
11712
11713
11714 for (i = 0; i < objc; i++) {
11715 len += Jim_Length(objv[i]);
 
11716 }
11717 if (objc)
11718 len += objc - 1;
11719
11720 p = bytes = Jim_Alloc(len + 1);
11721 for (i = 0; i < objc; i++) {
11722 const char *s = Jim_GetString(objv[i], &objLen);
11723
11724
11725 while (objLen && isspace(UCHAR(*s))) {
11726 s++;
11727 objLen--;
11728 len--;
11729 }
11730
11731 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
 
11732
11733 if (objLen > 1 && s[objLen - 2] == '\\') {
11734 break;
11735 }
11736 objLen--;
11737 len--;
11738 }
11739 memcpy(p, s, objLen);
11740 p += objLen;
11741 if (i + 1 != objc) {
11742 if (objLen)
11743 *p++ = ' ';
11744 else {
11745 len--;
11746 }
11747 }
11748 }
11749 *p = '\0';
11750 return Jim_NewStringObjNoAlloc(interp, bytes, len);
11751 }
@@ -11489,20 +11785,26 @@
11785
11786 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
11787 {
11788 return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
11789 }
11790
11791 static void *JimObjectHTKeyValDup(void *privdata, const void *val)
11792 {
11793 Jim_IncrRefCount((Jim_Obj *)val);
11794 return (void *)val;
11795 }
11796
11797 static void JimObjectHTKeyValDestructor(void *interp, void *val)
11798 {
11799 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11800 }
11801
11802 static const Jim_HashTableType JimDictHashTableType = {
11803 JimObjectHTHashFunction,
11804 JimObjectHTKeyValDup,
11805 JimObjectHTKeyValDup,
11806 JimObjectHTKeyCompare,
11807 JimObjectHTKeyValDestructor,
11808 JimObjectHTKeyValDestructor
11809 };
11810
@@ -11523,64 +11825,58 @@
11825 }
11826
11827 void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
11828 {
11829 Jim_HashTable *ht, *dupHt;
11830 Jim_HashTableIterator htiter;
11831 Jim_HashEntry *he;
11832
11833
11834 ht = srcPtr->internalRep.ptr;
11835 dupHt = Jim_Alloc(sizeof(*dupHt));
11836 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11837 if (ht->size != 0)
11838 Jim_ExpandHashTable(dupHt, ht->size);
11839
11840 JimInitHashTableIterator(ht, &htiter);
11841 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11842 Jim_AddHashEntry(dupHt, he->key, he->u.val);
11843 }
 
 
 
 
 
 
11844
11845 dupPtr->internalRep.ptr = dupHt;
11846 dupPtr->typePtr = &dictObjType;
11847 }
11848
11849 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
11850 {
11851 Jim_HashTable *ht;
11852 Jim_HashTableIterator htiter;
11853 Jim_HashEntry *he;
11854 Jim_Obj **objv;
11855 int i;
11856
11857 ht = dictPtr->internalRep.ptr;
11858
11859
11860 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11861 JimInitHashTableIterator(ht, &htiter);
11862 i = 0;
11863 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11864 objv[i++] = Jim_GetHashEntryKey(he);
11865 objv[i++] = Jim_GetHashEntryVal(he);
11866 }
11867 *len = i;
 
11868 return objv;
11869 }
11870
11871 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11872 {
11873
11874 int len;
11875 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11876
11877
11878 JimMakeListStringRep(objPtr, objv, len);
11879
11880 Jim_Free(objv);
11881 }
11882
@@ -11590,11 +11886,13 @@
11886
11887 if (objPtr->typePtr == &dictObjType) {
11888 return JIM_OK;
11889 }
11890
11891 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11892 Jim_String(objPtr);
11893 }
11894
11895
11896 listlen = Jim_ListLength(interp, objPtr);
11897 if (listlen % 2) {
11898 Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11607,28 +11905,14 @@
11905
11906 ht = Jim_Alloc(sizeof(*ht));
11907 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
11908
11909 for (i = 0; i < listlen; i += 2) {
11910 Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
11911 Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
11912
11913 Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11914 }
11915
11916 Jim_FreeIntRep(interp, objPtr);
11917 objPtr->typePtr = &dictObjType;
11918 objPtr->internalRep.ptr = ht;
@@ -11645,31 +11929,23 @@
11929 Jim_HashTable *ht = objPtr->internalRep.ptr;
11930
11931 if (valueObjPtr == NULL) {
11932 return Jim_DeleteHashEntry(ht, keyObjPtr);
11933 }
11934 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
 
 
 
 
 
11935 return JIM_OK;
11936 }
11937
11938 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
11939 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
11940 {
 
 
11941 JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
11942 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
11943 return JIM_ERR;
11944 }
 
11945 Jim_InvalidateStringRep(objPtr);
11946 return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
11947 }
11948
11949 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
11950 {
11951 Jim_Obj *objPtr;
@@ -11796,10 +12072,11 @@
12072 }
12073 objPtr = Jim_NewDictObj(interp, NULL, 0);
12074 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12075 }
12076 }
12077
12078 Jim_InvalidateStringRep(objPtr);
12079 Jim_InvalidateStringRep(varObjPtr);
12080 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12081 goto err;
12082 }
@@ -11821,28 +12098,29 @@
12098 NULL,
12099 UpdateStringOfIndex,
12100 JIM_TYPE_NONE,
12101 };
12102
12103 static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
12104 {
12105 if (objPtr->internalRep.intValue == -1) {
12106 JimSetStringBytes(objPtr, "end");
12107 }
 
 
 
 
12108 else {
12109 char buf[JIM_INTEGER_SPACE + 1];
12110 if (objPtr->internalRep.intValue >= 0) {
12111 sprintf(buf, "%d", objPtr->internalRep.intValue);
12112 }
12113 else {
12114
12115 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12116 }
12117 JimSetStringBytes(objPtr, buf);
12118 }
 
 
 
12119 }
12120
12121 static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12122 {
12123 int idx, end = 0;
12124 const char *str;
12125 char *endptr;
12126
@@ -11910,14 +12188,17 @@
12188 {
12189
12190 if (objPtr->typePtr == &intObjType) {
12191 jim_wide val = JimWideValue(objPtr);
12192
12193 if (val < 0)
12194 *indexPtr = -INT_MAX;
12195 else if (val > INT_MAX)
12196 *indexPtr = INT_MAX;
12197 else
12198 *indexPtr = (int)val;
12199 return JIM_OK;
12200 }
12201 if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
12202 return JIM_ERR;
12203 *indexPtr = objPtr->internalRep.intValue;
12204 return JIM_OK;
@@ -11937,12 +12218,10 @@
12218 NULL
12219 };
12220
12221 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
12222
 
 
12223 static const Jim_ObjType returnCodeObjType = {
12224 "return-code",
12225 NULL,
12226 NULL,
12227 NULL,
@@ -11957,11 +12236,11 @@
12236 else {
12237 return jimReturnCodes[code];
12238 }
12239 }
12240
12241 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12242 {
12243 int returnCode;
12244 jim_wide wideValue;
12245
12246
@@ -12089,14 +12368,15 @@
12368
12369
12370 typedef struct Jim_ExprOperator
12371 {
12372 const char *name;
 
 
12373 int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12374 unsigned char precedence;
12375 unsigned char arity;
12376 unsigned char lazy;
12377 unsigned char namelen;
12378 } Jim_ExprOperator;
12379
12380 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12381 {
12382 Jim_IncrRefCount(obj);
@@ -12108,24 +12388,21 @@
12388 return e->stack[--e->stacklen];
12389 }
12390
12391 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12392 {
12393 int intresult = 1;
12394 int rc = JIM_OK;
12395 Jim_Obj *A = ExprPop(e);
12396 double dA, dC = 0;
12397 jim_wide wA, wC = 0;
12398
12399 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
 
 
12400 switch (e->opcode) {
12401 case JIM_EXPROP_FUNC_INT:
 
 
12402 case JIM_EXPROP_FUNC_ROUND:
12403 case JIM_EXPROP_UNARYPLUS:
12404 wC = wA;
12405 break;
12406 case JIM_EXPROP_FUNC_DOUBLE:
12407 dC = wA;
12408 intresult = 0;
@@ -12134,13 +12411,10 @@
12411 wC = wA >= 0 ? wA : -wA;
12412 break;
12413 case JIM_EXPROP_UNARYMINUS:
12414 wC = -wA;
12415 break;
 
 
 
12416 case JIM_EXPROP_NOT:
12417 wC = !wA;
12418 break;
12419 default:
12420 abort();
@@ -12148,31 +12422,29 @@
12422 }
12423 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12424 switch (e->opcode) {
12425 case JIM_EXPROP_FUNC_INT:
12426 wC = dA;
 
12427 break;
12428 case JIM_EXPROP_FUNC_ROUND:
12429 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
 
12430 break;
12431 case JIM_EXPROP_FUNC_DOUBLE:
12432 case JIM_EXPROP_UNARYPLUS:
12433 dC = dA;
12434 intresult = 0;
12435 break;
12436 case JIM_EXPROP_FUNC_ABS:
12437 dC = dA >= 0 ? dA : -dA;
12438 intresult = 0;
12439 break;
12440 case JIM_EXPROP_UNARYMINUS:
12441 dC = -dA;
12442 intresult = 0;
 
 
12443 break;
12444 case JIM_EXPROP_NOT:
12445 wC = !dA;
 
12446 break;
12447 default:
12448 abort();
12449 }
12450 }
@@ -12383,11 +12655,11 @@
12655
12656
12657
12658 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12659 {
12660 int intresult = 1;
12661 int rc = JIM_OK;
12662 double dA, dB, dC = 0;
12663 jim_wide wA, wB, wC = 0;
12664
12665 Jim_Obj *B = ExprPop(e);
@@ -12397,12 +12669,10 @@
12669 (B->typePtr != &doubleObjType || B->bytes) &&
12670 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12671
12672
12673
 
 
12674 switch (e->opcode) {
12675 case JIM_EXPROP_POW:
12676 case JIM_EXPROP_FUNC_POW:
12677 wC = JimPowWide(wA, wB);
12678 break;
@@ -12452,10 +12722,11 @@
12722 default:
12723 abort();
12724 }
12725 }
12726 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12727 intresult = 0;
12728 switch (e->opcode) {
12729 case JIM_EXPROP_POW:
12730 case JIM_EXPROP_FUNC_POW:
12731 #ifdef JIM_MATH_FUNCTIONS
12732 dC = pow(dA, dB);
@@ -12517,12 +12788,10 @@
12788
12789
12790
12791 int i = Jim_StringCompareObj(interp, A, B, 0);
12792
 
 
12793 switch (e->opcode) {
12794 case JIM_EXPROP_LT:
12795 wC = i < 0;
12796 break;
12797 case JIM_EXPROP_GT:
@@ -12566,15 +12835,11 @@
12835 int listlen;
12836 int i;
12837
12838 listlen = Jim_ListLength(interp, listObjPtr);
12839 for (i = 0; i < listlen; i++) {
12840 if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
 
 
 
 
12841 return 1;
12842 }
12843 }
12844 return 0;
12845 }
@@ -12586,23 +12851,16 @@
12851
12852 jim_wide wC;
12853
12854 switch (e->opcode) {
12855 case JIM_EXPROP_STREQ:
12856 case JIM_EXPROP_STRNE:
12857 wC = Jim_StringEqObj(A, B);
12858 if (e->opcode == JIM_EXPROP_STRNE) {
12859 wC = !wC;
 
 
 
 
 
 
12860 }
12861 break;
 
12862 case JIM_EXPROP_STRIN:
12863 wC = JimSearchList(interp, B, A);
12864 break;
12865 case JIM_EXPROP_STRNI:
12866 wC = !JimSearchList(interp, B, A);
@@ -12774,93 +13032,98 @@
13032 LAZY_OP,
13033 LAZY_LEFT,
13034 LAZY_RIGHT
13035 };
13036
13037 #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13038 #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13039
13040 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13041 OPRINIT("*", 110, 2, JimExprOpBin),
13042 OPRINIT("/", 110, 2, JimExprOpBin),
13043 OPRINIT("%", 110, 2, JimExprOpIntBin),
13044
13045 OPRINIT("-", 100, 2, JimExprOpBin),
13046 OPRINIT("+", 100, 2, JimExprOpBin),
13047
13048 OPRINIT("<<", 90, 2, JimExprOpIntBin),
13049 OPRINIT(">>", 90, 2, JimExprOpIntBin),
13050
13051 OPRINIT("<<<", 90, 2, JimExprOpIntBin),
13052 OPRINIT(">>>", 90, 2, JimExprOpIntBin),
13053
13054 OPRINIT("<", 80, 2, JimExprOpBin),
13055 OPRINIT(">", 80, 2, JimExprOpBin),
13056 OPRINIT("<=", 80, 2, JimExprOpBin),
13057 OPRINIT(">=", 80, 2, JimExprOpBin),
13058
13059 OPRINIT("==", 70, 2, JimExprOpBin),
13060 OPRINIT("!=", 70, 2, JimExprOpBin),
13061
13062 OPRINIT("&", 50, 2, JimExprOpIntBin),
13063 OPRINIT("^", 49, 2, JimExprOpIntBin),
13064 OPRINIT("|", 48, 2, JimExprOpIntBin),
13065
13066 OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13067 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13068 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13069
13070 OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13071 OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13072 OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13073
13074 OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13075 OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13076 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13077
13078 OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13079 OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13080 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13081
13082 OPRINIT("**", 250, 2, JimExprOpBin),
13083
13084 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13085 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13086
13087 OPRINIT("in", 55, 2, JimExprOpStrBin),
13088 OPRINIT("ni", 55, 2, JimExprOpStrBin),
13089
13090 OPRINIT("!", 150, 1, JimExprOpNumUnary),
13091 OPRINIT("~", 150, 1, JimExprOpIntUnary),
13092 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13093 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13094
13095
13096
13097 OPRINIT("int", 200, 1, JimExprOpNumUnary),
13098 OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13099 OPRINIT("double", 200, 1, JimExprOpNumUnary),
13100 OPRINIT("round", 200, 1, JimExprOpNumUnary),
13101 OPRINIT("rand", 200, 0, JimExprOpNone),
13102 OPRINIT("srand", 200, 1, JimExprOpIntUnary),
13103
13104 #ifdef JIM_MATH_FUNCTIONS
13105 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13106 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13107 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13108 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13109 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13110 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13111 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13112 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13113 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13114 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13115 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13116 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13117 OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13118 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13119 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13120 OPRINIT("pow", 200, 2, JimExprOpBin),
13121 #endif
13122 };
13123 #undef OPRINIT
13124 #undef OPRINIT_LAZY
13125
13126 #define JIM_EXPR_OPERATORS_NUM \
13127 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13128
13129 static int JimParseExpression(struct JimParserCtx *pc)
@@ -12872,13 +13135,16 @@
13135 }
13136 pc->p++;
13137 pc->len--;
13138 }
13139
13140
13141 pc->tline = pc->linenr;
13142 pc->tstart = pc->p;
13143
13144 if (pc->len == 0) {
13145 pc->tend = pc->p;
 
13146 pc->tt = JIM_TT_EOL;
13147 pc->eof = 1;
13148 return JIM_OK;
13149 }
13150 switch (*(pc->p)) {
@@ -12889,12 +13155,11 @@
13155 pc->tt = JIM_TT_SUBEXPR_END;
13156 goto singlechar;
13157 case ',':
13158 pc->tt = JIM_TT_SUBEXPR_COMMA;
13159 singlechar:
13160 pc->tend = pc->p;
 
13161 pc->p++;
13162 pc->len--;
13163 break;
13164 case '[':
13165 return JimParseCmd(pc);
@@ -12940,82 +13205,44 @@
13205 return JIM_OK;
13206 }
13207
13208 static int JimParseExprNumber(struct JimParserCtx *pc)
13209 {
13210 char *end;
 
13211
13212
13213 pc->tt = JIM_TT_EXPR_INT;
13214
13215 jim_strtoull(pc->p, (char **)&pc->p);
13216
13217 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13218 if (strtod(pc->tstart, &end)) { }
13219 if (end == pc->tstart)
13220 return JIM_ERR;
13221 if (end > pc->p) {
13222
13223 pc->tt = JIM_TT_EXPR_DOUBLE;
13224 pc->p = end;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13225 }
13226 }
13227 pc->tend = pc->p - 1;
13228 pc->len -= (pc->p - pc->tstart);
13229 return JIM_OK;
13230 }
13231
13232 static int JimParseExprIrrational(struct JimParserCtx *pc)
13233 {
13234 const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13235 int i;
13236
13237 for (i = 0; irrationals[i]; i++) {
13238 const char *irr = irrationals[i];
13239
13240 if (strncmp(irr, pc->p, 3) == 0) {
13241 pc->p += 3;
13242 pc->len -= 3;
13243 pc->tend = pc->p - 1;
 
 
13244 pc->tt = JIM_TT_EXPR_DOUBLE;
13245 return JIM_OK;
13246 }
13247 }
13248 return JIM_ERR;
@@ -13026,20 +13253,18 @@
13253 int i;
13254 int bestIdx = -1, bestLen = 0;
13255
13256
13257 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13258 const char * const opname = Jim_ExprOperators[i].name;
13259 const int oplen = Jim_ExprOperators[i].namelen;
13260
13261 if (opname == NULL || opname[0] != pc->p[0]) {
 
13262 continue;
13263 }
 
13264
13265 if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
13266 bestIdx = i + JIM_TT_EXPR_OP;
13267 bestLen = oplen;
13268 }
13269 }
13270 if (bestIdx == -1) {
@@ -13057,15 +13282,13 @@
13282 }
13283 if (*p != '(') {
13284 return JIM_ERR;
13285 }
13286 }
 
13287 pc->tend = pc->p + bestLen - 1;
13288 pc->p += bestLen;
13289 pc->len -= bestLen;
 
13290
13291 pc->tt = bestIdx;
13292 return JIM_OK;
13293 }
13294
@@ -13111,12 +13334,12 @@
13334 };
13335
13336
13337 typedef struct ExprByteCode
13338 {
 
13339 ScriptToken *token;
13340 int len;
13341 int inUse;
13342 } ExprByteCode;
13343
13344 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13345 {
@@ -13563,17 +13786,23 @@
13786 }
13787
13788 #ifdef DEBUG_SHOW_EXPR_TOKENS
13789 {
13790 int i;
13791 printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
13792 for (i = 0; i < tokenlist.count; i++) {
13793 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
13794 tokenlist.list[i].len, tokenlist.list[i].token);
13795 }
13796 }
13797 #endif
13798
13799 if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
13800 ScriptTokenListFree(&tokenlist);
13801 Jim_DecrRefCount(interp, fileNameObj);
13802 return JIM_ERR;
13803 }
13804
13805
13806 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
13807
13808
@@ -13620,10 +13849,24 @@
13849 return NULL;
13850 }
13851 }
13852 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13853 }
13854
13855 #ifdef JIM_OPTIMIZATION
13856 static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
13857 {
13858 if (token->type == JIM_TT_EXPR_INT)
13859 return token->objPtr;
13860 else if (token->type == JIM_TT_VAR)
13861 return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
13862 else if (token->type == JIM_TT_DICTSUGAR)
13863 return JimExpandDictSugar(interp, token->objPtr);
13864 else
13865 return NULL;
13866 }
13867 #endif
13868
13869 #define JIM_EE_STATICSTACK_LEN 10
13870
13871 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
13872 {
@@ -13643,102 +13886,69 @@
13886 Jim_Obj *objPtr;
13887
13888
13889 switch (expr->len) {
13890 case 1:
13891 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13892 if (objPtr) {
13893 Jim_IncrRefCount(objPtr);
13894 *exprResultPtrPtr = objPtr;
13895 return JIM_OK;
 
 
 
 
 
 
 
13896 }
13897 break;
13898
13899 case 2:
13900 if (expr->token[1].type == JIM_EXPROP_NOT) {
13901 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13902
13903 if (objPtr && JimIsWide(objPtr)) {
13904 *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
 
 
13905 Jim_IncrRefCount(*exprResultPtrPtr);
13906 return JIM_OK;
13907 }
13908 }
13909 break;
13910
13911 case 3:
13912 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13913 if (objPtr && JimIsWide(objPtr)) {
13914 Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
13915 if (objPtr2 && JimIsWide(objPtr2)) {
13916 jim_wide wideValueA = JimWideValue(objPtr);
13917 jim_wide wideValueB = JimWideValue(objPtr2);
13918 int cmpRes;
13919 switch (expr->token[2].type) {
13920 case JIM_EXPROP_LT:
13921 cmpRes = wideValueA < wideValueB;
13922 break;
13923 case JIM_EXPROP_LTE:
13924 cmpRes = wideValueA <= wideValueB;
13925 break;
13926 case JIM_EXPROP_GT:
13927 cmpRes = wideValueA > wideValueB;
13928 break;
13929 case JIM_EXPROP_GTE:
13930 cmpRes = wideValueA >= wideValueB;
13931 break;
13932 case JIM_EXPROP_NUMEQ:
13933 cmpRes = wideValueA == wideValueB;
13934 break;
13935 case JIM_EXPROP_NUMNE:
13936 cmpRes = wideValueA != wideValueB;
13937 break;
13938 default:
13939 goto noopt;
13940 }
13941 *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
13942 Jim_IncrRefCount(*exprResultPtrPtr);
13943 return JIM_OK;
13944 }
13945 }
13946 break;
13947 }
13948 }
13949 noopt:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13950 #endif
13951
13952 expr->inUse++;
13953
13954
@@ -13855,16 +14065,16 @@
14065
14066
14067
14068 typedef struct ScanFmtPartDescr
14069 {
14070 char *arg;
14071 char *prefix;
14072 size_t width;
14073 int pos;
14074 char type;
14075 char modifier;
14076 } ScanFmtPartDescr;
14077
14078
14079 typedef struct ScanFmtStringObj
14080 {
@@ -13907,16 +14117,13 @@
14117 memcpy(newVec, srcPtr->internalRep.ptr, size);
14118 dupPtr->internalRep.ptr = newVec;
14119 dupPtr->typePtr = &scanFmtStringObjType;
14120 }
14121
14122 static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
14123 {
14124 JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
 
 
 
14125 }
14126
14127
14128 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
14129 {
@@ -14126,11 +14333,10 @@
14333 Jim_Obj *tmpObj = NULL;
14334
14335
14336 *valObjPtr = 0;
14337 if (descr->prefix) {
 
14338 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14339
14340 if (isspace(UCHAR(descr->prefix[i])))
14341 while (pos < strLen && isspace(UCHAR(str[pos])))
14342 ++pos;
@@ -14467,34 +14673,55 @@
14673 }
14674
14675 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14676 {
14677 int retcode;
14678 Jim_Cmd *cmdPtr;
14679
14680 #if 0
14681 printf("invoke");
14682 int j;
14683 for (j = 0; j < objc; j++) {
14684 printf(" '%s'", Jim_String(objv[j]));
14685 }
14686 printf("\n");
14687 #endif
14688
14689 if (interp->framePtr->tailcallCmd) {
14690
14691 cmdPtr = interp->framePtr->tailcallCmd;
14692 interp->framePtr->tailcallCmd = NULL;
14693 }
14694 else {
14695 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14696 if (cmdPtr == NULL) {
14697 return JimUnknown(interp, objc, objv);
14698 }
14699 JimIncrCmdRefCount(cmdPtr);
14700 }
14701
14702 if (interp->evalDepth == interp->maxEvalDepth) {
14703 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14704 retcode = JIM_ERR;
14705 goto out;
14706 }
14707 interp->evalDepth++;
14708
14709
 
14710 Jim_SetEmptyResult(interp);
14711 if (cmdPtr->isproc) {
14712 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14713 }
14714 else {
14715 interp->cmdPrivData = cmdPtr->u.native.privData;
14716 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14717 }
 
14718 interp->evalDepth--;
14719
14720 out:
14721 JimDecrCmdRefCount(interp, cmdPtr);
14722
14723 return retcode;
14724 }
14725
14726 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14727 {
@@ -14672,10 +14899,15 @@
14899 objPtr->typePtr = &interpolatedObjType;
14900 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14901 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14902 Jim_IncrRefCount(intv[2]);
14903 }
14904 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
14905
14906 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
14907 }
14908
14909
14910 s = objPtr->bytes = Jim_Alloc(totlen + 1);
14911 objPtr->length = totlen;
14912 for (i = 0; i < tokens; i++) {
14913 if (intv[i]) {
@@ -14727,10 +14959,14 @@
14959 return JimEvalObjList(interp, scriptObjPtr);
14960 }
14961
14962 Jim_IncrRefCount(scriptObjPtr);
14963 script = Jim_GetScript(interp, scriptObjPtr);
14964 if (script == NULL) {
14965 Jim_DecrRefCount(interp, scriptObjPtr);
14966 return JIM_ERR;
14967 }
14968
14969 Jim_SetEmptyResult(interp);
14970
14971 token = script->token;
14972
@@ -14871,12 +15107,12 @@
15107 }
15108
15109 if (retcode == JIM_OK && argc) {
15110
15111 retcode = JimInvokeCommand(interp, argc, argv);
15112
15113 if (Jim_CheckSignal(interp)) {
15114 retcode = JIM_SIGNAL;
15115 }
15116 }
15117
15118
@@ -15001,26 +15237,20 @@
15237 retcode = Jim_EvalObj(interp, scriptObj);
15238 }
15239
15240
15241 interp->framePtr = interp->framePtr->parent;
15242 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
 
 
 
 
 
15243
15244 return retcode;
15245 }
15246 #endif
15247
15248 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
15249 {
15250 Jim_CallFrame *callFramePtr;
15251 int i, d, retcode, optargs;
 
15252 ScriptObj *script;
15253
15254
15255 if (argc - 1 < cmd->u.proc.reqArity ||
15256 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15100,37 +15330,42 @@
15330
15331
15332 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15333
15334 badargset:
15335
15336
 
 
 
 
15337 interp->framePtr = interp->framePtr->parent;
15338 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15339
15340 if (interp->framePtr->tailcallObj) {
15341
15342 if (interp->framePtr->tailcall++ == 0) {
15343
15344 do {
15345 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15346
15347 interp->framePtr->tailcallObj = NULL;
15348
15349 if (retcode == JIM_EVAL) {
15350 retcode = Jim_EvalObjList(interp, tailcallObj);
15351 if (retcode == JIM_RETURN) {
15352 interp->returnLevel++;
15353 }
15354 }
15355 Jim_DecrRefCount(interp, tailcallObj);
15356 } while (interp->framePtr->tailcallObj);
15357
15358
15359 if (interp->framePtr->tailcallCmd) {
15360 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15361 interp->framePtr->tailcallCmd = NULL;
15362 }
15363 }
15364 interp->framePtr->tailcall--;
15365 }
15366
15367
15368 if (retcode == JIM_RETURN) {
15369 if (--interp->returnLevel <= 0) {
15370 retcode = interp->returnCode;
15371 interp->returnCode = JIM_OK;
@@ -15142,13 +15377,10 @@
15377 Jim_DecrRefCount(interp, interp->errorProc);
15378 interp->errorProc = argv[0];
15379 Jim_IncrRefCount(interp->errorProc);
15380 }
15381
 
 
 
15382 return retcode;
15383 }
15384
15385 int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
15386 {
@@ -15216,11 +15448,10 @@
15448 Jim_Obj *scriptObjPtr;
15449 Jim_Obj *prevScriptObj;
15450 struct stat sb;
15451 int retcode;
15452 int readlen;
 
15453
15454 if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
15455 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
15456 return JIM_ERR;
15457 }
@@ -15243,31 +15474,13 @@
15474 scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
15475 JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
15476 Jim_IncrRefCount(scriptObjPtr);
15477
15478
15479 if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
15480
15481 JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15482 Jim_DecrRefCount(interp, scriptObjPtr);
15483 return JIM_ERR;
15484 }
15485
15486 prevScriptObj = interp->currentScriptObj;
@@ -15430,11 +15643,11 @@
15643 }
15644
15645 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15646 Jim_HashEntry *he, int type);
15647
15648 #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15649
15650 static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
15651 JimHashtableIteratorCallbackType *callback, int type)
15652 {
15653 Jim_HashEntry *he;
@@ -15446,17 +15659,17 @@
15659 if (he) {
15660 callback(interp, listObjPtr, he, type);
15661 }
15662 }
15663 else {
15664 Jim_HashTableIterator htiter;
15665 JimInitHashTableIterator(ht, &htiter);
15666 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
15667 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
15668 callback(interp, listObjPtr, he, type);
15669 }
15670 }
 
15671 }
15672 return listObjPtr;
15673 }
15674
15675
@@ -15465,11 +15678,11 @@
15678 #define JIM_CMDLIST_CHANNELS 2
15679
15680 static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15681 Jim_HashEntry *he, int type)
15682 {
15683 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15684 Jim_Obj *objPtr;
15685
15686 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15687
15688 return;
@@ -15498,11 +15711,11 @@
15711 #define JIM_VARLIST_VALUES 0x1000
15712
15713 static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15714 Jim_HashEntry *he, int type)
15715 {
15716 Jim_Var *varPtr = Jim_GetHashEntryVal(he);
15717
15718 if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
15719 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
15720 if (type & JIM_VARLIST_VALUES) {
15721 Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15820,11 +16033,11 @@
16033
16034 expr = JimGetExpression(interp, argv[2]);
16035 incrScript = Jim_GetScript(interp, argv[3]);
16036
16037
16038 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16039 goto evalstart;
16040 }
16041
16042 if (incrScript->token[1].type != JIM_TT_ESC ||
16043 expr->token[0].type != JIM_TT_VAR ||
@@ -16043,11 +16256,11 @@
16256 }
16257
16258
16259 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16260 {
16261 int result = JIM_OK;
16262 int i, numargs;
16263 Jim_ListIter twoiters[2];
16264 Jim_ListIter *iters;
16265 Jim_Obj *script;
16266 Jim_Obj *resultObj;
@@ -16066,13 +16279,16 @@
16279 iters = Jim_Alloc(numargs * sizeof(*iters));
16280 }
16281 for (i = 0; i < numargs; i++) {
16282 JimListIterInit(&iters[i], argv[i + 1]);
16283 if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16284 result = JIM_ERR;
 
16285 }
16286 }
16287 if (result != JIM_OK) {
16288 Jim_SetResultString(interp, "foreach varlist is empty", -1);
16289 return result;
16290 }
16291
16292 if (doMap) {
16293 resultObj = Jim_NewListObj(interp, NULL, 0);
16294 }
@@ -16385,12 +16601,12 @@
16601 {
16602 Jim_Obj *objPtr, *listObjPtr;
16603 int i;
16604 int idx;
16605
16606 if (argc < 2) {
16607 Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
16608 return JIM_ERR;
16609 }
16610 objPtr = argv[1];
16611 Jim_IncrRefCount(objPtr);
16612 for (i = 2; i < argc; i++) {
@@ -16502,14 +16718,13 @@
16718 Jim_IncrRefCount(commandObj);
16719 }
16720
16721 listlen = Jim_ListLength(interp, argv[0]);
16722 for (i = 0; i < listlen; i++) {
 
16723 int eq = 0;
16724 Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
16725
 
16726 switch (opt_match) {
16727 case OPT_EXACT:
16728 eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
16729 break;
16730
@@ -16699,29 +16914,27 @@
16914 if (argc < 3) {
16915 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16916 return JIM_ERR;
16917 }
16918 else if (argc == 3) {
16919
16920 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16921 return JIM_ERR;
16922 Jim_SetResult(interp, argv[2]);
16923 return JIM_OK;
16924 }
16925 return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
 
 
 
16926 }
16927
16928
16929 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
16930 {
16931 static const char * const options[] = {
16932 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
16933 };
16934 enum
16935 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
16936 Jim_Obj *resObj;
16937 int i;
16938 int retCode;
16939
16940 struct lsort_info info;
@@ -16732,17 +16945,18 @@
16945 }
16946
16947 info.type = JIM_LSORT_ASCII;
16948 info.order = 1;
16949 info.indexed = 0;
16950 info.unique = 0;
16951 info.command = NULL;
16952 info.interp = interp;
16953
16954 for (i = 1; i < (argc - 1); i++) {
16955 int option;
16956
16957 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
16958 != JIM_OK)
16959 return JIM_ERR;
16960 switch (option) {
16961 case OPT_ASCII:
16962 info.type = JIM_LSORT_ASCII;
@@ -16751,16 +16965,22 @@
16965 info.type = JIM_LSORT_NOCASE;
16966 break;
16967 case OPT_INTEGER:
16968 info.type = JIM_LSORT_INTEGER;
16969 break;
16970 case OPT_REAL:
16971 info.type = JIM_LSORT_REAL;
16972 break;
16973 case OPT_INCREASING:
16974 info.order = 1;
16975 break;
16976 case OPT_DECREASING:
16977 info.order = -1;
16978 break;
16979 case OPT_UNIQUE:
16980 info.unique = 1;
16981 break;
16982 case OPT_COMMAND:
16983 if (i >= (argc - 2)) {
16984 Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
16985 return JIM_ERR;
16986 }
@@ -16870,20 +17090,20 @@
17090 static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17091 {
17092 if (argc >= 2) {
17093 int retcode;
17094 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17095 int savedTailcall;
17096 const char *str;
17097
17098
17099 savedCallFrame = interp->framePtr;
17100
17101
17102 str = Jim_String(argv[1]);
17103 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17104 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17105 argc--;
17106 argv++;
17107 }
17108 else {
17109 targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16890,25 +17110,25 @@
17110 }
17111 if (targetCallFrame == NULL) {
17112 return JIM_ERR;
17113 }
17114 if (argc < 2) {
17115 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
 
17116 return JIM_ERR;
17117 }
17118
17119 interp->framePtr = targetCallFrame;
17120
17121 savedTailcall = interp->framePtr->tailcall;
17122 interp->framePtr->tailcall = 0;
17123 if (argc == 2) {
17124 retcode = Jim_EvalObj(interp, argv[1]);
17125 }
17126 else {
17127 retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
 
 
 
17128 }
17129 interp->framePtr->tailcall = savedTailcall;
17130 interp->framePtr = savedCallFrame;
17131 return retcode;
17132 }
17133 else {
17134 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17019,12 +17239,39 @@
17239 }
17240
17241
17242 static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17243 {
17244 if (interp->framePtr->level == 0) {
17245 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17246 return JIM_ERR;
17247 }
17248 else if (argc >= 2) {
17249
17250 Jim_CallFrame *cf = interp->framePtr->parent;
17251
17252 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17253 if (cmdPtr == NULL) {
17254 return JIM_ERR;
17255 }
17256
17257 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17258
17259
17260 JimIncrCmdRefCount(cmdPtr);
17261 cf->tailcallCmd = cmdPtr;
17262
17263
17264 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17265
17266 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17267 Jim_IncrRefCount(cf->tailcallObj);
17268
17269
17270 return JIM_EVAL;
17271 }
17272 return JIM_OK;
17273 }
17274
17275 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17276 {
17277 Jim_Obj *cmdList;
@@ -17108,10 +17355,15 @@
17355
17356
17357 static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17358 {
17359 int retcode;
17360
17361 if (argc < 2) {
17362 Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17363 return JIM_ERR;
17364 }
17365
17366
17367 interp->local++;
17368 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17369 interp->local--;
@@ -17304,11 +17556,11 @@
17556 for (i = 0; i < numMaps; i += 2) {
17557 Jim_Obj *objPtr;
17558 const char *k;
17559 int kl;
17560
17561 objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17562 k = Jim_String(objPtr);
17563 kl = Jim_Utf8Length(interp, objPtr);
17564
17565 if (strLen >= kl && kl) {
17566 int rc;
@@ -17316,12 +17568,11 @@
17568 if (rc == 0) {
17569 if (noMatchStart) {
17570 Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
17571 noMatchStart = NULL;
17572 }
17573 Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
 
17574 str += utf8_index(str, kl);
17575 strLen -= kl;
17576 break;
17577 }
17578 }
@@ -17795,21 +18046,23 @@
18046 if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
18047 sig++;
18048 }
18049
18050 interp->signal_level += sig;
18051 if (Jim_CheckSignal(interp)) {
18052
18053 exitCode = JIM_SIGNAL;
18054 }
18055 else {
18056 exitCode = Jim_EvalObj(interp, argv[0]);
18057
18058 interp->errorFlag = 0;
18059 }
18060 interp->signal_level -= sig;
18061
18062
18063 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18064
18065 return exitCode;
18066 }
18067
18068 if (sig && exitCode == JIM_SIGNAL) {
@@ -17951,25 +18204,24 @@
18204
18205
18206 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18207 {
18208 Jim_Obj *listObjPtr;
18209 Jim_HashTableIterator htiter;
18210 Jim_HashEntry *he;
18211
18212 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18213
18214 JimInitHashTableIterator(&interp->references, &htiter);
18215 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18216 char buf[JIM_REFERENCE_SPACE + 1];
18217 Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18218 const unsigned long *refId = he->key;
18219
18220 JimFormatReference(buf, refPtr, *refId);
18221 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18222 }
 
18223 Jim_SetResult(interp, listObjPtr);
18224 return JIM_OK;
18225 }
18226 #endif
18227
@@ -17994,11 +18246,11 @@
18246
18247 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18248 {
18249 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18250 if (type & JIM_DICTMATCH_VALUES) {
18251 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18252 }
18253 }
18254
18255 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18256 JimDictMatchCallbackType *callback, int type)
@@ -18005,17 +18257,17 @@
18257 {
18258 Jim_HashEntry *he;
18259 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18260
18261
18262 Jim_HashTableIterator htiter;
18263 JimInitHashTableIterator(ht, &htiter);
18264 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18265 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18266 callback(interp, listObjPtr, he, type);
18267 }
18268 }
 
18269
18270 return listObjPtr;
18271 }
18272
18273
@@ -18043,21 +18295,65 @@
18295 return -1;
18296 }
18297 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18298 }
18299
18300 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18301 {
18302 Jim_HashTable *ht;
18303 unsigned int i;
18304
18305 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18306 return JIM_ERR;
18307 }
18308
18309 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18310
18311
18312 printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18313
18314 for (i = 0; i < ht->size; i++) {
18315 Jim_HashEntry *he = ht->table[i];
18316
18317 if (he) {
18318 printf("%d: ", i);
18319
18320 while (he) {
18321 printf(" %s", Jim_String(he->key));
18322 he = he->next;
18323 }
18324 printf("\n");
18325 }
18326 }
18327 return JIM_OK;
18328 }
18329
18330 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18331 {
18332 Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
18333
18334 Jim_AppendString(interp, prefixObj, " ", 1);
18335 Jim_AppendString(interp, prefixObj, subcmd, -1);
18336
18337 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18338 }
18339
18340
18341 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18342 {
18343 Jim_Obj *objPtr;
18344 int option;
18345 static const char * const options[] = {
18346 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18347 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18348 "replace", "update", NULL
18349 };
18350 enum
18351 {
18352 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
18353 OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
18354 OPT_REPLACE, OPT_UPDATE,
18355 };
18356
18357 if (argc < 2) {
18358 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18359 return JIM_ERR;
@@ -18068,11 +18364,11 @@
18364 }
18365
18366 switch (option) {
18367 case OPT_GET:
18368 if (argc < 3) {
18369 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
18370 return JIM_ERR;
18371 }
18372 if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
18373 JIM_ERRMSG) != JIM_OK) {
18374 return JIM_ERR;
@@ -18085,82 +18381,87 @@
18381 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
18382 return JIM_ERR;
18383 }
18384 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
18385
18386 case OPT_EXISTS:
18387 if (argc < 4) {
18388 Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
18389 return JIM_ERR;
18390 }
18391 else {
18392 int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
18393 if (rc < 0) {
18394 return JIM_ERR;
18395 }
18396 Jim_SetResultBool(interp, rc == JIM_OK);
18397 return JIM_OK;
18398 }
18399
18400 case OPT_UNSET:
18401 if (argc < 4) {
18402 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
18403 return JIM_ERR;
18404 }
18405 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18406 return JIM_ERR;
18407 }
18408 return JIM_OK;
18409
18410 case OPT_KEYS:
18411 if (argc != 3 && argc != 4) {
18412 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18413 return JIM_ERR;
18414 }
18415 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18416
18417 case OPT_SIZE:
 
 
18418 if (argc != 3) {
18419 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18420 return JIM_ERR;
18421 }
18422 else if (Jim_DictSize(interp, argv[2]) < 0) {
 
 
18423 return JIM_ERR;
18424 }
18425 Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
18426 return JIM_OK;
 
18427
18428 case OPT_MERGE:
18429 if (argc == 2) {
18430 return JIM_OK;
18431 }
18432 if (Jim_DictSize(interp, argv[2]) < 0) {
18433 return JIM_ERR;
18434 }
18435
18436 break;
18437
18438 case OPT_UPDATE:
18439 if (argc < 6 || argc % 2) {
18440
18441 argc = 2;
18442 }
18443 break;
 
 
 
 
 
 
18444
18445 case OPT_CREATE:
18446 if (argc % 2) {
18447 Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
18448 return JIM_ERR;
18449 }
18450 objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
18451 Jim_SetResult(interp, objPtr);
18452 return JIM_OK;
18453
18454 case OPT_INFO:
18455 if (argc != 3) {
18456 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18457 return JIM_ERR;
18458 }
18459 return Jim_DictInfo(interp, argv[2]);
18460 }
18461
18462 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18463 }
18464
18465
18466 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18467 {
@@ -18218,11 +18519,11 @@
18519 };
18520 enum
18521 { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
18522 INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
18523 INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18524 INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
18525 };
18526
18527 #ifdef jim_ext_namespace
18528 int nons = 0;
18529
@@ -18998,11 +19299,11 @@
19299 }
19300 }
19301
19302 static const struct {
19303 const char *name;
19304 Jim_CmdProc *cmdProc;
19305 } Jim_CoreCommandsTable[] = {
19306 {"alias", Jim_AliasCoreCommand},
19307 {"set", Jim_SetCoreCommand},
19308 {"unset", Jim_UnsetCoreCommand},
19309 {"puts", Jim_PutsCoreCommand},
@@ -19230,10 +19531,12 @@
19531 }
19532
19533 len += extra;
19534 buf = Jim_Alloc(len + 1);
19535 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19536
19537 va_end(args);
19538
19539 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19540 }
19541
19542
@@ -19481,344 +19784,373 @@
19784
19785 #include <ctype.h>
19786 #include <string.h>
19787
19788
 
19789 #define JIM_INTEGER_SPACE 24
19790 #define MAX_FLOAT_WIDTH 320
19791
19792 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
19793 {
19794 const char *span, *format, *formatEnd, *msg;
19795 int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
19796 static const char * const mixedXPG =
19797 "cannot mix \"%\" and \"%n$\" conversion specifiers";
19798 static const char * const badIndex[2] = {
19799 "not enough arguments for all format specifiers",
19800 "\"%n$\" argument index out of range"
19801 };
19802 int formatLen;
19803 Jim_Obj *resultPtr;
19804
19805 char *num_buffer = NULL;
19806 int num_buffer_size = 0;
19807
19808 span = format = Jim_GetString(fmtObjPtr, &formatLen);
19809 formatEnd = format + formatLen;
19810 resultPtr = Jim_NewEmptyStringObj(interp);
19811
19812 while (format != formatEnd) {
19813 char *end;
19814 int gotMinus, sawFlag;
19815 int gotPrecision, useShort;
19816 long width, precision;
19817 int newXpg;
19818 int ch;
19819 int step;
19820 int doubleType;
19821 char pad = ' ';
19822 char spec[2*JIM_INTEGER_SPACE + 12];
19823 char *p;
19824
19825 int formatted_chars;
19826 int formatted_bytes;
19827 const char *formatted_buf;
19828
19829 step = utf8_tounicode(format, &ch);
19830 format += step;
19831 if (ch != '%') {
19832 numBytes += step;
19833 continue;
19834 }
19835 if (numBytes) {
19836 Jim_AppendString(interp, resultPtr, span, numBytes);
19837 numBytes = 0;
19838 }
19839
19840
19841 step = utf8_tounicode(format, &ch);
19842 if (ch == '%') {
19843 span = format;
19844 numBytes = step;
19845 format += step;
19846 continue;
19847 }
19848
19849
19850 newXpg = 0;
19851 if (isdigit(ch)) {
19852 int position = strtoul(format, &end, 10);
19853 if (*end == '$') {
19854 newXpg = 1;
19855 objIndex = position - 1;
19856 format = end + 1;
19857 step = utf8_tounicode(format, &ch);
19858 }
19859 }
19860 if (newXpg) {
19861 if (gotSequential) {
19862 msg = mixedXPG;
19863 goto errorMsg;
19864 }
19865 gotXpg = 1;
19866 } else {
19867 if (gotXpg) {
19868 msg = mixedXPG;
19869 goto errorMsg;
19870 }
19871 gotSequential = 1;
19872 }
19873 if ((objIndex < 0) || (objIndex >= objc)) {
19874 msg = badIndex[gotXpg];
19875 goto errorMsg;
19876 }
19877
19878 p = spec;
19879 *p++ = '%';
19880
19881 gotMinus = 0;
19882 sawFlag = 1;
19883 do {
19884 switch (ch) {
19885 case '-':
19886 gotMinus = 1;
19887 break;
19888 case '0':
19889 pad = ch;
19890 break;
19891 case ' ':
19892 case '+':
19893 case '#':
19894 break;
19895 default:
19896 sawFlag = 0;
19897 continue;
19898 }
19899 *p++ = ch;
19900 format += step;
19901 step = utf8_tounicode(format, &ch);
19902 } while (sawFlag);
19903
19904
19905 width = 0;
19906 if (isdigit(ch)) {
19907 width = strtoul(format, &end, 10);
19908 format = end;
19909 step = utf8_tounicode(format, &ch);
19910 } else if (ch == '*') {
19911 if (objIndex >= objc - 1) {
19912 msg = badIndex[gotXpg];
19913 goto errorMsg;
19914 }
19915 if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19916 goto error;
19917 }
19918 if (width < 0) {
19919 width = -width;
19920 if (!gotMinus) {
19921 *p++ = '-';
19922 gotMinus = 1;
19923 }
19924 }
19925 objIndex++;
19926 format += step;
19927 step = utf8_tounicode(format, &ch);
19928 }
19929
19930
19931 gotPrecision = precision = 0;
19932 if (ch == '.') {
19933 gotPrecision = 1;
19934 format += step;
19935 step = utf8_tounicode(format, &ch);
19936 }
19937 if (isdigit(ch)) {
19938 precision = strtoul(format, &end, 10);
19939 format = end;
19940 step = utf8_tounicode(format, &ch);
19941 } else if (ch == '*') {
19942 if (objIndex >= objc - 1) {
19943 msg = badIndex[gotXpg];
19944 goto errorMsg;
19945 }
19946 if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19947 goto error;
19948 }
19949
19950
19951 if (precision < 0) {
19952 precision = 0;
19953 }
19954 objIndex++;
19955 format += step;
19956 step = utf8_tounicode(format, &ch);
19957 }
19958
19959
19960 useShort = 0;
19961 if (ch == 'h') {
19962 useShort = 1;
19963 format += step;
19964 step = utf8_tounicode(format, &ch);
19965 } else if (ch == 'l') {
19966
19967 format += step;
19968 step = utf8_tounicode(format, &ch);
19969 if (ch == 'l') {
19970 format += step;
19971 step = utf8_tounicode(format, &ch);
19972 }
19973 }
19974
19975 format += step;
19976 span = format;
19977
19978
19979 if (ch == 'i') {
19980 ch = 'd';
19981 }
19982
19983 doubleType = 0;
19984
19985 switch (ch) {
19986 case '\0':
19987 msg = "format string ended in middle of field specifier";
19988 goto errorMsg;
19989 case 's': {
19990 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19991 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19992 if (gotPrecision && (precision < formatted_chars)) {
19993
19994 formatted_chars = precision;
19995 formatted_bytes = utf8_index(formatted_buf, precision);
19996 }
19997 break;
19998 }
19999 case 'c': {
20000 jim_wide code;
20001
20002 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20003 goto error;
20004 }
20005
20006 formatted_bytes = utf8_getchars(spec, code);
20007 formatted_buf = spec;
20008 formatted_chars = 1;
20009 break;
20010 }
20011 case 'b': {
20012 unsigned jim_wide w;
20013 int length;
20014 int i;
20015 int j;
20016
20017 if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
20018 goto error;
20019 }
20020 length = sizeof(w) * 8;
20021
20022
20023
20024 if (num_buffer_size < length + 1) {
20025 num_buffer_size = length + 1;
20026 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20027 }
20028
20029 j = 0;
20030 for (i = length; i > 0; ) {
20031 i--;
20032 if (w & ((unsigned jim_wide)1 << i)) {
20033 num_buffer[j++] = '1';
20034 }
20035 else if (j || i == 0) {
20036 num_buffer[j++] = '0';
20037 }
20038 }
20039 num_buffer[j] = 0;
20040 formatted_chars = formatted_bytes = j;
20041 formatted_buf = num_buffer;
20042 break;
20043 }
20044
20045 case 'e':
20046 case 'E':
20047 case 'f':
20048 case 'g':
20049 case 'G':
20050 doubleType = 1;
20051
20052 case 'd':
20053 case 'u':
20054 case 'o':
20055 case 'x':
20056 case 'X': {
20057 jim_wide w;
20058 double d;
20059 int length;
20060
20061
20062 if (width) {
20063 p += sprintf(p, "%ld", width);
20064 }
20065 if (gotPrecision) {
20066 p += sprintf(p, ".%ld", precision);
20067 }
20068
20069
20070 if (doubleType) {
20071 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20072 goto error;
20073 }
20074 length = MAX_FLOAT_WIDTH;
20075 }
20076 else {
20077 if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
20078 goto error;
20079 }
20080 length = JIM_INTEGER_SPACE;
20081 if (useShort) {
20082 if (ch == 'd') {
20083 w = (short)w;
20084 }
20085 else {
20086 w = (unsigned short)w;
20087 }
20088 }
20089 *p++ = 'l';
20090 #ifdef HAVE_LONG_LONG
20091 if (sizeof(long long) == sizeof(jim_wide)) {
20092 *p++ = 'l';
20093 }
20094 #endif
20095 }
20096
20097 *p++ = (char) ch;
20098 *p = '\0';
20099
20100
20101 if (width > length) {
20102 length = width;
20103 }
20104 if (gotPrecision) {
20105 length += precision;
20106 }
20107
20108
20109 if (num_buffer_size < length + 1) {
20110 num_buffer_size = length + 1;
20111 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20112 }
20113
20114 if (doubleType) {
20115 snprintf(num_buffer, length + 1, spec, d);
20116 }
20117 else {
20118 formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
20119 }
20120 formatted_chars = formatted_bytes = strlen(num_buffer);
20121 formatted_buf = num_buffer;
20122 break;
20123 }
20124
20125 default: {
20126
20127 spec[0] = ch;
20128 spec[1] = '\0';
20129 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20130 goto error;
20131 }
20132 }
20133
20134 if (!gotMinus) {
20135 while (formatted_chars < width) {
20136 Jim_AppendString(interp, resultPtr, &pad, 1);
20137 formatted_chars++;
20138 }
20139 }
20140
20141 Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
20142
20143 while (formatted_chars < width) {
20144 Jim_AppendString(interp, resultPtr, &pad, 1);
20145 formatted_chars++;
20146 }
20147
20148 objIndex += gotSequential;
20149 }
20150 if (numBytes) {
20151 Jim_AppendString(interp, resultPtr, span, numBytes);
20152 }
20153
20154 Jim_Free(num_buffer);
20155 return resultPtr;
20156
@@ -19827,21 +20159,22 @@
20159 error:
20160 Jim_FreeNewObj(interp, resultPtr);
20161 Jim_Free(num_buffer);
20162 return NULL;
20163 }
20164
20165
20166 #if defined(JIM_REGEXP)
20167 #include <stdio.h>
20168 #include <ctype.h>
20169 #include <stdlib.h>
20170 #include <string.h>
20171
 
 
 
20172
20173
20174 #define REG_MAX_PAREN 100
20175
20176
20177
20178 #define END 0
20179 #define BOL 1
20180 #define EOL 2
@@ -19850,23 +20183,27 @@
20183 #define ANYBUT 5
20184 #define BRANCH 6
20185 #define BACK 7
20186 #define EXACTLY 8
20187 #define NOTHING 9
20188 #define REP 10
20189 #define REPMIN 11
20190 #define REPX 12
20191 #define REPXMIN 13
20192
20193 #define WORDA 15
20194 #define WORDZ 16
20195
20196 #define OPENNC 1000
20197 #define OPEN 1001
20198
20199
20200
20201
20202 #define CLOSENC 2000
20203 #define CLOSE 2001
20204 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
 
20205
20206 #define REG_MAGIC 0xFADED00D
20207
20208
20209 #define OP(preg, p) (preg->program[p])
@@ -19876,15 +20213,15 @@
20213
20214
20215
20216 #define FAIL(R,M) { (R)->err = (M); return (M); }
20217 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20218 #define META "^$.[()|?{+*"
20219
20220 #define HASWIDTH 1
20221 #define SIMPLE 2
20222 #define SPSTART 4
20223 #define WORST 0
20224
20225 #define MAX_REP_COUNT 1000000
20226
20227 static int reg(regex_t *preg, int paren , int *flagp );
@@ -19893,13 +20230,13 @@
20230 static int regatom(regex_t *preg, int *flagp );
20231 static int regnode(regex_t *preg, int op );
20232 static int regnext(regex_t *preg, int p );
20233 static void regc(regex_t *preg, int b );
20234 static int reginsert(regex_t *preg, int op, int size, int opnd );
20235 static void regtail(regex_t *preg, int p, int val);
20236 static void regoptail(regex_t *preg, int p, int val );
20237 static int regopsize(regex_t *preg, int p );
20238
20239 static int reg_range_find(const int *string, int c);
20240 static const char *str_find(const char *string, int c, int nocase);
20241 static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
20242
@@ -19936,13 +20273,10 @@
20273 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20274
20275
20276 preg->cflags = cflags;
20277 preg->regparse = exp;
 
 
 
20278
20279
20280 preg->proglen = (strlen(exp) + 1) * 5;
20281 preg->program = malloc(preg->proglen * sizeof(int));
20282 if (preg->program == NULL)
@@ -20103,11 +20437,10 @@
20437 {
20438 int ret;
20439 char op;
20440 int next;
20441 int flags;
 
20442 int min;
20443 int max;
20444
20445 ret = regatom(preg, &flags);
20446 if (ret == 0)
@@ -20186,11 +20519,11 @@
20519 if (ISMULT(*preg->regparse)) {
20520 preg->err = REG_ERR_NESTED_COUNT;
20521 return 0;
20522 }
20523
20524 return ret;
20525 }
20526
20527 static void reg_addrange(regex_t *preg, int lower, int upper)
20528 {
20529 if (lower > upper) {
@@ -20280,10 +20613,11 @@
20613 break;
20614 case 'U':
20615 if ((n = parse_hex(s, 8, ch)) > 0) {
20616 s += n;
20617 }
20618 break;
20619 case 'x':
20620 if ((n = parse_hex(s, 2, ch)) > 0) {
20621 s += n;
20622 }
20623 break;
@@ -20528,10 +20862,11 @@
20862
20863 static int regnode(regex_t *preg, int op)
20864 {
20865 reg_grow(preg, 2);
20866
20867
20868 preg->program[preg->p++] = op;
20869 preg->program[preg->p++] = 0;
20870
20871
20872 return preg->p - 2;
@@ -20557,11 +20892,11 @@
20892 preg->p += size;
20893
20894 return opnd + size;
20895 }
20896
20897 static void regtail(regex_t *preg, int p, int val)
20898 {
20899 int scan;
20900 int temp;
20901 int offset;
20902
@@ -20620,36 +20955,16 @@
20955 preg->pmatch = pmatch;
20956 preg->nmatch = nmatch;
20957 preg->start = string;
20958
20959
20960 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
20961 int op = OP(preg, scan);
20962 if (op == END)
20963 break;
20964 if (op == REPX || op == REPXMIN)
20965 preg->program[scan + 4] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20966 }
20967
20968
20969 if (preg->regmust != 0) {
20970 s = string;
@@ -20901,10 +21216,11 @@
21216
21217 static int regmatch(regex_t *preg, int prog)
21218 {
21219 int scan;
21220 int next;
21221 const char *save;
21222
21223 scan = prog;
21224
21225 #ifdef DEBUG
21226 if (scan != 0 && regnarrate)
@@ -20989,27 +21305,24 @@
21305 break;
21306 case NOTHING:
21307 break;
21308 case BACK:
21309 break;
21310 case BRANCH:
21311 if (OP(preg, next) != BRANCH)
21312 next = OPERAND(scan);
21313 else {
21314 do {
21315 save = preg->reginput;
21316 if (regmatch(preg, OPERAND(scan))) {
21317 return(1);
21318 }
21319 preg->reginput = save;
21320 scan = regnext(preg, scan);
21321 } while (scan != 0 && OP(preg, scan) == BRANCH);
21322 return(0);
21323
 
 
 
21324 }
21325 break;
21326 case REP:
21327 case REPMIN:
21328 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21017,43 +21330,35 @@
21330 case REPX:
21331 case REPXMIN:
21332 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21333
21334 case END:
21335 return 1;
 
21336
21337 case OPENNC:
21338 case CLOSENC:
21339 return regmatch(preg, next);
 
 
 
21340
21341 default:
21342 if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
 
 
21343 save = preg->reginput;
 
21344 if (regmatch(preg, next)) {
 
21345 if (OP(preg, scan) < CLOSE) {
21346 int no = OP(preg, scan) - OPEN;
21347 if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
21348 preg->pmatch[no].rm_so = save - preg->start;
21349 }
21350 }
21351 else {
21352 int no = OP(preg, scan) - CLOSE;
21353 if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
21354 preg->pmatch[no].rm_eo = save - preg->start;
21355 }
21356 }
21357 return(1);
21358 }
21359 return(0);
21360 }
21361 return REG_ERR_INTERNAL;
21362 }
21363
21364 scan = next;
@@ -21132,10 +21437,32 @@
21437 if (OP(preg, p) == BACK)
21438 return(p-offset);
21439 else
21440 return(p+offset);
21441 }
21442
21443 static int regopsize(regex_t *preg, int p )
21444 {
21445
21446 switch (OP(preg, p)) {
21447 case REP:
21448 case REPMIN:
21449 case REPX:
21450 case REPXMIN:
21451 return 5;
21452
21453 case ANYOF:
21454 case ANYBUT:
21455 case EXACTLY: {
21456 int s = p + 2;
21457 while (preg->program[s++]) {
21458 }
21459 return s - p;
21460 }
21461 }
21462 return 2;
21463 }
21464
21465
21466 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
21467 {
21468 static const char *error_strings[] = {
@@ -21310,19 +21637,24 @@
21637 char *Jim_HistoryGetline(const char *prompt)
21638 {
21639 #ifdef USE_LINENOISE
21640 return linenoise(prompt);
21641 #else
21642 int len;
21643 char *line = malloc(MAX_LINE_LEN);
21644
21645 fputs(prompt, stdout);
21646 fflush(stdout);
21647
21648 if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
21649 free(line);
21650 return NULL;
21651 }
21652 len = strlen(line);
21653 if (len && line[len - 1] == '\n') {
21654 line[len - 1] = '\0';
21655 }
21656 return line;
21657 #endif
21658 }
21659
21660 void Jim_HistoryLoad(const char *filename)
@@ -21373,11 +21705,11 @@
21705 snprintf(history_file, history_len, "%s/.jim_history", home);
21706 Jim_HistoryLoad(history_file);
21707 }
21708 #endif
21709
21710 printf("Welcome to Jim version %d.%d\n",
21711 JIM_VERSION / 100, JIM_VERSION % 100);
21712 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
21713
21714 while (1) {
21715 Jim_Obj *scriptObjPtr;
@@ -21485,10 +21817,16 @@
21817 }
21818
21819 Jim_SetVariableStr(interp, "argv", listObj);
21820 Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
21821 }
21822
21823 static void JimPrintErrorMessage(Jim_Interp *interp)
21824 {
21825 Jim_MakeErrorMessage(interp);
21826 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21827 }
21828
21829 int main(int argc, char *const argv[])
21830 {
21831 int retcode;
21832 Jim_Interp *interp;
@@ -21502,22 +21840,20 @@
21840 interp = Jim_CreateInterp();
21841 Jim_RegisterCoreCommands(interp);
21842
21843
21844 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21845 JimPrintErrorMessage(interp);
 
21846 }
21847
21848 Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
21849 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
21850 retcode = Jim_initjimshInit(interp);
21851
21852 if (argc == 1) {
21853 if (retcode == JIM_ERR) {
21854 JimPrintErrorMessage(interp);
 
21855 }
21856 if (retcode != JIM_EXIT) {
21857 JimSetArgv(interp, 0, NULL);
21858 retcode = Jim_InteractivePrompt(interp);
21859 }
@@ -21534,12 +21870,11 @@
21870 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
21871 JimSetArgv(interp, argc - 2, argv + 2);
21872 retcode = Jim_EvalFile(interp, argv[1]);
21873 }
21874 if (retcode == JIM_ERR) {
21875 JimPrintErrorMessage(interp);
 
21876 }
21877 }
21878 if (retcode == JIM_EXIT) {
21879 retcode = Jim_GetExitCode(interp);
21880 }
21881

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button