Fossil SCM

Merge the latest Jim Tcl code to trunk, post-0.75 with the 'glob.tcl' fix included. Approved by Jim Tcl release manager Steve Bennett.

mistachkin 2014-08-08 19:07 trunk merge
Commit 9d7d6775595aab786aa0b37f30d81414e5389dc8
1 file changed +1787 -1501
+1787 -1501
--- 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
@@ -47,10 +47,14 @@
4747
#define JIM_VERSION 75
4848
#ifndef JIM_WIN32COMPAT_H
4949
#define JIM_WIN32COMPAT_H
5050
5151
52
+
53
+#ifdef __cplusplus
54
+extern "C" {
55
+#endif
5256
5357
5458
#if defined(_WIN32) || defined(WIN32)
5559
5660
#define HAVE_DLOPEN
@@ -106,17 +110,31 @@
106110
} DIR;
107111
108112
DIR *opendir(const char *name);
109113
int closedir(DIR *dir);
110114
struct dirent *readdir(DIR *dir);
111
-#endif
115
+
116
+#elif defined(__MINGW32__)
117
+
118
+#define strtod __strtod
119
+
120
+#endif
112121
113122
#endif
123
+
124
+#ifdef __cplusplus
125
+}
126
+#endif
114127
115128
#endif
116129
#ifndef UTF8_UTIL_H
117130
#define UTF8_UTIL_H
131
+
132
+#ifdef __cplusplus
133
+extern "C" {
134
+#endif
135
+
118136
119137
120138
#define MAX_UTF8_LEN 4
121139
122140
int utf8_fromunicode(char *p, unsigned uc);
@@ -125,10 +143,11 @@
125143
#include <ctype.h>
126144
127145
128146
#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
129147
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
148
+#define utf8_getchars(CP, C) (*(CP) = (C), 1)
130149
#define utf8_upper(C) toupper(C)
131150
#define utf8_title(C) toupper(C)
132151
#define utf8_lower(C) tolower(C)
133152
#define utf8_index(C, I) (I)
134153
#define utf8_charlen(C) 1
@@ -135,10 +154,14 @@
135154
#define utf8_prev_len(S, L) 1
136155
137156
#else
138157
139158
#endif
159
+
160
+#ifdef __cplusplus
161
+}
162
+#endif
140163
141164
#endif
142165
143166
#ifndef __JIM__H
144167
#define __JIM__H
@@ -199,44 +222,34 @@
199222
#define JIM_EVAL 7
200223
201224
#define JIM_MAX_CALLFRAME_DEPTH 1000
202225
#define JIM_MAX_EVAL_DEPTH 2000
203226
204
-#define JIM_NONE 0
205
-#define JIM_ERRMSG 1
206
-
207
-#define JIM_UNSHARED 4
208
-#define JIM_MUSTEXIST 8
209
-
210
-
211
-#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
212235
213236
214237
#define JIM_SUBST_NOVAR 1
215238
#define JIM_SUBST_NOCMD 2
216239
#define JIM_SUBST_NOESC 4
217240
#define JIM_SUBST_FLAG 128
218241
219
-
220
-#define JIM_NOTUSED(V) ((void) V)
221
-
222
-
223
-#define JIM_ENUM_ABBREV 2
224
-
225242
226243
#define JIM_CASESENS 0
227244
#define JIM_NOCASE 1
228245
229246
230247
#define JIM_PATH_LEN 1024
231248
232249
233
-#ifdef JIM_CRLF
234
-#define JIM_NL "\r\n"
235
-#else
236
-#define JIM_NL "\n"
237
-#endif
250
+#define JIM_NOTUSED(V) ((void) V)
238251
239252
#define JIM_LIBPATH "auto_path"
240253
#define JIM_INTERACTIVE "tcl_interactive"
241254
242255
@@ -266,21 +279,22 @@
266279
} Jim_HashTableType;
267280
268281
typedef struct Jim_HashTable {
269282
Jim_HashEntry **table;
270283
const Jim_HashTableType *type;
284
+ void *privdata;
271285
unsigned int size;
272286
unsigned int sizemask;
273287
unsigned int used;
274288
unsigned int collisions;
275
- void *privdata;
289
+ unsigned int uniq;
276290
} Jim_HashTable;
277291
278292
typedef struct Jim_HashTableIterator {
279293
Jim_HashTable *ht;
280
- int index;
281294
Jim_HashEntry *entry, *nextEntry;
295
+ int index;
282296
} Jim_HashTableIterator;
283297
284298
285299
#define JIM_HT_INITIAL_SIZE 16
286300
@@ -289,35 +303,35 @@
289303
if ((ht)->type->valDestructor) \
290304
(ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
291305
292306
#define Jim_SetHashVal(ht, entry, _val_) do { \
293307
if ((ht)->type->valDup) \
294
- entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
308
+ (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
295309
else \
296
- entry->u.val = (_val_); \
310
+ (entry)->u.val = (_val_); \
297311
} while(0)
298312
299313
#define Jim_FreeEntryKey(ht, entry) \
300314
if ((ht)->type->keyDestructor) \
301315
(ht)->type->keyDestructor((ht)->privdata, (entry)->key)
302316
303317
#define Jim_SetHashKey(ht, entry, _key_) do { \
304318
if ((ht)->type->keyDup) \
305
- entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
319
+ (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
306320
else \
307
- entry->key = (void *)(_key_); \
321
+ (entry)->key = (void *)(_key_); \
308322
} while(0)
309323
310324
#define Jim_CompareHashKeys(ht, key1, key2) \
311325
(((ht)->type->keyCompare) ? \
312
- (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
326
+ (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
313327
(key1) == (key2))
314328
315
-#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
329
+#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
316330
317331
#define Jim_GetHashEntryKey(he) ((he)->key)
318
-#define Jim_GetHashEntryVal(he) ((he)->val)
332
+#define Jim_GetHashEntryVal(he) ((he)->u.val)
319333
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
320334
#define Jim_GetHashTableSize(ht) ((ht)->size)
321335
#define Jim_GetHashTableUsed(ht) ((ht)->used)
322336
323337
@@ -341,19 +355,19 @@
341355
void *ptr1;
342356
void *ptr2;
343357
} twoPtrValue;
344358
345359
struct {
346
- unsigned long callFrameId;
347360
struct Jim_Var *varPtr;
361
+ unsigned long callFrameId;
348362
int global;
349363
} varValue;
350364
351365
struct {
352
- unsigned long procEpoch;
353366
struct Jim_Obj *nsObj;
354367
struct Jim_Cmd *cmdPtr;
368
+ unsigned long procEpoch;
355369
} cmdValue;
356370
357371
struct {
358372
struct Jim_Obj **ele;
359373
int len;
@@ -379,12 +393,12 @@
379393
struct Jim_Obj *varNameObjPtr;
380394
struct Jim_Obj *indexObjPtr;
381395
} dictSubstValue;
382396
383397
struct {
384
- unsigned flags;
385398
void *compre;
399
+ unsigned flags;
386400
} regexpValue;
387401
struct {
388402
int line;
389403
int argc;
390404
} scriptLineValue;
@@ -453,21 +467,24 @@
453467
struct Jim_CallFrame *next;
454468
Jim_Obj *nsObj;
455469
Jim_Obj *fileNameObj;
456470
int line;
457471
Jim_Stack *localCommands;
472
+ int tailcall;
473
+ struct Jim_Obj *tailcallObj;
474
+ struct Jim_Cmd *tailcallCmd;
458475
} Jim_CallFrame;
459476
460477
typedef struct Jim_Var {
461478
Jim_Obj *objPtr;
462479
struct Jim_CallFrame *linkFramePtr;
463480
} Jim_Var;
464481
465482
466
-typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
483
+typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
467484
Jim_Obj *const *argv);
468
-typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
485
+typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
469486
470487
471488
472489
typedef struct Jim_Cmd {
473490
int inUse;
@@ -474,12 +491,12 @@
474491
int isproc;
475492
struct Jim_Cmd *prevCmd;
476493
union {
477494
struct {
478495
479
- Jim_CmdProc cmdProc;
480
- Jim_DelCmdProc delProc;
496
+ Jim_CmdProc *cmdProc;
497
+ Jim_DelCmdProc *delProc;
481498
void *privData;
482499
} native;
483500
struct {
484501
485502
Jim_Obj *argListObjPtr;
@@ -589,15 +606,11 @@
589606
Jim_Obj *finalizerCmdNamePtr;
590607
char tag[JIM_REFERENCE_TAGLEN+1];
591608
} Jim_Reference;
592609
593610
594
-
595611
#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
596
-
597
-
598
-
599612
#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
600613
601614
#define JIM_EXPORT
602615
603616
@@ -608,10 +621,11 @@
608621
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
609622
610623
611624
JIM_EXPORT char **Jim_GetEnviron(void);
612625
JIM_EXPORT void Jim_SetEnviron(char **env);
626
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
613627
614628
615629
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
616630
617631
@@ -739,13 +753,12 @@
739753
JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
740754
const char *name, const char *val);
741755
JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
742756
Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
743757
Jim_CallFrame *targetCallFrame);
744
-JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
745
- Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
746
-JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
758
+JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
759
+ Jim_Obj *nameObjPtr);
747760
JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
748761
Jim_Obj *nameObjPtr, int flags);
749762
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
750763
Jim_Obj *nameObjPtr, int flags);
751764
JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -804,10 +817,11 @@
804817
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
805818
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
806819
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
807820
JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
808821
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
822
+JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
809823
810824
811825
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
812826
int *intPtr);
813827
@@ -869,19 +883,19 @@
869883
870884
871885
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
872886
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
873887
JIM_EXPORT int Jim_IsBigEndian(void);
888
+
874889
#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
875890
876891
877892
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
878893
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
879894
880895
881896
JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
882
-
883897
884898
885899
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
886900
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
887901
@@ -903,16 +917,16 @@
903917
#define JIM_MODFLAG_HIDDEN 0x0001
904918
#define JIM_MODFLAG_FULLARGV 0x0002
905919
906920
907921
908
-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);
909923
910924
typedef struct {
911925
const char *cmd;
912926
const char *args;
913
- tclmod_cmd_function *function;
927
+ jim_subcmd_function *function;
914928
short minargs;
915929
short maxargs;
916930
unsigned short flags;
917931
} jim_subcmd_type;
918932
@@ -929,22 +943,16 @@
929943
930944
#endif
931945
#ifndef JIMREGEXP_H
932946
#define JIMREGEXP_H
933947
934
-#ifndef _JIMAUTOCONF_H
935
-#error Need jimautoconf.h
948
+
949
+#ifdef __cplusplus
950
+extern "C" {
936951
#endif
937952
938
-#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
939
-
940
-#include <regex.h>
941
-
942
-#else
943
-
944953
#include <stdlib.h>
945
-
946954
947955
typedef struct {
948956
int rm_so;
949957
int rm_eo;
950958
} regmatch_t;
@@ -1013,10 +1021,12 @@
10131021
int regcomp(regex_t *preg, const char *regex, int cflags);
10141022
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
10151023
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
10161024
void regfree(regex_t *preg);
10171025
1026
+#ifdef __cplusplus
1027
+}
10181028
#endif
10191029
10201030
#endif
10211031
int Jim_bootstrapInit(Jim_Interp *interp)
10221032
{
@@ -1079,10 +1089,15 @@
10791089
"\n"
10801090
"package require readdir\n"
10811091
"\n"
10821092
"\n"
10831093
"proc glob.globdir {dir pattern} {\n"
1094
+" if {[file exists $dir/$pattern]} {\n"
1095
+"\n"
1096
+" return $pattern\n"
1097
+" }\n"
1098
+"\n"
10841099
" set result {}\n"
10851100
" set files [readdir $dir]\n"
10861101
" lappend files . ..\n"
10871102
"\n"
10881103
" foreach name $files {\n"
@@ -1261,10 +1276,12 @@
12611276
{
12621277
if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
12631278
return JIM_ERR;
12641279
12651280
return Jim_EvalSource(interp, "stdlib.tcl", 1,
1281
+"\n"
1282
+"\n"
12661283
"\n"
12671284
"proc lambda {arglist args} {\n"
12681285
" tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
12691286
"}\n"
12701287
"\n"
@@ -1290,46 +1307,48 @@
12901307
"}\n"
12911308
"\n"
12921309
"\n"
12931310
"\n"
12941311
"\n"
1295
-"proc stacktrace {} {\n"
1312
+"proc stacktrace {{skip 0}} {\n"
12961313
" set trace {}\n"
1297
-" foreach level [range 1 [info level]] {\n"
1298
-" lassign [info frame -$level] p f l\n"
1299
-" 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"
13001317
" }\n"
13011318
" return $trace\n"
13021319
"}\n"
13031320
"\n"
13041321
"\n"
13051322
"proc stackdump {stacktrace} {\n"
1306
-" set result {}\n"
1307
-" set count 0\n"
1323
+" set lines {}\n"
13081324
" foreach {l f p} [lreverse $stacktrace] {\n"
1309
-" if {$count} {\n"
1310
-" append result \\n\n"
1311
-" }\n"
1312
-" incr count\n"
1325
+" set line {}\n"
13131326
" if {$p ne \"\"} {\n"
1314
-" append result \"in procedure '$p' \"\n"
1327
+" append line \"in procedure '$p' \"\n"
13151328
" if {$f ne \"\"} {\n"
1316
-" append result \"called \"\n"
1329
+" append line \"called \"\n"
13171330
" }\n"
13181331
" }\n"
13191332
" if {$f ne \"\"} {\n"
1320
-" 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"
13211337
" }\n"
13221338
" }\n"
1323
-" return $result\n"
1339
+" join $lines \\n\n"
13241340
"}\n"
13251341
"\n"
13261342
"\n"
13271343
"\n"
13281344
"proc errorInfo {msg {stacktrace \"\"}} {\n"
13291345
" if {$stacktrace eq \"\"} {\n"
1346
+"\n"
13301347
" set stacktrace [info stacktrace]\n"
1348
+"\n"
1349
+" lappend stacktrace {*}[stacktrace 1]\n"
13311350
" }\n"
13321351
" lassign $stacktrace p f l\n"
13331352
" if {$f ne \"\"} {\n"
13341353
" set result \"Runtime Error: $f:$l: \"\n"
13351354
" }\n"
@@ -1356,25 +1375,46 @@
13561375
" }\n"
13571376
" return \"\"\n"
13581377
"}\n"
13591378
"\n"
13601379
"\n"
1361
-"proc {dict with} {dictVar args script} {\n"
1362
-" upvar $dictVar dict\n"
1380
+"proc {dict with} {&dictVar {args key} script} {\n"
13631381
" set keys {}\n"
1364
-" foreach {n v} [dict get $dict {*}$args] {\n"
1382
+" foreach {n v} [dict get $dictVar {*}$key] {\n"
13651383
" upvar $n var_$n\n"
13661384
" set var_$n $v\n"
13671385
" lappend keys $n\n"
13681386
" }\n"
13691387
" catch {uplevel 1 $script} msg opts\n"
1370
-" if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1388
+" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
13711389
" foreach n $keys {\n"
13721390
" if {[info exists var_$n]} {\n"
1373
-" 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"
13741414
" } else {\n"
1375
-" dict unset dict {*}$args $n\n"
1415
+" dict unset varName $n\n"
13761416
" }\n"
13771417
" }\n"
13781418
" }\n"
13791419
" return {*}$opts $msg\n"
13801420
"}\n"
@@ -1389,10 +1429,69 @@
13891429
" dict set dict $k $v\n"
13901430
" }\n"
13911431
" }\n"
13921432
" return $dict\n"
13931433
"}\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"
13941493
);
13951494
}
13961495
int Jim_tclcompatInit(Jim_Interp *interp)
13971496
{
13981497
if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1403,12 +1502,14 @@
14031502
"\n"
14041503
"\n"
14051504
"\n"
14061505
"\n"
14071506
"\n"
1507
+"\n"
14081508
"\n"
14091509
"set env [env]\n"
1510
+"\n"
14101511
"\n"
14111512
"if {[info commands stdout] ne \"\"} {\n"
14121513
"\n"
14131514
" foreach p {gets flush close eof seek tell} {\n"
14141515
" proc $p {chan args} {p} {\n"
@@ -1455,51 +1556,10 @@
14551556
" }\n"
14561557
" }\n"
14571558
" }\n"
14581559
"}\n"
14591560
"\n"
1460
-"\n"
1461
-"proc case {var args} {\n"
1462
-"\n"
1463
-" if {[lindex $args 0] eq \"in\"} {\n"
1464
-" set args [lrange $args 1 end]\n"
1465
-" }\n"
1466
-"\n"
1467
-"\n"
1468
-" if {[llength $args] == 1} {\n"
1469
-" set args [lindex $args 0]\n"
1470
-" }\n"
1471
-"\n"
1472
-"\n"
1473
-" if {[llength $args] % 2 != 0} {\n"
1474
-" return -code error \"extra case pattern with no body\"\n"
1475
-" }\n"
1476
-"\n"
1477
-"\n"
1478
-" local proc case.checker {value pattern} {\n"
1479
-" string match $pattern $value\n"
1480
-" }\n"
1481
-"\n"
1482
-" foreach {value action} $args {\n"
1483
-" if {$value eq \"default\"} {\n"
1484
-" set do_action $action\n"
1485
-" continue\n"
1486
-" } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1487
-" set do_action $action\n"
1488
-" break\n"
1489
-" }\n"
1490
-" }\n"
1491
-"\n"
1492
-" if {[info exists do_action]} {\n"
1493
-" set rc [catch [list uplevel 1 $do_action] result opts]\n"
1494
-" if {$rc} {\n"
1495
-" incr opts(-level)\n"
1496
-" }\n"
1497
-" return {*}$opts $result\n"
1498
-" }\n"
1499
-"}\n"
1500
-"\n"
15011561
"\n"
15021562
"proc fileevent {args} {\n"
15031563
" tailcall {*}$args\n"
15041564
"}\n"
15051565
"\n"
@@ -1529,13 +1589,25 @@
15291589
" error \"bad option \\\"$force\\\": should be -force\"\n"
15301590
" }\n"
15311591
"\n"
15321592
" set in [open $source]\n"
15331593
"\n"
1534
-" if {$force eq \"\" && [file exists $target]} {\n"
1535
-" $in close\n"
1536
-" 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"
15371609
" }\n"
15381610
" set out [open $target w]\n"
15391611
" $in copyto $out\n"
15401612
" $out close\n"
15411613
" } on error {msg opts} {\n"
@@ -1580,18 +1652,18 @@
15801652
" error $error\n"
15811653
" }\n"
15821654
"}\n"
15831655
"\n"
15841656
"\n"
1585
-"local proc pid {{chan {}}} {\n"
1586
-" if {$chan eq \"\"} {\n"
1657
+"local proc pid {{channelId {}}} {\n"
1658
+" if {$channelId eq \"\"} {\n"
15871659
" tailcall upcall pid\n"
15881660
" }\n"
1589
-" if {[catch {$chan tell}]} {\n"
1590
-" 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"
15911663
" }\n"
1592
-" if {[catch {$chan pid} pids]} {\n"
1664
+" if {[catch {$channelId pid} pids]} {\n"
15931665
" return \"\"\n"
15941666
" }\n"
15951667
" return $pids\n"
15961668
"}\n"
15971669
"\n"
@@ -1680,23 +1752,25 @@
16801752
"}\n"
16811753
);
16821754
}
16831755
16841756
1685
-
16861757
#include <stdio.h>
16871758
#include <string.h>
16881759
#include <errno.h>
16891760
#include <fcntl.h>
1761
+#ifdef HAVE_UNISTD_H
1762
+#include <unistd.h>
1763
+#include <sys/stat.h>
1764
+#endif
16901765
16911766
16921767
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
16931768
#include <sys/socket.h>
16941769
#include <netinet/in.h>
16951770
#include <arpa/inet.h>
16961771
#include <netdb.h>
1697
-#include <unistd.h>
16981772
#ifdef HAVE_SYS_UN_H
16991773
#include <sys/un.h>
17001774
#endif
17011775
#else
17021776
#define JIM_ANSIC
@@ -1728,15 +1802,12 @@
17281802
typedef struct AioFile
17291803
{
17301804
FILE *fp;
17311805
Jim_Obj *filename;
17321806
int type;
1733
- int OpenFlags;
1807
+ int openFlags;
17341808
int fd;
1735
-#ifdef O_NDELAY
1736
- int flags;
1737
-#endif
17381809
Jim_Obj *rEvent;
17391810
Jim_Obj *wEvent;
17401811
Jim_Obj *eEvent;
17411812
int addr_family;
17421813
} AioFile;
@@ -1760,20 +1831,21 @@
17601831
{
17611832
AioFile *af = privData;
17621833
17631834
JIM_NOTUSED(interp);
17641835
1765
- if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1766
- fclose(af->fp);
1767
- }
1768
-
17691836
Jim_DecrRefCount(interp, af->filename);
17701837
17711838
#ifdef jim_ext_eventloop
17721839
17731840
Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
17741841
#endif
1842
+
1843
+ if (!(af->openFlags & AIO_KEEPOPEN)) {
1844
+ fclose(af->fp);
1845
+ }
1846
+
17751847
Jim_Free(af);
17761848
}
17771849
17781850
static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
17791851
{
@@ -2020,12 +2092,31 @@
20202092
return JIM_OK;
20212093
}
20222094
20232095
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20242096
{
2025
- Jim_DeleteCommand(interp, Jim_String(argv[0]));
2026
- 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]));
20272118
}
20282119
20292120
static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20302121
{
20312122
AioFile *af = Jim_CmdPrivData(interp);
@@ -2072,11 +2163,11 @@
20722163
#ifdef O_NDELAY
20732164
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20742165
{
20752166
AioFile *af = Jim_CmdPrivData(interp);
20762167
2077
- int fmode = af->flags;
2168
+ int fmode = fcntl(af->fd, F_GETFL);
20782169
20792170
if (argc) {
20802171
long nb;
20812172
20822173
if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2086,12 +2177,11 @@
20862177
fmode |= O_NDELAY;
20872178
}
20882179
else {
20892180
fmode &= ~O_NDELAY;
20902181
}
2091
- fcntl(af->fd, F_SETFL, fmode);
2092
- af->flags = fmode;
2182
+ (void)fcntl(af->fd, F_SETFL, fmode);
20932183
}
20942184
Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
20952185
return JIM_OK;
20962186
}
20972187
#endif
@@ -2195,11 +2285,11 @@
21952285
21962286
static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
21972287
{
21982288
AioFile *af = Jim_CmdPrivData(interp);
21992289
2200
- 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);
22012291
}
22022292
#endif
22032293
22042294
static const jim_subcmd_type aio_command_table[] = {
22052295
{ "read",
@@ -2250,14 +2340,14 @@
22502340
0,
22512341
0,
22522342
22532343
},
22542344
{ "close",
2255
- NULL,
2345
+ "?r(ead)|w(rite)?",
22562346
aio_cmd_close,
22572347
0,
2258
- 0,
2348
+ 1,
22592349
JIM_MODFLAG_FULLARGV,
22602350
22612351
},
22622352
{ "seek",
22632353
"offset ?start|current|end",
@@ -2329,30 +2419,32 @@
23292419
23302420
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
23312421
Jim_Obj *const *argv)
23322422
{
23332423
const char *mode;
2334
- const char *filename;
23352424
23362425
if (argc != 2 && argc != 3) {
23372426
Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
23382427
return JIM_ERR;
23392428
}
23402429
23412430
mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2342
- filename = Jim_String(argv[1]);
23432431
23442432
#ifdef jim_ext_tclcompat
2345
-
2346
- if (*filename == '|') {
2347
- Jim_Obj *evalObj[3];
2348
-
2349
- evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2350
- evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2351
- evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2352
-
2353
- 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
+ }
23542446
}
23552447
#endif
23562448
return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
23572449
}
23582450
@@ -2359,70 +2451,129 @@
23592451
static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
23602452
const char *hdlfmt, int family, const char *mode)
23612453
{
23622454
AioFile *af;
23632455
char buf[AIO_CMD_LEN];
2364
- int OpenFlags = 0;
2456
+ int openFlags = 0;
23652457
2366
- if (filename == NULL) {
2458
+ if (fh) {
23672459
filename = Jim_NewStringObj(interp, hdlfmt, -1);
2460
+ openFlags = AIO_KEEPOPEN;
23682461
}
23692462
23702463
Jim_IncrRefCount(filename);
23712464
23722465
if (fh == NULL) {
2373
- if (fd < 0) {
2374
- fh = fopen(Jim_String(filename), mode);
2375
- }
2376
- else {
2466
+#if !defined(JIM_ANSIC)
2467
+ if (fd >= 0) {
23772468
fh = fdopen(fd, mode);
23782469
}
2379
- }
2380
- else {
2381
- OpenFlags = AIO_KEEPOPEN;
2382
- }
2470
+ else
2471
+#endif
2472
+ fh = fopen(Jim_String(filename), mode);
23832473
2384
- if (fh == NULL) {
2385
- JimAioSetError(interp, filename);
2474
+ if (fh == NULL) {
2475
+ JimAioSetError(interp, filename);
23862476
#if !defined(JIM_ANSIC)
2387
- if (fd >= 0) {
2388
- close(fd);
2477
+ if (fd >= 0) {
2478
+ close(fd);
2479
+ }
2480
+#endif
2481
+ Jim_DecrRefCount(interp, filename);
2482
+ return JIM_ERR;
23892483
}
2390
-#endif
2391
- Jim_DecrRefCount(interp, filename);
2392
- return JIM_ERR;
23932484
}
23942485
23952486
23962487
af = Jim_Alloc(sizeof(*af));
23972488
memset(af, 0, sizeof(*af));
23982489
af->fp = fh;
23992490
af->fd = fileno(fh);
24002491
af->filename = filename;
24012492
#ifdef FD_CLOEXEC
2402
- if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2403
- fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2493
+ if ((openFlags & AIO_KEEPOPEN) == 0) {
2494
+ (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
24042495
}
24052496
#endif
2406
- af->OpenFlags = OpenFlags;
2407
-#ifdef O_NDELAY
2408
- af->flags = fcntl(af->fd, F_GETFL);
2409
-#endif
2497
+ af->openFlags = openFlags;
24102498
af->addr_family = family;
24112499
snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
24122500
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
24132501
2414
- Jim_SetResultString(interp, buf, -1);
2502
+ Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
24152503
24162504
return JIM_OK;
24172505
}
24182506
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
+}
24192569
24202570
FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
24212571
{
24222572
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
24232573
2574
+
24242575
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
24252576
return ((AioFile *) cmdPtr->u.native.privData)->fp;
24262577
}
24272578
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
24282579
return NULL;
@@ -2443,11 +2594,10 @@
24432594
JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
24442595
JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
24452596
24462597
return JIM_OK;
24472598
}
2448
-
24492599
24502600
#include <errno.h>
24512601
#include <stdio.h>
24522602
#include <string.h>
24532603
@@ -2479,28 +2629,29 @@
24792629
return JIM_OK;
24802630
}
24812631
Jim_SetResultString(interp, strerror(errno), -1);
24822632
return JIM_ERR;
24832633
}
2484
- Jim_SetResultString(interp, strerror(errno), -1);
2485
-
2486
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2487
-
2488
- while ((entryPtr = readdir(dirPtr)) != NULL) {
2489
- if (entryPtr->d_name[0] == '.') {
2490
- if (entryPtr->d_name[1] == '\0') {
2491
- continue;
2492
- }
2493
- if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2494
- continue;
2495
- }
2496
- Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2497
- entryPtr->d_name, -1));
2498
- }
2499
- closedir(dirPtr);
2500
-
2501
- 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
+ }
25022653
}
25032654
25042655
int Jim_readdirInit(Jim_Interp *interp)
25052656
{
25062657
if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2511,10 +2662,14 @@
25112662
}
25122663
25132664
#include <stdlib.h>
25142665
#include <string.h>
25152666
2667
+#if defined(JIM_REGEXP)
2668
+#else
2669
+ #include <regex.h>
2670
+#endif
25162671
25172672
static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
25182673
{
25192674
regfree(objPtr->internalRep.regexpValue.compre);
25202675
Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3058,58 +3213,61 @@
30583213
}
30593214
#endif
30603215
return "unknown";
30613216
}
30623217
3063
-
3064
-static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3065
- jim_wide value)
3066
-{
3067
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3068
- Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3069
-
3070
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3071
- Jim_FreeObj(interp, nameobj);
3072
- Jim_FreeObj(interp, valobj);
3073
- return JIM_ERR;
3074
- }
3075
- return JIM_OK;
3076
-}
3077
-
3078
-static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3079
- const char *value)
3080
-{
3081
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3082
- Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3083
-
3084
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3085
- Jim_FreeObj(interp, nameobj);
3086
- Jim_FreeObj(interp, valobj);
3087
- return JIM_ERR;
3088
- }
3089
- 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));
30903222
}
30913223
30923224
static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
30933225
{
3094
- if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3095
- Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3096
- return JIM_ERR;
3097
- }
3098
- set_array_int_value(interp, varName, "ino", sb->st_ino);
3099
- set_array_int_value(interp, varName, "mode", sb->st_mode);
3100
- set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3101
- set_array_int_value(interp, varName, "uid", sb->st_uid);
3102
- set_array_int_value(interp, varName, "gid", sb->st_gid);
3103
- set_array_int_value(interp, varName, "size", sb->st_size);
3104
- set_array_int_value(interp, varName, "atime", sb->st_atime);
3105
- set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3106
- set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3107
- set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3108
-
3109
-
3110
- 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);
31113269
31123270
return JIM_OK;
31133271
}
31143272
31153273
static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3264,14 +3422,11 @@
32643422
return JIM_OK;
32653423
}
32663424
32673425
static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
32683426
{
3269
- const char *path = Jim_String(filename);
3270
- int rc = access(path, mode);
3271
-
3272
- Jim_SetResultBool(interp, rc != -1);
3427
+ Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
32733428
32743429
return JIM_OK;
32753430
}
32763431
32773432
static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3287,10 +3442,11 @@
32873442
static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
32883443
{
32893444
#ifdef X_OK
32903445
return file_access(interp, argv[0], X_OK);
32913446
#else
3447
+
32923448
Jim_SetResultBool(interp, 1);
32933449
return JIM_OK;
32943450
#endif
32953451
}
32963452
@@ -3391,33 +3547,21 @@
33913547
argv++;
33923548
}
33933549
return JIM_OK;
33943550
}
33953551
3396
-#ifdef HAVE_MKSTEMP
33973552
static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
33983553
{
3399
- int fd;
3400
- char *filename;
3401
- const char *template = "/tmp/tcl.tmp.XXXXXX";
3402
-
3403
- if (argc >= 1) {
3404
- template = Jim_String(argv[0]);
3405
- }
3406
- filename = Jim_StrDup(template);
3407
-
3408
- fd = mkstemp(filename);
3409
- if (fd < 0) {
3410
- 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) {
34113557
return JIM_ERR;
34123558
}
34133559
close(fd);
34143560
3415
- Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
34163561
return JIM_OK;
34173562
}
3418
-#endif
34193563
34203564
static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34213565
{
34223566
const char *source;
34233567
const char *dest;
@@ -3459,14 +3603,11 @@
34593603
return JIM_ERR;
34603604
}
34613605
return JIM_OK;
34623606
}
34633607
3464
-#ifndef HAVE_LSTAT
3465
-#define lstat stat
3466
-#endif
3467
-
3608
+#ifdef HAVE_LSTAT
34683609
static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
34693610
{
34703611
const char *path = Jim_String(filename);
34713612
34723613
if (lstat(path, sb) == -1) {
@@ -3473,10 +3614,13 @@
34733614
Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
34743615
return JIM_ERR;
34753616
}
34763617
return JIM_OK;
34773618
}
3619
+#else
3620
+#define file_lstat file_stat
3621
+#endif
34783622
34793623
static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34803624
{
34813625
struct stat sb;
34823626
@@ -3601,28 +3745,32 @@
36013745
}
36023746
Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
36033747
return JIM_OK;
36043748
}
36053749
3750
+#ifdef HAVE_LSTAT
36063751
static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36073752
{
36083753
struct stat sb;
36093754
36103755
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
36113756
return JIM_ERR;
36123757
}
3613
- return StoreStatData(interp, argv[1], &sb);
3758
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36143759
}
3760
+#else
3761
+#define file_cmd_lstat file_cmd_stat
3762
+#endif
36153763
36163764
static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36173765
{
36183766
struct stat sb;
36193767
36203768
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
36213769
return JIM_ERR;
36223770
}
3623
- return StoreStatData(interp, argv[1], &sb);
3771
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36243772
}
36253773
36263774
static const jim_subcmd_type file_command_table[] = {
36273775
{ "atime",
36283776
"name",
@@ -3727,19 +3875,17 @@
37273875
file_cmd_mkdir,
37283876
1,
37293877
-1,
37303878
37313879
},
3732
-#ifdef HAVE_MKSTEMP
37333880
{ "tempfile",
37343881
"?template?",
37353882
file_cmd_tempfile,
37363883
0,
37373884
1,
37383885
37393886
},
3740
-#endif
37413887
{ "rename",
37423888
"?-force? source dest",
37433889
file_cmd_rename,
37443890
2,
37453891
3,
@@ -3760,20 +3906,20 @@
37603906
1,
37613907
1,
37623908
37633909
},
37643910
{ "stat",
3765
- "name var",
3911
+ "name ?var?",
37663912
file_cmd_stat,
3767
- 2,
3913
+ 1,
37683914
2,
37693915
37703916
},
37713917
{ "lstat",
3772
- "name var",
3918
+ "name ?var?",
37733919
file_cmd_lstat,
3774
- 2,
3920
+ 1,
37753921
2,
37763922
37773923
},
37783924
{ "type",
37793925
"name",
@@ -3829,15 +3975,15 @@
38293975
return JIM_OK;
38303976
}
38313977
38323978
static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
38333979
{
3834
- const int cwd_len = 2048;
3835
- char *cwd = malloc(cwd_len);
3980
+ char *cwd = Jim_Alloc(MAXPATHLEN);
38363981
3837
- if (getcwd(cwd, cwd_len) == NULL) {
3982
+ if (getcwd(cwd, MAXPATHLEN) == NULL) {
38383983
Jim_SetResultString(interp, "Failed to get pwd", -1);
3984
+ Jim_Free(cwd);
38393985
return JIM_ERR;
38403986
}
38413987
#if defined(__MINGW32__) || defined(_MSC_VER)
38423988
{
38433989
@@ -3848,11 +3994,11 @@
38483994
}
38493995
#endif
38503996
38513997
Jim_SetResultString(interp, cwd, -1);
38523998
3853
- free(cwd);
3999
+ Jim_Free(cwd);
38544000
return JIM_OK;
38554001
}
38564002
38574003
int Jim_fileInit(Jim_Interp *interp)
38584004
{
@@ -3917,10 +4063,11 @@
39174063
39184064
int Jim_execInit(Jim_Interp *interp)
39194065
{
39204066
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
39214067
return JIM_ERR;
4068
+
39224069
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
39234070
return JIM_OK;
39244071
}
39254072
#else
39264073
@@ -3960,10 +4107,11 @@
39604107
static int JimErrno(void);
39614108
#else
39624109
#include <unistd.h>
39634110
#include <fcntl.h>
39644111
#include <sys/wait.h>
4112
+ #include <sys/stat.h>
39654113
39664114
typedef int fdtype;
39674115
typedef int pidtype;
39684116
#define JimPipe pipe
39694117
#define JimErrno() errno
@@ -4034,23 +4182,12 @@
40344182
Jim_RemoveTrailingNewline(strObj);
40354183
fclose(fh);
40364184
return JIM_OK;
40374185
}
40384186
4039
-static void JimTrimTrailingNewline(Jim_Interp *interp)
4040
-{
4041
- int len;
4042
- const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4043
-
4044
- if (len > 0 && p[len - 1] == '\n') {
4045
- Jim_SetResultString(interp, p, len - 1);
4046
- }
4047
-}
4048
-
40494187
static char **JimBuildEnv(Jim_Interp *interp)
40504188
{
4051
-#if defined(jim_ext_tclcompat)
40524189
int i;
40534190
int size;
40544191
int num;
40554192
int n;
40564193
char **envptr;
@@ -4064,10 +4201,11 @@
40644201
40654202
40664203
40674204
num = Jim_ListLength(interp, objPtr);
40684205
if (num % 2) {
4206
+
40694207
num--;
40704208
}
40714209
size = Jim_Length(objPtr) + 2;
40724210
40734211
envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4090,22 +4228,17 @@
40904228
}
40914229
envptr[n] = NULL;
40924230
*envdata = 0;
40934231
40944232
return envptr;
4095
-#else
4096
- return Jim_GetEnviron();
4097
-#endif
40984233
}
40994234
41004235
static void JimFreeEnv(char **env, char **original_environ)
41014236
{
4102
-#ifdef jim_ext_tclcompat
41034237
if (env != original_environ) {
41044238
Jim_Free(env);
41054239
}
4106
-#endif
41074240
}
41084241
41094242
static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
41104243
{
41114244
Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4154,19 +4287,19 @@
41544287
}
41554288
41564289
41574290
struct WaitInfo
41584291
{
4159
- pidtype pid;
4292
+ pidtype pid;
41604293
int status;
41614294
int flags;
41624295
};
41634296
41644297
struct WaitInfoTable {
4165
- struct WaitInfo *info;
4166
- int size;
4167
- int used;
4298
+ struct WaitInfo *info;
4299
+ int size;
4300
+ int used;
41684301
};
41694302
41704303
41714304
#define WI_DETACHED 2
41724305
@@ -4189,14 +4322,12 @@
41894322
return table;
41904323
}
41914324
41924325
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
41934326
{
4194
- fdtype outputId; /* File id for output pipe. -1
4195
- * means command overrode. */
4196
- fdtype errorId; /* File id for temporary file
4197
- * containing error output. */
4327
+ fdtype outputId;
4328
+ fdtype errorId;
41984329
pidtype *pidPtr;
41994330
int numPids, result;
42004331
42014332
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
42024333
Jim_Obj *listObj;
@@ -4243,26 +4374,32 @@
42434374
42444375
static void JimReapDetachedPids(struct WaitInfoTable *table)
42454376
{
42464377
struct WaitInfo *waitPtr;
42474378
int count;
4379
+ int dest;
42484380
42494381
if (!table) {
42504382
return;
42514383
}
42524384
4253
- 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--) {
42544388
if (waitPtr->flags & WI_DETACHED) {
42554389
int status;
42564390
pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4257
- if (pid != JIM_BAD_PID) {
4258
- if (waitPtr != &table->info[table->used - 1]) {
4259
- *waitPtr = table->info[table->used - 1];
4260
- }
4391
+ if (pid == waitPtr->pid) {
4392
+
42614393
table->used--;
4394
+ continue;
42624395
}
42634396
}
4397
+ if (waitPtr != &table->info[dest]) {
4398
+ table->info[dest] = *waitPtr;
4399
+ }
4400
+ dest++;
42644401
}
42654402
}
42664403
42674404
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
42684405
{
@@ -4284,11 +4421,10 @@
42844421
}
42854422
42864423
42874424
return JIM_BAD_PID;
42884425
}
4289
-
42904426
42914427
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
42924428
{
42934429
int j;
42944430
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4609,27 +4745,23 @@
46094745
}
46104746
outputId = pipeIds[1];
46114747
}
46124748
46134749
4750
+ if (pipe_dup_err) {
4751
+ errorId = outputId;
4752
+ }
4753
+
4754
+
46144755
46154756
#ifdef __MINGW32__
46164757
pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
46174758
if (pid == JIM_BAD_PID) {
46184759
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
46194760
goto error;
46204761
}
46214762
#else
4622
- if (table->info == NULL) {
4623
- (void)signal(SIGPIPE, SIG_IGN);
4624
- }
4625
-
4626
-
4627
- if (pipe_dup_err) {
4628
- errorId = outputId;
4629
- }
4630
-
46314763
pid = vfork();
46324764
if (pid < 0) {
46334765
Jim_SetResultErrno(interp, "couldn't fork child process");
46344766
goto error;
46354767
}
@@ -4642,14 +4774,17 @@
46424774
46434775
for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
46444776
close(i);
46454777
}
46464778
4779
+
4780
+ (void)signal(SIGPIPE, SIG_DFL);
4781
+
46474782
execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
46484783
46494784
4650
- fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4785
+ fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
46514786
_exit(127);
46524787
}
46534788
#endif
46544789
46554790
@@ -4751,19 +4886,24 @@
47514886
if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
47524887
result = JIM_ERR;
47534888
}
47544889
}
47554890
4756
- JimTrimTrailingNewline(interp);
4891
+ Jim_RemoveTrailingNewline(Jim_GetResult(interp));
47574892
47584893
return result;
47594894
}
47604895
47614896
int Jim_execInit(Jim_Interp *interp)
47624897
{
47634898
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
47644899
return JIM_ERR;
4900
+
4901
+#ifdef SIGPIPE
4902
+ (void)signal(SIGPIPE, SIG_IGN);
4903
+#endif
4904
+
47654905
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
47664906
return JIM_OK;
47674907
}
47684908
47694909
#if defined(__MINGW32__)
@@ -5088,28 +5228,26 @@
50885228
{
50895229
STARTUPINFO startInfo;
50905230
PROCESS_INFORMATION procInfo;
50915231
HANDLE hProcess, h;
50925232
char execPath[MAX_PATH];
5093
- char *originalName;
50945233
pidtype pid = JIM_BAD_PID;
50955234
Jim_Obj *cmdLineObj;
50965235
50975236
if (JimWinFindExecutable(argv[0], execPath) < 0) {
50985237
return JIM_BAD_PID;
50995238
}
5100
- originalName = argv[0];
51015239
argv[0] = execPath;
51025240
51035241
hProcess = GetCurrentProcess();
51045242
cmdLineObj = JimWinBuildCommandLine(interp, argv);
51055243
51065244
51075245
ZeroMemory(&startInfo, sizeof(startInfo));
51085246
startInfo.cb = sizeof(startInfo);
51095247
startInfo.dwFlags = STARTF_USESTDHANDLES;
5110
- startInfo.hStdInput = INVALID_HANDLE_VALUE;
5248
+ startInfo.hStdInput = INVALID_HANDLE_VALUE;
51115249
startInfo.hStdOutput= INVALID_HANDLE_VALUE;
51125250
startInfo.hStdError = INVALID_HANDLE_VALUE;
51135251
51145252
if (inputId == JIM_BAD_FD) {
51155253
if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5182,18 +5320,17 @@
51825320
return lseek(fd, 0L, SEEK_SET);
51835321
}
51845322
51855323
static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
51865324
{
5187
- char inName[] = "/tmp/tcl.tmp.XXXXXX";
5325
+ int fd = Jim_MakeTempFile(interp, NULL);
51885326
5189
- int fd = mkstemp(inName);
51905327
if (fd == JIM_BAD_FD) {
51915328
Jim_SetResultErrno(interp, "couldn't create temp file");
51925329
return -1;
51935330
}
5194
- unlink(inName);
5331
+ unlink(Jim_String(Jim_GetResult(interp)));
51955332
if (contents) {
51965333
if (write(fd, contents, len) != len) {
51975334
Jim_SetResultErrno(interp, "couldn't write temp file");
51985335
close(fd);
51995336
return -1;
@@ -5217,11 +5354,10 @@
52175354
}
52185355
#endif
52195356
#endif
52205357
52215358
5222
-
52235359
#ifndef _XOPEN_SOURCE
52245360
#define _XOPEN_SOURCE 500
52255361
#endif
52265362
52275363
#include <stdlib.h>
@@ -5239,11 +5375,11 @@
52395375
52405376
char buf[100];
52415377
time_t t;
52425378
long seconds;
52435379
5244
- const char *format = "%a %b %d %H:%M:%S %Z %Y";
5380
+ const char *format = "%a %b %d %H:%M:%S %Z %Y";
52455381
52465382
if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
52475383
return -1;
52485384
}
52495385
@@ -5254,11 +5390,14 @@
52545390
if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
52555391
return JIM_ERR;
52565392
}
52575393
t = seconds;
52585394
5259
- 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
+ }
52605399
52615400
Jim_SetResultString(interp, buf, -1);
52625401
52635402
return JIM_OK;
52645403
}
@@ -5374,11 +5513,10 @@
53745513
53755514
Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
53765515
return JIM_OK;
53775516
}
53785517
5379
-
53805518
#include <limits.h>
53815519
#include <stdlib.h>
53825520
#include <string.h>
53835521
#include <stdio.h>
53845522
#include <errno.h>
@@ -5392,33 +5530,29 @@
53925530
}
53935531
53945532
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
53955533
{
53965534
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5535
+ Jim_Obj *patternObj;
53975536
53985537
if (!objPtr) {
53995538
return JIM_OK;
54005539
}
54015540
5402
- if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5403
-
5404
- if (Jim_IsList(objPtr)) {
5405
- if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5406
-
5407
- return JIM_ERR;
5408
- }
5409
- }
5410
- else if (Jim_DictSize(interp, objPtr) < 0) {
5411
-
5412
- return JIM_ERR;
5413
- }
5414
- Jim_SetResult(interp, objPtr);
5415
- 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
+ }
54165550
}
54175551
54185552
5419
- return Jim_DictValues(interp, objPtr, argv[1]);
5553
+ return Jim_DictValues(interp, objPtr, patternObj);
54205554
}
54215555
54225556
static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54235557
{
54245558
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5443,10 +5577,15 @@
54435577
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
54445578
return JIM_OK;
54455579
}
54465580
54475581
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5582
+
5583
+ if (objPtr == NULL) {
5584
+
5585
+ return JIM_OK;
5586
+ }
54485587
54495588
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
54505589
return JIM_ERR;
54515590
}
54525591
@@ -5480,10 +5619,20 @@
54805619
54815620
Jim_SetResultInt(interp, len);
54825621
54835622
return JIM_OK;
54845623
}
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
+}
54855634
54865635
static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54875636
{
54885637
int i;
54895638
int len;
@@ -5498,10 +5647,13 @@
54985647
54995648
dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
55005649
if (!dictObj) {
55015650
55025651
return Jim_SetVariable(interp, argv[0], listObj);
5652
+ }
5653
+ else if (Jim_DictSize(interp, dictObj) < 0) {
5654
+ return JIM_ERR;
55035655
}
55045656
55055657
if (Jim_IsShared(dictObj)) {
55065658
dictObj = Jim_DuplicateObj(interp, dictObj);
55075659
}
@@ -5551,10 +5703,17 @@
55515703
"arrayName",
55525704
array_cmd_size,
55535705
1,
55545706
1,
55555707
5708
+ },
5709
+ { "stat",
5710
+ "arrayName",
5711
+ array_cmd_stat,
5712
+ 1,
5713
+ 1,
5714
+
55565715
},
55575716
{ "unset",
55585717
"arrayName ?pattern?",
55595718
array_cmd_unset,
55605719
1,
@@ -5597,11 +5756,10 @@
55975756
Jim_arrayInit(interp);
55985757
Jim_stdlibInit(interp);
55995758
Jim_tclcompatInit(interp);
56005759
return JIM_OK;
56015760
}
5602
-
56035761
#define JIM_OPTIMIZATION
56045762
56055763
#include <stdio.h>
56065764
#include <stdlib.h>
56075765
@@ -5661,21 +5819,20 @@
56615819
#define JIM_INTEGER_SPACE 24
56625820
56635821
const char *jim_tt_name(int type);
56645822
56655823
#ifdef JIM_DEBUG_PANIC
5666
-static void JimPanicDump(int panic_condition, const char *fmt, ...);
5824
+static void JimPanicDump(int fail_condition, const char *fmt, ...);
56675825
#define JimPanic(X) JimPanicDump X
56685826
#else
56695827
#define JimPanic(X)
56705828
#endif
56715829
56725830
56735831
static char JimEmptyStringRep[] = "";
56745832
5675
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5676
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5833
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
56775834
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
56785835
int flags);
56795836
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
56805837
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
56815838
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -5922,44 +6079,10 @@
59226079
}
59236080
return n;
59246081
}
59256082
#endif
59266083
5927
-static int JimWideToString(char *buf, jim_wide wideValue)
5928
-{
5929
- int pos = 0;
5930
-
5931
- if (wideValue == 0) {
5932
- buf[pos++] = '0';
5933
- }
5934
- else {
5935
- char tmp[JIM_INTEGER_SPACE];
5936
- int num = 0;
5937
- int i;
5938
-
5939
- if (wideValue < 0) {
5940
- buf[pos++] = '-';
5941
-
5942
- i = wideValue % 10;
5943
- tmp[num++] = (i > 0) ? (10 - i) : -i;
5944
- wideValue /= -10;
5945
- }
5946
-
5947
- while (wideValue) {
5948
- tmp[num++] = wideValue % 10;
5949
- wideValue /= 10;
5950
- }
5951
-
5952
- for (i = 0; i < num; i++) {
5953
- buf[pos++] = '0' + tmp[num - i - 1];
5954
- }
5955
- }
5956
- buf[pos] = 0;
5957
-
5958
- return pos;
5959
-}
5960
-
59616084
static int JimCheckConversion(const char *str, const char *endptr)
59626085
{
59636086
if (str[0] == '\0' || str == endptr) {
59646087
return JIM_ERR;
59656088
}
@@ -6070,48 +6193,10 @@
60706193
}
60716194
60726195
return JimCheckConversion(str, endptr);
60736196
}
60746197
6075
-int Jim_DoubleToString(char *buf, double doubleValue)
6076
-{
6077
- int len;
6078
- int i;
6079
-
6080
- len = sprintf(buf, "%.12g", doubleValue);
6081
-
6082
-
6083
- for (i = 0; i < len; i++) {
6084
- if (buf[i] == '.' || buf[i] == 'e') {
6085
-#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6086
- char *e = strchr(buf, 'e');
6087
- if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6088
-
6089
- e += 2;
6090
- memmove(e, e + 1, len - (e - buf));
6091
- return len - 1;
6092
- }
6093
-#endif
6094
- return len;
6095
- }
6096
-
6097
- if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6098
- buf[i] = toupper(UCHAR(buf[i]));
6099
- if (buf[i] == 'n' || buf[i] == 'N')
6100
- buf[i+2] = toupper(UCHAR(buf[i+2]));
6101
- buf[i + 3] = 0;
6102
- return i + 3;
6103
- }
6104
- }
6105
-
6106
- buf[i++] = '.';
6107
- buf[i++] = '0';
6108
- buf[i] = '\0';
6109
-
6110
- return i;
6111
-}
6112
-
61136198
int Jim_StringToDouble(const char *str, double *doublePtr)
61146199
{
61156200
char *endptr;
61166201
61176202
@@ -6133,23 +6218,23 @@
61336218
}
61346219
return res;
61356220
}
61366221
61376222
#ifdef JIM_DEBUG_PANIC
6138
-void JimPanicDump(int condition, const char *fmt, ...)
6223
+static void JimPanicDump(int condition, const char *fmt, ...)
61396224
{
61406225
va_list ap;
61416226
61426227
if (!condition) {
61436228
return;
61446229
}
61456230
61466231
va_start(ap, fmt);
61476232
6148
- fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6233
+ fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
61496234
vfprintf(stderr, fmt, ap);
6150
- fprintf(stderr, JIM_NL JIM_NL);
6235
+ fprintf(stderr, "\n\n");
61516236
va_end(ap);
61526237
61536238
#ifdef HAVE_BACKTRACE
61546239
{
61556240
void *array[40];
@@ -6157,13 +6242,13 @@
61576242
char **strings;
61586243
61596244
size = backtrace(array, 40);
61606245
strings = backtrace_symbols(array, size);
61616246
for (i = 0; i < size; i++)
6162
- fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6163
- fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6164
- 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");
61656250
}
61666251
#endif
61676252
61686253
exit(1);
61696254
}
@@ -6237,18 +6322,24 @@
62376322
h += (h << 3) + *buf++;
62386323
return h;
62396324
}
62406325
62416326
6327
+
62426328
62436329
static void JimResetHashTable(Jim_HashTable *ht)
62446330
{
62456331
ht->table = NULL;
62466332
ht->size = 0;
62476333
ht->sizemask = 0;
62486334
ht->used = 0;
62496335
ht->collisions = 0;
6336
+#ifdef JIM_RANDOMISE_HASH
6337
+ ht->uniq = (rand() ^ time(NULL) ^ clock());
6338
+#else
6339
+ ht->uniq = 0;
6340
+#endif
62506341
}
62516342
62526343
static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
62536344
{
62546345
iter->ht = ht;
@@ -6286,10 +6377,12 @@
62866377
62876378
Jim_InitHashTable(&n, ht->type, ht->privdata);
62886379
n.size = realsize;
62896380
n.sizemask = realsize - 1;
62906381
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6382
+
6383
+ n.uniq = ht->uniq;
62916384
62926385
62936386
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
62946387
62956388
n.used = ht->used;
@@ -6342,20 +6435,27 @@
63426435
int existed;
63436436
Jim_HashEntry *entry;
63446437
63456438
entry = JimInsertHashEntry(ht, key, 1);
63466439
if (entry->key) {
6347
-
6348
- 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
+ }
63496449
existed = 1;
63506450
}
63516451
else {
63526452
63536453
Jim_SetHashKey(ht, entry, key);
6454
+ Jim_SetHashVal(ht, entry, val);
63546455
existed = 0;
63556456
}
6356
- Jim_SetHashVal(ht, entry, val);
63576457
63586458
return existed;
63596459
}
63606460
63616461
@@ -6520,11 +6620,11 @@
65206620
return Jim_GenHashFunction(key, strlen(key));
65216621
}
65226622
65236623
static void *JimStringCopyHTDup(void *privdata, const void *key)
65246624
{
6525
- return strdup(key);
6625
+ return Jim_StrDup(key);
65266626
}
65276627
65286628
static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
65296629
{
65306630
return strcmp(key1, key2) == 0;
@@ -6620,11 +6720,11 @@
66206720
freeFunc(stack->vector[i]);
66216721
}
66226722
66236723
66246724
6625
-#define JIM_TT_NONE 0
6725
+#define JIM_TT_NONE 0
66266726
#define JIM_TT_STR 1
66276727
#define JIM_TT_ESC 2
66286728
#define JIM_TT_VAR 3
66296729
#define JIM_TT_DICTSUGAR 4
66306730
#define JIM_TT_CMD 5
@@ -6652,10 +6752,15 @@
66526752
66536753
66546754
#define JIM_PS_DEF 0
66556755
#define JIM_PS_QUOTE 1
66566756
#define JIM_PS_DICTSUGAR 2
6757
+
6758
+struct JimParseMissing {
6759
+ int ch;
6760
+ int line;
6761
+};
66576762
66586763
struct JimParserCtx
66596764
{
66606765
const char *p;
66616766
int len;
@@ -6665,17 +6770,11 @@
66656770
int tline;
66666771
int tt;
66676772
int eof;
66686773
int state;
66696774
int comment;
6670
- char missing;
6671
- int missingline;
6672
-};
6673
-
6674
-struct JimParseResult {
6675
- char missing;
6676
- int line;
6775
+ struct JimParseMissing missing;
66776776
};
66786777
66796778
static int JimParseScript(struct JimParserCtx *pc);
66806779
static int JimParseSep(struct JimParserCtx *pc);
66816780
static int JimParseEol(struct JimParserCtx *pc);
@@ -6685,11 +6784,10 @@
66856784
static int JimParseBrace(struct JimParserCtx *pc);
66866785
static int JimParseStr(struct JimParserCtx *pc);
66876786
static int JimParseComment(struct JimParserCtx *pc);
66886787
static void JimParseSubCmd(struct JimParserCtx *pc);
66896788
static int JimParseSubQuote(struct JimParserCtx *pc);
6690
-static void JimParseSubCmd(struct JimParserCtx *pc);
66916789
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
66926790
66936791
static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
66946792
{
66956793
pc->p = prg;
@@ -6700,12 +6798,12 @@
67006798
pc->tt = JIM_TT_NONE;
67016799
pc->eof = 0;
67026800
pc->state = JIM_PS_DEF;
67036801
pc->linenr = linenr;
67046802
pc->comment = 1;
6705
- pc->missing = ' ';
6706
- pc->missingline = linenr;
6803
+ pc->missing.ch = ' ';
6804
+ pc->missing.line = linenr;
67076805
}
67086806
67096807
static int JimParseScript(struct JimParserCtx *pc)
67106808
{
67116809
while (1) {
@@ -6837,12 +6935,12 @@
68376935
break;
68386936
}
68396937
pc->p++;
68406938
pc->len--;
68416939
}
6842
- pc->missing = '{';
6843
- pc->missingline = pc->tline;
6940
+ pc->missing.ch = '{';
6941
+ pc->missing.line = pc->tline;
68446942
pc->tend = pc->p - 1;
68456943
}
68466944
68476945
static int JimParseSubQuote(struct JimParserCtx *pc)
68486946
{
@@ -6884,12 +6982,12 @@
68846982
break;
68856983
}
68866984
pc->p++;
68876985
pc->len--;
68886986
}
6889
- pc->missing = '"';
6890
- pc->missingline = line;
6987
+ pc->missing.ch = '"';
6988
+ pc->missing.line = line;
68916989
pc->tend = pc->p - 1;
68926990
return tt;
68936991
}
68946992
68956993
static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6943,12 +7041,12 @@
69437041
}
69447042
startofword = isspace(UCHAR(*pc->p));
69457043
pc->p++;
69467044
pc->len--;
69477045
}
6948
- pc->missing = '[';
6949
- pc->missingline = line;
7046
+ pc->missing.ch = '[';
7047
+ pc->missing.line = line;
69507048
pc->tend = pc->p - 1;
69517049
}
69527050
69537051
static int JimParseBrace(struct JimParserCtx *pc)
69547052
{
@@ -7088,19 +7186,19 @@
70887186
if (*pc->p == '"') {
70897187
pc->state = JIM_PS_QUOTE;
70907188
pc->p++;
70917189
pc->len--;
70927190
7093
- pc->missingline = pc->tline;
7191
+ pc->missing.line = pc->tline;
70947192
}
70957193
}
70967194
pc->tstart = pc->p;
70977195
pc->tline = pc->linenr;
70987196
while (1) {
70997197
if (pc->len == 0) {
71007198
if (pc->state == JIM_PS_QUOTE) {
7101
- pc->missing = '"';
7199
+ pc->missing.ch = '"';
71027200
}
71037201
pc->tend = pc->p - 1;
71047202
pc->tt = JIM_TT_ESC;
71057203
return JIM_OK;
71067204
}
@@ -7116,10 +7214,14 @@
71167214
pc->linenr++;
71177215
}
71187216
pc->p++;
71197217
pc->len--;
71207218
}
7219
+ else if (pc->len == 1) {
7220
+
7221
+ pc->missing.ch = '\\';
7222
+ }
71217223
break;
71227224
case '(':
71237225
71247226
if (pc->len > 1 && pc->p[1] != '$') {
71257227
break;
@@ -7176,17 +7278,26 @@
71767278
}
71777279
71787280
static int JimParseComment(struct JimParserCtx *pc)
71797281
{
71807282
while (*pc->p) {
7181
- 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--;
71827297
pc->linenr++;
7183
- if (*(pc->p - 1) != '\\') {
7184
- pc->p++;
7185
- pc->len--;
7186
- return JIM_OK;
7187
- }
7298
+ break;
71887299
}
71897300
pc->p++;
71907301
pc->len--;
71917302
}
71927303
return JIM_OK;
@@ -7404,13 +7515,13 @@
74047515
JimParserInit(&parser, s, len, 1);
74057516
while (!parser.eof) {
74067517
JimParseScript(&parser);
74077518
}
74087519
if (stateCharPtr) {
7409
- *stateCharPtr = parser.missing;
7520
+ *stateCharPtr = parser.missing.ch;
74107521
}
7411
- return parser.missing == ' ';
7522
+ return parser.missing.ch == ' ';
74127523
}
74137524
74147525
static int JimParseListSep(struct JimParserCtx *pc);
74157526
static int JimParseListStr(struct JimParserCtx *pc);
74167527
static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7662,10 +7773,16 @@
76627773
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
76637774
objPtr->typePtr->updateStringProc(objPtr);
76647775
}
76657776
return objPtr->bytes;
76667777
}
7778
+
7779
+static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
7780
+{
7781
+ objPtr->bytes = Jim_StrDup(str);
7782
+ objPtr->length = strlen(str);
7783
+}
76677784
76687785
static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
76697786
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
76707787
76717788
static const Jim_ObjType dictSubstObjType = {
@@ -7703,11 +7820,10 @@
77037820
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
77047821
{
77057822
JIM_NOTUSED(interp);
77067823
77077824
dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7708
-
77097825
dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
77107826
}
77117827
77127828
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
77137829
{
@@ -7752,18 +7868,17 @@
77527868
if (len == -1)
77537869
len = strlen(s);
77547870
77557871
if (len == 0) {
77567872
objPtr->bytes = JimEmptyStringRep;
7757
- objPtr->length = 0;
77587873
}
77597874
else {
77607875
objPtr->bytes = Jim_Alloc(len + 1);
7761
- objPtr->length = len;
77627876
memcpy(objPtr->bytes, s, len);
77637877
objPtr->bytes[len] = '\0';
77647878
}
7879
+ objPtr->length = len;
77657880
77667881
77677882
objPtr->typePtr = NULL;
77687883
return objPtr;
77697884
}
@@ -7791,11 +7906,11 @@
77917906
Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
77927907
{
77937908
Jim_Obj *objPtr = Jim_NewObj(interp);
77947909
77957910
objPtr->bytes = s;
7796
- objPtr->length = len == -1 ? strlen(s) : len;
7911
+ objPtr->length = (len == -1) ? strlen(s) : len;
77977912
objPtr->typePtr = NULL;
77987913
return objPtr;
77997914
}
78007915
78017916
static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7820,17 +7935,17 @@
78207935
}
78217936
objPtr->internalRep.strValue.maxLength = needlen;
78227937
}
78237938
memcpy(objPtr->bytes + objPtr->length, str, len);
78247939
objPtr->bytes[objPtr->length + len] = '\0';
7940
+
78257941
if (objPtr->internalRep.strValue.charLength >= 0) {
78267942
78277943
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
78287944
}
78297945
objPtr->length += len;
78307946
}
7831
-
78327947
78337948
void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
78347949
{
78357950
JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
78367951
SetStringFromAny(interp, objPtr);
@@ -7838,13 +7953,11 @@
78387953
}
78397954
78407955
void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
78417956
{
78427957
int len;
7843
- const char *str;
7844
-
7845
- str = Jim_GetString(appendObjPtr, &len);
7958
+ const char *str = Jim_GetString(appendObjPtr, &len);
78467959
Jim_AppendString(interp, objPtr, str, len);
78477960
}
78487961
78497962
void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
78507963
{
@@ -7851,11 +7964,11 @@
78517964
va_list ap;
78527965
78537966
SetStringFromAny(interp, objPtr);
78547967
va_start(ap, objPtr);
78557968
while (1) {
7856
- char *s = va_arg(ap, char *);
7969
+ const char *s = va_arg(ap, const char *);
78577970
78587971
if (s == NULL)
78597972
break;
78607973
Jim_AppendString(interp, objPtr, s, -1);
78617974
}
@@ -7862,20 +7975,20 @@
78627975
va_end(ap);
78637976
}
78647977
78657978
int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
78667979
{
7867
- const char *aStr, *bStr;
7868
- int aLen, bLen;
7869
-
7870
- if (aObjPtr == bObjPtr)
7980
+ if (aObjPtr == bObjPtr) {
78717981
return 1;
7872
- aStr = Jim_GetString(aObjPtr, &aLen);
7873
- bStr = Jim_GetString(bObjPtr, &bLen);
7874
- if (aLen != bLen)
7875
- return 0;
7876
- 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
+ }
78777990
}
78787991
78797992
int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
78807993
{
78817994
return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8036,11 +8149,11 @@
80368149
static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
80378150
{
80388151
while (*str) {
80398152
int c;
80408153
str += utf8_tounicode(str, &c);
8041
- dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8154
+ dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
80428155
}
80438156
*dest = 0;
80448157
}
80458158
80468159
static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8096,11 +8209,11 @@
80968209
len *= 2;
80978210
#endif
80988211
buf = p = Jim_Alloc(len + 1);
80998212
81008213
str += utf8_tounicode(str, &c);
8101
- p += utf8_fromunicode(p, utf8_title(c));
8214
+ p += utf8_getchars(p, utf8_title(c));
81028215
81038216
JimStrCopyUpperLower(p, str, 0);
81048217
81058218
return Jim_NewStringObjNoAlloc(interp, buf, -1);
81068219
}
@@ -8203,10 +8316,11 @@
82038316
if (nontrim == NULL) {
82048317
82058318
return Jim_NewEmptyStringObj(interp);
82068319
}
82078320
if (nontrim == strObjPtr->bytes + len) {
8321
+
82088322
return strObjPtr;
82098323
}
82108324
82118325
if (Jim_IsShared(strObjPtr)) {
82128326
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8226,14 +8340,14 @@
82268340
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
82278341
82288342
82298343
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
82308344
8231
- if (objPtr != strObjPtr) {
8345
+
8346
+ if (objPtr != strObjPtr && objPtr->refCount == 0) {
82328347
8233
- Jim_IncrRefCount(objPtr);
8234
- Jim_DecrRefCount(interp, objPtr);
8348
+ Jim_FreeNewObj(interp, objPtr);
82358349
}
82368350
82378351
return strObjPtr;
82388352
}
82398353
@@ -8270,26 +8384,26 @@
82708384
return JIM_ERR;
82718385
}
82728386
82738387
str = Jim_GetString(strObjPtr, &len);
82748388
if (len == 0) {
8275
- Jim_SetResultInt(interp, !strict);
8389
+ Jim_SetResultBool(interp, !strict);
82768390
return JIM_OK;
82778391
}
82788392
82798393
switch (strclass) {
82808394
case STR_IS_INTEGER:
82818395
{
82828396
jim_wide w;
8283
- Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8397
+ Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
82848398
return JIM_OK;
82858399
}
82868400
82878401
case STR_IS_DOUBLE:
82888402
{
82898403
double d;
8290
- 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);
82918405
return JIM_OK;
82928406
}
82938407
82948408
case STR_IS_ALPHA: isclassfunc = isalpha; break;
82958409
case STR_IS_ALNUM: isclassfunc = isalnum; break;
@@ -8307,15 +8421,15 @@
83078421
return JIM_ERR;
83088422
}
83098423
83108424
for (i = 0; i < len; i++) {
83118425
if (!isclassfunc(str[i])) {
8312
- Jim_SetResultInt(interp, 0);
8426
+ Jim_SetResultBool(interp, 0);
83138427
return JIM_OK;
83148428
}
83158429
}
8316
- Jim_SetResultInt(interp, 1);
8430
+ Jim_SetResultBool(interp, 1);
83178431
return JIM_OK;
83188432
}
83198433
83208434
83218435
@@ -8327,17 +8441,19 @@
83278441
JIM_TYPE_REFERENCES,
83288442
};
83298443
83308444
int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
83318445
{
8332
- if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8446
+ if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
83338447
return 1;
8448
+ }
83348449
else {
83358450
const char *objStr = Jim_String(objPtr);
83368451
83378452
if (strcmp(str, objStr) != 0)
83388453
return 0;
8454
+
83398455
if (objPtr->typePtr != &comparedStringObjType) {
83408456
Jim_FreeIntRep(interp, objPtr);
83418457
objPtr->typePtr = &comparedStringObjType;
83428458
}
83438459
objPtr->internalRep.ptr = (char *)str;
@@ -8379,24 +8495,23 @@
83798495
83808496
static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
83818497
Jim_Obj *fileNameObj, int lineNumber)
83828498
{
83838499
JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8384
- JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8500
+ JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
83858501
Jim_IncrRefCount(fileNameObj);
83868502
objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
83878503
objPtr->internalRep.sourceValue.lineNumber = lineNumber;
83888504
objPtr->typePtr = &sourceObjType;
83898505
}
83908506
8391
-
83928507
static const Jim_ObjType scriptLineObjType = {
83938508
"scriptline",
83948509
NULL,
83958510
NULL,
83968511
NULL,
8397
- 0,
8512
+ JIM_NONE,
83988513
};
83998514
84008515
static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
84018516
{
84028517
Jim_Obj *objPtr;
@@ -8413,15 +8528,14 @@
84138528
objPtr->internalRep.scriptLineValue.line = line;
84148529
84158530
return objPtr;
84168531
}
84178532
8418
-#define JIM_CMDSTRUCT_EXPAND -1
8419
-
84208533
static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
84218534
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8422
-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);
84238537
84248538
static const Jim_ObjType scriptObjType = {
84258539
"script",
84268540
FreeScriptInternalRep,
84278541
DupScriptInternalRep,
@@ -8429,34 +8543,33 @@
84298543
JIM_TYPE_REFERENCES,
84308544
};
84318545
84328546
typedef struct ScriptToken
84338547
{
8434
- int type;
84358548
Jim_Obj *objPtr;
8549
+ int type;
84368550
} ScriptToken;
84378551
84388552
typedef struct ScriptObj
84398553
{
8440
- int len;
84418554
ScriptToken *token;
8555
+ Jim_Obj *fileNameObj;
8556
+ int len;
84428557
int substFlags;
84438558
int inUse; /* Used to share a ScriptObj. Currently
84448559
only used by Jim_EvalObj() as protection against
84458560
shimmering of the currently evaluated object. */
8446
- Jim_Obj *fileNameObj;
84478561
int firstline;
84488562
int linenr;
84498563
} ScriptObj;
84508564
84518565
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
84528566
{
84538567
int i;
84548568
struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
84558569
8456
- script->inUse--;
8457
- if (script->inUse != 0)
8570
+ if (--script->inUse != 0)
84588571
return;
84598572
for (i = 0; i < script->len; i++) {
84608573
Jim_DecrRefCount(interp, script->token[i].objPtr);
84618574
}
84628575
Jim_Free(script->token);
@@ -8467,11 +8580,10 @@
84678580
void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
84688581
{
84698582
JIM_NOTUSED(interp);
84708583
JIM_NOTUSED(srcPtr);
84718584
8472
-
84738585
dupPtr->typePtr = NULL;
84748586
}
84758587
84768588
typedef struct
84778589
{
@@ -8666,11 +8778,11 @@
86668778
token--;
86678779
}
86688780
86698781
script->len = token - script->token;
86708782
8671
- assert(script->len < count);
8783
+ JimPanic((script->len >= count, "allocated script array is too short"));
86728784
86738785
#ifdef DEBUG_SHOW_SCRIPT
86748786
printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
86758787
for (i = 0; i < script->len; i++) {
86768788
const ScriptToken *t = &script->token[i];
@@ -8677,10 +8789,35 @@
86778789
printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
86788790
}
86798791
#endif
86808792
86818793
}
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
+}
86828819
86838820
static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
86848821
ParseTokenList *tokenlist)
86858822
{
86868823
int i;
@@ -8699,18 +8836,19 @@
86998836
}
87008837
87018838
script->len = i;
87028839
}
87038840
8704
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8841
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
87058842
{
87068843
int scriptTextLen;
87078844
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
87088845
struct JimParserCtx parser;
87098846
struct ScriptObj *script;
87108847
ParseTokenList tokenlist;
87118848
int line = 1;
8849
+ int retcode = JIM_OK;
87128850
87138851
87148852
if (objPtr->typePtr == &sourceObjType) {
87158853
line = objPtr->internalRep.sourceValue.lineNumber;
87168854
}
@@ -8722,16 +8860,12 @@
87228860
while (!parser.eof) {
87238861
JimParseScript(&parser);
87248862
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
87258863
parser.tline);
87268864
}
8727
- if (result && parser.missing != ' ') {
8728
- ScriptTokenListFree(&tokenlist);
8729
- result->missing = parser.missing;
8730
- result->line = parser.missingline;
8731
- return JIM_ERR;
8732
- }
8865
+
8866
+ retcode = JimParseCheckMissing(interp, parser.missing.ch);
87338867
87348868
87358869
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
87368870
87378871
@@ -8742,10 +8876,11 @@
87428876
script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
87438877
}
87448878
else {
87458879
script->fileNameObj = interp->emptyObj;
87468880
}
8881
+ script->linenr = parser.missing.line;
87478882
Jim_IncrRefCount(script->fileNameObj);
87488883
87498884
ScriptObjAddTokens(interp, script, &tokenlist);
87508885
87518886
@@ -8754,11 +8889,11 @@
87548889
87558890
Jim_FreeIntRep(interp, objPtr);
87568891
Jim_SetIntRepPtr(objPtr, script);
87578892
objPtr->typePtr = &scriptObjType;
87588893
8759
- return JIM_OK;
8894
+ return retcode;
87608895
}
87618896
87628897
ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
87638898
{
87648899
if (objPtr == interp->emptyObj) {
@@ -8765,11 +8900,13 @@
87658900
87668901
objPtr = interp->nullScriptObj;
87678902
}
87688903
87698904
if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8770
- SetScriptFromAny(interp, objPtr, NULL);
8905
+ if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
8906
+ return NULL;
8907
+ }
87718908
}
87728909
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
87738910
}
87748911
87758912
static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8850,10 +8987,26 @@
88508987
nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
88518988
Jim_AppendStrings(interp, nsObj, "::", name, NULL);
88528989
}
88538990
return nsObj;
88548991
}
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
+}
88559008
88569009
static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
88579010
{
88589011
Jim_Obj *objPtr = interp->emptyObj;
88599012
@@ -8877,10 +9030,15 @@
88779030
88789031
#else
88799032
88809033
#define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
88819034
#define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9035
+
9036
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9037
+{
9038
+ return nameObjPtr;
9039
+}
88829040
#endif
88839041
88849042
static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
88859043
{
88869044
Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8889,12 +9047,12 @@
88899047
Jim_InterpIncrProcEpoch(interp);
88909048
}
88919049
88929050
if (he && interp->local) {
88939051
8894
- cmd->prevCmd = he->u.val;
8895
- he->u.val = cmd;
9052
+ cmd->prevCmd = Jim_GetHashEntryVal(he);
9053
+ Jim_SetHashVal(&interp->commands, he, cmd);
88969054
}
88979055
else {
88989056
if (he) {
88999057
89009058
Jim_DeleteHashEntry(&interp->commands, name);
@@ -8933,19 +9091,19 @@
89339091
}
89349092
89359093
cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
89369094
Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
89379095
for (i = 0; i < len; i++) {
8938
- Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
9096
+ Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
89399097
Jim_Var *varPtr;
89409098
int subLen;
89419099
8942
- Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
9100
+ objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
89439101
89449102
subLen = Jim_ListLength(interp, objPtr);
89459103
if (subLen == 1 || subLen == 2) {
8946
- Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
9104
+ nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
89479105
if (subLen == 1) {
89489106
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
89499107
if (initObjPtr == NULL) {
89509108
Jim_SetResultFormatted(interp,
89519109
"variable for initialization of static \"%#s\" not found in the local context",
@@ -8952,11 +9110,11 @@
89529110
nameObjPtr);
89539111
return JIM_ERR;
89549112
}
89559113
}
89569114
else {
8957
- Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
9115
+ initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
89589116
}
89599117
if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
89609118
return JIM_ERR;
89619119
}
89629120
@@ -9038,11 +9196,11 @@
90389196
Jim_Obj *nameObjPtr;
90399197
Jim_Obj *defaultObjPtr;
90409198
int len;
90419199
90429200
9043
- Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9201
+ argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
90449202
len = Jim_ListLength(interp, argPtr);
90459203
if (len == 0) {
90469204
Jim_SetResultString(interp, "argument with no name", -1);
90479205
err:
90489206
JimDecrCmdRefCount(interp, cmdPtr);
@@ -9053,12 +9211,12 @@
90539211
goto err;
90549212
}
90559213
90569214
if (len == 2) {
90579215
9058
- Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9059
- Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9216
+ nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9217
+ defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
90609218
}
90619219
else {
90629220
90639221
nameObjPtr = argPtr;
90649222
defaultObjPtr = NULL;
@@ -9132,11 +9290,11 @@
91329290
else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
91339291
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
91349292
}
91359293
else {
91369294
9137
- cmdPtr = he->u.val;
9295
+ cmdPtr = Jim_GetHashEntryVal(he);
91389296
JimIncrCmdRefCount(cmdPtr);
91399297
JimUpdateProcNamespace(interp, cmdPtr, fqnew);
91409298
Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
91419299
91429300
@@ -9217,11 +9375,11 @@
92179375
return NULL;
92189376
}
92199377
#ifdef jim_ext_namespace
92209378
found:
92219379
#endif
9222
- cmd = (Jim_Cmd *)he->u.val;
9380
+ cmd = Jim_GetHashEntryVal(he);
92239381
92249382
92259383
Jim_FreeIntRep(interp, objPtr);
92269384
objPtr->typePtr = &commandObjType;
92279385
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9323,11 +9481,11 @@
93239481
93249482
93259483
Jim_FreeIntRep(interp, objPtr);
93269484
objPtr->typePtr = &variableObjType;
93279485
objPtr->internalRep.varValue.callFrameId = framePtr->id;
9328
- objPtr->internalRep.varValue.varPtr = he->u.val;
9486
+ objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
93299487
objPtr->internalRep.varValue.global = global;
93309488
return JIM_OK;
93319489
}
93329490
93339491
@@ -9641,11 +9799,11 @@
96419799
}
96429800
96439801
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
96449802
if (retval == JIM_OK) {
96459803
9646
- JimChangeCallFrameId(interp, framePtr);
9804
+ framePtr->id = interp->callFrameEpoch++;
96479805
}
96489806
}
96499807
}
96509808
if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
96519809
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9725,28 +9883,17 @@
97259883
return NULL;
97269884
}
97279885
97289886
ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
97299887
if (ret != JIM_OK) {
9730
- resObjPtr = NULL;
9731
- if (ret < 0) {
9732
- Jim_SetResultFormatted(interp,
9733
- "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9734
- }
9735
- else {
9736
- Jim_SetResultFormatted(interp,
9737
- "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9738
- }
9888
+ Jim_SetResultFormatted(interp,
9889
+ "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
9890
+ ret < 0 ? "variable isn't" : "no such element in");
97399891
}
97409892
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9741
- dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9742
- if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9743
-
9744
- JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9745
- }
97469893
9747
- Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9894
+ Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
97489895
}
97499896
97509897
return resObjPtr;
97519898
}
97529899
@@ -9843,68 +9990,67 @@
98439990
Jim_CallFrame *cf;
98449991
98459992
if (interp->freeFramesList) {
98469993
cf = interp->freeFramesList;
98479994
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;
984810006
}
984910007
else {
985010008
cf = Jim_Alloc(sizeof(*cf));
9851
- cf->vars.table = NULL;
10009
+ memset(cf, 0, sizeof(*cf));
10010
+
10011
+ Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
985210012
}
985310013
985410014
cf->id = interp->callFrameEpoch++;
985510015
cf->parent = parent;
985610016
cf->level = parent ? parent->level + 1 : 0;
9857
- cf->argv = NULL;
9858
- cf->argc = 0;
9859
- cf->procArgsObjPtr = NULL;
9860
- cf->procBodyObjPtr = NULL;
9861
- cf->next = NULL;
9862
- cf->staticVars = NULL;
9863
- cf->localCommands = NULL;
9864
-
986510017
cf->nsObj = nsObj;
986610018
Jim_IncrRefCount(nsObj);
9867
- if (cf->vars.table == NULL)
9868
- Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
10019
+
986910020
return cf;
987010021
}
987110022
9872
-
9873
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9874
-{
9875
- cf->id = interp->callFrameEpoch++;
9876
-}
9877
-
987810023
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
987910024
{
988010025
988110026
if (localCommands) {
988210027
Jim_Obj *cmdNameObj;
988310028
988410029
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
988510030
Jim_HashEntry *he;
988610031
Jim_Obj *fqObjName;
10032
+ Jim_HashTable *ht = &interp->commands;
988710033
988810034
const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
988910035
9890
- he = Jim_FindHashEntry(&interp->commands, fqname);
10036
+ he = Jim_FindHashEntry(ht, fqname);
989110037
989210038
if (he) {
9893
- Jim_Cmd *cmd = he->u.val;
10039
+ Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
989410040
if (cmd->prevCmd) {
989510041
Jim_Cmd *prevCmd = cmd->prevCmd;
989610042
cmd->prevCmd = NULL;
989710043
989810044
989910045
JimDecrCmdRefCount(interp, cmd);
990010046
990110047
9902
- he->u.val = prevCmd;
10048
+ Jim_SetHashVal(ht, he, prevCmd);
990310049
}
990410050
else {
9905
- Jim_DeleteHashEntry(&interp->commands, fqname);
10051
+ Jim_DeleteHashEntry(ht, fqname);
990610052
Jim_InterpIncrProcEpoch(interp);
990710053
}
990810054
}
990910055
Jim_DecrRefCount(interp, cmdNameObj);
991010056
JimFreeQualifiedName(interp, fqObjName);
@@ -9914,47 +10060,45 @@
991410060
}
991510061
return JIM_OK;
991610062
}
991710063
991810064
9919
-#define JIM_FCF_NONE 0
9920
-#define JIM_FCF_NOHT 1
9921
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9922
-{
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
+
992310071
if (cf->procArgsObjPtr)
992410072
Jim_DecrRefCount(interp, cf->procArgsObjPtr);
992510073
if (cf->procBodyObjPtr)
992610074
Jim_DecrRefCount(interp, cf->procBodyObjPtr);
992710075
Jim_DecrRefCount(interp, cf->nsObj);
9928
- if (!(flags & JIM_FCF_NOHT))
10076
+ if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
992910077
Jim_FreeHashTable(&cf->vars);
993010078
else {
993110079
int i;
993210080
Jim_HashEntry **table = cf->vars.table, *he;
993310081
993410082
for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
993510083
he = table[i];
993610084
while (he != NULL) {
993710085
Jim_HashEntry *nextEntry = he->next;
9938
- Jim_Var *varPtr = (void *)he->u.val;
10086
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
993910087
994010088
Jim_DecrRefCount(interp, varPtr->objPtr);
9941
- Jim_Free(he->u.val);
9942
- Jim_Free((void *)he->key);
10089
+ Jim_Free(Jim_GetHashEntryKey(he));
10090
+ Jim_Free(varPtr);
994310091
Jim_Free(he);
994410092
table[i] = NULL;
994510093
he = nextEntry;
994610094
}
994710095
}
994810096
cf->vars.used = 0;
994910097
}
9950
-
9951
- JimDeleteLocalProcs(interp, cf->localCommands);
9952
-
995310098
cf->next = interp->freeFramesList;
995410099
interp->freeFramesList = cf;
9955
-
995610100
}
995710101
995810102
995910103
#ifdef JIM_REFERENCES
996010104
@@ -10031,21 +10175,16 @@
1003110175
NULL,
1003210176
UpdateStringOfReference,
1003310177
JIM_TYPE_REFERENCES,
1003410178
};
1003510179
10036
-void UpdateStringOfReference(struct Jim_Obj *objPtr)
10180
+static void UpdateStringOfReference(struct Jim_Obj *objPtr)
1003710181
{
10038
- int len;
1003910182
char buf[JIM_REFERENCE_SPACE + 1];
10040
- Jim_Reference *refPtr;
1004110183
10042
- refPtr = objPtr->internalRep.refValue.refPtr;
10043
- len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10044
- objPtr->bytes = Jim_Alloc(len + 1);
10045
- memcpy(objPtr->bytes, buf, len + 1);
10046
- objPtr->length = len;
10184
+ JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10185
+ JimSetStringBytes(objPtr, buf);
1004710186
}
1004810187
1004910188
static int isrefchar(int c)
1005010189
{
1005110190
return (c == '_' || isalnum(c));
@@ -10096,11 +10235,11 @@
1009610235
he = Jim_FindHashEntry(&interp->references, &value);
1009710236
if (he == NULL) {
1009810237
Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
1009910238
return JIM_ERR;
1010010239
}
10101
- refPtr = he->u.val;
10240
+ refPtr = Jim_GetHashEntryVal(he);
1010210241
1010310242
Jim_FreeIntRep(interp, objPtr);
1010410243
objPtr->typePtr = &referenceObjType;
1010510244
objPtr->internalRep.refValue.id = value;
1010610245
objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10279,13 +10418,20 @@
1027910418
return i;
1028010419
}
1028110420
1028210421
void Jim_FreeInterp(Jim_Interp *i)
1028310422
{
10284
- Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
10423
+ Jim_CallFrame *cf, *cfx;
10424
+
1028510425
Jim_Obj *objPtr, *nextObjPtr;
1028610426
10427
+
10428
+ for (cf = i->framePtr; cf; cf = cfx) {
10429
+ cfx = cf->parent;
10430
+ JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10431
+ }
10432
+
1028710433
Jim_DecrRefCount(i, i->emptyObj);
1028810434
Jim_DecrRefCount(i, i->trueObj);
1028910435
Jim_DecrRefCount(i, i->falseObj);
1029010436
Jim_DecrRefCount(i, i->result);
1029110437
Jim_DecrRefCount(i, i->stackTrace);
@@ -10300,61 +10446,54 @@
1030010446
#endif
1030110447
Jim_FreeHashTable(&i->packages);
1030210448
Jim_Free(i->prngState);
1030310449
Jim_FreeHashTable(&i->assocData);
1030410450
10305
-
10306
- while (cf) {
10307
- prevcf = cf->parent;
10308
- JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10309
- cf = prevcf;
10310
- }
10451
+#ifdef JIM_MAINTAINER
1031110452
if (i->liveList != NULL) {
1031210453
objPtr = i->liveList;
1031310454
10314
- printf(JIM_NL "-------------------------------------" JIM_NL);
10315
- printf("Objects still in the free list:" JIM_NL);
10455
+ printf("\n-------------------------------------\n");
10456
+ printf("Objects still in the free list:\n");
1031610457
while (objPtr) {
1031710458
const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
1031810459
1031910460
if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10320
- printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10461
+ printf("%p (%d) %-10s: '%.20s...'\n",
1032110462
(void *)objPtr, objPtr->refCount, type, objPtr->bytes);
1032210463
}
1032310464
else {
10324
- printf("%p (%d) %-10s: '%s'" JIM_NL,
10465
+ printf("%p (%d) %-10s: '%s'\n",
1032510466
(void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
1032610467
}
1032710468
if (objPtr->typePtr == &sourceObjType) {
10328
- printf("FILE %s LINE %d" JIM_NL,
10469
+ printf("FILE %s LINE %d\n",
1032910470
Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
1033010471
objPtr->internalRep.sourceValue.lineNumber);
1033110472
}
1033210473
objPtr = objPtr->nextObjPtr;
1033310474
}
10334
- printf("-------------------------------------" JIM_NL JIM_NL);
10475
+ printf("-------------------------------------\n\n");
1033510476
JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
1033610477
}
10478
+#endif
10479
+
1033710480
1033810481
objPtr = i->freeList;
1033910482
while (objPtr) {
1034010483
nextObjPtr = objPtr->nextObjPtr;
1034110484
Jim_Free(objPtr);
1034210485
objPtr = nextObjPtr;
1034310486
}
10487
+
1034410488
10345
- cf = i->freeFramesList;
10346
- while (cf) {
10347
- nextcf = cf->next;
10348
- if (cf->vars.table != NULL)
10349
- 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);
1035010493
Jim_Free(cf);
10351
- cf = nextcf;
1035210494
}
10353
-#ifdef jim_ext_load
10354
- Jim_FreeLoadHandles(i);
10355
-#endif
1035610495
1035710496
1035810497
Jim_Free(i);
1035910498
}
1036010499
@@ -10455,11 +10594,10 @@
1045510594
interp->addStackTrace = 1;
1045610595
}
1045710596
}
1045810597
}
1045910598
10460
-
1046110599
static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
1046210600
Jim_Obj *fileNameObj, int linenr)
1046310601
{
1046410602
if (strcmp(procname, "unknown") == 0) {
1046510603
procname = "";
@@ -10513,12 +10651,11 @@
1051310651
void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
1051410652
{
1051510653
Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
1051610654
1051710655
if (entryPtr != NULL) {
10518
- AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10519
-
10656
+ AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
1052010657
return assocEntryPtr->data;
1052110658
}
1052210659
return NULL;
1052310660
}
1052410661
@@ -10552,20 +10689,44 @@
1055210689
};
1055310690
1055410691
1055510692
static void UpdateStringOfInt(struct Jim_Obj *objPtr)
1055610693
{
10557
- int len;
1055810694
char buf[JIM_INTEGER_SPACE + 1];
10695
+ jim_wide wideValue = JimWideValue(objPtr);
10696
+ int pos = 0;
1055910697
10560
- len = JimWideToString(buf, JimWideValue(objPtr));
10561
- objPtr->bytes = Jim_Alloc(len + 1);
10562
- memcpy(objPtr->bytes, buf, len + 1);
10563
- 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);
1056410725
}
1056510726
10566
-int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10727
+static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
1056710728
{
1056810729
jim_wide wideValue;
1056910730
const char *str;
1057010731
1057110732
if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10653,22 +10814,65 @@
1065310814
NULL,
1065410815
UpdateStringOfDouble,
1065510816
JIM_TYPE_NONE,
1065610817
};
1065710818
10658
-void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10659
-{
10660
- int len;
10661
- char buf[JIM_DOUBLE_SPACE + 1];
10662
-
10663
- len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10664
- objPtr->bytes = Jim_Alloc(len + 1);
10665
- memcpy(objPtr->bytes, buf, len + 1);
10666
- 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
+ }
1066710871
}
1066810872
10669
-int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10873
+static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1067010874
{
1067110875
double doubleValue;
1067210876
jim_wide wideValue;
1067310877
const char *str;
1067410878
@@ -10876,15 +11080,15 @@
1087611080
return JIM_ELESTR_SIMPLE;
1087711081
}
1087811082
return JIM_ELESTR_QUOTE;
1087911083
}
1088011084
10881
-static int BackslashQuoteString(const char *s, char *q)
11085
+static int BackslashQuoteString(const char *s, int len, char *q)
1088211086
{
1088311087
char *p = q;
1088411088
10885
- while (*s) {
11089
+ while (len--) {
1088611090
switch (*s) {
1088711091
case ' ':
1088811092
case '$':
1088911093
case '"':
1089011094
case '[':
@@ -10996,11 +11200,11 @@
1099611200
case JIM_ELESTR_QUOTE:
1099711201
if (i == 0 && strRep[0] == '#') {
1099811202
*p++ = '\\';
1099911203
realLength++;
1100011204
}
11001
- qlen = BackslashQuoteString(strRep, p);
11205
+ qlen = BackslashQuoteString(strRep, len, p);
1100211206
p += qlen;
1100311207
realLength += qlen;
1100411208
break;
1100511209
}
1100611210
@@ -11032,11 +11236,11 @@
1103211236
1103311237
if (objPtr->typePtr == &listObjType) {
1103411238
return JIM_OK;
1103511239
}
1103611240
11037
- if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11241
+ if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
1103811242
Jim_Obj **listObjPtrPtr;
1103911243
int len;
1104011244
int i;
1104111245
1104211246
listObjPtrPtr = JimDictPairs(objPtr, &len);
@@ -11136,15 +11340,17 @@
1113611340
Jim_Interp *interp;
1113711341
enum {
1113811342
JIM_LSORT_ASCII,
1113911343
JIM_LSORT_NOCASE,
1114011344
JIM_LSORT_INTEGER,
11345
+ JIM_LSORT_REAL,
1114111346
JIM_LSORT_COMMAND
1114211347
} type;
1114311348
int order;
1114411349
int index;
1114511350
int indexed;
11351
+ int unique;
1114611352
int (*subfn)(Jim_Obj **, Jim_Obj **);
1114711353
};
1114811354
1114911355
static struct lsort_info *sort_info;
1115011356
@@ -11179,10 +11385,27 @@
1117911385
longjmp(sort_info->jmpbuf, JIM_ERR);
1118011386
}
1118111387
1118211388
return JimSign(lhs - rhs) * sort_info->order;
1118311389
}
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
+}
1118411407
1118511408
static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
1118611409
{
1118711410
Jim_Obj *compare_script;
1118811411
int rc;
@@ -11201,10 +11424,34 @@
1120111424
}
1120211425
1120311426
return JimSign(ret) * sort_info->order;
1120411427
}
1120511428
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
+
1120611453
1120711454
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
1120811455
{
1120911456
struct lsort_info *prev_info;
1121011457
@@ -11212,11 +11459,11 @@
1121211459
int (*fn) (Jim_Obj **, Jim_Obj **);
1121311460
Jim_Obj **vector;
1121411461
int len;
1121511462
int rc;
1121611463
11217
- JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11464
+ JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
1121811465
SetListFromAny(interp, listObjPtr);
1121911466
1122011467
1122111468
prev_info = sort_info;
1122211469
sort_info = info;
@@ -11231,10 +11478,13 @@
1123111478
fn = ListSortStringNoCase;
1123211479
break;
1123311480
case JIM_LSORT_INTEGER:
1123411481
fn = ListSortInteger;
1123511482
break;
11483
+ case JIM_LSORT_REAL:
11484
+ fn = ListSortReal;
11485
+ break;
1123611486
case JIM_LSORT_COMMAND:
1123711487
fn = ListSortCommand;
1123811488
break;
1123911489
default:
1124011490
fn = NULL;
@@ -11247,12 +11497,17 @@
1124711497
fn = ListSortIndexHelper;
1124811498
}
1124911499
1125011500
if ((rc = setjmp(info->jmpbuf)) == 0) {
1125111501
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);
1125211508
}
11253
- Jim_InvalidateStringRep(listObjPtr);
1125411509
sort_info = prev_info;
1125511510
1125611511
return rc;
1125711512
}
1125811513
@@ -11377,11 +11632,11 @@
1137711632
listPtr->internalRep.listValue.ele[idx] = newObjPtr;
1137811633
Jim_IncrRefCount(newObjPtr);
1137911634
return JIM_OK;
1138011635
}
1138111636
11382
-int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11637
+int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
1138311638
Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
1138411639
{
1138511640
Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
1138611641
int shared, i, idx;
1138711642
@@ -11425,14 +11680,11 @@
1142511680
int i;
1142611681
int listLen = Jim_ListLength(interp, listObjPtr);
1142711682
Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
1142811683
1142911684
for (i = 0; i < listLen; ) {
11430
- Jim_Obj *objPtr;
11431
-
11432
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11433
- Jim_AppendObj(interp, resObjPtr, objPtr);
11685
+ Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
1143411686
if (++i != listLen) {
1143511687
Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
1143611688
}
1143711689
}
1143811690
return resObjPtr;
@@ -11458,43 +11710,42 @@
1145811710
int len = 0, objLen;
1145911711
char *bytes, *p;
1146011712
1146111713
1146211714
for (i = 0; i < objc; i++) {
11463
- Jim_GetString(objv[i], &objLen);
11464
- len += objLen;
11715
+ len += Jim_Length(objv[i]);
1146511716
}
1146611717
if (objc)
1146711718
len += objc - 1;
1146811719
1146911720
p = bytes = Jim_Alloc(len + 1);
1147011721
for (i = 0; i < objc; i++) {
1147111722
const char *s = Jim_GetString(objv[i], &objLen);
1147211723
1147311724
11474
- while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11725
+ while (objLen && isspace(UCHAR(*s))) {
1147511726
s++;
1147611727
objLen--;
1147711728
len--;
1147811729
}
1147911730
11480
- while (objLen && (s[objLen - 1] == ' ' ||
11481
- s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11731
+ while (objLen && isspace(UCHAR(s[objLen - 1]))) {
1148211732
1148311733
if (objLen > 1 && s[objLen - 2] == '\\') {
1148411734
break;
1148511735
}
1148611736
objLen--;
1148711737
len--;
1148811738
}
1148911739
memcpy(p, s, objLen);
1149011740
p += objLen;
11491
- if (objLen && i + 1 != objc) {
11492
- *p++ = ' ';
11493
- }
11494
- else if (i + 1 != objc) {
11495
- len--;
11741
+ if (i + 1 != objc) {
11742
+ if (objLen)
11743
+ *p++ = ' ';
11744
+ else {
11745
+ len--;
11746
+ }
1149611747
}
1149711748
}
1149811749
*p = '\0';
1149911750
return Jim_NewStringObjNoAlloc(interp, bytes, len);
1150011751
}
@@ -11534,20 +11785,26 @@
1153411785
1153511786
static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
1153611787
{
1153711788
return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
1153811789
}
11790
+
11791
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
11792
+{
11793
+ Jim_IncrRefCount((Jim_Obj *)val);
11794
+ return (void *)val;
11795
+}
1153911796
1154011797
static void JimObjectHTKeyValDestructor(void *interp, void *val)
1154111798
{
1154211799
Jim_DecrRefCount(interp, (Jim_Obj *)val);
1154311800
}
1154411801
1154511802
static const Jim_HashTableType JimDictHashTableType = {
1154611803
JimObjectHTHashFunction,
11547
- NULL,
11548
- NULL,
11804
+ JimObjectHTKeyValDup,
11805
+ JimObjectHTKeyValDup,
1154911806
JimObjectHTKeyCompare,
1155011807
JimObjectHTKeyValDestructor,
1155111808
JimObjectHTKeyValDestructor
1155211809
};
1155311810
@@ -11580,16 +11837,11 @@
1158011837
if (ht->size != 0)
1158111838
Jim_ExpandHashTable(dupHt, ht->size);
1158211839
1158311840
JimInitHashTableIterator(ht, &htiter);
1158411841
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11585
- const Jim_Obj *keyObjPtr = he->key;
11586
- Jim_Obj *valObjPtr = he->u.val;
11587
-
11588
- Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11589
- Jim_IncrRefCount(valObjPtr);
11590
- Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11842
+ Jim_AddHashEntry(dupHt, he->key, he->u.val);
1159111843
}
1159211844
1159311845
dupPtr->internalRep.ptr = dupHt;
1159411846
dupPtr->typePtr = &dictObjType;
1159511847
}
@@ -11607,12 +11859,12 @@
1160711859
1160811860
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
1160911861
JimInitHashTableIterator(ht, &htiter);
1161011862
i = 0;
1161111863
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11612
- objv[i++] = (Jim_Obj *)he->key;
11613
- objv[i++] = he->u.val;
11864
+ objv[i++] = Jim_GetHashEntryKey(he);
11865
+ objv[i++] = Jim_GetHashEntryVal(he);
1161411866
}
1161511867
*len = i;
1161611868
return objv;
1161711869
}
1161811870
@@ -11620,10 +11872,11 @@
1162011872
{
1162111873
1162211874
int len;
1162311875
Jim_Obj **objv = JimDictPairs(objPtr, &len);
1162411876
11877
+
1162511878
JimMakeListStringRep(objPtr, objv, len);
1162611879
1162711880
Jim_Free(objv);
1162811881
}
1162911882
@@ -11633,11 +11886,13 @@
1163311886
1163411887
if (objPtr->typePtr == &dictObjType) {
1163511888
return JIM_OK;
1163611889
}
1163711890
11638
- Jim_String(objPtr);
11891
+ if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11892
+ Jim_String(objPtr);
11893
+ }
1163911894
1164011895
1164111896
listlen = Jim_ListLength(interp, objPtr);
1164211897
if (listlen % 2) {
1164311898
Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11650,28 +11905,14 @@
1165011905
1165111906
ht = Jim_Alloc(sizeof(*ht));
1165211907
Jim_InitHashTable(ht, &JimDictHashTableType, interp);
1165311908
1165411909
for (i = 0; i < listlen; i += 2) {
11655
- Jim_Obj *keyObjPtr;
11656
- Jim_Obj *valObjPtr;
11657
-
11658
- Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11659
- Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11660
-
11661
- Jim_IncrRefCount(keyObjPtr);
11662
- Jim_IncrRefCount(valObjPtr);
11663
-
11664
- if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11665
- Jim_HashEntry *he;
11666
-
11667
- he = Jim_FindHashEntry(ht, keyObjPtr);
11668
- Jim_DecrRefCount(interp, keyObjPtr);
11669
-
11670
- Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11671
- he->u.val = valObjPtr;
11672
- }
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);
1167311914
}
1167411915
1167511916
Jim_FreeIntRep(interp, objPtr);
1167611917
objPtr->typePtr = &dictObjType;
1167711918
objPtr->internalRep.ptr = ht;
@@ -11688,31 +11929,23 @@
1168811929
Jim_HashTable *ht = objPtr->internalRep.ptr;
1168911930
1169011931
if (valueObjPtr == NULL) {
1169111932
return Jim_DeleteHashEntry(ht, keyObjPtr);
1169211933
}
11693
- Jim_IncrRefCount(keyObjPtr);
11694
- Jim_IncrRefCount(valueObjPtr);
11695
- if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11696
-
11697
- Jim_DecrRefCount(interp, keyObjPtr);
11698
- }
11934
+ Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
1169911935
return JIM_OK;
1170011936
}
1170111937
1170211938
int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
1170311939
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
1170411940
{
11705
- int retcode;
11706
-
1170711941
JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
1170811942
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1170911943
return JIM_ERR;
1171011944
}
11711
- retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1171211945
Jim_InvalidateStringRep(objPtr);
11713
- return retcode;
11946
+ return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1171411947
}
1171511948
1171611949
Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
1171711950
{
1171811951
Jim_Obj *objPtr;
@@ -11839,10 +12072,11 @@
1183912072
}
1184012073
objPtr = Jim_NewDictObj(interp, NULL, 0);
1184112074
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
1184212075
}
1184312076
}
12077
+
1184412078
Jim_InvalidateStringRep(objPtr);
1184512079
Jim_InvalidateStringRep(varObjPtr);
1184612080
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
1184712081
goto err;
1184812082
}
@@ -11864,28 +12098,29 @@
1186412098
NULL,
1186512099
UpdateStringOfIndex,
1186612100
JIM_TYPE_NONE,
1186712101
};
1186812102
11869
-void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11870
-{
11871
- int len;
11872
- char buf[JIM_INTEGER_SPACE + 1];
11873
-
11874
- if (objPtr->internalRep.intValue >= 0)
11875
- len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11876
- else if (objPtr->internalRep.intValue == -1)
11877
- len = sprintf(buf, "end");
12103
+static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
12104
+{
12105
+ if (objPtr->internalRep.intValue == -1) {
12106
+ JimSetStringBytes(objPtr, "end");
12107
+ }
1187812108
else {
11879
- 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);
1188012118
}
11881
- objPtr->bytes = Jim_Alloc(len + 1);
11882
- memcpy(objPtr->bytes, buf, len + 1);
11883
- objPtr->length = len;
1188412119
}
1188512120
11886
-int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12121
+static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1188712122
{
1188812123
int idx, end = 0;
1188912124
const char *str;
1189012125
char *endptr;
1189112126
@@ -11953,14 +12188,17 @@
1195312188
{
1195412189
1195512190
if (objPtr->typePtr == &intObjType) {
1195612191
jim_wide val = JimWideValue(objPtr);
1195712192
11958
- if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11959
- *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11960
- return JIM_OK;
11961
- }
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;
1196212200
}
1196312201
if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
1196412202
return JIM_ERR;
1196512203
*indexPtr = objPtr->internalRep.intValue;
1196612204
return JIM_OK;
@@ -11980,12 +12218,10 @@
1198012218
NULL
1198112219
};
1198212220
1198312221
#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
1198412222
11985
-static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11986
-
1198712223
static const Jim_ObjType returnCodeObjType = {
1198812224
"return-code",
1198912225
NULL,
1199012226
NULL,
1199112227
NULL,
@@ -12000,11 +12236,11 @@
1200012236
else {
1200112237
return jimReturnCodes[code];
1200212238
}
1200312239
}
1200412240
12005
-int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12241
+static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1200612242
{
1200712243
int returnCode;
1200812244
jim_wide wideValue;
1200912245
1201012246
@@ -12152,24 +12388,21 @@
1215212388
return e->stack[--e->stacklen];
1215312389
}
1215412390
1215512391
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
1215612392
{
12157
- int intresult = 0;
12393
+ int intresult = 1;
1215812394
int rc = JIM_OK;
1215912395
Jim_Obj *A = ExprPop(e);
1216012396
double dA, dC = 0;
1216112397
jim_wide wA, wC = 0;
1216212398
1216312399
if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12164
- intresult = 1;
12165
-
1216612400
switch (e->opcode) {
1216712401
case JIM_EXPROP_FUNC_INT:
12168
- wC = wA;
12169
- break;
1217012402
case JIM_EXPROP_FUNC_ROUND:
12403
+ case JIM_EXPROP_UNARYPLUS:
1217112404
wC = wA;
1217212405
break;
1217312406
case JIM_EXPROP_FUNC_DOUBLE:
1217412407
dC = wA;
1217512408
intresult = 0;
@@ -12178,13 +12411,10 @@
1217812411
wC = wA >= 0 ? wA : -wA;
1217912412
break;
1218012413
case JIM_EXPROP_UNARYMINUS:
1218112414
wC = -wA;
1218212415
break;
12183
- case JIM_EXPROP_UNARYPLUS:
12184
- wC = wA;
12185
- break;
1218612416
case JIM_EXPROP_NOT:
1218712417
wC = !wA;
1218812418
break;
1218912419
default:
1219012420
abort();
@@ -12192,31 +12422,29 @@
1219212422
}
1219312423
else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
1219412424
switch (e->opcode) {
1219512425
case JIM_EXPROP_FUNC_INT:
1219612426
wC = dA;
12197
- intresult = 1;
1219812427
break;
1219912428
case JIM_EXPROP_FUNC_ROUND:
1220012429
wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12201
- intresult = 1;
1220212430
break;
1220312431
case JIM_EXPROP_FUNC_DOUBLE:
12432
+ case JIM_EXPROP_UNARYPLUS:
1220412433
dC = dA;
12434
+ intresult = 0;
1220512435
break;
1220612436
case JIM_EXPROP_FUNC_ABS:
1220712437
dC = dA >= 0 ? dA : -dA;
12438
+ intresult = 0;
1220812439
break;
1220912440
case JIM_EXPROP_UNARYMINUS:
1221012441
dC = -dA;
12211
- break;
12212
- case JIM_EXPROP_UNARYPLUS:
12213
- dC = dA;
12442
+ intresult = 0;
1221412443
break;
1221512444
case JIM_EXPROP_NOT:
1221612445
wC = !dA;
12217
- intresult = 1;
1221812446
break;
1221912447
default:
1222012448
abort();
1222112449
}
1222212450
}
@@ -12427,11 +12655,11 @@
1242712655
1242812656
1242912657
1243012658
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
1243112659
{
12432
- int intresult = 0;
12660
+ int intresult = 1;
1243312661
int rc = JIM_OK;
1243412662
double dA, dB, dC = 0;
1243512663
jim_wide wA, wB, wC = 0;
1243612664
1243712665
Jim_Obj *B = ExprPop(e);
@@ -12441,12 +12669,10 @@
1244112669
(B->typePtr != &doubleObjType || B->bytes) &&
1244212670
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
1244312671
1244412672
1244512673
12446
- intresult = 1;
12447
-
1244812674
switch (e->opcode) {
1244912675
case JIM_EXPROP_POW:
1245012676
case JIM_EXPROP_FUNC_POW:
1245112677
wC = JimPowWide(wA, wB);
1245212678
break;
@@ -12496,10 +12722,11 @@
1249612722
default:
1249712723
abort();
1249812724
}
1249912725
}
1250012726
else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12727
+ intresult = 0;
1250112728
switch (e->opcode) {
1250212729
case JIM_EXPROP_POW:
1250312730
case JIM_EXPROP_FUNC_POW:
1250412731
#ifdef JIM_MATH_FUNCTIONS
1250512732
dC = pow(dA, dB);
@@ -12561,12 +12788,10 @@
1256112788
1256212789
1256312790
1256412791
int i = Jim_StringCompareObj(interp, A, B, 0);
1256512792
12566
- intresult = 1;
12567
-
1256812793
switch (e->opcode) {
1256912794
case JIM_EXPROP_LT:
1257012795
wC = i < 0;
1257112796
break;
1257212797
case JIM_EXPROP_GT:
@@ -12610,15 +12835,11 @@
1261012835
int listlen;
1261112836
int i;
1261212837
1261312838
listlen = Jim_ListLength(interp, listObjPtr);
1261412839
for (i = 0; i < listlen; i++) {
12615
- Jim_Obj *objPtr;
12616
-
12617
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12618
-
12619
- if (Jim_StringEqObj(objPtr, valObj)) {
12840
+ if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
1262012841
return 1;
1262112842
}
1262212843
}
1262312844
return 0;
1262412845
}
@@ -12630,23 +12851,16 @@
1263012851
1263112852
jim_wide wC;
1263212853
1263312854
switch (e->opcode) {
1263412855
case JIM_EXPROP_STREQ:
12635
- case JIM_EXPROP_STRNE: {
12636
- int Alen, Blen;
12637
- const char *sA = Jim_GetString(A, &Alen);
12638
- const char *sB = Jim_GetString(B, &Blen);
12639
-
12640
- if (e->opcode == JIM_EXPROP_STREQ) {
12641
- wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12642
- }
12643
- else {
12644
- 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;
1264512860
}
1264612861
break;
12647
- }
1264812862
case JIM_EXPROP_STRIN:
1264912863
wC = JimSearchList(interp, B, A);
1265012864
break;
1265112865
case JIM_EXPROP_STRNI:
1265212866
wC = !JimSearchList(interp, B, A);
@@ -12818,96 +13032,98 @@
1281813032
LAZY_OP,
1281913033
LAZY_LEFT,
1282013034
LAZY_RIGHT
1282113035
};
1282213036
12823
-#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
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}
1282413039
1282513040
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12826
- OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12827
- OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12828
- OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12829
-
12830
- OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12831
- OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12832
-
12833
- OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12834
- OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12835
-
12836
- OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12837
- OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12838
-
12839
- OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12840
- OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12841
- OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12842
- OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12843
-
12844
- OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12845
- OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12846
-
12847
- OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12848
- OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12849
- OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12850
-
12851
- OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12852
- OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12853
- OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12854
-
12855
- OPRINIT("||", 9, 2, NULL, LAZY_OP),
12856
- OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12857
- OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12858
-
12859
- OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12860
- OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12861
- OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12862
-
12863
- OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12864
- OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12865
- OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12866
-
12867
- OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12868
-
12869
- OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12870
- OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12871
-
12872
- OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12873
- OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12874
-
12875
- OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12876
- OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12877
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12878
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12879
-
12880
-
12881
-
12882
- OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12883
- OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12884
- OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12885
- OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12886
- OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12887
- OPRINIT("srand", 200, 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),
1288813103
1288913104
#ifdef JIM_MATH_FUNCTIONS
12890
- OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12891
- OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12892
- OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12893
- OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12894
- OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12895
- OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896
- OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897
- OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898
- OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899
- OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900
- OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901
- OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902
- OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903
- OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904
- OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905
- OPRINIT("pow", 200, 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),
1290613121
#endif
1290713122
};
1290813123
#undef OPRINIT
13124
+#undef OPRINIT_LAZY
1290913125
1291013126
#define JIM_EXPR_OPERATORS_NUM \
1291113127
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1291213128
1291313129
static int JimParseExpression(struct JimParserCtx *pc)
@@ -12919,13 +13135,16 @@
1291913135
}
1292013136
pc->p++;
1292113137
pc->len--;
1292213138
}
1292313139
13140
+
13141
+ pc->tline = pc->linenr;
13142
+ pc->tstart = pc->p;
13143
+
1292413144
if (pc->len == 0) {
12925
- pc->tstart = pc->tend = pc->p;
12926
- pc->tline = pc->linenr;
13145
+ pc->tend = pc->p;
1292713146
pc->tt = JIM_TT_EOL;
1292813147
pc->eof = 1;
1292913148
return JIM_OK;
1293013149
}
1293113150
switch (*(pc->p)) {
@@ -12936,12 +13155,11 @@
1293613155
pc->tt = JIM_TT_SUBEXPR_END;
1293713156
goto singlechar;
1293813157
case ',':
1293913158
pc->tt = JIM_TT_SUBEXPR_COMMA;
1294013159
singlechar:
12941
- pc->tstart = pc->tend = pc->p;
12942
- pc->tline = pc->linenr;
13160
+ pc->tend = pc->p;
1294313161
pc->p++;
1294413162
pc->len--;
1294513163
break;
1294613164
case '[':
1294713165
return JimParseCmd(pc);
@@ -12987,82 +13205,44 @@
1298713205
return JIM_OK;
1298813206
}
1298913207
1299013208
static int JimParseExprNumber(struct JimParserCtx *pc)
1299113209
{
12992
- int allowdot = 1;
12993
- int base = 10;
13210
+ char *end;
1299413211
1299513212
1299613213
pc->tt = JIM_TT_EXPR_INT;
12997
- pc->tstart = pc->p;
12998
- pc->tline = pc->linenr;
12999
-
13000
-
13001
- if (pc->p[0] == '0') {
13002
- switch (pc->p[1]) {
13003
- case 'x':
13004
- case 'X':
13005
- base = 16;
13006
- allowdot = 0;
13007
- pc->p += 2;
13008
- pc->len -= 2;
13009
- break;
13010
- case 'o':
13011
- case 'O':
13012
- base = 8;
13013
- allowdot = 0;
13014
- pc->p += 2;
13015
- pc->len -= 2;
13016
- break;
13017
- case 'b':
13018
- case 'B':
13019
- base = 2;
13020
- allowdot = 0;
13021
- pc->p += 2;
13022
- pc->len -= 2;
13023
- break;
13024
- }
13025
- }
13026
-
13027
- while (isdigit(UCHAR(*pc->p))
13028
- || (base == 16 && isxdigit(UCHAR(*pc->p)))
13029
- || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
13030
- || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
13031
- || (allowdot && *pc->p == '.')
13032
- ) {
13033
- if (*pc->p == '.') {
13034
- allowdot = 0;
13035
- pc->tt = JIM_TT_EXPR_DOUBLE;
13036
- }
13037
- pc->p++;
13038
- pc->len--;
13039
- if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
13040
- || isdigit(UCHAR(pc->p[1])))) {
13041
- pc->p += 2;
13042
- pc->len -= 2;
13043
- 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;
1304413225
}
1304513226
}
1304613227
pc->tend = pc->p - 1;
13228
+ pc->len -= (pc->p - pc->tstart);
1304713229
return JIM_OK;
1304813230
}
1304913231
1305013232
static int JimParseExprIrrational(struct JimParserCtx *pc)
1305113233
{
13052
- const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13053
- const char **token;
13054
-
13055
- for (token = Tokens; *token != NULL; token++) {
13056
- int len = strlen(*token);
13057
-
13058
- if (strncmp(*token, pc->p, len) == 0) {
13059
- pc->tstart = pc->p;
13060
- pc->tend = pc->p + len - 1;
13061
- pc->p += len;
13062
- pc->len -= len;
13063
- 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;
1306413244
pc->tt = JIM_TT_EXPR_DOUBLE;
1306513245
return JIM_OK;
1306613246
}
1306713247
}
1306813248
return JIM_ERR;
@@ -13102,15 +13282,13 @@
1310213282
}
1310313283
if (*p != '(') {
1310413284
return JIM_ERR;
1310513285
}
1310613286
}
13107
- pc->tstart = pc->p;
1310813287
pc->tend = pc->p + bestLen - 1;
1310913288
pc->p += bestLen;
1311013289
pc->len -= bestLen;
13111
- pc->tline = pc->linenr;
1311213290
1311313291
pc->tt = bestIdx;
1311413292
return JIM_OK;
1311513293
}
1311613294
@@ -13608,17 +13786,23 @@
1360813786
}
1360913787
1361013788
#ifdef DEBUG_SHOW_EXPR_TOKENS
1361113789
{
1361213790
int i;
13613
- printf("==== Expr Tokens ====\n");
13791
+ printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
1361413792
for (i = 0; i < tokenlist.count; i++) {
1361513793
printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
1361613794
tokenlist.list[i].len, tokenlist.list[i].token);
1361713795
}
1361813796
}
1361913797
#endif
13798
+
13799
+ if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
13800
+ ScriptTokenListFree(&tokenlist);
13801
+ Jim_DecrRefCount(interp, fileNameObj);
13802
+ return JIM_ERR;
13803
+ }
1362013804
1362113805
1362213806
expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
1362313807
1362413808
@@ -13665,10 +13849,24 @@
1366513849
return NULL;
1366613850
}
1366713851
}
1366813852
return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
1366913853
}
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
1367013868
1367113869
#define JIM_EE_STATICSTACK_LEN 10
1367213870
1367313871
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
1367413872
{
@@ -13688,102 +13886,69 @@
1368813886
Jim_Obj *objPtr;
1368913887
1369013888
1369113889
switch (expr->len) {
1369213890
case 1:
13693
- if (expr->token[0].type == JIM_TT_EXPR_INT) {
13694
- *exprResultPtrPtr = expr->token[0].objPtr;
13695
- Jim_IncrRefCount(*exprResultPtrPtr);
13696
- return JIM_OK;
13697
- }
13698
- if (expr->token[0].type == JIM_TT_VAR) {
13699
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13700
- if (objPtr) {
13701
- *exprResultPtrPtr = objPtr;
13702
- Jim_IncrRefCount(*exprResultPtrPtr);
13703
- return JIM_OK;
13704
- }
13891
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13892
+ if (objPtr) {
13893
+ Jim_IncrRefCount(objPtr);
13894
+ *exprResultPtrPtr = objPtr;
13895
+ return JIM_OK;
1370513896
}
1370613897
break;
1370713898
1370813899
case 2:
13709
- if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13710
- jim_wide wideValue;
13900
+ if (expr->token[1].type == JIM_EXPROP_NOT) {
13901
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
1371113902
13712
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13713
- if (objPtr && JimIsWide(objPtr)
13714
- && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13715
- *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13903
+ if (objPtr && JimIsWide(objPtr)) {
13904
+ *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
1371613905
Jim_IncrRefCount(*exprResultPtrPtr);
1371713906
return JIM_OK;
1371813907
}
1371913908
}
1372013909
break;
1372113910
1372213911
case 3:
13723
- if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13724
- || expr->token[1].type == JIM_TT_VAR)) {
13725
- switch (expr->token[2].type) {
13726
- case JIM_EXPROP_LT:
13727
- case JIM_EXPROP_LTE:
13728
- case JIM_EXPROP_GT:
13729
- case JIM_EXPROP_GTE:
13730
- case JIM_EXPROP_NUMEQ:
13731
- case JIM_EXPROP_NUMNE:{
13732
-
13733
- jim_wide wideValueA;
13734
- jim_wide wideValueB;
13735
-
13736
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13737
- if (objPtr && JimIsWide(objPtr)
13738
- && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13739
- if (expr->token[1].type == JIM_TT_VAR) {
13740
- objPtr =
13741
- Jim_GetVariable(interp, expr->token[1].objPtr,
13742
- JIM_NONE);
13743
- }
13744
- else {
13745
- objPtr = expr->token[1].objPtr;
13746
- }
13747
- if (objPtr && JimIsWide(objPtr)
13748
- && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13749
- int cmpRes;
13750
-
13751
- switch (expr->token[2].type) {
13752
- case JIM_EXPROP_LT:
13753
- cmpRes = wideValueA < wideValueB;
13754
- break;
13755
- case JIM_EXPROP_LTE:
13756
- cmpRes = wideValueA <= wideValueB;
13757
- break;
13758
- case JIM_EXPROP_GT:
13759
- cmpRes = wideValueA > wideValueB;
13760
- break;
13761
- case JIM_EXPROP_GTE:
13762
- cmpRes = wideValueA >= wideValueB;
13763
- break;
13764
- case JIM_EXPROP_NUMEQ:
13765
- cmpRes = wideValueA == wideValueB;
13766
- break;
13767
- case JIM_EXPROP_NUMNE:
13768
- cmpRes = wideValueA != wideValueB;
13769
- break;
13770
- default:
13771
- cmpRes = 0;
13772
- }
13773
- *exprResultPtrPtr =
13774
- cmpRes ? interp->trueObj : interp->falseObj;
13775
- Jim_IncrRefCount(*exprResultPtrPtr);
13776
- return JIM_OK;
13777
- }
13778
- }
13779
- }
13780
- }
13781
- }
13782
- break;
13783
- }
13784
- }
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:
1378513950
#endif
1378613951
1378713952
expr->inUse++;
1378813953
1378913954
@@ -13952,16 +14117,13 @@
1395214117
memcpy(newVec, srcPtr->internalRep.ptr, size);
1395314118
dupPtr->internalRep.ptr = newVec;
1395414119
dupPtr->typePtr = &scanFmtStringObjType;
1395514120
}
1395614121
13957
-void UpdateStringOfScanFmt(Jim_Obj *objPtr)
14122
+static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
1395814123
{
13959
- char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13960
-
13961
- objPtr->bytes = Jim_StrDup(bytes);
13962
- objPtr->length = strlen(bytes);
14124
+ JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
1396314125
}
1396414126
1396514127
1396614128
static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1396714129
{
@@ -14171,11 +14333,10 @@
1417114333
Jim_Obj *tmpObj = NULL;
1417214334
1417314335
1417414336
*valObjPtr = 0;
1417514337
if (descr->prefix) {
14176
-
1417714338
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
1417814339
1417914340
if (isspace(UCHAR(descr->prefix[i])))
1418014341
while (pos < strLen && isspace(UCHAR(str[pos])))
1418114342
++pos;
@@ -14512,34 +14673,55 @@
1451214673
}
1451314674
1451414675
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1451514676
{
1451614677
int retcode;
14517
- Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14678
+ Jim_Cmd *cmdPtr;
1451814679
14519
- if (cmdPtr == NULL) {
14520
- 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]));
1452114685
}
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
+
1452214702
if (interp->evalDepth == interp->maxEvalDepth) {
1452314703
Jim_SetResultString(interp, "Infinite eval recursion", -1);
14524
- return JIM_ERR;
14704
+ retcode = JIM_ERR;
14705
+ goto out;
1452514706
}
1452614707
interp->evalDepth++;
1452714708
1452814709
14529
- JimIncrCmdRefCount(cmdPtr);
1453014710
Jim_SetEmptyResult(interp);
1453114711
if (cmdPtr->isproc) {
1453214712
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
1453314713
}
1453414714
else {
1453514715
interp->cmdPrivData = cmdPtr->u.native.privData;
1453614716
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
1453714717
}
14538
- JimDecrCmdRefCount(interp, cmdPtr);
1453914718
interp->evalDepth--;
1454014719
14720
+out:
14721
+ JimDecrCmdRefCount(interp, cmdPtr);
14722
+
1454114723
return retcode;
1454214724
}
1454314725
1454414726
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1454514727
{
@@ -14717,10 +14899,15 @@
1471714899
objPtr->typePtr = &interpolatedObjType;
1471814900
objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
1471914901
objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
1472014902
Jim_IncrRefCount(intv[2]);
1472114903
}
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
+
1472214909
1472314910
s = objPtr->bytes = Jim_Alloc(totlen + 1);
1472414911
objPtr->length = totlen;
1472514912
for (i = 0; i < tokens; i++) {
1472614913
if (intv[i]) {
@@ -14772,10 +14959,14 @@
1477214959
return JimEvalObjList(interp, scriptObjPtr);
1477314960
}
1477414961
1477514962
Jim_IncrRefCount(scriptObjPtr);
1477614963
script = Jim_GetScript(interp, scriptObjPtr);
14964
+ if (script == NULL) {
14965
+ Jim_DecrRefCount(interp, scriptObjPtr);
14966
+ return JIM_ERR;
14967
+ }
1477714968
1477814969
Jim_SetEmptyResult(interp);
1477914970
1478014971
token = script->token;
1478114972
@@ -15046,26 +15237,20 @@
1504615237
retcode = Jim_EvalObj(interp, scriptObj);
1504715238
}
1504815239
1504915240
1505015241
interp->framePtr = interp->framePtr->parent;
15051
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15052
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15053
- }
15054
- else {
15055
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15056
- }
15242
+ JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1505715243
1505815244
return retcode;
1505915245
}
1506015246
#endif
1506115247
1506215248
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
1506315249
{
1506415250
Jim_CallFrame *callFramePtr;
1506515251
int i, d, retcode, optargs;
15066
- Jim_Stack *localCommands;
1506715252
ScriptObj *script;
1506815253
1506915254
1507015255
if (argc - 1 < cmd->u.proc.reqArity ||
1507115256
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15145,37 +15330,42 @@
1514515330
1514615331
1514715332
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
1514815333
1514915334
badargset:
15335
+
1515015336
15151
-
15152
- localCommands = callFramePtr->localCommands;
15153
- callFramePtr->localCommands = NULL;
15154
-
1515515337
interp->framePtr = interp->framePtr->parent;
15156
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15157
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15158
- }
15159
- else {
15160
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15161
- }
15162
-
15163
-
15164
- while (retcode == JIM_EVAL) {
15165
- Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15166
-
15167
- Jim_IncrRefCount(resultScriptObjPtr);
15168
-
15169
- JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15170
-
15171
- retcode = JimEvalObjList(interp, resultScriptObjPtr);
15172
- if (retcode == JIM_RETURN) {
15173
- interp->returnLevel++;
15174
- }
15175
- Jim_DecrRefCount(interp, resultScriptObjPtr);
15176
- }
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
+
1517715367
1517815368
if (retcode == JIM_RETURN) {
1517915369
if (--interp->returnLevel <= 0) {
1518015370
retcode = interp->returnCode;
1518115371
interp->returnCode = JIM_OK;
@@ -15187,13 +15377,10 @@
1518715377
Jim_DecrRefCount(interp, interp->errorProc);
1518815378
interp->errorProc = argv[0];
1518915379
Jim_IncrRefCount(interp->errorProc);
1519015380
}
1519115381
15192
-
15193
- JimDeleteLocalProcs(interp, localCommands);
15194
-
1519515382
return retcode;
1519615383
}
1519715384
1519815385
int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
1519915386
{
@@ -15261,11 +15448,10 @@
1526115448
Jim_Obj *scriptObjPtr;
1526215449
Jim_Obj *prevScriptObj;
1526315450
struct stat sb;
1526415451
int retcode;
1526515452
int readlen;
15266
- struct JimParseResult result;
1526715453
1526815454
if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
1526915455
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
1527015456
return JIM_ERR;
1527115457
}
@@ -15288,31 +15474,13 @@
1528815474
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
1528915475
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
1529015476
Jim_IncrRefCount(scriptObjPtr);
1529115477
1529215478
15293
- if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15294
- const char *msg;
15295
- char linebuf[20];
15296
-
15297
- switch (result.missing) {
15298
- case '[':
15299
- msg = "unmatched \"[\"";
15300
- break;
15301
- case '{':
15302
- msg = "missing close-brace";
15303
- break;
15304
- case '"':
15305
- default:
15306
- msg = "missing quote";
15307
- break;
15308
- }
15309
-
15310
- snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15311
-
15312
- Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15313
- msg, filename, linebuf);
15479
+ if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
15480
+
15481
+ JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
1531415482
Jim_DecrRefCount(interp, scriptObjPtr);
1531515483
return JIM_ERR;
1531615484
}
1531715485
1531815486
prevScriptObj = interp->currentScriptObj;
@@ -15475,11 +15643,11 @@
1547515643
}
1547615644
1547715645
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
1547815646
Jim_HashEntry *he, int type);
1547915647
15480
-#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15648
+#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
1548115649
1548215650
static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1548315651
JimHashtableIteratorCallbackType *callback, int type)
1548415652
{
1548515653
Jim_HashEntry *he;
@@ -15510,11 +15678,11 @@
1551015678
#define JIM_CMDLIST_CHANNELS 2
1551115679
1551215680
static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1551315681
Jim_HashEntry *he, int type)
1551415682
{
15515
- Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15683
+ Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
1551615684
Jim_Obj *objPtr;
1551715685
1551815686
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
1551915687
1552015688
return;
@@ -15543,11 +15711,11 @@
1554315711
#define JIM_VARLIST_VALUES 0x1000
1554415712
1554515713
static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1554615714
Jim_HashEntry *he, int type)
1554715715
{
15548
- Jim_Var *varPtr = (Jim_Var *)he->u.val;
15716
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
1554915717
1555015718
if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
1555115719
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
1555215720
if (type & JIM_VARLIST_VALUES) {
1555315721
Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15865,11 +16033,11 @@
1586516033
1586616034
expr = JimGetExpression(interp, argv[2]);
1586716035
incrScript = Jim_GetScript(interp, argv[3]);
1586816036
1586916037
15870
- if (incrScript->len != 3 || !expr || expr->len != 3) {
16038
+ if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
1587116039
goto evalstart;
1587216040
}
1587316041
1587416042
if (incrScript->token[1].type != JIM_TT_ESC ||
1587516043
expr->token[0].type != JIM_TT_VAR ||
@@ -16088,11 +16256,11 @@
1608816256
}
1608916257
1609016258
1609116259
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
1609216260
{
16093
- int result = JIM_ERR;
16261
+ int result = JIM_OK;
1609416262
int i, numargs;
1609516263
Jim_ListIter twoiters[2];
1609616264
Jim_ListIter *iters;
1609716265
Jim_Obj *script;
1609816266
Jim_Obj *resultObj;
@@ -16111,13 +16279,16 @@
1611116279
iters = Jim_Alloc(numargs * sizeof(*iters));
1611216280
}
1611316281
for (i = 0; i < numargs; i++) {
1611416282
JimListIterInit(&iters[i], argv[i + 1]);
1611516283
if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16116
- Jim_SetResultString(interp, "foreach varlist is empty", -1);
16117
- return JIM_ERR;
16284
+ result = JIM_ERR;
1611816285
}
16286
+ }
16287
+ if (result != JIM_OK) {
16288
+ Jim_SetResultString(interp, "foreach varlist is empty", -1);
16289
+ return result;
1611916290
}
1612016291
1612116292
if (doMap) {
1612216293
resultObj = Jim_NewListObj(interp, NULL, 0);
1612316294
}
@@ -16430,12 +16601,12 @@
1643016601
{
1643116602
Jim_Obj *objPtr, *listObjPtr;
1643216603
int i;
1643316604
int idx;
1643416605
16435
- if (argc < 3) {
16436
- Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16606
+ if (argc < 2) {
16607
+ Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
1643716608
return JIM_ERR;
1643816609
}
1643916610
objPtr = argv[1];
1644016611
Jim_IncrRefCount(objPtr);
1644116612
for (i = 2; i < argc; i++) {
@@ -16547,14 +16718,13 @@
1654716718
Jim_IncrRefCount(commandObj);
1654816719
}
1654916720
1655016721
listlen = Jim_ListLength(interp, argv[0]);
1655116722
for (i = 0; i < listlen; i++) {
16552
- Jim_Obj *objPtr;
1655316723
int eq = 0;
16724
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
1655416725
16555
- Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
1655616726
switch (opt_match) {
1655716727
case OPT_EXACT:
1655816728
eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
1655916729
break;
1656016730
@@ -16744,29 +16914,27 @@
1674416914
if (argc < 3) {
1674516915
Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
1674616916
return JIM_ERR;
1674716917
}
1674816918
else if (argc == 3) {
16919
+
1674916920
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1675016921
return JIM_ERR;
1675116922
Jim_SetResult(interp, argv[2]);
1675216923
return JIM_OK;
1675316924
}
16754
- if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16755
- == JIM_ERR)
16756
- return JIM_ERR;
16757
- return JIM_OK;
16925
+ return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
1675816926
}
1675916927
1676016928
1676116929
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
1676216930
{
1676316931
static const char * const options[] = {
16764
- "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16932
+ "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
1676516933
};
1676616934
enum
16767
- { 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 };
1676816936
Jim_Obj *resObj;
1676916937
int i;
1677016938
int retCode;
1677116939
1677216940
struct lsort_info info;
@@ -16777,17 +16945,18 @@
1677716945
}
1677816946
1677916947
info.type = JIM_LSORT_ASCII;
1678016948
info.order = 1;
1678116949
info.indexed = 0;
16950
+ info.unique = 0;
1678216951
info.command = NULL;
1678316952
info.interp = interp;
1678416953
1678516954
for (i = 1; i < (argc - 1); i++) {
1678616955
int option;
1678716956
16788
- 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)
1678916958
!= JIM_OK)
1679016959
return JIM_ERR;
1679116960
switch (option) {
1679216961
case OPT_ASCII:
1679316962
info.type = JIM_LSORT_ASCII;
@@ -16796,16 +16965,22 @@
1679616965
info.type = JIM_LSORT_NOCASE;
1679716966
break;
1679816967
case OPT_INTEGER:
1679916968
info.type = JIM_LSORT_INTEGER;
1680016969
break;
16970
+ case OPT_REAL:
16971
+ info.type = JIM_LSORT_REAL;
16972
+ break;
1680116973
case OPT_INCREASING:
1680216974
info.order = 1;
1680316975
break;
1680416976
case OPT_DECREASING:
1680516977
info.order = -1;
1680616978
break;
16979
+ case OPT_UNIQUE:
16980
+ info.unique = 1;
16981
+ break;
1680716982
case OPT_COMMAND:
1680816983
if (i >= (argc - 2)) {
1680916984
Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
1681016985
return JIM_ERR;
1681116986
}
@@ -16915,20 +17090,20 @@
1691517090
static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1691617091
{
1691717092
if (argc >= 2) {
1691817093
int retcode;
1691917094
Jim_CallFrame *savedCallFrame, *targetCallFrame;
16920
- Jim_Obj *objPtr;
17095
+ int savedTailcall;
1692117096
const char *str;
1692217097
1692317098
1692417099
savedCallFrame = interp->framePtr;
1692517100
1692617101
1692717102
str = Jim_String(argv[1]);
1692817103
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16929
- targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
17104
+ targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1693017105
argc--;
1693117106
argv++;
1693217107
}
1693317108
else {
1693417109
targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16935,25 +17110,25 @@
1693517110
}
1693617111
if (targetCallFrame == NULL) {
1693717112
return JIM_ERR;
1693817113
}
1693917114
if (argc < 2) {
16940
- argv--;
16941
- Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
17115
+ Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
1694217116
return JIM_ERR;
1694317117
}
1694417118
1694517119
interp->framePtr = targetCallFrame;
17120
+
17121
+ savedTailcall = interp->framePtr->tailcall;
17122
+ interp->framePtr->tailcall = 0;
1694617123
if (argc == 2) {
1694717124
retcode = Jim_EvalObj(interp, argv[1]);
1694817125
}
1694917126
else {
16950
- objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16951
- Jim_IncrRefCount(objPtr);
16952
- retcode = Jim_EvalObj(interp, objPtr);
16953
- Jim_DecrRefCount(interp, objPtr);
17127
+ retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1695417128
}
17129
+ interp->framePtr->tailcall = savedTailcall;
1695517130
interp->framePtr = savedCallFrame;
1695617131
return retcode;
1695717132
}
1695817133
else {
1695917134
Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17064,12 +17239,39 @@
1706417239
}
1706517240
1706617241
1706717242
static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1706817243
{
17069
- Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17070
- 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;
1707117273
}
1707217274
1707317275
static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1707417276
{
1707517277
Jim_Obj *cmdList;
@@ -17354,11 +17556,11 @@
1735417556
for (i = 0; i < numMaps; i += 2) {
1735517557
Jim_Obj *objPtr;
1735617558
const char *k;
1735717559
int kl;
1735817560
17359
- Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17561
+ objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
1736017562
k = Jim_String(objPtr);
1736117563
kl = Jim_Utf8Length(interp, objPtr);
1736217564
1736317565
if (strLen >= kl && kl) {
1736417566
int rc;
@@ -17366,12 +17568,11 @@
1736617568
if (rc == 0) {
1736717569
if (noMatchStart) {
1736817570
Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
1736917571
noMatchStart = NULL;
1737017572
}
17371
- Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17372
- Jim_AppendObj(interp, resultObjPtr, objPtr);
17573
+ Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
1737317574
str += utf8_index(str, kl);
1737417575
strLen -= kl;
1737517576
break;
1737617577
}
1737717578
}
@@ -17851,15 +18052,17 @@
1785118052
1785218053
exitCode = JIM_SIGNAL;
1785318054
}
1785418055
else {
1785518056
exitCode = Jim_EvalObj(interp, argv[0]);
18057
+
18058
+ interp->errorFlag = 0;
1785618059
}
1785718060
interp->signal_level -= sig;
1785818061
1785918062
17860
- 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)) {
1786118064
1786218065
return exitCode;
1786318066
}
1786418067
1786518068
if (sig && exitCode == JIM_SIGNAL) {
@@ -18009,11 +18212,11 @@
1800918212
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1801018213
1801118214
JimInitHashTableIterator(&interp->references, &htiter);
1801218215
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1801318216
char buf[JIM_REFERENCE_SPACE + 1];
18014
- Jim_Reference *refPtr = he->u.val;
18217
+ Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
1801518218
const unsigned long *refId = he->key;
1801618219
1801718220
JimFormatReference(buf, refPtr, *refId);
1801818221
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
1801918222
}
@@ -18043,11 +18246,11 @@
1804318246
1804418247
static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
1804518248
{
1804618249
Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
1804718250
if (type & JIM_DICTMATCH_VALUES) {
18048
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18251
+ Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
1804918252
}
1805018253
}
1805118254
1805218255
static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1805318256
JimDictMatchCallbackType *callback, int type)
@@ -18092,21 +18295,65 @@
1809218295
return -1;
1809318296
}
1809418297
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
1809518298
}
1809618299
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
+
1809718340
1809818341
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1809918342
{
1810018343
Jim_Obj *objPtr;
1810118344
int option;
1810218345
static const char * const options[] = {
18103
- "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
1810418349
};
1810518350
enum
1810618351
{
18107
- 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,
1810818355
};
1810918356
1811018357
if (argc < 2) {
1811118358
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
1811218359
return JIM_ERR;
@@ -18117,11 +18364,11 @@
1811718364
}
1811818365
1811918366
switch (option) {
1812018367
case OPT_GET:
1812118368
if (argc < 3) {
18122
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18369
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
1812318370
return JIM_ERR;
1812418371
}
1812518372
if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
1812618373
JIM_ERRMSG) != JIM_OK) {
1812718374
return JIM_ERR;
@@ -18134,82 +18381,87 @@
1813418381
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
1813518382
return JIM_ERR;
1813618383
}
1813718384
return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
1813818385
18139
- case OPT_EXIST:
18140
- if (argc < 3) {
18141
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18386
+ case OPT_EXISTS:
18387
+ if (argc < 4) {
18388
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
1814218389
return JIM_ERR;
1814318390
}
18144
- Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18145
- &objPtr, JIM_ERRMSG) == JIM_OK);
18146
- 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
+ }
1814718399
1814818400
case OPT_UNSET:
1814918401
if (argc < 4) {
1815018402
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
1815118403
return JIM_ERR;
1815218404
}
18153
- 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;
1815418409
1815518410
case OPT_KEYS:
1815618411
if (argc != 3 && argc != 4) {
18157
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18412
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
1815818413
return JIM_ERR;
1815918414
}
1816018415
return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
1816118416
18162
- case OPT_SIZE: {
18163
- int size;
18164
-
18417
+ case OPT_SIZE:
1816518418
if (argc != 3) {
18166
- Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18419
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1816718420
return JIM_ERR;
1816818421
}
18169
-
18170
- size = Jim_DictSize(interp, argv[2]);
18171
- if (size < 0) {
18422
+ else if (Jim_DictSize(interp, argv[2]) < 0) {
1817218423
return JIM_ERR;
1817318424
}
18174
- Jim_SetResultInt(interp, size);
18425
+ Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
1817518426
return JIM_OK;
18176
- }
1817718427
1817818428
case OPT_MERGE:
1817918429
if (argc == 2) {
1818018430
return JIM_OK;
1818118431
}
18182
- else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18183
- return JIM_ERR;
18184
- }
18185
- else {
18186
- return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18187
- }
18188
-
18189
- case OPT_WITH:
18190
- if (argc < 4) {
18191
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18192
- return JIM_ERR;
18193
- }
18194
- else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18195
- return JIM_ERR;
18196
- }
18197
- else {
18198
- return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18199
- }
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;
1820018444
1820118445
case OPT_CREATE:
1820218446
if (argc % 2) {
1820318447
Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
1820418448
return JIM_ERR;
1820518449
}
1820618450
objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
1820718451
Jim_SetResult(interp, objPtr);
1820818452
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]);
1820918460
}
18210
- return JIM_ERR;
18461
+
18462
+ return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
1821118463
}
1821218464
1821318465
1821418466
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1821518467
{
@@ -18267,11 +18519,11 @@
1826718519
};
1826818520
enum
1826918521
{ INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
1827018522
INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
1827118523
INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18272
- INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18524
+ INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
1827318525
};
1827418526
1827518527
#ifdef jim_ext_namespace
1827618528
int nons = 0;
1827718529
@@ -19047,11 +19299,11 @@
1904719299
}
1904819300
}
1904919301
1905019302
static const struct {
1905119303
const char *name;
19052
- Jim_CmdProc cmdProc;
19304
+ Jim_CmdProc *cmdProc;
1905319305
} Jim_CoreCommandsTable[] = {
1905419306
{"alias", Jim_AliasCoreCommand},
1905519307
{"set", Jim_SetCoreCommand},
1905619308
{"unset", Jim_UnsetCoreCommand},
1905719309
{"puts", Jim_PutsCoreCommand},
@@ -19279,10 +19531,12 @@
1927919531
}
1928019532
1928119533
len += extra;
1928219534
buf = Jim_Alloc(len + 1);
1928319535
len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19536
+
19537
+ va_end(args);
1928419538
1928519539
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
1928619540
}
1928719541
1928819542
@@ -19530,23 +19784,22 @@
1953019784
1953119785
#include <ctype.h>
1953219786
#include <string.h>
1953319787
1953419788
19535
-#define JIM_UTF_MAX 3
1953619789
#define JIM_INTEGER_SPACE 24
1953719790
#define MAX_FLOAT_WIDTH 320
1953819791
1953919792
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
1954019793
{
1954119794
const char *span, *format, *formatEnd, *msg;
1954219795
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
1954319796
static const char * const mixedXPG =
19544
- "cannot mix \"%\" and \"%n$\" conversion specifiers";
19797
+ "cannot mix \"%\" and \"%n$\" conversion specifiers";
1954519798
static const char * const badIndex[2] = {
19546
- "not enough arguments for all format specifiers",
19547
- "\"%n$\" argument index out of range"
19799
+ "not enough arguments for all format specifiers",
19800
+ "\"%n$\" argument index out of range"
1954819801
};
1954919802
int formatLen;
1955019803
Jim_Obj *resultPtr;
1955119804
1955219805
char *num_buffer = NULL;
@@ -19555,319 +19808,349 @@
1955519808
span = format = Jim_GetString(fmtObjPtr, &formatLen);
1955619809
formatEnd = format + formatLen;
1955719810
resultPtr = Jim_NewEmptyStringObj(interp);
1955819811
1955919812
while (format != formatEnd) {
19560
- char *end;
19561
- int gotMinus, sawFlag;
19562
- int gotPrecision, useShort;
19563
- long width, precision;
19564
- int newXpg;
19565
- int ch;
19566
- int step;
19567
- int doubleType;
19568
- char pad = ' ';
19569
- char spec[2*JIM_INTEGER_SPACE + 12];
19570
- char *p;
19571
-
19572
- int formatted_chars;
19573
- int formatted_bytes;
19574
- const char *formatted_buf;
19575
-
19576
- step = utf8_tounicode(format, &ch);
19577
- format += step;
19578
- if (ch != '%') {
19579
- numBytes += step;
19580
- continue;
19581
- }
19582
- if (numBytes) {
19583
- Jim_AppendString(interp, resultPtr, span, numBytes);
19584
- numBytes = 0;
19585
- }
19586
-
19587
-
19588
- step = utf8_tounicode(format, &ch);
19589
- if (ch == '%') {
19590
- span = format;
19591
- numBytes = step;
19592
- format += step;
19593
- continue;
19594
- }
19595
-
19596
-
19597
- newXpg = 0;
19598
- if (isdigit(ch)) {
19599
- int position = strtoul(format, &end, 10);
19600
- if (*end == '$') {
19601
- newXpg = 1;
19602
- objIndex = position - 1;
19603
- format = end + 1;
19604
- step = utf8_tounicode(format, &ch);
19605
- }
19606
- }
19607
- if (newXpg) {
19608
- if (gotSequential) {
19609
- msg = mixedXPG;
19610
- goto errorMsg;
19611
- }
19612
- gotXpg = 1;
19613
- } else {
19614
- if (gotXpg) {
19615
- msg = mixedXPG;
19616
- goto errorMsg;
19617
- }
19618
- gotSequential = 1;
19619
- }
19620
- if ((objIndex < 0) || (objIndex >= objc)) {
19621
- msg = badIndex[gotXpg];
19622
- goto errorMsg;
19623
- }
19624
-
19625
- p = spec;
19626
- *p++ = '%';
19627
-
19628
- gotMinus = 0;
19629
- sawFlag = 1;
19630
- do {
19631
- switch (ch) {
19632
- case '-':
19633
- gotMinus = 1;
19634
- break;
19635
- case '0':
19636
- pad = ch;
19637
- break;
19638
- case ' ':
19639
- case '+':
19640
- case '#':
19641
- break;
19642
- default:
19643
- sawFlag = 0;
19644
- continue;
19645
- }
19646
- *p++ = ch;
19647
- format += step;
19648
- step = utf8_tounicode(format, &ch);
19649
- } while (sawFlag);
19650
-
19651
-
19652
- width = 0;
19653
- if (isdigit(ch)) {
19654
- width = strtoul(format, &end, 10);
19655
- format = end;
19656
- step = utf8_tounicode(format, &ch);
19657
- } else if (ch == '*') {
19658
- if (objIndex >= objc - 1) {
19659
- msg = badIndex[gotXpg];
19660
- goto errorMsg;
19661
- }
19662
- if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19663
- goto error;
19664
- }
19665
- if (width < 0) {
19666
- width = -width;
19667
- if (!gotMinus) {
19668
- *p++ = '-';
19669
- gotMinus = 1;
19670
- }
19671
- }
19672
- objIndex++;
19673
- format += step;
19674
- step = utf8_tounicode(format, &ch);
19675
- }
19676
-
19677
-
19678
- gotPrecision = precision = 0;
19679
- if (ch == '.') {
19680
- gotPrecision = 1;
19681
- format += step;
19682
- step = utf8_tounicode(format, &ch);
19683
- }
19684
- if (isdigit(ch)) {
19685
- precision = strtoul(format, &end, 10);
19686
- format = end;
19687
- step = utf8_tounicode(format, &ch);
19688
- } else if (ch == '*') {
19689
- if (objIndex >= objc - 1) {
19690
- msg = badIndex[gotXpg];
19691
- goto errorMsg;
19692
- }
19693
- if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19694
- goto error;
19695
- }
19696
-
19697
-
19698
- if (precision < 0) {
19699
- precision = 0;
19700
- }
19701
- objIndex++;
19702
- format += step;
19703
- step = utf8_tounicode(format, &ch);
19704
- }
19705
-
19706
-
19707
- useShort = 0;
19708
- if (ch == 'h') {
19709
- useShort = 1;
19710
- format += step;
19711
- step = utf8_tounicode(format, &ch);
19712
- } else if (ch == 'l') {
19713
-
19714
- format += step;
19715
- step = utf8_tounicode(format, &ch);
19716
- if (ch == 'l') {
19717
- format += step;
19718
- step = utf8_tounicode(format, &ch);
19719
- }
19720
- }
19721
-
19722
- format += step;
19723
- span = format;
19724
-
19725
-
19726
- if (ch == 'i') {
19727
- ch = 'd';
19728
- }
19729
-
19730
- doubleType = 0;
19731
-
19732
- switch (ch) {
19733
- case '\0':
19734
- msg = "format string ended in middle of field specifier";
19735
- goto errorMsg;
19736
- case 's': {
19737
- formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19738
- formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19739
- if (gotPrecision && (precision < formatted_chars)) {
19740
-
19741
- formatted_chars = precision;
19742
- formatted_bytes = utf8_index(formatted_buf, precision);
19743
- }
19744
- break;
19745
- }
19746
- case 'c': {
19747
- jim_wide code;
19748
-
19749
- if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19750
- goto error;
19751
- }
19752
-
19753
- formatted_bytes = utf8_fromunicode(spec, code);
19754
- formatted_buf = spec;
19755
- formatted_chars = 1;
19756
- break;
19757
- }
19758
-
19759
- case 'e':
19760
- case 'E':
19761
- case 'f':
19762
- case 'g':
19763
- case 'G':
19764
- doubleType = 1;
19765
-
19766
- case 'd':
19767
- case 'u':
19768
- case 'o':
19769
- case 'x':
19770
- case 'X': {
19771
- jim_wide w;
19772
- double d;
19773
- int length;
19774
-
19775
-
19776
- if (width) {
19777
- p += sprintf(p, "%ld", width);
19778
- }
19779
- if (gotPrecision) {
19780
- p += sprintf(p, ".%ld", precision);
19781
- }
19782
-
19783
-
19784
- if (doubleType) {
19785
- if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19786
- goto error;
19787
- }
19788
- length = MAX_FLOAT_WIDTH;
19789
- }
19790
- else {
19791
- if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19792
- goto error;
19793
- }
19794
- length = JIM_INTEGER_SPACE;
19795
- if (useShort) {
19796
- *p++ = 'h';
19797
- if (ch == 'd') {
19798
- w = (short)w;
19799
- }
19800
- else {
19801
- w = (unsigned short)w;
19802
- }
19803
- }
19804
- else {
19805
- *p++ = 'l';
19806
-#ifdef HAVE_LONG_LONG
19807
- if (sizeof(long long) == sizeof(jim_wide)) {
19808
- *p++ = 'l';
19809
- }
19810
-#endif
19811
- }
19812
- }
19813
-
19814
- *p++ = (char) ch;
19815
- *p = '\0';
19816
-
19817
-
19818
- if (width > length) {
19819
- length = width;
19820
- }
19821
- if (gotPrecision) {
19822
- length += precision;
19823
- }
19824
-
19825
-
19826
- if (num_buffer_size < length + 1) {
19827
- num_buffer_size = length + 1;
19828
- num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19829
- }
19830
-
19831
- if (doubleType) {
19832
- snprintf(num_buffer, length + 1, spec, d);
19833
- }
19834
- else {
19835
- formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19836
- }
19837
- formatted_chars = formatted_bytes = strlen(num_buffer);
19838
- formatted_buf = num_buffer;
19839
- break;
19840
- }
19841
-
19842
- default: {
19843
-
19844
- spec[0] = ch;
19845
- spec[1] = '\0';
19846
- Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19847
- goto error;
19848
- }
19849
- }
19850
-
19851
- if (!gotMinus) {
19852
- while (formatted_chars < width) {
19853
- Jim_AppendString(interp, resultPtr, &pad, 1);
19854
- formatted_chars++;
19855
- }
19856
- }
19857
-
19858
- Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19859
-
19860
- while (formatted_chars < width) {
19861
- Jim_AppendString(interp, resultPtr, &pad, 1);
19862
- formatted_chars++;
19863
- }
19864
-
19865
- objIndex += gotSequential;
19866
- }
19867
- if (numBytes) {
19868
- 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);
1986920152
}
1987020153
1987120154
Jim_Free(num_buffer);
1987220155
return resultPtr;
1987320156
@@ -19876,21 +20159,22 @@
1987620159
error:
1987720160
Jim_FreeNewObj(interp, resultPtr);
1987820161
Jim_Free(num_buffer);
1987920162
return NULL;
1988020163
}
20164
+
20165
+
20166
+#if defined(JIM_REGEXP)
1988120167
#include <stdio.h>
1988220168
#include <ctype.h>
1988320169
#include <stdlib.h>
1988420170
#include <string.h>
1988520171
19886
-
19887
-#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19888
-
1988920172
1989020173
1989120174
#define REG_MAX_PAREN 100
20175
+
1989220176
1989320177
1989420178
#define END 0
1989520179
#define BOL 1
1989620180
#define EOL 2
@@ -19899,23 +20183,27 @@
1989920183
#define ANYBUT 5
1990020184
#define BRANCH 6
1990120185
#define BACK 7
1990220186
#define EXACTLY 8
1990320187
#define NOTHING 9
19904
-#define REP 10
20188
+#define REP 10
1990520189
#define REPMIN 11
1990620190
#define REPX 12
1990720191
#define REPXMIN 13
1990820192
1990920193
#define WORDA 15
1991020194
#define WORDZ 16
19911
-#define OPENNC 19
19912
-#define OPEN 20
20195
+
20196
+#define OPENNC 1000
20197
+#define OPEN 1001
1991320198
19914
-#define CLOSE (OPEN+REG_MAX_PAREN+1)
20199
+
20200
+
20201
+
20202
+#define CLOSENC 2000
20203
+#define CLOSE 2001
1991520204
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
19916
-#define CLOSENC (CLOSE-1)
1991720205
1991820206
#define REG_MAGIC 0xFADED00D
1991920207
1992020208
1992120209
#define OP(preg, p) (preg->program[p])
@@ -19925,15 +20213,15 @@
1992520213
1992620214
1992720215
1992820216
#define FAIL(R,M) { (R)->err = (M); return (M); }
1992920217
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19930
-#define META "^$.[()|?{+*"
20218
+#define META "^$.[()|?{+*"
1993120219
19932
-#define HASWIDTH 01
19933
-#define SIMPLE 02
19934
-#define SPSTART 04
20220
+#define HASWIDTH 1
20221
+#define SIMPLE 2
20222
+#define SPSTART 4
1993520223
#define WORST 0
1993620224
1993720225
#define MAX_REP_COUNT 1000000
1993820226
1993920227
static int reg(regex_t *preg, int paren , int *flagp );
@@ -19942,13 +20230,13 @@
1994220230
static int regatom(regex_t *preg, int *flagp );
1994320231
static int regnode(regex_t *preg, int op );
1994420232
static int regnext(regex_t *preg, int p );
1994520233
static void regc(regex_t *preg, int b );
1994620234
static int reginsert(regex_t *preg, int op, int size, int opnd );
19947
-static void regtail_(regex_t *preg, int p, int val, int line );
20235
+static void regtail(regex_t *preg, int p, int val);
1994820236
static void regoptail(regex_t *preg, int p, int val );
19949
-#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
20237
+static int regopsize(regex_t *preg, int p );
1995020238
1995120239
static int reg_range_find(const int *string, int c);
1995220240
static const char *str_find(const char *string, int c, int nocase);
1995320241
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
1995420242
@@ -19985,13 +20273,10 @@
1998520273
FAIL(preg, REG_ERR_NULL_ARGUMENT);
1998620274
1998720275
1998820276
preg->cflags = cflags;
1998920277
preg->regparse = exp;
19990
-
19991
- preg->program = NULL;
19992
- preg->proglen = 0;
1999320278
1999420279
1999520280
preg->proglen = (strlen(exp) + 1) * 5;
1999620281
preg->program = malloc(preg->proglen * sizeof(int));
1999720282
if (preg->program == NULL)
@@ -20152,11 +20437,10 @@
2015220437
{
2015320438
int ret;
2015420439
char op;
2015520440
int next;
2015620441
int flags;
20157
- int chain = 0;
2015820442
int min;
2015920443
int max;
2016020444
2016120445
ret = regatom(preg, &flags);
2016220446
if (ret == 0)
@@ -20235,11 +20519,11 @@
2023520519
if (ISMULT(*preg->regparse)) {
2023620520
preg->err = REG_ERR_NESTED_COUNT;
2023720521
return 0;
2023820522
}
2023920523
20240
- return chain ? chain : ret;
20524
+ return ret;
2024120525
}
2024220526
2024320527
static void reg_addrange(regex_t *preg, int lower, int upper)
2024420528
{
2024520529
if (lower > upper) {
@@ -20329,10 +20613,11 @@
2032920613
break;
2033020614
case 'U':
2033120615
if ((n = parse_hex(s, 8, ch)) > 0) {
2033220616
s += n;
2033320617
}
20618
+ break;
2033420619
case 'x':
2033520620
if ((n = parse_hex(s, 2, ch)) > 0) {
2033620621
s += n;
2033720622
}
2033820623
break;
@@ -20577,10 +20862,11 @@
2057720862
2057820863
static int regnode(regex_t *preg, int op)
2057920864
{
2058020865
reg_grow(preg, 2);
2058120866
20867
+
2058220868
preg->program[preg->p++] = op;
2058320869
preg->program[preg->p++] = 0;
2058420870
2058520871
2058620872
return preg->p - 2;
@@ -20606,11 +20892,11 @@
2060620892
preg->p += size;
2060720893
2060820894
return opnd + size;
2060920895
}
2061020896
20611
-static void regtail_(regex_t *preg, int p, int val, int line )
20897
+static void regtail(regex_t *preg, int p, int val)
2061220898
{
2061320899
int scan;
2061420900
int temp;
2061520901
int offset;
2061620902
@@ -20669,36 +20955,16 @@
2066920955
preg->pmatch = pmatch;
2067020956
preg->nmatch = nmatch;
2067120957
preg->start = string;
2067220958
2067320959
20674
- for (scan = OPERAND(1); scan != 0; ) {
20675
- switch (OP(preg, scan)) {
20676
- case REP:
20677
- case REPMIN:
20678
- case REPX:
20679
- case REPXMIN:
20680
- preg->program[scan + 4] = 0;
20681
- scan += 5;
20682
- break;
20683
-
20684
- case ANYOF:
20685
- case ANYBUT:
20686
- case EXACTLY:
20687
- scan += 2;
20688
- while (preg->program[scan++]) {
20689
- }
20690
- break;
20691
-
20692
- case END:
20693
- scan = 0;
20694
- break;
20695
-
20696
- default:
20697
- scan += 2;
20698
- break;
20699
- }
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;
2070020966
}
2070120967
2070220968
2070320969
if (preg->regmust != 0) {
2070420970
s = string;
@@ -20950,10 +21216,11 @@
2095021216
2095121217
static int regmatch(regex_t *preg, int prog)
2095221218
{
2095321219
int scan;
2095421220
int next;
21221
+ const char *save;
2095521222
2095621223
scan = prog;
2095721224
2095821225
#ifdef DEBUG
2095921226
if (scan != 0 && regnarrate)
@@ -21038,27 +21305,24 @@
2103821305
break;
2103921306
case NOTHING:
2104021307
break;
2104121308
case BACK:
2104221309
break;
21043
- case BRANCH: {
21044
- const char *save;
21045
-
21046
- if (OP(preg, next) != BRANCH)
21047
- next = OPERAND(scan);
21048
- else {
21049
- do {
21050
- save = preg->reginput;
21051
- if (regmatch(preg, OPERAND(scan))) {
21052
- return(1);
21053
- }
21054
- preg->reginput = save;
21055
- scan = regnext(preg, scan);
21056
- } while (scan != 0 && OP(preg, scan) == BRANCH);
21057
- return(0);
21058
-
21059
- }
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
+
2106021324
}
2106121325
break;
2106221326
case REP:
2106321327
case REPMIN:
2106421328
return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21066,43 +21330,35 @@
2106621330
case REPX:
2106721331
case REPXMIN:
2106821332
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
2106921333
2107021334
case END:
21071
- return(1);
21072
- break;
21335
+ return 1;
2107321336
2107421337
case OPENNC:
2107521338
case CLOSENC:
21076
- if (regmatch(preg, next)) {
21077
- return 1;
21078
- }
21079
- return 0;
21339
+ return regmatch(preg, next);
2108021340
2108121341
default:
2108221342
if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21083
- const char *save;
21084
-
2108521343
save = preg->reginput;
21086
-
2108721344
if (regmatch(preg, next)) {
21088
- int no;
2108921345
if (OP(preg, scan) < CLOSE) {
21090
- no = OP(preg, scan) - OPEN;
21346
+ int no = OP(preg, scan) - OPEN;
2109121347
if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
2109221348
preg->pmatch[no].rm_so = save - preg->start;
2109321349
}
2109421350
}
2109521351
else {
21096
- no = OP(preg, scan) - CLOSE;
21352
+ int no = OP(preg, scan) - CLOSE;
2109721353
if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
2109821354
preg->pmatch[no].rm_eo = save - preg->start;
2109921355
}
2110021356
}
2110121357
return(1);
21102
- } else
21103
- return(0);
21358
+ }
21359
+ return(0);
2110421360
}
2110521361
return REG_ERR_INTERNAL;
2110621362
}
2110721363
2110821364
scan = next;
@@ -21181,10 +21437,32 @@
2118121437
if (OP(preg, p) == BACK)
2118221438
return(p-offset);
2118321439
else
2118421440
return(p+offset);
2118521441
}
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
+}
2118621464
2118721465
2118821466
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
2118921467
{
2119021468
static const char *error_strings[] = {
@@ -21359,19 +21637,24 @@
2135921637
char *Jim_HistoryGetline(const char *prompt)
2136021638
{
2136121639
#ifdef USE_LINENOISE
2136221640
return linenoise(prompt);
2136321641
#else
21642
+ int len;
2136421643
char *line = malloc(MAX_LINE_LEN);
2136521644
2136621645
fputs(prompt, stdout);
2136721646
fflush(stdout);
2136821647
2136921648
if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
2137021649
free(line);
2137121650
return NULL;
2137221651
}
21652
+ len = strlen(line);
21653
+ if (len && line[len - 1] == '\n') {
21654
+ line[len - 1] = '\0';
21655
+ }
2137321656
return line;
2137421657
#endif
2137521658
}
2137621659
2137721660
void Jim_HistoryLoad(const char *filename)
@@ -21422,11 +21705,11 @@
2142221705
snprintf(history_file, history_len, "%s/.jim_history", home);
2142321706
Jim_HistoryLoad(history_file);
2142421707
}
2142521708
#endif
2142621709
21427
- printf("Welcome to Jim version %d.%d" JIM_NL,
21710
+ printf("Welcome to Jim version %d.%d\n",
2142821711
JIM_VERSION / 100, JIM_VERSION % 100);
2142921712
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
2143021713
2143121714
while (1) {
2143221715
Jim_Obj *scriptObjPtr;
@@ -21534,10 +21817,16 @@
2153421817
}
2153521818
2153621819
Jim_SetVariableStr(interp, "argv", listObj);
2153721820
Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
2153821821
}
21822
+
21823
+static void JimPrintErrorMessage(Jim_Interp *interp)
21824
+{
21825
+ Jim_MakeErrorMessage(interp);
21826
+ fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21827
+}
2153921828
2154021829
int main(int argc, char *const argv[])
2154121830
{
2154221831
int retcode;
2154321832
Jim_Interp *interp;
@@ -21551,22 +21840,20 @@
2155121840
interp = Jim_CreateInterp();
2155221841
Jim_RegisterCoreCommands(interp);
2155321842
2155421843
2155521844
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21556
- Jim_MakeErrorMessage(interp);
21557
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21845
+ JimPrintErrorMessage(interp);
2155821846
}
2155921847
2156021848
Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
2156121849
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
2156221850
retcode = Jim_initjimshInit(interp);
2156321851
2156421852
if (argc == 1) {
2156521853
if (retcode == JIM_ERR) {
21566
- Jim_MakeErrorMessage(interp);
21567
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21854
+ JimPrintErrorMessage(interp);
2156821855
}
2156921856
if (retcode != JIM_EXIT) {
2157021857
JimSetArgv(interp, 0, NULL);
2157121858
retcode = Jim_InteractivePrompt(interp);
2157221859
}
@@ -21583,12 +21870,11 @@
2158321870
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
2158421871
JimSetArgv(interp, argc - 2, argv + 2);
2158521872
retcode = Jim_EvalFile(interp, argv[1]);
2158621873
}
2158721874
if (retcode == JIM_ERR) {
21588
- Jim_MakeErrorMessage(interp);
21589
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21875
+ JimPrintErrorMessage(interp);
2159021876
}
2159121877
}
2159221878
if (retcode == JIM_EXIT) {
2159321879
retcode = Jim_GetExitCode(interp);
2159421880
}
2159521881
--- 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
@@ -47,10 +47,14 @@
47 #define JIM_VERSION 75
48 #ifndef JIM_WIN32COMPAT_H
49 #define JIM_WIN32COMPAT_H
50
51
 
 
 
 
52
53
54 #if defined(_WIN32) || defined(WIN32)
55
56 #define HAVE_DLOPEN
@@ -106,17 +110,31 @@
106 } DIR;
107
108 DIR *opendir(const char *name);
109 int closedir(DIR *dir);
110 struct dirent *readdir(DIR *dir);
111 #endif
 
 
 
 
 
112
113 #endif
 
 
 
 
114
115 #endif
116 #ifndef UTF8_UTIL_H
117 #define UTF8_UTIL_H
 
 
 
 
 
118
119
120 #define MAX_UTF8_LEN 4
121
122 int utf8_fromunicode(char *p, unsigned uc);
@@ -125,10 +143,11 @@
125 #include <ctype.h>
126
127
128 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
129 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
 
130 #define utf8_upper(C) toupper(C)
131 #define utf8_title(C) toupper(C)
132 #define utf8_lower(C) tolower(C)
133 #define utf8_index(C, I) (I)
134 #define utf8_charlen(C) 1
@@ -135,10 +154,14 @@
135 #define utf8_prev_len(S, L) 1
136
137 #else
138
139 #endif
 
 
 
 
140
141 #endif
142
143 #ifndef __JIM__H
144 #define __JIM__H
@@ -199,44 +222,34 @@
199 #define JIM_EVAL 7
200
201 #define JIM_MAX_CALLFRAME_DEPTH 1000
202 #define JIM_MAX_EVAL_DEPTH 2000
203
204 #define JIM_NONE 0
205 #define JIM_ERRMSG 1
206
207 #define JIM_UNSHARED 4
208 #define JIM_MUSTEXIST 8
209
210
211 #define JIM_GLOBAL_ONLY 0x100
212
213
214 #define JIM_SUBST_NOVAR 1
215 #define JIM_SUBST_NOCMD 2
216 #define JIM_SUBST_NOESC 4
217 #define JIM_SUBST_FLAG 128
218
219
220 #define JIM_NOTUSED(V) ((void) V)
221
222
223 #define JIM_ENUM_ABBREV 2
224
225
226 #define JIM_CASESENS 0
227 #define JIM_NOCASE 1
228
229
230 #define JIM_PATH_LEN 1024
231
232
233 #ifdef JIM_CRLF
234 #define JIM_NL "\r\n"
235 #else
236 #define JIM_NL "\n"
237 #endif
238
239 #define JIM_LIBPATH "auto_path"
240 #define JIM_INTERACTIVE "tcl_interactive"
241
242
@@ -266,21 +279,22 @@
266 } Jim_HashTableType;
267
268 typedef struct Jim_HashTable {
269 Jim_HashEntry **table;
270 const Jim_HashTableType *type;
 
271 unsigned int size;
272 unsigned int sizemask;
273 unsigned int used;
274 unsigned int collisions;
275 void *privdata;
276 } Jim_HashTable;
277
278 typedef struct Jim_HashTableIterator {
279 Jim_HashTable *ht;
280 int index;
281 Jim_HashEntry *entry, *nextEntry;
 
282 } Jim_HashTableIterator;
283
284
285 #define JIM_HT_INITIAL_SIZE 16
286
@@ -289,35 +303,35 @@
289 if ((ht)->type->valDestructor) \
290 (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
291
292 #define Jim_SetHashVal(ht, entry, _val_) do { \
293 if ((ht)->type->valDup) \
294 entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
295 else \
296 entry->u.val = (_val_); \
297 } while(0)
298
299 #define Jim_FreeEntryKey(ht, entry) \
300 if ((ht)->type->keyDestructor) \
301 (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
302
303 #define Jim_SetHashKey(ht, entry, _key_) do { \
304 if ((ht)->type->keyDup) \
305 entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
306 else \
307 entry->key = (void *)(_key_); \
308 } while(0)
309
310 #define Jim_CompareHashKeys(ht, key1, key2) \
311 (((ht)->type->keyCompare) ? \
312 (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
313 (key1) == (key2))
314
315 #define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
316
317 #define Jim_GetHashEntryKey(he) ((he)->key)
318 #define Jim_GetHashEntryVal(he) ((he)->val)
319 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
320 #define Jim_GetHashTableSize(ht) ((ht)->size)
321 #define Jim_GetHashTableUsed(ht) ((ht)->used)
322
323
@@ -341,19 +355,19 @@
341 void *ptr1;
342 void *ptr2;
343 } twoPtrValue;
344
345 struct {
346 unsigned long callFrameId;
347 struct Jim_Var *varPtr;
 
348 int global;
349 } varValue;
350
351 struct {
352 unsigned long procEpoch;
353 struct Jim_Obj *nsObj;
354 struct Jim_Cmd *cmdPtr;
 
355 } cmdValue;
356
357 struct {
358 struct Jim_Obj **ele;
359 int len;
@@ -379,12 +393,12 @@
379 struct Jim_Obj *varNameObjPtr;
380 struct Jim_Obj *indexObjPtr;
381 } dictSubstValue;
382
383 struct {
384 unsigned flags;
385 void *compre;
 
386 } regexpValue;
387 struct {
388 int line;
389 int argc;
390 } scriptLineValue;
@@ -453,21 +467,24 @@
453 struct Jim_CallFrame *next;
454 Jim_Obj *nsObj;
455 Jim_Obj *fileNameObj;
456 int line;
457 Jim_Stack *localCommands;
 
 
 
458 } Jim_CallFrame;
459
460 typedef struct Jim_Var {
461 Jim_Obj *objPtr;
462 struct Jim_CallFrame *linkFramePtr;
463 } Jim_Var;
464
465
466 typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
467 Jim_Obj *const *argv);
468 typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
469
470
471
472 typedef struct Jim_Cmd {
473 int inUse;
@@ -474,12 +491,12 @@
474 int isproc;
475 struct Jim_Cmd *prevCmd;
476 union {
477 struct {
478
479 Jim_CmdProc cmdProc;
480 Jim_DelCmdProc delProc;
481 void *privData;
482 } native;
483 struct {
484
485 Jim_Obj *argListObjPtr;
@@ -589,15 +606,11 @@
589 Jim_Obj *finalizerCmdNamePtr;
590 char tag[JIM_REFERENCE_TAGLEN+1];
591 } Jim_Reference;
592
593
594
595 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
596
597
598
599 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
600
601 #define JIM_EXPORT
602
603
@@ -608,10 +621,11 @@
608 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
609
610
611 JIM_EXPORT char **Jim_GetEnviron(void);
612 JIM_EXPORT void Jim_SetEnviron(char **env);
 
613
614
615 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
616
617
@@ -739,13 +753,12 @@
739 JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
740 const char *name, const char *val);
741 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
742 Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
743 Jim_CallFrame *targetCallFrame);
744 JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
745 Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
746 JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
747 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
748 Jim_Obj *nameObjPtr, int flags);
749 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
750 Jim_Obj *nameObjPtr, int flags);
751 JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -804,10 +817,11 @@
804 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
805 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
806 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
807 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
808 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
 
809
810
811 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
812 int *intPtr);
813
@@ -869,19 +883,19 @@
869
870
871 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
872 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
873 JIM_EXPORT int Jim_IsBigEndian(void);
 
874 #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
875
876
877 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
878 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
879
880
881 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
882
883
884
885 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
886 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
887
@@ -903,16 +917,16 @@
903 #define JIM_MODFLAG_HIDDEN 0x0001
904 #define JIM_MODFLAG_FULLARGV 0x0002
905
906
907
908 typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
909
910 typedef struct {
911 const char *cmd;
912 const char *args;
913 tclmod_cmd_function *function;
914 short minargs;
915 short maxargs;
916 unsigned short flags;
917 } jim_subcmd_type;
918
@@ -929,22 +943,16 @@
929
930 #endif
931 #ifndef JIMREGEXP_H
932 #define JIMREGEXP_H
933
934 #ifndef _JIMAUTOCONF_H
935 #error Need jimautoconf.h
 
936 #endif
937
938 #if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
939
940 #include <regex.h>
941
942 #else
943
944 #include <stdlib.h>
945
946
947 typedef struct {
948 int rm_so;
949 int rm_eo;
950 } regmatch_t;
@@ -1013,10 +1021,12 @@
1013 int regcomp(regex_t *preg, const char *regex, int cflags);
1014 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
1015 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
1016 void regfree(regex_t *preg);
1017
 
 
1018 #endif
1019
1020 #endif
1021 int Jim_bootstrapInit(Jim_Interp *interp)
1022 {
@@ -1079,10 +1089,15 @@
1079 "\n"
1080 "package require readdir\n"
1081 "\n"
1082 "\n"
1083 "proc glob.globdir {dir pattern} {\n"
 
 
 
 
 
1084 " set result {}\n"
1085 " set files [readdir $dir]\n"
1086 " lappend files . ..\n"
1087 "\n"
1088 " foreach name $files {\n"
@@ -1261,10 +1276,12 @@
1261 {
1262 if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
1263 return JIM_ERR;
1264
1265 return Jim_EvalSource(interp, "stdlib.tcl", 1,
 
 
1266 "\n"
1267 "proc lambda {arglist args} {\n"
1268 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1269 "}\n"
1270 "\n"
@@ -1290,46 +1307,48 @@
1290 "}\n"
1291 "\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "proc stacktrace {} {\n"
1296 " set trace {}\n"
1297 " foreach level [range 1 [info level]] {\n"
1298 " lassign [info frame -$level] p f l\n"
1299 " lappend trace $p $f $l\n"
1300 " }\n"
1301 " return $trace\n"
1302 "}\n"
1303 "\n"
1304 "\n"
1305 "proc stackdump {stacktrace} {\n"
1306 " set result {}\n"
1307 " set count 0\n"
1308 " foreach {l f p} [lreverse $stacktrace] {\n"
1309 " if {$count} {\n"
1310 " append result \\n\n"
1311 " }\n"
1312 " incr count\n"
1313 " if {$p ne \"\"} {\n"
1314 " append result \"in procedure '$p' \"\n"
1315 " if {$f ne \"\"} {\n"
1316 " append result \"called \"\n"
1317 " }\n"
1318 " }\n"
1319 " if {$f ne \"\"} {\n"
1320 " append result \"at file \\\"$f\\\", line $l\"\n"
 
 
 
1321 " }\n"
1322 " }\n"
1323 " return $result\n"
1324 "}\n"
1325 "\n"
1326 "\n"
1327 "\n"
1328 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1329 " if {$stacktrace eq \"\"} {\n"
 
1330 " set stacktrace [info stacktrace]\n"
 
 
1331 " }\n"
1332 " lassign $stacktrace p f l\n"
1333 " if {$f ne \"\"} {\n"
1334 " set result \"Runtime Error: $f:$l: \"\n"
1335 " }\n"
@@ -1356,25 +1375,46 @@
1356 " }\n"
1357 " return \"\"\n"
1358 "}\n"
1359 "\n"
1360 "\n"
1361 "proc {dict with} {dictVar args script} {\n"
1362 " upvar $dictVar dict\n"
1363 " set keys {}\n"
1364 " foreach {n v} [dict get $dict {*}$args] {\n"
1365 " upvar $n var_$n\n"
1366 " set var_$n $v\n"
1367 " lappend keys $n\n"
1368 " }\n"
1369 " catch {uplevel 1 $script} msg opts\n"
1370 " if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1371 " foreach n $keys {\n"
1372 " if {[info exists var_$n]} {\n"
1373 " dict set dict {*}$args $n [set var_$n]\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1374 " } else {\n"
1375 " dict unset dict {*}$args $n\n"
1376 " }\n"
1377 " }\n"
1378 " }\n"
1379 " return {*}$opts $msg\n"
1380 "}\n"
@@ -1389,10 +1429,69 @@
1389 " dict set dict $k $v\n"
1390 " }\n"
1391 " }\n"
1392 " return $dict\n"
1393 "}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1394 );
1395 }
1396 int Jim_tclcompatInit(Jim_Interp *interp)
1397 {
1398 if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1403,12 +1502,14 @@
1403 "\n"
1404 "\n"
1405 "\n"
1406 "\n"
1407 "\n"
 
1408 "\n"
1409 "set env [env]\n"
 
1410 "\n"
1411 "if {[info commands stdout] ne \"\"} {\n"
1412 "\n"
1413 " foreach p {gets flush close eof seek tell} {\n"
1414 " proc $p {chan args} {p} {\n"
@@ -1455,51 +1556,10 @@
1455 " }\n"
1456 " }\n"
1457 " }\n"
1458 "}\n"
1459 "\n"
1460 "\n"
1461 "proc case {var args} {\n"
1462 "\n"
1463 " if {[lindex $args 0] eq \"in\"} {\n"
1464 " set args [lrange $args 1 end]\n"
1465 " }\n"
1466 "\n"
1467 "\n"
1468 " if {[llength $args] == 1} {\n"
1469 " set args [lindex $args 0]\n"
1470 " }\n"
1471 "\n"
1472 "\n"
1473 " if {[llength $args] % 2 != 0} {\n"
1474 " return -code error \"extra case pattern with no body\"\n"
1475 " }\n"
1476 "\n"
1477 "\n"
1478 " local proc case.checker {value pattern} {\n"
1479 " string match $pattern $value\n"
1480 " }\n"
1481 "\n"
1482 " foreach {value action} $args {\n"
1483 " if {$value eq \"default\"} {\n"
1484 " set do_action $action\n"
1485 " continue\n"
1486 " } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1487 " set do_action $action\n"
1488 " break\n"
1489 " }\n"
1490 " }\n"
1491 "\n"
1492 " if {[info exists do_action]} {\n"
1493 " set rc [catch [list uplevel 1 $do_action] result opts]\n"
1494 " if {$rc} {\n"
1495 " incr opts(-level)\n"
1496 " }\n"
1497 " return {*}$opts $result\n"
1498 " }\n"
1499 "}\n"
1500 "\n"
1501 "\n"
1502 "proc fileevent {args} {\n"
1503 " tailcall {*}$args\n"
1504 "}\n"
1505 "\n"
@@ -1529,13 +1589,25 @@
1529 " error \"bad option \\\"$force\\\": should be -force\"\n"
1530 " }\n"
1531 "\n"
1532 " set in [open $source]\n"
1533 "\n"
1534 " if {$force eq \"\" && [file exists $target]} {\n"
1535 " $in close\n"
1536 " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
 
 
 
 
 
 
 
 
 
 
 
 
1537 " }\n"
1538 " set out [open $target w]\n"
1539 " $in copyto $out\n"
1540 " $out close\n"
1541 " } on error {msg opts} {\n"
@@ -1580,18 +1652,18 @@
1580 " error $error\n"
1581 " }\n"
1582 "}\n"
1583 "\n"
1584 "\n"
1585 "local proc pid {{chan {}}} {\n"
1586 " if {$chan eq \"\"} {\n"
1587 " tailcall upcall pid\n"
1588 " }\n"
1589 " if {[catch {$chan tell}]} {\n"
1590 " return -code error \"can not find channel named \\\"$chan\\\"\"\n"
1591 " }\n"
1592 " if {[catch {$chan pid} pids]} {\n"
1593 " return \"\"\n"
1594 " }\n"
1595 " return $pids\n"
1596 "}\n"
1597 "\n"
@@ -1680,23 +1752,25 @@
1680 "}\n"
1681 );
1682 }
1683
1684
1685
1686 #include <stdio.h>
1687 #include <string.h>
1688 #include <errno.h>
1689 #include <fcntl.h>
 
 
 
 
1690
1691
1692 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1693 #include <sys/socket.h>
1694 #include <netinet/in.h>
1695 #include <arpa/inet.h>
1696 #include <netdb.h>
1697 #include <unistd.h>
1698 #ifdef HAVE_SYS_UN_H
1699 #include <sys/un.h>
1700 #endif
1701 #else
1702 #define JIM_ANSIC
@@ -1728,15 +1802,12 @@
1728 typedef struct AioFile
1729 {
1730 FILE *fp;
1731 Jim_Obj *filename;
1732 int type;
1733 int OpenFlags;
1734 int fd;
1735 #ifdef O_NDELAY
1736 int flags;
1737 #endif
1738 Jim_Obj *rEvent;
1739 Jim_Obj *wEvent;
1740 Jim_Obj *eEvent;
1741 int addr_family;
1742 } AioFile;
@@ -1760,20 +1831,21 @@
1760 {
1761 AioFile *af = privData;
1762
1763 JIM_NOTUSED(interp);
1764
1765 if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1766 fclose(af->fp);
1767 }
1768
1769 Jim_DecrRefCount(interp, af->filename);
1770
1771 #ifdef jim_ext_eventloop
1772
1773 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1774 #endif
 
 
 
 
 
1775 Jim_Free(af);
1776 }
1777
1778 static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
1779 {
@@ -2020,12 +2092,31 @@
2020 return JIM_OK;
2021 }
2022
2023 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2024 {
2025 Jim_DeleteCommand(interp, Jim_String(argv[0]));
2026 return JIM_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2027 }
2028
2029 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2030 {
2031 AioFile *af = Jim_CmdPrivData(interp);
@@ -2072,11 +2163,11 @@
2072 #ifdef O_NDELAY
2073 static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2074 {
2075 AioFile *af = Jim_CmdPrivData(interp);
2076
2077 int fmode = af->flags;
2078
2079 if (argc) {
2080 long nb;
2081
2082 if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2086,12 +2177,11 @@
2086 fmode |= O_NDELAY;
2087 }
2088 else {
2089 fmode &= ~O_NDELAY;
2090 }
2091 fcntl(af->fd, F_SETFL, fmode);
2092 af->flags = fmode;
2093 }
2094 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2095 return JIM_OK;
2096 }
2097 #endif
@@ -2195,11 +2285,11 @@
2195
2196 static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2197 {
2198 AioFile *af = Jim_CmdPrivData(interp);
2199
2200 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
2201 }
2202 #endif
2203
2204 static const jim_subcmd_type aio_command_table[] = {
2205 { "read",
@@ -2250,14 +2340,14 @@
2250 0,
2251 0,
2252
2253 },
2254 { "close",
2255 NULL,
2256 aio_cmd_close,
2257 0,
2258 0,
2259 JIM_MODFLAG_FULLARGV,
2260
2261 },
2262 { "seek",
2263 "offset ?start|current|end",
@@ -2329,30 +2419,32 @@
2329
2330 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
2331 Jim_Obj *const *argv)
2332 {
2333 const char *mode;
2334 const char *filename;
2335
2336 if (argc != 2 && argc != 3) {
2337 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
2338 return JIM_ERR;
2339 }
2340
2341 mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2342 filename = Jim_String(argv[1]);
2343
2344 #ifdef jim_ext_tclcompat
2345
2346 if (*filename == '|') {
2347 Jim_Obj *evalObj[3];
2348
2349 evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2350 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2351 evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2352
2353 return Jim_EvalObjVector(interp, 3, evalObj);
 
 
 
 
2354 }
2355 #endif
2356 return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
2357 }
2358
@@ -2359,70 +2451,129 @@
2359 static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
2360 const char *hdlfmt, int family, const char *mode)
2361 {
2362 AioFile *af;
2363 char buf[AIO_CMD_LEN];
2364 int OpenFlags = 0;
2365
2366 if (filename == NULL) {
2367 filename = Jim_NewStringObj(interp, hdlfmt, -1);
 
2368 }
2369
2370 Jim_IncrRefCount(filename);
2371
2372 if (fh == NULL) {
2373 if (fd < 0) {
2374 fh = fopen(Jim_String(filename), mode);
2375 }
2376 else {
2377 fh = fdopen(fd, mode);
2378 }
2379 }
2380 else {
2381 OpenFlags = AIO_KEEPOPEN;
2382 }
2383
2384 if (fh == NULL) {
2385 JimAioSetError(interp, filename);
2386 #if !defined(JIM_ANSIC)
2387 if (fd >= 0) {
2388 close(fd);
 
 
 
 
2389 }
2390 #endif
2391 Jim_DecrRefCount(interp, filename);
2392 return JIM_ERR;
2393 }
2394
2395
2396 af = Jim_Alloc(sizeof(*af));
2397 memset(af, 0, sizeof(*af));
2398 af->fp = fh;
2399 af->fd = fileno(fh);
2400 af->filename = filename;
2401 #ifdef FD_CLOEXEC
2402 if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2403 fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2404 }
2405 #endif
2406 af->OpenFlags = OpenFlags;
2407 #ifdef O_NDELAY
2408 af->flags = fcntl(af->fd, F_GETFL);
2409 #endif
2410 af->addr_family = family;
2411 snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
2412 Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
2413
2414 Jim_SetResultString(interp, buf, -1);
2415
2416 return JIM_OK;
2417 }
2418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2419
2420 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
2421 {
2422 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2423
 
2424 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2425 return ((AioFile *) cmdPtr->u.native.privData)->fp;
2426 }
2427 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2428 return NULL;
@@ -2443,11 +2594,10 @@
2443 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2444 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2445
2446 return JIM_OK;
2447 }
2448
2449
2450 #include <errno.h>
2451 #include <stdio.h>
2452 #include <string.h>
2453
@@ -2479,28 +2629,29 @@
2479 return JIM_OK;
2480 }
2481 Jim_SetResultString(interp, strerror(errno), -1);
2482 return JIM_ERR;
2483 }
2484 Jim_SetResultString(interp, strerror(errno), -1);
2485
2486 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2487
2488 while ((entryPtr = readdir(dirPtr)) != NULL) {
2489 if (entryPtr->d_name[0] == '.') {
2490 if (entryPtr->d_name[1] == '\0') {
2491 continue;
2492 }
2493 if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2494 continue;
2495 }
2496 Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2497 entryPtr->d_name, -1));
2498 }
2499 closedir(dirPtr);
2500
2501 return JIM_OK;
 
2502 }
2503
2504 int Jim_readdirInit(Jim_Interp *interp)
2505 {
2506 if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2511,10 +2662,14 @@
2511 }
2512
2513 #include <stdlib.h>
2514 #include <string.h>
2515
 
 
 
 
2516
2517 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2518 {
2519 regfree(objPtr->internalRep.regexpValue.compre);
2520 Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3058,58 +3213,61 @@
3058 }
3059 #endif
3060 return "unknown";
3061 }
3062
3063
3064 static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3065 jim_wide value)
3066 {
3067 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3068 Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3069
3070 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3071 Jim_FreeObj(interp, nameobj);
3072 Jim_FreeObj(interp, valobj);
3073 return JIM_ERR;
3074 }
3075 return JIM_OK;
3076 }
3077
3078 static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3079 const char *value)
3080 {
3081 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3082 Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3083
3084 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3085 Jim_FreeObj(interp, nameobj);
3086 Jim_FreeObj(interp, valobj);
3087 return JIM_ERR;
3088 }
3089 return JIM_OK;
3090 }
3091
3092 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3093 {
3094 if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3095 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3096 return JIM_ERR;
3097 }
3098 set_array_int_value(interp, varName, "ino", sb->st_ino);
3099 set_array_int_value(interp, varName, "mode", sb->st_mode);
3100 set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3101 set_array_int_value(interp, varName, "uid", sb->st_uid);
3102 set_array_int_value(interp, varName, "gid", sb->st_gid);
3103 set_array_int_value(interp, varName, "size", sb->st_size);
3104 set_array_int_value(interp, varName, "atime", sb->st_atime);
3105 set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3106 set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3107 set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3108
3109
3110 Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3111
3112 return JIM_OK;
3113 }
3114
3115 static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3264,14 +3422,11 @@
3264 return JIM_OK;
3265 }
3266
3267 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
3268 {
3269 const char *path = Jim_String(filename);
3270 int rc = access(path, mode);
3271
3272 Jim_SetResultBool(interp, rc != -1);
3273
3274 return JIM_OK;
3275 }
3276
3277 static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3287,10 +3442,11 @@
3287 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3288 {
3289 #ifdef X_OK
3290 return file_access(interp, argv[0], X_OK);
3291 #else
 
3292 Jim_SetResultBool(interp, 1);
3293 return JIM_OK;
3294 #endif
3295 }
3296
@@ -3391,33 +3547,21 @@
3391 argv++;
3392 }
3393 return JIM_OK;
3394 }
3395
3396 #ifdef HAVE_MKSTEMP
3397 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3398 {
3399 int fd;
3400 char *filename;
3401 const char *template = "/tmp/tcl.tmp.XXXXXX";
3402
3403 if (argc >= 1) {
3404 template = Jim_String(argv[0]);
3405 }
3406 filename = Jim_StrDup(template);
3407
3408 fd = mkstemp(filename);
3409 if (fd < 0) {
3410 Jim_SetResultString(interp, "Failed to create tempfile", -1);
3411 return JIM_ERR;
3412 }
3413 close(fd);
3414
3415 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
3416 return JIM_OK;
3417 }
3418 #endif
3419
3420 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3421 {
3422 const char *source;
3423 const char *dest;
@@ -3459,14 +3603,11 @@
3459 return JIM_ERR;
3460 }
3461 return JIM_OK;
3462 }
3463
3464 #ifndef HAVE_LSTAT
3465 #define lstat stat
3466 #endif
3467
3468 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
3469 {
3470 const char *path = Jim_String(filename);
3471
3472 if (lstat(path, sb) == -1) {
@@ -3473,10 +3614,13 @@
3473 Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
3474 return JIM_ERR;
3475 }
3476 return JIM_OK;
3477 }
 
 
 
3478
3479 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3480 {
3481 struct stat sb;
3482
@@ -3601,28 +3745,32 @@
3601 }
3602 Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
3603 return JIM_OK;
3604 }
3605
 
3606 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3607 {
3608 struct stat sb;
3609
3610 if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
3611 return JIM_ERR;
3612 }
3613 return StoreStatData(interp, argv[1], &sb);
3614 }
 
 
 
3615
3616 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3617 {
3618 struct stat sb;
3619
3620 if (file_stat(interp, argv[0], &sb) != JIM_OK) {
3621 return JIM_ERR;
3622 }
3623 return StoreStatData(interp, argv[1], &sb);
3624 }
3625
3626 static const jim_subcmd_type file_command_table[] = {
3627 { "atime",
3628 "name",
@@ -3727,19 +3875,17 @@
3727 file_cmd_mkdir,
3728 1,
3729 -1,
3730
3731 },
3732 #ifdef HAVE_MKSTEMP
3733 { "tempfile",
3734 "?template?",
3735 file_cmd_tempfile,
3736 0,
3737 1,
3738
3739 },
3740 #endif
3741 { "rename",
3742 "?-force? source dest",
3743 file_cmd_rename,
3744 2,
3745 3,
@@ -3760,20 +3906,20 @@
3760 1,
3761 1,
3762
3763 },
3764 { "stat",
3765 "name var",
3766 file_cmd_stat,
3767 2,
3768 2,
3769
3770 },
3771 { "lstat",
3772 "name var",
3773 file_cmd_lstat,
3774 2,
3775 2,
3776
3777 },
3778 { "type",
3779 "name",
@@ -3829,15 +3975,15 @@
3829 return JIM_OK;
3830 }
3831
3832 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3833 {
3834 const int cwd_len = 2048;
3835 char *cwd = malloc(cwd_len);
3836
3837 if (getcwd(cwd, cwd_len) == NULL) {
3838 Jim_SetResultString(interp, "Failed to get pwd", -1);
 
3839 return JIM_ERR;
3840 }
3841 #if defined(__MINGW32__) || defined(_MSC_VER)
3842 {
3843
@@ -3848,11 +3994,11 @@
3848 }
3849 #endif
3850
3851 Jim_SetResultString(interp, cwd, -1);
3852
3853 free(cwd);
3854 return JIM_OK;
3855 }
3856
3857 int Jim_fileInit(Jim_Interp *interp)
3858 {
@@ -3917,10 +4063,11 @@
3917
3918 int Jim_execInit(Jim_Interp *interp)
3919 {
3920 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
3921 return JIM_ERR;
 
3922 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
3923 return JIM_OK;
3924 }
3925 #else
3926
@@ -3960,10 +4107,11 @@
3960 static int JimErrno(void);
3961 #else
3962 #include <unistd.h>
3963 #include <fcntl.h>
3964 #include <sys/wait.h>
 
3965
3966 typedef int fdtype;
3967 typedef int pidtype;
3968 #define JimPipe pipe
3969 #define JimErrno() errno
@@ -4034,23 +4182,12 @@
4034 Jim_RemoveTrailingNewline(strObj);
4035 fclose(fh);
4036 return JIM_OK;
4037 }
4038
4039 static void JimTrimTrailingNewline(Jim_Interp *interp)
4040 {
4041 int len;
4042 const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4043
4044 if (len > 0 && p[len - 1] == '\n') {
4045 Jim_SetResultString(interp, p, len - 1);
4046 }
4047 }
4048
4049 static char **JimBuildEnv(Jim_Interp *interp)
4050 {
4051 #if defined(jim_ext_tclcompat)
4052 int i;
4053 int size;
4054 int num;
4055 int n;
4056 char **envptr;
@@ -4064,10 +4201,11 @@
4064
4065
4066
4067 num = Jim_ListLength(interp, objPtr);
4068 if (num % 2) {
 
4069 num--;
4070 }
4071 size = Jim_Length(objPtr) + 2;
4072
4073 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4090,22 +4228,17 @@
4090 }
4091 envptr[n] = NULL;
4092 *envdata = 0;
4093
4094 return envptr;
4095 #else
4096 return Jim_GetEnviron();
4097 #endif
4098 }
4099
4100 static void JimFreeEnv(char **env, char **original_environ)
4101 {
4102 #ifdef jim_ext_tclcompat
4103 if (env != original_environ) {
4104 Jim_Free(env);
4105 }
4106 #endif
4107 }
4108
4109 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
4110 {
4111 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4154,19 +4287,19 @@
4154 }
4155
4156
4157 struct WaitInfo
4158 {
4159 pidtype pid;
4160 int status;
4161 int flags;
4162 };
4163
4164 struct WaitInfoTable {
4165 struct WaitInfo *info;
4166 int size;
4167 int used;
4168 };
4169
4170
4171 #define WI_DETACHED 2
4172
@@ -4189,14 +4322,12 @@
4189 return table;
4190 }
4191
4192 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4193 {
4194 fdtype outputId; /* File id for output pipe. -1
4195 * means command overrode. */
4196 fdtype errorId; /* File id for temporary file
4197 * containing error output. */
4198 pidtype *pidPtr;
4199 int numPids, result;
4200
4201 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4202 Jim_Obj *listObj;
@@ -4243,26 +4374,32 @@
4243
4244 static void JimReapDetachedPids(struct WaitInfoTable *table)
4245 {
4246 struct WaitInfo *waitPtr;
4247 int count;
 
4248
4249 if (!table) {
4250 return;
4251 }
4252
4253 for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
 
 
4254 if (waitPtr->flags & WI_DETACHED) {
4255 int status;
4256 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4257 if (pid != JIM_BAD_PID) {
4258 if (waitPtr != &table->info[table->used - 1]) {
4259 *waitPtr = table->info[table->used - 1];
4260 }
4261 table->used--;
 
4262 }
4263 }
 
 
 
 
4264 }
4265 }
4266
4267 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4268 {
@@ -4284,11 +4421,10 @@
4284 }
4285
4286
4287 return JIM_BAD_PID;
4288 }
4289
4290
4291 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4292 {
4293 int j;
4294 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4609,27 +4745,23 @@
4609 }
4610 outputId = pipeIds[1];
4611 }
4612
4613
 
 
 
 
 
4614
4615 #ifdef __MINGW32__
4616 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
4617 if (pid == JIM_BAD_PID) {
4618 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
4619 goto error;
4620 }
4621 #else
4622 if (table->info == NULL) {
4623 (void)signal(SIGPIPE, SIG_IGN);
4624 }
4625
4626
4627 if (pipe_dup_err) {
4628 errorId = outputId;
4629 }
4630
4631 pid = vfork();
4632 if (pid < 0) {
4633 Jim_SetResultErrno(interp, "couldn't fork child process");
4634 goto error;
4635 }
@@ -4642,14 +4774,17 @@
4642
4643 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
4644 close(i);
4645 }
4646
 
 
 
4647 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
4648
4649
4650 fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4651 _exit(127);
4652 }
4653 #endif
4654
4655
@@ -4751,19 +4886,24 @@
4751 if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
4752 result = JIM_ERR;
4753 }
4754 }
4755
4756 JimTrimTrailingNewline(interp);
4757
4758 return result;
4759 }
4760
4761 int Jim_execInit(Jim_Interp *interp)
4762 {
4763 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4764 return JIM_ERR;
 
 
 
 
 
4765 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
4766 return JIM_OK;
4767 }
4768
4769 #if defined(__MINGW32__)
@@ -5088,28 +5228,26 @@
5088 {
5089 STARTUPINFO startInfo;
5090 PROCESS_INFORMATION procInfo;
5091 HANDLE hProcess, h;
5092 char execPath[MAX_PATH];
5093 char *originalName;
5094 pidtype pid = JIM_BAD_PID;
5095 Jim_Obj *cmdLineObj;
5096
5097 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5098 return JIM_BAD_PID;
5099 }
5100 originalName = argv[0];
5101 argv[0] = execPath;
5102
5103 hProcess = GetCurrentProcess();
5104 cmdLineObj = JimWinBuildCommandLine(interp, argv);
5105
5106
5107 ZeroMemory(&startInfo, sizeof(startInfo));
5108 startInfo.cb = sizeof(startInfo);
5109 startInfo.dwFlags = STARTF_USESTDHANDLES;
5110 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5111 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5112 startInfo.hStdError = INVALID_HANDLE_VALUE;
5113
5114 if (inputId == JIM_BAD_FD) {
5115 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5182,18 +5320,17 @@
5182 return lseek(fd, 0L, SEEK_SET);
5183 }
5184
5185 static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5186 {
5187 char inName[] = "/tmp/tcl.tmp.XXXXXX";
5188
5189 int fd = mkstemp(inName);
5190 if (fd == JIM_BAD_FD) {
5191 Jim_SetResultErrno(interp, "couldn't create temp file");
5192 return -1;
5193 }
5194 unlink(inName);
5195 if (contents) {
5196 if (write(fd, contents, len) != len) {
5197 Jim_SetResultErrno(interp, "couldn't write temp file");
5198 close(fd);
5199 return -1;
@@ -5217,11 +5354,10 @@
5217 }
5218 #endif
5219 #endif
5220
5221
5222
5223 #ifndef _XOPEN_SOURCE
5224 #define _XOPEN_SOURCE 500
5225 #endif
5226
5227 #include <stdlib.h>
@@ -5239,11 +5375,11 @@
5239
5240 char buf[100];
5241 time_t t;
5242 long seconds;
5243
5244 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5245
5246 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5247 return -1;
5248 }
5249
@@ -5254,11 +5390,14 @@
5254 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5255 return JIM_ERR;
5256 }
5257 t = seconds;
5258
5259 strftime(buf, sizeof(buf), format, localtime(&t));
 
 
 
5260
5261 Jim_SetResultString(interp, buf, -1);
5262
5263 return JIM_OK;
5264 }
@@ -5374,11 +5513,10 @@
5374
5375 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
5376 return JIM_OK;
5377 }
5378
5379
5380 #include <limits.h>
5381 #include <stdlib.h>
5382 #include <string.h>
5383 #include <stdio.h>
5384 #include <errno.h>
@@ -5392,33 +5530,29 @@
5392 }
5393
5394 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5395 {
5396 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
5397
5398 if (!objPtr) {
5399 return JIM_OK;
5400 }
5401
5402 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5403
5404 if (Jim_IsList(objPtr)) {
5405 if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5406
5407 return JIM_ERR;
5408 }
5409 }
5410 else if (Jim_DictSize(interp, objPtr) < 0) {
5411
5412 return JIM_ERR;
5413 }
5414 Jim_SetResult(interp, objPtr);
5415 return JIM_OK;
5416 }
5417
5418
5419 return Jim_DictValues(interp, objPtr, argv[1]);
5420 }
5421
5422 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5423 {
5424 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5443,10 +5577,15 @@
5443 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5444 return JIM_OK;
5445 }
5446
5447 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
 
 
 
 
5448
5449 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5450 return JIM_ERR;
5451 }
5452
@@ -5480,10 +5619,20 @@
5480
5481 Jim_SetResultInt(interp, len);
5482
5483 return JIM_OK;
5484 }
 
 
 
 
 
 
 
 
 
 
5485
5486 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5487 {
5488 int i;
5489 int len;
@@ -5498,10 +5647,13 @@
5498
5499 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5500 if (!dictObj) {
5501
5502 return Jim_SetVariable(interp, argv[0], listObj);
 
 
 
5503 }
5504
5505 if (Jim_IsShared(dictObj)) {
5506 dictObj = Jim_DuplicateObj(interp, dictObj);
5507 }
@@ -5551,10 +5703,17 @@
5551 "arrayName",
5552 array_cmd_size,
5553 1,
5554 1,
5555
 
 
 
 
 
 
 
5556 },
5557 { "unset",
5558 "arrayName ?pattern?",
5559 array_cmd_unset,
5560 1,
@@ -5597,11 +5756,10 @@
5597 Jim_arrayInit(interp);
5598 Jim_stdlibInit(interp);
5599 Jim_tclcompatInit(interp);
5600 return JIM_OK;
5601 }
5602
5603 #define JIM_OPTIMIZATION
5604
5605 #include <stdio.h>
5606 #include <stdlib.h>
5607
@@ -5661,21 +5819,20 @@
5661 #define JIM_INTEGER_SPACE 24
5662
5663 const char *jim_tt_name(int type);
5664
5665 #ifdef JIM_DEBUG_PANIC
5666 static void JimPanicDump(int panic_condition, const char *fmt, ...);
5667 #define JimPanic(X) JimPanicDump X
5668 #else
5669 #define JimPanic(X)
5670 #endif
5671
5672
5673 static char JimEmptyStringRep[] = "";
5674
5675 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5676 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5677 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5678 int flags);
5679 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5680 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5681 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -5922,44 +6079,10 @@
5922 }
5923 return n;
5924 }
5925 #endif
5926
5927 static int JimWideToString(char *buf, jim_wide wideValue)
5928 {
5929 int pos = 0;
5930
5931 if (wideValue == 0) {
5932 buf[pos++] = '0';
5933 }
5934 else {
5935 char tmp[JIM_INTEGER_SPACE];
5936 int num = 0;
5937 int i;
5938
5939 if (wideValue < 0) {
5940 buf[pos++] = '-';
5941
5942 i = wideValue % 10;
5943 tmp[num++] = (i > 0) ? (10 - i) : -i;
5944 wideValue /= -10;
5945 }
5946
5947 while (wideValue) {
5948 tmp[num++] = wideValue % 10;
5949 wideValue /= 10;
5950 }
5951
5952 for (i = 0; i < num; i++) {
5953 buf[pos++] = '0' + tmp[num - i - 1];
5954 }
5955 }
5956 buf[pos] = 0;
5957
5958 return pos;
5959 }
5960
5961 static int JimCheckConversion(const char *str, const char *endptr)
5962 {
5963 if (str[0] == '\0' || str == endptr) {
5964 return JIM_ERR;
5965 }
@@ -6070,48 +6193,10 @@
6070 }
6071
6072 return JimCheckConversion(str, endptr);
6073 }
6074
6075 int Jim_DoubleToString(char *buf, double doubleValue)
6076 {
6077 int len;
6078 int i;
6079
6080 len = sprintf(buf, "%.12g", doubleValue);
6081
6082
6083 for (i = 0; i < len; i++) {
6084 if (buf[i] == '.' || buf[i] == 'e') {
6085 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6086 char *e = strchr(buf, 'e');
6087 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6088
6089 e += 2;
6090 memmove(e, e + 1, len - (e - buf));
6091 return len - 1;
6092 }
6093 #endif
6094 return len;
6095 }
6096
6097 if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6098 buf[i] = toupper(UCHAR(buf[i]));
6099 if (buf[i] == 'n' || buf[i] == 'N')
6100 buf[i+2] = toupper(UCHAR(buf[i+2]));
6101 buf[i + 3] = 0;
6102 return i + 3;
6103 }
6104 }
6105
6106 buf[i++] = '.';
6107 buf[i++] = '0';
6108 buf[i] = '\0';
6109
6110 return i;
6111 }
6112
6113 int Jim_StringToDouble(const char *str, double *doublePtr)
6114 {
6115 char *endptr;
6116
6117
@@ -6133,23 +6218,23 @@
6133 }
6134 return res;
6135 }
6136
6137 #ifdef JIM_DEBUG_PANIC
6138 void JimPanicDump(int condition, const char *fmt, ...)
6139 {
6140 va_list ap;
6141
6142 if (!condition) {
6143 return;
6144 }
6145
6146 va_start(ap, fmt);
6147
6148 fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6149 vfprintf(stderr, fmt, ap);
6150 fprintf(stderr, JIM_NL JIM_NL);
6151 va_end(ap);
6152
6153 #ifdef HAVE_BACKTRACE
6154 {
6155 void *array[40];
@@ -6157,13 +6242,13 @@
6157 char **strings;
6158
6159 size = backtrace(array, 40);
6160 strings = backtrace_symbols(array, size);
6161 for (i = 0; i < size; i++)
6162 fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6163 fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6164 fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
6165 }
6166 #endif
6167
6168 exit(1);
6169 }
@@ -6237,18 +6322,24 @@
6237 h += (h << 3) + *buf++;
6238 return h;
6239 }
6240
6241
 
6242
6243 static void JimResetHashTable(Jim_HashTable *ht)
6244 {
6245 ht->table = NULL;
6246 ht->size = 0;
6247 ht->sizemask = 0;
6248 ht->used = 0;
6249 ht->collisions = 0;
 
 
 
 
 
6250 }
6251
6252 static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6253 {
6254 iter->ht = ht;
@@ -6286,10 +6377,12 @@
6286
6287 Jim_InitHashTable(&n, ht->type, ht->privdata);
6288 n.size = realsize;
6289 n.sizemask = realsize - 1;
6290 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
 
 
6291
6292
6293 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6294
6295 n.used = ht->used;
@@ -6342,20 +6435,27 @@
6342 int existed;
6343 Jim_HashEntry *entry;
6344
6345 entry = JimInsertHashEntry(ht, key, 1);
6346 if (entry->key) {
6347
6348 Jim_FreeEntryVal(ht, entry);
 
 
 
 
 
 
 
6349 existed = 1;
6350 }
6351 else {
6352
6353 Jim_SetHashKey(ht, entry, key);
 
6354 existed = 0;
6355 }
6356 Jim_SetHashVal(ht, entry, val);
6357
6358 return existed;
6359 }
6360
6361
@@ -6520,11 +6620,11 @@
6520 return Jim_GenHashFunction(key, strlen(key));
6521 }
6522
6523 static void *JimStringCopyHTDup(void *privdata, const void *key)
6524 {
6525 return strdup(key);
6526 }
6527
6528 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
6529 {
6530 return strcmp(key1, key2) == 0;
@@ -6620,11 +6720,11 @@
6620 freeFunc(stack->vector[i]);
6621 }
6622
6623
6624
6625 #define JIM_TT_NONE 0
6626 #define JIM_TT_STR 1
6627 #define JIM_TT_ESC 2
6628 #define JIM_TT_VAR 3
6629 #define JIM_TT_DICTSUGAR 4
6630 #define JIM_TT_CMD 5
@@ -6652,10 +6752,15 @@
6652
6653
6654 #define JIM_PS_DEF 0
6655 #define JIM_PS_QUOTE 1
6656 #define JIM_PS_DICTSUGAR 2
 
 
 
 
 
6657
6658 struct JimParserCtx
6659 {
6660 const char *p;
6661 int len;
@@ -6665,17 +6770,11 @@
6665 int tline;
6666 int tt;
6667 int eof;
6668 int state;
6669 int comment;
6670 char missing;
6671 int missingline;
6672 };
6673
6674 struct JimParseResult {
6675 char missing;
6676 int line;
6677 };
6678
6679 static int JimParseScript(struct JimParserCtx *pc);
6680 static int JimParseSep(struct JimParserCtx *pc);
6681 static int JimParseEol(struct JimParserCtx *pc);
@@ -6685,11 +6784,10 @@
6685 static int JimParseBrace(struct JimParserCtx *pc);
6686 static int JimParseStr(struct JimParserCtx *pc);
6687 static int JimParseComment(struct JimParserCtx *pc);
6688 static void JimParseSubCmd(struct JimParserCtx *pc);
6689 static int JimParseSubQuote(struct JimParserCtx *pc);
6690 static void JimParseSubCmd(struct JimParserCtx *pc);
6691 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
6692
6693 static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
6694 {
6695 pc->p = prg;
@@ -6700,12 +6798,12 @@
6700 pc->tt = JIM_TT_NONE;
6701 pc->eof = 0;
6702 pc->state = JIM_PS_DEF;
6703 pc->linenr = linenr;
6704 pc->comment = 1;
6705 pc->missing = ' ';
6706 pc->missingline = linenr;
6707 }
6708
6709 static int JimParseScript(struct JimParserCtx *pc)
6710 {
6711 while (1) {
@@ -6837,12 +6935,12 @@
6837 break;
6838 }
6839 pc->p++;
6840 pc->len--;
6841 }
6842 pc->missing = '{';
6843 pc->missingline = pc->tline;
6844 pc->tend = pc->p - 1;
6845 }
6846
6847 static int JimParseSubQuote(struct JimParserCtx *pc)
6848 {
@@ -6884,12 +6982,12 @@
6884 break;
6885 }
6886 pc->p++;
6887 pc->len--;
6888 }
6889 pc->missing = '"';
6890 pc->missingline = line;
6891 pc->tend = pc->p - 1;
6892 return tt;
6893 }
6894
6895 static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6943,12 +7041,12 @@
6943 }
6944 startofword = isspace(UCHAR(*pc->p));
6945 pc->p++;
6946 pc->len--;
6947 }
6948 pc->missing = '[';
6949 pc->missingline = line;
6950 pc->tend = pc->p - 1;
6951 }
6952
6953 static int JimParseBrace(struct JimParserCtx *pc)
6954 {
@@ -7088,19 +7186,19 @@
7088 if (*pc->p == '"') {
7089 pc->state = JIM_PS_QUOTE;
7090 pc->p++;
7091 pc->len--;
7092
7093 pc->missingline = pc->tline;
7094 }
7095 }
7096 pc->tstart = pc->p;
7097 pc->tline = pc->linenr;
7098 while (1) {
7099 if (pc->len == 0) {
7100 if (pc->state == JIM_PS_QUOTE) {
7101 pc->missing = '"';
7102 }
7103 pc->tend = pc->p - 1;
7104 pc->tt = JIM_TT_ESC;
7105 return JIM_OK;
7106 }
@@ -7116,10 +7214,14 @@
7116 pc->linenr++;
7117 }
7118 pc->p++;
7119 pc->len--;
7120 }
 
 
 
 
7121 break;
7122 case '(':
7123
7124 if (pc->len > 1 && pc->p[1] != '$') {
7125 break;
@@ -7176,17 +7278,26 @@
7176 }
7177
7178 static int JimParseComment(struct JimParserCtx *pc)
7179 {
7180 while (*pc->p) {
7181 if (*pc->p == '\n') {
 
 
 
 
 
 
 
 
 
 
 
 
 
7182 pc->linenr++;
7183 if (*(pc->p - 1) != '\\') {
7184 pc->p++;
7185 pc->len--;
7186 return JIM_OK;
7187 }
7188 }
7189 pc->p++;
7190 pc->len--;
7191 }
7192 return JIM_OK;
@@ -7404,13 +7515,13 @@
7404 JimParserInit(&parser, s, len, 1);
7405 while (!parser.eof) {
7406 JimParseScript(&parser);
7407 }
7408 if (stateCharPtr) {
7409 *stateCharPtr = parser.missing;
7410 }
7411 return parser.missing == ' ';
7412 }
7413
7414 static int JimParseListSep(struct JimParserCtx *pc);
7415 static int JimParseListStr(struct JimParserCtx *pc);
7416 static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7662,10 +7773,16 @@
7662 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7663 objPtr->typePtr->updateStringProc(objPtr);
7664 }
7665 return objPtr->bytes;
7666 }
 
 
 
 
 
 
7667
7668 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
7669 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
7670
7671 static const Jim_ObjType dictSubstObjType = {
@@ -7703,11 +7820,10 @@
7703 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
7704 {
7705 JIM_NOTUSED(interp);
7706
7707 dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7708
7709 dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
7710 }
7711
7712 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
7713 {
@@ -7752,18 +7868,17 @@
7752 if (len == -1)
7753 len = strlen(s);
7754
7755 if (len == 0) {
7756 objPtr->bytes = JimEmptyStringRep;
7757 objPtr->length = 0;
7758 }
7759 else {
7760 objPtr->bytes = Jim_Alloc(len + 1);
7761 objPtr->length = len;
7762 memcpy(objPtr->bytes, s, len);
7763 objPtr->bytes[len] = '\0';
7764 }
 
7765
7766
7767 objPtr->typePtr = NULL;
7768 return objPtr;
7769 }
@@ -7791,11 +7906,11 @@
7791 Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
7792 {
7793 Jim_Obj *objPtr = Jim_NewObj(interp);
7794
7795 objPtr->bytes = s;
7796 objPtr->length = len == -1 ? strlen(s) : len;
7797 objPtr->typePtr = NULL;
7798 return objPtr;
7799 }
7800
7801 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7820,17 +7935,17 @@
7820 }
7821 objPtr->internalRep.strValue.maxLength = needlen;
7822 }
7823 memcpy(objPtr->bytes + objPtr->length, str, len);
7824 objPtr->bytes[objPtr->length + len] = '\0';
 
7825 if (objPtr->internalRep.strValue.charLength >= 0) {
7826
7827 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
7828 }
7829 objPtr->length += len;
7830 }
7831
7832
7833 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
7834 {
7835 JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
7836 SetStringFromAny(interp, objPtr);
@@ -7838,13 +7953,11 @@
7838 }
7839
7840 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
7841 {
7842 int len;
7843 const char *str;
7844
7845 str = Jim_GetString(appendObjPtr, &len);
7846 Jim_AppendString(interp, objPtr, str, len);
7847 }
7848
7849 void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
7850 {
@@ -7851,11 +7964,11 @@
7851 va_list ap;
7852
7853 SetStringFromAny(interp, objPtr);
7854 va_start(ap, objPtr);
7855 while (1) {
7856 char *s = va_arg(ap, char *);
7857
7858 if (s == NULL)
7859 break;
7860 Jim_AppendString(interp, objPtr, s, -1);
7861 }
@@ -7862,20 +7975,20 @@
7862 va_end(ap);
7863 }
7864
7865 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
7866 {
7867 const char *aStr, *bStr;
7868 int aLen, bLen;
7869
7870 if (aObjPtr == bObjPtr)
7871 return 1;
7872 aStr = Jim_GetString(aObjPtr, &aLen);
7873 bStr = Jim_GetString(bObjPtr, &bLen);
7874 if (aLen != bLen)
7875 return 0;
7876 return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
 
 
 
7877 }
7878
7879 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
7880 {
7881 return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8036,11 +8149,11 @@
8036 static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
8037 {
8038 while (*str) {
8039 int c;
8040 str += utf8_tounicode(str, &c);
8041 dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8042 }
8043 *dest = 0;
8044 }
8045
8046 static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8096,11 +8209,11 @@
8096 len *= 2;
8097 #endif
8098 buf = p = Jim_Alloc(len + 1);
8099
8100 str += utf8_tounicode(str, &c);
8101 p += utf8_fromunicode(p, utf8_title(c));
8102
8103 JimStrCopyUpperLower(p, str, 0);
8104
8105 return Jim_NewStringObjNoAlloc(interp, buf, -1);
8106 }
@@ -8203,10 +8316,11 @@
8203 if (nontrim == NULL) {
8204
8205 return Jim_NewEmptyStringObj(interp);
8206 }
8207 if (nontrim == strObjPtr->bytes + len) {
 
8208 return strObjPtr;
8209 }
8210
8211 if (Jim_IsShared(strObjPtr)) {
8212 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8226,14 +8340,14 @@
8226 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8227
8228
8229 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8230
8231 if (objPtr != strObjPtr) {
 
8232
8233 Jim_IncrRefCount(objPtr);
8234 Jim_DecrRefCount(interp, objPtr);
8235 }
8236
8237 return strObjPtr;
8238 }
8239
@@ -8270,26 +8384,26 @@
8270 return JIM_ERR;
8271 }
8272
8273 str = Jim_GetString(strObjPtr, &len);
8274 if (len == 0) {
8275 Jim_SetResultInt(interp, !strict);
8276 return JIM_OK;
8277 }
8278
8279 switch (strclass) {
8280 case STR_IS_INTEGER:
8281 {
8282 jim_wide w;
8283 Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8284 return JIM_OK;
8285 }
8286
8287 case STR_IS_DOUBLE:
8288 {
8289 double d;
8290 Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8291 return JIM_OK;
8292 }
8293
8294 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8295 case STR_IS_ALNUM: isclassfunc = isalnum; break;
@@ -8307,15 +8421,15 @@
8307 return JIM_ERR;
8308 }
8309
8310 for (i = 0; i < len; i++) {
8311 if (!isclassfunc(str[i])) {
8312 Jim_SetResultInt(interp, 0);
8313 return JIM_OK;
8314 }
8315 }
8316 Jim_SetResultInt(interp, 1);
8317 return JIM_OK;
8318 }
8319
8320
8321
@@ -8327,17 +8441,19 @@
8327 JIM_TYPE_REFERENCES,
8328 };
8329
8330 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
8331 {
8332 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8333 return 1;
 
8334 else {
8335 const char *objStr = Jim_String(objPtr);
8336
8337 if (strcmp(str, objStr) != 0)
8338 return 0;
 
8339 if (objPtr->typePtr != &comparedStringObjType) {
8340 Jim_FreeIntRep(interp, objPtr);
8341 objPtr->typePtr = &comparedStringObjType;
8342 }
8343 objPtr->internalRep.ptr = (char *)str;
@@ -8379,24 +8495,23 @@
8379
8380 static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
8381 Jim_Obj *fileNameObj, int lineNumber)
8382 {
8383 JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8384 JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8385 Jim_IncrRefCount(fileNameObj);
8386 objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
8387 objPtr->internalRep.sourceValue.lineNumber = lineNumber;
8388 objPtr->typePtr = &sourceObjType;
8389 }
8390
8391
8392 static const Jim_ObjType scriptLineObjType = {
8393 "scriptline",
8394 NULL,
8395 NULL,
8396 NULL,
8397 0,
8398 };
8399
8400 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
8401 {
8402 Jim_Obj *objPtr;
@@ -8413,15 +8528,14 @@
8413 objPtr->internalRep.scriptLineValue.line = line;
8414
8415 return objPtr;
8416 }
8417
8418 #define JIM_CMDSTRUCT_EXPAND -1
8419
8420 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8421 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8422 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
 
8423
8424 static const Jim_ObjType scriptObjType = {
8425 "script",
8426 FreeScriptInternalRep,
8427 DupScriptInternalRep,
@@ -8429,34 +8543,33 @@
8429 JIM_TYPE_REFERENCES,
8430 };
8431
8432 typedef struct ScriptToken
8433 {
8434 int type;
8435 Jim_Obj *objPtr;
 
8436 } ScriptToken;
8437
8438 typedef struct ScriptObj
8439 {
8440 int len;
8441 ScriptToken *token;
 
 
8442 int substFlags;
8443 int inUse; /* Used to share a ScriptObj. Currently
8444 only used by Jim_EvalObj() as protection against
8445 shimmering of the currently evaluated object. */
8446 Jim_Obj *fileNameObj;
8447 int firstline;
8448 int linenr;
8449 } ScriptObj;
8450
8451 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8452 {
8453 int i;
8454 struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
8455
8456 script->inUse--;
8457 if (script->inUse != 0)
8458 return;
8459 for (i = 0; i < script->len; i++) {
8460 Jim_DecrRefCount(interp, script->token[i].objPtr);
8461 }
8462 Jim_Free(script->token);
@@ -8467,11 +8580,10 @@
8467 void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8468 {
8469 JIM_NOTUSED(interp);
8470 JIM_NOTUSED(srcPtr);
8471
8472
8473 dupPtr->typePtr = NULL;
8474 }
8475
8476 typedef struct
8477 {
@@ -8666,11 +8778,11 @@
8666 token--;
8667 }
8668
8669 script->len = token - script->token;
8670
8671 assert(script->len < count);
8672
8673 #ifdef DEBUG_SHOW_SCRIPT
8674 printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
8675 for (i = 0; i < script->len; i++) {
8676 const ScriptToken *t = &script->token[i];
@@ -8677,10 +8789,35 @@
8677 printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
8678 }
8679 #endif
8680
8681 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8682
8683 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8684 ParseTokenList *tokenlist)
8685 {
8686 int i;
@@ -8699,18 +8836,19 @@
8699 }
8700
8701 script->len = i;
8702 }
8703
8704 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8705 {
8706 int scriptTextLen;
8707 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
8708 struct JimParserCtx parser;
8709 struct ScriptObj *script;
8710 ParseTokenList tokenlist;
8711 int line = 1;
 
8712
8713
8714 if (objPtr->typePtr == &sourceObjType) {
8715 line = objPtr->internalRep.sourceValue.lineNumber;
8716 }
@@ -8722,16 +8860,12 @@
8722 while (!parser.eof) {
8723 JimParseScript(&parser);
8724 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
8725 parser.tline);
8726 }
8727 if (result && parser.missing != ' ') {
8728 ScriptTokenListFree(&tokenlist);
8729 result->missing = parser.missing;
8730 result->line = parser.missingline;
8731 return JIM_ERR;
8732 }
8733
8734
8735 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
8736
8737
@@ -8742,10 +8876,11 @@
8742 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
8743 }
8744 else {
8745 script->fileNameObj = interp->emptyObj;
8746 }
 
8747 Jim_IncrRefCount(script->fileNameObj);
8748
8749 ScriptObjAddTokens(interp, script, &tokenlist);
8750
8751
@@ -8754,11 +8889,11 @@
8754
8755 Jim_FreeIntRep(interp, objPtr);
8756 Jim_SetIntRepPtr(objPtr, script);
8757 objPtr->typePtr = &scriptObjType;
8758
8759 return JIM_OK;
8760 }
8761
8762 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
8763 {
8764 if (objPtr == interp->emptyObj) {
@@ -8765,11 +8900,13 @@
8765
8766 objPtr = interp->nullScriptObj;
8767 }
8768
8769 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8770 SetScriptFromAny(interp, objPtr, NULL);
 
 
8771 }
8772 return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
8773 }
8774
8775 static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8850,10 +8987,26 @@
8850 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
8851 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
8852 }
8853 return nsObj;
8854 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8855
8856 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
8857 {
8858 Jim_Obj *objPtr = interp->emptyObj;
8859
@@ -8877,10 +9030,15 @@
8877
8878 #else
8879
8880 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
8881 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
 
 
 
 
 
8882 #endif
8883
8884 static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
8885 {
8886 Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8889,12 +9047,12 @@
8889 Jim_InterpIncrProcEpoch(interp);
8890 }
8891
8892 if (he && interp->local) {
8893
8894 cmd->prevCmd = he->u.val;
8895 he->u.val = cmd;
8896 }
8897 else {
8898 if (he) {
8899
8900 Jim_DeleteHashEntry(&interp->commands, name);
@@ -8933,19 +9091,19 @@
8933 }
8934
8935 cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
8936 Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
8937 for (i = 0; i < len; i++) {
8938 Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
8939 Jim_Var *varPtr;
8940 int subLen;
8941
8942 Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
8943
8944 subLen = Jim_ListLength(interp, objPtr);
8945 if (subLen == 1 || subLen == 2) {
8946 Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
8947 if (subLen == 1) {
8948 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
8949 if (initObjPtr == NULL) {
8950 Jim_SetResultFormatted(interp,
8951 "variable for initialization of static \"%#s\" not found in the local context",
@@ -8952,11 +9110,11 @@
8952 nameObjPtr);
8953 return JIM_ERR;
8954 }
8955 }
8956 else {
8957 Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
8958 }
8959 if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
8960 return JIM_ERR;
8961 }
8962
@@ -9038,11 +9196,11 @@
9038 Jim_Obj *nameObjPtr;
9039 Jim_Obj *defaultObjPtr;
9040 int len;
9041
9042
9043 Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9044 len = Jim_ListLength(interp, argPtr);
9045 if (len == 0) {
9046 Jim_SetResultString(interp, "argument with no name", -1);
9047 err:
9048 JimDecrCmdRefCount(interp, cmdPtr);
@@ -9053,12 +9211,12 @@
9053 goto err;
9054 }
9055
9056 if (len == 2) {
9057
9058 Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9059 Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9060 }
9061 else {
9062
9063 nameObjPtr = argPtr;
9064 defaultObjPtr = NULL;
@@ -9132,11 +9290,11 @@
9132 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9133 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9134 }
9135 else {
9136
9137 cmdPtr = he->u.val;
9138 JimIncrCmdRefCount(cmdPtr);
9139 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9140 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9141
9142
@@ -9217,11 +9375,11 @@
9217 return NULL;
9218 }
9219 #ifdef jim_ext_namespace
9220 found:
9221 #endif
9222 cmd = (Jim_Cmd *)he->u.val;
9223
9224
9225 Jim_FreeIntRep(interp, objPtr);
9226 objPtr->typePtr = &commandObjType;
9227 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9323,11 +9481,11 @@
9323
9324
9325 Jim_FreeIntRep(interp, objPtr);
9326 objPtr->typePtr = &variableObjType;
9327 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9328 objPtr->internalRep.varValue.varPtr = he->u.val;
9329 objPtr->internalRep.varValue.global = global;
9330 return JIM_OK;
9331 }
9332
9333
@@ -9641,11 +9799,11 @@
9641 }
9642
9643 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
9644 if (retval == JIM_OK) {
9645
9646 JimChangeCallFrameId(interp, framePtr);
9647 }
9648 }
9649 }
9650 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
9651 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9725,28 +9883,17 @@
9725 return NULL;
9726 }
9727
9728 ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9729 if (ret != JIM_OK) {
9730 resObjPtr = NULL;
9731 if (ret < 0) {
9732 Jim_SetResultFormatted(interp,
9733 "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9734 }
9735 else {
9736 Jim_SetResultFormatted(interp,
9737 "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9738 }
9739 }
9740 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9741 dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9742 if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9743
9744 JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9745 }
9746
9747 Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9748 }
9749
9750 return resObjPtr;
9751 }
9752
@@ -9843,68 +9990,67 @@
9843 Jim_CallFrame *cf;
9844
9845 if (interp->freeFramesList) {
9846 cf = interp->freeFramesList;
9847 interp->freeFramesList = cf->next;
 
 
 
 
 
 
 
 
 
 
 
9848 }
9849 else {
9850 cf = Jim_Alloc(sizeof(*cf));
9851 cf->vars.table = NULL;
 
 
9852 }
9853
9854 cf->id = interp->callFrameEpoch++;
9855 cf->parent = parent;
9856 cf->level = parent ? parent->level + 1 : 0;
9857 cf->argv = NULL;
9858 cf->argc = 0;
9859 cf->procArgsObjPtr = NULL;
9860 cf->procBodyObjPtr = NULL;
9861 cf->next = NULL;
9862 cf->staticVars = NULL;
9863 cf->localCommands = NULL;
9864
9865 cf->nsObj = nsObj;
9866 Jim_IncrRefCount(nsObj);
9867 if (cf->vars.table == NULL)
9868 Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
9869 return cf;
9870 }
9871
9872
9873 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9874 {
9875 cf->id = interp->callFrameEpoch++;
9876 }
9877
9878 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
9879 {
9880
9881 if (localCommands) {
9882 Jim_Obj *cmdNameObj;
9883
9884 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
9885 Jim_HashEntry *he;
9886 Jim_Obj *fqObjName;
 
9887
9888 const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
9889
9890 he = Jim_FindHashEntry(&interp->commands, fqname);
9891
9892 if (he) {
9893 Jim_Cmd *cmd = he->u.val;
9894 if (cmd->prevCmd) {
9895 Jim_Cmd *prevCmd = cmd->prevCmd;
9896 cmd->prevCmd = NULL;
9897
9898
9899 JimDecrCmdRefCount(interp, cmd);
9900
9901
9902 he->u.val = prevCmd;
9903 }
9904 else {
9905 Jim_DeleteHashEntry(&interp->commands, fqname);
9906 Jim_InterpIncrProcEpoch(interp);
9907 }
9908 }
9909 Jim_DecrRefCount(interp, cmdNameObj);
9910 JimFreeQualifiedName(interp, fqObjName);
@@ -9914,47 +10060,45 @@
9914 }
9915 return JIM_OK;
9916 }
9917
9918
9919 #define JIM_FCF_NONE 0
9920 #define JIM_FCF_NOHT 1
9921 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9922 {
 
 
9923 if (cf->procArgsObjPtr)
9924 Jim_DecrRefCount(interp, cf->procArgsObjPtr);
9925 if (cf->procBodyObjPtr)
9926 Jim_DecrRefCount(interp, cf->procBodyObjPtr);
9927 Jim_DecrRefCount(interp, cf->nsObj);
9928 if (!(flags & JIM_FCF_NOHT))
9929 Jim_FreeHashTable(&cf->vars);
9930 else {
9931 int i;
9932 Jim_HashEntry **table = cf->vars.table, *he;
9933
9934 for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
9935 he = table[i];
9936 while (he != NULL) {
9937 Jim_HashEntry *nextEntry = he->next;
9938 Jim_Var *varPtr = (void *)he->u.val;
9939
9940 Jim_DecrRefCount(interp, varPtr->objPtr);
9941 Jim_Free(he->u.val);
9942 Jim_Free((void *)he->key);
9943 Jim_Free(he);
9944 table[i] = NULL;
9945 he = nextEntry;
9946 }
9947 }
9948 cf->vars.used = 0;
9949 }
9950
9951 JimDeleteLocalProcs(interp, cf->localCommands);
9952
9953 cf->next = interp->freeFramesList;
9954 interp->freeFramesList = cf;
9955
9956 }
9957
9958
9959 #ifdef JIM_REFERENCES
9960
@@ -10031,21 +10175,16 @@
10031 NULL,
10032 UpdateStringOfReference,
10033 JIM_TYPE_REFERENCES,
10034 };
10035
10036 void UpdateStringOfReference(struct Jim_Obj *objPtr)
10037 {
10038 int len;
10039 char buf[JIM_REFERENCE_SPACE + 1];
10040 Jim_Reference *refPtr;
10041
10042 refPtr = objPtr->internalRep.refValue.refPtr;
10043 len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10044 objPtr->bytes = Jim_Alloc(len + 1);
10045 memcpy(objPtr->bytes, buf, len + 1);
10046 objPtr->length = len;
10047 }
10048
10049 static int isrefchar(int c)
10050 {
10051 return (c == '_' || isalnum(c));
@@ -10096,11 +10235,11 @@
10096 he = Jim_FindHashEntry(&interp->references, &value);
10097 if (he == NULL) {
10098 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10099 return JIM_ERR;
10100 }
10101 refPtr = he->u.val;
10102
10103 Jim_FreeIntRep(interp, objPtr);
10104 objPtr->typePtr = &referenceObjType;
10105 objPtr->internalRep.refValue.id = value;
10106 objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10279,13 +10418,20 @@
10279 return i;
10280 }
10281
10282 void Jim_FreeInterp(Jim_Interp *i)
10283 {
10284 Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
 
10285 Jim_Obj *objPtr, *nextObjPtr;
10286
 
 
 
 
 
 
10287 Jim_DecrRefCount(i, i->emptyObj);
10288 Jim_DecrRefCount(i, i->trueObj);
10289 Jim_DecrRefCount(i, i->falseObj);
10290 Jim_DecrRefCount(i, i->result);
10291 Jim_DecrRefCount(i, i->stackTrace);
@@ -10300,61 +10446,54 @@
10300 #endif
10301 Jim_FreeHashTable(&i->packages);
10302 Jim_Free(i->prngState);
10303 Jim_FreeHashTable(&i->assocData);
10304
10305
10306 while (cf) {
10307 prevcf = cf->parent;
10308 JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10309 cf = prevcf;
10310 }
10311 if (i->liveList != NULL) {
10312 objPtr = i->liveList;
10313
10314 printf(JIM_NL "-------------------------------------" JIM_NL);
10315 printf("Objects still in the free list:" JIM_NL);
10316 while (objPtr) {
10317 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10318
10319 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10320 printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10321 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10322 }
10323 else {
10324 printf("%p (%d) %-10s: '%s'" JIM_NL,
10325 (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
10326 }
10327 if (objPtr->typePtr == &sourceObjType) {
10328 printf("FILE %s LINE %d" JIM_NL,
10329 Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
10330 objPtr->internalRep.sourceValue.lineNumber);
10331 }
10332 objPtr = objPtr->nextObjPtr;
10333 }
10334 printf("-------------------------------------" JIM_NL JIM_NL);
10335 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10336 }
 
 
10337
10338 objPtr = i->freeList;
10339 while (objPtr) {
10340 nextObjPtr = objPtr->nextObjPtr;
10341 Jim_Free(objPtr);
10342 objPtr = nextObjPtr;
10343 }
 
10344
10345 cf = i->freeFramesList;
10346 while (cf) {
10347 nextcf = cf->next;
10348 if (cf->vars.table != NULL)
10349 Jim_Free(cf->vars.table);
10350 Jim_Free(cf);
10351 cf = nextcf;
10352 }
10353 #ifdef jim_ext_load
10354 Jim_FreeLoadHandles(i);
10355 #endif
10356
10357
10358 Jim_Free(i);
10359 }
10360
@@ -10455,11 +10594,10 @@
10455 interp->addStackTrace = 1;
10456 }
10457 }
10458 }
10459
10460
10461 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
10462 Jim_Obj *fileNameObj, int linenr)
10463 {
10464 if (strcmp(procname, "unknown") == 0) {
10465 procname = "";
@@ -10513,12 +10651,11 @@
10513 void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
10514 {
10515 Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
10516
10517 if (entryPtr != NULL) {
10518 AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10519
10520 return assocEntryPtr->data;
10521 }
10522 return NULL;
10523 }
10524
@@ -10552,20 +10689,44 @@
10552 };
10553
10554
10555 static void UpdateStringOfInt(struct Jim_Obj *objPtr)
10556 {
10557 int len;
10558 char buf[JIM_INTEGER_SPACE + 1];
 
 
10559
10560 len = JimWideToString(buf, JimWideValue(objPtr));
10561 objPtr->bytes = Jim_Alloc(len + 1);
10562 memcpy(objPtr->bytes, buf, len + 1);
10563 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10564 }
10565
10566 int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10567 {
10568 jim_wide wideValue;
10569 const char *str;
10570
10571 if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10653,22 +10814,65 @@
10653 NULL,
10654 UpdateStringOfDouble,
10655 JIM_TYPE_NONE,
10656 };
10657
10658 void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10659 {
10660 int len;
10661 char buf[JIM_DOUBLE_SPACE + 1];
10662
10663 len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10664 objPtr->bytes = Jim_Alloc(len + 1);
10665 memcpy(objPtr->bytes, buf, len + 1);
10666 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10667 }
10668
10669 int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10670 {
10671 double doubleValue;
10672 jim_wide wideValue;
10673 const char *str;
10674
@@ -10876,15 +11080,15 @@
10876 return JIM_ELESTR_SIMPLE;
10877 }
10878 return JIM_ELESTR_QUOTE;
10879 }
10880
10881 static int BackslashQuoteString(const char *s, char *q)
10882 {
10883 char *p = q;
10884
10885 while (*s) {
10886 switch (*s) {
10887 case ' ':
10888 case '$':
10889 case '"':
10890 case '[':
@@ -10996,11 +11200,11 @@
10996 case JIM_ELESTR_QUOTE:
10997 if (i == 0 && strRep[0] == '#') {
10998 *p++ = '\\';
10999 realLength++;
11000 }
11001 qlen = BackslashQuoteString(strRep, p);
11002 p += qlen;
11003 realLength += qlen;
11004 break;
11005 }
11006
@@ -11032,11 +11236,11 @@
11032
11033 if (objPtr->typePtr == &listObjType) {
11034 return JIM_OK;
11035 }
11036
11037 if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11038 Jim_Obj **listObjPtrPtr;
11039 int len;
11040 int i;
11041
11042 listObjPtrPtr = JimDictPairs(objPtr, &len);
@@ -11136,15 +11340,17 @@
11136 Jim_Interp *interp;
11137 enum {
11138 JIM_LSORT_ASCII,
11139 JIM_LSORT_NOCASE,
11140 JIM_LSORT_INTEGER,
 
11141 JIM_LSORT_COMMAND
11142 } type;
11143 int order;
11144 int index;
11145 int indexed;
 
11146 int (*subfn)(Jim_Obj **, Jim_Obj **);
11147 };
11148
11149 static struct lsort_info *sort_info;
11150
@@ -11179,10 +11385,27 @@
11179 longjmp(sort_info->jmpbuf, JIM_ERR);
11180 }
11181
11182 return JimSign(lhs - rhs) * sort_info->order;
11183 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11184
11185 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11186 {
11187 Jim_Obj *compare_script;
11188 int rc;
@@ -11201,10 +11424,34 @@
11201 }
11202
11203 return JimSign(ret) * sort_info->order;
11204 }
11205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11206
11207 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
11208 {
11209 struct lsort_info *prev_info;
11210
@@ -11212,11 +11459,11 @@
11212 int (*fn) (Jim_Obj **, Jim_Obj **);
11213 Jim_Obj **vector;
11214 int len;
11215 int rc;
11216
11217 JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11218 SetListFromAny(interp, listObjPtr);
11219
11220
11221 prev_info = sort_info;
11222 sort_info = info;
@@ -11231,10 +11478,13 @@
11231 fn = ListSortStringNoCase;
11232 break;
11233 case JIM_LSORT_INTEGER:
11234 fn = ListSortInteger;
11235 break;
 
 
 
11236 case JIM_LSORT_COMMAND:
11237 fn = ListSortCommand;
11238 break;
11239 default:
11240 fn = NULL;
@@ -11247,12 +11497,17 @@
11247 fn = ListSortIndexHelper;
11248 }
11249
11250 if ((rc = setjmp(info->jmpbuf)) == 0) {
11251 qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
 
 
 
 
 
 
11252 }
11253 Jim_InvalidateStringRep(listObjPtr);
11254 sort_info = prev_info;
11255
11256 return rc;
11257 }
11258
@@ -11377,11 +11632,11 @@
11377 listPtr->internalRep.listValue.ele[idx] = newObjPtr;
11378 Jim_IncrRefCount(newObjPtr);
11379 return JIM_OK;
11380 }
11381
11382 int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11383 Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
11384 {
11385 Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
11386 int shared, i, idx;
11387
@@ -11425,14 +11680,11 @@
11425 int i;
11426 int listLen = Jim_ListLength(interp, listObjPtr);
11427 Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
11428
11429 for (i = 0; i < listLen; ) {
11430 Jim_Obj *objPtr;
11431
11432 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11433 Jim_AppendObj(interp, resObjPtr, objPtr);
11434 if (++i != listLen) {
11435 Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
11436 }
11437 }
11438 return resObjPtr;
@@ -11458,43 +11710,42 @@
11458 int len = 0, objLen;
11459 char *bytes, *p;
11460
11461
11462 for (i = 0; i < objc; i++) {
11463 Jim_GetString(objv[i], &objLen);
11464 len += objLen;
11465 }
11466 if (objc)
11467 len += objc - 1;
11468
11469 p = bytes = Jim_Alloc(len + 1);
11470 for (i = 0; i < objc; i++) {
11471 const char *s = Jim_GetString(objv[i], &objLen);
11472
11473
11474 while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11475 s++;
11476 objLen--;
11477 len--;
11478 }
11479
11480 while (objLen && (s[objLen - 1] == ' ' ||
11481 s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11482
11483 if (objLen > 1 && s[objLen - 2] == '\\') {
11484 break;
11485 }
11486 objLen--;
11487 len--;
11488 }
11489 memcpy(p, s, objLen);
11490 p += objLen;
11491 if (objLen && i + 1 != objc) {
11492 *p++ = ' ';
11493 }
11494 else if (i + 1 != objc) {
11495 len--;
 
11496 }
11497 }
11498 *p = '\0';
11499 return Jim_NewStringObjNoAlloc(interp, bytes, len);
11500 }
@@ -11534,20 +11785,26 @@
11534
11535 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
11536 {
11537 return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
11538 }
 
 
 
 
 
 
11539
11540 static void JimObjectHTKeyValDestructor(void *interp, void *val)
11541 {
11542 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11543 }
11544
11545 static const Jim_HashTableType JimDictHashTableType = {
11546 JimObjectHTHashFunction,
11547 NULL,
11548 NULL,
11549 JimObjectHTKeyCompare,
11550 JimObjectHTKeyValDestructor,
11551 JimObjectHTKeyValDestructor
11552 };
11553
@@ -11580,16 +11837,11 @@
11580 if (ht->size != 0)
11581 Jim_ExpandHashTable(dupHt, ht->size);
11582
11583 JimInitHashTableIterator(ht, &htiter);
11584 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11585 const Jim_Obj *keyObjPtr = he->key;
11586 Jim_Obj *valObjPtr = he->u.val;
11587
11588 Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11589 Jim_IncrRefCount(valObjPtr);
11590 Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11591 }
11592
11593 dupPtr->internalRep.ptr = dupHt;
11594 dupPtr->typePtr = &dictObjType;
11595 }
@@ -11607,12 +11859,12 @@
11607
11608 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11609 JimInitHashTableIterator(ht, &htiter);
11610 i = 0;
11611 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11612 objv[i++] = (Jim_Obj *)he->key;
11613 objv[i++] = he->u.val;
11614 }
11615 *len = i;
11616 return objv;
11617 }
11618
@@ -11620,10 +11872,11 @@
11620 {
11621
11622 int len;
11623 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11624
 
11625 JimMakeListStringRep(objPtr, objv, len);
11626
11627 Jim_Free(objv);
11628 }
11629
@@ -11633,11 +11886,13 @@
11633
11634 if (objPtr->typePtr == &dictObjType) {
11635 return JIM_OK;
11636 }
11637
11638 Jim_String(objPtr);
 
 
11639
11640
11641 listlen = Jim_ListLength(interp, objPtr);
11642 if (listlen % 2) {
11643 Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11650,28 +11905,14 @@
11650
11651 ht = Jim_Alloc(sizeof(*ht));
11652 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
11653
11654 for (i = 0; i < listlen; i += 2) {
11655 Jim_Obj *keyObjPtr;
11656 Jim_Obj *valObjPtr;
11657
11658 Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11659 Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11660
11661 Jim_IncrRefCount(keyObjPtr);
11662 Jim_IncrRefCount(valObjPtr);
11663
11664 if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11665 Jim_HashEntry *he;
11666
11667 he = Jim_FindHashEntry(ht, keyObjPtr);
11668 Jim_DecrRefCount(interp, keyObjPtr);
11669
11670 Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11671 he->u.val = valObjPtr;
11672 }
11673 }
11674
11675 Jim_FreeIntRep(interp, objPtr);
11676 objPtr->typePtr = &dictObjType;
11677 objPtr->internalRep.ptr = ht;
@@ -11688,31 +11929,23 @@
11688 Jim_HashTable *ht = objPtr->internalRep.ptr;
11689
11690 if (valueObjPtr == NULL) {
11691 return Jim_DeleteHashEntry(ht, keyObjPtr);
11692 }
11693 Jim_IncrRefCount(keyObjPtr);
11694 Jim_IncrRefCount(valueObjPtr);
11695 if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11696
11697 Jim_DecrRefCount(interp, keyObjPtr);
11698 }
11699 return JIM_OK;
11700 }
11701
11702 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
11703 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
11704 {
11705 int retcode;
11706
11707 JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
11708 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
11709 return JIM_ERR;
11710 }
11711 retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
11712 Jim_InvalidateStringRep(objPtr);
11713 return retcode;
11714 }
11715
11716 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
11717 {
11718 Jim_Obj *objPtr;
@@ -11839,10 +12072,11 @@
11839 }
11840 objPtr = Jim_NewDictObj(interp, NULL, 0);
11841 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
11842 }
11843 }
 
11844 Jim_InvalidateStringRep(objPtr);
11845 Jim_InvalidateStringRep(varObjPtr);
11846 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
11847 goto err;
11848 }
@@ -11864,28 +12098,29 @@
11864 NULL,
11865 UpdateStringOfIndex,
11866 JIM_TYPE_NONE,
11867 };
11868
11869 void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11870 {
11871 int len;
11872 char buf[JIM_INTEGER_SPACE + 1];
11873
11874 if (objPtr->internalRep.intValue >= 0)
11875 len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11876 else if (objPtr->internalRep.intValue == -1)
11877 len = sprintf(buf, "end");
11878 else {
11879 len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
 
 
 
 
 
 
 
 
11880 }
11881 objPtr->bytes = Jim_Alloc(len + 1);
11882 memcpy(objPtr->bytes, buf, len + 1);
11883 objPtr->length = len;
11884 }
11885
11886 int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
11887 {
11888 int idx, end = 0;
11889 const char *str;
11890 char *endptr;
11891
@@ -11953,14 +12188,17 @@
11953 {
11954
11955 if (objPtr->typePtr == &intObjType) {
11956 jim_wide val = JimWideValue(objPtr);
11957
11958 if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11959 *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11960 return JIM_OK;
11961 }
 
 
 
11962 }
11963 if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
11964 return JIM_ERR;
11965 *indexPtr = objPtr->internalRep.intValue;
11966 return JIM_OK;
@@ -11980,12 +12218,10 @@
11980 NULL
11981 };
11982
11983 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
11984
11985 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11986
11987 static const Jim_ObjType returnCodeObjType = {
11988 "return-code",
11989 NULL,
11990 NULL,
11991 NULL,
@@ -12000,11 +12236,11 @@
12000 else {
12001 return jimReturnCodes[code];
12002 }
12003 }
12004
12005 int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12006 {
12007 int returnCode;
12008 jim_wide wideValue;
12009
12010
@@ -12152,24 +12388,21 @@
12152 return e->stack[--e->stacklen];
12153 }
12154
12155 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12156 {
12157 int intresult = 0;
12158 int rc = JIM_OK;
12159 Jim_Obj *A = ExprPop(e);
12160 double dA, dC = 0;
12161 jim_wide wA, wC = 0;
12162
12163 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12164 intresult = 1;
12165
12166 switch (e->opcode) {
12167 case JIM_EXPROP_FUNC_INT:
12168 wC = wA;
12169 break;
12170 case JIM_EXPROP_FUNC_ROUND:
 
12171 wC = wA;
12172 break;
12173 case JIM_EXPROP_FUNC_DOUBLE:
12174 dC = wA;
12175 intresult = 0;
@@ -12178,13 +12411,10 @@
12178 wC = wA >= 0 ? wA : -wA;
12179 break;
12180 case JIM_EXPROP_UNARYMINUS:
12181 wC = -wA;
12182 break;
12183 case JIM_EXPROP_UNARYPLUS:
12184 wC = wA;
12185 break;
12186 case JIM_EXPROP_NOT:
12187 wC = !wA;
12188 break;
12189 default:
12190 abort();
@@ -12192,31 +12422,29 @@
12192 }
12193 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12194 switch (e->opcode) {
12195 case JIM_EXPROP_FUNC_INT:
12196 wC = dA;
12197 intresult = 1;
12198 break;
12199 case JIM_EXPROP_FUNC_ROUND:
12200 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12201 intresult = 1;
12202 break;
12203 case JIM_EXPROP_FUNC_DOUBLE:
 
12204 dC = dA;
 
12205 break;
12206 case JIM_EXPROP_FUNC_ABS:
12207 dC = dA >= 0 ? dA : -dA;
 
12208 break;
12209 case JIM_EXPROP_UNARYMINUS:
12210 dC = -dA;
12211 break;
12212 case JIM_EXPROP_UNARYPLUS:
12213 dC = dA;
12214 break;
12215 case JIM_EXPROP_NOT:
12216 wC = !dA;
12217 intresult = 1;
12218 break;
12219 default:
12220 abort();
12221 }
12222 }
@@ -12427,11 +12655,11 @@
12427
12428
12429
12430 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12431 {
12432 int intresult = 0;
12433 int rc = JIM_OK;
12434 double dA, dB, dC = 0;
12435 jim_wide wA, wB, wC = 0;
12436
12437 Jim_Obj *B = ExprPop(e);
@@ -12441,12 +12669,10 @@
12441 (B->typePtr != &doubleObjType || B->bytes) &&
12442 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12443
12444
12445
12446 intresult = 1;
12447
12448 switch (e->opcode) {
12449 case JIM_EXPROP_POW:
12450 case JIM_EXPROP_FUNC_POW:
12451 wC = JimPowWide(wA, wB);
12452 break;
@@ -12496,10 +12722,11 @@
12496 default:
12497 abort();
12498 }
12499 }
12500 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
 
12501 switch (e->opcode) {
12502 case JIM_EXPROP_POW:
12503 case JIM_EXPROP_FUNC_POW:
12504 #ifdef JIM_MATH_FUNCTIONS
12505 dC = pow(dA, dB);
@@ -12561,12 +12788,10 @@
12561
12562
12563
12564 int i = Jim_StringCompareObj(interp, A, B, 0);
12565
12566 intresult = 1;
12567
12568 switch (e->opcode) {
12569 case JIM_EXPROP_LT:
12570 wC = i < 0;
12571 break;
12572 case JIM_EXPROP_GT:
@@ -12610,15 +12835,11 @@
12610 int listlen;
12611 int i;
12612
12613 listlen = Jim_ListLength(interp, listObjPtr);
12614 for (i = 0; i < listlen; i++) {
12615 Jim_Obj *objPtr;
12616
12617 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12618
12619 if (Jim_StringEqObj(objPtr, valObj)) {
12620 return 1;
12621 }
12622 }
12623 return 0;
12624 }
@@ -12630,23 +12851,16 @@
12630
12631 jim_wide wC;
12632
12633 switch (e->opcode) {
12634 case JIM_EXPROP_STREQ:
12635 case JIM_EXPROP_STRNE: {
12636 int Alen, Blen;
12637 const char *sA = Jim_GetString(A, &Alen);
12638 const char *sB = Jim_GetString(B, &Blen);
12639
12640 if (e->opcode == JIM_EXPROP_STREQ) {
12641 wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12642 }
12643 else {
12644 wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
12645 }
12646 break;
12647 }
12648 case JIM_EXPROP_STRIN:
12649 wC = JimSearchList(interp, B, A);
12650 break;
12651 case JIM_EXPROP_STRNI:
12652 wC = !JimSearchList(interp, B, A);
@@ -12818,96 +13032,98 @@
12818 LAZY_OP,
12819 LAZY_LEFT,
12820 LAZY_RIGHT
12821 };
12822
12823 #define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
 
12824
12825 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12826 OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12827 OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12828 OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12829
12830 OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12831 OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12832
12833 OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12834 OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12835
12836 OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12837 OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12838
12839 OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12840 OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12841 OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12842 OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12843
12844 OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12845 OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12846
12847 OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12848 OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12849 OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12850
12851 OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12852 OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12853 OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12854
12855 OPRINIT("||", 9, 2, NULL, LAZY_OP),
12856 OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12857 OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12858
12859 OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12860 OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12861 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12862
12863 OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12864 OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12865 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12866
12867 OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12868
12869 OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12870 OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12871
12872 OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12873 OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12874
12875 OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12876 OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12877 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12878 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12879
12880
12881
12882 OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12883 OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12884 OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12885 OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12886 OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12887 OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
12888
12889 #ifdef JIM_MATH_FUNCTIONS
12890 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12891 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12892 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12893 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12894 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12895 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902 OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905 OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
12906 #endif
12907 };
12908 #undef OPRINIT
 
12909
12910 #define JIM_EXPR_OPERATORS_NUM \
12911 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
12912
12913 static int JimParseExpression(struct JimParserCtx *pc)
@@ -12919,13 +13135,16 @@
12919 }
12920 pc->p++;
12921 pc->len--;
12922 }
12923
 
 
 
 
12924 if (pc->len == 0) {
12925 pc->tstart = pc->tend = pc->p;
12926 pc->tline = pc->linenr;
12927 pc->tt = JIM_TT_EOL;
12928 pc->eof = 1;
12929 return JIM_OK;
12930 }
12931 switch (*(pc->p)) {
@@ -12936,12 +13155,11 @@
12936 pc->tt = JIM_TT_SUBEXPR_END;
12937 goto singlechar;
12938 case ',':
12939 pc->tt = JIM_TT_SUBEXPR_COMMA;
12940 singlechar:
12941 pc->tstart = pc->tend = pc->p;
12942 pc->tline = pc->linenr;
12943 pc->p++;
12944 pc->len--;
12945 break;
12946 case '[':
12947 return JimParseCmd(pc);
@@ -12987,82 +13205,44 @@
12987 return JIM_OK;
12988 }
12989
12990 static int JimParseExprNumber(struct JimParserCtx *pc)
12991 {
12992 int allowdot = 1;
12993 int base = 10;
12994
12995
12996 pc->tt = JIM_TT_EXPR_INT;
12997 pc->tstart = pc->p;
12998 pc->tline = pc->linenr;
12999
13000
13001 if (pc->p[0] == '0') {
13002 switch (pc->p[1]) {
13003 case 'x':
13004 case 'X':
13005 base = 16;
13006 allowdot = 0;
13007 pc->p += 2;
13008 pc->len -= 2;
13009 break;
13010 case 'o':
13011 case 'O':
13012 base = 8;
13013 allowdot = 0;
13014 pc->p += 2;
13015 pc->len -= 2;
13016 break;
13017 case 'b':
13018 case 'B':
13019 base = 2;
13020 allowdot = 0;
13021 pc->p += 2;
13022 pc->len -= 2;
13023 break;
13024 }
13025 }
13026
13027 while (isdigit(UCHAR(*pc->p))
13028 || (base == 16 && isxdigit(UCHAR(*pc->p)))
13029 || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
13030 || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
13031 || (allowdot && *pc->p == '.')
13032 ) {
13033 if (*pc->p == '.') {
13034 allowdot = 0;
13035 pc->tt = JIM_TT_EXPR_DOUBLE;
13036 }
13037 pc->p++;
13038 pc->len--;
13039 if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
13040 || isdigit(UCHAR(pc->p[1])))) {
13041 pc->p += 2;
13042 pc->len -= 2;
13043 pc->tt = JIM_TT_EXPR_DOUBLE;
13044 }
13045 }
13046 pc->tend = pc->p - 1;
 
13047 return JIM_OK;
13048 }
13049
13050 static int JimParseExprIrrational(struct JimParserCtx *pc)
13051 {
13052 const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13053 const char **token;
13054
13055 for (token = Tokens; *token != NULL; token++) {
13056 int len = strlen(*token);
13057
13058 if (strncmp(*token, pc->p, len) == 0) {
13059 pc->tstart = pc->p;
13060 pc->tend = pc->p + len - 1;
13061 pc->p += len;
13062 pc->len -= len;
13063 pc->tline = pc->linenr;
13064 pc->tt = JIM_TT_EXPR_DOUBLE;
13065 return JIM_OK;
13066 }
13067 }
13068 return JIM_ERR;
@@ -13102,15 +13282,13 @@
13102 }
13103 if (*p != '(') {
13104 return JIM_ERR;
13105 }
13106 }
13107 pc->tstart = pc->p;
13108 pc->tend = pc->p + bestLen - 1;
13109 pc->p += bestLen;
13110 pc->len -= bestLen;
13111 pc->tline = pc->linenr;
13112
13113 pc->tt = bestIdx;
13114 return JIM_OK;
13115 }
13116
@@ -13608,17 +13786,23 @@
13608 }
13609
13610 #ifdef DEBUG_SHOW_EXPR_TOKENS
13611 {
13612 int i;
13613 printf("==== Expr Tokens ====\n");
13614 for (i = 0; i < tokenlist.count; i++) {
13615 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
13616 tokenlist.list[i].len, tokenlist.list[i].token);
13617 }
13618 }
13619 #endif
 
 
 
 
 
 
13620
13621
13622 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
13623
13624
@@ -13665,10 +13849,24 @@
13665 return NULL;
13666 }
13667 }
13668 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13669 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13670
13671 #define JIM_EE_STATICSTACK_LEN 10
13672
13673 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
13674 {
@@ -13688,102 +13886,69 @@
13688 Jim_Obj *objPtr;
13689
13690
13691 switch (expr->len) {
13692 case 1:
13693 if (expr->token[0].type == JIM_TT_EXPR_INT) {
13694 *exprResultPtrPtr = expr->token[0].objPtr;
13695 Jim_IncrRefCount(*exprResultPtrPtr);
13696 return JIM_OK;
13697 }
13698 if (expr->token[0].type == JIM_TT_VAR) {
13699 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13700 if (objPtr) {
13701 *exprResultPtrPtr = objPtr;
13702 Jim_IncrRefCount(*exprResultPtrPtr);
13703 return JIM_OK;
13704 }
13705 }
13706 break;
13707
13708 case 2:
13709 if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13710 jim_wide wideValue;
13711
13712 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13713 if (objPtr && JimIsWide(objPtr)
13714 && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13715 *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13716 Jim_IncrRefCount(*exprResultPtrPtr);
13717 return JIM_OK;
13718 }
13719 }
13720 break;
13721
13722 case 3:
13723 if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13724 || expr->token[1].type == JIM_TT_VAR)) {
13725 switch (expr->token[2].type) {
13726 case JIM_EXPROP_LT:
13727 case JIM_EXPROP_LTE:
13728 case JIM_EXPROP_GT:
13729 case JIM_EXPROP_GTE:
13730 case JIM_EXPROP_NUMEQ:
13731 case JIM_EXPROP_NUMNE:{
13732
13733 jim_wide wideValueA;
13734 jim_wide wideValueB;
13735
13736 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13737 if (objPtr && JimIsWide(objPtr)
13738 && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13739 if (expr->token[1].type == JIM_TT_VAR) {
13740 objPtr =
13741 Jim_GetVariable(interp, expr->token[1].objPtr,
13742 JIM_NONE);
13743 }
13744 else {
13745 objPtr = expr->token[1].objPtr;
13746 }
13747 if (objPtr && JimIsWide(objPtr)
13748 && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13749 int cmpRes;
13750
13751 switch (expr->token[2].type) {
13752 case JIM_EXPROP_LT:
13753 cmpRes = wideValueA < wideValueB;
13754 break;
13755 case JIM_EXPROP_LTE:
13756 cmpRes = wideValueA <= wideValueB;
13757 break;
13758 case JIM_EXPROP_GT:
13759 cmpRes = wideValueA > wideValueB;
13760 break;
13761 case JIM_EXPROP_GTE:
13762 cmpRes = wideValueA >= wideValueB;
13763 break;
13764 case JIM_EXPROP_NUMEQ:
13765 cmpRes = wideValueA == wideValueB;
13766 break;
13767 case JIM_EXPROP_NUMNE:
13768 cmpRes = wideValueA != wideValueB;
13769 break;
13770 default:
13771 cmpRes = 0;
13772 }
13773 *exprResultPtrPtr =
13774 cmpRes ? interp->trueObj : interp->falseObj;
13775 Jim_IncrRefCount(*exprResultPtrPtr);
13776 return JIM_OK;
13777 }
13778 }
13779 }
13780 }
13781 }
13782 break;
13783 }
13784 }
13785 #endif
13786
13787 expr->inUse++;
13788
13789
@@ -13952,16 +14117,13 @@
13952 memcpy(newVec, srcPtr->internalRep.ptr, size);
13953 dupPtr->internalRep.ptr = newVec;
13954 dupPtr->typePtr = &scanFmtStringObjType;
13955 }
13956
13957 void UpdateStringOfScanFmt(Jim_Obj *objPtr)
13958 {
13959 char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13960
13961 objPtr->bytes = Jim_StrDup(bytes);
13962 objPtr->length = strlen(bytes);
13963 }
13964
13965
13966 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
13967 {
@@ -14171,11 +14333,10 @@
14171 Jim_Obj *tmpObj = NULL;
14172
14173
14174 *valObjPtr = 0;
14175 if (descr->prefix) {
14176
14177 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14178
14179 if (isspace(UCHAR(descr->prefix[i])))
14180 while (pos < strLen && isspace(UCHAR(str[pos])))
14181 ++pos;
@@ -14512,34 +14673,55 @@
14512 }
14513
14514 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14515 {
14516 int retcode;
14517 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14518
14519 if (cmdPtr == NULL) {
14520 return JimUnknown(interp, objc, objv);
 
 
 
14521 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14522 if (interp->evalDepth == interp->maxEvalDepth) {
14523 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14524 return JIM_ERR;
 
14525 }
14526 interp->evalDepth++;
14527
14528
14529 JimIncrCmdRefCount(cmdPtr);
14530 Jim_SetEmptyResult(interp);
14531 if (cmdPtr->isproc) {
14532 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14533 }
14534 else {
14535 interp->cmdPrivData = cmdPtr->u.native.privData;
14536 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14537 }
14538 JimDecrCmdRefCount(interp, cmdPtr);
14539 interp->evalDepth--;
14540
 
 
 
14541 return retcode;
14542 }
14543
14544 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14545 {
@@ -14717,10 +14899,15 @@
14717 objPtr->typePtr = &interpolatedObjType;
14718 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14719 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14720 Jim_IncrRefCount(intv[2]);
14721 }
 
 
 
 
 
14722
14723 s = objPtr->bytes = Jim_Alloc(totlen + 1);
14724 objPtr->length = totlen;
14725 for (i = 0; i < tokens; i++) {
14726 if (intv[i]) {
@@ -14772,10 +14959,14 @@
14772 return JimEvalObjList(interp, scriptObjPtr);
14773 }
14774
14775 Jim_IncrRefCount(scriptObjPtr);
14776 script = Jim_GetScript(interp, scriptObjPtr);
 
 
 
 
14777
14778 Jim_SetEmptyResult(interp);
14779
14780 token = script->token;
14781
@@ -15046,26 +15237,20 @@
15046 retcode = Jim_EvalObj(interp, scriptObj);
15047 }
15048
15049
15050 interp->framePtr = interp->framePtr->parent;
15051 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15052 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15053 }
15054 else {
15055 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15056 }
15057
15058 return retcode;
15059 }
15060 #endif
15061
15062 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
15063 {
15064 Jim_CallFrame *callFramePtr;
15065 int i, d, retcode, optargs;
15066 Jim_Stack *localCommands;
15067 ScriptObj *script;
15068
15069
15070 if (argc - 1 < cmd->u.proc.reqArity ||
15071 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15145,37 +15330,42 @@
15145
15146
15147 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15148
15149 badargset:
 
15150
15151
15152 localCommands = callFramePtr->localCommands;
15153 callFramePtr->localCommands = NULL;
15154
15155 interp->framePtr = interp->framePtr->parent;
15156 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15157 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15158 }
15159 else {
15160 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15161 }
15162
15163
15164 while (retcode == JIM_EVAL) {
15165 Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15166
15167 Jim_IncrRefCount(resultScriptObjPtr);
15168
15169 JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15170
15171 retcode = JimEvalObjList(interp, resultScriptObjPtr);
15172 if (retcode == JIM_RETURN) {
15173 interp->returnLevel++;
15174 }
15175 Jim_DecrRefCount(interp, resultScriptObjPtr);
15176 }
 
 
 
 
 
 
 
 
15177
15178 if (retcode == JIM_RETURN) {
15179 if (--interp->returnLevel <= 0) {
15180 retcode = interp->returnCode;
15181 interp->returnCode = JIM_OK;
@@ -15187,13 +15377,10 @@
15187 Jim_DecrRefCount(interp, interp->errorProc);
15188 interp->errorProc = argv[0];
15189 Jim_IncrRefCount(interp->errorProc);
15190 }
15191
15192
15193 JimDeleteLocalProcs(interp, localCommands);
15194
15195 return retcode;
15196 }
15197
15198 int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
15199 {
@@ -15261,11 +15448,10 @@
15261 Jim_Obj *scriptObjPtr;
15262 Jim_Obj *prevScriptObj;
15263 struct stat sb;
15264 int retcode;
15265 int readlen;
15266 struct JimParseResult result;
15267
15268 if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
15269 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
15270 return JIM_ERR;
15271 }
@@ -15288,31 +15474,13 @@
15288 scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
15289 JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
15290 Jim_IncrRefCount(scriptObjPtr);
15291
15292
15293 if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15294 const char *msg;
15295 char linebuf[20];
15296
15297 switch (result.missing) {
15298 case '[':
15299 msg = "unmatched \"[\"";
15300 break;
15301 case '{':
15302 msg = "missing close-brace";
15303 break;
15304 case '"':
15305 default:
15306 msg = "missing quote";
15307 break;
15308 }
15309
15310 snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15311
15312 Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15313 msg, filename, linebuf);
15314 Jim_DecrRefCount(interp, scriptObjPtr);
15315 return JIM_ERR;
15316 }
15317
15318 prevScriptObj = interp->currentScriptObj;
@@ -15475,11 +15643,11 @@
15475 }
15476
15477 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15478 Jim_HashEntry *he, int type);
15479
15480 #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15481
15482 static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
15483 JimHashtableIteratorCallbackType *callback, int type)
15484 {
15485 Jim_HashEntry *he;
@@ -15510,11 +15678,11 @@
15510 #define JIM_CMDLIST_CHANNELS 2
15511
15512 static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15513 Jim_HashEntry *he, int type)
15514 {
15515 Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15516 Jim_Obj *objPtr;
15517
15518 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15519
15520 return;
@@ -15543,11 +15711,11 @@
15543 #define JIM_VARLIST_VALUES 0x1000
15544
15545 static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15546 Jim_HashEntry *he, int type)
15547 {
15548 Jim_Var *varPtr = (Jim_Var *)he->u.val;
15549
15550 if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
15551 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
15552 if (type & JIM_VARLIST_VALUES) {
15553 Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15865,11 +16033,11 @@
15865
15866 expr = JimGetExpression(interp, argv[2]);
15867 incrScript = Jim_GetScript(interp, argv[3]);
15868
15869
15870 if (incrScript->len != 3 || !expr || expr->len != 3) {
15871 goto evalstart;
15872 }
15873
15874 if (incrScript->token[1].type != JIM_TT_ESC ||
15875 expr->token[0].type != JIM_TT_VAR ||
@@ -16088,11 +16256,11 @@
16088 }
16089
16090
16091 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16092 {
16093 int result = JIM_ERR;
16094 int i, numargs;
16095 Jim_ListIter twoiters[2];
16096 Jim_ListIter *iters;
16097 Jim_Obj *script;
16098 Jim_Obj *resultObj;
@@ -16111,13 +16279,16 @@
16111 iters = Jim_Alloc(numargs * sizeof(*iters));
16112 }
16113 for (i = 0; i < numargs; i++) {
16114 JimListIterInit(&iters[i], argv[i + 1]);
16115 if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16116 Jim_SetResultString(interp, "foreach varlist is empty", -1);
16117 return JIM_ERR;
16118 }
 
 
 
 
16119 }
16120
16121 if (doMap) {
16122 resultObj = Jim_NewListObj(interp, NULL, 0);
16123 }
@@ -16430,12 +16601,12 @@
16430 {
16431 Jim_Obj *objPtr, *listObjPtr;
16432 int i;
16433 int idx;
16434
16435 if (argc < 3) {
16436 Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16437 return JIM_ERR;
16438 }
16439 objPtr = argv[1];
16440 Jim_IncrRefCount(objPtr);
16441 for (i = 2; i < argc; i++) {
@@ -16547,14 +16718,13 @@
16547 Jim_IncrRefCount(commandObj);
16548 }
16549
16550 listlen = Jim_ListLength(interp, argv[0]);
16551 for (i = 0; i < listlen; i++) {
16552 Jim_Obj *objPtr;
16553 int eq = 0;
 
16554
16555 Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
16556 switch (opt_match) {
16557 case OPT_EXACT:
16558 eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
16559 break;
16560
@@ -16744,29 +16914,27 @@
16744 if (argc < 3) {
16745 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16746 return JIM_ERR;
16747 }
16748 else if (argc == 3) {
 
16749 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16750 return JIM_ERR;
16751 Jim_SetResult(interp, argv[2]);
16752 return JIM_OK;
16753 }
16754 if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16755 == JIM_ERR)
16756 return JIM_ERR;
16757 return JIM_OK;
16758 }
16759
16760
16761 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
16762 {
16763 static const char * const options[] = {
16764 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16765 };
16766 enum
16767 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
16768 Jim_Obj *resObj;
16769 int i;
16770 int retCode;
16771
16772 struct lsort_info info;
@@ -16777,17 +16945,18 @@
16777 }
16778
16779 info.type = JIM_LSORT_ASCII;
16780 info.order = 1;
16781 info.indexed = 0;
 
16782 info.command = NULL;
16783 info.interp = interp;
16784
16785 for (i = 1; i < (argc - 1); i++) {
16786 int option;
16787
16788 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
16789 != JIM_OK)
16790 return JIM_ERR;
16791 switch (option) {
16792 case OPT_ASCII:
16793 info.type = JIM_LSORT_ASCII;
@@ -16796,16 +16965,22 @@
16796 info.type = JIM_LSORT_NOCASE;
16797 break;
16798 case OPT_INTEGER:
16799 info.type = JIM_LSORT_INTEGER;
16800 break;
 
 
 
16801 case OPT_INCREASING:
16802 info.order = 1;
16803 break;
16804 case OPT_DECREASING:
16805 info.order = -1;
16806 break;
 
 
 
16807 case OPT_COMMAND:
16808 if (i >= (argc - 2)) {
16809 Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
16810 return JIM_ERR;
16811 }
@@ -16915,20 +17090,20 @@
16915 static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
16916 {
16917 if (argc >= 2) {
16918 int retcode;
16919 Jim_CallFrame *savedCallFrame, *targetCallFrame;
16920 Jim_Obj *objPtr;
16921 const char *str;
16922
16923
16924 savedCallFrame = interp->framePtr;
16925
16926
16927 str = Jim_String(argv[1]);
16928 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16929 targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
16930 argc--;
16931 argv++;
16932 }
16933 else {
16934 targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16935,25 +17110,25 @@
16935 }
16936 if (targetCallFrame == NULL) {
16937 return JIM_ERR;
16938 }
16939 if (argc < 2) {
16940 argv--;
16941 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
16942 return JIM_ERR;
16943 }
16944
16945 interp->framePtr = targetCallFrame;
 
 
 
16946 if (argc == 2) {
16947 retcode = Jim_EvalObj(interp, argv[1]);
16948 }
16949 else {
16950 objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16951 Jim_IncrRefCount(objPtr);
16952 retcode = Jim_EvalObj(interp, objPtr);
16953 Jim_DecrRefCount(interp, objPtr);
16954 }
 
16955 interp->framePtr = savedCallFrame;
16956 return retcode;
16957 }
16958 else {
16959 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17064,12 +17239,39 @@
17064 }
17065
17066
17067 static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17068 {
17069 Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17070 return JIM_EVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17071 }
17072
17073 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17074 {
17075 Jim_Obj *cmdList;
@@ -17354,11 +17556,11 @@
17354 for (i = 0; i < numMaps; i += 2) {
17355 Jim_Obj *objPtr;
17356 const char *k;
17357 int kl;
17358
17359 Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17360 k = Jim_String(objPtr);
17361 kl = Jim_Utf8Length(interp, objPtr);
17362
17363 if (strLen >= kl && kl) {
17364 int rc;
@@ -17366,12 +17568,11 @@
17366 if (rc == 0) {
17367 if (noMatchStart) {
17368 Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
17369 noMatchStart = NULL;
17370 }
17371 Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17372 Jim_AppendObj(interp, resultObjPtr, objPtr);
17373 str += utf8_index(str, kl);
17374 strLen -= kl;
17375 break;
17376 }
17377 }
@@ -17851,15 +18052,17 @@
17851
17852 exitCode = JIM_SIGNAL;
17853 }
17854 else {
17855 exitCode = Jim_EvalObj(interp, argv[0]);
 
 
17856 }
17857 interp->signal_level -= sig;
17858
17859
17860 if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
17861
17862 return exitCode;
17863 }
17864
17865 if (sig && exitCode == JIM_SIGNAL) {
@@ -18009,11 +18212,11 @@
18009 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18010
18011 JimInitHashTableIterator(&interp->references, &htiter);
18012 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18013 char buf[JIM_REFERENCE_SPACE + 1];
18014 Jim_Reference *refPtr = he->u.val;
18015 const unsigned long *refId = he->key;
18016
18017 JimFormatReference(buf, refPtr, *refId);
18018 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18019 }
@@ -18043,11 +18246,11 @@
18043
18044 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18045 {
18046 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18047 if (type & JIM_DICTMATCH_VALUES) {
18048 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18049 }
18050 }
18051
18052 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18053 JimDictMatchCallbackType *callback, int type)
@@ -18092,21 +18295,65 @@
18092 return -1;
18093 }
18094 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18095 }
18096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18097
18098 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18099 {
18100 Jim_Obj *objPtr;
18101 int option;
18102 static const char * const options[] = {
18103 "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
 
 
18104 };
18105 enum
18106 {
18107 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
 
 
18108 };
18109
18110 if (argc < 2) {
18111 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18112 return JIM_ERR;
@@ -18117,11 +18364,11 @@
18117 }
18118
18119 switch (option) {
18120 case OPT_GET:
18121 if (argc < 3) {
18122 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18123 return JIM_ERR;
18124 }
18125 if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
18126 JIM_ERRMSG) != JIM_OK) {
18127 return JIM_ERR;
@@ -18134,82 +18381,87 @@
18134 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
18135 return JIM_ERR;
18136 }
18137 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
18138
18139 case OPT_EXIST:
18140 if (argc < 3) {
18141 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18142 return JIM_ERR;
18143 }
18144 Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18145 &objPtr, JIM_ERRMSG) == JIM_OK);
18146 return JIM_OK;
 
 
 
 
 
18147
18148 case OPT_UNSET:
18149 if (argc < 4) {
18150 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
18151 return JIM_ERR;
18152 }
18153 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
 
 
 
18154
18155 case OPT_KEYS:
18156 if (argc != 3 && argc != 4) {
18157 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18158 return JIM_ERR;
18159 }
18160 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18161
18162 case OPT_SIZE: {
18163 int size;
18164
18165 if (argc != 3) {
18166 Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18167 return JIM_ERR;
18168 }
18169
18170 size = Jim_DictSize(interp, argv[2]);
18171 if (size < 0) {
18172 return JIM_ERR;
18173 }
18174 Jim_SetResultInt(interp, size);
18175 return JIM_OK;
18176 }
18177
18178 case OPT_MERGE:
18179 if (argc == 2) {
18180 return JIM_OK;
18181 }
18182 else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18183 return JIM_ERR;
18184 }
18185 else {
18186 return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18187 }
18188
18189 case OPT_WITH:
18190 if (argc < 4) {
18191 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18192 return JIM_ERR;
18193 }
18194 else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18195 return JIM_ERR;
18196 }
18197 else {
18198 return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18199 }
18200
18201 case OPT_CREATE:
18202 if (argc % 2) {
18203 Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
18204 return JIM_ERR;
18205 }
18206 objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
18207 Jim_SetResult(interp, objPtr);
18208 return JIM_OK;
 
 
 
 
 
 
 
18209 }
18210 return JIM_ERR;
 
18211 }
18212
18213
18214 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18215 {
@@ -18267,11 +18519,11 @@
18267 };
18268 enum
18269 { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
18270 INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
18271 INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18272 INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18273 };
18274
18275 #ifdef jim_ext_namespace
18276 int nons = 0;
18277
@@ -19047,11 +19299,11 @@
19047 }
19048 }
19049
19050 static const struct {
19051 const char *name;
19052 Jim_CmdProc cmdProc;
19053 } Jim_CoreCommandsTable[] = {
19054 {"alias", Jim_AliasCoreCommand},
19055 {"set", Jim_SetCoreCommand},
19056 {"unset", Jim_UnsetCoreCommand},
19057 {"puts", Jim_PutsCoreCommand},
@@ -19279,10 +19531,12 @@
19279 }
19280
19281 len += extra;
19282 buf = Jim_Alloc(len + 1);
19283 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
 
 
19284
19285 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19286 }
19287
19288
@@ -19530,23 +19784,22 @@
19530
19531 #include <ctype.h>
19532 #include <string.h>
19533
19534
19535 #define JIM_UTF_MAX 3
19536 #define JIM_INTEGER_SPACE 24
19537 #define MAX_FLOAT_WIDTH 320
19538
19539 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
19540 {
19541 const char *span, *format, *formatEnd, *msg;
19542 int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
19543 static const char * const mixedXPG =
19544 "cannot mix \"%\" and \"%n$\" conversion specifiers";
19545 static const char * const badIndex[2] = {
19546 "not enough arguments for all format specifiers",
19547 "\"%n$\" argument index out of range"
19548 };
19549 int formatLen;
19550 Jim_Obj *resultPtr;
19551
19552 char *num_buffer = NULL;
@@ -19555,319 +19808,349 @@
19555 span = format = Jim_GetString(fmtObjPtr, &formatLen);
19556 formatEnd = format + formatLen;
19557 resultPtr = Jim_NewEmptyStringObj(interp);
19558
19559 while (format != formatEnd) {
19560 char *end;
19561 int gotMinus, sawFlag;
19562 int gotPrecision, useShort;
19563 long width, precision;
19564 int newXpg;
19565 int ch;
19566 int step;
19567 int doubleType;
19568 char pad = ' ';
19569 char spec[2*JIM_INTEGER_SPACE + 12];
19570 char *p;
19571
19572 int formatted_chars;
19573 int formatted_bytes;
19574 const char *formatted_buf;
19575
19576 step = utf8_tounicode(format, &ch);
19577 format += step;
19578 if (ch != '%') {
19579 numBytes += step;
19580 continue;
19581 }
19582 if (numBytes) {
19583 Jim_AppendString(interp, resultPtr, span, numBytes);
19584 numBytes = 0;
19585 }
19586
19587
19588 step = utf8_tounicode(format, &ch);
19589 if (ch == '%') {
19590 span = format;
19591 numBytes = step;
19592 format += step;
19593 continue;
19594 }
19595
19596
19597 newXpg = 0;
19598 if (isdigit(ch)) {
19599 int position = strtoul(format, &end, 10);
19600 if (*end == '$') {
19601 newXpg = 1;
19602 objIndex = position - 1;
19603 format = end + 1;
19604 step = utf8_tounicode(format, &ch);
19605 }
19606 }
19607 if (newXpg) {
19608 if (gotSequential) {
19609 msg = mixedXPG;
19610 goto errorMsg;
19611 }
19612 gotXpg = 1;
19613 } else {
19614 if (gotXpg) {
19615 msg = mixedXPG;
19616 goto errorMsg;
19617 }
19618 gotSequential = 1;
19619 }
19620 if ((objIndex < 0) || (objIndex >= objc)) {
19621 msg = badIndex[gotXpg];
19622 goto errorMsg;
19623 }
19624
19625 p = spec;
19626 *p++ = '%';
19627
19628 gotMinus = 0;
19629 sawFlag = 1;
19630 do {
19631 switch (ch) {
19632 case '-':
19633 gotMinus = 1;
19634 break;
19635 case '0':
19636 pad = ch;
19637 break;
19638 case ' ':
19639 case '+':
19640 case '#':
19641 break;
19642 default:
19643 sawFlag = 0;
19644 continue;
19645 }
19646 *p++ = ch;
19647 format += step;
19648 step = utf8_tounicode(format, &ch);
19649 } while (sawFlag);
19650
19651
19652 width = 0;
19653 if (isdigit(ch)) {
19654 width = strtoul(format, &end, 10);
19655 format = end;
19656 step = utf8_tounicode(format, &ch);
19657 } else if (ch == '*') {
19658 if (objIndex >= objc - 1) {
19659 msg = badIndex[gotXpg];
19660 goto errorMsg;
19661 }
19662 if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19663 goto error;
19664 }
19665 if (width < 0) {
19666 width = -width;
19667 if (!gotMinus) {
19668 *p++ = '-';
19669 gotMinus = 1;
19670 }
19671 }
19672 objIndex++;
19673 format += step;
19674 step = utf8_tounicode(format, &ch);
19675 }
19676
19677
19678 gotPrecision = precision = 0;
19679 if (ch == '.') {
19680 gotPrecision = 1;
19681 format += step;
19682 step = utf8_tounicode(format, &ch);
19683 }
19684 if (isdigit(ch)) {
19685 precision = strtoul(format, &end, 10);
19686 format = end;
19687 step = utf8_tounicode(format, &ch);
19688 } else if (ch == '*') {
19689 if (objIndex >= objc - 1) {
19690 msg = badIndex[gotXpg];
19691 goto errorMsg;
19692 }
19693 if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19694 goto error;
19695 }
19696
19697
19698 if (precision < 0) {
19699 precision = 0;
19700 }
19701 objIndex++;
19702 format += step;
19703 step = utf8_tounicode(format, &ch);
19704 }
19705
19706
19707 useShort = 0;
19708 if (ch == 'h') {
19709 useShort = 1;
19710 format += step;
19711 step = utf8_tounicode(format, &ch);
19712 } else if (ch == 'l') {
19713
19714 format += step;
19715 step = utf8_tounicode(format, &ch);
19716 if (ch == 'l') {
19717 format += step;
19718 step = utf8_tounicode(format, &ch);
19719 }
19720 }
19721
19722 format += step;
19723 span = format;
19724
19725
19726 if (ch == 'i') {
19727 ch = 'd';
19728 }
19729
19730 doubleType = 0;
19731
19732 switch (ch) {
19733 case '\0':
19734 msg = "format string ended in middle of field specifier";
19735 goto errorMsg;
19736 case 's': {
19737 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19738 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19739 if (gotPrecision && (precision < formatted_chars)) {
19740
19741 formatted_chars = precision;
19742 formatted_bytes = utf8_index(formatted_buf, precision);
19743 }
19744 break;
19745 }
19746 case 'c': {
19747 jim_wide code;
19748
19749 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19750 goto error;
19751 }
19752
19753 formatted_bytes = utf8_fromunicode(spec, code);
19754 formatted_buf = spec;
19755 formatted_chars = 1;
19756 break;
19757 }
19758
19759 case 'e':
19760 case 'E':
19761 case 'f':
19762 case 'g':
19763 case 'G':
19764 doubleType = 1;
19765
19766 case 'd':
19767 case 'u':
19768 case 'o':
19769 case 'x':
19770 case 'X': {
19771 jim_wide w;
19772 double d;
19773 int length;
19774
19775
19776 if (width) {
19777 p += sprintf(p, "%ld", width);
19778 }
19779 if (gotPrecision) {
19780 p += sprintf(p, ".%ld", precision);
19781 }
19782
19783
19784 if (doubleType) {
19785 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19786 goto error;
19787 }
19788 length = MAX_FLOAT_WIDTH;
19789 }
19790 else {
19791 if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19792 goto error;
19793 }
19794 length = JIM_INTEGER_SPACE;
19795 if (useShort) {
19796 *p++ = 'h';
19797 if (ch == 'd') {
19798 w = (short)w;
19799 }
19800 else {
19801 w = (unsigned short)w;
19802 }
19803 }
19804 else {
19805 *p++ = 'l';
19806 #ifdef HAVE_LONG_LONG
19807 if (sizeof(long long) == sizeof(jim_wide)) {
19808 *p++ = 'l';
19809 }
19810 #endif
19811 }
19812 }
19813
19814 *p++ = (char) ch;
19815 *p = '\0';
19816
19817
19818 if (width > length) {
19819 length = width;
19820 }
19821 if (gotPrecision) {
19822 length += precision;
19823 }
19824
19825
19826 if (num_buffer_size < length + 1) {
19827 num_buffer_size = length + 1;
19828 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19829 }
19830
19831 if (doubleType) {
19832 snprintf(num_buffer, length + 1, spec, d);
19833 }
19834 else {
19835 formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19836 }
19837 formatted_chars = formatted_bytes = strlen(num_buffer);
19838 formatted_buf = num_buffer;
19839 break;
19840 }
19841
19842 default: {
19843
19844 spec[0] = ch;
19845 spec[1] = '\0';
19846 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19847 goto error;
19848 }
19849 }
19850
19851 if (!gotMinus) {
19852 while (formatted_chars < width) {
19853 Jim_AppendString(interp, resultPtr, &pad, 1);
19854 formatted_chars++;
19855 }
19856 }
19857
19858 Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19859
19860 while (formatted_chars < width) {
19861 Jim_AppendString(interp, resultPtr, &pad, 1);
19862 formatted_chars++;
19863 }
19864
19865 objIndex += gotSequential;
19866 }
19867 if (numBytes) {
19868 Jim_AppendString(interp, resultPtr, span, numBytes);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19869 }
19870
19871 Jim_Free(num_buffer);
19872 return resultPtr;
19873
@@ -19876,21 +20159,22 @@
19876 error:
19877 Jim_FreeNewObj(interp, resultPtr);
19878 Jim_Free(num_buffer);
19879 return NULL;
19880 }
 
 
 
19881 #include <stdio.h>
19882 #include <ctype.h>
19883 #include <stdlib.h>
19884 #include <string.h>
19885
19886
19887 #if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19888
19889
19890
19891 #define REG_MAX_PAREN 100
 
19892
19893
19894 #define END 0
19895 #define BOL 1
19896 #define EOL 2
@@ -19899,23 +20183,27 @@
19899 #define ANYBUT 5
19900 #define BRANCH 6
19901 #define BACK 7
19902 #define EXACTLY 8
19903 #define NOTHING 9
19904 #define REP 10
19905 #define REPMIN 11
19906 #define REPX 12
19907 #define REPXMIN 13
19908
19909 #define WORDA 15
19910 #define WORDZ 16
19911 #define OPENNC 19
19912 #define OPEN 20
 
19913
19914 #define CLOSE (OPEN+REG_MAX_PAREN+1)
 
 
 
 
19915 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
19916 #define CLOSENC (CLOSE-1)
19917
19918 #define REG_MAGIC 0xFADED00D
19919
19920
19921 #define OP(preg, p) (preg->program[p])
@@ -19925,15 +20213,15 @@
19925
19926
19927
19928 #define FAIL(R,M) { (R)->err = (M); return (M); }
19929 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19930 #define META "^$.[()|?{+*"
19931
19932 #define HASWIDTH 01
19933 #define SIMPLE 02
19934 #define SPSTART 04
19935 #define WORST 0
19936
19937 #define MAX_REP_COUNT 1000000
19938
19939 static int reg(regex_t *preg, int paren , int *flagp );
@@ -19942,13 +20230,13 @@
19942 static int regatom(regex_t *preg, int *flagp );
19943 static int regnode(regex_t *preg, int op );
19944 static int regnext(regex_t *preg, int p );
19945 static void regc(regex_t *preg, int b );
19946 static int reginsert(regex_t *preg, int op, int size, int opnd );
19947 static void regtail_(regex_t *preg, int p, int val, int line );
19948 static void regoptail(regex_t *preg, int p, int val );
19949 #define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
19950
19951 static int reg_range_find(const int *string, int c);
19952 static const char *str_find(const char *string, int c, int nocase);
19953 static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
19954
@@ -19985,13 +20273,10 @@
19985 FAIL(preg, REG_ERR_NULL_ARGUMENT);
19986
19987
19988 preg->cflags = cflags;
19989 preg->regparse = exp;
19990
19991 preg->program = NULL;
19992 preg->proglen = 0;
19993
19994
19995 preg->proglen = (strlen(exp) + 1) * 5;
19996 preg->program = malloc(preg->proglen * sizeof(int));
19997 if (preg->program == NULL)
@@ -20152,11 +20437,10 @@
20152 {
20153 int ret;
20154 char op;
20155 int next;
20156 int flags;
20157 int chain = 0;
20158 int min;
20159 int max;
20160
20161 ret = regatom(preg, &flags);
20162 if (ret == 0)
@@ -20235,11 +20519,11 @@
20235 if (ISMULT(*preg->regparse)) {
20236 preg->err = REG_ERR_NESTED_COUNT;
20237 return 0;
20238 }
20239
20240 return chain ? chain : ret;
20241 }
20242
20243 static void reg_addrange(regex_t *preg, int lower, int upper)
20244 {
20245 if (lower > upper) {
@@ -20329,10 +20613,11 @@
20329 break;
20330 case 'U':
20331 if ((n = parse_hex(s, 8, ch)) > 0) {
20332 s += n;
20333 }
 
20334 case 'x':
20335 if ((n = parse_hex(s, 2, ch)) > 0) {
20336 s += n;
20337 }
20338 break;
@@ -20577,10 +20862,11 @@
20577
20578 static int regnode(regex_t *preg, int op)
20579 {
20580 reg_grow(preg, 2);
20581
 
20582 preg->program[preg->p++] = op;
20583 preg->program[preg->p++] = 0;
20584
20585
20586 return preg->p - 2;
@@ -20606,11 +20892,11 @@
20606 preg->p += size;
20607
20608 return opnd + size;
20609 }
20610
20611 static void regtail_(regex_t *preg, int p, int val, int line )
20612 {
20613 int scan;
20614 int temp;
20615 int offset;
20616
@@ -20669,36 +20955,16 @@
20669 preg->pmatch = pmatch;
20670 preg->nmatch = nmatch;
20671 preg->start = string;
20672
20673
20674 for (scan = OPERAND(1); scan != 0; ) {
20675 switch (OP(preg, scan)) {
20676 case REP:
20677 case REPMIN:
20678 case REPX:
20679 case REPXMIN:
20680 preg->program[scan + 4] = 0;
20681 scan += 5;
20682 break;
20683
20684 case ANYOF:
20685 case ANYBUT:
20686 case EXACTLY:
20687 scan += 2;
20688 while (preg->program[scan++]) {
20689 }
20690 break;
20691
20692 case END:
20693 scan = 0;
20694 break;
20695
20696 default:
20697 scan += 2;
20698 break;
20699 }
20700 }
20701
20702
20703 if (preg->regmust != 0) {
20704 s = string;
@@ -20950,10 +21216,11 @@
20950
20951 static int regmatch(regex_t *preg, int prog)
20952 {
20953 int scan;
20954 int next;
 
20955
20956 scan = prog;
20957
20958 #ifdef DEBUG
20959 if (scan != 0 && regnarrate)
@@ -21038,27 +21305,24 @@
21038 break;
21039 case NOTHING:
21040 break;
21041 case BACK:
21042 break;
21043 case BRANCH: {
21044 const char *save;
21045
21046 if (OP(preg, next) != BRANCH)
21047 next = OPERAND(scan);
21048 else {
21049 do {
21050 save = preg->reginput;
21051 if (regmatch(preg, OPERAND(scan))) {
21052 return(1);
21053 }
21054 preg->reginput = save;
21055 scan = regnext(preg, scan);
21056 } while (scan != 0 && OP(preg, scan) == BRANCH);
21057 return(0);
21058
21059 }
21060 }
21061 break;
21062 case REP:
21063 case REPMIN:
21064 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21066,43 +21330,35 @@
21066 case REPX:
21067 case REPXMIN:
21068 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21069
21070 case END:
21071 return(1);
21072 break;
21073
21074 case OPENNC:
21075 case CLOSENC:
21076 if (regmatch(preg, next)) {
21077 return 1;
21078 }
21079 return 0;
21080
21081 default:
21082 if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21083 const char *save;
21084
21085 save = preg->reginput;
21086
21087 if (regmatch(preg, next)) {
21088 int no;
21089 if (OP(preg, scan) < CLOSE) {
21090 no = OP(preg, scan) - OPEN;
21091 if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
21092 preg->pmatch[no].rm_so = save - preg->start;
21093 }
21094 }
21095 else {
21096 no = OP(preg, scan) - CLOSE;
21097 if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
21098 preg->pmatch[no].rm_eo = save - preg->start;
21099 }
21100 }
21101 return(1);
21102 } else
21103 return(0);
21104 }
21105 return REG_ERR_INTERNAL;
21106 }
21107
21108 scan = next;
@@ -21181,10 +21437,32 @@
21181 if (OP(preg, p) == BACK)
21182 return(p-offset);
21183 else
21184 return(p+offset);
21185 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21186
21187
21188 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
21189 {
21190 static const char *error_strings[] = {
@@ -21359,19 +21637,24 @@
21359 char *Jim_HistoryGetline(const char *prompt)
21360 {
21361 #ifdef USE_LINENOISE
21362 return linenoise(prompt);
21363 #else
 
21364 char *line = malloc(MAX_LINE_LEN);
21365
21366 fputs(prompt, stdout);
21367 fflush(stdout);
21368
21369 if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
21370 free(line);
21371 return NULL;
21372 }
 
 
 
 
21373 return line;
21374 #endif
21375 }
21376
21377 void Jim_HistoryLoad(const char *filename)
@@ -21422,11 +21705,11 @@
21422 snprintf(history_file, history_len, "%s/.jim_history", home);
21423 Jim_HistoryLoad(history_file);
21424 }
21425 #endif
21426
21427 printf("Welcome to Jim version %d.%d" JIM_NL,
21428 JIM_VERSION / 100, JIM_VERSION % 100);
21429 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
21430
21431 while (1) {
21432 Jim_Obj *scriptObjPtr;
@@ -21534,10 +21817,16 @@
21534 }
21535
21536 Jim_SetVariableStr(interp, "argv", listObj);
21537 Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
21538 }
 
 
 
 
 
 
21539
21540 int main(int argc, char *const argv[])
21541 {
21542 int retcode;
21543 Jim_Interp *interp;
@@ -21551,22 +21840,20 @@
21551 interp = Jim_CreateInterp();
21552 Jim_RegisterCoreCommands(interp);
21553
21554
21555 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21556 Jim_MakeErrorMessage(interp);
21557 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21558 }
21559
21560 Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
21561 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
21562 retcode = Jim_initjimshInit(interp);
21563
21564 if (argc == 1) {
21565 if (retcode == JIM_ERR) {
21566 Jim_MakeErrorMessage(interp);
21567 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21568 }
21569 if (retcode != JIM_EXIT) {
21570 JimSetArgv(interp, 0, NULL);
21571 retcode = Jim_InteractivePrompt(interp);
21572 }
@@ -21583,12 +21870,11 @@
21583 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
21584 JimSetArgv(interp, argc - 2, argv + 2);
21585 retcode = Jim_EvalFile(interp, argv[1]);
21586 }
21587 if (retcode == JIM_ERR) {
21588 Jim_MakeErrorMessage(interp);
21589 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21590 }
21591 }
21592 if (retcode == JIM_EXIT) {
21593 retcode = Jim_GetExitCode(interp);
21594 }
21595
--- 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
@@ -47,10 +47,14 @@
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
@@ -106,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);
@@ -125,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
@@ -135,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
@@ -199,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
@@ -266,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
@@ -289,35 +303,35 @@
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
@@ -341,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;
@@ -379,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;
@@ -453,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;
@@ -474,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;
@@ -589,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
@@ -608,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
@@ -739,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,
@@ -804,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
@@ -869,19 +883,19 @@
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
@@ -903,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
@@ -929,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;
@@ -1013,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 {
@@ -1079,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"
@@ -1261,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"
@@ -1290,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"
@@ -1356,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"
@@ -1389,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))
@@ -1403,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"
@@ -1455,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"
@@ -1529,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"
@@ -1580,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"
@@ -1680,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
@@ -1728,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;
@@ -1760,20 +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 {
@@ -2020,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);
@@ -2072,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) {
@@ -2086,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
@@ -2195,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",
@@ -2250,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",
@@ -2329,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
@@ -2359,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;
@@ -2443,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
@@ -2479,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))
@@ -2511,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);
@@ -3058,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)
@@ -3264,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)
@@ -3287,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
@@ -3391,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;
@@ -3459,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) {
@@ -3473,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
@@ -3601,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",
@@ -3727,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,
@@ -3760,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",
@@ -3829,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
@@ -3848,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 {
@@ -3917,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
@@ -3960,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
@@ -4034,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;
@@ -4064,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);
@@ -4090,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);
@@ -4154,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
@@ -4189,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;
@@ -4243,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 {
@@ -4284,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);
@@ -4609,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 }
@@ -4642,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
@@ -4751,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__)
@@ -5088,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) {
@@ -5182,18 +5320,17 @@
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;
@@ -5217,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>
@@ -5239,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
@@ -5254,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 }
@@ -5374,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>
@@ -5392,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);
@@ -5443,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
@@ -5480,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;
@@ -5498,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 }
@@ -5551,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,
@@ -5597,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
@@ -5661,21 +5819,20 @@
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);
@@ -5922,44 +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 }
@@ -6070,48 +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
@@ -6133,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];
@@ -6157,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 }
@@ -6237,18 +6322,24 @@
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;
@@ -6286,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;
@@ -6342,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
@@ -6520,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;
@@ -6620,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
@@ -6652,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;
@@ -6665,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);
@@ -6685,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;
@@ -6700,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) {
@@ -6837,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 {
@@ -6884,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)
@@ -6943,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 {
@@ -7088,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 }
@@ -7116,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;
@@ -7176,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;
@@ -7404,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);
@@ -7662,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 = {
@@ -7703,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 {
@@ -7752,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 }
@@ -7791,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)
@@ -7820,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);
@@ -7838,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 {
@@ -7851,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 }
@@ -7862,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);
@@ -8036,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)
@@ -8096,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 }
@@ -8203,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));
@@ -8226,14 +8340,14 @@
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
@@ -8270,26 +8384,26 @@
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;
@@ -8307,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
@@ -8327,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;
@@ -8379,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;
@@ -8413,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,
@@ -8429,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);
@@ -8467,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 {
@@ -8666,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];
@@ -8677,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;
@@ -8699,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 }
@@ -8722,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
@@ -8742,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
@@ -8754,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) {
@@ -8765,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)
@@ -8850,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
@@ -8877,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);
@@ -8889,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);
@@ -8933,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",
@@ -8952,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
@@ -9038,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);
@@ -9053,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;
@@ -9132,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
@@ -9217,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;
@@ -9323,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
@@ -9641,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);
@@ -9725,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
@@ -9843,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);
@@ -9914,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
@@ -10031,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));
@@ -10096,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;
@@ -10279,13 +10418,20 @@
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);
@@ -10300,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
@@ -10455,11 +10594,10 @@
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) {
10603 procname = "";
@@ -10513,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
@@ -10552,20 +10689,44 @@
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) {
@@ -10653,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
@@ -10876,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 '[':
@@ -10996,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
@@ -11032,11 +11236,11 @@
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);
@@ -11136,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
@@ -11179,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;
@@ -11201,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
@@ -11212,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;
@@ -11231,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;
@@ -11247,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
@@ -11377,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
@@ -11425,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;
@@ -11458,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 }
@@ -11534,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
@@ -11580,16 +11837,11 @@
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 }
@@ -11607,12 +11859,12 @@
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
@@ -11620,10 +11872,11 @@
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
@@ -11633,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);
@@ -11650,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;
@@ -11688,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;
@@ -11839,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 }
@@ -11864,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
@@ -11953,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;
@@ -11980,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,
@@ -12000,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
@@ -12152,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;
@@ -12178,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();
@@ -12192,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 }
@@ -12427,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);
@@ -12441,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;
@@ -12496,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);
@@ -12561,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:
@@ -12610,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 }
@@ -12630,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);
@@ -12818,96 +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)
@@ -12919,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)) {
@@ -12936,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);
@@ -12987,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;
@@ -13102,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
@@ -13608,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
@@ -13665,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 {
@@ -13688,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
@@ -13952,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 {
@@ -14171,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;
@@ -14512,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 {
@@ -14717,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]) {
@@ -14772,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
@@ -15046,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)) {
@@ -15145,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;
@@ -15187,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 {
@@ -15261,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 }
@@ -15288,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;
@@ -15475,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;
@@ -15510,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;
@@ -15543,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);
@@ -15865,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 ||
@@ -16088,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;
@@ -16111,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 }
@@ -16430,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++) {
@@ -16547,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
@@ -16744,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;
@@ -16777,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;
@@ -16796,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 }
@@ -16915,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);
@@ -16935,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 ...?");
@@ -17064,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;
@@ -17354,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;
@@ -17366,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 }
@@ -17851,15 +18052,17 @@
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) {
@@ -18009,11 +18212,11 @@
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 }
@@ -18043,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)
@@ -18092,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;
@@ -18117,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;
@@ -18134,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 {
@@ -18267,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
@@ -19047,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},
@@ -19279,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
@@ -19530,23 +19784,22 @@
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;
@@ -19555,319 +19808,349 @@
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
@@ -19876,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
@@ -19899,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])
@@ -19925,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 );
@@ -19942,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
@@ -19985,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)
@@ -20152,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)
@@ -20235,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) {
@@ -20329,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;
@@ -20577,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;
@@ -20606,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
@@ -20669,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;
@@ -20950,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)
@@ -21038,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);
@@ -21066,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;
@@ -21181,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[] = {
@@ -21359,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)
@@ -21422,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;
@@ -21534,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;
@@ -21551,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 }
@@ -21583,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