Fossil SCM

Update Jim Tcl to 0.78.

mistachkin 2019-07-06 21:42 UTC trunk
Commit 907f66bfd80710ad7fe03804e1f4a9082c50955d74ff237aba8c7ff0bac26ed7
1 file changed +3590 -3378
+3590 -3378
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
11
/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
2
-#define _GNU_SOURCE
32
#define JIM_TCL_COMPAT
4
-#define JIM_REFERENCES
53
#define JIM_ANSIC
64
#define JIM_REGEXP
75
#define HAVE_NO_AUTOCONF
86
#define _JIMAUTOCONF_H
97
#define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
3129
#define HAVE_MKDIR_ONE_ARG
3230
#define HAVE_SYSTEM
3331
#define HAVE_SYS_TIME_H
3432
#define HAVE_DIRENT_H
3533
#define HAVE_UNISTD_H
34
+#define HAVE_UMASK
35
+#include <sys/stat.h>
36
+#ifndef S_IRWXG
37
+#define S_IRWXG 0
38
+#endif
39
+#ifndef S_IRWXO
40
+#define S_IRWXO 0
41
+#endif
3642
#else
3743
#define TCL_PLATFORM_OS "unknown"
3844
#define TCL_PLATFORM_PLATFORM "unix"
3945
#define TCL_PLATFORM_PATH_SEPARATOR ":"
46
+#ifdef _MINIX
47
+#define vfork fork
48
+#define _POSIX_SOURCE
49
+#else
50
+#define _GNU_SOURCE
51
+#endif
4052
#define HAVE_VFORK
4153
#define HAVE_WAITPID
4254
#define HAVE_ISATTY
4355
#define HAVE_MKSTEMP
4456
#define HAVE_LINK
4557
#define HAVE_SYS_TIME_H
4658
#define HAVE_DIRENT_H
4759
#define HAVE_UNISTD_H
60
+#define HAVE_UMASK
4861
#endif
49
-#define JIM_VERSION 76
62
+#define JIM_VERSION 78
5063
#ifndef JIM_WIN32COMPAT_H
5164
#define JIM_WIN32COMPAT_H
5265
5366
5467
@@ -88,11 +101,10 @@
88101
#define JIM_WIDE_MIN LLONG_MIN
89102
#define JIM_WIDE_MAX LLONG_MAX
90103
#define JIM_WIDE_MODIFIER "I64d"
91104
#define strcasecmp _stricmp
92105
#define strtoull _strtoui64
93
-#define snprintf _snprintf
94106
95107
#include <io.h>
96108
97109
struct timeval {
98110
long tv_sec;
@@ -105,29 +117,24 @@
105117
struct dirent {
106118
char *d_name;
107119
};
108120
109121
typedef struct DIR {
110
- long handle;
122
+ long handle;
111123
struct _finddata_t info;
112
- struct dirent result;
113
- char *name;
124
+ struct dirent result;
125
+ char *name;
114126
} DIR;
115127
116128
DIR *opendir(const char *name);
117129
int closedir(DIR *dir);
118130
struct dirent *readdir(DIR *dir);
119131
120
-#elif defined(__MINGW32__)
121
-
122
-#include <stdlib.h>
123
-#define strtod __strtod
132
+#endif
124133
125134
#endif
126135
127
-#endif
128
-
129136
#ifdef __cplusplus
130137
}
131138
#endif
132139
133140
#endif
@@ -146,19 +153,21 @@
146153
147154
#ifndef JIM_UTF8
148155
#include <ctype.h>
149156
150157
151
-#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
158
+#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
159
+#define utf8_strwidth(S, B) utf8_strlen((S), (B))
152160
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
153161
#define utf8_getchars(CP, C) (*(CP) = (C), 1)
154162
#define utf8_upper(C) toupper(C)
155163
#define utf8_title(C) toupper(C)
156164
#define utf8_lower(C) tolower(C)
157165
#define utf8_index(C, I) (I)
158166
#define utf8_charlen(C) 1
159167
#define utf8_prev_len(S, L) 1
168
+#define utf8_width(C) 1
160169
161170
#else
162171
163172
#endif
164173
@@ -175,13 +184,13 @@
175184
extern "C" {
176185
#endif
177186
178187
#include <time.h>
179188
#include <limits.h>
180
-#include <stdio.h>
181
-#include <stdlib.h>
182
-#include <stdarg.h>
189
+#include <stdio.h>
190
+#include <stdlib.h>
191
+#include <stdarg.h>
183192
184193
185194
#ifndef HAVE_NO_AUTOCONF
186195
#endif
187196
@@ -224,31 +233,31 @@
224233
#define JIM_SIGNAL 5
225234
#define JIM_EXIT 6
226235
227236
#define JIM_EVAL 7
228237
229
-#define JIM_MAX_CALLFRAME_DEPTH 1000
230
-#define JIM_MAX_EVAL_DEPTH 2000
238
+#define JIM_MAX_CALLFRAME_DEPTH 1000
239
+#define JIM_MAX_EVAL_DEPTH 2000
231240
232241
233242
#define JIM_PRIV_FLAG_SHIFT 20
234243
235
-#define JIM_NONE 0
236
-#define JIM_ERRMSG 1
237
-#define JIM_ENUM_ABBREV 2
238
-#define JIM_UNSHARED 4
239
-#define JIM_MUSTEXIST 8
240
-
241
-
242
-#define JIM_SUBST_NOVAR 1
243
-#define JIM_SUBST_NOCMD 2
244
-#define JIM_SUBST_NOESC 4
245
-#define JIM_SUBST_FLAG 128
246
-
247
-
248
-#define JIM_CASESENS 0
249
-#define JIM_NOCASE 1
244
+#define JIM_NONE 0
245
+#define JIM_ERRMSG 1
246
+#define JIM_ENUM_ABBREV 2
247
+#define JIM_UNSHARED 4
248
+#define JIM_MUSTEXIST 8
249
+
250
+
251
+#define JIM_SUBST_NOVAR 1
252
+#define JIM_SUBST_NOCMD 2
253
+#define JIM_SUBST_NOESC 4
254
+#define JIM_SUBST_FLAG 128
255
+
256
+
257
+#define JIM_CASESENS 0
258
+#define JIM_NOCASE 1
250259
251260
252261
#define JIM_PATH_LEN 1024
253262
254263
@@ -339,79 +348,80 @@
339348
#define Jim_GetHashTableSize(ht) ((ht)->size)
340349
#define Jim_GetHashTableUsed(ht) ((ht)->used)
341350
342351
343352
typedef struct Jim_Obj {
344
- char *bytes;
345
- const struct Jim_ObjType *typePtr;
346
- int refCount;
347
- int length;
348
-
353
+ char *bytes;
354
+ const struct Jim_ObjType *typePtr;
355
+ int refCount;
356
+ int length;
357
+
349358
union {
350
-
359
+
351360
jim_wide wideValue;
352
-
361
+
353362
int intValue;
354
-
363
+
355364
double doubleValue;
356
-
365
+
357366
void *ptr;
358
-
367
+
359368
struct {
360369
void *ptr1;
361370
void *ptr2;
362371
} twoPtrValue;
363
-
372
+
373
+ struct {
374
+ void *ptr;
375
+ int int1;
376
+ int int2;
377
+ } ptrIntValue;
378
+
364379
struct {
365380
struct Jim_Var *varPtr;
366
- unsigned long callFrameId;
367
- int global;
381
+ unsigned long callFrameId;
382
+ int global;
368383
} varValue;
369
-
384
+
370385
struct {
371386
struct Jim_Obj *nsObj;
372387
struct Jim_Cmd *cmdPtr;
373
- unsigned long procEpoch;
388
+ unsigned long procEpoch;
374389
} cmdValue;
375
-
390
+
376391
struct {
377
- struct Jim_Obj **ele;
378
- int len;
379
- int maxLen;
392
+ struct Jim_Obj **ele;
393
+ int len;
394
+ int maxLen;
380395
} listValue;
381
-
396
+
382397
struct {
383398
int maxLength;
384
- int charLength;
399
+ int charLength;
385400
} strValue;
386
-
401
+
387402
struct {
388403
unsigned long id;
389404
struct Jim_Reference *refPtr;
390405
} refValue;
391
-
406
+
392407
struct {
393408
struct Jim_Obj *fileNameObj;
394409
int lineNumber;
395410
} sourceValue;
396
-
411
+
397412
struct {
398413
struct Jim_Obj *varNameObjPtr;
399414
struct Jim_Obj *indexObjPtr;
400415
} dictSubstValue;
401
-
402
- struct {
403
- void *compre;
404
- unsigned flags;
405
- } regexpValue;
406416
struct {
407417
int line;
408418
int argc;
409419
} scriptLineValue;
410420
} internalRep;
411
- struct Jim_Obj *prevObjPtr;
412
- struct Jim_Obj *nextObjPtr;
421
+ struct Jim_Obj *prevObjPtr;
422
+ struct Jim_Obj *nextObjPtr;
413423
} Jim_Obj;
414424
415425
416426
#define Jim_IncrRefCount(objPtr) \
417427
++(objPtr)->refCount
@@ -442,40 +452,40 @@
442452
typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
443453
struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
444454
typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
445455
446456
typedef struct Jim_ObjType {
447
- const char *name;
457
+ const char *name;
448458
Jim_FreeInternalRepProc *freeIntRepProc;
449459
Jim_DupInternalRepProc *dupIntRepProc;
450460
Jim_UpdateStringProc *updateStringProc;
451461
int flags;
452462
} Jim_ObjType;
453463
454464
455
-#define JIM_TYPE_NONE 0
456
-#define JIM_TYPE_REFERENCES 1
465
+#define JIM_TYPE_NONE 0
466
+#define JIM_TYPE_REFERENCES 1
457467
458468
459469
460470
typedef struct Jim_CallFrame {
461
- unsigned long id;
462
- int level;
463
- struct Jim_HashTable vars;
464
- struct Jim_HashTable *staticVars;
465
- struct Jim_CallFrame *parent;
466
- Jim_Obj *const *argv;
467
- int argc;
468
- Jim_Obj *procArgsObjPtr;
469
- Jim_Obj *procBodyObjPtr;
470
- struct Jim_CallFrame *next;
471
- Jim_Obj *nsObj;
472
- Jim_Obj *fileNameObj;
471
+ unsigned long id;
472
+ int level;
473
+ struct Jim_HashTable vars;
474
+ struct Jim_HashTable *staticVars;
475
+ struct Jim_CallFrame *parent;
476
+ Jim_Obj *const *argv;
477
+ int argc;
478
+ Jim_Obj *procArgsObjPtr;
479
+ Jim_Obj *procBodyObjPtr;
480
+ struct Jim_CallFrame *next;
481
+ Jim_Obj *nsObj;
482
+ Jim_Obj *fileNameObj;
473483
int line;
474
- Jim_Stack *localCommands;
475
- struct Jim_Obj *tailcallObj;
476
- struct Jim_Cmd *tailcallCmd;
484
+ Jim_Stack *localCommands;
485
+ struct Jim_Obj *tailcallObj;
486
+ struct Jim_Cmd *tailcallCmd;
477487
} Jim_CallFrame;
478488
479489
typedef struct Jim_Var {
480490
Jim_Obj *objPtr;
481491
struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +497,35 @@
487497
typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
488498
489499
490500
491501
typedef struct Jim_Cmd {
492
- int inUse;
493
- int isproc;
494
- struct Jim_Cmd *prevCmd;
502
+ int inUse;
503
+ int isproc;
504
+ struct Jim_Cmd *prevCmd;
495505
union {
496506
struct {
497
-
498
- Jim_CmdProc *cmdProc;
499
- Jim_DelCmdProc *delProc;
500
- void *privData;
507
+
508
+ Jim_CmdProc *cmdProc;
509
+ Jim_DelCmdProc *delProc;
510
+ void *privData;
501511
} native;
502512
struct {
503
-
513
+
504514
Jim_Obj *argListObjPtr;
505515
Jim_Obj *bodyObjPtr;
506
- Jim_HashTable *staticVars;
507
- int argListLen;
508
- int reqArity;
509
- int optArity;
510
- int argsPos;
511
- int upcall;
516
+ Jim_HashTable *staticVars;
517
+ int argListLen;
518
+ int reqArity;
519
+ int optArity;
520
+ int argsPos;
521
+ int upcall;
512522
struct Jim_ProcArg {
513
- Jim_Obj *nameObjPtr;
514
- Jim_Obj *defaultObjPtr;
523
+ Jim_Obj *nameObjPtr;
524
+ Jim_Obj *defaultObjPtr;
515525
} *arglist;
516
- Jim_Obj *nsObj;
526
+ Jim_Obj *nsObj;
517527
} proc;
518528
} u;
519529
} Jim_Cmd;
520530
521531
@@ -523,64 +533,64 @@
523533
unsigned char sbox[256];
524534
unsigned int i, j;
525535
} Jim_PrngState;
526536
527537
typedef struct Jim_Interp {
528
- Jim_Obj *result;
529
- int errorLine;
530
- Jim_Obj *errorFileNameObj;
531
- int addStackTrace;
532
- int maxCallFrameDepth;
533
- int maxEvalDepth;
534
- int evalDepth;
535
- int returnCode;
536
- int returnLevel;
537
- int exitCode;
538
- long id;
539
- int signal_level;
540
- jim_wide sigmask;
541
- int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
542
- Jim_CallFrame *framePtr;
543
- Jim_CallFrame *topFramePtr;
544
- struct Jim_HashTable commands;
538
+ Jim_Obj *result;
539
+ int errorLine;
540
+ Jim_Obj *errorFileNameObj;
541
+ int addStackTrace;
542
+ int maxCallFrameDepth;
543
+ int maxEvalDepth;
544
+ int evalDepth;
545
+ int returnCode;
546
+ int returnLevel;
547
+ int exitCode;
548
+ long id;
549
+ int signal_level;
550
+ jim_wide sigmask;
551
+ int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
552
+ Jim_CallFrame *framePtr;
553
+ Jim_CallFrame *topFramePtr;
554
+ struct Jim_HashTable commands;
545555
unsigned long procEpoch; /* Incremented every time the result
546556
of procedures names lookup caching
547557
may no longer be valid. */
548558
unsigned long callFrameEpoch; /* Incremented every time a new
549559
callframe is created. This id is used for the
550560
'ID' field contained in the Jim_CallFrame
551561
structure. */
552
- int local;
553
- Jim_Obj *liveList;
554
- Jim_Obj *freeList;
555
- Jim_Obj *currentScriptObj;
556
- Jim_Obj *nullScriptObj;
557
- Jim_Obj *emptyObj;
558
- Jim_Obj *trueObj;
559
- Jim_Obj *falseObj;
560
- unsigned long referenceNextId;
561
- struct Jim_HashTable references;
562
+ int local;
563
+ Jim_Obj *liveList;
564
+ Jim_Obj *freeList;
565
+ Jim_Obj *currentScriptObj;
566
+ Jim_Obj *nullScriptObj;
567
+ Jim_Obj *emptyObj;
568
+ Jim_Obj *trueObj;
569
+ Jim_Obj *falseObj;
570
+ unsigned long referenceNextId;
571
+ struct Jim_HashTable references;
562572
unsigned long lastCollectId; /* reference max Id of the last GC
563573
execution. It's set to -1 while the collection
564574
is running as sentinel to avoid to recursive
565575
calls via the [collect] command inside
566576
finalizers. */
567
- time_t lastCollectTime;
568
- Jim_Obj *stackTrace;
569
- Jim_Obj *errorProc;
570
- Jim_Obj *unknown;
571
- int unknown_called;
572
- int errorFlag;
577
+ time_t lastCollectTime;
578
+ Jim_Obj *stackTrace;
579
+ Jim_Obj *errorProc;
580
+ Jim_Obj *unknown;
581
+ int unknown_called;
582
+ int errorFlag;
573583
void *cmdPrivData; /* Used to pass the private data pointer to
574584
a command. It is set to what the user specified
575585
via Jim_CreateCommand(). */
576586
577
- struct Jim_CallFrame *freeFramesList;
578
- struct Jim_HashTable assocData;
579
- Jim_PrngState *prngState;
580
- struct Jim_HashTable packages;
581
- Jim_Stack *loadHandles;
587
+ struct Jim_CallFrame *freeFramesList;
588
+ struct Jim_HashTable assocData;
589
+ Jim_PrngState *prngState;
590
+ struct Jim_HashTable packages;
591
+ Jim_Stack *loadHandles;
582592
} Jim_Interp;
583593
584594
#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
585595
#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
586596
#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +633,11 @@
623633
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
624634
625635
626636
JIM_EXPORT char **Jim_GetEnviron(void);
627637
JIM_EXPORT void Jim_SetEnviron(char **env);
628
-JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
638
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file);
629639
630640
631641
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
632642
633643
@@ -816,25 +826,33 @@
816826
Jim_Obj *newObjPtr, int flags);
817827
JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
818828
Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
819829
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
820830
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
821
-JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
822
-JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
831
+
832
+#define JIM_DICTMATCH_KEYS 0x0001
833
+#define JIM_DICTMATCH_VALUES 0x002
834
+
835
+JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types);
823836
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
824837
JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
838
+JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv);
825839
826840
827841
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
828842
int *intPtr);
829843
830844
831845
JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
832
- Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
846
+ Jim_Obj *exprObjPtr);
833847
JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
834848
Jim_Obj *exprObjPtr, int *boolPtr);
835849
850
+
851
+JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr,
852
+ int *booleanPtr);
853
+
836854
837855
JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
838856
jim_wide *widePtr);
839857
JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
840858
long *longPtr);
@@ -852,10 +870,12 @@
852870
853871
JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
854872
Jim_Obj *const *argv, const char *msg);
855873
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
856874
const char * const *tablePtr, int *indexPtr, const char *name, int flags);
875
+JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr,
876
+ const char *const *tablePtr);
857877
JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
858878
Jim_Obj *scriptObj, char *stateCharPtr);
859879
860880
JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
861881
@@ -878,11 +898,12 @@
878898
879899
880900
JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
881901
JIM_EXPORT void Jim_HistoryLoad(const char *filename);
882902
JIM_EXPORT void Jim_HistorySave(const char *filename);
883
-JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
903
+JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt);
904
+JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj);
884905
JIM_EXPORT void Jim_HistoryAdd(const char *line);
885906
JIM_EXPORT void Jim_HistoryShow(void);
886907
887908
888909
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
@@ -904,11 +925,11 @@
904925
905926
#ifdef __cplusplus
906927
}
907928
#endif
908929
909
-#endif
930
+#endif
910931
911932
#ifndef JIM_SUBCMD_H
912933
#define JIM_SUBCMD_H
913934
914935
@@ -915,24 +936,24 @@
915936
#ifdef __cplusplus
916937
extern "C" {
917938
#endif
918939
919940
920
-#define JIM_MODFLAG_HIDDEN 0x0001
921
-#define JIM_MODFLAG_FULLARGV 0x0002
941
+#define JIM_MODFLAG_HIDDEN 0x0001
942
+#define JIM_MODFLAG_FULLARGV 0x0002
922943
923944
924945
925946
typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
926947
927948
typedef struct {
928
- const char *cmd;
929
- const char *args;
930
- jim_subcmd_function *function;
931
- short minargs;
932
- short maxargs;
933
- unsigned short flags;
949
+ const char *cmd;
950
+ const char *args;
951
+ jim_subcmd_function *function;
952
+ short minargs;
953
+ short maxargs;
954
+ unsigned short flags;
934955
} jim_subcmd_type;
935956
936957
const jim_subcmd_type *
937958
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
938959
@@ -960,36 +981,36 @@
960981
int rm_eo;
961982
} regmatch_t;
962983
963984
964985
typedef struct regexp {
965
-
966
- int re_nsub;
967
-
968
-
969
- int cflags;
970
- int err;
971
- int regstart;
972
- int reganch;
973
- int regmust;
974
- int regmlen;
975
- int *program;
976
-
977
-
978
- const char *regparse;
979
- int p;
980
- int proglen;
981
-
982
-
983
- int eflags;
984
- const char *start;
985
- const char *reginput;
986
- const char *regbol;
987
-
988
-
989
- regmatch_t *pmatch;
990
- int nmatch;
986
+
987
+ int re_nsub;
988
+
989
+
990
+ int cflags;
991
+ int err;
992
+ int regstart;
993
+ int reganch;
994
+ int regmust;
995
+ int regmlen;
996
+ int *program;
997
+
998
+
999
+ const char *regparse;
1000
+ int p;
1001
+ int proglen;
1002
+
1003
+
1004
+ int eflags;
1005
+ const char *start;
1006
+ const char *reginput;
1007
+ const char *regbol;
1008
+
1009
+
1010
+ regmatch_t *pmatch;
1011
+ int nmatch;
9911012
} regexp;
9921013
9931014
typedef regexp regex_t;
9941015
9951016
#define REG_EXTENDED 0
@@ -997,13 +1018,13 @@
9971018
#define REG_ICASE 2
9981019
9991020
#define REG_NOTBOL 16
10001021
10011022
enum {
1002
- REG_NOERROR,
1003
- REG_NOMATCH,
1004
- REG_BADPAT,
1023
+ REG_NOERROR,
1024
+ REG_NOMATCH,
1025
+ REG_BADPAT,
10051026
REG_ERR_NULL_ARGUMENT,
10061027
REG_ERR_UNKNOWN,
10071028
REG_ERR_TOO_BIG,
10081029
REG_ERR_NOMEM,
10091030
REG_ERR_TOO_MANY_PAREN,
@@ -1027,10 +1048,83 @@
10271048
void regfree(regex_t *preg);
10281049
10291050
#ifdef __cplusplus
10301051
}
10311052
#endif
1053
+
1054
+#endif
1055
+#ifndef JIM_SIGNAL_H
1056
+#define JIM_SIGNAL_H
1057
+
1058
+#ifdef __cplusplus
1059
+extern "C" {
1060
+#endif
1061
+
1062
+const char *Jim_SignalId(int sig);
1063
+
1064
+#ifdef __cplusplus
1065
+}
1066
+#endif
1067
+
1068
+#endif
1069
+#ifndef JIMIOCOMPAT_H
1070
+#define JIMIOCOMPAT_H
1071
+
1072
+
1073
+#include <stdio.h>
1074
+#include <errno.h>
1075
+
1076
+
1077
+void Jim_SetResultErrno(Jim_Interp *interp, const char *msg);
1078
+
1079
+int Jim_OpenForWrite(const char *filename, int append);
1080
+
1081
+int Jim_OpenForRead(const char *filename);
1082
+
1083
+#if defined(__MINGW32__)
1084
+ #ifndef STRICT
1085
+ #define STRICT
1086
+ #endif
1087
+ #define WIN32_LEAN_AND_MEAN
1088
+ #include <windows.h>
1089
+ #include <fcntl.h>
1090
+ #include <io.h>
1091
+ #include <process.h>
1092
+
1093
+ typedef HANDLE pidtype;
1094
+ #define JIM_BAD_PID INVALID_HANDLE_VALUE
1095
+
1096
+ #define JIM_NO_PID INVALID_HANDLE_VALUE
1097
+
1098
+
1099
+ #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0)
1100
+ #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff)
1101
+ #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0)
1102
+ #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff)
1103
+ #define WNOHANG 1
1104
+
1105
+ int Jim_Errno(void);
1106
+ pidtype waitpid(pidtype pid, int *status, int nohang);
1107
+
1108
+ #define HAVE_PIPE
1109
+ #define pipe(P) _pipe((P), 0, O_NOINHERIT)
1110
+
1111
+#elif defined(HAVE_UNISTD_H)
1112
+ #include <unistd.h>
1113
+ #include <fcntl.h>
1114
+ #include <sys/wait.h>
1115
+ #include <sys/stat.h>
1116
+
1117
+ typedef int pidtype;
1118
+ #define Jim_Errno() errno
1119
+ #define JIM_BAD_PID -1
1120
+ #define JIM_NO_PID 0
1121
+
1122
+ #ifndef HAVE_EXECVPE
1123
+ #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
1124
+ #endif
1125
+#endif
10321126
10331127
#endif
10341128
int Jim_bootstrapInit(Jim_Interp *interp)
10351129
{
10361130
if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
@@ -1100,10 +1194,43 @@
11001194
"\n"
11011195
"if {$tcl_platform(platform) eq \"windows\"} {\n"
11021196
" set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
11031197
"}\n"
11041198
"\n"
1199
+"\n"
1200
+"set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n"
1201
+"\n"
1202
+"\n"
1203
+"\n"
1204
+"proc tcl::autocomplete {prefix} {\n"
1205
+" if {[set space [string first \" \" $prefix]] != -1} {\n"
1206
+" set cmd [string range $prefix 0 $space-1]\n"
1207
+" if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n"
1208
+" set arg [string range $prefix $space+1 end]\n"
1209
+"\n"
1210
+" return [lmap p [$cmd -commands] {\n"
1211
+" if {![string match \"${arg}*\" $p]} continue\n"
1212
+" function \"$cmd $p\"\n"
1213
+" }]\n"
1214
+" }\n"
1215
+" }\n"
1216
+"\n"
1217
+" if {[string match \"source *\" $prefix]} {\n"
1218
+" set path [string range $prefix 7 end]\n"
1219
+" return [lmap p [glob -nocomplain \"${path}*\"] {\n"
1220
+" function \"source $p\"\n"
1221
+" }]\n"
1222
+" }\n"
1223
+"\n"
1224
+" return [lmap p [lsort [info commands $prefix*]] {\n"
1225
+" if {[string match \"* *\" $p]} {\n"
1226
+" continue\n"
1227
+" }\n"
1228
+" function $p\n"
1229
+" }]\n"
1230
+"}\n"
1231
+"\n"
11051232
"_jimsh_init\n"
11061233
);
11071234
}
11081235
int Jim_globInit(Jim_Interp *interp)
11091236
{
@@ -1315,10 +1442,17 @@
13151442
return JIM_ERR;
13161443
13171444
return Jim_EvalSource(interp, "stdlib.tcl", 1,
13181445
"\n"
13191446
"\n"
1447
+"if {![exists -command ref]} {\n"
1448
+"\n"
1449
+" proc ref {args} {{count 0}} {\n"
1450
+" format %08x [incr count]\n"
1451
+" }\n"
1452
+"}\n"
1453
+"\n"
13201454
"\n"
13211455
"proc lambda {arglist args} {\n"
13221456
" tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
13231457
"}\n"
13241458
"\n"
@@ -1375,10 +1509,17 @@
13751509
" }\n"
13761510
" join $lines \\n\n"
13771511
"}\n"
13781512
"\n"
13791513
"\n"
1514
+"\n"
1515
+"proc defer {script} {\n"
1516
+" upvar jim::defer v\n"
1517
+" lappend v $script\n"
1518
+"}\n"
1519
+"\n"
1520
+"\n"
13801521
"\n"
13811522
"proc errorInfo {msg {stacktrace \"\"}} {\n"
13821523
" if {$stacktrace eq \"\"} {\n"
13831524
"\n"
13841525
" set stacktrace [info stacktrace]\n"
@@ -1402,31 +1543,10 @@
14021543
" if {[exists ::jim::exe]} {\n"
14031544
" return $::jim::exe\n"
14041545
" }\n"
14051546
"}\n"
14061547
"\n"
1407
-"\n"
1408
-"proc {dict with} {&dictVar {args key} script} {\n"
1409
-" set keys {}\n"
1410
-" foreach {n v} [dict get $dictVar {*}$key] {\n"
1411
-" upvar $n var_$n\n"
1412
-" set var_$n $v\n"
1413
-" lappend keys $n\n"
1414
-" }\n"
1415
-" catch {uplevel 1 $script} msg opts\n"
1416
-" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1417
-" foreach n $keys {\n"
1418
-" if {[info exists var_$n]} {\n"
1419
-" dict set dictVar {*}$key $n [set var_$n]\n"
1420
-" } else {\n"
1421
-" dict unset dictVar {*}$key $n\n"
1422
-" }\n"
1423
-" }\n"
1424
-" }\n"
1425
-" return {*}$opts $msg\n"
1426
-"}\n"
1427
-"\n"
14281548
"\n"
14291549
"proc {dict update} {&varName args script} {\n"
14301550
" set keys {}\n"
14311551
" foreach {n v} $args {\n"
14321552
" upvar $v var_$v\n"
@@ -1445,23 +1565,10 @@
14451565
" }\n"
14461566
" }\n"
14471567
" return {*}$opts $msg\n"
14481568
"}\n"
14491569
"\n"
1450
-"\n"
1451
-"\n"
1452
-"proc {dict merge} {dict args} {\n"
1453
-" foreach d $args {\n"
1454
-"\n"
1455
-" dict size $d\n"
1456
-" foreach {k v} $d {\n"
1457
-" dict set dict $k $v\n"
1458
-" }\n"
1459
-" }\n"
1460
-" return $dict\n"
1461
-"}\n"
1462
-"\n"
14631570
"proc {dict replace} {dictionary {args {key value}}} {\n"
14641571
" if {[llength ${key value}] % 2} {\n"
14651572
" tailcall {dict replace}\n"
14661573
" }\n"
14671574
" tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1610,10 @@
15031610
" dict unset dictionary $k\n"
15041611
" }\n"
15051612
" return $dictionary\n"
15061613
"}\n"
15071614
"\n"
1508
-"\n"
1509
-"proc {dict values} {dictionary {pattern *}} {\n"
1510
-" dict keys [lreverse $dictionary] $pattern\n"
1511
-"}\n"
1512
-"\n"
15131615
"\n"
15141616
"proc {dict for} {vars dictionary script} {\n"
15151617
" if {[llength $vars] != 2} {\n"
15161618
" return -code error \"must have exactly two variable names\"\n"
15171619
" }\n"
@@ -1591,11 +1693,10 @@
15911693
" tailcall {*}$args\n"
15921694
"}\n"
15931695
"\n"
15941696
"\n"
15951697
"\n"
1596
-"\n"
15971698
"proc parray {arrayname {pattern *} {puts puts}} {\n"
15981699
" upvar $arrayname a\n"
15991700
"\n"
16001701
" set max 0\n"
16011702
" foreach name [array names a $pattern]] {\n"
@@ -1647,11 +1748,11 @@
16471748
"}\n"
16481749
"\n"
16491750
"\n"
16501751
"\n"
16511752
"proc popen {cmd {mode r}} {\n"
1652
-" lassign [socket pipe] r w\n"
1753
+" lassign [pipe] r w\n"
16531754
" try {\n"
16541755
" if {[string match \"w*\" $mode]} {\n"
16551756
" lappend cmd <@$r &\n"
16561757
" set pids [exec {*}$cmd]\n"
16571758
" $r close\n"
@@ -1663,16 +1764,31 @@
16631764
" set f $r\n"
16641765
" }\n"
16651766
" lambda {cmd args} {f pids} {\n"
16661767
" if {$cmd eq \"pid\"} {\n"
16671768
" return $pids\n"
1769
+" }\n"
1770
+" if {$cmd eq \"getfd\"} {\n"
1771
+" $f getfd\n"
16681772
" }\n"
16691773
" if {$cmd eq \"close\"} {\n"
16701774
" $f close\n"
16711775
"\n"
1672
-" foreach p $pids { os.wait $p }\n"
1673
-" return\n"
1776
+" set retopts {}\n"
1777
+" foreach p $pids {\n"
1778
+" lassign [wait $p] status - rc\n"
1779
+" if {$status eq \"CHILDSTATUS\"} {\n"
1780
+" if {$rc == 0} {\n"
1781
+" continue\n"
1782
+" }\n"
1783
+" set msg \"child process exited abnormally\"\n"
1784
+" } else {\n"
1785
+" set msg \"child killed: received signal\"\n"
1786
+" }\n"
1787
+" set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n"
1788
+" }\n"
1789
+" return {*}$retopts\n"
16741790
" }\n"
16751791
" tailcall $f $cmd {*}$args\n"
16761792
" }\n"
16771793
" } on error {error opts} {\n"
16781794
" $r close\n"
@@ -1692,14 +1808,10 @@
16921808
" if {[catch {$channelId pid} pids]} {\n"
16931809
" return \"\"\n"
16941810
" }\n"
16951811
" return $pids\n"
16961812
"}\n"
1697
-"\n"
1698
-"\n"
1699
-"\n"
1700
-"\n"
17011813
"\n"
17021814
"\n"
17031815
"\n"
17041816
"\n"
17051817
"\n"
@@ -1780,10 +1892,13 @@
17801892
"}\n"
17811893
);
17821894
}
17831895
17841896
1897
+#ifndef _GNU_SOURCE
1898
+#define _GNU_SOURCE
1899
+#endif
17851900
#include <stdio.h>
17861901
#include <string.h>
17871902
#include <errno.h>
17881903
#include <fcntl.h>
17891904
#ifdef HAVE_UNISTD_H
@@ -1793,27 +1908,34 @@
17931908
17941909
17951910
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
17961911
#include <sys/socket.h>
17971912
#include <netinet/in.h>
1913
+#include <netinet/tcp.h>
17981914
#include <arpa/inet.h>
17991915
#include <netdb.h>
18001916
#ifdef HAVE_SYS_UN_H
18011917
#include <sys/un.h>
18021918
#endif
1919
+#define HAVE_SOCKETS
1920
+#elif defined (__MINGW32__)
1921
+
18031922
#else
18041923
#define JIM_ANSIC
18051924
#endif
18061925
18071926
#if defined(JIM_SSL)
18081927
#include <openssl/ssl.h>
18091928
#include <openssl/err.h>
18101929
#endif
18111930
1931
+#ifdef HAVE_TERMIOS_H
1932
+#endif
18121933
1813
-#define AIO_CMD_LEN 32
1814
-#define AIO_BUF_LEN 256
1934
+
1935
+#define AIO_CMD_LEN 32
1936
+#define AIO_BUF_LEN 256
18151937
18161938
#ifndef HAVE_FTELLO
18171939
#define ftello ftell
18181940
#endif
18191941
#ifndef HAVE_FSEEKO
@@ -1828,10 +1950,16 @@
18281950
#define IPV6 0
18291951
#ifndef PF_INET6
18301952
#define PF_INET6 0
18311953
#endif
18321954
#endif
1955
+
1956
+#ifdef JIM_ANSIC
1957
+
1958
+#undef HAVE_PIPE
1959
+#undef HAVE_SOCKETPAIR
1960
+#endif
18331961
18341962
#define JimCheckStreamError(interp, af) af->fops->error(af)
18351963
18361964
18371965
struct AioFile;
@@ -1848,11 +1976,11 @@
18481976
typedef struct AioFile
18491977
{
18501978
FILE *fp;
18511979
Jim_Obj *filename;
18521980
int type;
1853
- int openFlags;
1981
+ int openFlags;
18541982
int fd;
18551983
Jim_Obj *rEvent;
18561984
Jim_Obj *wEvent;
18571985
Jim_Obj *eEvent;
18581986
int addr_family;
@@ -1879,21 +2007,21 @@
18792007
{
18802008
if (!ferror(af->fp)) {
18812009
return JIM_OK;
18822010
}
18832011
clearerr(af->fp);
1884
-
2012
+
18852013
if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
18862014
return JIM_OK;
18872015
}
18882016
#ifdef ECONNRESET
18892017
if (errno == ECONNRESET) {
18902018
return JIM_OK;
18912019
}
18922020
#endif
18932021
#ifdef ECONNABORTED
1894
- if (errno != ECONNABORTED) {
2022
+ if (errno == ECONNABORTED) {
18952023
return JIM_OK;
18962024
}
18972025
#endif
18982026
return JIM_ERR;
18992027
}
@@ -1945,20 +2073,19 @@
19452073
JIM_NOTUSED(interp);
19462074
19472075
Jim_DecrRefCount(interp, af->filename);
19482076
19492077
#ifdef jim_ext_eventloop
1950
-
1951
- Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
2078
+
2079
+ Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
19522080
#endif
19532081
19542082
#if defined(JIM_SSL)
19552083
if (af->ssl != NULL) {
19562084
SSL_free(af->ssl);
19572085
}
19582086
#endif
1959
-
19602087
if (!(af->openFlags & AIO_KEEPOPEN)) {
19612088
fclose(af->fp);
19622089
}
19632090
19642091
Jim_Free(af);
@@ -1968,11 +2095,11 @@
19682095
{
19692096
AioFile *af = Jim_CmdPrivData(interp);
19702097
char buf[AIO_BUF_LEN];
19712098
Jim_Obj *objPtr;
19722099
int nonewline = 0;
1973
- jim_wide neededLen = -1;
2100
+ jim_wide neededLen = -1;
19742101
19752102
if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
19762103
nonewline = 1;
19772104
argv++;
19782105
argc--;
@@ -2007,11 +2134,11 @@
20072134
}
20082135
}
20092136
if (retval != readlen)
20102137
break;
20112138
}
2012
-
2139
+
20132140
if (JimCheckStreamError(interp, af)) {
20142141
Jim_FreeNewObj(interp, objPtr);
20152142
return JIM_ERR;
20162143
}
20172144
if (nonewline) {
@@ -2029,11 +2156,11 @@
20292156
20302157
AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
20312158
{
20322159
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
20332160
2034
-
2161
+
20352162
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
20362163
return (AioFile *) cmdPtr->u.native.privData;
20372164
}
20382165
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
20392166
return NULL;
@@ -2048,10 +2175,20 @@
20482175
return NULL;
20492176
}
20502177
20512178
return af->fp;
20522179
}
2180
+
2181
+static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2182
+{
2183
+ AioFile *af = Jim_CmdPrivData(interp);
2184
+
2185
+ fflush(af->fp);
2186
+ Jim_SetResultInt(interp, fileno(af->fp));
2187
+
2188
+ return JIM_OK;
2189
+}
20532190
20542191
static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20552192
{
20562193
AioFile *af = Jim_CmdPrivData(interp);
20572194
jim_wide count = 0;
@@ -2110,21 +2247,21 @@
21102247
}
21112248
else {
21122249
len = strlen(buf);
21132250
21142251
if (len && (buf[len - 1] == '\n')) {
2115
-
2252
+
21162253
len--;
21172254
}
21182255
21192256
Jim_AppendString(interp, objPtr, buf, len);
21202257
break;
21212258
}
21222259
}
21232260
21242261
if (JimCheckStreamError(interp, af)) {
2125
-
2262
+
21262263
Jim_FreeNewObj(interp, objPtr);
21272264
return JIM_ERR;
21282265
}
21292266
21302267
if (argc) {
@@ -2134,11 +2271,11 @@
21342271
}
21352272
21362273
len = Jim_Length(objPtr);
21372274
21382275
if (len == 0 && feof(af->fp)) {
2139
-
2276
+
21402277
len = -1;
21412278
}
21422279
Jim_SetResultInt(interp, len);
21432280
}
21442281
else {
@@ -2207,11 +2344,11 @@
22072344
}
22082345
22092346
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
22102347
{
22112348
if (argc == 3) {
2212
-#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2349
+#if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN)
22132350
static const char * const options[] = { "r", "w", NULL };
22142351
enum { OPT_R, OPT_W, };
22152352
int option;
22162353
AioFile *af = Jim_CmdPrivData(interp);
22172354
@@ -2297,10 +2434,11 @@
22972434
}
22982435
Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
22992436
return JIM_OK;
23002437
}
23012438
#endif
2439
+
23022440
23032441
#ifdef HAVE_FSYNC
23042442
static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
23052443
{
23062444
AioFile *af = Jim_CmdPrivData(interp);
@@ -2364,33 +2502,33 @@
23642502
23652503
static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
23662504
int argc, Jim_Obj * const *argv)
23672505
{
23682506
if (argc == 0) {
2369
-
2507
+
23702508
if (*scriptHandlerObj) {
23712509
Jim_SetResult(interp, *scriptHandlerObj);
23722510
}
23732511
return JIM_OK;
23742512
}
23752513
23762514
if (*scriptHandlerObj) {
2377
-
2378
- Jim_DeleteFileHandler(interp, af->fp, mask);
2515
+
2516
+ Jim_DeleteFileHandler(interp, af->fd, mask);
23792517
}
23802518
2381
-
2519
+
23822520
if (Jim_Length(argv[0]) == 0) {
2383
-
2521
+
23842522
return JIM_OK;
23852523
}
23862524
2387
-
2525
+
23882526
Jim_IncrRefCount(argv[0]);
23892527
*scriptHandlerObj = argv[0];
23902528
2391
- Jim_CreateFileHandler(interp, af->fp, mask,
2529
+ Jim_CreateFileHandler(interp, af->fd, mask,
23922530
JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
23932531
23942532
return JIM_OK;
23952533
}
23962534
@@ -2414,136 +2552,145 @@
24142552
24152553
return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
24162554
}
24172555
#endif
24182556
2557
+
2558
+
24192559
24202560
static const jim_subcmd_type aio_command_table[] = {
24212561
{ "read",
24222562
"?-nonewline? ?len?",
24232563
aio_cmd_read,
24242564
0,
24252565
2,
2426
-
2566
+
24272567
},
24282568
{ "copyto",
24292569
"handle ?size?",
24302570
aio_cmd_copy,
24312571
1,
24322572
2,
2433
-
2573
+
2574
+ },
2575
+ { "getfd",
2576
+ NULL,
2577
+ aio_cmd_getfd,
2578
+ 0,
2579
+ 0,
2580
+
24342581
},
24352582
{ "gets",
24362583
"?var?",
24372584
aio_cmd_gets,
24382585
0,
24392586
1,
2440
-
2587
+
24412588
},
24422589
{ "puts",
24432590
"?-nonewline? str",
24442591
aio_cmd_puts,
24452592
1,
24462593
2,
2447
-
2594
+
24482595
},
24492596
{ "isatty",
24502597
NULL,
24512598
aio_cmd_isatty,
24522599
0,
24532600
0,
2454
-
2601
+
24552602
},
24562603
{ "flush",
24572604
NULL,
24582605
aio_cmd_flush,
24592606
0,
24602607
0,
2461
-
2608
+
24622609
},
24632610
{ "eof",
24642611
NULL,
24652612
aio_cmd_eof,
24662613
0,
24672614
0,
2468
-
2615
+
24692616
},
24702617
{ "close",
24712618
"?r(ead)|w(rite)?",
24722619
aio_cmd_close,
24732620
0,
24742621
1,
24752622
JIM_MODFLAG_FULLARGV,
2476
-
2623
+
24772624
},
24782625
{ "seek",
24792626
"offset ?start|current|end",
24802627
aio_cmd_seek,
24812628
1,
24822629
2,
2483
-
2630
+
24842631
},
24852632
{ "tell",
24862633
NULL,
24872634
aio_cmd_tell,
24882635
0,
24892636
0,
2490
-
2637
+
24912638
},
24922639
{ "filename",
24932640
NULL,
24942641
aio_cmd_filename,
24952642
0,
24962643
0,
2497
-
2644
+
24982645
},
24992646
#ifdef O_NDELAY
25002647
{ "ndelay",
25012648
"?0|1?",
25022649
aio_cmd_ndelay,
25032650
0,
25042651
1,
2505
-
2652
+
25062653
},
25072654
#endif
25082655
#ifdef HAVE_FSYNC
25092656
{ "sync",
25102657
NULL,
25112658
aio_cmd_sync,
25122659
0,
25132660
0,
2514
-
2661
+
25152662
},
25162663
#endif
25172664
{ "buffering",
25182665
"none|line|full",
25192666
aio_cmd_buffering,
25202667
1,
25212668
1,
2522
-
2669
+
25232670
},
25242671
#ifdef jim_ext_eventloop
25252672
{ "readable",
25262673
"?readable-script?",
25272674
aio_cmd_readable,
25282675
0,
25292676
1,
2530
-
2677
+
25312678
},
25322679
{ "writable",
25332680
"?writable-script?",
25342681
aio_cmd_writable,
25352682
0,
25362683
1,
2537
-
2684
+
25382685
},
25392686
{ "onexception",
25402687
"?exception-script?",
25412688
aio_cmd_onexception,
25422689
0,
25432690
1,
2544
-
2691
+
25452692
},
25462693
#endif
25472694
{ NULL }
25482695
};
25492696
@@ -2566,11 +2713,11 @@
25662713
25672714
#ifdef jim_ext_tclcompat
25682715
{
25692716
const char *filename = Jim_String(argv[1]);
25702717
2571
-
2718
+
25722719
if (*filename == '|') {
25732720
Jim_Obj *evalObj[3];
25742721
25752722
evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
25762723
evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2603,35 +2750,37 @@
26032750
}
26042751
26052752
Jim_IncrRefCount(filename);
26062753
26072754
if (fh == NULL) {
2608
-#if !defined(JIM_ANSIC)
26092755
if (fd >= 0) {
2756
+#ifndef JIM_ANSIC
26102757
fh = fdopen(fd, mode);
2758
+#endif
26112759
}
26122760
else
2613
-#endif
26142761
fh = fopen(Jim_String(filename), mode);
26152762
26162763
if (fh == NULL) {
26172764
JimAioSetError(interp, filename);
2618
-#if !defined(JIM_ANSIC)
2765
+#ifndef JIM_ANSIC
26192766
if (fd >= 0) {
26202767
close(fd);
26212768
}
26222769
#endif
26232770
Jim_DecrRefCount(interp, filename);
26242771
return NULL;
26252772
}
26262773
}
26272774
2628
-
2775
+
26292776
af = Jim_Alloc(sizeof(*af));
26302777
memset(af, 0, sizeof(*af));
26312778
af->fp = fh;
2779
+#ifndef JIM_ANSIC
26322780
af->fd = fileno(fh);
2781
+#endif
26332782
af->filename = filename;
26342783
#ifdef FD_CLOEXEC
26352784
if ((openFlags & AIO_KEEPOPEN) == 0) {
26362785
(void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
26372786
}
@@ -2653,72 +2802,45 @@
26532802
const char *hdlfmt, int family, const char *mode[2])
26542803
{
26552804
if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
26562805
Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
26572806
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2658
-
26592807
if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) {
26602808
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
26612809
Jim_SetResult(interp, objPtr);
26622810
return JIM_OK;
26632811
}
26642812
}
26652813
2666
-
2814
+
26672815
close(p[0]);
26682816
close(p[1]);
26692817
JimAioSetError(interp, NULL);
26702818
return JIM_ERR;
26712819
}
26722820
#endif
26732821
2674
-
2675
-int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2676
-{
2677
-#ifdef HAVE_MKSTEMP
2678
- int fd;
2679
- mode_t mask;
2680
- Jim_Obj *filenameObj;
2681
-
2682
- if (template == NULL) {
2683
- const char *tmpdir = getenv("TMPDIR");
2684
- if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2685
- tmpdir = "/tmp/";
2686
- }
2687
- filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2688
- if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2689
- Jim_AppendString(interp, filenameObj, "/", 1);
2690
- }
2691
- Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2692
- }
2693
- else {
2694
- filenameObj = Jim_NewStringObj(interp, template, -1);
2695
- }
2696
-
2697
-#if defined(S_IRWXG) && defined(S_IRWXO)
2698
- mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2699
-#else
2700
-
2701
- mask = umask(S_IXUSR);
2702
-#endif
2703
-
2704
-
2705
- fd = mkstemp(filenameObj->bytes);
2706
- umask(mask);
2707
- if (fd < 0) {
2708
- JimAioSetError(interp, filenameObj);
2709
- Jim_FreeNewObj(interp, filenameObj);
2710
- return -1;
2711
- }
2712
-
2713
- Jim_SetResult(interp, filenameObj);
2714
- return fd;
2715
-#else
2716
- Jim_SetResultString(interp, "platform has no tempfile support", -1);
2717
- return -1;
2718
-#endif
2719
-}
2822
+#ifdef HAVE_PIPE
2823
+static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2824
+{
2825
+ int p[2];
2826
+ static const char *mode[2] = { "r", "w" };
2827
+
2828
+ if (argc != 1) {
2829
+ Jim_WrongNumArgs(interp, 1, argv, "");
2830
+ return JIM_ERR;
2831
+ }
2832
+
2833
+ if (pipe(p) != 0) {
2834
+ JimAioSetError(interp, NULL);
2835
+ return JIM_ERR;
2836
+ }
2837
+
2838
+ return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode);
2839
+}
2840
+#endif
2841
+
27202842
27212843
27222844
int Jim_aioInit(Jim_Interp *interp)
27232845
{
27242846
if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
@@ -2727,15 +2849,18 @@
27272849
#if defined(JIM_SSL)
27282850
Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL);
27292851
#endif
27302852
27312853
Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
2732
-#ifndef JIM_ANSIC
2854
+#ifdef HAVE_SOCKETS
27332855
Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
27342856
#endif
2857
+#ifdef HAVE_PIPE
2858
+ Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL);
2859
+#endif
27352860
2736
-
2861
+
27372862
JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
27382863
JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
27392864
JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
27402865
27412866
return JIM_OK;
@@ -2813,12 +2938,12 @@
28132938
#include <regex.h>
28142939
#endif
28152940
28162941
static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
28172942
{
2818
- regfree(objPtr->internalRep.regexpValue.compre);
2819
- Jim_Free(objPtr->internalRep.regexpValue.compre);
2943
+ regfree(objPtr->internalRep.ptrIntValue.ptr);
2944
+ Jim_Free(objPtr->internalRep.ptrIntValue.ptr);
28202945
}
28212946
28222947
static const Jim_ObjType regexpObjType = {
28232948
"regexp",
28242949
FreeRegexpInternalRep,
@@ -2831,20 +2956,20 @@
28312956
{
28322957
regex_t *compre;
28332958
const char *pattern;
28342959
int ret;
28352960
2836
-
2961
+
28372962
if (objPtr->typePtr == &regexpObjType &&
2838
- objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
2839
-
2840
- return objPtr->internalRep.regexpValue.compre;
2963
+ objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) {
2964
+
2965
+ return objPtr->internalRep.ptrIntValue.ptr;
28412966
}
28422967
2843
-
28442968
2845
-
2969
+
2970
+
28462971
pattern = Jim_String(objPtr);
28472972
compre = Jim_Alloc(sizeof(regex_t));
28482973
28492974
if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
28502975
char buf[100];
@@ -2857,12 +2982,12 @@
28572982
}
28582983
28592984
Jim_FreeIntRep(interp, objPtr);
28602985
28612986
objPtr->typePtr = &regexpObjType;
2862
- objPtr->internalRep.regexpValue.flags = flags;
2863
- objPtr->internalRep.regexpValue.compre = compre;
2987
+ objPtr->internalRep.ptrIntValue.int1 = flags;
2988
+ objPtr->internalRep.ptrIntValue.ptr = compre;
28642989
28652990
return compre;
28662991
}
28672992
28682993
int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3001,11 +3126,11 @@
30013126
}
30023127
30033128
num_matches++;
30043129
30053130
if (opt_all && !opt_inline) {
3006
-
3131
+
30073132
goto try_next_match;
30083133
}
30093134
30103135
30113136
j = 0;
@@ -3041,11 +3166,11 @@
30413166
30423167
if (opt_inline) {
30433168
Jim_ListAppendElement(interp, resultListObj, resultObj);
30443169
}
30453170
else {
3046
-
3171
+
30473172
result = Jim_SetVariable(interp, argv[i], resultObj);
30483173
30493174
if (result != JIM_OK) {
30503175
Jim_FreeObj(interp, resultObj);
30513176
break;
@@ -3168,11 +3293,11 @@
31683293
31693294
source_str = Jim_GetString(argv[i + 1], &source_len);
31703295
replace_str = Jim_GetString(argv[i + 2], &replace_len);
31713296
varname = argv[i + 3];
31723297
3173
-
3298
+
31743299
resultObj = Jim_NewStringObj(interp, "", 0);
31753300
31763301
if (offset) {
31773302
if (offset < 0) {
31783303
offset += source_len + 1;
@@ -3183,11 +3308,11 @@
31833308
else if (offset < 0) {
31843309
offset = 0;
31853310
}
31863311
}
31873312
3188
-
3313
+
31893314
Jim_AppendString(interp, resultObj, source_str, offset);
31903315
31913316
31923317
n = source_len - offset;
31933318
p = source_str + offset;
@@ -3242,23 +3367,23 @@
32423367
}
32433368
32443369
p += pmatch[0].rm_eo;
32453370
n -= pmatch[0].rm_eo;
32463371
3247
-
3372
+
32483373
if (!opt_all || n == 0) {
32493374
break;
32503375
}
32513376
3252
-
3377
+
32533378
if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
32543379
break;
32553380
}
32563381
3257
-
3382
+
32583383
if (pattern[0] == '\0' && n) {
3259
-
3384
+
32603385
Jim_AppendString(interp, resultObj, p, 1);
32613386
p++;
32623387
n--;
32633388
}
32643389
@@ -3265,11 +3390,11 @@
32653390
regexec_flags |= REG_NOTBOL;
32663391
} while (n);
32673392
32683393
Jim_AppendString(interp, resultObj, p, -1);
32693394
3270
-
3395
+
32713396
if (argc - i == 4) {
32723397
result = Jim_SetVariable(interp, varname, resultObj);
32733398
32743399
if (result == JIM_OK) {
32753400
Jim_SetResultInt(interp, num_matches);
@@ -3320,11 +3445,11 @@
33203445
33213446
# ifndef MAXPATHLEN
33223447
# define MAXPATHLEN JIM_PATH_LEN
33233448
# endif
33243449
3325
-#if defined(__MINGW32__) || defined(_MSC_VER)
3450
+#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
33263451
#define ISWINDOWS 1
33273452
#else
33283453
#define ISWINDOWS 0
33293454
#endif
33303455
@@ -3371,11 +3496,11 @@
33713496
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
33723497
}
33733498
33743499
static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
33753500
{
3376
-
3501
+
33773502
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
33783503
33793504
AppendStatElement(interp, listObj, "dev", sb->st_dev);
33803505
AppendStatElement(interp, listObj, "ino", sb->st_ino);
33813506
AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3512,38 @@
33873512
AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
33883513
AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
33893514
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
33903515
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
33913516
3392
-
3517
+
33933518
if (varName) {
3394
- Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3519
+ Jim_Obj *objPtr;
3520
+ objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3521
+
33953522
if (objPtr) {
3396
- if (Jim_DictSize(interp, objPtr) < 0) {
3397
-
3523
+ Jim_Obj *objv[2];
3524
+
3525
+ objv[0] = objPtr;
3526
+ objv[1] = listObj;
3527
+
3528
+ objPtr = Jim_DictMerge(interp, 2, objv);
3529
+ if (objPtr == NULL) {
3530
+
33983531
Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
33993532
Jim_FreeNewObj(interp, listObj);
34003533
return JIM_ERR;
34013534
}
34023535
3403
- if (Jim_IsShared(objPtr))
3404
- objPtr = Jim_DuplicateObj(interp, objPtr);
3405
-
3406
-
3407
- Jim_ListAppendList(interp, objPtr, listObj);
3408
- Jim_DictSize(interp, objPtr);
34093536
Jim_InvalidateStringRep(objPtr);
34103537
34113538
Jim_FreeNewObj(interp, listObj);
34123539
listObj = objPtr;
34133540
}
34143541
Jim_SetVariable(interp, varName, listObj);
34153542
}
34163543
3417
-
3544
+
34183545
Jim_SetResult(interp, listObj);
34193546
34203547
return JIM_OK;
34213548
}
34223549
@@ -3432,11 +3559,11 @@
34323559
}
34333560
else if (p == path) {
34343561
Jim_SetResultString(interp, "/", -1);
34353562
}
34363563
else if (ISWINDOWS && p[-1] == ':') {
3437
-
3564
+
34383565
Jim_SetResultString(interp, path, p - path + 1);
34393566
}
34403567
else {
34413568
Jim_SetResultString(interp, path, p - path);
34423569
}
@@ -3512,35 +3639,35 @@
35123639
char *newname = Jim_Alloc(MAXPATHLEN + 1);
35133640
char *last = newname;
35143641
35153642
*newname = 0;
35163643
3517
-
3644
+
35183645
for (i = 0; i < argc; i++) {
35193646
int len;
35203647
const char *part = Jim_GetString(argv[i], &len);
35213648
35223649
if (*part == '/') {
3523
-
3650
+
35243651
last = newname;
35253652
}
35263653
else if (ISWINDOWS && strchr(part, ':')) {
3527
-
3654
+
35283655
last = newname;
35293656
}
35303657
else if (part[0] == '.') {
35313658
if (part[1] == '/') {
35323659
part += 2;
35333660
len -= 2;
35343661
}
35353662
else if (part[1] == 0 && last != newname) {
3536
-
3663
+
35373664
continue;
35383665
}
35393666
}
35403667
3541
-
3668
+
35423669
if (last != newname && last[-1] != '/') {
35433670
*last++ = '/';
35443671
}
35453672
35463673
if (len) {
@@ -3551,22 +3678,22 @@
35513678
}
35523679
memcpy(last, part, len);
35533680
last += len;
35543681
}
35553682
3556
-
3683
+
35573684
if (last > newname + 1 && last[-1] == '/') {
3558
-
3685
+
35593686
if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
35603687
*--last = 0;
35613688
}
35623689
}
35633690
}
35643691
35653692
*last = 0;
35663693
3567
-
3694
+
35683695
35693696
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
35703697
35713698
return JIM_OK;
35723699
}
@@ -3591,11 +3718,11 @@
35913718
static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
35923719
{
35933720
#ifdef X_OK
35943721
return file_access(interp, argv[0], X_OK);
35953722
#else
3596
-
3723
+
35973724
Jim_SetResultBool(interp, 1);
35983725
return JIM_OK;
35993726
#endif
36003727
}
36013728
@@ -3616,11 +3743,11 @@
36163743
while (argc--) {
36173744
const char *path = Jim_String(argv[0]);
36183745
36193746
if (unlink(path) == -1 && errno != ENOENT) {
36203747
if (rmdir(path) == -1) {
3621
-
3748
+
36223749
if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
36233750
Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
36243751
strerror(errno));
36253752
return JIM_ERR;
36263753
}
@@ -3639,15 +3766,15 @@
36393766
36403767
static int mkdir_all(char *path)
36413768
{
36423769
int ok = 1;
36433770
3644
-
3771
+
36453772
goto first;
36463773
36473774
while (ok--) {
3648
-
3775
+
36493776
{
36503777
char *slash = strrchr(path, '/');
36513778
36523779
if (slash && slash != path) {
36533780
*slash = 0;
@@ -3660,24 +3787,24 @@
36603787
first:
36613788
if (MKDIR_DEFAULT(path) == 0) {
36623789
return 0;
36633790
}
36643791
if (errno == ENOENT) {
3665
-
3792
+
36663793
continue;
36673794
}
3668
-
3795
+
36693796
if (errno == EEXIST) {
36703797
struct stat sb;
36713798
36723799
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
36733800
return 0;
36743801
}
3675
-
3802
+
36763803
errno = EEXIST;
36773804
}
3678
-
3805
+
36793806
break;
36803807
}
36813808
return -1;
36823809
}
36833810
@@ -3698,11 +3825,11 @@
36983825
return JIM_OK;
36993826
}
37003827
37013828
static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
37023829
{
3703
- int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3830
+ int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0);
37043831
37053832
if (fd < 0) {
37063833
return JIM_ERR;
37073834
}
37083835
close(fd);
@@ -3962,192 +4089,192 @@
39624089
{ "atime",
39634090
"name",
39644091
file_cmd_atime,
39654092
1,
39664093
1,
3967
-
4094
+
39684095
},
39694096
{ "mtime",
39704097
"name ?time?",
39714098
file_cmd_mtime,
39724099
1,
39734100
2,
3974
-
4101
+
39754102
},
39764103
{ "copy",
39774104
"?-force? source dest",
39784105
file_cmd_copy,
39794106
2,
39804107
3,
3981
-
4108
+
39824109
},
39834110
{ "dirname",
39844111
"name",
39854112
file_cmd_dirname,
39864113
1,
39874114
1,
3988
-
4115
+
39894116
},
39904117
{ "rootname",
39914118
"name",
39924119
file_cmd_rootname,
39934120
1,
39944121
1,
3995
-
4122
+
39964123
},
39974124
{ "extension",
39984125
"name",
39994126
file_cmd_extension,
40004127
1,
40014128
1,
4002
-
4129
+
40034130
},
40044131
{ "tail",
40054132
"name",
40064133
file_cmd_tail,
40074134
1,
40084135
1,
4009
-
4136
+
40104137
},
40114138
{ "normalize",
40124139
"name",
40134140
file_cmd_normalize,
40144141
1,
40154142
1,
4016
-
4143
+
40174144
},
40184145
{ "join",
40194146
"name ?name ...?",
40204147
file_cmd_join,
40214148
1,
40224149
-1,
4023
-
4150
+
40244151
},
40254152
{ "readable",
40264153
"name",
40274154
file_cmd_readable,
40284155
1,
40294156
1,
4030
-
4157
+
40314158
},
40324159
{ "writable",
40334160
"name",
40344161
file_cmd_writable,
40354162
1,
40364163
1,
4037
-
4164
+
40384165
},
40394166
{ "executable",
40404167
"name",
40414168
file_cmd_executable,
40424169
1,
40434170
1,
4044
-
4171
+
40454172
},
40464173
{ "exists",
40474174
"name",
40484175
file_cmd_exists,
40494176
1,
40504177
1,
4051
-
4178
+
40524179
},
40534180
{ "delete",
40544181
"?-force|--? name ...",
40554182
file_cmd_delete,
40564183
1,
40574184
-1,
4058
-
4185
+
40594186
},
40604187
{ "mkdir",
40614188
"dir ...",
40624189
file_cmd_mkdir,
40634190
1,
40644191
-1,
4065
-
4192
+
40664193
},
40674194
{ "tempfile",
40684195
"?template?",
40694196
file_cmd_tempfile,
40704197
0,
40714198
1,
4072
-
4199
+
40734200
},
40744201
{ "rename",
40754202
"?-force? source dest",
40764203
file_cmd_rename,
40774204
2,
40784205
3,
4079
-
4206
+
40804207
},
40814208
#if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
40824209
{ "link",
40834210
"?-symbolic|-hard? newname target",
40844211
file_cmd_link,
40854212
2,
40864213
3,
4087
-
4214
+
40884215
},
40894216
#endif
40904217
#if defined(HAVE_READLINK)
40914218
{ "readlink",
40924219
"name",
40934220
file_cmd_readlink,
40944221
1,
40954222
1,
4096
-
4223
+
40974224
},
40984225
#endif
40994226
{ "size",
41004227
"name",
41014228
file_cmd_size,
41024229
1,
41034230
1,
4104
-
4231
+
41054232
},
41064233
{ "stat",
41074234
"name ?var?",
41084235
file_cmd_stat,
41094236
1,
41104237
2,
4111
-
4238
+
41124239
},
41134240
{ "lstat",
41144241
"name ?var?",
41154242
file_cmd_lstat,
41164243
1,
41174244
2,
4118
-
4245
+
41194246
},
41204247
{ "type",
41214248
"name",
41224249
file_cmd_type,
41234250
1,
41244251
1,
4125
-
4252
+
41264253
},
41274254
#ifdef HAVE_GETEUID
41284255
{ "owned",
41294256
"name",
41304257
file_cmd_owned,
41314258
1,
41324259
1,
4133
-
4260
+
41344261
},
41354262
#endif
41364263
{ "isdirectory",
41374264
"name",
41384265
file_cmd_isdirectory,
41394266
1,
41404267
1,
4141
-
4268
+
41424269
},
41434270
{ "isfile",
41444271
"name",
41454272
file_cmd_isfile,
41464273
1,
41474274
1,
4148
-
4275
+
41494276
},
41504277
{
41514278
NULL
41524279
}
41534280
};
@@ -4179,11 +4306,11 @@
41794306
Jim_SetResultString(interp, "Failed to get pwd", -1);
41804307
Jim_Free(cwd);
41814308
return JIM_ERR;
41824309
}
41834310
else if (ISWINDOWS) {
4184
-
4311
+
41854312
char *p = cwd;
41864313
while ((p = strchr(p, '\\')) != NULL) {
41874314
*p++ = '/';
41884315
}
41894316
}
@@ -4203,10 +4330,13 @@
42034330
Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
42044331
Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
42054332
return JIM_OK;
42064333
}
42074334
4335
+#ifndef _GNU_SOURCE
4336
+#define _GNU_SOURCE
4337
+#endif
42084338
#include <string.h>
42094339
#include <ctype.h>
42104340
42114341
42124342
#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4344,20 @@
42144344
{
42154345
Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
42164346
int i, j;
42174347
int rc;
42184348
4219
-
4349
+
42204350
for (i = 1; i < argc; i++) {
42214351
int len;
42224352
const char *arg = Jim_GetString(argv[i], &len);
42234353
42244354
if (i > 1) {
42254355
Jim_AppendString(interp, cmdlineObj, " ", 1);
42264356
}
42274357
if (strpbrk(arg, "\\\" ") == NULL) {
4228
-
4358
+
42294359
Jim_AppendString(interp, cmdlineObj, arg, len);
42304360
continue;
42314361
}
42324362
42334363
Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4266,86 +4396,26 @@
42664396
#else
42674397
42684398
42694399
#include <errno.h>
42704400
#include <signal.h>
4271
-
4272
-#if defined(__MINGW32__)
4273
-
4274
- #ifndef STRICT
4275
- #define STRICT
4276
- #endif
4277
- #define WIN32_LEAN_AND_MEAN
4278
- #include <windows.h>
4279
- #include <fcntl.h>
4280
-
4281
- typedef HANDLE fdtype;
4282
- typedef HANDLE pidtype;
4283
- #define JIM_BAD_FD INVALID_HANDLE_VALUE
4284
- #define JIM_BAD_PID INVALID_HANDLE_VALUE
4285
- #define JimCloseFd CloseHandle
4286
-
4287
- #define WIFEXITED(STATUS) 1
4288
- #define WEXITSTATUS(STATUS) (STATUS)
4289
- #define WIFSIGNALED(STATUS) 0
4290
- #define WTERMSIG(STATUS) 0
4291
- #define WNOHANG 1
4292
-
4293
- static fdtype JimFileno(FILE *fh);
4294
- static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
4295
- static fdtype JimDupFd(fdtype infd);
4296
- static fdtype JimOpenForRead(const char *filename);
4297
- static FILE *JimFdOpenForRead(fdtype fd);
4298
- static int JimPipe(fdtype pipefd[2]);
4299
- static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
4300
- fdtype inputId, fdtype outputId, fdtype errorId);
4301
- static int JimErrno(void);
4302
-#else
4303
- #include <unistd.h>
4304
- #include <fcntl.h>
4305
- #include <sys/wait.h>
4306
- #include <sys/stat.h>
4307
-
4308
- typedef int fdtype;
4309
- typedef int pidtype;
4310
- #define JimPipe pipe
4311
- #define JimErrno() errno
4312
- #define JIM_BAD_FD -1
4313
- #define JIM_BAD_PID -1
4314
- #define JimFileno fileno
4315
- #define JimReadFd read
4316
- #define JimCloseFd close
4317
- #define JimWaitPid waitpid
4318
- #define JimDupFd dup
4319
- #define JimFdOpenForRead(FD) fdopen((FD), "r")
4320
- #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
4321
-
4322
- #ifndef HAVE_EXECVPE
4323
- #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
4324
- #endif
4325
-#endif
4326
-
4327
-static const char *JimStrError(void);
4401
+#include <sys/stat.h>
4402
+
4403
+struct WaitInfoTable;
4404
+
4405
+static char **JimOriginalEnviron(void);
43284406
static char **JimSaveEnv(char **env);
43294407
static void JimRestoreEnv(char **env);
43304408
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4331
- pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4332
-static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
4409
+ pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
4410
+static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr);
43334411
static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj);
4334
-static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
4335
-static fdtype JimOpenForWrite(const char *filename, int append);
4336
-static int JimRewindFd(fdtype fd);
4337
-
4338
-static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
4339
-{
4340
- Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
4341
-}
4342
-
4343
-static const char *JimStrError(void)
4344
-{
4345
- return strerror(JimErrno());
4346
-}
4412
+static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
4413
+
4414
+#if defined(__MINGW32__)
4415
+static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId);
4416
+#endif
43474417
43484418
static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
43494419
{
43504420
int len;
43514421
const char *s = Jim_GetString(objPtr, &len);
@@ -4354,14 +4424,14 @@
43544424
objPtr->length--;
43554425
objPtr->bytes[objPtr->length] = '\0';
43564426
}
43574427
}
43584428
4359
-static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj)
4429
+static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj)
43604430
{
43614431
char buf[256];
4362
- FILE *fh = JimFdOpenForRead(fd);
4432
+ FILE *fh = fdopen(fd, "r");
43634433
int ret = 0;
43644434
43654435
if (fh == NULL) {
43664436
return -1;
43674437
}
@@ -4390,18 +4460,18 @@
43904460
char *envdata;
43914461
43924462
Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
43934463
43944464
if (!objPtr) {
4395
- return Jim_GetEnviron();
4465
+ return JimOriginalEnviron();
43964466
}
43974467
43984468
4399
-
4469
+
44004470
num = Jim_ListLength(interp, objPtr);
44014471
if (num % 2) {
4402
-
4472
+
44034473
num--;
44044474
}
44054475
size = Jim_Length(objPtr) + 2;
44064476
44074477
envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4433,79 +4503,76 @@
44334503
if (env != original_environ) {
44344504
Jim_Free(env);
44354505
}
44364506
}
44374507
4438
-#ifndef jim_ext_signal
4439
-
4440
-const char *Jim_SignalId(int sig)
4441
-{
4442
- static char buf[10];
4443
- snprintf(buf, sizeof(buf), "%d", sig);
4444
- return buf;
4445
-}
4446
-
4447
-const char *Jim_SignalName(int sig)
4448
-{
4449
- return Jim_SignalId(sig);
4450
-}
4451
-#endif
4452
-
4453
-static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4454
-{
4455
- Jim_Obj *errorCode;
4456
-
4457
- if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
4458
- return JIM_OK;
4459
- }
4460
- errorCode = Jim_NewListObj(interp, NULL, 0);
4461
-
4462
- if (WIFEXITED(waitStatus)) {
4508
+static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4509
+{
4510
+ Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
4511
+
4512
+ if (pid == JIM_BAD_PID || pid == JIM_NO_PID) {
4513
+ Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1));
4514
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4515
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1));
4516
+ }
4517
+ else if (WIFEXITED(waitStatus)) {
44634518
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
44644519
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
44654520
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
44664521
}
44674522
else {
44684523
const char *type;
44694524
const char *action;
4525
+ const char *signame;
44704526
44714527
if (WIFSIGNALED(waitStatus)) {
44724528
type = "CHILDKILLED";
44734529
action = "killed";
4530
+ signame = Jim_SignalId(WTERMSIG(waitStatus));
44744531
}
44754532
else {
44764533
type = "CHILDSUSP";
44774534
action = "suspended";
4535
+ signame = "none";
44784536
}
44794537
44804538
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
44814539
44824540
if (errStrObj) {
44834541
Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL);
44844542
}
44854543
44864544
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4487
- Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1));
4488
- Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1));
4545
+ Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1));
44894546
}
4490
- Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
4547
+ return errorCode;
4548
+}
4549
+
4550
+static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4551
+{
4552
+ if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
4553
+ return JIM_OK;
4554
+ }
4555
+ Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj));
44914556
44924557
return JIM_ERR;
44934558
}
44944559
44954560
44964561
struct WaitInfo
44974562
{
4498
- pidtype pid;
4499
- int status;
4500
- int flags;
4563
+ pidtype pid;
4564
+ int status;
4565
+ int flags;
45014566
};
4567
+
45024568
45034569
struct WaitInfoTable {
4504
- struct WaitInfo *info;
4505
- int size;
4506
- int used;
4570
+ struct WaitInfo *info;
4571
+ int size;
4572
+ int used;
4573
+ int refcount;
45074574
};
45084575
45094576
45104577
#define WI_DETACHED 2
45114578
@@ -4513,32 +4580,53 @@
45134580
45144581
static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData)
45154582
{
45164583
struct WaitInfoTable *table = privData;
45174584
4518
- Jim_Free(table->info);
4519
- Jim_Free(table);
4585
+ if (--table->refcount == 0) {
4586
+ Jim_Free(table->info);
4587
+ Jim_Free(table);
4588
+ }
45204589
}
45214590
45224591
static struct WaitInfoTable *JimAllocWaitInfoTable(void)
45234592
{
45244593
struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
45254594
table->info = NULL;
45264595
table->size = table->used = 0;
4596
+ table->refcount = 1;
45274597
45284598
return table;
45294599
}
4600
+
4601
+static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid)
4602
+{
4603
+ int i;
4604
+
4605
+
4606
+ for (i = 0; i < table->used; i++) {
4607
+ if (pid == table->info[i].pid) {
4608
+ if (i != table->used - 1) {
4609
+ table->info[i] = table->info[table->used - 1];
4610
+ }
4611
+ table->used--;
4612
+ return 0;
4613
+ }
4614
+ }
4615
+ return -1;
4616
+}
45304617
45314618
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
45324619
{
4533
- fdtype outputId;
4534
- fdtype errorId;
4620
+ int outputId;
4621
+ int errorId;
45354622
pidtype *pidPtr;
45364623
int numPids, result;
45374624
int child_siginfo = 1;
45384625
Jim_Obj *childErrObj;
45394626
Jim_Obj *errStrObj;
4627
+ struct WaitInfoTable *table = Jim_CmdPrivData(interp);
45404628
45414629
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
45424630
Jim_Obj *listObj;
45434631
int i;
45444632
@@ -4545,17 +4633,17 @@
45454633
argc--;
45464634
numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
45474635
if (numPids < 0) {
45484636
return JIM_ERR;
45494637
}
4550
-
4638
+
45514639
listObj = Jim_NewListObj(interp, NULL, 0);
45524640
for (i = 0; i < numPids; i++) {
45534641
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
45544642
}
45554643
Jim_SetResult(interp, listObj);
4556
- JimDetachPids(interp, numPids, pidPtr);
4644
+ JimDetachPids(table, numPids, pidPtr);
45574645
Jim_Free(pidPtr);
45584646
return JIM_OK;
45594647
}
45604648
45614649
numPids =
@@ -4567,54 +4655,98 @@
45674655
45684656
result = JIM_OK;
45694657
45704658
errStrObj = Jim_NewStringObj(interp, "", 0);
45714659
4572
-
4573
- if (outputId != JIM_BAD_FD) {
4660
+
4661
+ if (outputId != -1) {
45744662
if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
45754663
result = JIM_ERR;
45764664
Jim_SetResultErrno(interp, "error reading from output pipe");
45774665
}
45784666
}
45794667
4580
-
4668
+
45814669
childErrObj = Jim_NewStringObj(interp, "", 0);
45824670
Jim_IncrRefCount(childErrObj);
45834671
45844672
if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
45854673
result = JIM_ERR;
45864674
}
45874675
4588
- if (errorId != JIM_BAD_FD) {
4676
+ if (errorId != -1) {
45894677
int ret;
4590
- JimRewindFd(errorId);
4678
+ lseek(errorId, 0, SEEK_SET);
45914679
ret = JimAppendStreamToString(interp, errorId, errStrObj);
45924680
if (ret < 0) {
45934681
Jim_SetResultErrno(interp, "error reading from error pipe");
45944682
result = JIM_ERR;
45954683
}
45964684
else if (ret > 0) {
4597
-
4685
+
45984686
child_siginfo = 0;
45994687
}
46004688
}
46014689
46024690
if (child_siginfo) {
4603
-
4691
+
46044692
Jim_AppendObj(interp, errStrObj, childErrObj);
46054693
}
46064694
Jim_DecrRefCount(interp, childErrObj);
46074695
4608
-
4696
+
46094697
Jim_RemoveTrailingNewline(errStrObj);
46104698
4611
-
4699
+
46124700
Jim_SetResult(interp, errStrObj);
46134701
46144702
return result;
46154703
}
4704
+
4705
+static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4706
+{
4707
+ if (JimWaitRemove(table, pid) == 0) {
4708
+
4709
+ waitpid(pid, statusPtr, 0);
4710
+ return pid;
4711
+ }
4712
+
4713
+
4714
+ return JIM_BAD_PID;
4715
+}
4716
+
4717
+static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr)
4718
+{
4719
+ int j;
4720
+
4721
+ for (j = 0; j < numPids; j++) {
4722
+
4723
+ int i;
4724
+ for (i = 0; i < table->used; i++) {
4725
+ if (pidPtr[j] == table->info[i].pid) {
4726
+ table->info[i].flags |= WI_DETACHED;
4727
+ break;
4728
+ }
4729
+ }
4730
+ }
4731
+}
4732
+
4733
+static int JimGetChannelFd(Jim_Interp *interp, const char *name)
4734
+{
4735
+ Jim_Obj *objv[2];
4736
+
4737
+ objv[0] = Jim_NewStringObj(interp, name, -1);
4738
+ objv[1] = Jim_NewStringObj(interp, "getfd", -1);
4739
+
4740
+ if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) {
4741
+ jim_wide fd;
4742
+ if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) {
4743
+ return fd;
4744
+ }
4745
+ }
4746
+ return -1;
4747
+}
46164748
46174749
static void JimReapDetachedPids(struct WaitInfoTable *table)
46184750
{
46194751
struct WaitInfo *waitPtr;
46204752
int count;
@@ -4627,13 +4759,13 @@
46274759
waitPtr = table->info;
46284760
dest = 0;
46294761
for (count = table->used; count > 0; waitPtr++, count--) {
46304762
if (waitPtr->flags & WI_DETACHED) {
46314763
int status;
4632
- pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4764
+ pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG);
46334765
if (pid == waitPtr->pid) {
4634
-
4766
+
46354767
table->used--;
46364768
continue;
46374769
}
46384770
}
46394771
if (waitPtr != &table->info[dest]) {
@@ -4641,66 +4773,62 @@
46414773
}
46424774
dest++;
46434775
}
46444776
}
46454777
4646
-static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4647
-{
4648
- int i;
4649
-
4650
-
4651
- for (i = 0; i < table->used; i++) {
4652
- if (pid == table->info[i].pid) {
4653
-
4654
- JimWaitPid(pid, statusPtr, 0);
4655
-
4656
-
4657
- if (i != table->used - 1) {
4658
- table->info[i] = table->info[table->used - 1];
4659
- }
4660
- table->used--;
4661
- return pid;
4662
- }
4663
- }
4664
-
4665
-
4666
- return JIM_BAD_PID;
4667
-}
4668
-
4669
-static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4670
-{
4671
- int j;
4778
+static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4779
+{
46724780
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4673
-
4674
- for (j = 0; j < numPids; j++) {
4675
-
4676
- int i;
4677
- for (i = 0; i < table->used; i++) {
4678
- if (pidPtr[j] == table->info[i].pid) {
4679
- table->info[i].flags |= WI_DETACHED;
4680
- break;
4681
- }
4682
- }
4683
- }
4684
-}
4685
-
4686
-static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name)
4687
-{
4688
- FILE *fh;
4689
- Jim_Obj *fhObj;
4690
-
4691
- fhObj = Jim_NewStringObj(interp, name, -1);
4692
- Jim_IncrRefCount(fhObj);
4693
- fh = Jim_AioFilehandle(interp, fhObj);
4694
- Jim_DecrRefCount(interp, fhObj);
4695
-
4696
- return fh;
4781
+ int nohang = 0;
4782
+ pidtype pid;
4783
+ long pidarg;
4784
+ int status;
4785
+ Jim_Obj *errCodeObj;
4786
+
4787
+
4788
+ if (argc == 1) {
4789
+ JimReapDetachedPids(table);
4790
+ return JIM_OK;
4791
+ }
4792
+
4793
+ if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) {
4794
+ nohang = 1;
4795
+ }
4796
+ if (argc != nohang + 2) {
4797
+ Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?");
4798
+ return JIM_ERR;
4799
+ }
4800
+ if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) {
4801
+ return JIM_ERR;
4802
+ }
4803
+
4804
+ pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0);
4805
+
4806
+ errCodeObj = JimMakeErrorCode(interp, pid, status, NULL);
4807
+
4808
+ if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) {
4809
+
4810
+ JimWaitRemove(table, pid);
4811
+ }
4812
+ Jim_SetResult(interp, errCodeObj);
4813
+ return JIM_OK;
4814
+}
4815
+
4816
+static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4817
+{
4818
+ if (argc != 1) {
4819
+ Jim_WrongNumArgs(interp, 1, argv, "");
4820
+ return JIM_ERR;
4821
+ }
4822
+
4823
+ Jim_SetResultInt(interp, (jim_wide)getpid());
4824
+ return JIM_OK;
46974825
}
46984826
46994827
static int
47004828
JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
4701
- fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
4829
+ int *inPipePtr, int *outPipePtr, int *errFilePtr)
47024830
{
47034831
pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all
47044832
* the pids of child processes. */
47054833
int numPids = 0; /* Actual number of processes that exist
47064834
* at *pidPtr right now. */
@@ -4707,16 +4835,16 @@
47074835
int cmdCount; /* Count of number of distinct commands
47084836
* found in argc/argv. */
47094837
const char *input = NULL; /* Describes input for pipeline, depending
47104838
* on "inputFile". NULL means take input
47114839
* from stdin/pipe. */
4712
- int input_len = 0;
4840
+ int input_len = 0;
47134841
4714
-#define FILE_NAME 0
4715
-#define FILE_APPEND 1
4716
-#define FILE_HANDLE 2
4717
-#define FILE_TEXT 3
4842
+#define FILE_NAME 0
4843
+#define FILE_APPEND 1
4844
+#define FILE_HANDLE 2
4845
+#define FILE_TEXT 3
47184846
47194847
int inputFile = FILE_NAME; /* 1 means input is name of input file.
47204848
* 2 means input is filehandle name.
47214849
* 0 means input holds actual
47224850
* text to be input to command. */
@@ -4733,39 +4861,37 @@
47334861
*/
47344862
const char *output = NULL; /* Holds name of output file to pipe to,
47354863
* or NULL if output goes to stdout/pipe. */
47364864
const char *error = NULL; /* Holds name of stderr file to pipe to,
47374865
* or NULL if stderr goes to stderr/pipe. */
4738
- fdtype inputId = JIM_BAD_FD;
4739
- fdtype outputId = JIM_BAD_FD;
4740
- fdtype errorId = JIM_BAD_FD;
4741
- fdtype lastOutputId = JIM_BAD_FD;
4742
- fdtype pipeIds[2];
4866
+ int inputId = -1;
4867
+ int outputId = -1;
4868
+ int errorId = -1;
4869
+ int lastOutputId = -1;
4870
+ int pipeIds[2];
47434871
int firstArg, lastArg; /* Indexes of first and last arguments in
47444872
* current command. */
47454873
int lastBar;
47464874
int i;
47474875
pidtype pid;
47484876
char **save_environ;
47494877
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
47504878
4751
-
4879
+
47524880
char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
47534881
int arg_count = 0;
47544882
4755
- JimReapDetachedPids(table);
4756
-
47574883
if (inPipePtr != NULL) {
4758
- *inPipePtr = JIM_BAD_FD;
4884
+ *inPipePtr = -1;
47594885
}
47604886
if (outPipePtr != NULL) {
4761
- *outPipePtr = JIM_BAD_FD;
4887
+ *outPipePtr = -1;
47624888
}
47634889
if (errFilePtr != NULL) {
4764
- *errFilePtr = JIM_BAD_FD;
4890
+ *errFilePtr = -1;
47654891
}
4766
- pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4892
+ pipeIds[0] = pipeIds[1] = -1;
47674893
47684894
cmdCount = 1;
47694895
lastBar = -1;
47704896
for (i = 0; i < argc; i++) {
47714897
const char *arg = Jim_String(argv[i]);
@@ -4796,11 +4922,11 @@
47964922
if (*output == '>') {
47974923
outputFile = FILE_APPEND;
47984924
output++;
47994925
}
48004926
if (*output == '&') {
4801
-
4927
+
48024928
output++;
48034929
dup_error = 1;
48044930
}
48054931
if (*output == '@') {
48064932
outputFile = FILE_HANDLE;
@@ -4837,11 +4963,11 @@
48374963
goto badargs;
48384964
}
48394965
lastBar = i;
48404966
cmdCount++;
48414967
}
4842
-
4968
+
48434969
arg_array[arg_count++] = (char *)arg;
48444970
continue;
48454971
}
48464972
48474973
if (i >= argc) {
@@ -4855,150 +4981,160 @@
48554981
badargs:
48564982
Jim_Free(arg_array);
48574983
return -1;
48584984
}
48594985
4860
-
4986
+
48614987
save_environ = JimSaveEnv(JimBuildEnv(interp));
48624988
48634989
if (input != NULL) {
48644990
if (inputFile == FILE_TEXT) {
4865
- inputId = JimCreateTemp(interp, input, input_len);
4866
- if (inputId == JIM_BAD_FD) {
4991
+ inputId = Jim_MakeTempFile(interp, NULL, 1);
4992
+ if (inputId == -1) {
4993
+ goto error;
4994
+ }
4995
+ if (write(inputId, input, input_len) != input_len) {
4996
+ Jim_SetResultErrno(interp, "couldn't write temp file");
4997
+ close(inputId);
48674998
goto error;
48684999
}
5000
+ lseek(inputId, 0L, SEEK_SET);
48695001
}
48705002
else if (inputFile == FILE_HANDLE) {
4871
-
4872
- FILE *fh = JimGetAioFilehandle(interp, input);
5003
+ int fd = JimGetChannelFd(interp, input);
48735004
4874
- if (fh == NULL) {
5005
+ if (fd < 0) {
48755006
goto error;
48765007
}
4877
- inputId = JimDupFd(JimFileno(fh));
5008
+ inputId = dup(fd);
48785009
}
48795010
else {
4880
- inputId = JimOpenForRead(input);
4881
- if (inputId == JIM_BAD_FD) {
4882
- Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
5011
+ inputId = Jim_OpenForRead(input);
5012
+ if (inputId == -1) {
5013
+ Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno()));
48835014
goto error;
48845015
}
48855016
}
48865017
}
48875018
else if (inPipePtr != NULL) {
4888
- if (JimPipe(pipeIds) != 0) {
5019
+ if (pipe(pipeIds) != 0) {
48895020
Jim_SetResultErrno(interp, "couldn't create input pipe for command");
48905021
goto error;
48915022
}
48925023
inputId = pipeIds[0];
48935024
*inPipePtr = pipeIds[1];
4894
- pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5025
+ pipeIds[0] = pipeIds[1] = -1;
48955026
}
48965027
48975028
if (output != NULL) {
48985029
if (outputFile == FILE_HANDLE) {
4899
- FILE *fh = JimGetAioFilehandle(interp, output);
4900
- if (fh == NULL) {
5030
+ int fd = JimGetChannelFd(interp, output);
5031
+ if (fd < 0) {
49015032
goto error;
49025033
}
4903
- fflush(fh);
4904
- lastOutputId = JimDupFd(JimFileno(fh));
5034
+ lastOutputId = dup(fd);
49055035
}
49065036
else {
4907
- lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
4908
- if (lastOutputId == JIM_BAD_FD) {
4909
- Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
5037
+ lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND);
5038
+ if (lastOutputId == -1) {
5039
+ Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno()));
49105040
goto error;
49115041
}
49125042
}
49135043
}
49145044
else if (outPipePtr != NULL) {
4915
- if (JimPipe(pipeIds) != 0) {
5045
+ if (pipe(pipeIds) != 0) {
49165046
Jim_SetResultErrno(interp, "couldn't create output pipe");
49175047
goto error;
49185048
}
49195049
lastOutputId = pipeIds[1];
49205050
*outPipePtr = pipeIds[0];
4921
- pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5051
+ pipeIds[0] = pipeIds[1] = -1;
49225052
}
4923
-
5053
+
49245054
if (error != NULL) {
49255055
if (errorFile == FILE_HANDLE) {
49265056
if (strcmp(error, "1") == 0) {
4927
-
4928
- if (lastOutputId != JIM_BAD_FD) {
4929
- errorId = JimDupFd(lastOutputId);
5057
+
5058
+ if (lastOutputId != -1) {
5059
+ errorId = dup(lastOutputId);
49305060
}
49315061
else {
4932
-
5062
+
49335063
error = "stdout";
49345064
}
49355065
}
4936
- if (errorId == JIM_BAD_FD) {
4937
- FILE *fh = JimGetAioFilehandle(interp, error);
4938
- if (fh == NULL) {
5066
+ if (errorId == -1) {
5067
+ int fd = JimGetChannelFd(interp, error);
5068
+ if (fd < 0) {
49395069
goto error;
49405070
}
4941
- fflush(fh);
4942
- errorId = JimDupFd(JimFileno(fh));
5071
+ errorId = dup(fd);
49435072
}
49445073
}
49455074
else {
4946
- errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
4947
- if (errorId == JIM_BAD_FD) {
4948
- Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
5075
+ errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND);
5076
+ if (errorId == -1) {
5077
+ Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno()));
49495078
goto error;
49505079
}
49515080
}
49525081
}
49535082
else if (errFilePtr != NULL) {
4954
- errorId = JimCreateTemp(interp, NULL, 0);
4955
- if (errorId == JIM_BAD_FD) {
5083
+ errorId = Jim_MakeTempFile(interp, NULL, 1);
5084
+ if (errorId == -1) {
49565085
goto error;
49575086
}
4958
- *errFilePtr = JimDupFd(errorId);
5087
+ *errFilePtr = dup(errorId);
49595088
}
49605089
49615090
49625091
pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
49635092
for (i = 0; i < numPids; i++) {
49645093
pidPtr[i] = JIM_BAD_PID;
49655094
}
49665095
for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
49675096
int pipe_dup_err = 0;
4968
- fdtype origErrorId = errorId;
5097
+ int origErrorId = errorId;
49695098
49705099
for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
4971
- if (arg_array[lastArg][0] == '|') {
4972
- if (arg_array[lastArg][1] == '&') {
4973
- pipe_dup_err = 1;
4974
- }
5100
+ if (strcmp(arg_array[lastArg], "|") == 0) {
5101
+ break;
5102
+ }
5103
+ if (strcmp(arg_array[lastArg], "|&") == 0) {
5104
+ pipe_dup_err = 1;
49755105
break;
49765106
}
49775107
}
4978
-
5108
+
5109
+ if (lastArg == firstArg) {
5110
+ Jim_SetResultString(interp, "missing command to exec", -1);
5111
+ goto error;
5112
+ }
5113
+
5114
+
49795115
arg_array[lastArg] = NULL;
49805116
if (lastArg == arg_count) {
49815117
outputId = lastOutputId;
49825118
}
49835119
else {
4984
- if (JimPipe(pipeIds) != 0) {
5120
+ if (pipe(pipeIds) != 0) {
49855121
Jim_SetResultErrno(interp, "couldn't create pipe");
49865122
goto error;
49875123
}
49885124
outputId = pipeIds[1];
49895125
}
49905126
4991
-
5127
+
49925128
if (pipe_dup_err) {
49935129
errorId = outputId;
49945130
}
49955131
4996
-
5132
+
49975133
49985134
#ifdef __MINGW32__
4999
- pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
5135
+ pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
50005136
if (pid == JIM_BAD_PID) {
50015137
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
50025138
goto error;
50035139
}
50045140
#else
@@ -5006,32 +5142,37 @@
50065142
if (pid < 0) {
50075143
Jim_SetResultErrno(interp, "couldn't fork child process");
50085144
goto error;
50095145
}
50105146
if (pid == 0) {
5011
-
50125147
5013
- if (inputId != -1) dup2(inputId, 0);
5014
- if (outputId != -1) dup2(outputId, 1);
5015
- if (errorId != -1) dup2(errorId, 2);
5148
+ if (inputId != -1) dup2(inputId, fileno(stdin));
5149
+ if (outputId != -1) dup2(outputId, fileno(stdout));
5150
+ if (errorId != -1) dup2(errorId, fileno(stderr));
50165151
50175152
for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
50185153
close(i);
50195154
}
50205155
5021
-
5156
+
50225157
(void)signal(SIGPIPE, SIG_DFL);
50235158
50245159
execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
50255160
5026
-
50275161
fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
5162
+#ifdef JIM_MAINTAINER
5163
+ {
5164
+
5165
+ static char *const false_argv[2] = {"false", NULL};
5166
+ execvp(false_argv[0],false_argv);
5167
+ }
5168
+#endif
50285169
_exit(127);
50295170
}
50305171
#endif
50315172
5032
-
5173
+
50335174
50345175
if (table->used == table->size) {
50355176
table->size += WAIT_TABLE_GROW_BY;
50365177
table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
50375178
}
@@ -5040,66 +5181,67 @@
50405181
table->info[table->used].flags = 0;
50415182
table->used++;
50425183
50435184
pidPtr[numPids] = pid;
50445185
5045
-
5186
+
50465187
errorId = origErrorId;
50475188
50485189
5049
- if (inputId != JIM_BAD_FD) {
5050
- JimCloseFd(inputId);
5190
+ if (inputId != -1) {
5191
+ close(inputId);
50515192
}
5052
- if (outputId != JIM_BAD_FD) {
5053
- JimCloseFd(outputId);
5193
+ if (outputId != -1) {
5194
+ close(outputId);
5195
+ outputId = -1;
50545196
}
50555197
inputId = pipeIds[0];
5056
- pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5198
+ pipeIds[0] = pipeIds[1] = -1;
50575199
}
50585200
*pidArrayPtr = pidPtr;
50595201
50605202
50615203
cleanup:
5062
- if (inputId != JIM_BAD_FD) {
5063
- JimCloseFd(inputId);
5064
- }
5065
- if (lastOutputId != JIM_BAD_FD) {
5066
- JimCloseFd(lastOutputId);
5067
- }
5068
- if (errorId != JIM_BAD_FD) {
5069
- JimCloseFd(errorId);
5204
+ if (inputId != -1) {
5205
+ close(inputId);
5206
+ }
5207
+ if (lastOutputId != -1) {
5208
+ close(lastOutputId);
5209
+ }
5210
+ if (errorId != -1) {
5211
+ close(errorId);
50705212
}
50715213
Jim_Free(arg_array);
50725214
50735215
JimRestoreEnv(save_environ);
50745216
50755217
return numPids;
50765218
50775219
50785220
error:
5079
- if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
5080
- JimCloseFd(*inPipePtr);
5081
- *inPipePtr = JIM_BAD_FD;
5082
- }
5083
- if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
5084
- JimCloseFd(*outPipePtr);
5085
- *outPipePtr = JIM_BAD_FD;
5086
- }
5087
- if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
5088
- JimCloseFd(*errFilePtr);
5089
- *errFilePtr = JIM_BAD_FD;
5090
- }
5091
- if (pipeIds[0] != JIM_BAD_FD) {
5092
- JimCloseFd(pipeIds[0]);
5093
- }
5094
- if (pipeIds[1] != JIM_BAD_FD) {
5095
- JimCloseFd(pipeIds[1]);
5221
+ if ((inPipePtr != NULL) && (*inPipePtr != -1)) {
5222
+ close(*inPipePtr);
5223
+ *inPipePtr = -1;
5224
+ }
5225
+ if ((outPipePtr != NULL) && (*outPipePtr != -1)) {
5226
+ close(*outPipePtr);
5227
+ *outPipePtr = -1;
5228
+ }
5229
+ if ((errFilePtr != NULL) && (*errFilePtr != -1)) {
5230
+ close(*errFilePtr);
5231
+ *errFilePtr = -1;
5232
+ }
5233
+ if (pipeIds[0] != -1) {
5234
+ close(pipeIds[0]);
5235
+ }
5236
+ if (pipeIds[1] != -1) {
5237
+ close(pipeIds[1]);
50965238
}
50975239
if (pidPtr != NULL) {
50985240
for (i = 0; i < numPids; i++) {
50995241
if (pidPtr[i] != JIM_BAD_PID) {
5100
- JimDetachPids(interp, 1, &pidPtr[i]);
5242
+ JimDetachPids(table, 1, &pidPtr[i]);
51015243
}
51025244
}
51035245
Jim_Free(pidPtr);
51045246
}
51055247
numPids = -1;
@@ -5111,11 +5253,11 @@
51115253
{
51125254
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
51135255
int result = JIM_OK;
51145256
int i;
51155257
5116
-
5258
+
51175259
for (i = 0; i < numPids; i++) {
51185260
int waitStatus = 0;
51195261
if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
51205262
if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
51215263
result = JIM_ERR;
@@ -5127,234 +5269,30 @@
51275269
return result;
51285270
}
51295271
51305272
int Jim_execInit(Jim_Interp *interp)
51315273
{
5274
+ struct WaitInfoTable *waitinfo;
51325275
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
51335276
return JIM_ERR;
51345277
51355278
#ifdef SIGPIPE
51365279
(void)signal(SIGPIPE, SIG_IGN);
51375280
#endif
51385281
5139
- Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
5282
+ waitinfo = JimAllocWaitInfoTable();
5283
+ Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable);
5284
+ waitinfo->refcount++;
5285
+ Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable);
5286
+ Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0);
5287
+
51405288
return JIM_OK;
51415289
}
51425290
51435291
#if defined(__MINGW32__)
51445292
51455293
5146
-static SECURITY_ATTRIBUTES *JimStdSecAttrs(void)
5147
-{
5148
- static SECURITY_ATTRIBUTES secAtts;
5149
-
5150
- secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
5151
- secAtts.lpSecurityDescriptor = NULL;
5152
- secAtts.bInheritHandle = TRUE;
5153
- return &secAtts;
5154
-}
5155
-
5156
-static int JimErrno(void)
5157
-{
5158
- switch (GetLastError()) {
5159
- case ERROR_FILE_NOT_FOUND: return ENOENT;
5160
- case ERROR_PATH_NOT_FOUND: return ENOENT;
5161
- case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
5162
- case ERROR_ACCESS_DENIED: return EACCES;
5163
- case ERROR_INVALID_HANDLE: return EBADF;
5164
- case ERROR_BAD_ENVIRONMENT: return E2BIG;
5165
- case ERROR_BAD_FORMAT: return ENOEXEC;
5166
- case ERROR_INVALID_ACCESS: return EACCES;
5167
- case ERROR_INVALID_DRIVE: return ENOENT;
5168
- case ERROR_CURRENT_DIRECTORY: return EACCES;
5169
- case ERROR_NOT_SAME_DEVICE: return EXDEV;
5170
- case ERROR_NO_MORE_FILES: return ENOENT;
5171
- case ERROR_WRITE_PROTECT: return EROFS;
5172
- case ERROR_BAD_UNIT: return ENXIO;
5173
- case ERROR_NOT_READY: return EBUSY;
5174
- case ERROR_BAD_COMMAND: return EIO;
5175
- case ERROR_CRC: return EIO;
5176
- case ERROR_BAD_LENGTH: return EIO;
5177
- case ERROR_SEEK: return EIO;
5178
- case ERROR_WRITE_FAULT: return EIO;
5179
- case ERROR_READ_FAULT: return EIO;
5180
- case ERROR_GEN_FAILURE: return EIO;
5181
- case ERROR_SHARING_VIOLATION: return EACCES;
5182
- case ERROR_LOCK_VIOLATION: return EACCES;
5183
- case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
5184
- case ERROR_HANDLE_DISK_FULL: return ENOSPC;
5185
- case ERROR_NOT_SUPPORTED: return ENODEV;
5186
- case ERROR_REM_NOT_LIST: return EBUSY;
5187
- case ERROR_DUP_NAME: return EEXIST;
5188
- case ERROR_BAD_NETPATH: return ENOENT;
5189
- case ERROR_NETWORK_BUSY: return EBUSY;
5190
- case ERROR_DEV_NOT_EXIST: return ENODEV;
5191
- case ERROR_TOO_MANY_CMDS: return EAGAIN;
5192
- case ERROR_ADAP_HDW_ERR: return EIO;
5193
- case ERROR_BAD_NET_RESP: return EIO;
5194
- case ERROR_UNEXP_NET_ERR: return EIO;
5195
- case ERROR_NETNAME_DELETED: return ENOENT;
5196
- case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
5197
- case ERROR_BAD_DEV_TYPE: return ENODEV;
5198
- case ERROR_BAD_NET_NAME: return ENOENT;
5199
- case ERROR_TOO_MANY_NAMES: return ENFILE;
5200
- case ERROR_TOO_MANY_SESS: return EIO;
5201
- case ERROR_SHARING_PAUSED: return EAGAIN;
5202
- case ERROR_REDIR_PAUSED: return EAGAIN;
5203
- case ERROR_FILE_EXISTS: return EEXIST;
5204
- case ERROR_CANNOT_MAKE: return ENOSPC;
5205
- case ERROR_OUT_OF_STRUCTURES: return ENFILE;
5206
- case ERROR_ALREADY_ASSIGNED: return EEXIST;
5207
- case ERROR_INVALID_PASSWORD: return EPERM;
5208
- case ERROR_NET_WRITE_FAULT: return EIO;
5209
- case ERROR_NO_PROC_SLOTS: return EAGAIN;
5210
- case ERROR_DISK_CHANGE: return EXDEV;
5211
- case ERROR_BROKEN_PIPE: return EPIPE;
5212
- case ERROR_OPEN_FAILED: return ENOENT;
5213
- case ERROR_DISK_FULL: return ENOSPC;
5214
- case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
5215
- case ERROR_INVALID_TARGET_HANDLE: return EBADF;
5216
- case ERROR_INVALID_NAME: return ENOENT;
5217
- case ERROR_PROC_NOT_FOUND: return ESRCH;
5218
- case ERROR_WAIT_NO_CHILDREN: return ECHILD;
5219
- case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
5220
- case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
5221
- case ERROR_SEEK_ON_DEVICE: return ESPIPE;
5222
- case ERROR_BUSY_DRIVE: return EAGAIN;
5223
- case ERROR_DIR_NOT_EMPTY: return EEXIST;
5224
- case ERROR_NOT_LOCKED: return EACCES;
5225
- case ERROR_BAD_PATHNAME: return ENOENT;
5226
- case ERROR_LOCK_FAILED: return EACCES;
5227
- case ERROR_ALREADY_EXISTS: return EEXIST;
5228
- case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
5229
- case ERROR_BAD_PIPE: return EPIPE;
5230
- case ERROR_PIPE_BUSY: return EAGAIN;
5231
- case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
5232
- case ERROR_DIRECTORY: return ENOTDIR;
5233
- }
5234
- return EINVAL;
5235
-}
5236
-
5237
-static int JimPipe(fdtype pipefd[2])
5238
-{
5239
- if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) {
5240
- return 0;
5241
- }
5242
- return -1;
5243
-}
5244
-
5245
-static fdtype JimDupFd(fdtype infd)
5246
-{
5247
- fdtype dupfd;
5248
- pidtype pid = GetCurrentProcess();
5249
-
5250
- if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
5251
- return dupfd;
5252
- }
5253
- return JIM_BAD_FD;
5254
-}
5255
-
5256
-static int JimRewindFd(fdtype fd)
5257
-{
5258
- return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0;
5259
-}
5260
-
5261
-#if 0
5262
-static int JimReadFd(fdtype fd, char *buffer, size_t len)
5263
-{
5264
- DWORD num;
5265
-
5266
- if (ReadFile(fd, buffer, len, &num, NULL)) {
5267
- return num;
5268
- }
5269
- if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) {
5270
- return 0;
5271
- }
5272
- return -1;
5273
-}
5274
-#endif
5275
-
5276
-static FILE *JimFdOpenForRead(fdtype fd)
5277
-{
5278
- return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r");
5279
-}
5280
-
5281
-static fdtype JimFileno(FILE *fh)
5282
-{
5283
- return (fdtype)_get_osfhandle(_fileno(fh));
5284
-}
5285
-
5286
-static fdtype JimOpenForRead(const char *filename)
5287
-{
5288
- return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
5289
- JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
5290
-}
5291
-
5292
-static fdtype JimOpenForWrite(const char *filename, int append)
5293
-{
5294
- return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5295
- JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
5296
-}
5297
-
5298
-static FILE *JimFdOpenForWrite(fdtype fd)
5299
-{
5300
- return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
5301
-}
5302
-
5303
-static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
5304
-{
5305
- DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
5306
- if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
5307
-
5308
- return JIM_BAD_PID;
5309
- }
5310
- GetExitCodeProcess(pid, &ret);
5311
- *status = ret;
5312
- CloseHandle(pid);
5313
- return pid;
5314
-}
5315
-
5316
-static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5317
-{
5318
- char name[MAX_PATH];
5319
- HANDLE handle;
5320
-
5321
- if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
5322
- return JIM_BAD_FD;
5323
- }
5324
-
5325
- handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(),
5326
- CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
5327
- NULL);
5328
-
5329
- if (handle == INVALID_HANDLE_VALUE) {
5330
- goto error;
5331
- }
5332
-
5333
- if (contents != NULL) {
5334
-
5335
- FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
5336
- if (fh == NULL) {
5337
- goto error;
5338
- }
5339
-
5340
- if (fwrite(contents, len, 1, fh) != 1) {
5341
- fclose(fh);
5342
- goto error;
5343
- }
5344
- fseek(fh, 0, SEEK_SET);
5345
- fclose(fh);
5346
- }
5347
- return handle;
5348
-
5349
- error:
5350
- Jim_SetResultErrno(interp, "failed to create temp file");
5351
- CloseHandle(handle);
5352
- DeleteFile(name);
5353
- return JIM_BAD_FD;
5354
-}
5355
-
53565294
static int
53575295
JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
53585296
{
53595297
int i;
53605298
static char extensions[][5] = {".exe", "", ".bat"};
@@ -5381,10 +5319,15 @@
53815319
53825320
static void JimRestoreEnv(char **env)
53835321
{
53845322
JimFreeEnv(env, Jim_GetEnviron());
53855323
}
5324
+
5325
+static char **JimOriginalEnviron(void)
5326
+{
5327
+ return NULL;
5328
+}
53865329
53875330
static Jim_Obj *
53885331
JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
53895332
{
53905333
char *start, *special;
@@ -5455,18 +5398,19 @@
54555398
}
54565399
return strObj;
54575400
}
54585401
54595402
static pidtype
5460
-JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
5403
+JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId)
54615404
{
54625405
STARTUPINFO startInfo;
54635406
PROCESS_INFORMATION procInfo;
5464
- HANDLE hProcess, h;
5407
+ HANDLE hProcess;
54655408
char execPath[MAX_PATH];
54665409
pidtype pid = JIM_BAD_PID;
54675410
Jim_Obj *cmdLineObj;
5411
+ char *winenv;
54685412
54695413
if (JimWinFindExecutable(argv[0], execPath) < 0) {
54705414
return JIM_BAD_PID;
54715415
}
54725416
argv[0] = execPath;
@@ -5480,47 +5424,51 @@
54805424
startInfo.dwFlags = STARTF_USESTDHANDLES;
54815425
startInfo.hStdInput = INVALID_HANDLE_VALUE;
54825426
startInfo.hStdOutput= INVALID_HANDLE_VALUE;
54835427
startInfo.hStdError = INVALID_HANDLE_VALUE;
54845428
5485
- if (inputId == JIM_BAD_FD) {
5486
- if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
5487
- CloseHandle(h);
5488
- }
5489
- } else {
5490
- DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
5491
- 0, TRUE, DUPLICATE_SAME_ACCESS);
5492
- }
5493
- if (startInfo.hStdInput == JIM_BAD_FD) {
5494
- goto end;
5495
- }
5496
-
5497
- if (outputId == JIM_BAD_FD) {
5498
- startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
5499
- JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
5500
- } else {
5501
- DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
5502
- 0, TRUE, DUPLICATE_SAME_ACCESS);
5503
- }
5504
- if (startInfo.hStdOutput == JIM_BAD_FD) {
5505
- goto end;
5506
- }
5507
-
5508
- if (errorId == JIM_BAD_FD) {
5509
-
5510
- startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
5511
- JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
5512
- } else {
5513
- DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
5514
- 0, TRUE, DUPLICATE_SAME_ACCESS);
5515
- }
5516
- if (startInfo.hStdError == JIM_BAD_FD) {
5517
- goto end;
5518
- }
5519
-
5520
- if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5521
- 0, env, NULL, &startInfo, &procInfo)) {
5429
+ if (inputId == -1) {
5430
+ inputId = _fileno(stdin);
5431
+ }
5432
+ DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput,
5433
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
5434
+ if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {
5435
+ goto end;
5436
+ }
5437
+
5438
+ if (outputId == -1) {
5439
+ outputId = _fileno(stdout);
5440
+ }
5441
+ DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput,
5442
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
5443
+ if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) {
5444
+ goto end;
5445
+ }
5446
+
5447
+
5448
+ if (errorId == -1) {
5449
+ errorId = _fileno(stderr);
5450
+ }
5451
+ DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError,
5452
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
5453
+ if (startInfo.hStdError == INVALID_HANDLE_VALUE) {
5454
+ goto end;
5455
+ }
5456
+
5457
+ if (env == NULL) {
5458
+
5459
+ winenv = NULL;
5460
+ }
5461
+ else if (env[0] == NULL) {
5462
+ winenv = (char *)"\0";
5463
+ }
5464
+ else {
5465
+ winenv = env[0];
5466
+ }
5467
+
5468
+ if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5469
+ 0, winenv, NULL, &startInfo, &procInfo)) {
55225470
goto end;
55235471
}
55245472
55255473
55265474
WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5528,49 +5476,27 @@
55285476
55295477
pid = procInfo.hProcess;
55305478
55315479
end:
55325480
Jim_FreeNewObj(interp, cmdLineObj);
5533
- if (startInfo.hStdInput != JIM_BAD_FD) {
5481
+ if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
55345482
CloseHandle(startInfo.hStdInput);
55355483
}
5536
- if (startInfo.hStdOutput != JIM_BAD_FD) {
5484
+ if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) {
55375485
CloseHandle(startInfo.hStdOutput);
55385486
}
5539
- if (startInfo.hStdError != JIM_BAD_FD) {
5487
+ if (startInfo.hStdError != INVALID_HANDLE_VALUE) {
55405488
CloseHandle(startInfo.hStdError);
55415489
}
55425490
return pid;
55435491
}
5492
+
55445493
#else
55455494
5546
-static int JimOpenForWrite(const char *filename, int append)
5547
-{
5548
- return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
5549
-}
5550
-
5551
-static int JimRewindFd(int fd)
5552
-{
5553
- return lseek(fd, 0L, SEEK_SET);
5554
-}
5555
-
5556
-static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5557
-{
5558
- int fd = Jim_MakeTempFile(interp, NULL);
5559
-
5560
- if (fd != JIM_BAD_FD) {
5561
- unlink(Jim_String(Jim_GetResult(interp)));
5562
- if (contents) {
5563
- if (write(fd, contents, len) != len) {
5564
- Jim_SetResultErrno(interp, "couldn't write temp file");
5565
- close(fd);
5566
- return -1;
5567
- }
5568
- lseek(fd, 0L, SEEK_SET);
5569
- }
5570
- }
5571
- return fd;
5495
+static char **JimOriginalEnviron(void)
5496
+{
5497
+ return Jim_GetEnviron();
55725498
}
55735499
55745500
static char **JimSaveEnv(char **env)
55755501
{
55765502
char **saveenv = Jim_GetEnviron();
@@ -5585,13 +5511,21 @@
55855511
}
55865512
#endif
55875513
#endif
55885514
55895515
5516
+
5517
+#ifdef STRPTIME_NEEDS_XOPEN_SOURCE
55905518
#ifndef _XOPEN_SOURCE
55915519
#define _XOPEN_SOURCE 500
55925520
#endif
5521
+#endif
5522
+
5523
+
5524
+#ifndef _GNU_SOURCE
5525
+#define _GNU_SOURCE
5526
+#endif
55935527
55945528
#include <stdlib.h>
55955529
#include <string.h>
55965530
#include <stdio.h>
55975531
#include <time.h>
@@ -5598,65 +5532,126 @@
55985532
55995533
56005534
#ifdef HAVE_SYS_TIME_H
56015535
#include <sys/time.h>
56025536
#endif
5537
+
5538
+struct clock_options {
5539
+ int gmt;
5540
+ const char *format;
5541
+};
5542
+
5543
+static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts)
5544
+{
5545
+ static const char * const options[] = { "-gmt", "-format", NULL };
5546
+ enum { OPT_GMT, OPT_FORMAT, };
5547
+ int i;
5548
+
5549
+ for (i = 0; i < argc; i += 2) {
5550
+ int option;
5551
+ if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
5552
+ return JIM_ERR;
5553
+ }
5554
+ switch (option) {
5555
+ case OPT_GMT:
5556
+ if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) {
5557
+ return JIM_ERR;
5558
+ }
5559
+ break;
5560
+ case OPT_FORMAT:
5561
+ opts->format = Jim_String(argv[i + 1]);
5562
+ break;
5563
+ }
5564
+ }
5565
+ return JIM_OK;
5566
+}
56035567
56045568
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
56055569
{
5606
-
5570
+
56075571
char buf[100];
56085572
time_t t;
5609
- long seconds;
5573
+ jim_wide seconds;
5574
+ struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" };
5575
+ struct tm *tm;
56105576
5611
- const char *format = "%a %b %d %H:%M:%S %Z %Y";
5612
-
5613
- if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5577
+ if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) {
5578
+ return JIM_ERR;
5579
+ }
5580
+ if (argc % 2 == 0) {
56145581
return -1;
56155582
}
5616
-
5617
- if (argc == 3) {
5618
- format = Jim_String(argv[2]);
5583
+ if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
5584
+ return JIM_ERR;
56195585
}
56205586
5621
- if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5622
- return JIM_ERR;
5623
- }
56245587
t = seconds;
5588
+ tm = options.gmt ? gmtime(&t) : localtime(&t);
56255589
5626
- if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5627
- Jim_SetResultString(interp, "format string too long", -1);
5590
+ if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) {
5591
+ Jim_SetResultString(interp, "format string too long or invalid time", -1);
56285592
return JIM_ERR;
56295593
}
56305594
56315595
Jim_SetResultString(interp, buf, -1);
56325596
56335597
return JIM_OK;
56345598
}
56355599
56365600
#ifdef HAVE_STRPTIME
5601
+#ifndef HAVE_TIMEGM
5602
+
5603
+static time_t timegm(struct tm *tm)
5604
+{
5605
+ time_t t;
5606
+ const char *tz = getenv("TZ");
5607
+ setenv("TZ", "", 1);
5608
+ tzset();
5609
+ t = mktime(tm);
5610
+ if (tz) {
5611
+ setenv("TZ", tz, 1);
5612
+ }
5613
+ else {
5614
+ unsetenv("TZ");
5615
+ }
5616
+ tzset();
5617
+ return t;
5618
+}
5619
+#endif
5620
+
56375621
static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
56385622
{
56395623
char *pt;
56405624
struct tm tm;
5641
- time_t now = time(0);
56425625
5643
- if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
5626
+
5627
+ struct clock_options options = { 0, NULL };
5628
+
5629
+ if (argc % 2 == 0) {
5630
+ return -1;
5631
+ }
5632
+
5633
+ if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
5634
+ return JIM_ERR;
5635
+ }
5636
+ if (options.format == NULL) {
56445637
return -1;
56455638
}
56465639
5647
-
5648
- localtime_r(&now, &tm);
56495640
5650
- pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
5641
+ memset(&tm, 0, sizeof(tm));
5642
+
5643
+ tm.tm_mday = 1;
5644
+
5645
+ pt = strptime(Jim_String(argv[0]), options.format, &tm);
56515646
if (pt == 0 || *pt != 0) {
56525647
Jim_SetResultString(interp, "Failed to parse time according to format", -1);
56535648
return JIM_ERR;
56545649
}
56555650
5656
-
5657
- Jim_SetResultInt(interp, mktime(&tm));
5651
+
5652
+ Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm));
56585653
56595654
return JIM_OK;
56605655
}
56615656
#endif
56625657
@@ -5688,54 +5683,54 @@
56885683
56895684
return JIM_OK;
56905685
}
56915686
56925687
static const jim_subcmd_type clock_command_table[] = {
5693
- { "seconds",
5694
- NULL,
5695
- clock_cmd_seconds,
5696
- 0,
5697
- 0,
5698
-
5699
- },
57005688
{ "clicks",
57015689
NULL,
57025690
clock_cmd_micros,
57035691
0,
57045692
0,
5705
-
5693
+
5694
+ },
5695
+ { "format",
5696
+ "seconds ?-format string? ?-gmt boolean?",
5697
+ clock_cmd_format,
5698
+ 1,
5699
+ 5,
5700
+
57065701
},
57075702
{ "microseconds",
57085703
NULL,
57095704
clock_cmd_micros,
57105705
0,
57115706
0,
5712
-
5707
+
57135708
},
57145709
{ "milliseconds",
57155710
NULL,
57165711
clock_cmd_millis,
57175712
0,
57185713
0,
5719
-
5720
- },
5721
- { "format",
5722
- "seconds ?-format format?",
5723
- clock_cmd_format,
5724
- 1,
5725
- 3,
5726
-
5714
+
57275715
},
57285716
#ifdef HAVE_STRPTIME
57295717
{ "scan",
5730
- "str -format format",
5718
+ "str -format format ?-gmt boolean?",
57315719
clock_cmd_scan,
57325720
3,
5733
- 3,
5734
-
5721
+ 5,
5722
+
57355723
},
57365724
#endif
5725
+ { "seconds",
5726
+ NULL,
5727
+ clock_cmd_seconds,
5728
+ 0,
5729
+ 0,
5730
+
5731
+ },
57375732
{ NULL }
57385733
};
57395734
57405735
int Jim_clockInit(Jim_Interp *interp)
57415736
{
@@ -5753,12 +5748,13 @@
57535748
#include <errno.h>
57545749
57555750
57565751
static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57575752
{
5758
-
5759
- Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
5753
+
5754
+ Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5755
+ Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
57605756
return JIM_OK;
57615757
}
57625758
57635759
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57645760
{
@@ -5769,21 +5765,20 @@
57695765
return JIM_OK;
57705766
}
57715767
57725768
patternObj = (argc == 1) ? NULL : argv[1];
57735769
5774
-
5770
+
57755771
if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
57765772
if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5777
-
5773
+
57785774
Jim_SetResult(interp, objPtr);
57795775
return JIM_OK;
57805776
}
57815777
}
57825778
5783
-
5784
- return Jim_DictValues(interp, objPtr, patternObj);
5779
+ return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES);
57855780
}
57865781
57875782
static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57885783
{
57895784
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5785,11 @@
57905785
57915786
if (!objPtr) {
57925787
return JIM_OK;
57935788
}
57945789
5795
- return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
5790
+ return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS);
57965791
}
57975792
57985793
static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57995794
{
58005795
int i;
@@ -5802,27 +5797,29 @@
58025797
Jim_Obj *resultObj;
58035798
Jim_Obj *objPtr;
58045799
Jim_Obj **dictValuesObj;
58055800
58065801
if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5807
-
5802
+
58085803
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
58095804
return JIM_OK;
58105805
}
58115806
58125807
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
58135808
58145809
if (objPtr == NULL) {
5815
-
5810
+
58165811
return JIM_OK;
58175812
}
58185813
58195814
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5820
- return JIM_ERR;
5815
+
5816
+ Jim_SetResultString(interp, "", -1);
5817
+ return JIM_OK;
58215818
}
58225819
5823
-
5820
+
58245821
resultObj = Jim_NewDictObj(interp, NULL, 0);
58255822
58265823
for (i = 0; i < len; i += 2) {
58275824
if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
58285825
Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5834,18 @@
58375834
static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
58385835
{
58395836
Jim_Obj *objPtr;
58405837
int len = 0;
58415838
5842
-
5839
+
58435840
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
58445841
if (objPtr) {
58455842
len = Jim_DictSize(interp, objPtr);
58465843
if (len < 0) {
5847
- return JIM_ERR;
5844
+
5845
+ Jim_SetResultInt(interp, 0);
5846
+ return JIM_OK;
58485847
}
58495848
}
58505849
58515850
Jim_SetResultInt(interp, len);
58525851
@@ -5876,11 +5875,11 @@
58765875
return JIM_ERR;
58775876
}
58785877
58795878
dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
58805879
if (!dictObj) {
5881
-
5880
+
58825881
return Jim_SetVariable(interp, argv[0], listObj);
58835882
}
58845883
else if (Jim_DictSize(interp, dictObj) < 0) {
58855884
return JIM_ERR;
58865885
}
@@ -5905,53 +5904,53 @@
59055904
{ "exists",
59065905
"arrayName",
59075906
array_cmd_exists,
59085907
1,
59095908
1,
5910
-
5909
+
59115910
},
59125911
{ "get",
59135912
"arrayName ?pattern?",
59145913
array_cmd_get,
59155914
1,
59165915
2,
5917
-
5916
+
59185917
},
59195918
{ "names",
59205919
"arrayName ?pattern?",
59215920
array_cmd_names,
59225921
1,
59235922
2,
5924
-
5923
+
59255924
},
59265925
{ "set",
59275926
"arrayName list",
59285927
array_cmd_set,
59295928
2,
59305929
2,
5931
-
5930
+
59325931
},
59335932
{ "size",
59345933
"arrayName",
59355934
array_cmd_size,
59365935
1,
59375936
1,
5938
-
5937
+
59395938
},
59405939
{ "stat",
59415940
"arrayName",
59425941
array_cmd_stat,
59435942
1,
59445943
1,
5945
-
5944
+
59465945
},
59475946
{ "unset",
59485947
"arrayName ?pattern?",
59495948
array_cmd_unset,
59505949
1,
59515950
2,
5952
-
5951
+
59535952
},
59545953
{ NULL
59555954
}
59565955
};
59575956
@@ -5987,11 +5986,14 @@
59875986
Jim_arrayInit(interp);
59885987
Jim_stdlibInit(interp);
59895988
Jim_tclcompatInit(interp);
59905989
return JIM_OK;
59915990
}
5992
-#define JIM_OPTIMIZATION
5991
+#define JIM_OPTIMIZATION
5992
+#ifndef _GNU_SOURCE
5993
+#define _GNU_SOURCE
5994
+#endif
59935995
59945996
#include <stdio.h>
59955997
#include <stdlib.h>
59965998
59975999
#include <string.h>
@@ -6056,10 +6058,16 @@
60566058
#define JimPanic(X) JimPanicDump X
60576059
#else
60586060
#define JimPanic(X)
60596061
#endif
60606062
6063
+#ifdef JIM_OPTIMIZATION
6064
+#define JIM_IF_OPTIM(X) X
6065
+#else
6066
+#define JIM_IF_OPTIM(X)
6067
+#endif
6068
+
60616069
60626070
static char JimEmptyStringRep[] = "";
60636071
60646072
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
60656073
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6120,34 @@
61126120
if (*pattern == '^') {
61136121
not++;
61146122
pattern++;
61156123
}
61166124
6117
-
6125
+
61186126
if (*pattern == ']') {
61196127
goto first;
61206128
}
61216129
}
61226130
61236131
while (*pattern && *pattern != ']') {
6124
-
6132
+
61256133
if (pattern[0] == '\\') {
61266134
first:
61276135
pattern += utf8_tounicode_case(pattern, &pchar, nocase);
61286136
}
61296137
else {
6130
-
6138
+
61316139
int start;
61326140
int end;
61336141
61346142
pattern += utf8_tounicode_case(pattern, &start, nocase);
61356143
if (pattern[0] == '-' && pattern[1]) {
6136
-
6137
- pattern += utf8_tounicode(pattern, &pchar);
6144
+
6145
+ pattern++;
61386146
pattern += utf8_tounicode_case(pattern, &end, nocase);
61396147
6140
-
6148
+
61416149
if ((c >= start && c <= end) || (c >= end && c <= start)) {
61426150
match = 1;
61436151
}
61446152
continue;
61456153
}
@@ -6169,19 +6177,19 @@
61696177
while (pattern[1] == '*') {
61706178
pattern++;
61716179
}
61726180
pattern++;
61736181
if (!pattern[0]) {
6174
- return 1;
6182
+ return 1;
61756183
}
61766184
while (*string) {
6177
-
6185
+
61786186
if (JimGlobMatch(pattern, string, nocase))
6179
- return 1;
6187
+ return 1;
61806188
string += utf8_tounicode(string, &c);
61816189
}
6182
- return 0;
6190
+ return 0;
61836191
61846192
case '?':
61856193
string += utf8_tounicode(string, &c);
61866194
break;
61876195
@@ -6190,20 +6198,20 @@
61906198
pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
61916199
if (!pattern) {
61926200
return 0;
61936201
}
61946202
if (!*pattern) {
6195
-
6203
+
61966204
continue;
61976205
}
61986206
break;
61996207
}
62006208
case '\\':
62016209
if (pattern[1]) {
62026210
pattern++;
62036211
}
6204
-
6212
+
62056213
default:
62066214
string += utf8_tounicode_case(string, &c, nocase);
62076215
utf8_tounicode_case(pattern, &pchar, nocase);
62086216
if (pchar != c) {
62096217
return 0;
@@ -6249,11 +6257,11 @@
62496257
maxchars--;
62506258
}
62516259
if (!maxchars) {
62526260
return 0;
62536261
}
6254
-
6262
+
62556263
if (*s1) {
62566264
return 1;
62576265
}
62586266
if (*s2) {
62596267
return -1;
@@ -6290,11 +6298,11 @@
62906298
const char *p;
62916299
62926300
if (!l1 || !l2 || l1 > l2)
62936301
return -1;
62946302
6295
-
6303
+
62966304
for (p = s2 + l2 - 1; p != s2 - 1; p--) {
62976305
if (*p == *s1 && memcmp(s1, p, l1) == 0) {
62986306
return p - s2;
62996307
}
63006308
}
@@ -6349,28 +6357,28 @@
63496357
}
63506358
*sign = 1;
63516359
}
63526360
63536361
if (str[i] != '0') {
6354
-
6362
+
63556363
return 0;
63566364
}
63576365
6358
-
6366
+
63596367
switch (str[i + 1]) {
63606368
case 'x': case 'X': *base = 16; break;
63616369
case 'o': case 'O': *base = 8; break;
63626370
case 'b': case 'B': *base = 2; break;
63636371
default: return 0;
63646372
}
63656373
i += 2;
6366
-
6374
+
63676375
if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6368
-
6376
+
63696377
return i;
63706378
}
6371
-
6379
+
63726380
*base = 10;
63736381
return 0;
63746382
}
63756383
63766384
static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6392,11 @@
63846392
if (endptr == NULL || *endptr != str + i) {
63856393
return value * sign;
63866394
}
63876395
}
63886396
6389
-
6397
+
63906398
return strtol(str, endptr, 10);
63916399
}
63926400
63936401
63946402
static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6411,11 @@
64036411
if (endptr == NULL || *endptr != str + i) {
64046412
return value * sign;
64056413
}
64066414
}
64076415
6408
-
6416
+
64096417
return strtoull(str, endptr, 10);
64106418
#else
64116419
return (unsigned long)jim_strtol(str, endptr);
64126420
#endif
64136421
}
@@ -6428,26 +6436,40 @@
64286436
64296437
int Jim_StringToDouble(const char *str, double *doublePtr)
64306438
{
64316439
char *endptr;
64326440
6433
-
6441
+
64346442
errno = 0;
64356443
64366444
*doublePtr = strtod(str, &endptr);
64376445
64386446
return JimCheckConversion(str, endptr);
64396447
}
64406448
64416449
static jim_wide JimPowWide(jim_wide b, jim_wide e)
64426450
{
6443
- jim_wide i, res = 1;
6451
+ jim_wide res = 1;
64446452
6445
- if ((b == 0 && e != 0) || (e < 0))
6446
- return 0;
6447
- for (i = 0; i < e; i++) {
6448
- res *= b;
6453
+
6454
+ if (b == 1) {
6455
+
6456
+ return 1;
6457
+ }
6458
+ if (e < 0) {
6459
+ if (b != -1) {
6460
+ return 0;
6461
+ }
6462
+ e = -e;
6463
+ }
6464
+ while (e)
6465
+ {
6466
+ if (e & 1) {
6467
+ res *= b;
6468
+ }
6469
+ e >>= 1;
6470
+ b *= b;
64496471
}
64506472
return res;
64516473
}
64526474
64536475
#ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6531,11 @@
65096531
char *Jim_StrDupLen(const char *s, int l)
65106532
{
65116533
char *copy = Jim_Alloc(l + 1);
65126534
65136535
memcpy(copy, s, l + 1);
6514
- copy[l] = 0;
6536
+ copy[l] = 0;
65156537
return copy;
65166538
}
65176539
65186540
65196541
@@ -6598,52 +6620,52 @@
65986620
}
65996621
66006622
66016623
void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
66026624
{
6603
- Jim_HashTable n;
6625
+ Jim_HashTable n;
66046626
unsigned int realsize = JimHashTableNextPower(size), i;
66056627
66066628
if (size <= ht->used)
66076629
return;
66086630
66096631
Jim_InitHashTable(&n, ht->type, ht->privdata);
66106632
n.size = realsize;
66116633
n.sizemask = realsize - 1;
66126634
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6613
-
6635
+
66146636
n.uniq = ht->uniq;
66156637
6616
-
6638
+
66176639
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
66186640
66196641
n.used = ht->used;
66206642
for (i = 0; ht->used > 0; i++) {
66216643
Jim_HashEntry *he, *nextHe;
66226644
66236645
if (ht->table[i] == NULL)
66246646
continue;
66256647
6626
-
6648
+
66276649
he = ht->table[i];
66286650
while (he) {
66296651
unsigned int h;
66306652
66316653
nextHe = he->next;
6632
-
6654
+
66336655
h = Jim_HashKey(ht, he->key) & n.sizemask;
66346656
he->next = n.table[h];
66356657
n.table[h] = he;
66366658
ht->used--;
6637
-
6659
+
66386660
he = nextHe;
66396661
}
66406662
}
66416663
assert(ht->used == 0);
66426664
Jim_Free(ht->table);
66436665
6644
-
6666
+
66456667
*ht = n;
66466668
}
66476669
66486670
66496671
int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6674,11 @@
66526674
66536675
entry = JimInsertHashEntry(ht, key, 0);
66546676
if (entry == NULL)
66556677
return JIM_ERR;
66566678
6657
-
6679
+
66586680
Jim_SetHashKey(ht, entry, key);
66596681
Jim_SetHashVal(ht, entry, val);
66606682
return JIM_OK;
66616683
}
66626684
@@ -6678,11 +6700,11 @@
66786700
Jim_SetHashVal(ht, entry, val);
66796701
}
66806702
existed = 1;
66816703
}
66826704
else {
6683
-
6705
+
66846706
Jim_SetHashKey(ht, entry, key);
66856707
Jim_SetHashVal(ht, entry, val);
66866708
existed = 0;
66876709
}
66886710
@@ -6701,11 +6723,11 @@
67016723
he = ht->table[h];
67026724
67036725
prevHe = NULL;
67046726
while (he) {
67056727
if (Jim_CompareHashKeys(ht, key, he->key)) {
6706
-
6728
+
67076729
if (prevHe)
67086730
prevHe->next = he->next;
67096731
else
67106732
ht->table[h] = he->next;
67116733
Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6737,19 @@
67156737
return JIM_OK;
67166738
}
67176739
prevHe = he;
67186740
he = he->next;
67196741
}
6720
- return JIM_ERR;
6742
+ return JIM_ERR;
67216743
}
67226744
67236745
67246746
int Jim_FreeHashTable(Jim_HashTable *ht)
67256747
{
67266748
unsigned int i;
67276749
6728
-
6750
+
67296751
for (i = 0; ht->used > 0; i++) {
67306752
Jim_HashEntry *he, *nextHe;
67316753
67326754
if ((he = ht->table[i]) == NULL)
67336755
continue;
@@ -6738,15 +6760,15 @@
67386760
Jim_Free(he);
67396761
ht->used--;
67406762
he = nextHe;
67416763
}
67426764
}
6743
-
6765
+
67446766
Jim_Free(ht->table);
6745
-
6767
+
67466768
JimResetHashTable(ht);
6747
- return JIM_OK;
6769
+ return JIM_OK;
67486770
}
67496771
67506772
Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
67516773
{
67526774
Jim_HashEntry *he;
@@ -6819,24 +6841,24 @@
68196841
static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
68206842
{
68216843
unsigned int h;
68226844
Jim_HashEntry *he;
68236845
6824
-
6846
+
68256847
JimExpandHashTableIfNeeded(ht);
68266848
6827
-
6849
+
68286850
h = Jim_HashKey(ht, key) & ht->sizemask;
6829
-
6851
+
68306852
he = ht->table[h];
68316853
while (he) {
68326854
if (Jim_CompareHashKeys(ht, key, he->key))
68336855
return replace ? he : NULL;
68346856
he = he->next;
68356857
}
68366858
6837
-
6859
+
68386860
he = Jim_Alloc(sizeof(*he));
68396861
he->next = ht->table[h];
68406862
ht->table[h] = he;
68416863
ht->used++;
68426864
he->key = NULL;
@@ -6865,16 +6887,16 @@
68656887
{
68666888
Jim_Free(key);
68676889
}
68686890
68696891
static const Jim_HashTableType JimPackageHashTableType = {
6870
- JimStringCopyHTHashFunction,
6871
- JimStringCopyHTDup,
6872
- NULL,
6873
- JimStringCopyHTKeyCompare,
6874
- JimStringCopyHTKeyDestructor,
6875
- NULL
6892
+ JimStringCopyHTHashFunction,
6893
+ JimStringCopyHTDup,
6894
+ NULL,
6895
+ JimStringCopyHTKeyCompare,
6896
+ JimStringCopyHTKeyDestructor,
6897
+ NULL
68766898
};
68776899
68786900
typedef struct AssocDataValue
68796901
{
68806902
Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6911,16 @@
68896911
assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
68906912
Jim_Free(data);
68916913
}
68926914
68936915
static const Jim_HashTableType JimAssocDataHashTableType = {
6894
- JimStringCopyHTHashFunction,
6895
- JimStringCopyHTDup,
6896
- NULL,
6897
- JimStringCopyHTKeyCompare,
6898
- JimStringCopyHTKeyDestructor,
6899
- JimAssocDataHashTableValueDestructor
6916
+ JimStringCopyHTHashFunction,
6917
+ JimStringCopyHTDup,
6918
+ NULL,
6919
+ JimStringCopyHTKeyCompare,
6920
+ JimStringCopyHTKeyDestructor,
6921
+ JimAssocDataHashTableValueDestructor
69006922
};
69016923
69026924
void Jim_InitStack(Jim_Stack *stack)
69036925
{
69046926
stack->len = 0;
@@ -6951,56 +6973,61 @@
69516973
freeFunc(stack->vector[i]);
69526974
}
69536975
69546976
69556977
6956
-#define JIM_TT_NONE 0
6957
-#define JIM_TT_STR 1
6958
-#define JIM_TT_ESC 2
6959
-#define JIM_TT_VAR 3
6960
-#define JIM_TT_DICTSUGAR 4
6961
-#define JIM_TT_CMD 5
6962
-
6963
-#define JIM_TT_SEP 6
6964
-#define JIM_TT_EOL 7
6965
-#define JIM_TT_EOF 8
6966
-
6967
-#define JIM_TT_LINE 9
6968
-#define JIM_TT_WORD 10
6978
+#define JIM_TT_NONE 0
6979
+#define JIM_TT_STR 1
6980
+#define JIM_TT_ESC 2
6981
+#define JIM_TT_VAR 3
6982
+#define JIM_TT_DICTSUGAR 4
6983
+#define JIM_TT_CMD 5
6984
+
6985
+#define JIM_TT_SEP 6
6986
+#define JIM_TT_EOL 7
6987
+#define JIM_TT_EOF 8
6988
+
6989
+#define JIM_TT_LINE 9
6990
+#define JIM_TT_WORD 10
69696991
69706992
69716993
#define JIM_TT_SUBEXPR_START 11
69726994
#define JIM_TT_SUBEXPR_END 12
69736995
#define JIM_TT_SUBEXPR_COMMA 13
69746996
#define JIM_TT_EXPR_INT 14
69756997
#define JIM_TT_EXPR_DOUBLE 15
6998
+#define JIM_TT_EXPR_BOOLEAN 16
69766999
6977
-#define JIM_TT_EXPRSUGAR 16
7000
+#define JIM_TT_EXPRSUGAR 17
69787001
69797002
69807003
#define JIM_TT_EXPR_OP 20
69817004
69827005
#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
69837006
7007
+#define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA)
7008
+
7009
+#define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP)
7010
+
69847011
struct JimParseMissing {
6985
- int ch;
6986
- int line;
7012
+ int ch;
7013
+ int line;
69877014
};
69887015
69897016
struct JimParserCtx
69907017
{
6991
- const char *p;
6992
- int len;
6993
- int linenr;
7018
+ const char *p;
7019
+ int len;
7020
+ int linenr;
69947021
const char *tstart;
6995
- const char *tend;
6996
- int tline;
6997
- int tt;
6998
- int eof;
6999
- int inquote;
7000
- int comment;
7001
- struct JimParseMissing missing;
7022
+ const char *tend;
7023
+ int tline;
7024
+ int tt;
7025
+ int eof;
7026
+ int inquote;
7027
+ int comment;
7028
+ struct JimParseMissing missing;
70027029
};
70037030
70047031
static int JimParseScript(struct JimParserCtx *pc);
70057032
static int JimParseSep(struct JimParserCtx *pc);
70067033
static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7057,11 @@
70307057
pc->missing.line = linenr;
70317058
}
70327059
70337060
static int JimParseScript(struct JimParserCtx *pc)
70347061
{
7035
- while (1) {
7062
+ while (1) {
70367063
if (!pc->len) {
70377064
pc->tstart = pc->p;
70387065
pc->tend = pc->p - 1;
70397066
pc->tline = pc->linenr;
70407067
pc->tt = JIM_TT_EOL;
@@ -7066,11 +7093,11 @@
70667093
pc->comment = 0;
70677094
return JimParseCmd(pc);
70687095
case '$':
70697096
pc->comment = 0;
70707097
if (JimParseVar(pc) == JIM_ERR) {
7071
-
7098
+
70727099
pc->tstart = pc->tend = pc->p++;
70737100
pc->len--;
70747101
pc->tt = JIM_TT_ESC;
70757102
}
70767103
return JIM_OK;
@@ -7127,11 +7154,11 @@
71277154
71287155
static void JimParseSubBrace(struct JimParserCtx *pc)
71297156
{
71307157
int level = 1;
71317158
7132
-
7159
+
71337160
pc->p++;
71347161
pc->len--;
71357162
while (pc->len) {
71367163
switch (*pc->p) {
71377164
case '\\':
@@ -7171,11 +7198,11 @@
71717198
static int JimParseSubQuote(struct JimParserCtx *pc)
71727199
{
71737200
int tt = JIM_TT_STR;
71747201
int line = pc->tline;
71757202
7176
-
7203
+
71777204
pc->p++;
71787205
pc->len--;
71797206
while (pc->len) {
71807207
switch (*pc->p) {
71817208
case '\\':
@@ -7220,11 +7247,11 @@
72207247
{
72217248
int level = 1;
72227249
int startofword = 1;
72237250
int line = pc->tline;
72247251
7225
-
7252
+
72267253
pc->p++;
72277254
pc->len--;
72287255
while (pc->len) {
72297256
switch (*pc->p) {
72307257
case '\\':
@@ -7300,17 +7327,17 @@
73007327
return JIM_OK;
73017328
}
73027329
73037330
static int JimParseVar(struct JimParserCtx *pc)
73047331
{
7305
-
7332
+
73067333
pc->p++;
73077334
pc->len--;
73087335
73097336
#ifdef EXPRSUGAR_BRACKET
73107337
if (*pc->p == '[') {
7311
-
7338
+
73127339
JimParseCmd(pc);
73137340
pc->tt = JIM_TT_EXPRSUGAR;
73147341
return JIM_OK;
73157342
}
73167343
#endif
@@ -7336,11 +7363,11 @@
73367363
pc->len--;
73377364
}
73387365
}
73397366
else {
73407367
while (1) {
7341
-
7368
+
73427369
if (pc->p[0] == ':' && pc->p[1] == ':') {
73437370
while (*pc->p == ':') {
73447371
pc->p++;
73457372
pc->len--;
73467373
}
@@ -7351,11 +7378,11 @@
73517378
pc->len--;
73527379
continue;
73537380
}
73547381
break;
73557382
}
7356
-
7383
+
73577384
if (*pc->p == '(') {
73587385
int count = 1;
73597386
const char *paren = NULL;
73607387
73617388
pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7405,11 @@
73787405
if (count == 0) {
73797406
pc->p++;
73807407
pc->len--;
73817408
}
73827409
else if (paren) {
7383
-
7410
+
73847411
paren++;
73857412
pc->len += (pc->p - paren);
73867413
pc->p = paren;
73877414
}
73887415
#ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7430,19 @@
74037430
74047431
static int JimParseStr(struct JimParserCtx *pc)
74057432
{
74067433
if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
74077434
pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7408
-
7435
+
74097436
if (*pc->p == '{') {
74107437
return JimParseBrace(pc);
74117438
}
74127439
if (*pc->p == '"') {
74137440
pc->inquote = 1;
74147441
pc->p++;
74157442
pc->len--;
7416
-
7443
+
74177444
pc->missing.line = pc->tline;
74187445
}
74197446
}
74207447
pc->tstart = pc->p;
74217448
pc->tline = pc->linenr;
@@ -7441,25 +7468,25 @@
74417468
}
74427469
pc->p++;
74437470
pc->len--;
74447471
}
74457472
else if (pc->len == 1) {
7446
-
7473
+
74477474
pc->missing.ch = '\\';
74487475
}
74497476
break;
74507477
case '(':
7451
-
7478
+
74527479
if (pc->len > 1 && pc->p[1] != '$') {
74537480
break;
74547481
}
7455
-
7482
+
74567483
case ')':
7457
-
7484
+
74587485
if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
74597486
if (pc->p == pc->tstart) {
7460
-
7487
+
74617488
pc->p++;
74627489
pc->len--;
74637490
}
74647491
pc->tend = pc->p - 1;
74657492
pc->tt = JIM_TT_ESC;
@@ -7499,11 +7526,11 @@
74997526
break;
75007527
}
75017528
pc->p++;
75027529
pc->len--;
75037530
}
7504
- return JIM_OK;
7531
+ return JIM_OK;
75057532
}
75067533
75077534
static int JimParseComment(struct JimParserCtx *pc)
75087535
{
75097536
while (*pc->p) {
@@ -7610,34 +7637,34 @@
76107637
if (c == -1) {
76117638
break;
76127639
}
76137640
val = (val << 4) | c;
76147641
}
7615
-
7642
+
76167643
if (s[i] == '{') {
76177644
if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7618
-
7645
+
76197646
i--;
76207647
k = 0;
76217648
}
76227649
else {
7623
-
7650
+
76247651
k++;
76257652
}
76267653
}
76277654
if (k) {
7628
-
7655
+
76297656
if (s[i] == 'x') {
76307657
*p++ = val;
76317658
}
76327659
else {
76337660
p += utf8_fromunicode(p, val);
76347661
}
76357662
i += k;
76367663
break;
76377664
}
7638
-
7665
+
76397666
*p++ = s[i];
76407667
}
76417668
break;
76427669
case 'v':
76437670
*p++ = 0xb;
@@ -7646,11 +7673,11 @@
76467673
case '\0':
76477674
*p++ = '\\';
76487675
i++;
76497676
break;
76507677
case '\n':
7651
-
7678
+
76527679
*p++ = ' ';
76537680
do {
76547681
i++;
76557682
} while (s[i + 1] == ' ' || s[i + 1] == '\t');
76567683
break;
@@ -7660,11 +7687,11 @@
76607687
case '3':
76617688
case '4':
76627689
case '5':
76637690
case '6':
76647691
case '7':
7665
-
7692
+
76667693
{
76677694
int val = 0;
76687695
int c = odigitval(s[i + 1]);
76697696
76707697
val = c;
@@ -7708,27 +7735,23 @@
77087735
char *token;
77097736
int len;
77107737
77117738
start = pc->tstart;
77127739
end = pc->tend;
7713
- if (start > end) {
7740
+ len = (end - start) + 1;
7741
+ if (len < 0) {
77147742
len = 0;
7715
- token = Jim_Alloc(1);
7716
- token[0] = '\0';
7717
- }
7718
- else {
7719
- len = (end - start) + 1;
7720
- token = Jim_Alloc(len + 1);
7721
- if (pc->tt != JIM_TT_ESC) {
7722
-
7723
- memcpy(token, start, len);
7724
- token[len] = '\0';
7725
- }
7726
- else {
7727
-
7728
- len = JimEscape(token, start, len);
7729
- }
7743
+ }
7744
+ token = Jim_Alloc(len + 1);
7745
+ if (pc->tt != JIM_TT_ESC) {
7746
+
7747
+ memcpy(token, start, len);
7748
+ token[len] = '\0';
7749
+ }
7750
+ else {
7751
+
7752
+ len = JimEscape(token, start, len);
77307753
}
77317754
77327755
return Jim_NewStringObjNoAlloc(interp, token, len);
77337756
}
77347757
@@ -7790,11 +7813,11 @@
77907813
while (pc->len) {
77917814
switch (*pc->p) {
77927815
case '\\':
77937816
pc->tt = JIM_TT_ESC;
77947817
if (--pc->len == 0) {
7795
-
7818
+
77967819
pc->tend = pc->p;
77977820
return JIM_OK;
77987821
}
77997822
pc->p++;
78007823
break;
@@ -7826,11 +7849,11 @@
78267849
pc->tend = pc->p - 1;
78277850
return JIM_OK;
78287851
}
78297852
if (*pc->p == '\\') {
78307853
if (--pc->len == 0) {
7831
-
7854
+
78327855
pc->tend = pc->p;
78337856
return JIM_OK;
78347857
}
78357858
pc->tt = JIM_TT_ESC;
78367859
pc->p++;
@@ -7846,24 +7869,24 @@
78467869
78477870
Jim_Obj *Jim_NewObj(Jim_Interp *interp)
78487871
{
78497872
Jim_Obj *objPtr;
78507873
7851
-
7874
+
78527875
if (interp->freeList != NULL) {
7853
-
7876
+
78547877
objPtr = interp->freeList;
78557878
interp->freeList = objPtr->nextObjPtr;
78567879
}
78577880
else {
7858
-
7881
+
78597882
objPtr = Jim_Alloc(sizeof(*objPtr));
78607883
}
78617884
78627885
objPtr->refCount = 0;
78637886
7864
-
7887
+
78657888
objPtr->prevObjPtr = NULL;
78667889
objPtr->nextObjPtr = interp->liveList;
78677890
if (interp->liveList)
78687891
interp->liveList->prevObjPtr = objPtr;
78697892
interp->liveList = objPtr;
@@ -7871,32 +7894,32 @@
78717894
return objPtr;
78727895
}
78737896
78747897
void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
78757898
{
7876
-
7899
+
78777900
JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
78787901
objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
78797902
7880
-
7903
+
78817904
Jim_FreeIntRep(interp, objPtr);
7882
-
7905
+
78837906
if (objPtr->bytes != NULL) {
78847907
if (objPtr->bytes != JimEmptyStringRep)
78857908
Jim_Free(objPtr->bytes);
78867909
}
7887
-
7910
+
78887911
if (objPtr->prevObjPtr)
78897912
objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
78907913
if (objPtr->nextObjPtr)
78917914
objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
78927915
if (interp->liveList == objPtr)
78937916
interp->liveList = objPtr->nextObjPtr;
78947917
#ifdef JIM_DISABLE_OBJECT_POOL
78957918
Jim_Free(objPtr);
78967919
#else
7897
-
7920
+
78987921
objPtr->prevObjPtr = NULL;
78997922
objPtr->nextObjPtr = interp->freeList;
79007923
if (interp->freeList)
79017924
interp->freeList->prevObjPtr = objPtr;
79027925
interp->freeList = objPtr;
@@ -7919,45 +7942,44 @@
79197942
{
79207943
Jim_Obj *dupPtr;
79217944
79227945
dupPtr = Jim_NewObj(interp);
79237946
if (objPtr->bytes == NULL) {
7924
-
7947
+
79257948
dupPtr->bytes = NULL;
79267949
}
79277950
else if (objPtr->length == 0) {
7928
-
79297951
dupPtr->bytes = JimEmptyStringRep;
79307952
dupPtr->length = 0;
79317953
dupPtr->typePtr = NULL;
79327954
return dupPtr;
79337955
}
79347956
else {
79357957
dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
79367958
dupPtr->length = objPtr->length;
7937
-
7959
+
79387960
memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
79397961
}
79407962
7941
-
7963
+
79427964
dupPtr->typePtr = objPtr->typePtr;
79437965
if (objPtr->typePtr != NULL) {
79447966
if (objPtr->typePtr->dupIntRepProc == NULL) {
79457967
dupPtr->internalRep = objPtr->internalRep;
79467968
}
79477969
else {
7948
-
7970
+
79497971
objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
79507972
}
79517973
}
79527974
return dupPtr;
79537975
}
79547976
79557977
const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
79567978
{
79577979
if (objPtr->bytes == NULL) {
7958
-
7980
+
79597981
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
79607982
objPtr->typePtr->updateStringProc(objPtr);
79617983
}
79627984
if (lenPtr)
79637985
*lenPtr = objPtr->length;
@@ -7966,25 +7988,22 @@
79667988
79677989
79687990
int Jim_Length(Jim_Obj *objPtr)
79697991
{
79707992
if (objPtr->bytes == NULL) {
7971
-
7972
- JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7973
- objPtr->typePtr->updateStringProc(objPtr);
7993
+
7994
+ Jim_GetString(objPtr, NULL);
79747995
}
79757996
return objPtr->length;
79767997
}
79777998
79787999
79798000
const char *Jim_String(Jim_Obj *objPtr)
79808001
{
79818002
if (objPtr->bytes == NULL) {
7982
-
7983
- JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
7984
- JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7985
- objPtr->typePtr->updateStringProc(objPtr);
8003
+
8004
+ Jim_GetString(objPtr, NULL);
79868005
}
79878006
return objPtr->bytes;
79888007
}
79898008
79908009
static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
@@ -8001,23 +8020,34 @@
80018020
FreeDictSubstInternalRep,
80028021
DupDictSubstInternalRep,
80038022
NULL,
80048023
JIM_TYPE_NONE,
80058024
};
8025
+
8026
+static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8027
+static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8028
+
8029
+static const Jim_ObjType interpolatedObjType = {
8030
+ "interpolated",
8031
+ FreeInterpolatedInternalRep,
8032
+ DupInterpolatedInternalRep,
8033
+ NULL,
8034
+ JIM_TYPE_NONE,
8035
+};
80068036
80078037
static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
80088038
{
80098039
Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
80108040
}
80118041
8012
-static const Jim_ObjType interpolatedObjType = {
8013
- "interpolated",
8014
- FreeInterpolatedInternalRep,
8015
- NULL,
8016
- NULL,
8017
- JIM_TYPE_NONE,
8018
-};
8042
+static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8043
+{
8044
+
8045
+ dupPtr->internalRep = srcPtr->internalRep;
8046
+
8047
+ Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
8048
+}
80198049
80208050
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
80218051
static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
80228052
80238053
static const Jim_ObjType stringObjType = {
@@ -8037,22 +8067,22 @@
80378067
}
80388068
80398069
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
80408070
{
80418071
if (objPtr->typePtr != &stringObjType) {
8042
-
8072
+
80438073
if (objPtr->bytes == NULL) {
8044
-
8074
+
80458075
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
80468076
objPtr->typePtr->updateStringProc(objPtr);
80478077
}
8048
-
8078
+
80498079
Jim_FreeIntRep(interp, objPtr);
8050
-
8080
+
80518081
objPtr->typePtr = &stringObjType;
80528082
objPtr->internalRep.strValue.maxLength = objPtr->length;
8053
-
8083
+
80548084
objPtr->internalRep.strValue.charLength = -1;
80558085
}
80568086
return JIM_OK;
80578087
}
80588088
@@ -8073,39 +8103,37 @@
80738103
80748104
Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
80758105
{
80768106
Jim_Obj *objPtr = Jim_NewObj(interp);
80778107
8078
-
8108
+
80798109
if (len == -1)
80808110
len = strlen(s);
8081
-
8111
+
80828112
if (len == 0) {
80838113
objPtr->bytes = JimEmptyStringRep;
80848114
}
80858115
else {
8086
- objPtr->bytes = Jim_Alloc(len + 1);
8087
- memcpy(objPtr->bytes, s, len);
8088
- objPtr->bytes[len] = '\0';
8116
+ objPtr->bytes = Jim_StrDupLen(s, len);
80898117
}
80908118
objPtr->length = len;
80918119
8092
-
8120
+
80938121
objPtr->typePtr = NULL;
80948122
return objPtr;
80958123
}
80968124
80978125
80988126
Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
80998127
{
81008128
#ifdef JIM_UTF8
8101
-
8129
+
81028130
int bytelen = utf8_index(s, charlen);
81038131
81048132
Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
81058133
8106
-
8134
+
81078135
objPtr->typePtr = &stringObjType;
81088136
objPtr->internalRep.strValue.maxLength = bytelen;
81098137
objPtr->internalRep.strValue.charLength = charlen;
81108138
81118139
return objPtr;
@@ -8132,11 +8160,11 @@
81328160
len = strlen(str);
81338161
needlen = objPtr->length + len;
81348162
if (objPtr->internalRep.strValue.maxLength < needlen ||
81358163
objPtr->internalRep.strValue.maxLength == 0) {
81368164
needlen *= 2;
8137
-
8165
+
81388166
if (needlen < 7) {
81398167
needlen = 7;
81408168
}
81418169
if (objPtr->bytes == JimEmptyStringRep) {
81428170
objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8176,11 @@
81488176
}
81498177
memcpy(objPtr->bytes + objPtr->length, str, len);
81508178
objPtr->bytes[objPtr->length + len] = '\0';
81518179
81528180
if (objPtr->internalRep.strValue.charLength >= 0) {
8153
-
8181
+
81548182
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
81558183
}
81568184
objPtr->length += len;
81578185
}
81588186
@@ -8210,11 +8238,11 @@
82108238
int l1, l2;
82118239
const char *s1 = Jim_GetString(firstObjPtr, &l1);
82128240
const char *s2 = Jim_GetString(secondObjPtr, &l2);
82138241
82148242
if (nocase) {
8215
-
8243
+
82168244
return JimStringCompareLen(s1, s2, -1, nocase);
82178245
}
82188246
return JimStringCompare(s1, l1, s2, l2);
82198247
}
82208248
@@ -8312,11 +8340,11 @@
83128340
83138341
if (first == 0 && rangeLen == len) {
83148342
return strObjPtr;
83158343
}
83168344
if (len == bytelen) {
8317
-
8345
+
83188346
return Jim_NewStringObj(interp, str + first, rangeLen);
83198347
}
83208348
return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
83218349
#else
83228350
return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8369,19 @@
83418369
return strObjPtr;
83428370
}
83438371
83448372
str = Jim_String(strObjPtr);
83458373
8346
-
8374
+
83478375
objPtr = Jim_NewStringObjUtf8(interp, str, first);
83488376
8349
-
8377
+
83508378
if (newStrObj) {
83518379
Jim_AppendObj(interp, objPtr, newStrObj);
83528380
}
83538381
8354
-
8382
+
83558383
Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
83568384
83578385
return objPtr;
83588386
}
83598387
@@ -8371,12 +8399,10 @@
83718399
{
83728400
char *buf;
83738401
int len;
83748402
const char *str;
83758403
8376
- SetStringFromAny(interp, strObjPtr);
8377
-
83788404
str = Jim_GetString(strObjPtr, &len);
83798405
83808406
#ifdef JIM_UTF8
83818407
len *= 2;
83828408
#endif
@@ -8389,14 +8415,10 @@
83898415
{
83908416
char *buf;
83918417
const char *str;
83928418
int len;
83938419
8394
- if (strObjPtr->typePtr != &stringObjType) {
8395
- SetStringFromAny(interp, strObjPtr);
8396
- }
8397
-
83988420
str = Jim_GetString(strObjPtr, &len);
83998421
84008422
#ifdef JIM_UTF8
84018423
len *= 2;
84028424
#endif
@@ -8411,13 +8433,11 @@
84118433
int len;
84128434
int c;
84138435
const char *str;
84148436
84158437
str = Jim_GetString(strObjPtr, &len);
8416
- if (len == 0) {
8417
- return strObjPtr;
8418
- }
8438
+
84198439
#ifdef JIM_UTF8
84208440
len *= 2;
84218441
#endif
84228442
buf = p = Jim_Alloc(len + 1);
84238443
@@ -8452,11 +8472,11 @@
84528472
while (len) {
84538473
int c;
84548474
int n = utf8_tounicode(str, &c);
84558475
84568476
if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8457
-
8477
+
84588478
break;
84598479
}
84608480
str += n;
84618481
len -= n;
84628482
}
@@ -8523,41 +8543,41 @@
85238543
85248544
len = Jim_Length(strObjPtr);
85258545
nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
85268546
85278547
if (nontrim == NULL) {
8528
-
8548
+
85298549
return Jim_NewEmptyStringObj(interp);
85308550
}
85318551
if (nontrim == strObjPtr->bytes + len) {
8532
-
8552
+
85338553
return strObjPtr;
85348554
}
85358555
85368556
if (Jim_IsShared(strObjPtr)) {
85378557
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
85388558
}
85398559
else {
8540
-
8560
+
85418561
strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
85428562
strObjPtr->length = (nontrim - strObjPtr->bytes);
85438563
}
85448564
85458565
return strObjPtr;
85468566
}
85478567
85488568
static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
85498569
{
8550
-
8570
+
85518571
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
85528572
8553
-
8573
+
85548574
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
85558575
8556
-
8576
+
85578577
if (objPtr != strObjPtr && objPtr->refCount == 0) {
8558
-
8578
+
85598579
Jim_FreeNewObj(interp, objPtr);
85608580
}
85618581
85628582
return strObjPtr;
85638583
}
@@ -8575,17 +8595,17 @@
85758595
static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
85768596
{
85778597
static const char * const strclassnames[] = {
85788598
"integer", "alpha", "alnum", "ascii", "digit",
85798599
"double", "lower", "upper", "space", "xdigit",
8580
- "control", "print", "graph", "punct",
8600
+ "control", "print", "graph", "punct", "boolean",
85818601
NULL
85828602
};
85838603
enum {
85848604
STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
85858605
STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8586
- STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT
8606
+ STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN,
85878607
};
85888608
int strclass;
85898609
int len;
85908610
int i;
85918611
const char *str;
@@ -8613,10 +8633,17 @@
86138633
{
86148634
double d;
86158635
Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
86168636
return JIM_OK;
86178637
}
8638
+
8639
+ case STR_IS_BOOLEAN:
8640
+ {
8641
+ int b;
8642
+ Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK);
8643
+ return JIM_OK;
8644
+ }
86188645
86198646
case STR_IS_ALPHA: isclassfunc = isalpha; break;
86208647
case STR_IS_ALNUM: isclassfunc = isalnum; break;
86218648
case STR_IS_ASCII: isclassfunc = jim_isascii; break;
86228649
case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8658,11 @@
86318658
default:
86328659
return JIM_ERR;
86338660
}
86348661
86358662
for (i = 0; i < len; i++) {
8636
- if (!isclassfunc(str[i])) {
8663
+ if (!isclassfunc(UCHAR(str[i]))) {
86378664
Jim_SetResultBool(interp, 0);
86388665
return JIM_OK;
86398666
}
86408667
}
86418668
Jim_SetResultBool(interp, 1);
@@ -8656,20 +8683,18 @@
86568683
{
86578684
if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
86588685
return 1;
86598686
}
86608687
else {
8661
- const char *objStr = Jim_String(objPtr);
8662
-
8663
- if (strcmp(str, objStr) != 0)
8688
+ if (strcmp(str, Jim_String(objPtr)) != 0)
86648689
return 0;
86658690
86668691
if (objPtr->typePtr != &comparedStringObjType) {
86678692
Jim_FreeIntRep(interp, objPtr);
86688693
objPtr->typePtr = &comparedStringObjType;
86698694
}
8670
- objPtr->internalRep.ptr = (char *)str;
8695
+ objPtr->internalRep.ptr = (char *)str;
86718696
return 1;
86728697
}
86738698
}
86748699
86758700
static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8783,20 @@
87588783
int type;
87598784
} ScriptToken;
87608785
87618786
typedef struct ScriptObj
87628787
{
8763
- ScriptToken *token;
8764
- Jim_Obj *fileNameObj;
8765
- int len;
8766
- int substFlags;
8788
+ ScriptToken *token;
8789
+ Jim_Obj *fileNameObj;
8790
+ int len;
8791
+ int substFlags;
87678792
int inUse; /* Used to share a ScriptObj. Currently
87688793
only used by Jim_EvalObj() as protection against
87698794
shimmering of the currently evaluated object. */
8770
- int firstline;
8771
- int linenr;
8772
- int missing;
8795
+ int firstline;
8796
+ int linenr;
8797
+ int missing;
87738798
} ScriptObj;
87748799
87758800
static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
87768801
static int JimParseCheckMissing(Jim_Interp *interp, int ch);
87778802
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8824,23 @@
87998824
dupPtr->typePtr = NULL;
88008825
}
88018826
88028827
typedef struct
88038828
{
8804
- const char *token;
8805
- int len;
8806
- int type;
8807
- int line;
8829
+ const char *token;
8830
+ int len;
8831
+ int type;
8832
+ int line;
88088833
} ParseToken;
88098834
88108835
typedef struct
88118836
{
8812
-
8813
- ParseToken *list;
8814
- int size;
8815
- int count;
8816
- ParseToken static_list[20];
8837
+
8838
+ ParseToken *list;
8839
+ int size;
8840
+ int count;
8841
+ ParseToken static_list[20];
88178842
} ParseTokenList;
88188843
88198844
static void ScriptTokenListInit(ParseTokenList *tokenlist)
88208845
{
88218846
tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8859,18 @@
88348859
int line)
88358860
{
88368861
ParseToken *t;
88378862
88388863
if (tokenlist->count == tokenlist->size) {
8839
-
8864
+
88408865
tokenlist->size *= 2;
88418866
if (tokenlist->list != tokenlist->static_list) {
88428867
tokenlist->list =
88438868
Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
88448869
}
88458870
else {
8846
-
8871
+
88478872
tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
88488873
memcpy(tokenlist->list, tokenlist->static_list,
88498874
tokenlist->count * sizeof(*tokenlist->list));
88508875
}
88518876
}
@@ -8854,25 +8879,32 @@
88548879
t->len = len;
88558880
t->type = type;
88568881
t->line = line;
88578882
}
88588883
8859
-static int JimCountWordTokens(ParseToken *t)
8884
+static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t)
88608885
{
88618886
int expand = 1;
88628887
int count = 0;
88638888
8864
-
8889
+
88658890
if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
88668891
if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8867
-
8892
+
88688893
expand = -1;
88698894
t++;
88708895
}
8896
+ else {
8897
+ if (script->missing == ' ') {
8898
+
8899
+ script->missing = '}';
8900
+ script->linenr = t[1].line;
8901
+ }
8902
+ }
88718903
}
88728904
8873
-
8905
+
88748906
while (!TOKEN_IS_SEP(t->type)) {
88758907
t++;
88768908
count++;
88778909
}
88788910
@@ -8882,11 +8914,11 @@
88828914
static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
88838915
{
88848916
Jim_Obj *objPtr;
88858917
88868918
if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8887
-
8919
+
88888920
int len = t->len;
88898921
char *str = Jim_Alloc(len + 1);
88908922
len = JimEscape(str, t->token, len);
88918923
objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
88928924
}
@@ -8899,13 +8931,13 @@
88998931
static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
89008932
ParseTokenList *tokenlist)
89018933
{
89028934
int i;
89038935
struct ScriptToken *token;
8904
-
8936
+
89058937
int lineargs = 0;
8906
-
8938
+
89078939
ScriptToken *linefirst;
89088940
int count;
89098941
int linenr;
89108942
89118943
#ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +8946,11 @@
89148946
printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
89158947
tokenlist->list[i].len, tokenlist->list[i].token);
89168948
}
89178949
#endif
89188950
8919
-
8951
+
89208952
count = tokenlist->count;
89218953
for (i = 0; i < tokenlist->count; i++) {
89228954
if (tokenlist->list[i].type == JIM_TT_EOL) {
89238955
count++;
89248956
}
@@ -8925,59 +8957,59 @@
89258957
}
89268958
linenr = script->firstline = tokenlist->list[0].line;
89278959
89288960
token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
89298961
8930
-
8962
+
89318963
linefirst = token++;
89328964
89338965
for (i = 0; i < tokenlist->count; ) {
8934
-
8966
+
89358967
int wordtokens;
89368968
8937
-
8969
+
89388970
while (tokenlist->list[i].type == JIM_TT_SEP) {
89398971
i++;
89408972
}
89418973
8942
- wordtokens = JimCountWordTokens(tokenlist->list + i);
8974
+ wordtokens = JimCountWordTokens(script, tokenlist->list + i);
89438975
89448976
if (wordtokens == 0) {
8945
-
8977
+
89468978
if (lineargs) {
89478979
linefirst->type = JIM_TT_LINE;
89488980
linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
89498981
Jim_IncrRefCount(linefirst->objPtr);
89508982
8951
-
8983
+
89528984
lineargs = 0;
89538985
linefirst = token++;
89548986
}
89558987
i++;
89568988
continue;
89578989
}
89588990
else if (wordtokens != 1) {
8959
-
8991
+
89608992
token->type = JIM_TT_WORD;
89618993
token->objPtr = Jim_NewIntObj(interp, wordtokens);
89628994
Jim_IncrRefCount(token->objPtr);
89638995
token++;
89648996
if (wordtokens < 0) {
8965
-
8997
+
89668998
i++;
89678999
wordtokens = -wordtokens - 1;
89689000
lineargs--;
89699001
}
89709002
}
89719003
89729004
if (lineargs == 0) {
8973
-
9005
+
89749006
linenr = tokenlist->list[i].line;
89759007
}
89769008
lineargs++;
89779009
8978
-
9010
+
89799011
while (wordtokens--) {
89809012
const ParseToken *t = &tokenlist->list[i++];
89819013
89829014
token->type = t->type;
89839015
token->objPtr = JimMakeScriptObj(interp, t);
@@ -9010,11 +9042,11 @@
90109042
{
90119043
ScriptObj *script = JimGetScript(interp, scriptObj);
90129044
if (stateCharPtr) {
90139045
*stateCharPtr = script->missing;
90149046
}
9015
- return (script->missing == ' ');
9047
+ return script->missing == ' ' || script->missing == '}';
90169048
}
90179049
90189050
static int JimParseCheckMissing(Jim_Interp *interp, int ch)
90199051
{
90209052
const char *msg;
@@ -9028,10 +9060,13 @@
90289060
msg = "unmatched \"[\"";
90299061
break;
90309062
case '{':
90319063
msg = "missing close-brace";
90329064
break;
9065
+ case '}':
9066
+ msg = "extra characters after close-brace";
9067
+ break;
90339068
case '"':
90349069
default:
90359070
msg = "missing quote";
90369071
break;
90379072
}
@@ -9049,11 +9084,11 @@
90499084
token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
90509085
90519086
for (i = 0; i < tokenlist->count; i++) {
90529087
const ParseToken *t = &tokenlist->list[i];
90539088
9054
-
9089
+
90559090
token->type = t->type;
90569091
token->objPtr = JimMakeScriptObj(interp, t);
90579092
Jim_IncrRefCount(token->objPtr);
90589093
token++;
90599094
}
@@ -9068,29 +9103,29 @@
90689103
struct JimParserCtx parser;
90699104
struct ScriptObj *script;
90709105
ParseTokenList tokenlist;
90719106
int line = 1;
90729107
9073
-
9108
+
90749109
if (objPtr->typePtr == &sourceObjType) {
90759110
line = objPtr->internalRep.sourceValue.lineNumber;
90769111
}
90779112
9078
-
9113
+
90799114
ScriptTokenListInit(&tokenlist);
90809115
90819116
JimParserInit(&parser, scriptText, scriptTextLen, line);
90829117
while (!parser.eof) {
90839118
JimParseScript(&parser);
90849119
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
90859120
parser.tline);
90869121
}
90879122
9088
-
9123
+
90899124
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
90909125
9091
-
9126
+
90929127
script = Jim_Alloc(sizeof(*script));
90939128
memset(script, 0, sizeof(*script));
90949129
script->inUse = 1;
90959130
if (objPtr->typePtr == &sourceObjType) {
90969131
script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9137,14 @@
91029137
script->missing = parser.missing.ch;
91039138
script->linenr = parser.missing.line;
91049139
91059140
ScriptObjAddTokens(interp, script, &tokenlist);
91069141
9107
-
9142
+
91089143
ScriptTokenListFree(&tokenlist);
91099144
9110
-
9145
+
91119146
Jim_FreeIntRep(interp, objPtr);
91129147
Jim_SetIntRepPtr(objPtr, script);
91139148
objPtr->typePtr = &scriptObjType;
91149149
}
91159150
@@ -9116,11 +9151,11 @@
91169151
static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
91179152
91189153
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
91199154
{
91209155
if (objPtr == interp->emptyObj) {
9121
-
9156
+
91229157
objPtr = interp->nullScriptObj;
91239158
}
91249159
91259160
if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
91269161
JimSetScriptFromAny(interp, objPtr);
@@ -9155,67 +9190,66 @@
91559190
Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
91569191
Jim_Free(cmdPtr->u.proc.staticVars);
91579192
}
91589193
}
91599194
else {
9160
-
9195
+
91619196
if (cmdPtr->u.native.delProc) {
91629197
cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
91639198
}
91649199
}
91659200
if (cmdPtr->prevCmd) {
9166
-
9201
+
91679202
JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
91689203
}
91699204
Jim_Free(cmdPtr);
91709205
}
91719206
}
9172
-
91739207
91749208
static void JimVariablesHTValDestructor(void *interp, void *val)
91759209
{
91769210
Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
91779211
Jim_Free(val);
91789212
}
91799213
91809214
static const Jim_HashTableType JimVariablesHashTableType = {
9181
- JimStringCopyHTHashFunction,
9182
- JimStringCopyHTDup,
9183
- NULL,
9184
- JimStringCopyHTKeyCompare,
9185
- JimStringCopyHTKeyDestructor,
9186
- JimVariablesHTValDestructor
9215
+ JimStringCopyHTHashFunction,
9216
+ JimStringCopyHTDup,
9217
+ NULL,
9218
+ JimStringCopyHTKeyCompare,
9219
+ JimStringCopyHTKeyDestructor,
9220
+ JimVariablesHTValDestructor
91879221
};
91889222
91899223
static void JimCommandsHT_ValDestructor(void *interp, void *val)
91909224
{
91919225
JimDecrCmdRefCount(interp, val);
91929226
}
91939227
91949228
static const Jim_HashTableType JimCommandsHashTableType = {
9195
- JimStringCopyHTHashFunction,
9196
- JimStringCopyHTDup,
9197
- NULL,
9198
- JimStringCopyHTKeyCompare,
9199
- JimStringCopyHTKeyDestructor,
9200
- JimCommandsHT_ValDestructor
9229
+ JimStringCopyHTHashFunction,
9230
+ JimStringCopyHTDup,
9231
+ NULL,
9232
+ JimStringCopyHTKeyCompare,
9233
+ JimStringCopyHTKeyDestructor,
9234
+ JimCommandsHT_ValDestructor
92019235
};
92029236
92039237
92049238
92059239
#ifdef jim_ext_namespace
92069240
static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
92079241
{
92089242
const char *name = Jim_String(nsObj);
92099243
if (name[0] == ':' && name[1] == ':') {
9210
-
9244
+
92119245
while (*++name == ':') {
92129246
}
92139247
nsObj = Jim_NewStringObj(interp, name, -1);
92149248
}
92159249
else if (Jim_Length(interp->framePtr->nsObj)) {
9216
-
9250
+
92179251
nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
92189252
Jim_AppendStrings(interp, nsObj, "::", name, NULL);
92199253
}
92209254
return nsObj;
92219255
}
@@ -9239,16 +9273,16 @@
92399273
static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
92409274
{
92419275
Jim_Obj *objPtr = interp->emptyObj;
92429276
92439277
if (name[0] == ':' && name[1] == ':') {
9244
-
9278
+
92459279
while (*++name == ':') {
92469280
}
92479281
}
92489282
else if (Jim_Length(interp->framePtr->nsObj)) {
9249
-
9283
+
92509284
objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
92519285
Jim_AppendStrings(interp, objPtr, "::", name, NULL);
92529286
name = Jim_String(objPtr);
92539287
}
92549288
Jim_IncrRefCount(objPtr);
@@ -9257,11 +9291,11 @@
92579291
}
92589292
92599293
#define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
92609294
92619295
#else
9262
-
9296
+
92639297
#define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
92649298
#define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
92659299
92669300
Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
92679301
{
@@ -9276,17 +9310,17 @@
92769310
92779311
Jim_InterpIncrProcEpoch(interp);
92789312
}
92799313
92809314
if (he && interp->local) {
9281
-
9315
+
92829316
cmd->prevCmd = Jim_GetHashEntryVal(he);
92839317
Jim_SetHashVal(&interp->commands, he, cmd);
92849318
}
92859319
else {
92869320
if (he) {
9287
-
9321
+
92889322
Jim_DeleteHashEntry(&interp->commands, name);
92899323
}
92909324
92919325
Jim_AddHashEntry(&interp->commands, name, cmd);
92929326
}
@@ -9297,11 +9331,11 @@
92979331
int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
92989332
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
92999333
{
93009334
Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
93019335
9302
-
9336
+
93039337
memset(cmdPtr, 0, sizeof(*cmdPtr));
93049338
cmdPtr->inUse = 1;
93059339
cmdPtr->u.native.delProc = delProc;
93069340
cmdPtr->u.native.cmdProc = cmdProc;
93079341
cmdPtr->u.native.privData = privData;
@@ -9326,11 +9360,11 @@
93269360
Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
93279361
Jim_Var *varPtr;
93289362
int subLen;
93299363
93309364
objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9331
-
9365
+
93329366
subLen = Jim_ListLength(interp, objPtr);
93339367
if (subLen == 1 || subLen == 2) {
93349368
nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
93359369
if (subLen == 1) {
93369370
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9406,19 @@
93729406
93739407
static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
93749408
{
93759409
#ifdef jim_ext_namespace
93769410
if (cmdPtr->isproc) {
9377
-
9411
+
93789412
const char *pt = strrchr(cmdname, ':');
93799413
if (pt && pt != cmdname && pt[-1] == ':') {
93809414
Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
93819415
cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
93829416
Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
93839417
93849418
if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9385
-
9419
+
93869420
Jim_InterpIncrProcEpoch(interp);
93879421
}
93889422
}
93899423
}
93909424
#endif
@@ -9397,11 +9431,11 @@
93979431
int argListLen;
93989432
int i;
93999433
94009434
argListLen = Jim_ListLength(interp, argListObjPtr);
94019435
9402
-
9436
+
94039437
cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
94049438
memset(cmdPtr, 0, sizeof(*cmdPtr));
94059439
cmdPtr->inUse = 1;
94069440
cmdPtr->isproc = 1;
94079441
cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9446,24 @@
94129446
cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
94139447
Jim_IncrRefCount(argListObjPtr);
94149448
Jim_IncrRefCount(bodyObjPtr);
94159449
Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
94169450
9417
-
9451
+
94189452
if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
94199453
goto err;
94209454
}
94219455
9422
-
9423
-
9456
+
9457
+
94249458
for (i = 0; i < argListLen; i++) {
94259459
Jim_Obj *argPtr;
94269460
Jim_Obj *nameObjPtr;
94279461
Jim_Obj *defaultObjPtr;
94289462
int len;
94299463
9430
-
9464
+
94319465
argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
94329466
len = Jim_ListLength(interp, argPtr);
94339467
if (len == 0) {
94349468
Jim_SetResultString(interp, "argument with no name", -1);
94359469
err:
@@ -9440,16 +9474,16 @@
94409474
Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
94419475
goto err;
94429476
}
94439477
94449478
if (len == 2) {
9445
-
9479
+
94469480
nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
94479481
defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
94489482
}
94499483
else {
9450
-
9484
+
94519485
nameObjPtr = argPtr;
94529486
defaultObjPtr = NULL;
94539487
}
94549488
94559489
@@ -9510,29 +9544,29 @@
95109544
}
95119545
95129546
fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
95139547
fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
95149548
9515
-
9549
+
95169550
he = Jim_FindHashEntry(&interp->commands, fqold);
95179551
if (he == NULL) {
95189552
Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
95199553
}
95209554
else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
95219555
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
95229556
}
95239557
else {
9524
-
9558
+
95259559
cmdPtr = Jim_GetHashEntryVal(he);
95269560
JimIncrCmdRefCount(cmdPtr);
95279561
JimUpdateProcNamespace(interp, cmdPtr, fqnew);
95289562
Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
95299563
9530
-
9564
+
95319565
Jim_DeleteHashEntry(&interp->commands, fqold);
95329566
9533
-
9567
+
95349568
Jim_InterpIncrProcEpoch(interp);
95359569
95369570
ret = JIM_OK;
95379571
}
95389572
@@ -9571,23 +9605,23 @@
95719605
objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
95729606
#ifdef jim_ext_namespace
95739607
|| !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
95749608
#endif
95759609
) {
9576
-
95779610
9578
-
9611
+
9612
+
95799613
const char *name = Jim_String(objPtr);
95809614
Jim_HashEntry *he;
95819615
95829616
if (name[0] == ':' && name[1] == ':') {
95839617
while (*++name == ':') {
95849618
}
95859619
}
95869620
#ifdef jim_ext_namespace
95879621
else if (Jim_Length(interp->framePtr->nsObj)) {
9588
-
9622
+
95899623
Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
95909624
Jim_AppendStrings(interp, nameObj, "::", name, NULL);
95919625
he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
95929626
Jim_FreeNewObj(interp, nameObj);
95939627
if (he) {
@@ -9594,11 +9628,11 @@
95949628
goto found;
95959629
}
95969630
}
95979631
#endif
95989632
9599
-
9633
+
96009634
he = Jim_FindHashEntry(&interp->commands, name);
96019635
if (he == NULL) {
96029636
if (flags & JIM_ERRMSG) {
96039637
Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
96049638
}
@@ -9607,11 +9641,11 @@
96079641
#ifdef jim_ext_namespace
96089642
found:
96099643
#endif
96109644
cmd = Jim_GetHashEntryVal(he);
96119645
9612
-
9646
+
96139647
Jim_FreeIntRep(interp, objPtr);
96149648
objPtr->typePtr = &commandObjType;
96159649
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
96169650
objPtr->internalRep.cmdValue.cmdPtr = cmd;
96179651
objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9660,11 @@
96269660
return cmd;
96279661
}
96289662
96299663
96309664
9631
-#define JIM_DICT_SUGAR 100
9665
+#define JIM_DICT_SUGAR 100
96329666
96339667
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
96349668
96359669
static const Jim_ObjType variableObjType = {
96369670
"variable",
@@ -9640,11 +9674,11 @@
96409674
JIM_TYPE_REFERENCES,
96419675
};
96429676
96439677
static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
96449678
{
9645
-
9679
+
96469680
if (nameObjPtr->typePtr != &variableObjType) {
96479681
int len;
96489682
const char *str = Jim_GetString(nameObjPtr, &len);
96499683
if (memchr(str, '\0', len)) {
96509684
Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9694,18 @@
96609694
Jim_CallFrame *framePtr;
96619695
Jim_HashEntry *he;
96629696
int global;
96639697
int len;
96649698
9665
-
9699
+
96669700
if (objPtr->typePtr == &variableObjType) {
96679701
framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
96689702
if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9669
-
9703
+
96709704
return JIM_OK;
96719705
}
9672
-
9706
+
96739707
}
96749708
else if (objPtr->typePtr == &dictSubstObjType) {
96759709
return JIM_DICT_SUGAR;
96769710
}
96779711
else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9713,11 @@
96799713
}
96809714
96819715
96829716
varName = Jim_GetString(objPtr, &len);
96839717
9684
-
9718
+
96859719
if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
96869720
return JIM_DICT_SUGAR;
96879721
}
96889722
96899723
if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9729,23 @@
96959729
else {
96969730
global = 0;
96979731
framePtr = interp->framePtr;
96989732
}
96999733
9700
-
9734
+
97019735
he = Jim_FindHashEntry(&framePtr->vars, varName);
97029736
if (he == NULL) {
97039737
if (!global && framePtr->staticVars) {
9704
-
9738
+
97059739
he = Jim_FindHashEntry(framePtr->staticVars, varName);
97069740
}
97079741
if (he == NULL) {
97089742
return JIM_ERR;
97099743
}
97109744
}
97119745
9712
-
9746
+
97139747
Jim_FreeIntRep(interp, objPtr);
97149748
objPtr->typePtr = &variableObjType;
97159749
objPtr->internalRep.varValue.callFrameId = framePtr->id;
97169750
objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
97179751
objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9760,11 @@
97269760
{
97279761
const char *name;
97289762
Jim_CallFrame *framePtr;
97299763
int global;
97309764
9731
-
9765
+
97329766
Jim_Var *var = Jim_Alloc(sizeof(*var));
97339767
97349768
var->objPtr = valObjPtr;
97359769
Jim_IncrRefCount(valObjPtr);
97369770
var->linkFramePtr = NULL;
@@ -9745,14 +9779,14 @@
97459779
else {
97469780
framePtr = interp->framePtr;
97479781
global = 0;
97489782
}
97499783
9750
-
9784
+
97519785
Jim_AddHashEntry(&framePtr->vars, name, var);
97529786
9753
-
9787
+
97549788
Jim_FreeIntRep(interp, nameObjPtr);
97559789
nameObjPtr->typePtr = &variableObjType;
97569790
nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
97579791
nameObjPtr->internalRep.varValue.varPtr = var;
97589792
nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9816,11 @@
97829816
if (var->linkFramePtr == NULL) {
97839817
Jim_IncrRefCount(valObjPtr);
97849818
Jim_DecrRefCount(interp, var->objPtr);
97859819
var->objPtr = valObjPtr;
97869820
}
9787
- else {
9821
+ else {
97889822
Jim_CallFrame *savedCallFrame;
97899823
97909824
savedCallFrame = interp->framePtr;
97919825
interp->framePtr = var->linkFramePtr;
97929826
err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9822,19 +9856,16 @@
98229856
return result;
98239857
}
98249858
98259859
int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val)
98269860
{
9827
- Jim_Obj *nameObjPtr, *valObjPtr;
9861
+ Jim_Obj *valObjPtr;
98289862
int result;
98299863
9830
- nameObjPtr = Jim_NewStringObj(interp, name, -1);
98319864
valObjPtr = Jim_NewStringObj(interp, val, -1);
9832
- Jim_IncrRefCount(nameObjPtr);
98339865
Jim_IncrRefCount(valObjPtr);
9834
- result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
9835
- Jim_DecrRefCount(interp, nameObjPtr);
9866
+ result = Jim_SetVariableStr(interp, name, valObjPtr);
98369867
Jim_DecrRefCount(interp, valObjPtr);
98379868
return result;
98389869
}
98399870
98409871
int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
@@ -9843,14 +9874,14 @@
98439874
const char *varName;
98449875
const char *targetName;
98459876
Jim_CallFrame *framePtr;
98469877
Jim_Var *varPtr;
98479878
9848
-
9879
+
98499880
switch (SetVariableFromAny(interp, nameObjPtr)) {
98509881
case JIM_DICT_SUGAR:
9851
-
9882
+
98529883
Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
98539884
return JIM_ERR;
98549885
98559886
case JIM_OK:
98569887
varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9889,23 @@
98589889
if (varPtr->linkFramePtr == NULL) {
98599890
Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
98609891
return JIM_ERR;
98619892
}
98629893
9863
-
9894
+
98649895
varPtr->linkFramePtr = NULL;
98659896
break;
98669897
}
98679898
9868
-
9869
-
9899
+
9900
+
98709901
varName = Jim_String(nameObjPtr);
98719902
98729903
if (varName[0] == ':' && varName[1] == ':') {
98739904
while (*++varName == ':') {
98749905
}
9875
-
9906
+
98769907
framePtr = interp->topFramePtr;
98779908
}
98789909
else {
98799910
framePtr = interp->framePtr;
98809911
}
@@ -9894,15 +9925,15 @@
98949925
nameObjPtr);
98959926
Jim_DecrRefCount(interp, targetNameObjPtr);
98969927
return JIM_ERR;
98979928
}
98989929
9899
-
9930
+
99009931
if (framePtr == targetCallFrame) {
99019932
Jim_Obj *objPtr = targetNameObjPtr;
99029933
9903
-
9934
+
99049935
while (1) {
99059936
if (strcmp(Jim_String(objPtr), varName) == 0) {
99069937
Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
99079938
Jim_DecrRefCount(interp, targetNameObjPtr);
99089939
return JIM_ERR;
@@ -9914,13 +9945,13 @@
99149945
break;
99159946
objPtr = varPtr->objPtr;
99169947
}
99179948
}
99189949
9919
-
9950
+
99209951
Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
9921
-
9952
+
99229953
nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
99239954
Jim_DecrRefCount(interp, targetNameObjPtr);
99249955
return JIM_OK;
99259956
}
99269957
@@ -9934,26 +9965,26 @@
99349965
return varPtr->objPtr;
99359966
}
99369967
else {
99379968
Jim_Obj *objPtr;
99389969
9939
-
9970
+
99409971
Jim_CallFrame *savedCallFrame = interp->framePtr;
99419972
99429973
interp->framePtr = varPtr->linkFramePtr;
99439974
objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
99449975
interp->framePtr = savedCallFrame;
99459976
if (objPtr) {
99469977
return objPtr;
99479978
}
9948
-
9979
+
99499980
}
99509981
}
99519982
break;
99529983
99539984
case JIM_DICT_SUGAR:
9954
-
9985
+
99559986
return JimDictSugarGet(interp, nameObjPtr, flags);
99569987
}
99579988
if (flags & JIM_ERRMSG) {
99589989
Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
99599990
}
@@ -10003,17 +10034,17 @@
1000310034
int retval;
1000410035
Jim_CallFrame *framePtr;
1000510036
1000610037
retval = SetVariableFromAny(interp, nameObjPtr);
1000710038
if (retval == JIM_DICT_SUGAR) {
10008
-
10039
+
1000910040
return JimDictSugarSet(interp, nameObjPtr, NULL);
1001010041
}
1001110042
else if (retval == JIM_OK) {
1001210043
varPtr = nameObjPtr->internalRep.varValue.varPtr;
1001310044
10014
-
10045
+
1001510046
if (varPtr->linkFramePtr) {
1001610047
framePtr = interp->framePtr;
1001710048
interp->framePtr = varPtr->linkFramePtr;
1001810049
retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
1001910050
interp->framePtr = framePtr;
@@ -10028,11 +10059,11 @@
1002810059
framePtr = interp->framePtr;
1002910060
}
1003010061
1003110062
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
1003210063
if (retval == JIM_OK) {
10033
-
10064
+
1003410065
framePtr->id = interp->callFrameEpoch++;
1003510066
}
1003610067
}
1003710068
}
1003810069
if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10092,11 @@
1006110092
keyLen = (str + len) - p;
1006210093
if (str[len - 1] == ')') {
1006310094
keyLen--;
1006410095
}
1006510096
10066
-
10097
+
1006710098
keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
1006810099
1006910100
Jim_IncrRefCount(varObjPtr);
1007010101
Jim_IncrRefCount(keyObjPtr);
1007110102
*varPtrPtr = varObjPtr;
@@ -10080,23 +10111,23 @@
1008010111
1008110112
err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
1008210113
&objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
1008310114
1008410115
if (err == JIM_OK) {
10085
-
10116
+
1008610117
Jim_SetEmptyResult(interp);
1008710118
}
1008810119
else {
1008910120
if (!valObjPtr) {
10090
-
10121
+
1009110122
if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
1009210123
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
1009310124
objPtr);
1009410125
return err;
1009510126
}
1009610127
}
10097
-
10128
+
1009810129
Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
1009910130
(valObjPtr ? "set" : "unset"), objPtr);
1010010131
}
1010110132
return err;
1010210133
}
@@ -10118,11 +10149,11 @@
1011810149
Jim_SetResultFormatted(interp,
1011910150
"can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
1012010151
ret < 0 ? "variable isn't" : "no such element in");
1012110152
}
1012210153
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10123
-
10154
+
1012410155
Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
1012510156
}
1012610157
1012710158
return resObjPtr;
1012810159
}
@@ -10143,28 +10174,27 @@
1014310174
{
1014410175
Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr);
1014510176
Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
1014610177
}
1014710178
10148
-void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
10149
-{
10150
- JIM_NOTUSED(interp);
10151
-
10152
- dupPtr->internalRep.dictSubstValue.varNameObjPtr =
10153
- srcPtr->internalRep.dictSubstValue.varNameObjPtr;
10154
- dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr;
10155
- dupPtr->typePtr = &dictSubstObjType;
10179
+static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
10180
+{
10181
+
10182
+ dupPtr->internalRep = srcPtr->internalRep;
10183
+
10184
+ Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr);
10185
+ Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
1015610186
}
1015710187
1015810188
1015910189
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1016010190
{
1016110191
if (objPtr->typePtr != &dictSubstObjType) {
1016210192
Jim_Obj *varObjPtr, *keyObjPtr;
1016310193
1016410194
if (objPtr->typePtr == &interpolatedObjType) {
10165
-
10195
+
1016610196
1016710197
varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
1016810198
keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
1016910199
1017010200
Jim_IncrRefCount(varObjPtr);
@@ -10202,16 +10232,12 @@
1020210232
return resObjPtr;
1020310233
}
1020410234
1020510235
static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
1020610236
{
10207
- Jim_Obj *resultObjPtr;
10208
-
10209
- if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
10210
-
10211
- resultObjPtr->refCount--;
10212
- return resultObjPtr;
10237
+ if (Jim_EvalExpression(interp, objPtr) == JIM_OK) {
10238
+ return Jim_GetResult(interp);
1021310239
}
1021410240
return NULL;
1021510241
}
1021610242
1021710243
@@ -10249,11 +10275,11 @@
1024910275
return cf;
1025010276
}
1025110277
1025210278
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
1025310279
{
10254
-
10280
+
1025510281
if (localCommands) {
1025610282
Jim_Obj *cmdNameObj;
1025710283
1025810284
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
1025910285
Jim_HashEntry *he;
@@ -10268,20 +10294,20 @@
1026810294
Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
1026910295
if (cmd->prevCmd) {
1027010296
Jim_Cmd *prevCmd = cmd->prevCmd;
1027110297
cmd->prevCmd = NULL;
1027210298
10273
-
10299
+
1027410300
JimDecrCmdRefCount(interp, cmd);
1027510301
10276
-
10302
+
1027710303
Jim_SetHashVal(ht, he, prevCmd);
1027810304
}
1027910305
else {
1028010306
Jim_DeleteHashEntry(ht, fqname);
10281
- Jim_InterpIncrProcEpoch(interp);
1028210307
}
10308
+ Jim_InterpIncrProcEpoch(interp);
1028310309
}
1028410310
Jim_DecrRefCount(interp, cmdNameObj);
1028510311
JimFreeQualifiedName(interp, fqObjName);
1028610312
}
1028710313
Jim_FreeStack(localCommands);
@@ -10288,13 +10314,59 @@
1028810314
Jim_Free(localCommands);
1028910315
}
1029010316
return JIM_OK;
1029110317
}
1029210318
10319
+static int JimInvokeDefer(Jim_Interp *interp, int retcode)
10320
+{
10321
+ Jim_Obj *objPtr;
1029310322
10294
-#define JIM_FCF_FULL 0
10295
-#define JIM_FCF_REUSE 1
10323
+
10324
+ if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) {
10325
+ return retcode;
10326
+ }
10327
+
10328
+ objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE);
10329
+
10330
+ if (objPtr) {
10331
+ int ret = JIM_OK;
10332
+ int i;
10333
+ int listLen = Jim_ListLength(interp, objPtr);
10334
+ Jim_Obj *resultObjPtr;
10335
+
10336
+ Jim_IncrRefCount(objPtr);
10337
+
10338
+ resultObjPtr = Jim_GetResult(interp);
10339
+ Jim_IncrRefCount(resultObjPtr);
10340
+ Jim_SetEmptyResult(interp);
10341
+
10342
+
10343
+ for (i = listLen; i > 0; i--) {
10344
+
10345
+ Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1);
10346
+ ret = Jim_EvalObj(interp, scriptObjPtr);
10347
+ if (ret != JIM_OK) {
10348
+ break;
10349
+ }
10350
+ }
10351
+
10352
+ if (ret == JIM_OK || retcode == JIM_ERR) {
10353
+
10354
+ Jim_SetResult(interp, resultObjPtr);
10355
+ }
10356
+ else {
10357
+ retcode = ret;
10358
+ }
10359
+
10360
+ Jim_DecrRefCount(interp, resultObjPtr);
10361
+ Jim_DecrRefCount(interp, objPtr);
10362
+ }
10363
+ return retcode;
10364
+}
10365
+
10366
+#define JIM_FCF_FULL 0
10367
+#define JIM_FCF_REUSE 1
1029610368
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
1029710369
{
1029810370
JimDeleteLocalProcs(interp, cf->localCommands);
1029910371
1030010372
if (cf->procArgsObjPtr)
@@ -10327,263 +10399,10 @@
1032710399
cf->next = interp->freeFramesList;
1032810400
interp->freeFramesList = cf;
1032910401
}
1033010402
1033110403
10332
-#ifdef JIM_REFERENCES
10333
-
10334
-static void JimReferencesHTValDestructor(void *interp, void *val)
10335
-{
10336
- Jim_Reference *refPtr = (void *)val;
10337
-
10338
- Jim_DecrRefCount(interp, refPtr->objPtr);
10339
- if (refPtr->finalizerCmdNamePtr != NULL) {
10340
- Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10341
- }
10342
- Jim_Free(val);
10343
-}
10344
-
10345
-static unsigned int JimReferencesHTHashFunction(const void *key)
10346
-{
10347
-
10348
- const unsigned long *widePtr = key;
10349
- unsigned int intValue = (unsigned int)*widePtr;
10350
-
10351
- return Jim_IntHashFunction(intValue);
10352
-}
10353
-
10354
-static void *JimReferencesHTKeyDup(void *privdata, const void *key)
10355
-{
10356
- void *copy = Jim_Alloc(sizeof(unsigned long));
10357
-
10358
- JIM_NOTUSED(privdata);
10359
-
10360
- memcpy(copy, key, sizeof(unsigned long));
10361
- return copy;
10362
-}
10363
-
10364
-static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2)
10365
-{
10366
- JIM_NOTUSED(privdata);
10367
-
10368
- return memcmp(key1, key2, sizeof(unsigned long)) == 0;
10369
-}
10370
-
10371
-static void JimReferencesHTKeyDestructor(void *privdata, void *key)
10372
-{
10373
- JIM_NOTUSED(privdata);
10374
-
10375
- Jim_Free(key);
10376
-}
10377
-
10378
-static const Jim_HashTableType JimReferencesHashTableType = {
10379
- JimReferencesHTHashFunction,
10380
- JimReferencesHTKeyDup,
10381
- NULL,
10382
- JimReferencesHTKeyCompare,
10383
- JimReferencesHTKeyDestructor,
10384
- JimReferencesHTValDestructor
10385
-};
10386
-
10387
-
10388
-
10389
-#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
10390
-
10391
-static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
10392
-{
10393
- const char *fmt = "<reference.<%s>.%020lu>";
10394
-
10395
- sprintf(buf, fmt, refPtr->tag, id);
10396
- return JIM_REFERENCE_SPACE;
10397
-}
10398
-
10399
-static void UpdateStringOfReference(struct Jim_Obj *objPtr);
10400
-
10401
-static const Jim_ObjType referenceObjType = {
10402
- "reference",
10403
- NULL,
10404
- NULL,
10405
- UpdateStringOfReference,
10406
- JIM_TYPE_REFERENCES,
10407
-};
10408
-
10409
-static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10410
-{
10411
- char buf[JIM_REFERENCE_SPACE + 1];
10412
-
10413
- JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10414
- JimSetStringBytes(objPtr, buf);
10415
-}
10416
-
10417
-static int isrefchar(int c)
10418
-{
10419
- return (c == '_' || isalnum(c));
10420
-}
10421
-
10422
-static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10423
-{
10424
- unsigned long value;
10425
- int i, len;
10426
- const char *str, *start, *end;
10427
- char refId[21];
10428
- Jim_Reference *refPtr;
10429
- Jim_HashEntry *he;
10430
- char *endptr;
10431
-
10432
-
10433
- str = Jim_GetString(objPtr, &len);
10434
-
10435
- if (len < JIM_REFERENCE_SPACE)
10436
- goto badformat;
10437
-
10438
- start = str;
10439
- end = str + len - 1;
10440
- while (*start == ' ')
10441
- start++;
10442
- while (*end == ' ' && end > start)
10443
- end--;
10444
- if (end - start + 1 != JIM_REFERENCE_SPACE)
10445
- goto badformat;
10446
-
10447
- if (memcmp(start, "<reference.<", 12) != 0)
10448
- goto badformat;
10449
- if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
10450
- goto badformat;
10451
-
10452
- for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10453
- if (!isrefchar(start[12 + i]))
10454
- goto badformat;
10455
- }
10456
-
10457
- memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
10458
- refId[20] = '\0';
10459
-
10460
- value = strtoul(refId, &endptr, 10);
10461
- if (JimCheckConversion(refId, endptr) != JIM_OK)
10462
- goto badformat;
10463
-
10464
- he = Jim_FindHashEntry(&interp->references, &value);
10465
- if (he == NULL) {
10466
- Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10467
- return JIM_ERR;
10468
- }
10469
- refPtr = Jim_GetHashEntryVal(he);
10470
-
10471
- Jim_FreeIntRep(interp, objPtr);
10472
- objPtr->typePtr = &referenceObjType;
10473
- objPtr->internalRep.refValue.id = value;
10474
- objPtr->internalRep.refValue.refPtr = refPtr;
10475
- return JIM_OK;
10476
-
10477
- badformat:
10478
- Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr);
10479
- return JIM_ERR;
10480
-}
10481
-
10482
-Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
10483
-{
10484
- struct Jim_Reference *refPtr;
10485
- unsigned long id;
10486
- Jim_Obj *refObjPtr;
10487
- const char *tag;
10488
- int tagLen, i;
10489
-
10490
-
10491
- Jim_CollectIfNeeded(interp);
10492
-
10493
- refPtr = Jim_Alloc(sizeof(*refPtr));
10494
- refPtr->objPtr = objPtr;
10495
- Jim_IncrRefCount(objPtr);
10496
- refPtr->finalizerCmdNamePtr = cmdNamePtr;
10497
- if (cmdNamePtr)
10498
- Jim_IncrRefCount(cmdNamePtr);
10499
- id = interp->referenceNextId++;
10500
- Jim_AddHashEntry(&interp->references, &id, refPtr);
10501
- refObjPtr = Jim_NewObj(interp);
10502
- refObjPtr->typePtr = &referenceObjType;
10503
- refObjPtr->bytes = NULL;
10504
- refObjPtr->internalRep.refValue.id = id;
10505
- refObjPtr->internalRep.refValue.refPtr = refPtr;
10506
- interp->referenceNextId++;
10507
- tag = Jim_GetString(tagPtr, &tagLen);
10508
- if (tagLen > JIM_REFERENCE_TAGLEN)
10509
- tagLen = JIM_REFERENCE_TAGLEN;
10510
- for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10511
- if (i < tagLen && isrefchar(tag[i]))
10512
- refPtr->tag[i] = tag[i];
10513
- else
10514
- refPtr->tag[i] = '_';
10515
- }
10516
- refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0';
10517
- return refObjPtr;
10518
-}
10519
-
10520
-Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr)
10521
-{
10522
- if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR)
10523
- return NULL;
10524
- return objPtr->internalRep.refValue.refPtr;
10525
-}
10526
-
10527
-int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr)
10528
-{
10529
- Jim_Reference *refPtr;
10530
-
10531
- if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10532
- return JIM_ERR;
10533
- Jim_IncrRefCount(cmdNamePtr);
10534
- if (refPtr->finalizerCmdNamePtr)
10535
- Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10536
- refPtr->finalizerCmdNamePtr = cmdNamePtr;
10537
- return JIM_OK;
10538
-}
10539
-
10540
-int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr)
10541
-{
10542
- Jim_Reference *refPtr;
10543
-
10544
- if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10545
- return JIM_ERR;
10546
- *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr;
10547
- return JIM_OK;
10548
-}
10549
-
10550
-
10551
-
10552
-static const Jim_HashTableType JimRefMarkHashTableType = {
10553
- JimReferencesHTHashFunction,
10554
- JimReferencesHTKeyDup,
10555
- NULL,
10556
- JimReferencesHTKeyCompare,
10557
- JimReferencesHTKeyDestructor,
10558
- NULL
10559
-};
10560
-
10561
-
10562
-int Jim_Collect(Jim_Interp *interp)
10563
-{
10564
- int collected = 0;
10565
- return collected;
10566
-}
10567
-
10568
-#define JIM_COLLECT_ID_PERIOD 5000
10569
-#define JIM_COLLECT_TIME_PERIOD 300
10570
-
10571
-void Jim_CollectIfNeeded(Jim_Interp *interp)
10572
-{
10573
- unsigned long elapsedId;
10574
- int elapsedTime;
10575
-
10576
- elapsedId = interp->referenceNextId - interp->lastCollectId;
10577
- elapsedTime = time(NULL) - interp->lastCollectTime;
10578
-
10579
-
10580
- if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
10581
- Jim_Collect(interp);
10582
- }
10583
-}
10584
-#endif
1058510404
1058610405
int Jim_IsBigEndian(void)
1058710406
{
1058810407
union {
1058910408
unsigned short s;
@@ -10630,11 +10449,11 @@
1063010449
Jim_IncrRefCount(i->nullScriptObj);
1063110450
Jim_IncrRefCount(i->errorProc);
1063210451
Jim_IncrRefCount(i->trueObj);
1063310452
Jim_IncrRefCount(i->falseObj);
1063410453
10635
-
10454
+
1063610455
Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
1063710456
Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
1063810457
1063910458
Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
1064010459
Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,12 +10471,14 @@
1065210471
{
1065310472
Jim_CallFrame *cf, *cfx;
1065410473
1065510474
Jim_Obj *objPtr, *nextObjPtr;
1065610475
10657
-
10476
+
1065810477
for (cf = i->framePtr; cf; cf = cfx) {
10478
+
10479
+ JimInvokeDefer(i, JIM_OK);
1065910480
cfx = cf->parent;
1066010481
JimFreeCallFrame(i, cf, JIM_FCF_FULL);
1066110482
}
1066210483
1066310484
Jim_DecrRefCount(i, i->emptyObj);
@@ -10684,10 +10505,11 @@
1068410505
1068510506
printf("\n-------------------------------------\n");
1068610507
printf("Objects still in the free list:\n");
1068710508
while (objPtr) {
1068810509
const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10510
+ Jim_String(objPtr);
1068910511
1069010512
if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
1069110513
printf("%p (%d) %-10s: '%.20s...'\n",
1069210514
(void *)objPtr, objPtr->refCount, type, objPtr->bytes);
1069310515
}
@@ -10705,27 +10527,27 @@
1070510527
printf("-------------------------------------\n\n");
1070610528
JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
1070710529
}
1070810530
#endif
1070910531
10710
-
10532
+
1071110533
objPtr = i->freeList;
1071210534
while (objPtr) {
1071310535
nextObjPtr = objPtr->nextObjPtr;
1071410536
Jim_Free(objPtr);
1071510537
objPtr = nextObjPtr;
1071610538
}
1071710539
10718
-
10540
+
1071910541
for (cf = i->freeFramesList; cf; cf = cfx) {
1072010542
cfx = cf->next;
1072110543
if (cf->vars.table)
1072210544
Jim_FreeHashTable(&cf->vars);
1072310545
Jim_Free(cf);
1072410546
}
1072510547
10726
-
10548
+
1072710549
Jim_Free(i);
1072810550
}
1072910551
1073010552
Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
1073110553
{
@@ -10746,25 +10568,25 @@
1074610568
else {
1074710569
if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
1074810570
level = -1;
1074910571
}
1075010572
else {
10751
-
10573
+
1075210574
level = interp->framePtr->level - level;
1075310575
}
1075410576
}
1075510577
}
1075610578
else {
10757
- str = "1";
10579
+ str = "1";
1075810580
level = interp->framePtr->level - 1;
1075910581
}
1076010582
1076110583
if (level == 0) {
1076210584
return interp->topFramePtr;
1076310585
}
1076410586
if (level > 0) {
10765
-
10587
+
1076610588
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
1076710589
if (framePtr->level == level) {
1076810590
return framePtr;
1076910591
}
1077010592
}
@@ -10779,19 +10601,19 @@
1077910601
long level;
1078010602
Jim_CallFrame *framePtr;
1078110603
1078210604
if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
1078310605
if (level <= 0) {
10784
-
10606
+
1078510607
level = interp->framePtr->level + level;
1078610608
}
1078710609
1078810610
if (level == 0) {
1078910611
return interp->topFramePtr;
1079010612
}
1079110613
10792
-
10614
+
1079310615
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
1079410616
if (framePtr->level == level) {
1079510617
return framePtr;
1079610618
}
1079710619
}
@@ -10810,11 +10632,11 @@
1081010632
1081110633
static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
1081210634
{
1081310635
int len;
1081410636
10815
-
10637
+
1081610638
Jim_IncrRefCount(stackTraceObj);
1081710639
Jim_DecrRefCount(interp, interp->stackTrace);
1081810640
interp->stackTrace = stackTraceObj;
1081910641
interp->errorFlag = 1;
1082010642
@@ -10831,32 +10653,32 @@
1083110653
{
1083210654
if (strcmp(procname, "unknown") == 0) {
1083310655
procname = "";
1083410656
}
1083510657
if (!*procname && !Jim_Length(fileNameObj)) {
10836
-
10658
+
1083710659
return;
1083810660
}
1083910661
1084010662
if (Jim_IsShared(interp->stackTrace)) {
1084110663
Jim_DecrRefCount(interp, interp->stackTrace);
1084210664
interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
1084310665
Jim_IncrRefCount(interp->stackTrace);
1084410666
}
1084510667
10846
-
10668
+
1084710669
if (!*procname && Jim_Length(fileNameObj)) {
10848
-
10670
+
1084910671
int len = Jim_ListLength(interp, interp->stackTrace);
1085010672
1085110673
if (len >= 3) {
1085210674
Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
1085310675
if (Jim_Length(objPtr)) {
10854
-
10676
+
1085510677
objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
1085610678
if (Jim_Length(objPtr) == 0) {
10857
-
10679
+
1085810680
ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
1085910681
ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
1086010682
return;
1086110683
}
1086210684
}
@@ -10958,18 +10780,18 @@
1095810780
{
1095910781
jim_wide wideValue;
1096010782
const char *str;
1096110783
1096210784
if (objPtr->typePtr == &coercedDoubleObjType) {
10963
-
10785
+
1096410786
objPtr->typePtr = &intObjType;
1096510787
return JIM_OK;
1096610788
}
1096710789
10968
-
10790
+
1096910791
str = Jim_String(objPtr);
10970
-
10792
+
1097110793
if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
1097210794
if (flags & JIM_ERRMSG) {
1097310795
Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
1097410796
}
1097510797
return JIM_ERR;
@@ -10976,11 +10798,11 @@
1097610798
}
1097710799
if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
1097810800
Jim_SetResultString(interp, "Integer value too big to be represented", -1);
1097910801
return JIM_ERR;
1098010802
}
10981
-
10803
+
1098210804
Jim_FreeIntRep(interp, objPtr);
1098310805
objPtr->typePtr = &intObjType;
1098410806
objPtr->internalRep.wideValue = wideValue;
1098510807
return JIM_OK;
1098610808
}
@@ -11075,17 +10897,17 @@
1107510897
{
1107610898
char buf[JIM_DOUBLE_SPACE + 1];
1107710899
int i;
1107810900
int len = sprintf(buf, "%.12g", value);
1107910901
11080
-
10902
+
1108110903
for (i = 0; i < len; i++) {
1108210904
if (buf[i] == '.' || buf[i] == 'e') {
1108310905
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
1108410906
char *e = strchr(buf, 'e');
1108510907
if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
11086
-
10908
+
1108710909
e += 2;
1108810910
memmove(e, e + 1, len - (e - buf));
1108910911
}
1109010912
#endif
1109110913
break;
@@ -11104,41 +10926,40 @@
1110410926
{
1110510927
double doubleValue;
1110610928
jim_wide wideValue;
1110710929
const char *str;
1110810930
11109
- str = Jim_String(objPtr);
11110
-
1111110931
#ifdef HAVE_LONG_LONG
11112
-
10932
+
1111310933
#define MIN_INT_IN_DOUBLE -(1LL << 53)
1111410934
#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
1111510935
1111610936
if (objPtr->typePtr == &intObjType
1111710937
&& JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
1111810938
&& JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
1111910939
11120
-
10940
+
1112110941
objPtr->typePtr = &coercedDoubleObjType;
1112210942
return JIM_OK;
1112310943
}
11124
- else
1112510944
#endif
10945
+ str = Jim_String(objPtr);
10946
+
1112610947
if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
11127
-
10948
+
1112810949
Jim_FreeIntRep(interp, objPtr);
1112910950
objPtr->typePtr = &coercedDoubleObjType;
1113010951
objPtr->internalRep.wideValue = wideValue;
1113110952
return JIM_OK;
1113210953
}
1113310954
else {
11134
-
10955
+
1113510956
if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
1113610957
Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
1113710958
return JIM_ERR;
1113810959
}
11139
-
10960
+
1114010961
Jim_FreeIntRep(interp, objPtr);
1114110962
}
1114210963
objPtr->typePtr = &doubleObjType;
1114310964
objPtr->internalRep.doubleValue = doubleValue;
1114410965
return JIM_OK;
@@ -11170,10 +10991,50 @@
1117010991
objPtr->typePtr = &doubleObjType;
1117110992
objPtr->bytes = NULL;
1117210993
objPtr->internalRep.doubleValue = doubleValue;
1117310994
return objPtr;
1117410995
}
10996
+
10997
+static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10998
+
10999
+int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr)
11000
+{
11001
+ if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR)
11002
+ return JIM_ERR;
11003
+ *booleanPtr = (int) JimWideValue(objPtr);
11004
+ return JIM_OK;
11005
+}
11006
+
11007
+static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
11008
+{
11009
+ static const char * const falses[] = {
11010
+ "0", "false", "no", "off", NULL
11011
+ };
11012
+ static const char * const trues[] = {
11013
+ "1", "true", "yes", "on", NULL
11014
+ };
11015
+
11016
+ int boolean;
11017
+
11018
+ int index;
11019
+ if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) {
11020
+ boolean = 0;
11021
+ } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) {
11022
+ boolean = 1;
11023
+ } else {
11024
+ if (flags & JIM_ERRMSG) {
11025
+ Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr);
11026
+ }
11027
+ return JIM_ERR;
11028
+ }
11029
+
11030
+
11031
+ Jim_FreeIntRep(interp, objPtr);
11032
+ objPtr->typePtr = &intObjType;
11033
+ objPtr->internalRep.wideValue = boolean;
11034
+ return JIM_OK;
11035
+}
1117511036
1117611037
static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
1117711038
static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
1117811039
static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
1117911040
static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11082,11 @@
1122111082
#define JIM_ELESTR_QUOTE 2
1122211083
static unsigned char ListElementQuotingType(const char *s, int len)
1122311084
{
1122411085
int i, level, blevel, trySimple = 1;
1122511086
11226
-
11087
+
1122711088
if (len == 0)
1122811089
return JIM_ELESTR_BRACE;
1122911090
if (s[0] == '"' || s[0] == '{') {
1123011091
trySimple = 0;
1123111092
goto testbrace;
@@ -11243,20 +11104,20 @@
1124311104
case '\n':
1124411105
case '\t':
1124511106
case '\f':
1124611107
case '\v':
1124711108
trySimple = 0;
11248
-
11109
+
1124911110
case '{':
1125011111
case '}':
1125111112
goto testbrace;
1125211113
}
1125311114
}
1125411115
return JIM_ELESTR_SIMPLE;
1125511116
1125611117
testbrace:
11257
-
11118
+
1125811119
if (s[len - 1] == '\\')
1125911120
return JIM_ELESTR_QUOTE;
1126011121
level = 0;
1126111122
blevel = 0;
1126211123
for (i = 0; i < len; i++) {
@@ -11372,11 +11233,11 @@
1137211233
int i, bufLen, realLength;
1137311234
const char *strRep;
1137411235
char *p;
1137511236
unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
1137611237
11377
-
11238
+
1137811239
if (objc > STATIC_QUOTING_LEN) {
1137911240
quotingType = Jim_Alloc(objc);
1138011241
}
1138111242
else {
1138211243
quotingType = staticQuoting;
@@ -11391,25 +11252,25 @@
1139111252
case JIM_ELESTR_SIMPLE:
1139211253
if (i != 0 || strRep[0] != '#') {
1139311254
bufLen += len;
1139411255
break;
1139511256
}
11396
-
11257
+
1139711258
quotingType[i] = JIM_ELESTR_BRACE;
11398
-
11259
+
1139911260
case JIM_ELESTR_BRACE:
1140011261
bufLen += len + 2;
1140111262
break;
1140211263
case JIM_ELESTR_QUOTE:
1140311264
bufLen += len * 2;
1140411265
break;
1140511266
}
11406
- bufLen++;
11267
+ bufLen++;
1140711268
}
1140811269
bufLen++;
1140911270
11410
-
11271
+
1141111272
p = objPtr->bytes = Jim_Alloc(bufLen + 1);
1141211273
realLength = 0;
1141311274
for (i = 0; i < objc; i++) {
1141411275
int len, qlen;
1141511276
@@ -11436,17 +11297,17 @@
1143611297
qlen = BackslashQuoteString(strRep, len, p);
1143711298
p += qlen;
1143811299
realLength += qlen;
1143911300
break;
1144011301
}
11441
-
11302
+
1144211303
if (i + 1 != objc) {
1144311304
*p++ = ' ';
1144411305
realLength++;
1144511306
}
1144611307
}
11447
- *p = '\0';
11308
+ *p = '\0';
1144811309
objPtr->length = realLength;
1144911310
1145011311
if (quotingType != staticQuoting) {
1145111312
Jim_Free(quotingType);
1145211313
}
@@ -11477,21 +11338,21 @@
1147711338
listObjPtrPtr = JimDictPairs(objPtr, &len);
1147811339
for (i = 0; i < len; i++) {
1147911340
Jim_IncrRefCount(listObjPtrPtr[i]);
1148011341
}
1148111342
11482
-
11343
+
1148311344
Jim_FreeIntRep(interp, objPtr);
1148411345
objPtr->typePtr = &listObjType;
1148511346
objPtr->internalRep.listValue.len = len;
1148611347
objPtr->internalRep.listValue.maxLen = len;
1148711348
objPtr->internalRep.listValue.ele = listObjPtrPtr;
1148811349
1148911350
return JIM_OK;
1149011351
}
1149111352
11492
-
11353
+
1149311354
if (objPtr->typePtr == &sourceObjType) {
1149411355
fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
1149511356
linenr = objPtr->internalRep.sourceValue.lineNumber;
1149611357
}
1149711358
else {
@@ -11498,20 +11359,20 @@
1149811359
fileNameObj = interp->emptyObj;
1149911360
linenr = 1;
1150011361
}
1150111362
Jim_IncrRefCount(fileNameObj);
1150211363
11503
-
11364
+
1150411365
str = Jim_GetString(objPtr, &strLen);
1150511366
1150611367
Jim_FreeIntRep(interp, objPtr);
1150711368
objPtr->typePtr = &listObjType;
1150811369
objPtr->internalRep.listValue.len = 0;
1150911370
objPtr->internalRep.listValue.maxLen = 0;
1151011371
objPtr->internalRep.listValue.ele = NULL;
1151111372
11512
-
11373
+
1151311374
if (strLen) {
1151411375
JimParserInit(&parser, str, strLen, linenr);
1151511376
while (!parser.eof) {
1151611377
Jim_Obj *elementPtr;
1151711378
@@ -11641,11 +11502,11 @@
1164111502
Jim_Obj *compare_script;
1164211503
int rc;
1164311504
1164411505
jim_wide ret = 0;
1164511506
11646
-
11507
+
1164711508
compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
1164811509
Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
1164911510
Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
1165011511
1165111512
rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11524,27 @@
1166311524
int dst = 0;
1166411525
Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
1166511526
1166611527
for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
1166711528
if (comp(&ele[dst], &ele[src]) == 0) {
11668
-
11529
+
1166911530
Jim_DecrRefCount(sort_info->interp, ele[dst]);
1167011531
}
1167111532
else {
11672
-
11533
+
1167311534
dst++;
1167411535
}
1167511536
ele[dst] = ele[src];
1167611537
}
11677
-
11678
- ele[++dst] = ele[src];
1167911538
11680
-
11539
+
11540
+ dst++;
11541
+ if (dst < listObjPtr->internalRep.listValue.len) {
11542
+ ele[dst] = ele[src];
11543
+ }
11544
+
11545
+
1168111546
listObjPtr->internalRep.listValue.len = dst;
1168211547
}
1168311548
1168411549
1168511550
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11558,11 @@
1169311558
int rc;
1169411559
1169511560
JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
1169611561
SetListFromAny(interp, listObjPtr);
1169711562
11698
-
11563
+
1169911564
prev_info = sort_info;
1170011565
sort_info = info;
1170111566
1170211567
vector = listObjPtr->internalRep.listValue.ele;
1170311568
len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11581,17 @@
1171611581
break;
1171711582
case JIM_LSORT_COMMAND:
1171811583
fn = ListSortCommand;
1171911584
break;
1172011585
default:
11721
- fn = NULL;
11586
+ fn = NULL;
1172211587
JimPanic((1, "ListSort called with invalid sort type"));
11723
- return -1;
11588
+ return -1;
1172411589
}
1172511590
1172611591
if (info->indexed) {
11727
-
11592
+
1172811593
info->subfn = fn;
1172911594
fn = ListSortIndexHelper;
1173011595
}
1173111596
1173211597
if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11615,11 @@
1175011615
int i;
1175111616
Jim_Obj **point;
1175211617
1175311618
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
1175411619
if (requiredLen < 2) {
11755
-
11620
+
1175611621
requiredLen = 4;
1175711622
}
1175811623
else {
1175911624
requiredLen *= 2;
1176011625
}
@@ -11936,34 +11801,34 @@
1193611801
for (i = 0; i < objc; i++)
1193711802
ListAppendList(objPtr, objv[i]);
1193811803
return objPtr;
1193911804
}
1194011805
else {
11941
-
11806
+
1194211807
int len = 0, objLen;
1194311808
char *bytes, *p;
1194411809
11945
-
11810
+
1194611811
for (i = 0; i < objc; i++) {
1194711812
len += Jim_Length(objv[i]);
1194811813
}
1194911814
if (objc)
1195011815
len += objc - 1;
11951
-
11816
+
1195211817
p = bytes = Jim_Alloc(len + 1);
1195311818
for (i = 0; i < objc; i++) {
1195411819
const char *s = Jim_GetString(objv[i], &objLen);
1195511820
11956
-
11821
+
1195711822
while (objLen && isspace(UCHAR(*s))) {
1195811823
s++;
1195911824
objLen--;
1196011825
len--;
1196111826
}
11962
-
11827
+
1196311828
while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11964
-
11829
+
1196511830
if (objLen > 1 && s[objLen - 2] == '\\') {
1196611831
break;
1196711832
}
1196811833
objLen--;
1196911834
len--;
@@ -11990,11 +11855,11 @@
1199011855
int len, rangeLen;
1199111856
1199211857
if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
1199311858
Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
1199411859
return NULL;
11995
- len = Jim_ListLength(interp, listObjPtr);
11860
+ len = Jim_ListLength(interp, listObjPtr);
1199611861
first = JimRelToAbsIndex(len, first);
1199711862
last = JimRelToAbsIndex(len, last);
1199811863
JimRelToAbsRange(len, &first, &last, &rangeLen);
1199911864
if (first == 0 && last == len) {
1200011865
return listObjPtr;
@@ -12030,16 +11895,16 @@
1203011895
{
1203111896
Jim_DecrRefCount(interp, (Jim_Obj *)val);
1203211897
}
1203311898
1203411899
static const Jim_HashTableType JimDictHashTableType = {
12035
- JimObjectHTHashFunction,
12036
- JimObjectHTKeyValDup,
12037
- JimObjectHTKeyValDup,
12038
- JimObjectHTKeyCompare,
12039
- JimObjectHTKeyValDestructor,
12040
- JimObjectHTKeyValDestructor
11900
+ JimObjectHTHashFunction,
11901
+ JimObjectHTKeyValDup,
11902
+ JimObjectHTKeyValDup,
11903
+ JimObjectHTKeyCompare,
11904
+ JimObjectHTKeyValDestructor,
11905
+ JimObjectHTKeyValDestructor
1204111906
};
1204211907
1204311908
static const Jim_ObjType dictObjType = {
1204411909
"dict",
1204511910
FreeDictInternalRep,
@@ -12060,17 +11925,17 @@
1206011925
{
1206111926
Jim_HashTable *ht, *dupHt;
1206211927
Jim_HashTableIterator htiter;
1206311928
Jim_HashEntry *he;
1206411929
12065
-
11930
+
1206611931
ht = srcPtr->internalRep.ptr;
1206711932
dupHt = Jim_Alloc(sizeof(*dupHt));
1206811933
Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
1206911934
if (ht->size != 0)
1207011935
Jim_ExpandHashTable(dupHt, ht->size);
12071
-
11936
+
1207211937
JimInitHashTableIterator(ht, &htiter);
1207311938
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1207411939
Jim_AddHashEntry(dupHt, he->key, he->u.val);
1207511940
}
1207611941
@@ -12086,11 +11951,11 @@
1208611951
Jim_Obj **objv;
1208711952
int i;
1208811953
1208911954
ht = dictPtr->internalRep.ptr;
1209011955
12091
-
11956
+
1209211957
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
1209311958
JimInitHashTableIterator(ht, &htiter);
1209411959
i = 0;
1209511960
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1209611961
objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11965,15 @@
1210011965
return objv;
1210111966
}
1210211967
1210311968
static void UpdateStringOfDict(struct Jim_Obj *objPtr)
1210411969
{
12105
-
11970
+
1210611971
int len;
1210711972
Jim_Obj **objv = JimDictPairs(objPtr, &len);
1210811973
12109
-
11974
+
1211011975
JimMakeListStringRep(objPtr, objv, len);
1211111976
1211211977
Jim_Free(objv);
1211311978
}
1211411979
@@ -12122,18 +11987,18 @@
1212211987
1212311988
if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
1212411989
Jim_String(objPtr);
1212511990
}
1212611991
12127
-
11992
+
1212811993
listlen = Jim_ListLength(interp, objPtr);
1212911994
if (listlen % 2) {
1213011995
Jim_SetResultString(interp, "missing value to go with key", -1);
1213111996
return JIM_ERR;
1213211997
}
1213311998
else {
12134
-
11999
+
1213512000
Jim_HashTable *ht;
1213612001
int i;
1213712002
1213812003
ht = Jim_Alloc(sizeof(*ht));
1213912004
Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12023,11 @@
1215812023
static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
1215912024
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
1216012025
{
1216112026
Jim_HashTable *ht = objPtr->internalRep.ptr;
1216212027
12163
- if (valueObjPtr == NULL) {
12028
+ if (valueObjPtr == NULL) {
1216412029
return Jim_DeleteHashEntry(ht, keyObjPtr);
1216512030
}
1216612031
Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
1216712032
return JIM_OK;
1216812033
}
@@ -12209,12 +12074,14 @@
1220912074
if (flags & JIM_ERRMSG) {
1221012075
Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
1221112076
}
1221212077
return JIM_ERR;
1221312078
}
12214
- *objPtrPtr = he->u.val;
12215
- return JIM_OK;
12079
+ else {
12080
+ *objPtrPtr = Jim_GetHashEntryVal(he);
12081
+ return JIM_OK;
12082
+ }
1221612083
}
1221712084
1221812085
1221912086
int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
1222012087
{
@@ -12258,11 +12125,11 @@
1225812125
int shared, i;
1225912126
1226012127
varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
1226112128
if (objPtr == NULL) {
1226212129
if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12263
-
12130
+
1226412131
return JIM_ERR;
1226512132
}
1226612133
varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
1226712134
if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
1226812135
Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12139,26 @@
1227212139
if ((shared = Jim_IsShared(objPtr)))
1227312140
varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
1227412141
for (i = 0; i < keyc; i++) {
1227512142
dictObjPtr = objPtr;
1227612143
12277
-
12144
+
1227812145
if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
1227912146
goto err;
1228012147
}
1228112148
1228212149
if (i == keyc - 1) {
12283
-
12150
+
1228412151
if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
1228512152
if (newObjPtr || (flags & JIM_MUSTEXIST)) {
1228612153
goto err;
1228712154
}
1228812155
}
1228912156
break;
1229012157
}
1229112158
12292
-
12159
+
1229312160
Jim_InvalidateStringRep(dictObjPtr);
1229412161
if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
1229512162
newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
1229612163
if (Jim_IsShared(objPtr)) {
1229712164
objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12171,11 @@
1230412171
}
1230512172
objPtr = Jim_NewDictObj(interp, NULL, 0);
1230612173
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
1230712174
}
1230812175
}
12309
-
12176
+
1231012177
Jim_InvalidateStringRep(objPtr);
1231112178
Jim_InvalidateStringRep(varObjPtr);
1231212179
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
1231312180
goto err;
1231412181
}
@@ -12341,11 +12208,11 @@
1234112208
char buf[JIM_INTEGER_SPACE + 1];
1234212209
if (objPtr->internalRep.intValue >= 0) {
1234312210
sprintf(buf, "%d", objPtr->internalRep.intValue);
1234412211
}
1234512212
else {
12346
-
12213
+
1234712214
sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
1234812215
}
1234912216
JimSetStringBytes(objPtr, buf);
1235012217
}
1235112218
}
@@ -12354,14 +12221,14 @@
1235412221
{
1235512222
int idx, end = 0;
1235612223
const char *str;
1235712224
char *endptr;
1235812225
12359
-
12226
+
1236012227
str = Jim_String(objPtr);
1236112228
12362
-
12229
+
1236312230
if (strncmp(str, "end", 3) == 0) {
1236412231
end = 1;
1236512232
str += 3;
1236612233
idx = 0;
1236712234
}
@@ -12372,21 +12239,21 @@
1237212239
goto badindex;
1237312240
}
1237412241
str = endptr;
1237512242
}
1237612243
12377
-
12244
+
1237812245
if (*str == '+' || *str == '-') {
1237912246
int sign = (*str == '+' ? 1 : -1);
1238012247
1238112248
idx += sign * jim_strtol(++str, &endptr);
1238212249
if (str == endptr || *endptr) {
1238312250
goto badindex;
1238412251
}
1238512252
str = endptr;
1238612253
}
12387
-
12254
+
1238812255
while (isspace(UCHAR(*str))) {
1238912256
str++;
1239012257
}
1239112258
if (*str) {
1239212259
goto badindex;
@@ -12394,19 +12261,19 @@
1239412261
if (end) {
1239512262
if (idx > 0) {
1239612263
idx = INT_MAX;
1239712264
}
1239812265
else {
12399
-
12266
+
1240012267
idx--;
1240112268
}
1240212269
}
1240312270
else if (idx < 0) {
1240412271
idx = -INT_MAX;
1240512272
}
1240612273
12407
-
12274
+
1240812275
Jim_FreeIntRep(interp, objPtr);
1240912276
objPtr->typePtr = &indexObjType;
1241012277
objPtr->internalRep.intValue = idx;
1241112278
return JIM_OK;
1241212279
@@ -12416,11 +12283,11 @@
1241612283
return JIM_ERR;
1241712284
}
1241812285
1241912286
int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
1242012287
{
12421
-
12288
+
1242212289
if (objPtr->typePtr == &intObjType) {
1242312290
jim_wide val = JimWideValue(objPtr);
1242412291
1242512292
if (val < 0)
1242612293
*indexPtr = -INT_MAX;
@@ -12448,11 +12315,11 @@
1244812315
"exit",
1244912316
"eval",
1245012317
NULL
1245112318
};
1245212319
12453
-#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
12320
+#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1)
1245412321
1245512322
static const Jim_ObjType returnCodeObjType = {
1245612323
"return-code",
1245712324
NULL,
1245812325
NULL,
@@ -12473,18 +12340,18 @@
1247312340
static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1247412341
{
1247512342
int returnCode;
1247612343
jim_wide wideValue;
1247712344
12478
-
12345
+
1247912346
if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
1248012347
returnCode = (int)wideValue;
1248112348
else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
1248212349
Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
1248312350
return JIM_ERR;
1248412351
}
12485
-
12352
+
1248612353
Jim_FreeIntRep(interp, objPtr);
1248712354
objPtr->typePtr = &returnCodeObjType;
1248812355
objPtr->internalRep.intValue = returnCode;
1248912356
return JIM_OK;
1249012357
}
@@ -12498,19 +12365,19 @@
1249812365
}
1249912366
1250012367
static int JimParseExprOperator(struct JimParserCtx *pc);
1250112368
static int JimParseExprNumber(struct JimParserCtx *pc);
1250212369
static int JimParseExprIrrational(struct JimParserCtx *pc);
12503
-
12504
-
12370
+static int JimParseExprBoolean(struct JimParserCtx *pc);
1250512371
1250612372
1250712373
enum
1250812374
{
12509
-
12510
-
12511
- JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
12375
+
12376
+
12377
+
12378
+ JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
1251212379
JIM_EXPROP_DIV,
1251312380
JIM_EXPROP_MOD,
1251412381
JIM_EXPROP_SUB,
1251512382
JIM_EXPROP_ADD,
1251612383
JIM_EXPROP_LSHIFT,
@@ -12521,66 +12388,48 @@
1252112388
JIM_EXPROP_GT,
1252212389
JIM_EXPROP_LTE,
1252312390
JIM_EXPROP_GTE,
1252412391
JIM_EXPROP_NUMEQ,
1252512392
JIM_EXPROP_NUMNE,
12526
- JIM_EXPROP_BITAND,
12393
+ JIM_EXPROP_BITAND,
1252712394
JIM_EXPROP_BITXOR,
1252812395
JIM_EXPROP_BITOR,
12529
-
12530
-
12531
- JIM_EXPROP_LOGICAND,
12532
- JIM_EXPROP_LOGICAND_LEFT,
12533
- JIM_EXPROP_LOGICAND_RIGHT,
12534
-
12535
-
12536
- JIM_EXPROP_LOGICOR,
12537
- JIM_EXPROP_LOGICOR_LEFT,
12538
- JIM_EXPROP_LOGICOR_RIGHT,
12539
-
12540
-
12541
-
12542
- JIM_EXPROP_TERNARY,
12543
- JIM_EXPROP_TERNARY_LEFT,
12544
- JIM_EXPROP_TERNARY_RIGHT,
12545
-
12546
-
12547
- JIM_EXPROP_COLON,
12548
- JIM_EXPROP_COLON_LEFT,
12549
- JIM_EXPROP_COLON_RIGHT,
12550
-
12551
- JIM_EXPROP_POW,
12552
-
12553
-
12554
- JIM_EXPROP_STREQ,
12396
+ JIM_EXPROP_LOGICAND,
12397
+ JIM_EXPROP_LOGICOR,
12398
+ JIM_EXPROP_TERNARY,
12399
+ JIM_EXPROP_COLON,
12400
+ JIM_EXPROP_POW,
12401
+
12402
+
12403
+ JIM_EXPROP_STREQ,
1255512404
JIM_EXPROP_STRNE,
1255612405
JIM_EXPROP_STRIN,
1255712406
JIM_EXPROP_STRNI,
1255812407
1255912408
12560
- JIM_EXPROP_NOT,
12409
+ JIM_EXPROP_NOT,
1256112410
JIM_EXPROP_BITNOT,
1256212411
JIM_EXPROP_UNARYMINUS,
1256312412
JIM_EXPROP_UNARYPLUS,
1256412413
12565
-
12566
- JIM_EXPROP_FUNC_FIRST,
12567
- JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
12414
+
12415
+ JIM_EXPROP_FUNC_INT,
1256812416
JIM_EXPROP_FUNC_WIDE,
1256912417
JIM_EXPROP_FUNC_ABS,
1257012418
JIM_EXPROP_FUNC_DOUBLE,
1257112419
JIM_EXPROP_FUNC_ROUND,
1257212420
JIM_EXPROP_FUNC_RAND,
1257312421
JIM_EXPROP_FUNC_SRAND,
1257412422
12575
-
12576
- JIM_EXPROP_FUNC_SIN,
12423
+
12424
+ JIM_EXPROP_FUNC_SIN,
1257712425
JIM_EXPROP_FUNC_COS,
1257812426
JIM_EXPROP_FUNC_TAN,
1257912427
JIM_EXPROP_FUNC_ASIN,
1258012428
JIM_EXPROP_FUNC_ACOS,
1258112429
JIM_EXPROP_FUNC_ATAN,
12430
+ JIM_EXPROP_FUNC_ATAN2,
1258212431
JIM_EXPROP_FUNC_SINH,
1258312432
JIM_EXPROP_FUNC_COSH,
1258412433
JIM_EXPROP_FUNC_TANH,
1258512434
JIM_EXPROP_FUNC_CEIL,
1258612435
JIM_EXPROP_FUNC_FLOOR,
@@ -12587,52 +12436,52 @@
1258712436
JIM_EXPROP_FUNC_EXP,
1258812437
JIM_EXPROP_FUNC_LOG,
1258912438
JIM_EXPROP_FUNC_LOG10,
1259012439
JIM_EXPROP_FUNC_SQRT,
1259112440
JIM_EXPROP_FUNC_POW,
12441
+ JIM_EXPROP_FUNC_HYPOT,
12442
+ JIM_EXPROP_FUNC_FMOD,
1259212443
};
1259312444
12594
-struct JimExprState
12595
-{
12596
- Jim_Obj **stack;
12597
- int stacklen;
12598
- int opcode;
12599
- int skip;
12445
+struct JimExprNode {
12446
+ int type;
12447
+ struct Jim_Obj *objPtr;
12448
+
12449
+ struct JimExprNode *left;
12450
+ struct JimExprNode *right;
12451
+ struct JimExprNode *ternary;
1260012452
};
1260112453
1260212454
1260312455
typedef struct Jim_ExprOperator
1260412456
{
1260512457
const char *name;
12606
- int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12458
+ int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode);
1260712459
unsigned char precedence;
1260812460
unsigned char arity;
12609
- unsigned char lazy;
12461
+ unsigned char attr;
1261012462
unsigned char namelen;
1261112463
} Jim_ExprOperator;
1261212464
12613
-static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12614
-{
12615
- Jim_IncrRefCount(obj);
12616
- e->stack[e->stacklen++] = obj;
12617
-}
12618
-
12619
-static Jim_Obj *ExprPop(struct JimExprState *e)
12620
-{
12621
- return e->stack[--e->stacklen];
12622
-}
12623
-
12624
-static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12465
+static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr);
12466
+static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node);
12467
+static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node);
12468
+
12469
+static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
1262512470
{
1262612471
int intresult = 1;
12627
- int rc = JIM_OK;
12628
- Jim_Obj *A = ExprPop(e);
12472
+ int rc;
1262912473
double dA, dC = 0;
1263012474
jim_wide wA, wC = 0;
12475
+ Jim_Obj *A;
12476
+
12477
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12478
+ return rc;
12479
+ }
1263112480
1263212481
if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12633
- switch (e->opcode) {
12482
+ switch (node->type) {
1263412483
case JIM_EXPROP_FUNC_INT:
1263512484
case JIM_EXPROP_FUNC_WIDE:
1263612485
case JIM_EXPROP_FUNC_ROUND:
1263712486
case JIM_EXPROP_UNARYPLUS:
1263812487
wC = wA;
@@ -12653,11 +12502,11 @@
1265312502
default:
1265412503
abort();
1265512504
}
1265612505
}
1265712506
else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12658
- switch (e->opcode) {
12507
+ switch (node->type) {
1265912508
case JIM_EXPROP_FUNC_INT:
1266012509
case JIM_EXPROP_FUNC_WIDE:
1266112510
wC = dA;
1266212511
break;
1266312512
case JIM_EXPROP_FUNC_ROUND:
@@ -12667,11 +12516,15 @@
1266712516
case JIM_EXPROP_UNARYPLUS:
1266812517
dC = dA;
1266912518
intresult = 0;
1267012519
break;
1267112520
case JIM_EXPROP_FUNC_ABS:
12521
+#ifdef JIM_MATH_FUNCTIONS
12522
+ dC = fabs(dA);
12523
+#else
1267212524
dC = dA >= 0 ? dA : -dA;
12525
+#endif
1267312526
intresult = 0;
1267412527
break;
1267512528
case JIM_EXPROP_UNARYMINUS:
1267612529
dC = -dA;
1267712530
intresult = 0;
@@ -12684,14 +12537,14 @@
1268412537
}
1268512538
}
1268612539
1268712540
if (rc == JIM_OK) {
1268812541
if (intresult) {
12689
- ExprPush(e, Jim_NewIntObj(interp, wC));
12542
+ Jim_SetResultInt(interp, wC);
1269012543
}
1269112544
else {
12692
- ExprPush(e, Jim_NewDoubleObj(interp, dC));
12545
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
1269312546
}
1269412547
}
1269512548
1269612549
Jim_DecrRefCount(interp, A);
1269712550
@@ -12704,24 +12557,29 @@
1270412557
JimRandomBytes(interp, &x, sizeof(x));
1270512558
1270612559
return (double)x / (unsigned long)~0;
1270712560
}
1270812561
12709
-static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
12562
+static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node)
1271012563
{
12711
- Jim_Obj *A = ExprPop(e);
1271212564
jim_wide wA;
12565
+ Jim_Obj *A;
12566
+ int rc;
1271312567
12714
- int rc = Jim_GetWide(interp, A, &wA);
12568
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12569
+ return rc;
12570
+ }
12571
+
12572
+ rc = Jim_GetWide(interp, A, &wA);
1271512573
if (rc == JIM_OK) {
12716
- switch (e->opcode) {
12574
+ switch (node->type) {
1271712575
case JIM_EXPROP_BITNOT:
12718
- ExprPush(e, Jim_NewIntObj(interp, ~wA));
12576
+ Jim_SetResultInt(interp, ~wA);
1271912577
break;
1272012578
case JIM_EXPROP_FUNC_SRAND:
1272112579
JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
12722
- ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12580
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
1272312581
break;
1272412582
default:
1272512583
abort();
1272612584
}
1272712585
}
@@ -12729,29 +12587,33 @@
1272912587
Jim_DecrRefCount(interp, A);
1273012588
1273112589
return rc;
1273212590
}
1273312591
12734
-static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
12592
+static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node)
1273512593
{
12736
- JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
12594
+ JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
1273712595
12738
- ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12596
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
1273912597
1274012598
return JIM_OK;
1274112599
}
1274212600
1274312601
#ifdef JIM_MATH_FUNCTIONS
12744
-static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
12602
+static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node)
1274512603
{
1274612604
int rc;
12747
- Jim_Obj *A = ExprPop(e);
1274812605
double dA, dC;
12606
+ Jim_Obj *A;
12607
+
12608
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12609
+ return rc;
12610
+ }
1274912611
1275012612
rc = Jim_GetDouble(interp, A, &dA);
1275112613
if (rc == JIM_OK) {
12752
- switch (e->opcode) {
12614
+ switch (node->type) {
1275312615
case JIM_EXPROP_FUNC_SIN:
1275412616
dC = sin(dA);
1275512617
break;
1275612618
case JIM_EXPROP_FUNC_COS:
1275712619
dC = cos(dA);
@@ -12796,33 +12658,42 @@
1279612658
dC = sqrt(dA);
1279712659
break;
1279812660
default:
1279912661
abort();
1280012662
}
12801
- ExprPush(e, Jim_NewDoubleObj(interp, dC));
12663
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
1280212664
}
1280312665
1280412666
Jim_DecrRefCount(interp, A);
1280512667
1280612668
return rc;
1280712669
}
1280812670
#endif
1280912671
1281012672
12811
-static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
12673
+static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node)
1281212674
{
12813
- Jim_Obj *B = ExprPop(e);
12814
- Jim_Obj *A = ExprPop(e);
1281512675
jim_wide wA, wB;
12816
- int rc = JIM_ERR;
12676
+ int rc;
12677
+ Jim_Obj *A, *B;
12678
+
12679
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12680
+ return rc;
12681
+ }
12682
+ if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12683
+ Jim_DecrRefCount(interp, A);
12684
+ return rc;
12685
+ }
12686
+
12687
+ rc = JIM_ERR;
1281712688
1281812689
if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) {
1281912690
jim_wide wC;
1282012691
1282112692
rc = JIM_OK;
1282212693
12823
- switch (e->opcode) {
12694
+ switch (node->type) {
1282412695
case JIM_EXPROP_LSHIFT:
1282512696
wC = wA << wB;
1282612697
break;
1282712698
case JIM_EXPROP_RSHIFT:
1282812699
wC = wA >> wB;
@@ -12859,29 +12730,28 @@
1285912730
}
1286012731
}
1286112732
break;
1286212733
case JIM_EXPROP_ROTL:
1286312734
case JIM_EXPROP_ROTR:{
12864
-
12735
+
1286512736
unsigned long uA = (unsigned long)wA;
1286612737
unsigned long uB = (unsigned long)wB;
1286712738
const unsigned int S = sizeof(unsigned long) * 8;
1286812739
12869
-
12740
+
1287012741
uB %= S;
1287112742
12872
- if (e->opcode == JIM_EXPROP_ROTR) {
12743
+ if (node->type == JIM_EXPROP_ROTR) {
1287312744
uB = S - uB;
1287412745
}
1287512746
wC = (unsigned long)(uA << uB) | (uA >> (S - uB));
1287612747
break;
1287712748
}
1287812749
default:
1287912750
abort();
1288012751
}
12881
- ExprPush(e, Jim_NewIntObj(interp, wC));
12882
-
12752
+ Jim_SetResultInt(interp, wC);
1288312753
}
1288412754
1288512755
Jim_DecrRefCount(interp, A);
1288612756
Jim_DecrRefCount(interp, B);
1288712757
@@ -12888,44 +12758,55 @@
1288812758
return rc;
1288912759
}
1289012760
1289112761
1289212762
12893
-static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12763
+static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node)
1289412764
{
12895
- int intresult = 1;
1289612765
int rc = JIM_OK;
1289712766
double dA, dB, dC = 0;
1289812767
jim_wide wA, wB, wC = 0;
12768
+ Jim_Obj *A, *B;
1289912769
12900
- Jim_Obj *B = ExprPop(e);
12901
- Jim_Obj *A = ExprPop(e);
12770
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12771
+ return rc;
12772
+ }
12773
+ if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12774
+ Jim_DecrRefCount(interp, A);
12775
+ return rc;
12776
+ }
1290212777
1290312778
if ((A->typePtr != &doubleObjType || A->bytes) &&
1290412779
(B->typePtr != &doubleObjType || B->bytes) &&
1290512780
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
1290612781
12907
-
1290812782
12909
- switch (e->opcode) {
12783
+
12784
+ switch (node->type) {
1291012785
case JIM_EXPROP_POW:
1291112786
case JIM_EXPROP_FUNC_POW:
12787
+ if (wA == 0 && wB < 0) {
12788
+ Jim_SetResultString(interp, "exponentiation of zero by negative power", -1);
12789
+ rc = JIM_ERR;
12790
+ goto done;
12791
+ }
1291212792
wC = JimPowWide(wA, wB);
12913
- break;
12793
+ goto intresult;
1291412794
case JIM_EXPROP_ADD:
1291512795
wC = wA + wB;
12916
- break;
12796
+ goto intresult;
1291712797
case JIM_EXPROP_SUB:
1291812798
wC = wA - wB;
12919
- break;
12799
+ goto intresult;
1292012800
case JIM_EXPROP_MUL:
1292112801
wC = wA * wB;
12922
- break;
12802
+ goto intresult;
1292312803
case JIM_EXPROP_DIV:
1292412804
if (wB == 0) {
1292512805
Jim_SetResultString(interp, "Division by zero", -1);
1292612806
rc = JIM_ERR;
12807
+ goto done;
1292712808
}
1292812809
else {
1292912810
if (wB < 0) {
1293012811
wB = -wB;
1293112812
wA = -wA;
@@ -12932,55 +12813,67 @@
1293212813
}
1293312814
wC = wA / wB;
1293412815
if (wA % wB < 0) {
1293512816
wC--;
1293612817
}
12818
+ goto intresult;
1293712819
}
12938
- break;
1293912820
case JIM_EXPROP_LT:
1294012821
wC = wA < wB;
12941
- break;
12822
+ goto intresult;
1294212823
case JIM_EXPROP_GT:
1294312824
wC = wA > wB;
12944
- break;
12825
+ goto intresult;
1294512826
case JIM_EXPROP_LTE:
1294612827
wC = wA <= wB;
12947
- break;
12828
+ goto intresult;
1294812829
case JIM_EXPROP_GTE:
1294912830
wC = wA >= wB;
12950
- break;
12831
+ goto intresult;
1295112832
case JIM_EXPROP_NUMEQ:
1295212833
wC = wA == wB;
12953
- break;
12834
+ goto intresult;
1295412835
case JIM_EXPROP_NUMNE:
1295512836
wC = wA != wB;
12956
- break;
12957
- default:
12958
- abort();
12837
+ goto intresult;
1295912838
}
1296012839
}
12961
- else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12962
- intresult = 0;
12963
- switch (e->opcode) {
12840
+ if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12841
+ switch (node->type) {
12842
+#ifndef JIM_MATH_FUNCTIONS
1296412843
case JIM_EXPROP_POW:
1296512844
case JIM_EXPROP_FUNC_POW:
12966
-#ifdef JIM_MATH_FUNCTIONS
12967
- dC = pow(dA, dB);
12968
-#else
12845
+ case JIM_EXPROP_FUNC_ATAN2:
12846
+ case JIM_EXPROP_FUNC_HYPOT:
12847
+ case JIM_EXPROP_FUNC_FMOD:
1296912848
Jim_SetResultString(interp, "unsupported", -1);
1297012849
rc = JIM_ERR;
12850
+ goto done;
12851
+#else
12852
+ case JIM_EXPROP_POW:
12853
+ case JIM_EXPROP_FUNC_POW:
12854
+ dC = pow(dA, dB);
12855
+ goto doubleresult;
12856
+ case JIM_EXPROP_FUNC_ATAN2:
12857
+ dC = atan2(dA, dB);
12858
+ goto doubleresult;
12859
+ case JIM_EXPROP_FUNC_HYPOT:
12860
+ dC = hypot(dA, dB);
12861
+ goto doubleresult;
12862
+ case JIM_EXPROP_FUNC_FMOD:
12863
+ dC = fmod(dA, dB);
12864
+ goto doubleresult;
1297112865
#endif
12972
- break;
1297312866
case JIM_EXPROP_ADD:
1297412867
dC = dA + dB;
12975
- break;
12868
+ goto doubleresult;
1297612869
case JIM_EXPROP_SUB:
1297712870
dC = dA - dB;
12978
- break;
12871
+ goto doubleresult;
1297912872
case JIM_EXPROP_MUL:
1298012873
dC = dA * dB;
12981
- break;
12874
+ goto doubleresult;
1298212875
case JIM_EXPROP_DIV:
1298312876
if (dB == 0) {
1298412877
#ifdef INFINITY
1298512878
dC = dA < 0 ? -INFINITY : INFINITY;
1298612879
#else
@@ -12988,83 +12881,70 @@
1298812881
#endif
1298912882
}
1299012883
else {
1299112884
dC = dA / dB;
1299212885
}
12993
- break;
12886
+ goto doubleresult;
1299412887
case JIM_EXPROP_LT:
1299512888
wC = dA < dB;
12996
- intresult = 1;
12997
- break;
12889
+ goto intresult;
1299812890
case JIM_EXPROP_GT:
1299912891
wC = dA > dB;
13000
- intresult = 1;
13001
- break;
12892
+ goto intresult;
1300212893
case JIM_EXPROP_LTE:
1300312894
wC = dA <= dB;
13004
- intresult = 1;
13005
- break;
12895
+ goto intresult;
1300612896
case JIM_EXPROP_GTE:
1300712897
wC = dA >= dB;
13008
- intresult = 1;
13009
- break;
12898
+ goto intresult;
1301012899
case JIM_EXPROP_NUMEQ:
1301112900
wC = dA == dB;
13012
- intresult = 1;
13013
- break;
12901
+ goto intresult;
1301412902
case JIM_EXPROP_NUMNE:
1301512903
wC = dA != dB;
13016
- intresult = 1;
13017
- break;
13018
- default:
13019
- abort();
12904
+ goto intresult;
1302012905
}
1302112906
}
1302212907
else {
13023
-
1302412908
13025
-
12909
+
12910
+
1302612911
int i = Jim_StringCompareObj(interp, A, B, 0);
1302712912
13028
- switch (e->opcode) {
12913
+ switch (node->type) {
1302912914
case JIM_EXPROP_LT:
1303012915
wC = i < 0;
13031
- break;
12916
+ goto intresult;
1303212917
case JIM_EXPROP_GT:
1303312918
wC = i > 0;
13034
- break;
12919
+ goto intresult;
1303512920
case JIM_EXPROP_LTE:
1303612921
wC = i <= 0;
13037
- break;
12922
+ goto intresult;
1303812923
case JIM_EXPROP_GTE:
1303912924
wC = i >= 0;
13040
- break;
12925
+ goto intresult;
1304112926
case JIM_EXPROP_NUMEQ:
1304212927
wC = i == 0;
13043
- break;
12928
+ goto intresult;
1304412929
case JIM_EXPROP_NUMNE:
1304512930
wC = i != 0;
13046
- break;
13047
- default:
13048
- rc = JIM_ERR;
13049
- break;
12931
+ goto intresult;
1305012932
}
1305112933
}
1305212934
13053
- if (rc == JIM_OK) {
13054
- if (intresult) {
13055
- ExprPush(e, Jim_NewIntObj(interp, wC));
13056
- }
13057
- else {
13058
- ExprPush(e, Jim_NewDoubleObj(interp, dC));
13059
- }
13060
- }
13061
-
12935
+ rc = JIM_ERR;
12936
+done:
1306212937
Jim_DecrRefCount(interp, A);
1306312938
Jim_DecrRefCount(interp, B);
13064
-
1306512939
return rc;
12940
+intresult:
12941
+ Jim_SetResultInt(interp, wC);
12942
+ goto done;
12943
+doubleresult:
12944
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
12945
+ goto done;
1306612946
}
1306712947
1306812948
static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
1306912949
{
1307012950
int listlen;
@@ -13077,22 +12957,31 @@
1307712957
}
1307812958
}
1307912959
return 0;
1308012960
}
1308112961
13082
-static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
12962
+
12963
+
12964
+static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
1308312965
{
13084
- Jim_Obj *B = ExprPop(e);
13085
- Jim_Obj *A = ExprPop(e);
13086
-
12966
+ Jim_Obj *A, *B;
1308712967
jim_wide wC;
12968
+ int rc;
1308812969
13089
- switch (e->opcode) {
12970
+ if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12971
+ return rc;
12972
+ }
12973
+ if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12974
+ Jim_DecrRefCount(interp, A);
12975
+ return rc;
12976
+ }
12977
+
12978
+ switch (node->type) {
1309012979
case JIM_EXPROP_STREQ:
1309112980
case JIM_EXPROP_STRNE:
1309212981
wC = Jim_StringEqObj(A, B);
13093
- if (e->opcode == JIM_EXPROP_STRNE) {
12982
+ if (node->type == JIM_EXPROP_STRNE) {
1309412983
wC = !wC;
1309512984
}
1309612985
break;
1309712986
case JIM_EXPROP_STRIN:
1309812987
wC = JimSearchList(interp, B, A);
@@ -13101,178 +12990,99 @@
1310112990
wC = !JimSearchList(interp, B, A);
1310212991
break;
1310312992
default:
1310412993
abort();
1310512994
}
13106
- ExprPush(e, Jim_NewIntObj(interp, wC));
12995
+ Jim_SetResultInt(interp, wC);
1310712996
1310812997
Jim_DecrRefCount(interp, A);
1310912998
Jim_DecrRefCount(interp, B);
1311012999
13111
- return JIM_OK;
13000
+ return rc;
1311213001
}
1311313002
1311413003
static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
1311513004
{
1311613005
long l;
1311713006
double d;
13007
+ int b;
13008
+ int ret = -1;
13009
+
13010
+
13011
+ Jim_IncrRefCount(obj);
1311813012
1311913013
if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
13120
- return l != 0;
13121
- }
13122
- if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13123
- return d != 0;
13124
- }
13125
- return -1;
13126
-}
13127
-
13128
-static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
13129
-{
13130
- Jim_Obj *skip = ExprPop(e);
13131
- Jim_Obj *A = ExprPop(e);
13132
- int rc = JIM_OK;
13133
-
13134
- switch (ExprBool(interp, A)) {
13135
- case 0:
13136
-
13137
- e->skip = JimWideValue(skip);
13138
- ExprPush(e, Jim_NewIntObj(interp, 0));
13139
- break;
13140
-
13141
- case 1:
13142
-
13143
- break;
13144
-
13145
- case -1:
13146
-
13147
- rc = JIM_ERR;
13148
- }
13149
- Jim_DecrRefCount(interp, A);
13150
- Jim_DecrRefCount(interp, skip);
13151
-
13152
- return rc;
13153
-}
13154
-
13155
-static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e)
13156
-{
13157
- Jim_Obj *skip = ExprPop(e);
13158
- Jim_Obj *A = ExprPop(e);
13159
- int rc = JIM_OK;
13160
-
13161
- switch (ExprBool(interp, A)) {
13162
- case 0:
13163
-
13164
- break;
13165
-
13166
- case 1:
13167
-
13168
- e->skip = JimWideValue(skip);
13169
- ExprPush(e, Jim_NewIntObj(interp, 1));
13170
- break;
13171
-
13172
- case -1:
13173
-
13174
- rc = JIM_ERR;
13175
- break;
13176
- }
13177
- Jim_DecrRefCount(interp, A);
13178
- Jim_DecrRefCount(interp, skip);
13179
-
13180
- return rc;
13181
-}
13182
-
13183
-static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e)
13184
-{
13185
- Jim_Obj *A = ExprPop(e);
13186
- int rc = JIM_OK;
13187
-
13188
- switch (ExprBool(interp, A)) {
13189
- case 0:
13190
- ExprPush(e, Jim_NewIntObj(interp, 0));
13191
- break;
13192
-
13193
- case 1:
13194
- ExprPush(e, Jim_NewIntObj(interp, 1));
13195
- break;
13196
-
13197
- case -1:
13198
-
13199
- rc = JIM_ERR;
13200
- break;
13201
- }
13202
- Jim_DecrRefCount(interp, A);
13203
-
13204
- return rc;
13205
-}
13206
-
13207
-static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e)
13208
-{
13209
- Jim_Obj *skip = ExprPop(e);
13210
- Jim_Obj *A = ExprPop(e);
13211
- int rc = JIM_OK;
13212
-
13213
-
13214
- ExprPush(e, A);
13215
-
13216
- switch (ExprBool(interp, A)) {
13217
- case 0:
13218
-
13219
- e->skip = JimWideValue(skip);
13220
-
13221
- ExprPush(e, Jim_NewIntObj(interp, 0));
13222
- break;
13223
-
13224
- case 1:
13225
-
13226
- break;
13227
-
13228
- case -1:
13229
-
13230
- rc = JIM_ERR;
13231
- break;
13232
- }
13233
- Jim_DecrRefCount(interp, A);
13234
- Jim_DecrRefCount(interp, skip);
13235
-
13236
- return rc;
13237
-}
13238
-
13239
-static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e)
13240
-{
13241
- Jim_Obj *skip = ExprPop(e);
13242
- Jim_Obj *B = ExprPop(e);
13243
- Jim_Obj *A = ExprPop(e);
13244
-
13245
-
13246
- if (ExprBool(interp, A)) {
13247
-
13248
- e->skip = JimWideValue(skip);
13249
-
13250
- ExprPush(e, B);
13251
- }
13252
-
13253
- Jim_DecrRefCount(interp, skip);
13254
- Jim_DecrRefCount(interp, A);
13255
- Jim_DecrRefCount(interp, B);
13256
- return JIM_OK;
13257
-}
13258
-
13259
-static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e)
13260
-{
13261
- return JIM_OK;
13014
+ ret = (l != 0);
13015
+ }
13016
+ else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13017
+ ret = (d != 0);
13018
+ }
13019
+ else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
13020
+ ret = (b != 0);
13021
+ }
13022
+
13023
+ Jim_DecrRefCount(interp, obj);
13024
+ return ret;
13025
+}
13026
+
13027
+static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node)
13028
+{
13029
+
13030
+ int result = JimExprGetTermBoolean(interp, node->left);
13031
+
13032
+ if (result == 1) {
13033
+
13034
+ result = JimExprGetTermBoolean(interp, node->right);
13035
+ }
13036
+ if (result == -1) {
13037
+ return JIM_ERR;
13038
+ }
13039
+ Jim_SetResultInt(interp, result);
13040
+ return JIM_OK;
13041
+}
13042
+
13043
+static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node)
13044
+{
13045
+
13046
+ int result = JimExprGetTermBoolean(interp, node->left);
13047
+
13048
+ if (result == 0) {
13049
+
13050
+ result = JimExprGetTermBoolean(interp, node->right);
13051
+ }
13052
+ if (result == -1) {
13053
+ return JIM_ERR;
13054
+ }
13055
+ Jim_SetResultInt(interp, result);
13056
+ return JIM_OK;
13057
+}
13058
+
13059
+static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node)
13060
+{
13061
+
13062
+ int result = JimExprGetTermBoolean(interp, node->left);
13063
+
13064
+ if (result == 1) {
13065
+
13066
+ return JimExprEvalTermNode(interp, node->right);
13067
+ }
13068
+ else if (result == 0) {
13069
+
13070
+ return JimExprEvalTermNode(interp, node->ternary);
13071
+ }
13072
+
13073
+ return JIM_ERR;
1326213074
}
1326313075
1326413076
enum
1326513077
{
13266
- LAZY_NONE,
13267
- LAZY_OP,
13268
- LAZY_LEFT,
13269
- LAZY_RIGHT
13078
+ OP_FUNC = 0x0001,
13079
+ OP_RIGHT_ASSOC = 0x0002,
1327013080
};
1327113081
13272
-#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13273
-#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13082
+#define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1}
13083
+#define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0)
1327413084
1327513085
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
1327613086
OPRINIT("*", 110, 2, JimExprOpBin),
1327713087
OPRINIT("/", 110, 2, JimExprOpBin),
1327813088
OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,86 +13106,79 @@
1329613106
1329713107
OPRINIT("&", 50, 2, JimExprOpIntBin),
1329813108
OPRINIT("^", 49, 2, JimExprOpIntBin),
1329913109
OPRINIT("|", 48, 2, JimExprOpIntBin),
1330013110
13301
- OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13302
- OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13303
- OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13304
-
13305
- OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13306
- OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13307
- OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13308
-
13309
- OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13310
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13311
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13312
-
13313
- OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13314
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13315
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13316
-
13317
- OPRINIT("**", 250, 2, JimExprOpBin),
13111
+ OPRINIT("&&", 10, 2, JimExprOpAnd),
13112
+ OPRINIT("||", 9, 2, JimExprOpOr),
13113
+ OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC),
13114
+ OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC),
13115
+
13116
+
13117
+ OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC),
1331813118
1331913119
OPRINIT("eq", 60, 2, JimExprOpStrBin),
1332013120
OPRINIT("ne", 60, 2, JimExprOpStrBin),
1332113121
1332213122
OPRINIT("in", 55, 2, JimExprOpStrBin),
1332313123
OPRINIT("ni", 55, 2, JimExprOpStrBin),
1332413124
13325
- OPRINIT("!", 150, 1, JimExprOpNumUnary),
13326
- OPRINIT("~", 150, 1, JimExprOpIntUnary),
13327
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13328
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13125
+ OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
13126
+ OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC),
13127
+ OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
13128
+ OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
1332913129
1333013130
1333113131
13332
- OPRINIT("int", 200, 1, JimExprOpNumUnary),
13333
- OPRINIT("wide", 200, 1, JimExprOpNumUnary),
13334
- OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13335
- OPRINIT("double", 200, 1, JimExprOpNumUnary),
13336
- OPRINIT("round", 200, 1, JimExprOpNumUnary),
13337
- OPRINIT("rand", 200, 0, JimExprOpNone),
13338
- OPRINIT("srand", 200, 1, JimExprOpIntUnary),
13132
+ OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC),
13133
+ OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC),
13134
+ OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC),
13135
+ OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC),
13136
+ OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC),
13137
+ OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC),
13138
+ OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC),
1333913139
1334013140
#ifdef JIM_MATH_FUNCTIONS
13341
- OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13342
- OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13343
- OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13344
- OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13345
- OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13346
- OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13347
- OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13348
- OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13349
- OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13350
- OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13351
- OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13352
- OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13353
- OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13354
- OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13355
- OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13356
- OPRINIT("pow", 200, 2, JimExprOpBin),
13141
+ OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13142
+ OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13143
+ OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13144
+ OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13145
+ OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13146
+ OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13147
+ OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC),
13148
+ OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13149
+ OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13150
+ OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13151
+ OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13152
+ OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13153
+ OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13154
+ OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13155
+ OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13156
+ OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13157
+ OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC),
13158
+ OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC),
13159
+ OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC),
1335713160
#endif
1335813161
};
1335913162
#undef OPRINIT
13360
-#undef OPRINIT_LAZY
13163
+#undef OPRINIT_ATTR
1336113164
1336213165
#define JIM_EXPR_OPERATORS_NUM \
1336313166
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1336413167
1336513168
static int JimParseExpression(struct JimParserCtx *pc)
1336613169
{
13367
-
13170
+
1336813171
while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
1336913172
if (*pc->p == '\n') {
1337013173
pc->linenr++;
1337113174
}
1337213175
pc->p++;
1337313176
pc->len--;
1337413177
}
1337513178
13376
-
13179
+
1337713180
pc->tline = pc->linenr;
1337813181
pc->tstart = pc->p;
1337913182
1338013183
if (pc->len == 0) {
1338113184
pc->tend = pc->p;
@@ -13401,11 +13204,11 @@
1340113204
return JimParseCmd(pc);
1340213205
case '$':
1340313206
if (JimParseVar(pc) == JIM_ERR)
1340413207
return JimParseExprOperator(pc);
1340513208
else {
13406
-
13209
+
1340713210
if (pc->tt == JIM_TT_EXPRSUGAR) {
1340813211
return JIM_ERR;
1340913212
}
1341013213
return JIM_OK;
1341113214
}
@@ -13430,10 +13233,18 @@
1343013233
case 'N':
1343113234
case 'I':
1343213235
case 'n':
1343313236
case 'i':
1343413237
if (JimParseExprIrrational(pc) == JIM_ERR)
13238
+ if (JimParseExprBoolean(pc) == JIM_ERR)
13239
+ return JimParseExprOperator(pc);
13240
+ break;
13241
+ case 't':
13242
+ case 'f':
13243
+ case 'o':
13244
+ case 'y':
13245
+ if (JimParseExprBoolean(pc) == JIM_ERR)
1343513246
return JimParseExprOperator(pc);
1343613247
break;
1343713248
default:
1343813249
return JimParseExprOperator(pc);
1343913250
break;
@@ -13443,21 +13254,21 @@
1344313254
1344413255
static int JimParseExprNumber(struct JimParserCtx *pc)
1344513256
{
1344613257
char *end;
1344713258
13448
-
13259
+
1344913260
pc->tt = JIM_TT_EXPR_INT;
1345013261
1345113262
jim_strtoull(pc->p, (char **)&pc->p);
13452
-
13263
+
1345313264
if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13454
- if (strtod(pc->tstart, &end)) { }
13265
+ if (strtod(pc->tstart, &end)) { }
1345513266
if (end == pc->tstart)
1345613267
return JIM_ERR;
1345713268
if (end > pc->p) {
13458
-
13269
+
1345913270
pc->tt = JIM_TT_EXPR_DOUBLE;
1346013271
pc->p = end;
1346113272
}
1346213273
}
1346313274
pc->tend = pc->p - 1;
@@ -13481,36 +13292,66 @@
1348113292
return JIM_OK;
1348213293
}
1348313294
}
1348413295
return JIM_ERR;
1348513296
}
13297
+
13298
+static int JimParseExprBoolean(struct JimParserCtx *pc)
13299
+{
13300
+ const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL };
13301
+ const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 };
13302
+ int i;
13303
+
13304
+ for (i = 0; booleans[i]; i++) {
13305
+ const char *boolean = booleans[i];
13306
+ int length = lengths[i];
13307
+
13308
+ if (strncmp(boolean, pc->p, length) == 0) {
13309
+ pc->p += length;
13310
+ pc->len -= length;
13311
+ pc->tend = pc->p - 1;
13312
+ pc->tt = JIM_TT_EXPR_BOOLEAN;
13313
+ return JIM_OK;
13314
+ }
13315
+ }
13316
+ return JIM_ERR;
13317
+}
13318
+
13319
+static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
13320
+{
13321
+ static Jim_ExprOperator dummy_op;
13322
+ if (opcode < JIM_TT_EXPR_OP) {
13323
+ return &dummy_op;
13324
+ }
13325
+ return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
13326
+}
1348613327
1348713328
static int JimParseExprOperator(struct JimParserCtx *pc)
1348813329
{
1348913330
int i;
13490
- int bestIdx = -1, bestLen = 0;
13331
+ const struct Jim_ExprOperator *bestOp = NULL;
13332
+ int bestLen = 0;
1349113333
13492
-
13334
+
1349313335
for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13494
- const char * const opname = Jim_ExprOperators[i].name;
13495
- const int oplen = Jim_ExprOperators[i].namelen;
13336
+ const struct Jim_ExprOperator *op = &Jim_ExprOperators[i];
1349613337
13497
- if (opname == NULL || opname[0] != pc->p[0]) {
13338
+ if (op->name[0] != pc->p[0]) {
1349813339
continue;
1349913340
}
1350013341
13501
- if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
13502
- bestIdx = i + JIM_TT_EXPR_OP;
13503
- bestLen = oplen;
13342
+ if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) {
13343
+ bestOp = op;
13344
+ bestLen = op->namelen;
1350413345
}
1350513346
}
13506
- if (bestIdx == -1) {
13347
+ if (bestOp == NULL) {
1350713348
return JIM_ERR;
1350813349
}
1350913350
13510
-
13511
- if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
13351
+
13352
+ if (bestOp->attr & OP_FUNC) {
1351213353
const char *p = pc->p + bestLen;
1351313354
int len = pc->len - bestLen;
1351413355
1351513356
while (len && isspace(UCHAR(*p))) {
1351613357
len--;
@@ -13522,30 +13363,27 @@
1352213363
}
1352313364
pc->tend = pc->p + bestLen - 1;
1352413365
pc->p += bestLen;
1352513366
pc->len -= bestLen;
1352613367
13527
- pc->tt = bestIdx;
13368
+ pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP;
1352813369
return JIM_OK;
1352913370
}
1353013371
13531
-static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
13532
-{
13533
- static Jim_ExprOperator dummy_op;
13534
- if (opcode < JIM_TT_EXPR_OP) {
13535
- return &dummy_op;
13536
- }
13537
- return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
13538
-}
13539
-
1354013372
const char *jim_tt_name(int type)
1354113373
{
1354213374
static const char * const tt_names[JIM_TT_EXPR_OP] =
1354313375
{ "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13544
- "DBL", "$()" };
13376
+ "DBL", "BOO", "$()" };
1354513377
if (type < JIM_TT_EXPR_OP) {
1354613378
return tt_names[type];
13379
+ }
13380
+ else if (type == JIM_EXPROP_UNARYMINUS) {
13381
+ return "-VE";
13382
+ }
13383
+ else if (type == JIM_EXPROP_UNARYPLUS) {
13384
+ return "+VE";
1354713385
}
1354813386
else {
1354913387
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
1355013388
static char buf[20];
1355113389
@@ -13568,432 +13406,400 @@
1356813406
NULL,
1356913407
JIM_TYPE_REFERENCES,
1357013408
};
1357113409
1357213410
13573
-typedef struct ExprByteCode
13574
-{
13575
- ScriptToken *token;
13576
- int len;
13577
- int inUse;
13578
-} ExprByteCode;
13579
-
13580
-static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13411
+struct ExprTree
13412
+{
13413
+ struct JimExprNode *expr;
13414
+ struct JimExprNode *nodes;
13415
+ int len;
13416
+ int inUse;
13417
+};
13418
+
13419
+static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num)
1358113420
{
1358213421
int i;
13422
+ for (i = 0; i < num; i++) {
13423
+ if (nodes[i].objPtr) {
13424
+ Jim_DecrRefCount(interp, nodes[i].objPtr);
13425
+ }
13426
+ }
13427
+ Jim_Free(nodes);
13428
+}
1358313429
13584
- for (i = 0; i < expr->len; i++) {
13585
- Jim_DecrRefCount(interp, expr->token[i].objPtr);
13586
- }
13587
- Jim_Free(expr->token);
13430
+static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr)
13431
+{
13432
+ ExprTreeFreeNodes(interp, expr->nodes, expr->len);
1358813433
Jim_Free(expr);
1358913434
}
1359013435
1359113436
static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
1359213437
{
13593
- ExprByteCode *expr = (void *)objPtr->internalRep.ptr;
13438
+ struct ExprTree *expr = (void *)objPtr->internalRep.ptr;
1359413439
1359513440
if (expr) {
1359613441
if (--expr->inUse != 0) {
1359713442
return;
1359813443
}
1359913444
13600
- ExprFreeByteCode(interp, expr);
13445
+ ExprTreeFree(interp, expr);
1360113446
}
1360213447
}
1360313448
1360413449
static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
1360513450
{
1360613451
JIM_NOTUSED(interp);
1360713452
JIM_NOTUSED(srcPtr);
1360813453
13609
-
13454
+
1361013455
dupPtr->typePtr = NULL;
1361113456
}
1361213457
13613
-
13614
-static int ExprCheckCorrectness(ExprByteCode * expr)
13615
-{
13616
- int i;
13617
- int stacklen = 0;
13618
- int ternary = 0;
13619
-
13620
- for (i = 0; i < expr->len; i++) {
13621
- ScriptToken *t = &expr->token[i];
13622
- const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13623
-
13624
- stacklen -= op->arity;
13625
- if (stacklen < 0) {
13626
- break;
13627
- }
13628
- if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
13629
- ternary++;
13630
- }
13631
- else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
13632
- ternary--;
13633
- }
13634
-
13635
-
13636
- stacklen++;
13637
- }
13638
- if (stacklen != 1 || ternary != 0) {
13639
- return JIM_ERR;
13640
- }
13641
- return JIM_OK;
13642
-}
13643
-
13644
-static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13645
-{
13646
- int i;
13647
-
13648
- int leftindex, arity, offset;
13649
-
13650
-
13651
- leftindex = expr->len - 1;
13652
-
13653
- arity = 1;
13654
- while (arity) {
13655
- ScriptToken *tt = &expr->token[leftindex];
13656
-
13657
- if (tt->type >= JIM_TT_EXPR_OP) {
13658
- arity += JimExprOperatorInfoByOpcode(tt->type)->arity;
13659
- }
13660
- arity--;
13661
- if (--leftindex < 0) {
13662
- return JIM_ERR;
13663
- }
13664
- }
13665
- leftindex++;
13666
-
13667
-
13668
- memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
13669
- sizeof(*expr->token) * (expr->len - leftindex));
13670
- expr->len += 2;
13671
- offset = (expr->len - leftindex) - 1;
13672
-
13673
- expr->token[leftindex + 1].type = t->type + 1;
13674
- expr->token[leftindex + 1].objPtr = interp->emptyObj;
13675
-
13676
- expr->token[leftindex].type = JIM_TT_EXPR_INT;
13677
- expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
13678
-
13679
-
13680
- expr->token[expr->len].objPtr = interp->emptyObj;
13681
- expr->token[expr->len].type = t->type + 2;
13682
- expr->len++;
13683
-
13684
-
13685
- for (i = leftindex - 1; i > 0; i--) {
13686
- const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
13687
- if (op->lazy == LAZY_LEFT) {
13688
- if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
13689
- JimWideValue(expr->token[i - 1].objPtr) += 2;
13690
- }
13691
- }
13692
- }
13693
- return JIM_OK;
13694
-}
13695
-
13696
-static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13697
-{
13698
- struct ScriptToken *token = &expr->token[expr->len];
13699
- const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13700
-
13701
- if (op->lazy == LAZY_OP) {
13702
- if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) {
13703
- Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name);
13704
- return JIM_ERR;
13705
- }
13706
- }
13707
- else {
13708
- token->objPtr = interp->emptyObj;
13709
- token->type = t->type;
13710
- expr->len++;
13711
- }
13712
- return JIM_OK;
13713
-}
13714
-
13715
-static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
13716
-{
13717
- int ternary_count = 1;
13718
-
13719
- right_index--;
13720
-
13721
- while (right_index > 1) {
13722
- if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) {
13723
- ternary_count--;
13724
- }
13725
- else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) {
13726
- ternary_count++;
13727
- }
13728
- else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) {
13729
- return right_index;
13730
- }
13731
- right_index--;
13732
- }
13733
-
13734
-
13735
- return -1;
13736
-}
13737
-
13738
-static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
13739
-{
13740
- int i = right_index - 1;
13741
- int ternary_count = 1;
13742
-
13743
- while (i > 1) {
13744
- if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) {
13745
- if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) {
13746
- *prev_right_index = i - 2;
13747
- *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index);
13748
- return 1;
13749
- }
13750
- }
13751
- else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) {
13752
- if (ternary_count == 0) {
13753
- return 0;
13754
- }
13755
- ternary_count++;
13756
- }
13757
- i--;
13758
- }
13759
- return 0;
13760
-}
13761
-
13762
-static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
13763
-{
13764
- int i;
13765
-
13766
- for (i = expr->len - 1; i > 1; i--) {
13767
- int prev_right_index;
13768
- int prev_left_index;
13769
- int j;
13770
- ScriptToken tmp;
13771
-
13772
- if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
13773
- continue;
13774
- }
13775
-
13776
-
13777
- if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
13778
- continue;
13779
- }
13780
-
13781
- tmp = expr->token[prev_right_index];
13782
- for (j = prev_right_index; j < i; j++) {
13783
- expr->token[j] = expr->token[j + 1];
13784
- }
13785
- expr->token[i] = tmp;
13786
-
13787
- JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
13788
-
13789
-
13790
- i++;
13791
- }
13792
-}
13793
-
13794
-static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
13795
-{
13458
+struct ExprBuilder {
13459
+ int parencount;
13460
+ int level;
13461
+ ParseToken *token;
13462
+ ParseToken *first_token;
1379613463
Jim_Stack stack;
13797
- ExprByteCode *expr;
13798
- int ok = 1;
13464
+ Jim_Obj *exprObjPtr;
13465
+ Jim_Obj *fileNameObj;
13466
+ struct JimExprNode *nodes;
13467
+ struct JimExprNode *next;
13468
+};
13469
+
13470
+#ifdef DEBUG_SHOW_EXPR
13471
+static void JimShowExprNode(struct JimExprNode *node, int level)
13472
+{
1379913473
int i;
13800
- int prevtt = JIM_TT_NONE;
13801
- int have_ternary = 0;
13474
+ for (i = 0; i < level; i++) {
13475
+ printf(" ");
13476
+ }
13477
+ if (TOKEN_IS_EXPR_OP(node->type)) {
13478
+ printf("%s\n", jim_tt_name(node->type));
13479
+ if (node->left) {
13480
+ JimShowExprNode(node->left, level + 1);
13481
+ }
13482
+ if (node->right) {
13483
+ JimShowExprNode(node->right, level + 1);
13484
+ }
13485
+ if (node->ternary) {
13486
+ JimShowExprNode(node->ternary, level + 1);
13487
+ }
13488
+ }
13489
+ else {
13490
+ printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr));
13491
+ }
13492
+}
13493
+#endif
1380213494
13803
-
13804
- int count = tokenlist->count - 1;
13495
+#define EXPR_UNTIL_CLOSE 0x0001
13496
+#define EXPR_FUNC_ARGS 0x0002
13497
+#define EXPR_TERNARY 0x0004
13498
+
13499
+static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms)
13500
+{
13501
+ int rc;
13502
+ struct JimExprNode *node;
13503
+
13504
+ int exp_stacklen = builder->stack.len + exp_numterms;
13505
+
13506
+ if (builder->level++ > 200) {
13507
+ Jim_SetResultString(interp, "Expression too complex", -1);
13508
+ return JIM_ERR;
13509
+ }
13510
+
13511
+ while (builder->token->type != JIM_TT_EOL) {
13512
+ ParseToken *t = builder->token++;
13513
+ int prevtt;
13514
+
13515
+ if (t == builder->first_token) {
13516
+ prevtt = JIM_TT_NONE;
13517
+ }
13518
+ else {
13519
+ prevtt = t[-1].type;
13520
+ }
13521
+
13522
+ if (t->type == JIM_TT_SUBEXPR_START) {
13523
+ if (builder->stack.len == exp_stacklen) {
13524
+ Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr);
13525
+ return JIM_ERR;
13526
+ }
13527
+ builder->parencount++;
13528
+ rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1);
13529
+ if (rc != JIM_OK) {
13530
+ return rc;
13531
+ }
13532
+
13533
+ }
13534
+ else if (t->type == JIM_TT_SUBEXPR_END) {
13535
+ if (!(flags & EXPR_UNTIL_CLOSE)) {
13536
+ if (builder->stack.len == exp_stacklen && builder->level > 1) {
13537
+ builder->token--;
13538
+ builder->level--;
13539
+ return JIM_OK;
13540
+ }
13541
+ Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr);
13542
+ return JIM_ERR;
13543
+ }
13544
+ builder->parencount--;
13545
+ if (builder->stack.len == exp_stacklen) {
13546
+
13547
+ break;
13548
+ }
13549
+ }
13550
+ else if (t->type == JIM_TT_SUBEXPR_COMMA) {
13551
+ if (!(flags & EXPR_FUNC_ARGS)) {
13552
+ if (builder->stack.len == exp_stacklen) {
13553
+
13554
+ builder->token--;
13555
+ builder->level--;
13556
+ return JIM_OK;
13557
+ }
13558
+ Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr);
13559
+ return JIM_ERR;
13560
+ }
13561
+ else {
13562
+
13563
+ if (builder->stack.len > exp_stacklen) {
13564
+ Jim_SetResultFormatted(interp, "too many arguments to math function");
13565
+ return JIM_ERR;
13566
+ }
13567
+ }
13568
+
13569
+ }
13570
+ else if (t->type == JIM_EXPROP_COLON) {
13571
+ if (!(flags & EXPR_TERNARY)) {
13572
+ if (builder->level != 1) {
13573
+
13574
+ builder->token--;
13575
+ builder->level--;
13576
+ return JIM_OK;
13577
+ }
13578
+ Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr);
13579
+ return JIM_ERR;
13580
+ }
13581
+ if (builder->stack.len == exp_stacklen) {
13582
+
13583
+ builder->token--;
13584
+ builder->level--;
13585
+ return JIM_OK;
13586
+ }
13587
+
13588
+ }
13589
+ else if (TOKEN_IS_EXPR_OP(t->type)) {
13590
+ const struct Jim_ExprOperator *op;
13591
+
13592
+
13593
+ if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) {
13594
+ if (t->type == JIM_EXPROP_SUB) {
13595
+ t->type = JIM_EXPROP_UNARYMINUS;
13596
+ }
13597
+ else if (t->type == JIM_EXPROP_ADD) {
13598
+ t->type = JIM_EXPROP_UNARYPLUS;
13599
+ }
13600
+ }
13601
+
13602
+ op = JimExprOperatorInfoByOpcode(t->type);
13603
+
13604
+ if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) {
13605
+
13606
+ builder->token--;
13607
+ break;
13608
+ }
13609
+
13610
+ if (op->attr & OP_FUNC) {
13611
+ if (builder->token->type != JIM_TT_SUBEXPR_START) {
13612
+ Jim_SetResultString(interp, "missing arguments for math function", -1);
13613
+ return JIM_ERR;
13614
+ }
13615
+ builder->token++;
13616
+ if (op->arity == 0) {
13617
+ if (builder->token->type != JIM_TT_SUBEXPR_END) {
13618
+ Jim_SetResultString(interp, "too many arguments for math function", -1);
13619
+ return JIM_ERR;
13620
+ }
13621
+ builder->token++;
13622
+ goto noargs;
13623
+ }
13624
+ builder->parencount++;
13625
+
13626
+
13627
+ rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity);
13628
+ }
13629
+ else if (t->type == JIM_EXPROP_TERNARY) {
13630
+
13631
+ rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2);
13632
+ }
13633
+ else {
13634
+ rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1);
13635
+ }
13636
+
13637
+ if (rc != JIM_OK) {
13638
+ return rc;
13639
+ }
13640
+
13641
+noargs:
13642
+ node = builder->next++;
13643
+ node->type = t->type;
13644
+
13645
+ if (op->arity >= 3) {
13646
+ node->ternary = Jim_StackPop(&builder->stack);
13647
+ if (node->ternary == NULL) {
13648
+ goto missingoperand;
13649
+ }
13650
+ }
13651
+ if (op->arity >= 2) {
13652
+ node->right = Jim_StackPop(&builder->stack);
13653
+ if (node->right == NULL) {
13654
+ goto missingoperand;
13655
+ }
13656
+ }
13657
+ if (op->arity >= 1) {
13658
+ node->left = Jim_StackPop(&builder->stack);
13659
+ if (node->left == NULL) {
13660
+missingoperand:
13661
+ Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr);
13662
+ builder->next--;
13663
+ return JIM_ERR;
13664
+
13665
+ }
13666
+ }
13667
+
13668
+
13669
+ Jim_StackPush(&builder->stack, node);
13670
+ }
13671
+ else {
13672
+ Jim_Obj *objPtr = NULL;
13673
+
13674
+
13675
+
13676
+
13677
+ if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) {
13678
+ Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr);
13679
+ return JIM_ERR;
13680
+ }
13681
+
13682
+
13683
+ if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) {
13684
+ char *endptr;
13685
+ if (t->type == JIM_TT_EXPR_INT) {
13686
+ objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13687
+ }
13688
+ else {
13689
+ objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13690
+ }
13691
+ if (endptr != t->token + t->len) {
13692
+
13693
+ Jim_FreeNewObj(interp, objPtr);
13694
+ objPtr = NULL;
13695
+ }
13696
+ }
13697
+
13698
+ if (!objPtr) {
13699
+
13700
+ objPtr = Jim_NewStringObj(interp, t->token, t->len);
13701
+ if (t->type == JIM_TT_CMD) {
13702
+
13703
+ JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line);
13704
+ }
13705
+ }
13706
+
13707
+
13708
+ node = builder->next++;
13709
+ node->objPtr = objPtr;
13710
+ Jim_IncrRefCount(node->objPtr);
13711
+ node->type = t->type;
13712
+ Jim_StackPush(&builder->stack, node);
13713
+ }
13714
+ }
13715
+
13716
+ if (builder->stack.len == exp_stacklen) {
13717
+ builder->level--;
13718
+ return JIM_OK;
13719
+ }
13720
+
13721
+ if ((flags & EXPR_FUNC_ARGS)) {
13722
+ Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many");
13723
+ }
13724
+ else {
13725
+ if (builder->stack.len < exp_stacklen) {
13726
+ if (builder->level == 0) {
13727
+ Jim_SetResultFormatted(interp, "empty expression");
13728
+ }
13729
+ else {
13730
+ Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr);
13731
+ }
13732
+ }
13733
+ else {
13734
+ Jim_SetResultFormatted(interp, "extra terms after expression");
13735
+ }
13736
+ }
13737
+
13738
+ return JIM_ERR;
13739
+}
13740
+
13741
+static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
13742
+{
13743
+ struct ExprTree *expr;
13744
+ struct ExprBuilder builder;
13745
+ int rc;
13746
+ struct JimExprNode *top;
13747
+
13748
+ builder.parencount = 0;
13749
+ builder.level = 0;
13750
+ builder.token = builder.first_token = tokenlist->list;
13751
+ builder.exprObjPtr = exprObjPtr;
13752
+ builder.fileNameObj = fileNameObj;
13753
+
13754
+ builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
13755
+ memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1));
13756
+ builder.next = builder.nodes;
13757
+ Jim_InitStack(&builder.stack);
13758
+
13759
+ rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1);
13760
+
13761
+ if (rc == JIM_OK) {
13762
+ top = Jim_StackPop(&builder.stack);
13763
+
13764
+ if (builder.parencount) {
13765
+ Jim_SetResultString(interp, "missing close parenthesis", -1);
13766
+ rc = JIM_ERR;
13767
+ }
13768
+ }
13769
+
13770
+
13771
+ Jim_FreeStack(&builder.stack);
13772
+
13773
+ if (rc != JIM_OK) {
13774
+ ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes);
13775
+ return NULL;
13776
+ }
1380513777
1380613778
expr = Jim_Alloc(sizeof(*expr));
1380713779
expr->inUse = 1;
13808
- expr->len = 0;
13809
-
13810
- Jim_InitStack(&stack);
13811
-
13812
- for (i = 0; i < tokenlist->count; i++) {
13813
- ParseToken *t = &tokenlist->list[i];
13814
- const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13815
-
13816
- if (op->lazy == LAZY_OP) {
13817
- count += 2;
13818
-
13819
- if (t->type == JIM_EXPROP_TERNARY) {
13820
- have_ternary = 1;
13821
- }
13822
- }
13823
- }
13824
-
13825
- expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
13826
-
13827
- for (i = 0; i < tokenlist->count && ok; i++) {
13828
- ParseToken *t = &tokenlist->list[i];
13829
-
13830
-
13831
- struct ScriptToken *token = &expr->token[expr->len];
13832
-
13833
- if (t->type == JIM_TT_EOL) {
13834
- break;
13835
- }
13836
-
13837
- switch (t->type) {
13838
- case JIM_TT_STR:
13839
- case JIM_TT_ESC:
13840
- case JIM_TT_VAR:
13841
- case JIM_TT_DICTSUGAR:
13842
- case JIM_TT_EXPRSUGAR:
13843
- case JIM_TT_CMD:
13844
- token->type = t->type;
13845
-strexpr:
13846
- token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13847
- if (t->type == JIM_TT_CMD) {
13848
-
13849
- JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13850
- }
13851
- expr->len++;
13852
- break;
13853
-
13854
- case JIM_TT_EXPR_INT:
13855
- case JIM_TT_EXPR_DOUBLE:
13856
- {
13857
- char *endptr;
13858
- if (t->type == JIM_TT_EXPR_INT) {
13859
- token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13860
- }
13861
- else {
13862
- token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13863
- }
13864
- if (endptr != t->token + t->len) {
13865
-
13866
- Jim_FreeNewObj(interp, token->objPtr);
13867
- token->type = JIM_TT_STR;
13868
- goto strexpr;
13869
- }
13870
- token->type = t->type;
13871
- expr->len++;
13872
- }
13873
- break;
13874
-
13875
- case JIM_TT_SUBEXPR_START:
13876
- Jim_StackPush(&stack, t);
13877
- prevtt = JIM_TT_NONE;
13878
- continue;
13879
-
13880
- case JIM_TT_SUBEXPR_COMMA:
13881
-
13882
- continue;
13883
-
13884
- case JIM_TT_SUBEXPR_END:
13885
- ok = 0;
13886
- while (Jim_StackLen(&stack)) {
13887
- ParseToken *tt = Jim_StackPop(&stack);
13888
-
13889
- if (tt->type == JIM_TT_SUBEXPR_START) {
13890
- ok = 1;
13891
- break;
13892
- }
13893
-
13894
- if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13895
- goto err;
13896
- }
13897
- }
13898
- if (!ok) {
13899
- Jim_SetResultString(interp, "Unexpected close parenthesis", -1);
13900
- goto err;
13901
- }
13902
- break;
13903
-
13904
-
13905
- default:{
13906
-
13907
- const struct Jim_ExprOperator *op;
13908
- ParseToken *tt;
13909
-
13910
-
13911
- if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
13912
- if (t->type == JIM_EXPROP_SUB) {
13913
- t->type = JIM_EXPROP_UNARYMINUS;
13914
- }
13915
- else if (t->type == JIM_EXPROP_ADD) {
13916
- t->type = JIM_EXPROP_UNARYPLUS;
13917
- }
13918
- }
13919
-
13920
- op = JimExprOperatorInfoByOpcode(t->type);
13921
-
13922
-
13923
- while ((tt = Jim_StackPeek(&stack)) != NULL) {
13924
- const struct Jim_ExprOperator *tt_op =
13925
- JimExprOperatorInfoByOpcode(tt->type);
13926
-
13927
-
13928
-
13929
- if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13930
- if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13931
- ok = 0;
13932
- goto err;
13933
- }
13934
- Jim_StackPop(&stack);
13935
- }
13936
- else {
13937
- break;
13938
- }
13939
- }
13940
- Jim_StackPush(&stack, t);
13941
- break;
13942
- }
13943
- }
13944
- prevtt = t->type;
13945
- }
13946
-
13947
-
13948
- while (Jim_StackLen(&stack)) {
13949
- ParseToken *tt = Jim_StackPop(&stack);
13950
-
13951
- if (tt->type == JIM_TT_SUBEXPR_START) {
13952
- ok = 0;
13953
- Jim_SetResultString(interp, "Missing close parenthesis", -1);
13954
- goto err;
13955
- }
13956
- if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13957
- ok = 0;
13958
- goto err;
13959
- }
13960
- }
13961
-
13962
- if (have_ternary) {
13963
- ExprTernaryReorderExpression(interp, expr);
13964
- }
13965
-
13966
- err:
13967
-
13968
- Jim_FreeStack(&stack);
13969
-
13970
- for (i = 0; i < expr->len; i++) {
13971
- Jim_IncrRefCount(expr->token[i].objPtr);
13972
- }
13973
-
13974
- if (!ok) {
13975
- ExprFreeByteCode(interp, expr);
13976
- return NULL;
13977
- }
13780
+ expr->expr = top;
13781
+ expr->nodes = builder.nodes;
13782
+ expr->len = builder.next - builder.nodes;
13783
+
13784
+ assert(expr->len <= tokenlist->count - 1);
1397813785
1397913786
return expr;
1398013787
}
13981
-
1398213788
1398313789
static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
1398413790
{
1398513791
int exprTextLen;
1398613792
const char *exprText;
1398713793
struct JimParserCtx parser;
13988
- struct ExprByteCode *expr;
13794
+ struct ExprTree *expr;
1398913795
ParseTokenList tokenlist;
1399013796
int line;
1399113797
Jim_Obj *fileNameObj;
1399213798
int rc = JIM_ERR;
1399313799
13994
-
13800
+
1399513801
if (objPtr->typePtr == &sourceObjType) {
1399613802
fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
1399713803
line = objPtr->internalRep.sourceValue.lineNumber;
1399813804
}
1399913805
else {
@@ -14002,18 +13808,17 @@
1400213808
}
1400313809
Jim_IncrRefCount(fileNameObj);
1400413810
1400513811
exprText = Jim_GetString(objPtr, &exprTextLen);
1400613812
14007
-
13813
+
1400813814
ScriptTokenListInit(&tokenlist);
1400913815
1401013816
JimParserInit(&parser, exprText, exprTextLen, line);
1401113817
while (!parser.eof) {
1401213818
if (JimParseExpression(&parser) != JIM_OK) {
1401313819
ScriptTokenListFree(&tokenlist);
14014
- invalidexpr:
1401513820
Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
1401613821
expr = NULL;
1401713822
goto err;
1401813823
}
1401913824
@@ -14036,125 +13841,174 @@
1403613841
ScriptTokenListFree(&tokenlist);
1403713842
Jim_DecrRefCount(interp, fileNameObj);
1403813843
return JIM_ERR;
1403913844
}
1404013845
14041
-
14042
- expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
1404313846
14044
-
13847
+ expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj);
13848
+
13849
+
1404513850
ScriptTokenListFree(&tokenlist);
1404613851
1404713852
if (!expr) {
1404813853
goto err;
1404913854
}
1405013855
1405113856
#ifdef DEBUG_SHOW_EXPR
14052
- {
14053
- int i;
14054
-
14055
- printf("==== Expr ====\n");
14056
- for (i = 0; i < expr->len; i++) {
14057
- ScriptToken *t = &expr->token[i];
14058
-
14059
- printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
14060
- }
14061
- }
13857
+ printf("==== Expr ====\n");
13858
+ JimShowExprNode(expr->expr, 0);
1406213859
#endif
1406313860
14064
-
14065
- if (ExprCheckCorrectness(expr) != JIM_OK) {
14066
- ExprFreeByteCode(interp, expr);
14067
- goto invalidexpr;
14068
- }
14069
-
1407013861
rc = JIM_OK;
1407113862
1407213863
err:
14073
-
13864
+
1407413865
Jim_DecrRefCount(interp, fileNameObj);
1407513866
Jim_FreeIntRep(interp, objPtr);
1407613867
Jim_SetIntRepPtr(objPtr, expr);
1407713868
objPtr->typePtr = &exprObjType;
1407813869
return rc;
1407913870
}
1408013871
14081
-static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
13872
+static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
1408213873
{
1408313874
if (objPtr->typePtr != &exprObjType) {
1408413875
if (SetExprFromAny(interp, objPtr) != JIM_OK) {
1408513876
return NULL;
1408613877
}
1408713878
}
14088
- return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13879
+ return (struct ExprTree *) Jim_GetIntRepPtr(objPtr);
1408913880
}
1409013881
1409113882
#ifdef JIM_OPTIMIZATION
14092
-static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
14093
-{
14094
- if (token->type == JIM_TT_EXPR_INT)
14095
- return token->objPtr;
14096
- else if (token->type == JIM_TT_VAR)
14097
- return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
14098
- else if (token->type == JIM_TT_DICTSUGAR)
14099
- return JimExpandDictSugar(interp, token->objPtr);
13883
+static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node)
13884
+{
13885
+ if (node->type == JIM_TT_EXPR_INT)
13886
+ return node->objPtr;
13887
+ else if (node->type == JIM_TT_VAR)
13888
+ return Jim_GetVariable(interp, node->objPtr, JIM_NONE);
13889
+ else if (node->type == JIM_TT_DICTSUGAR)
13890
+ return JimExpandDictSugar(interp, node->objPtr);
1410013891
else
1410113892
return NULL;
1410213893
}
1410313894
#endif
1410413895
14105
-#define JIM_EE_STATICSTACK_LEN 10
14106
-
14107
-int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
14108
-{
14109
- ExprByteCode *expr;
14110
- Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];
14111
- int i;
14112
- int retcode = JIM_OK;
14113
- struct JimExprState e;
13896
+
13897
+static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node)
13898
+{
13899
+ if (TOKEN_IS_EXPR_OP(node->type)) {
13900
+ const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type);
13901
+ return op->funcop(interp, node);
13902
+ }
13903
+ else {
13904
+ Jim_Obj *objPtr;
13905
+
13906
+
13907
+ switch (node->type) {
13908
+ case JIM_TT_EXPR_INT:
13909
+ case JIM_TT_EXPR_DOUBLE:
13910
+ case JIM_TT_EXPR_BOOLEAN:
13911
+ case JIM_TT_STR:
13912
+ Jim_SetResult(interp, node->objPtr);
13913
+ return JIM_OK;
13914
+
13915
+ case JIM_TT_VAR:
13916
+ objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG);
13917
+ if (objPtr) {
13918
+ Jim_SetResult(interp, objPtr);
13919
+ return JIM_OK;
13920
+ }
13921
+ return JIM_ERR;
13922
+
13923
+ case JIM_TT_DICTSUGAR:
13924
+ objPtr = JimExpandDictSugar(interp, node->objPtr);
13925
+ if (objPtr) {
13926
+ Jim_SetResult(interp, objPtr);
13927
+ return JIM_OK;
13928
+ }
13929
+ return JIM_ERR;
13930
+
13931
+ case JIM_TT_ESC:
13932
+ if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) {
13933
+ Jim_SetResult(interp, objPtr);
13934
+ return JIM_OK;
13935
+ }
13936
+ return JIM_ERR;
13937
+
13938
+ case JIM_TT_CMD:
13939
+ return Jim_EvalObj(interp, node->objPtr);
13940
+
13941
+ default:
13942
+
13943
+ return JIM_ERR;
13944
+ }
13945
+ }
13946
+}
13947
+
13948
+static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr)
13949
+{
13950
+ int rc = JimExprEvalTermNode(interp, node);
13951
+ if (rc == JIM_OK) {
13952
+ *objPtrPtr = Jim_GetResult(interp);
13953
+ Jim_IncrRefCount(*objPtrPtr);
13954
+ }
13955
+ return rc;
13956
+}
13957
+
13958
+static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node)
13959
+{
13960
+ if (JimExprEvalTermNode(interp, node) == JIM_OK) {
13961
+ return ExprBool(interp, Jim_GetResult(interp));
13962
+ }
13963
+ return -1;
13964
+}
13965
+
13966
+int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
13967
+{
13968
+ struct ExprTree *expr;
13969
+ int retcode = JIM_OK;
1411413970
1411513971
expr = JimGetExpression(interp, exprObjPtr);
1411613972
if (!expr) {
14117
- return JIM_ERR;
13973
+ return JIM_ERR;
1411813974
}
1411913975
1412013976
#ifdef JIM_OPTIMIZATION
1412113977
{
1412213978
Jim_Obj *objPtr;
1412313979
1412413980
1412513981
switch (expr->len) {
1412613982
case 1:
14127
- objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13983
+ objPtr = JimExprIntValOrVar(interp, expr->expr);
1412813984
if (objPtr) {
14129
- Jim_IncrRefCount(objPtr);
14130
- *exprResultPtrPtr = objPtr;
13985
+ Jim_SetResult(interp, objPtr);
1413113986
return JIM_OK;
1413213987
}
1413313988
break;
1413413989
1413513990
case 2:
14136
- if (expr->token[1].type == JIM_EXPROP_NOT) {
14137
- objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13991
+ if (expr->expr->type == JIM_EXPROP_NOT) {
13992
+ objPtr = JimExprIntValOrVar(interp, expr->expr->left);
1413813993
1413913994
if (objPtr && JimIsWide(objPtr)) {
14140
- *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
14141
- Jim_IncrRefCount(*exprResultPtrPtr);
13995
+ Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj);
1414213996
return JIM_OK;
1414313997
}
1414413998
}
1414513999
break;
1414614000
1414714001
case 3:
14148
- objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
14002
+ objPtr = JimExprIntValOrVar(interp, expr->expr->left);
1414914003
if (objPtr && JimIsWide(objPtr)) {
14150
- Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
14004
+ Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right);
1415114005
if (objPtr2 && JimIsWide(objPtr2)) {
1415214006
jim_wide wideValueA = JimWideValue(objPtr);
1415314007
jim_wide wideValueB = JimWideValue(objPtr2);
1415414008
int cmpRes;
14155
- switch (expr->token[2].type) {
14009
+ switch (expr->expr->type) {
1415614010
case JIM_EXPROP_LT:
1415714011
cmpRes = wideValueA < wideValueB;
1415814012
break;
1415914013
case JIM_EXPROP_LTE:
1416014014
cmpRes = wideValueA <= wideValueB;
@@ -14172,12 +14026,11 @@
1417214026
cmpRes = wideValueA != wideValueB;
1417314027
break;
1417414028
default:
1417514029
goto noopt;
1417614030
}
14177
- *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
14178
- Jim_IncrRefCount(*exprResultPtrPtr);
14031
+ Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj);
1417914032
return JIM_OK;
1418014033
}
1418114034
}
1418214035
break;
1418314036
}
@@ -14185,145 +14038,64 @@
1418514038
noopt:
1418614039
#endif
1418714040
1418814041
expr->inUse++;
1418914042
14190
-
14191
-
14192
- if (expr->len > JIM_EE_STATICSTACK_LEN)
14193
- e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
14194
- else
14195
- e.stack = staticStack;
14196
-
14197
- e.stacklen = 0;
14198
-
14199
-
14200
- for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
14201
- Jim_Obj *objPtr;
14202
-
14203
- switch (expr->token[i].type) {
14204
- case JIM_TT_EXPR_INT:
14205
- case JIM_TT_EXPR_DOUBLE:
14206
- case JIM_TT_STR:
14207
- ExprPush(&e, expr->token[i].objPtr);
14208
- break;
14209
-
14210
- case JIM_TT_VAR:
14211
- objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG);
14212
- if (objPtr) {
14213
- ExprPush(&e, objPtr);
14214
- }
14215
- else {
14216
- retcode = JIM_ERR;
14217
- }
14218
- break;
14219
-
14220
- case JIM_TT_DICTSUGAR:
14221
- objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr);
14222
- if (objPtr) {
14223
- ExprPush(&e, objPtr);
14224
- }
14225
- else {
14226
- retcode = JIM_ERR;
14227
- }
14228
- break;
14229
-
14230
- case JIM_TT_ESC:
14231
- retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE);
14232
- if (retcode == JIM_OK) {
14233
- ExprPush(&e, objPtr);
14234
- }
14235
- break;
14236
-
14237
- case JIM_TT_CMD:
14238
- retcode = Jim_EvalObj(interp, expr->token[i].objPtr);
14239
- if (retcode == JIM_OK) {
14240
- ExprPush(&e, Jim_GetResult(interp));
14241
- }
14242
- break;
14243
-
14244
- default:{
14245
-
14246
- e.skip = 0;
14247
- e.opcode = expr->token[i].type;
14248
-
14249
- retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
14250
-
14251
- i += e.skip;
14252
- continue;
14253
- }
14254
- }
14255
- }
14043
+
14044
+ retcode = JimExprEvalTermNode(interp, expr->expr);
1425614045
1425714046
expr->inUse--;
1425814047
14259
- if (retcode == JIM_OK) {
14260
- *exprResultPtrPtr = ExprPop(&e);
14261
- }
14262
- else {
14263
- for (i = 0; i < e.stacklen; i++) {
14264
- Jim_DecrRefCount(interp, e.stack[i]);
14265
- }
14266
- }
14267
- if (e.stack != staticStack) {
14268
- Jim_Free(e.stack);
14269
- }
1427014048
return retcode;
1427114049
}
1427214050
1427314051
int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
1427414052
{
14275
- int retcode;
14276
- jim_wide wideValue;
14277
- double doubleValue;
14278
- Jim_Obj *exprResultPtr;
14279
-
14280
- retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
14281
- if (retcode != JIM_OK)
14282
- return retcode;
14283
-
14284
- if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
14285
- if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
14286
- Jim_DecrRefCount(interp, exprResultPtr);
14287
- return JIM_ERR;
14288
- }
14289
- else {
14290
- Jim_DecrRefCount(interp, exprResultPtr);
14291
- *boolPtr = doubleValue != 0;
14292
- return JIM_OK;
14293
- }
14294
- }
14295
- *boolPtr = wideValue != 0;
14296
-
14297
- Jim_DecrRefCount(interp, exprResultPtr);
14298
- return JIM_OK;
14053
+ int retcode = Jim_EvalExpression(interp, exprObjPtr);
14054
+
14055
+ if (retcode == JIM_OK) {
14056
+ switch (ExprBool(interp, Jim_GetResult(interp))) {
14057
+ case 0:
14058
+ *boolPtr = 0;
14059
+ break;
14060
+
14061
+ case 1:
14062
+ *boolPtr = 1;
14063
+ break;
14064
+
14065
+ case -1:
14066
+ retcode = JIM_ERR;
14067
+ break;
14068
+ }
14069
+ }
14070
+ return retcode;
1429914071
}
1430014072
1430114073
1430214074
1430314075
1430414076
typedef struct ScanFmtPartDescr
1430514077
{
14306
- char *arg;
14307
- char *prefix;
14308
- size_t width;
14309
- int pos;
14310
- char type;
14311
- char modifier;
14078
+ const char *arg;
14079
+ const char *prefix;
14080
+ size_t width;
14081
+ int pos;
14082
+ char type;
14083
+ char modifier;
1431214084
} ScanFmtPartDescr;
1431314085
1431414086
1431514087
typedef struct ScanFmtStringObj
1431614088
{
14317
- jim_wide size;
14318
- char *stringRep;
14319
- size_t count;
14320
- size_t convCount;
14321
- size_t maxPos;
14322
- const char *error;
14323
- char *scratch;
14324
- ScanFmtPartDescr descr[1];
14089
+ jim_wide size;
14090
+ char *stringRep;
14091
+ size_t count;
14092
+ size_t convCount;
14093
+ size_t maxPos;
14094
+ const char *error;
14095
+ char *scratch;
14096
+ ScanFmtPartDescr descr[1];
1432514097
} ScanFmtStringObj;
1432614098
1432714099
1432814100
static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
1432914101
static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14364,28 +14136,28 @@
1436414136
static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1436514137
{
1436614138
ScanFmtStringObj *fmtObj;
1436714139
char *buffer;
1436814140
int maxCount, i, approxSize, lastPos = -1;
14369
- const char *fmt = objPtr->bytes;
14370
- int maxFmtLen = objPtr->length;
14141
+ const char *fmt = Jim_String(objPtr);
14142
+ int maxFmtLen = Jim_Length(objPtr);
1437114143
const char *fmtEnd = fmt + maxFmtLen;
1437214144
int curr;
1437314145
1437414146
Jim_FreeIntRep(interp, objPtr);
14375
-
14147
+
1437614148
for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
1437714149
if (fmt[i] == '%')
1437814150
++maxCount;
14379
-
14380
- approxSize = sizeof(ScanFmtStringObj)
14381
- +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14382
- +maxFmtLen * sizeof(char) + 3 + 1
14383
- + maxFmtLen * sizeof(char) + 1
14384
- + maxFmtLen * sizeof(char)
14385
- +(maxCount + 1) * sizeof(char)
14386
- +1;
14151
+
14152
+ approxSize = sizeof(ScanFmtStringObj)
14153
+ +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14154
+ +maxFmtLen * sizeof(char) + 3 + 1
14155
+ + maxFmtLen * sizeof(char) + 1
14156
+ + maxFmtLen * sizeof(char)
14157
+ +(maxCount + 1) * sizeof(char)
14158
+ +1;
1438714159
fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
1438814160
memset(fmtObj, 0, approxSize);
1438914161
fmtObj->size = approxSize;
1439014162
fmtObj->maxPos = 0;
1439114163
fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14169,12 @@
1439714169
for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
1439814170
int width = 0, skip;
1439914171
ScanFmtPartDescr *descr = &fmtObj->descr[curr];
1440014172
1440114173
fmtObj->count++;
14402
- descr->width = 0;
14403
-
14174
+ descr->width = 0;
14175
+
1440414176
if (*fmt != '%' || fmt[1] == '%') {
1440514177
descr->type = 0;
1440614178
descr->prefix = &buffer[i];
1440714179
for (; fmt < fmtEnd; ++fmt) {
1440814180
if (*fmt == '%') {
@@ -14412,65 +14184,70 @@
1441214184
}
1441314185
buffer[i++] = *fmt;
1441414186
}
1441514187
buffer[i++] = 0;
1441614188
}
14417
-
14189
+
1441814190
++fmt;
14419
-
14191
+
1442014192
if (fmt >= fmtEnd)
1442114193
goto done;
14422
- descr->pos = 0;
14194
+ descr->pos = 0;
1442314195
if (*fmt == '*') {
14424
- descr->pos = -1;
14196
+ descr->pos = -1;
1442514197
++fmt;
1442614198
}
1442714199
else
14428
- fmtObj->convCount++;
14429
-
14200
+ fmtObj->convCount++;
14201
+
1443014202
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
1443114203
fmt += skip;
14432
-
14204
+
1443314205
if (descr->pos != -1 && *fmt == '$') {
1443414206
int prev;
1443514207
1443614208
++fmt;
1443714209
descr->pos = width;
1443814210
width = 0;
14439
-
14211
+
1444014212
if ((lastPos == 0 && descr->pos > 0)
1444114213
|| (lastPos > 0 && descr->pos == 0)) {
1444214214
fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
1444314215
return JIM_ERR;
1444414216
}
14445
-
14217
+
1444614218
for (prev = 0; prev < curr; ++prev) {
1444714219
if (fmtObj->descr[prev].pos == -1)
1444814220
continue;
1444914221
if (fmtObj->descr[prev].pos == descr->pos) {
1445014222
fmtObj->error =
1445114223
"variable is assigned by multiple \"%n$\" conversion specifiers";
1445214224
return JIM_ERR;
1445314225
}
1445414226
}
14455
-
14227
+ if (descr->pos < 0) {
14228
+ fmtObj->error =
14229
+ "\"%n$\" conversion specifier is negative";
14230
+ return JIM_ERR;
14231
+ }
14232
+
1445614233
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
1445714234
descr->width = width;
1445814235
fmt += skip;
1445914236
}
1446014237
if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
1446114238
fmtObj->maxPos = descr->pos;
1446214239
}
1446314240
else {
14464
-
14241
+
1446514242
descr->width = width;
1446614243
}
1446714244
}
14468
-
14245
+
1446914246
if (lastPos == -1)
1447014247
lastPos = descr->pos;
14471
-
14248
+
1447214249
if (*fmt == '[') {
1447314250
int swapped = 1, beg = i, end, j;
1447414251
1447514252
descr->type = '[';
1447614253
descr->arg = &buffer[i];
@@ -14485,11 +14262,11 @@
1448514262
fmtObj->error = "unmatched [ in format string";
1448614263
return JIM_ERR;
1448714264
}
1448814265
end = i;
1448914266
buffer[i++] = 0;
14490
-
14267
+
1449114268
while (swapped) {
1449214269
swapped = 0;
1449314270
for (j = beg + 1; j < end - 1; ++j) {
1449414271
if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
1449514272
char tmp = buffer[j - 1];
@@ -14500,13 +14277,18 @@
1450014277
}
1450114278
}
1450214279
}
1450314280
}
1450414281
else {
14505
-
14506
- if (strchr("hlL", *fmt) != 0)
14282
+
14283
+ if (fmt < fmtEnd && strchr("hlL", *fmt))
1450714284
descr->modifier = tolower((int)*fmt++);
14285
+
14286
+ if (fmt >= fmtEnd) {
14287
+ fmtObj->error = "missing scan conversion character";
14288
+ return JIM_ERR;
14289
+ }
1450814290
1450914291
descr->type = *fmt;
1451014292
if (strchr("efgcsndoxui", *fmt) == 0) {
1451114293
fmtObj->error = "bad scan conversion character";
1451214294
return JIM_ERR;
@@ -14543,11 +14325,11 @@
1454314325
while (*str) {
1454414326
int c;
1454514327
int n;
1454614328
1454714329
if (!sdescr && isspace(UCHAR(*str)))
14548
- break;
14330
+ break;
1454914331
1455014332
n = utf8_tounicode(str, &c);
1455114333
if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
1455214334
break;
1455314335
while (n--)
@@ -14566,89 +14348,89 @@
1456614348
size_t scanned = 0;
1456714349
size_t anchor = pos;
1456814350
int i;
1456914351
Jim_Obj *tmpObj = NULL;
1457014352
14571
-
14353
+
1457214354
*valObjPtr = 0;
1457314355
if (descr->prefix) {
1457414356
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14575
-
14357
+
1457614358
if (isspace(UCHAR(descr->prefix[i])))
1457714359
while (pos < strLen && isspace(UCHAR(str[pos])))
1457814360
++pos;
1457914361
else if (descr->prefix[i] != str[pos])
14580
- break;
14362
+ break;
1458114363
else
14582
- ++pos;
14364
+ ++pos;
1458314365
}
1458414366
if (pos >= strLen) {
14585
- return -1;
14367
+ return -1;
1458614368
}
1458714369
else if (descr->prefix[i] != 0)
14588
- return 0;
14370
+ return 0;
1458914371
}
14590
-
14372
+
1459114373
if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
1459214374
while (isspace(UCHAR(str[pos])))
1459314375
++pos;
14594
-
14376
+
1459514377
scanned = pos - anchor;
1459614378
14597
-
14379
+
1459814380
if (descr->type == 'n') {
14599
-
14381
+
1460014382
*valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
1460114383
}
1460214384
else if (pos >= strLen) {
14603
-
14385
+
1460414386
return -1;
1460514387
}
1460614388
else if (descr->type == 'c') {
1460714389
int c;
1460814390
scanned += utf8_tounicode(&str[pos], &c);
1460914391
*valObjPtr = Jim_NewIntObj(interp, c);
1461014392
return scanned;
1461114393
}
1461214394
else {
14613
-
14395
+
1461414396
if (descr->width > 0) {
1461514397
size_t sLen = utf8_strlen(&str[pos], strLen - pos);
1461614398
size_t tLen = descr->width > sLen ? sLen : descr->width;
1461714399
1461814400
tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
1461914401
tok = tmpObj->bytes;
1462014402
}
1462114403
else {
14622
-
14404
+
1462314405
tok = &str[pos];
1462414406
}
1462514407
switch (descr->type) {
1462614408
case 'd':
1462714409
case 'o':
1462814410
case 'x':
1462914411
case 'u':
1463014412
case 'i':{
14631
- char *endp;
14413
+ char *endp;
1463214414
jim_wide w;
1463314415
1463414416
int base = descr->type == 'o' ? 8
1463514417
: descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
1463614418
14637
-
14419
+
1463814420
if (base == 0) {
1463914421
w = jim_strtoull(tok, &endp);
1464014422
}
1464114423
else {
1464214424
w = strtoull(tok, &endp, base);
1464314425
}
1464414426
1464514427
if (endp != tok) {
14646
-
14428
+
1464714429
*valObjPtr = Jim_NewIntObj(interp, w);
1464814430
14649
-
14431
+
1465014432
scanned += endp - tok;
1465114433
}
1465214434
else {
1465314435
scanned = *tok ? 0 : -1;
1465414436
}
@@ -14665,13 +14447,13 @@
1466514447
case 'g':{
1466614448
char *endp;
1466714449
double value = strtod(tok, &endp);
1466814450
1466914451
if (endp != tok) {
14670
-
14452
+
1467114453
*valObjPtr = Jim_NewDoubleObj(interp, value);
14672
-
14454
+
1467314455
scanned += endp - tok;
1467414456
}
1467514457
else {
1467614458
scanned = *tok ? 0 : -1;
1467714459
}
@@ -14696,65 +14478,65 @@
1469614478
Jim_Obj **resultVec = 0;
1469714479
int resultc;
1469814480
Jim_Obj *emptyStr = 0;
1469914481
ScanFmtStringObj *fmtObj;
1470014482
14701
-
14483
+
1470214484
JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
1470314485
1470414486
fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14705
-
14487
+
1470614488
if (fmtObj->error != 0) {
1470714489
if (flags & JIM_ERRMSG)
1470814490
Jim_SetResultString(interp, fmtObj->error, -1);
1470914491
return 0;
1471014492
}
14711
-
14493
+
1471214494
emptyStr = Jim_NewEmptyStringObj(interp);
1471314495
Jim_IncrRefCount(emptyStr);
14714
-
14496
+
1471514497
resultList = Jim_NewListObj(interp, NULL, 0);
1471614498
if (fmtObj->maxPos > 0) {
1471714499
for (i = 0; i < fmtObj->maxPos; ++i)
1471814500
Jim_ListAppendElement(interp, resultList, emptyStr);
1471914501
JimListGetElements(interp, resultList, &resultc, &resultVec);
1472014502
}
14721
-
14503
+
1472214504
for (i = 0, pos = 0; i < fmtObj->count; ++i) {
1472314505
ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
1472414506
Jim_Obj *value = 0;
1472514507
14726
-
14508
+
1472714509
if (descr->type == 0)
1472814510
continue;
14729
-
14511
+
1473014512
if (scanned > 0)
1473114513
scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14732
-
14514
+
1473314515
if (scanned == -1 && i == 0)
1473414516
goto eof;
14735
-
14517
+
1473614518
pos += scanned;
1473714519
14738
-
14520
+
1473914521
if (value == 0)
1474014522
value = Jim_NewEmptyStringObj(interp);
14741
-
14523
+
1474214524
if (descr->pos == -1) {
1474314525
Jim_FreeNewObj(interp, value);
1474414526
}
1474514527
else if (descr->pos == 0)
14746
-
14528
+
1474714529
Jim_ListAppendElement(interp, resultList, value);
1474814530
else if (resultVec[descr->pos - 1] == emptyStr) {
14749
-
14531
+
1475014532
Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
1475114533
Jim_IncrRefCount(value);
1475214534
resultVec[descr->pos - 1] = value;
1475314535
}
1475414536
else {
14755
-
14537
+
1475614538
Jim_FreeNewObj(interp, value);
1475714539
goto err;
1475814540
}
1475914541
}
1476014542
Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14574,15 @@
1479214574
{
1479314575
Jim_PrngState *prng;
1479414576
unsigned char *destByte = (unsigned char *)dest;
1479514577
unsigned int si, sj, x;
1479614578
14797
-
14579
+
1479814580
if (interp->prngState == NULL)
1479914581
JimPrngInit(interp);
1480014582
prng = interp->prngState;
14801
-
14583
+
1480214584
for (x = 0; x < len; x++) {
1480314585
prng->i = (prng->i + 1) & 0xff;
1480414586
si = prng->sbox[prng->i];
1480514587
prng->j = (prng->j + si) & 0xff;
1480614588
sj = prng->sbox[prng->j];
@@ -14814,19 +14596,19 @@
1481414596
static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
1481514597
{
1481614598
int i;
1481714599
Jim_PrngState *prng;
1481814600
14819
-
14601
+
1482014602
if (interp->prngState == NULL)
1482114603
JimPrngInit(interp);
1482214604
prng = interp->prngState;
1482314605
14824
-
14606
+
1482514607
for (i = 0; i < 256; i++)
1482614608
prng->sbox[i] = i;
14827
-
14609
+
1482814610
for (i = 0; i < seedLen; i++) {
1482914611
unsigned char t;
1483014612
1483114613
t = prng->sbox[i & 0xFF];
1483214614
prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14635,11 @@
1485314635
if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
1485414636
return JIM_ERR;
1485514637
}
1485614638
intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1485714639
if (!intObjPtr) {
14858
-
14640
+
1485914641
wideValue = 0;
1486014642
}
1486114643
else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
1486214644
return JIM_ERR;
1486314645
}
@@ -14867,26 +14649,26 @@
1486714649
Jim_FreeNewObj(interp, intObjPtr);
1486814650
return JIM_ERR;
1486914651
}
1487014652
}
1487114653
else {
14872
-
14654
+
1487314655
Jim_InvalidateStringRep(intObjPtr);
1487414656
JimWideValue(intObjPtr) = wideValue + increment;
1487514657
1487614658
if (argv[1]->typePtr != &variableObjType) {
14877
-
14659
+
1487814660
Jim_SetVariable(interp, argv[1], intObjPtr);
1487914661
}
1488014662
}
1488114663
Jim_SetResult(interp, intObjPtr);
1488214664
return JIM_OK;
1488314665
}
1488414666
1488514667
14886
-#define JIM_EVAL_SARGV_LEN 8
14887
-#define JIM_EVAL_SINTV_LEN 8
14668
+#define JIM_EVAL_SARGV_LEN 8
14669
+#define JIM_EVAL_SINTV_LEN 8
1488814670
1488914671
1489014672
static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1489114673
{
1489214674
int retcode;
@@ -14894,16 +14676,16 @@
1489414676
if (interp->unknown_called > 50) {
1489514677
return JIM_ERR;
1489614678
}
1489714679
1489814680
14899
-
14681
+
1490014682
if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
1490114683
return JIM_ERR;
1490214684
1490314685
interp->unknown_called++;
14904
-
14686
+
1490514687
retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
1490614688
interp->unknown_called--;
1490714689
1490814690
return retcode;
1490914691
}
@@ -14910,10 +14692,11 @@
1491014692
1491114693
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1491214694
{
1491314695
int retcode;
1491414696
Jim_Cmd *cmdPtr;
14697
+ void *prevPrivData;
1491514698
1491614699
#if 0
1491714700
printf("invoke");
1491814701
int j;
1491914702
for (j = 0; j < objc; j++) {
@@ -14921,11 +14704,11 @@
1492114704
}
1492214705
printf("\n");
1492314706
#endif
1492414707
1492514708
if (interp->framePtr->tailcallCmd) {
14926
-
14709
+
1492714710
cmdPtr = interp->framePtr->tailcallCmd;
1492814711
interp->framePtr->tailcallCmd = NULL;
1492914712
}
1493014713
else {
1493114714
cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14939,20 +14722,22 @@
1493914722
Jim_SetResultString(interp, "Infinite eval recursion", -1);
1494014723
retcode = JIM_ERR;
1494114724
goto out;
1494214725
}
1494314726
interp->evalDepth++;
14727
+ prevPrivData = interp->cmdPrivData;
1494414728
14945
-
14729
+
1494614730
Jim_SetEmptyResult(interp);
1494714731
if (cmdPtr->isproc) {
1494814732
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
1494914733
}
1495014734
else {
1495114735
interp->cmdPrivData = cmdPtr->u.native.privData;
1495214736
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
1495314737
}
14738
+ interp->cmdPrivData = prevPrivData;
1495414739
interp->evalDepth--;
1495514740
1495614741
out:
1495714742
JimDecrCmdRefCount(interp, cmdPtr);
1495814743
@@ -14961,17 +14746,17 @@
1496114746
1496214747
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1496314748
{
1496414749
int i, retcode;
1496514750
14966
-
14751
+
1496714752
for (i = 0; i < objc; i++)
1496814753
Jim_IncrRefCount(objv[i]);
1496914754
1497014755
retcode = JimInvokeCommand(interp, objc, objv);
1497114756
14972
-
14757
+
1497314758
for (i = 0; i < objc; i++)
1497414759
Jim_DecrRefCount(interp, objv[i]);
1497514760
1497614761
return retcode;
1497714762
}
@@ -14989,25 +14774,25 @@
1498914774
}
1499014775
1499114776
static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
1499214777
{
1499314778
if (!interp->errorFlag) {
14994
-
14779
+
1499514780
interp->errorFlag = 1;
1499614781
Jim_IncrRefCount(script->fileNameObj);
1499714782
Jim_DecrRefCount(interp, interp->errorFileNameObj);
1499814783
interp->errorFileNameObj = script->fileNameObj;
1499914784
interp->errorLine = script->linenr;
1500014785
1500114786
JimResetStackTrace(interp);
15002
-
14787
+
1500314788
interp->addStackTrace++;
1500414789
}
1500514790
15006
-
14791
+
1500714792
if (interp->addStackTrace > 0) {
15008
-
14793
+
1500914794
1501014795
JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
1501114796
1501214797
if (Jim_Length(script->fileNameObj)) {
1501314798
interp->addStackTrace = 0;
@@ -15042,14 +14827,14 @@
1504214827
case JIM_OK:
1504314828
case JIM_RETURN:
1504414829
objPtr = interp->result;
1504514830
break;
1504614831
case JIM_BREAK:
15047
-
14832
+
1504814833
return JIM_BREAK;
1504914834
case JIM_CONTINUE:
15050
-
14835
+
1505114836
return JIM_CONTINUE;
1505214837
default:
1505314838
return JIM_ERR;
1505414839
}
1505514840
break;
@@ -15084,23 +14869,23 @@
1508414869
case JIM_OK:
1508514870
case JIM_RETURN:
1508614871
break;
1508714872
case JIM_BREAK:
1508814873
if (flags & JIM_SUBST_FLAG) {
15089
-
14874
+
1509014875
tokens = i;
1509114876
continue;
1509214877
}
15093
-
15094
-
14878
+
14879
+
1509514880
case JIM_CONTINUE:
1509614881
if (flags & JIM_SUBST_FLAG) {
1509714882
intv[i] = NULL;
1509814883
continue;
1509914884
}
15100
-
15101
-
14885
+
14886
+
1510214887
default:
1510314888
while (i--) {
1510414889
Jim_DecrRefCount(interp, intv[i]);
1510514890
}
1510614891
if (intv != sintv) {
@@ -15111,28 +14896,29 @@
1511114896
Jim_IncrRefCount(intv[i]);
1511214897
Jim_String(intv[i]);
1511314898
totlen += intv[i]->length;
1511414899
}
1511514900
15116
-
14901
+
1511714902
if (tokens == 1 && intv[0] && intv == sintv) {
15118
- Jim_DecrRefCount(interp, intv[0]);
14903
+
14904
+ intv[0]->refCount--;
1511914905
return intv[0];
1512014906
}
1512114907
1512214908
objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
1512314909
1512414910
if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
1512514911
&& token[2].type == JIM_TT_VAR) {
15126
-
14912
+
1512714913
objPtr->typePtr = &interpolatedObjType;
1512814914
objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
1512914915
objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
1513014916
Jim_IncrRefCount(intv[2]);
1513114917
}
1513214918
else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
15133
-
14919
+
1513414920
JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
1513514921
}
1513614922
1513714923
1513814924
s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +14929,11 @@
1514314929
s += intv[i]->length;
1514414930
Jim_DecrRefCount(interp, intv[i]);
1514514931
}
1514614932
}
1514714933
objPtr->bytes[totlen] = '\0';
15148
-
14934
+
1514914935
if (intv != sintv) {
1515014936
Jim_Free(intv);
1515114937
}
1515214938
1515314939
return objPtr;
@@ -15187,11 +14973,11 @@
1518714973
1518814974
if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
1518914975
return JimEvalObjList(interp, scriptObjPtr);
1519014976
}
1519114977
15192
- Jim_IncrRefCount(scriptObjPtr);
14978
+ Jim_IncrRefCount(scriptObjPtr);
1519314979
script = JimGetScript(interp, scriptObjPtr);
1519414980
if (!JimScriptValid(interp, script)) {
1519514981
Jim_DecrRefCount(interp, scriptObjPtr);
1519614982
return JIM_ERR;
1519714983
}
@@ -15223,11 +15009,11 @@
1522315009
}
1522415010
#endif
1522515011
1522615012
script->inUse++;
1522715013
15228
-
15014
+
1522915015
prevScriptObj = interp->currentScriptObj;
1523015016
interp->currentScriptObj = scriptObjPtr;
1523115017
1523215018
interp->errorFlag = 0;
1523315019
argv = sargv;
@@ -15234,19 +15020,19 @@
1523415020
1523515021
for (i = 0; i < script->len && retcode == JIM_OK; ) {
1523615022
int argc;
1523715023
int j;
1523815024
15239
-
15025
+
1524015026
argc = token[i].objPtr->internalRep.scriptLineValue.argc;
1524115027
script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
1524215028
15243
-
15029
+
1524415030
if (argc > JIM_EVAL_SARGV_LEN)
1524515031
argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
1524615032
15247
-
15033
+
1524815034
i++;
1524915035
1525015036
for (j = 0; j < argc; j++) {
1525115037
long wordtokens = 1;
1525215038
int expand = 0;
@@ -15302,11 +15088,11 @@
1530215088
1530315089
if (!expand) {
1530415090
argv[j] = wordObjPtr;
1530515091
}
1530615092
else {
15307
-
15093
+
1530815094
int len = Jim_ListLength(interp, wordObjPtr);
1530915095
int newargc = argc + len - 1;
1531015096
int k;
1531115097
1531215098
if (len > 1) {
@@ -15315,39 +15101,39 @@
1531515101
argv = Jim_Alloc(sizeof(*argv) * newargc);
1531615102
memcpy(argv, sargv, sizeof(*argv) * j);
1531715103
}
1531815104
}
1531915105
else {
15320
-
15106
+
1532115107
argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
1532215108
}
1532315109
}
1532415110
15325
-
15111
+
1532615112
for (k = 0; k < len; k++) {
1532715113
argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
1532815114
Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
1532915115
}
1533015116
1533115117
Jim_DecrRefCount(interp, wordObjPtr);
1533215118
15333
-
15119
+
1533415120
j--;
1533515121
argc += len - 1;
1533615122
}
1533715123
}
1533815124
1533915125
if (retcode == JIM_OK && argc) {
15340
-
15126
+
1534115127
retcode = JimInvokeCommand(interp, argc, argv);
15342
-
15128
+
1534315129
if (Jim_CheckSignal(interp)) {
1534415130
retcode = JIM_SIGNAL;
1534515131
}
1534615132
}
1534715133
15348
-
15134
+
1534915135
while (j-- > 0) {
1535015136
Jim_DecrRefCount(interp, argv[j]);
1535115137
}
1535215138
1535315139
if (argv != sargv) {
@@ -15354,21 +15140,21 @@
1535415140
Jim_Free(argv);
1535515141
argv = sargv;
1535615142
}
1535715143
}
1535815144
15359
-
15145
+
1536015146
if (retcode == JIM_ERR) {
1536115147
JimAddErrorToStack(interp, script);
1536215148
}
15363
-
15149
+
1536415150
else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15365
-
15151
+
1536615152
interp->addStackTrace = 0;
1536715153
}
1536815154
15369
-
15155
+
1537015156
interp->currentScriptObj = prevScriptObj;
1537115157
1537215158
Jim_FreeIntRep(interp, scriptObjPtr);
1537315159
scriptObjPtr->typePtr = &scriptObjType;
1537415160
Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15164,14 @@
1537815164
}
1537915165
1538015166
static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
1538115167
{
1538215168
int retcode;
15383
-
15169
+
1538415170
const char *varname = Jim_String(argNameObj);
1538515171
if (*varname == '&') {
15386
-
15172
+
1538715173
Jim_Obj *objPtr;
1538815174
Jim_CallFrame *savedCallFrame = interp->framePtr;
1538915175
1539015176
interp->framePtr = interp->framePtr->parent;
1539115177
objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15178,11 @@
1539215178
interp->framePtr = savedCallFrame;
1539315179
if (!objPtr) {
1539415180
return JIM_ERR;
1539515181
}
1539615182
15397
-
15183
+
1539815184
objPtr = Jim_NewStringObj(interp, varname + 1, -1);
1539915185
Jim_IncrRefCount(objPtr);
1540015186
retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
1540115187
Jim_DecrRefCount(interp, objPtr);
1540215188
}
@@ -15406,26 +15192,26 @@
1540615192
return retcode;
1540715193
}
1540815194
1540915195
static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
1541015196
{
15411
-
15197
+
1541215198
Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
1541315199
int i;
1541415200
1541515201
for (i = 0; i < cmd->u.proc.argListLen; i++) {
1541615202
Jim_AppendString(interp, argmsg, " ", 1);
1541715203
1541815204
if (i == cmd->u.proc.argsPos) {
1541915205
if (cmd->u.proc.arglist[i].defaultObjPtr) {
15420
-
15206
+
1542115207
Jim_AppendString(interp, argmsg, "?", 1);
1542215208
Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
1542315209
Jim_AppendString(interp, argmsg, " ...?", -1);
1542415210
}
1542515211
else {
15426
-
15212
+
1542715213
Jim_AppendString(interp, argmsg, "?arg...?", -1);
1542815214
}
1542915215
}
1543015216
else {
1543115217
if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15227,19 @@
1544115227
Jim_AppendString(interp, argmsg, arg, -1);
1544215228
}
1544315229
}
1544415230
}
1544515231
Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
15446
- Jim_FreeNewObj(interp, argmsg);
1544715232
}
1544815233
1544915234
#ifdef jim_ext_namespace
1545015235
int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
1545115236
{
1545215237
Jim_CallFrame *callFramePtr;
1545315238
int retcode;
1545415239
15455
-
15240
+
1545615241
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
1545715242
callFramePtr->argv = &interp->emptyObj;
1545815243
callFramePtr->argc = 0;
1545915244
callFramePtr->procArgsObjPtr = NULL;
1546015245
callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15247,21 @@
1546215247
callFramePtr->fileNameObj = interp->emptyObj;
1546315248
callFramePtr->line = 0;
1546415249
Jim_IncrRefCount(scriptObj);
1546515250
interp->framePtr = callFramePtr;
1546615251
15467
-
15252
+
1546815253
if (interp->framePtr->level == interp->maxCallFrameDepth) {
1546915254
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
1547015255
retcode = JIM_ERR;
1547115256
}
1547215257
else {
15473
-
15258
+
1547415259
retcode = Jim_EvalObj(interp, scriptObj);
1547515260
}
1547615261
15477
-
15262
+
1547815263
interp->framePtr = interp->framePtr->parent;
1547915264
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1548015265
1548115266
return retcode;
1548215267
}
@@ -15486,62 +15271,62 @@
1548615271
{
1548715272
Jim_CallFrame *callFramePtr;
1548815273
int i, d, retcode, optargs;
1548915274
ScriptObj *script;
1549015275
15491
-
15276
+
1549215277
if (argc - 1 < cmd->u.proc.reqArity ||
1549315278
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
1549415279
JimSetProcWrongArgs(interp, argv[0], cmd);
1549515280
return JIM_ERR;
1549615281
}
1549715282
1549815283
if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15499
-
15284
+
1550015285
return JIM_OK;
1550115286
}
1550215287
15503
-
15288
+
1550415289
if (interp->framePtr->level == interp->maxCallFrameDepth) {
1550515290
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
1550615291
return JIM_ERR;
1550715292
}
1550815293
15509
-
15294
+
1551015295
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
1551115296
callFramePtr->argv = argv;
1551215297
callFramePtr->argc = argc;
1551315298
callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
1551415299
callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
1551515300
callFramePtr->staticVars = cmd->u.proc.staticVars;
1551615301
15517
-
15302
+
1551815303
script = JimGetScript(interp, interp->currentScriptObj);
1551915304
callFramePtr->fileNameObj = script->fileNameObj;
1552015305
callFramePtr->line = script->linenr;
1552115306
1552215307
Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
1552315308
Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
1552415309
interp->framePtr = callFramePtr;
1552515310
15526
-
15311
+
1552715312
optargs = (argc - 1 - cmd->u.proc.reqArity);
1552815313
15529
-
15314
+
1553015315
i = 1;
1553115316
for (d = 0; d < cmd->u.proc.argListLen; d++) {
1553215317
Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
1553315318
if (d == cmd->u.proc.argsPos) {
15534
-
15319
+
1553515320
Jim_Obj *listObjPtr;
1553615321
int argsLen = 0;
1553715322
if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
1553815323
argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
1553915324
}
1554015325
listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
1554115326
15542
-
15327
+
1554315328
if (cmd->u.proc.arglist[d].defaultObjPtr) {
1554415329
nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
1554515330
}
1554615331
retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
1554715332
if (retcode != JIM_OK) {
@@ -15550,33 +15335,34 @@
1555015335
1555115336
i += argsLen;
1555215337
continue;
1555315338
}
1555415339
15555
-
15340
+
1555615341
if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
1555715342
retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
1555815343
}
1555915344
else {
15560
-
15345
+
1556115346
retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
1556215347
}
1556315348
if (retcode != JIM_OK) {
1556415349
goto badargset;
1556515350
}
1556615351
}
1556715352
15568
-
15353
+
1556915354
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
1557015355
1557115356
badargset:
1557215357
15573
-
15358
+
15359
+ retcode = JimInvokeDefer(interp, retcode);
1557415360
interp->framePtr = interp->framePtr->parent;
1557515361
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1557615362
15577
-
15363
+
1557815364
if (interp->framePtr->tailcallObj) {
1557915365
do {
1558015366
Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
1558115367
1558215368
interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15374,18 @@
1558815374
}
1558915375
}
1559015376
Jim_DecrRefCount(interp, tailcallObj);
1559115377
} while (interp->framePtr->tailcallObj);
1559215378
15593
-
15379
+
1559415380
if (interp->framePtr->tailcallCmd) {
1559515381
JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
1559615382
interp->framePtr->tailcallCmd = NULL;
1559715383
}
1559815384
}
1559915385
15600
-
15386
+
1560115387
if (retcode == JIM_RETURN) {
1560215388
if (--interp->returnLevel <= 0) {
1560315389
retcode = interp->returnCode;
1560415390
interp->returnCode = JIM_OK;
1560515391
interp->returnLevel = 0;
@@ -15711,20 +15497,20 @@
1571115497
prevScriptObj = interp->currentScriptObj;
1571215498
interp->currentScriptObj = scriptObjPtr;
1571315499
1571415500
retcode = Jim_EvalObj(interp, scriptObjPtr);
1571515501
15716
-
15502
+
1571715503
if (retcode == JIM_RETURN) {
1571815504
if (--interp->returnLevel <= 0) {
1571915505
retcode = interp->returnCode;
1572015506
interp->returnCode = JIM_OK;
1572115507
interp->returnLevel = 0;
1572215508
}
1572315509
}
1572415510
if (retcode == JIM_ERR) {
15725
-
15511
+
1572615512
interp->addStackTrace++;
1572715513
}
1572815514
1572915515
interp->currentScriptObj = prevScriptObj;
1573015516
@@ -15750,11 +15536,11 @@
1575015536
}
1575115537
if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
1575215538
if (JimParseVar(pc) == JIM_OK) {
1575315539
return;
1575415540
}
15755
-
15541
+
1575615542
pc->tstart = pc->p;
1575715543
flags |= JIM_SUBST_NOVAR;
1575815544
}
1575915545
while (pc->len) {
1576015546
if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15567,32 @@
1578115567
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
1578215568
struct JimParserCtx parser;
1578315569
struct ScriptObj *script = Jim_Alloc(sizeof(*script));
1578415570
ParseTokenList tokenlist;
1578515571
15786
-
15572
+
1578715573
ScriptTokenListInit(&tokenlist);
1578815574
1578915575
JimParserInit(&parser, scriptText, scriptTextLen, 1);
1579015576
while (1) {
1579115577
JimParseSubst(&parser, flags);
1579215578
if (parser.eof) {
15793
-
15579
+
1579415580
break;
1579515581
}
1579615582
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
1579715583
parser.tline);
1579815584
}
1579915585
15800
-
15586
+
1580115587
script->inUse = 1;
1580215588
script->substFlags = flags;
1580315589
script->fileNameObj = interp->emptyObj;
1580415590
Jim_IncrRefCount(script->fileNameObj);
1580515591
SubstObjAddTokens(interp, script, &tokenlist);
1580615592
15807
-
15593
+
1580815594
ScriptTokenListFree(&tokenlist);
1580915595
1581015596
#ifdef DEBUG_SHOW_SUBST
1581115597
{
1581215598
int i;
@@ -15817,11 +15603,11 @@
1581715603
Jim_String(script->token[i].objPtr));
1581815604
}
1581915605
}
1582015606
#endif
1582115607
15822
-
15608
+
1582315609
Jim_FreeIntRep(interp, objPtr);
1582415610
Jim_SetIntRepPtr(objPtr, script);
1582515611
objPtr->typePtr = &scriptObjType;
1582615612
return JIM_OK;
1582715613
}
@@ -15835,11 +15621,11 @@
1583515621
1583615622
int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
1583715623
{
1583815624
ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
1583915625
15840
- Jim_IncrRefCount(substObjPtr);
15626
+ Jim_IncrRefCount(substObjPtr);
1584115627
script->inUse++;
1584215628
1584315629
*resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
1584415630
1584515631
script->inUse--;
@@ -15851,22 +15637,24 @@
1585115637
}
1585215638
1585315639
void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
1585415640
{
1585515641
Jim_Obj *objPtr;
15856
- Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
15642
+ Jim_Obj *listObjPtr;
1585715643
15858
- if (*msg) {
15644
+ JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0"));
15645
+
15646
+ listObjPtr = Jim_NewListObj(interp, argv, argc);
15647
+
15648
+ if (msg && *msg) {
1585915649
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
1586015650
}
1586115651
Jim_IncrRefCount(listObjPtr);
1586215652
objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
1586315653
Jim_DecrRefCount(interp, listObjPtr);
1586415654
15865
- Jim_IncrRefCount(objPtr);
1586615655
Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
15867
- Jim_DecrRefCount(interp, objPtr);
1586815656
}
1586915657
1587015658
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
1587115659
Jim_HashEntry *he, int type);
1587215660
@@ -15876,11 +15664,11 @@
1587615664
JimHashtableIteratorCallbackType *callback, int type)
1587715665
{
1587815666
Jim_HashEntry *he;
1587915667
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
1588015668
15881
-
15669
+
1588215670
if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
1588315671
he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
1588415672
if (he) {
1588515673
callback(interp, listObjPtr, he, type);
1588615674
}
@@ -15907,11 +15695,11 @@
1590715695
{
1590815696
Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
1590915697
Jim_Obj *objPtr;
1591015698
1591115699
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15912
-
15700
+
1591315701
return;
1591415702
}
1591515703
1591615704
objPtr = Jim_NewStringObj(interp, he->key, -1);
1591715705
Jim_IncrRefCount(objPtr);
@@ -15967,11 +15755,11 @@
1596715755
1596815756
targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
1596915757
if (targetCallFrame == NULL) {
1597015758
return JIM_ERR;
1597115759
}
15972
-
15760
+
1597315761
if (targetCallFrame == interp->topFramePtr) {
1597415762
Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
1597515763
return JIM_ERR;
1597615764
}
1597715765
if (info_level_cmd) {
@@ -16095,12 +15883,17 @@
1609515883
doubleRes = (double)res;
1609615884
goto trydouble;
1609715885
}
1609815886
if (op == JIM_EXPROP_SUB)
1609915887
res -= wideValue;
16100
- else
15888
+ else {
15889
+ if (wideValue == 0) {
15890
+ Jim_SetResultString(interp, "Division by zero", -1);
15891
+ return JIM_ERR;
15892
+ }
1610115893
res /= wideValue;
15894
+ }
1610215895
}
1610315896
Jim_SetResultInt(interp, res);
1610415897
return JIM_OK;
1610515898
trydouble:
1610615899
for (; i < argc; i++) {
@@ -16154,11 +15947,11 @@
1615415947
if (!objPtr)
1615515948
return JIM_ERR;
1615615949
Jim_SetResult(interp, objPtr);
1615715950
return JIM_OK;
1615815951
}
16159
-
15952
+
1616015953
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1616115954
return JIM_ERR;
1616215955
Jim_SetResult(interp, argv[2]);
1616315956
return JIM_OK;
1616415957
}
@@ -16197,11 +15990,11 @@
1619715990
if (argc != 3) {
1619815991
Jim_WrongNumArgs(interp, 1, argv, "condition body");
1619915992
return JIM_ERR;
1620015993
}
1620115994
16202
-
15995
+
1620315996
while (1) {
1620415997
int boolean, retval;
1620515998
1620615999
if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
1620716000
return retval;
@@ -16237,11 +16030,11 @@
1623716030
if (argc != 5) {
1623816031
Jim_WrongNumArgs(interp, 1, argv, "start test next body");
1623916032
return JIM_ERR;
1624016033
}
1624116034
16242
-
16035
+
1624316036
if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
1624416037
return retval;
1624516038
}
1624616039
1624716040
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16248,78 +16041,84 @@
1624816041
1624916042
1625016043
#ifdef JIM_OPTIMIZATION
1625116044
if (retval == JIM_OK && boolean) {
1625216045
ScriptObj *incrScript;
16253
- ExprByteCode *expr;
16046
+ struct ExprTree *expr;
1625416047
jim_wide stop, currentVal;
1625516048
Jim_Obj *objPtr;
1625616049
int cmpOffset;
1625716050
16258
-
16051
+
1625916052
expr = JimGetExpression(interp, argv[2]);
1626016053
incrScript = JimGetScript(interp, argv[3]);
1626116054
16262
-
16055
+
1626316056
if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
1626416057
goto evalstart;
1626516058
}
16266
-
16267
- if (incrScript->token[1].type != JIM_TT_ESC ||
16268
- expr->token[0].type != JIM_TT_VAR ||
16269
- (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
16059
+
16060
+ if (incrScript->token[1].type != JIM_TT_ESC) {
1627016061
goto evalstart;
1627116062
}
1627216063
16273
- if (expr->token[2].type == JIM_EXPROP_LT) {
16064
+ if (expr->expr->type == JIM_EXPROP_LT) {
1627416065
cmpOffset = 0;
1627516066
}
16276
- else if (expr->token[2].type == JIM_EXPROP_LTE) {
16067
+ else if (expr->expr->type == JIM_EXPROP_LTE) {
1627716068
cmpOffset = 1;
1627816069
}
1627916070
else {
1628016071
goto evalstart;
1628116072
}
1628216073
16283
-
16074
+ if (expr->expr->left->type != JIM_TT_VAR) {
16075
+ goto evalstart;
16076
+ }
16077
+
16078
+ if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) {
16079
+ goto evalstart;
16080
+ }
16081
+
16082
+
1628416083
if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
1628516084
goto evalstart;
1628616085
}
1628716086
16288
-
16289
- if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
16087
+
16088
+ if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) {
1629016089
goto evalstart;
1629116090
}
1629216091
16293
-
16294
- if (expr->token[1].type == JIM_TT_EXPR_INT) {
16295
- if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
16092
+
16093
+ if (expr->expr->right->type == JIM_TT_EXPR_INT) {
16094
+ if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) {
1629616095
goto evalstart;
1629716096
}
1629816097
}
1629916098
else {
16300
- stopVarNamePtr = expr->token[1].objPtr;
16099
+ stopVarNamePtr = expr->expr->right->objPtr;
1630116100
Jim_IncrRefCount(stopVarNamePtr);
16302
-
16101
+
1630316102
stop = 0;
1630416103
}
1630516104
16306
-
16307
- varNamePtr = expr->token[0].objPtr;
16105
+
16106
+ varNamePtr = expr->expr->left->objPtr;
1630816107
Jim_IncrRefCount(varNamePtr);
1630916108
1631016109
objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
1631116110
if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
1631216111
goto testcond;
1631316112
}
1631416113
16315
-
16114
+
1631616115
while (retval == JIM_OK) {
16317
-
16318
-
1631916116
16320
-
16117
+
16118
+
16119
+
1632116120
if (stopVarNamePtr) {
1632216121
objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
1632316122
if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
1632416123
goto testcond;
1632516124
}
@@ -16327,18 +16126,18 @@
1632716126
1632816127
if (currentVal >= stop + cmpOffset) {
1632916128
break;
1633016129
}
1633116130
16332
-
16131
+
1633316132
retval = Jim_EvalObj(interp, argv[4]);
1633416133
if (retval == JIM_OK || retval == JIM_CONTINUE) {
1633516134
retval = JIM_OK;
1633616135
1633716136
objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
1633816137
16339
-
16138
+
1634016139
if (objPtr == NULL) {
1634116140
retval = JIM_ERR;
1634216141
goto out;
1634316142
}
1634416143
if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16157,25 @@
1635816157
}
1635916158
evalstart:
1636016159
#endif
1636116160
1636216161
while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16363
-
16162
+
1636416163
retval = Jim_EvalObj(interp, argv[4]);
1636516164
1636616165
if (retval == JIM_OK || retval == JIM_CONTINUE) {
16367
-
16368
- evalnext:
16166
+
16167
+JIM_IF_OPTIM(evalnext:)
1636916168
retval = Jim_EvalObj(interp, argv[3]);
1637016169
if (retval == JIM_OK || retval == JIM_CONTINUE) {
16371
-
16372
- testcond:
16170
+
16171
+JIM_IF_OPTIM(testcond:)
1637316172
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
1637416173
}
1637516174
}
1637616175
}
16377
- out:
16176
+JIM_IF_OPTIM(out:)
1637816177
if (stopVarNamePtr) {
1637916178
Jim_DecrRefCount(interp, stopVarNamePtr);
1638016179
}
1638116180
if (varNamePtr) {
1638216181
Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16217,11 @@
1641816217
if (retval == JIM_OK || retval == JIM_CONTINUE) {
1641916218
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
1642016219
1642116220
retval = JIM_OK;
1642216221
16423
-
16222
+
1642416223
i += incr;
1642516224
1642616225
if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
1642716226
if (argv[1]->typePtr != &variableObjType) {
1642816227
if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16282,21 @@
1648316282
1648416283
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
1648516284
{
1648616285
int result = JIM_OK;
1648716286
int i, numargs;
16488
- Jim_ListIter twoiters[2];
16287
+ Jim_ListIter twoiters[2];
1648916288
Jim_ListIter *iters;
1649016289
Jim_Obj *script;
1649116290
Jim_Obj *resultObj;
1649216291
1649316292
if (argc < 4 || argc % 2 != 0) {
1649416293
Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
1649516294
return JIM_ERR;
1649616295
}
16497
- script = argv[argc - 1];
16498
- numargs = (argc - 1 - 1);
16296
+ script = argv[argc - 1];
16297
+ numargs = (argc - 1 - 1);
1649916298
1650016299
if (numargs == 2) {
1650116300
iters = twoiters;
1650216301
}
1650316302
else {
@@ -16521,34 +16320,34 @@
1652116320
resultObj = interp->emptyObj;
1652216321
}
1652316322
Jim_IncrRefCount(resultObj);
1652416323
1652516324
while (1) {
16526
-
16325
+
1652716326
for (i = 0; i < numargs; i += 2) {
1652816327
if (!JimListIterDone(interp, &iters[i + 1])) {
1652916328
break;
1653016329
}
1653116330
}
1653216331
if (i == numargs) {
16533
-
16332
+
1653416333
break;
1653516334
}
1653616335
16537
-
16336
+
1653816337
for (i = 0; i < numargs; i += 2) {
1653916338
Jim_Obj *varName;
1654016339
16541
-
16340
+
1654216341
JimListIterInit(&iters[i], argv[i + 1]);
1654316342
while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
1654416343
Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
1654516344
if (!valObj) {
16546
-
16345
+
1654716346
valObj = interp->emptyObj;
1654816347
}
16549
-
16348
+
1655016349
Jim_IncrRefCount(valObj);
1655116350
result = Jim_SetVariable(interp, varName, valObj);
1655216351
Jim_DecrRefCount(interp, valObj);
1655316352
if (result != JIM_OK) {
1655416353
goto err;
@@ -16630,41 +16429,41 @@
1663016429
{
1663116430
int boolean, retval, current = 1, falsebody = 0;
1663216431
1663316432
if (argc >= 3) {
1663416433
while (1) {
16635
-
16434
+
1663616435
if (current >= argc)
1663716436
goto err;
1663816437
if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
1663916438
!= JIM_OK)
1664016439
return retval;
16641
-
16440
+
1664216441
if (current >= argc)
1664316442
goto err;
1664416443
if (Jim_CompareStringImmediate(interp, argv[current], "then"))
1664516444
current++;
16646
-
16445
+
1664716446
if (current >= argc)
1664816447
goto err;
1664916448
if (boolean)
1665016449
return Jim_EvalObj(interp, argv[current]);
16651
-
16450
+
1665216451
if (++current >= argc) {
1665316452
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
1665416453
return JIM_OK;
1665516454
}
1665616455
falsebody = current++;
1665716456
if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16658
-
16457
+
1665916458
if (current != argc - 1)
1666016459
goto err;
1666116460
return Jim_EvalObj(interp, argv[current]);
1666216461
}
1666316462
else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
1666416463
continue;
16665
-
16464
+
1666616465
else if (falsebody != argc - 1)
1666716466
goto err;
1666816467
return Jim_EvalObj(interp, argv[falsebody]);
1666916468
}
1667016469
return JIM_OK;
@@ -16698,19 +16497,17 @@
1669816497
}
1669916498
1670016499
return eq;
1670116500
}
1670216501
16703
-enum
16704
-{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
16705
-
1670616502
1670716503
static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1670816504
{
16505
+ enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
1670916506
int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
16710
- Jim_Obj *command = 0, *const *caseList = 0, *strObj;
16711
- Jim_Obj *script = 0;
16507
+ Jim_Obj *command = NULL, *scriptObj = NULL, *strObj;
16508
+ Jim_Obj **caseList;
1671216509
1671316510
if (argc < 3) {
1671416511
wrongnumargs:
1671516512
Jim_WrongNumArgs(interp, 1, argv, "?options? string "
1671616513
"pattern body ... ?default body? or " "{pattern body ?pattern body ...?}");
@@ -16747,68 +16544,62 @@
1674716544
goto wrongnumargs;
1674816545
}
1674916546
strObj = argv[opt++];
1675016547
patCount = argc - opt;
1675116548
if (patCount == 1) {
16752
- Jim_Obj **vector;
16753
-
16754
- JimListGetElements(interp, argv[opt], &patCount, &vector);
16755
- caseList = vector;
16549
+ JimListGetElements(interp, argv[opt], &patCount, &caseList);
1675616550
}
1675716551
else
16758
- caseList = &argv[opt];
16552
+ caseList = (Jim_Obj **)&argv[opt];
1675916553
if (patCount == 0 || patCount % 2 != 0)
1676016554
goto wrongnumargs;
16761
- for (i = 0; script == 0 && i < patCount; i += 2) {
16555
+ for (i = 0; scriptObj == NULL && i < patCount; i += 2) {
1676216556
Jim_Obj *patObj = caseList[i];
1676316557
1676416558
if (!Jim_CompareStringImmediate(interp, patObj, "default")
1676516559
|| i < (patCount - 2)) {
1676616560
switch (matchOpt) {
1676716561
case SWITCH_EXACT:
1676816562
if (Jim_StringEqObj(strObj, patObj))
16769
- script = caseList[i + 1];
16563
+ scriptObj = caseList[i + 1];
1677016564
break;
1677116565
case SWITCH_GLOB:
1677216566
if (Jim_StringMatchObj(interp, patObj, strObj, 0))
16773
- script = caseList[i + 1];
16567
+ scriptObj = caseList[i + 1];
1677416568
break;
1677516569
case SWITCH_RE:
1677616570
command = Jim_NewStringObj(interp, "regexp", -1);
16777
-
16571
+
1677816572
case SWITCH_CMD:{
1677916573
int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
1678016574
1678116575
if (argc - opt == 1) {
16782
- Jim_Obj **vector;
16783
-
16784
- JimListGetElements(interp, argv[opt], &patCount, &vector);
16785
- caseList = vector;
16576
+ JimListGetElements(interp, argv[opt], &patCount, &caseList);
1678616577
}
16787
-
16578
+
1678816579
if (rc < 0) {
1678916580
return -rc;
1679016581
}
1679116582
if (rc)
16792
- script = caseList[i + 1];
16583
+ scriptObj = caseList[i + 1];
1679316584
break;
1679416585
}
1679516586
}
1679616587
}
1679716588
else {
16798
- script = caseList[i + 1];
16589
+ scriptObj = caseList[i + 1];
1679916590
}
1680016591
}
16801
- for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2)
16802
- script = caseList[i + 1];
16803
- if (script && Jim_CompareStringImmediate(interp, script, "-")) {
16592
+ for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2)
16593
+ scriptObj = caseList[i + 1];
16594
+ if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) {
1680416595
Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]);
1680516596
return JIM_ERR;
1680616597
}
1680716598
Jim_SetEmptyResult(interp);
16808
- if (script) {
16809
- return Jim_EvalObj(interp, script);
16599
+ if (scriptObj) {
16600
+ return Jim_EvalObj(interp, scriptObj);
1681016601
}
1681116602
return JIM_OK;
1681216603
}
1681316604
1681416605
@@ -16920,11 +16711,11 @@
1692016711
case OPT_COMMAND:
1692116712
if (i >= argc - 2) {
1692216713
goto wrongargs;
1692316714
}
1692416715
commandObj = argv[++i];
16925
-
16716
+
1692616717
case OPT_EXACT:
1692716718
case OPT_GLOB:
1692816719
case OPT_REGEXP:
1692916720
opt_match = option;
1693016721
break;
@@ -16968,17 +16759,17 @@
1696816759
goto done;
1696916760
}
1697016761
break;
1697116762
}
1697216763
16973
-
16764
+
1697416765
if (!eq && opt_bool && opt_not && !opt_all) {
1697516766
continue;
1697616767
}
1697716768
1697816769
if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16979
-
16770
+
1698016771
Jim_Obj *resultObj;
1698116772
1698216773
if (opt_bool) {
1698316774
resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
1698416775
}
@@ -17001,11 +16792,11 @@
1700116792
1700216793
if (opt_all) {
1700316794
Jim_SetResult(interp, listObjPtr);
1700416795
}
1700516796
else {
17006
-
16797
+
1700716798
if (opt_bool) {
1700816799
Jim_SetResultBool(interp, opt_not);
1700916800
}
1701016801
else if (!opt_inline) {
1701116802
Jim_SetResultInt(interp, -1);
@@ -17030,11 +16821,11 @@
1703016821
Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
1703116822
return JIM_ERR;
1703216823
}
1703316824
listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1703416825
if (!listObjPtr) {
17035
-
16826
+
1703616827
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1703716828
new_obj = 1;
1703816829
}
1703916830
else if (Jim_IsShared(listObjPtr)) {
1704016831
listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +16894,31 @@
1710316894
first = JimRelToAbsIndex(len, first);
1710416895
last = JimRelToAbsIndex(len, last);
1710516896
JimRelToAbsRange(len, &first, &last, &rangeLen);
1710616897
1710716898
17108
-
16899
+
1710916900
if (first < len) {
17110
-
16901
+
1711116902
}
1711216903
else if (len == 0) {
17113
-
16904
+
1711416905
first = 0;
1711516906
}
1711616907
else {
1711716908
Jim_SetResultString(interp, "list doesn't contain element ", -1);
1711816909
Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
1711916910
return JIM_ERR;
1712016911
}
1712116912
17122
-
16913
+
1712316914
newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
1712416915
17125
-
16916
+
1712616917
ListInsertElements(newListObj, -1, argc - 4, argv + 4);
1712716918
17128
-
16919
+
1712916920
ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
1713016921
1713116922
Jim_SetResult(interp, newListObj);
1713216923
return JIM_OK;
1713316924
}
@@ -17138,11 +16929,11 @@
1713816929
if (argc < 3) {
1713916930
Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
1714016931
return JIM_ERR;
1714116932
}
1714216933
else if (argc == 3) {
17143
-
16934
+
1714416935
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1714516936
return JIM_ERR;
1714616937
Jim_SetResult(interp, argv[2]);
1714716938
return JIM_OK;
1714816939
}
@@ -17158,10 +16949,11 @@
1715816949
enum
1715916950
{ OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
1716016951
Jim_Obj *resObj;
1716116952
int i;
1716216953
int retCode;
16954
+ int shared;
1716316955
1716416956
struct lsort_info info;
1716516957
1716616958
if (argc < 2) {
1716716959
Jim_WrongNumArgs(interp, 1, argv, "?options? list");
@@ -17223,16 +17015,18 @@
1722317015
info.indexed = 1;
1722417016
i++;
1722517017
break;
1722617018
}
1722717019
}
17228
- resObj = Jim_DuplicateObj(interp, argv[argc - 1]);
17020
+ resObj = argv[argc - 1];
17021
+ if ((shared = Jim_IsShared(resObj)))
17022
+ resObj = Jim_DuplicateObj(interp, resObj);
1722917023
retCode = ListSortElements(interp, resObj, &info);
1723017024
if (retCode == JIM_OK) {
1723117025
Jim_SetResult(interp, resObj);
1723217026
}
17233
- else {
17027
+ else if (shared) {
1723417028
Jim_FreeNewObj(interp, resObj);
1723517029
}
1723617030
return retCode;
1723717031
}
1723817032
@@ -17253,11 +17047,11 @@
1725317047
}
1725417048
else {
1725517049
int new_obj = 0;
1725617050
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1725717051
if (!stringObjPtr) {
17258
-
17052
+
1725917053
stringObjPtr = Jim_NewEmptyStringObj(interp);
1726017054
new_obj = 1;
1726117055
}
1726217056
else if (Jim_IsShared(stringObjPtr)) {
1726317057
new_obj = 1;
@@ -17274,10 +17068,11 @@
1727417068
}
1727517069
}
1727617070
Jim_SetResult(interp, stringObjPtr);
1727717071
return JIM_OK;
1727817072
}
17073
+
1727917074
1728017075
1728117076
static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1728217077
{
1728317078
#if !defined(JIM_DEBUG_COMMAND)
@@ -17302,11 +17097,11 @@
1730217097
else {
1730317098
rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1730417099
}
1730517100
1730617101
if (rc == JIM_ERR) {
17307
-
17102
+
1730817103
interp->addStackTrace++;
1730917104
}
1731017105
return rc;
1731117106
}
1731217107
@@ -17316,14 +17111,14 @@
1731617111
if (argc >= 2) {
1731717112
int retcode;
1731817113
Jim_CallFrame *savedCallFrame, *targetCallFrame;
1731917114
const char *str;
1732017115
17321
-
17116
+
1732217117
savedCallFrame = interp->framePtr;
1732317118
17324
-
17119
+
1732517120
str = Jim_String(argv[1]);
1732617121
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
1732717122
targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1732817123
argc--;
1732917124
argv++;
@@ -17336,11 +17131,11 @@
1733617131
}
1733717132
if (argc < 2) {
1733817133
Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
1733917134
return JIM_ERR;
1734017135
}
17341
-
17136
+
1734217137
interp->framePtr = targetCallFrame;
1734317138
if (argc == 2) {
1734417139
retcode = Jim_EvalObj(interp, argv[1]);
1734517140
}
1734617141
else {
@@ -17356,32 +17151,29 @@
1735617151
}
1735717152
1735817153
1735917154
static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1736017155
{
17361
- Jim_Obj *exprResultPtr;
1736217156
int retcode;
1736317157
1736417158
if (argc == 2) {
17365
- retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr);
17159
+ retcode = Jim_EvalExpression(interp, argv[1]);
1736617160
}
1736717161
else if (argc > 2) {
1736817162
Jim_Obj *objPtr;
1736917163
1737017164
objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
1737117165
Jim_IncrRefCount(objPtr);
17372
- retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr);
17166
+ retcode = Jim_EvalExpression(interp, objPtr);
1737317167
Jim_DecrRefCount(interp, objPtr);
1737417168
}
1737517169
else {
1737617170
Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
1737717171
return JIM_ERR;
1737817172
}
1737917173
if (retcode != JIM_OK)
1738017174
return retcode;
17381
- Jim_SetResult(interp, exprResultPtr);
17382
- Jim_DecrRefCount(interp, exprResultPtr);
1738317175
return JIM_OK;
1738417176
}
1738517177
1738617178
1738717179
static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -17438,15 +17230,15 @@
1743817230
if (i != argc - 1 && i != argc) {
1743917231
Jim_WrongNumArgs(interp, 1, argv,
1744017232
"?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
1744117233
}
1744217234
17443
-
17235
+
1744417236
if (stackTraceObj && returnCode == JIM_ERR) {
1744517237
JimSetStackTrace(interp, stackTraceObj);
1744617238
}
17447
-
17239
+
1744817240
if (errorCodeObj && returnCode == JIM_ERR) {
1744917241
Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
1745017242
}
1745117243
interp->returnCode = returnCode;
1745217244
interp->returnLevel = level;
@@ -17463,31 +17255,31 @@
1746317255
if (interp->framePtr->level == 0) {
1746417256
Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
1746517257
return JIM_ERR;
1746617258
}
1746717259
else if (argc >= 2) {
17468
-
17260
+
1746917261
Jim_CallFrame *cf = interp->framePtr->parent;
1747017262
1747117263
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
1747217264
if (cmdPtr == NULL) {
1747317265
return JIM_ERR;
1747417266
}
1747517267
1747617268
JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
1747717269
17478
-
17270
+
1747917271
JimIncrCmdRefCount(cmdPtr);
1748017272
cf->tailcallCmd = cmdPtr;
1748117273
17482
-
17274
+
1748317275
JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
1748417276
1748517277
cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
1748617278
Jim_IncrRefCount(cf->tailcallObj);
1748717279
17488
-
17280
+
1748917281
return JIM_EVAL;
1749017282
}
1749117283
return JIM_OK;
1749217284
}
1749317285
@@ -17494,11 +17286,11 @@
1749417286
static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1749517287
{
1749617288
Jim_Obj *cmdList;
1749717289
Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
1749817290
17499
-
17291
+
1750017292
cmdList = Jim_DuplicateObj(interp, prefixListObj);
1750117293
Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
1750217294
1750317295
return JimEvalObjList(interp, cmdList);
1750417296
}
@@ -17552,22 +17344,22 @@
1755217344
else {
1755317345
cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
1755417346
}
1755517347
1755617348
if (cmd) {
17557
-
17349
+
1755817350
Jim_Obj *qualifiedCmdNameObj;
1755917351
const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
1756017352
1756117353
JimCreateCommand(interp, cmdname, cmd);
1756217354
17563
-
17355
+
1756417356
JimUpdateProcNamespace(interp, cmd, cmdname);
1756517357
1756617358
JimFreeQualifiedName(interp, qualifiedCmdNameObj);
1756717359
17568
-
17360
+
1756917361
Jim_SetResult(interp, argv[1]);
1757017362
return JIM_OK;
1757117363
}
1757217364
return JIM_ERR;
1757317365
}
@@ -17580,17 +17372,17 @@
1758017372
if (argc < 2) {
1758117373
Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
1758217374
return JIM_ERR;
1758317375
}
1758417376
17585
-
17377
+
1758617378
interp->local++;
1758717379
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
1758817380
interp->local--;
1758917381
1759017382
17591
-
17383
+
1759217384
if (retcode == 0) {
1759317385
Jim_Obj *cmdNameObj = Jim_GetResult(interp);
1759417386
1759517387
if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
1759617388
return JIM_ERR;
@@ -17619,18 +17411,18 @@
1761917411
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
1762017412
if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
1762117413
Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
1762217414
return JIM_ERR;
1762317415
}
17624
-
17416
+
1762517417
cmdPtr->u.proc.upcall++;
1762617418
JimIncrCmdRefCount(cmdPtr);
1762717419
17628
-
17420
+
1762917421
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
1763017422
17631
-
17423
+
1763217424
cmdPtr->u.proc.upcall--;
1763317425
JimDecrCmdRefCount(interp, cmdPtr);
1763417426
1763517427
return retcode;
1763617428
}
@@ -17657,11 +17449,11 @@
1765717449
return JIM_ERR;
1765817450
}
1765917451
1766017452
if (len == 3) {
1766117453
#ifdef jim_ext_namespace
17662
-
17454
+
1766317455
nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
1766417456
#else
1766517457
Jim_SetResultString(interp, "namespaces not enabled", -1);
1766617458
return JIM_ERR;
1766717459
#endif
@@ -17670,11 +17462,11 @@
1767017462
bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
1767117463
1767217464
cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
1767317465
1767417466
if (cmd) {
17675
-
17467
+
1767617468
nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
1767717469
nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
1767817470
Jim_IncrRefCount(nargv[0]);
1767917471
memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
1768017472
ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17492,11 @@
1770017492
static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1770117493
{
1770217494
int i;
1770317495
Jim_CallFrame *targetCallFrame;
1770417496
17705
-
17497
+
1770617498
if (argc > 3 && (argc % 2 == 0)) {
1770717499
targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1770817500
argc--;
1770917501
argv++;
1771017502
}
@@ -17713,17 +17505,17 @@
1771317505
}
1771417506
if (targetCallFrame == NULL) {
1771517507
return JIM_ERR;
1771617508
}
1771717509
17718
-
17510
+
1771917511
if (argc < 3) {
1772017512
Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
1772117513
return JIM_ERR;
1772217514
}
1772317515
17724
-
17516
+
1772517517
for (i = 1; i < argc; i += 2) {
1772617518
if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
1772717519
return JIM_ERR;
1772817520
}
1772917521
return JIM_OK;
@@ -17736,15 +17528,15 @@
1773617528
1773717529
if (argc < 2) {
1773817530
Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
1773917531
return JIM_ERR;
1774017532
}
17741
-
17533
+
1774217534
if (interp->framePtr->level == 0)
17743
- return JIM_OK;
17535
+ return JIM_OK;
1774417536
for (i = 1; i < argc; i++) {
17745
-
17537
+
1774617538
const char *name = Jim_String(argv[i]);
1774717539
if (name[0] != ':' || name[1] != ':') {
1774817540
if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
1774917541
return JIM_ERR;
1775017542
}
@@ -17767,21 +17559,21 @@
1776717559
}
1776817560
1776917561
str = Jim_String(objPtr);
1777017562
strLen = Jim_Utf8Length(interp, objPtr);
1777117563
17772
-
17564
+
1777317565
resultObjPtr = Jim_NewStringObj(interp, "", 0);
1777417566
while (strLen) {
1777517567
for (i = 0; i < numMaps; i += 2) {
17776
- Jim_Obj *objPtr;
17568
+ Jim_Obj *eachObjPtr;
1777717569
const char *k;
1777817570
int kl;
1777917571
17780
- objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17781
- k = Jim_String(objPtr);
17782
- kl = Jim_Utf8Length(interp, objPtr);
17572
+ eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17573
+ k = Jim_String(eachObjPtr);
17574
+ kl = Jim_Utf8Length(interp, eachObjPtr);
1778317575
1778417576
if (strLen >= kl && kl) {
1778517577
int rc;
1778617578
rc = JimStringCompareLen(str, k, kl, nocase);
1778717579
if (rc == 0) {
@@ -17794,11 +17586,11 @@
1779417586
strLen -= kl;
1779517587
break;
1779617588
}
1779717589
}
1779817590
}
17799
- if (i == numMaps) {
17591
+ if (i == numMaps) {
1780017592
int c;
1780117593
if (noMatchStart == NULL)
1780217594
noMatchStart = str;
1780317595
str += utf8_tounicode(str, &c);
1780417596
strLen--;
@@ -17838,11 +17630,11 @@
1783817630
Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
1783917631
return JIM_ERR;
1784017632
}
1784117633
if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
1784217634
JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17843
- return JIM_ERR;
17635
+ return Jim_CheckShowCommands(interp, argv[1], options);
1784417636
1784517637
switch (option) {
1784617638
case OPT_LENGTH:
1784717639
case OPT_BYTELENGTH:
1784817640
if (argc != 3) {
@@ -17859,11 +17651,11 @@
1785917651
return JIM_OK;
1786017652
1786117653
case OPT_CAT:{
1786217654
Jim_Obj *objPtr;
1786317655
if (argc == 3) {
17864
-
17656
+
1786517657
objPtr = argv[2];
1786617658
}
1786717659
else {
1786817660
int i;
1786917661
@@ -17878,11 +17670,11 @@
1787817670
}
1787917671
1788017672
case OPT_COMPARE:
1788117673
case OPT_EQUAL:
1788217674
{
17883
-
17675
+
1788417676
long opt_length = -1;
1788517677
int n = argc - 4;
1788617678
int i = 2;
1788717679
while (n > 0) {
1788817680
int subopt;
@@ -17891,16 +17683,16 @@
1789117683
badcompareargs:
1789217684
Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
1789317685
return JIM_ERR;
1789417686
}
1789517687
if (subopt == 0) {
17896
-
17688
+
1789717689
opt_case = 0;
1789817690
n--;
1789917691
}
1790017692
else {
17901
-
17693
+
1790217694
if (n < 2) {
1790317695
goto badcompareargs;
1790417696
}
1790517697
if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
1790617698
return JIM_ERR;
@@ -17911,11 +17703,11 @@
1791117703
if (n) {
1791217704
goto badcompareargs;
1791317705
}
1791417706
argv += argc - 2;
1791517707
if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17916
-
17708
+
1791717709
Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
1791817710
}
1791917711
else {
1792017712
if (opt_length >= 0) {
1792117713
n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17817,10 @@
1802517817
}
1802617818
1802717819
case OPT_REVERSE:{
1802817820
char *buf, *p;
1802917821
const char *str;
18030
- int len;
1803117822
int i;
1803217823
1803317824
if (argc != 3) {
1803417825
Jim_WrongNumArgs(interp, 2, argv, "string");
1803517826
return JIM_ERR;
@@ -18069,11 +17860,11 @@
1806917860
}
1807017861
if (idx < 0 || idx >= len || str == NULL) {
1807117862
Jim_SetResultString(interp, "", 0);
1807217863
}
1807317864
else if (len == Jim_Length(argv[2])) {
18074
-
17865
+
1807517866
Jim_SetResultString(interp, str + idx, 1);
1807617867
}
1807717868
else {
1807817869
int c;
1807917870
int i = utf8_index(str, idx);
@@ -18223,11 +18014,11 @@
1822318014
{
1822418015
int exitCode = 0;
1822518016
int i;
1822618017
int sig = 0;
1822718018
18228
-
18019
+
1822918020
jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
1823018021
static const int max_ignore_code = sizeof(ignore_mask) * 8;
1823118022
1823218023
Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
1823318024
@@ -18234,11 +18025,11 @@
1823418025
for (i = 1; i < argc - 1; i++) {
1823518026
const char *arg = Jim_String(argv[i]);
1823618027
jim_wide option;
1823718028
int ignore;
1823818029
18239
-
18030
+
1824018031
if (strcmp(arg, "--") == 0) {
1824118032
i++;
1824218033
break;
1824318034
}
1824418035
if (*arg != '-') {
@@ -18285,28 +18076,28 @@
1828518076
sig++;
1828618077
}
1828718078
1828818079
interp->signal_level += sig;
1828918080
if (Jim_CheckSignal(interp)) {
18290
-
18081
+
1829118082
exitCode = JIM_SIGNAL;
1829218083
}
1829318084
else {
1829418085
exitCode = Jim_EvalObj(interp, argv[0]);
18295
-
18086
+
1829618087
interp->errorFlag = 0;
1829718088
}
1829818089
interp->signal_level -= sig;
1829918090
18300
-
18091
+
1830118092
if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18302
-
18093
+
1830318094
return exitCode;
1830418095
}
1830518096
1830618097
if (sig && exitCode == JIM_SIGNAL) {
18307
-
18098
+
1830818099
if (interp->signal_set_result) {
1830918100
interp->signal_set_result(interp, interp->sigmask);
1831018101
}
1831118102
else {
1831218103
Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18136,10 @@
1834518136
}
1834618137
Jim_SetResultInt(interp, exitCode);
1834718138
return JIM_OK;
1834818139
}
1834918140
18350
-#ifdef JIM_REFERENCES
18351
-
18352
-
18353
-static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18354
-{
18355
- if (argc != 3 && argc != 4) {
18356
- Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?");
18357
- return JIM_ERR;
18358
- }
18359
- if (argc == 3) {
18360
- Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL));
18361
- }
18362
- else {
18363
- Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3]));
18364
- }
18365
- return JIM_OK;
18366
-}
18367
-
18368
-
18369
-static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18370
-{
18371
- Jim_Reference *refPtr;
18372
-
18373
- if (argc != 2) {
18374
- Jim_WrongNumArgs(interp, 1, argv, "reference");
18375
- return JIM_ERR;
18376
- }
18377
- if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18378
- return JIM_ERR;
18379
- Jim_SetResult(interp, refPtr->objPtr);
18380
- return JIM_OK;
18381
-}
18382
-
18383
-
18384
-static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18385
-{
18386
- Jim_Reference *refPtr;
18387
-
18388
- if (argc != 3) {
18389
- Jim_WrongNumArgs(interp, 1, argv, "reference newValue");
18390
- return JIM_ERR;
18391
- }
18392
- if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18393
- return JIM_ERR;
18394
- Jim_IncrRefCount(argv[2]);
18395
- Jim_DecrRefCount(interp, refPtr->objPtr);
18396
- refPtr->objPtr = argv[2];
18397
- Jim_SetResult(interp, argv[2]);
18398
- return JIM_OK;
18399
-}
18400
-
18401
-
18402
-static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18403
-{
18404
- if (argc != 1) {
18405
- Jim_WrongNumArgs(interp, 1, argv, "");
18406
- return JIM_ERR;
18407
- }
18408
- Jim_SetResultInt(interp, Jim_Collect(interp));
18409
-
18410
-
18411
- while (interp->freeList) {
18412
- Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
18413
- Jim_Free(interp->freeList);
18414
- interp->freeList = nextObjPtr;
18415
- }
18416
-
18417
- return JIM_OK;
18418
-}
18419
-
18420
-
18421
-static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18422
-{
18423
- if (argc != 2 && argc != 3) {
18424
- Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?");
18425
- return JIM_ERR;
18426
- }
18427
- if (argc == 2) {
18428
- Jim_Obj *cmdNamePtr;
18429
-
18430
- if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
18431
- return JIM_ERR;
18432
- if (cmdNamePtr != NULL)
18433
- Jim_SetResult(interp, cmdNamePtr);
18434
- }
18435
- else {
18436
- if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK)
18437
- return JIM_ERR;
18438
- Jim_SetResult(interp, argv[2]);
18439
- }
18440
- return JIM_OK;
18441
-}
18442
-
18443
-
18444
-static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18445
-{
18446
- Jim_Obj *listObjPtr;
18447
- Jim_HashTableIterator htiter;
18448
- Jim_HashEntry *he;
18449
-
18450
- listObjPtr = Jim_NewListObj(interp, NULL, 0);
18451
-
18452
- JimInitHashTableIterator(&interp->references, &htiter);
18453
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18454
- char buf[JIM_REFERENCE_SPACE + 1];
18455
- Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18456
- const unsigned long *refId = he->key;
18457
-
18458
- JimFormatReference(buf, refPtr, *refId);
18459
- Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18460
- }
18461
- Jim_SetResult(interp, listObjPtr);
18462
- return JIM_OK;
18463
-}
18464
-#endif
1846518141
1846618142
1846718143
static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1846818144
{
1846918145
if (argc != 3) {
@@ -18476,56 +18152,43 @@
1847618152
}
1847718153
1847818154
return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
1847918155
}
1848018156
18481
-#define JIM_DICTMATCH_VALUES 0x0001
18482
-
18483
-typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
18484
-
18485
-static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18486
-{
18487
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18488
- if (type & JIM_DICTMATCH_VALUES) {
18489
- Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18490
- }
18491
-}
18492
-
18493
-static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18494
- JimDictMatchCallbackType *callback, int type)
18495
-{
18496
- Jim_HashEntry *he;
18497
- Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18498
-
18499
-
18500
- Jim_HashTableIterator htiter;
18501
- JimInitHashTableIterator(ht, &htiter);
18502
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18503
- if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18504
- callback(interp, listObjPtr, he, type);
18505
- }
18506
- }
18507
-
18508
- return listObjPtr;
18509
-}
18510
-
18511
-
18512
-int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18513
-{
18514
- if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18515
- return JIM_ERR;
18516
- }
18517
- Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
18518
- return JIM_OK;
18519
-}
18520
-
18521
-int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18522
-{
18523
- if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18524
- return JIM_ERR;
18525
- }
18526
- Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
18157
+#define JIM_DICTMATCH_KEYS 0x0001
18158
+#define JIM_DICTMATCH_VALUES 0x002
18159
+
18160
+int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types)
18161
+{
18162
+ Jim_HashEntry *he;
18163
+ Jim_Obj *listObjPtr;
18164
+ Jim_HashTableIterator htiter;
18165
+
18166
+ if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18167
+ return JIM_ERR;
18168
+ }
18169
+
18170
+ listObjPtr = Jim_NewListObj(interp, NULL, 0);
18171
+
18172
+ JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter);
18173
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18174
+ if (patternObj) {
18175
+ Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
18176
+ if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
18177
+
18178
+ continue;
18179
+ }
18180
+ }
18181
+ if (return_types & JIM_DICTMATCH_KEYS) {
18182
+ Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18183
+ }
18184
+ if (return_types & JIM_DICTMATCH_VALUES) {
18185
+ Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18186
+ }
18187
+ }
18188
+
18189
+ Jim_SetResult(interp, listObjPtr);
1852718190
return JIM_OK;
1852818191
}
1852918192
1853018193
int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
1853118194
{
@@ -18532,38 +18195,85 @@
1853218195
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1853318196
return -1;
1853418197
}
1853518198
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
1853618199
}
18200
+
18201
+Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
18202
+{
18203
+ Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0);
18204
+ int i;
18205
+
18206
+ JimPanic((objc == 0, "Jim_DictMerge called with objc=0"));
18207
+
18208
+
18209
+
18210
+ for (i = 0; i < objc; i++) {
18211
+ Jim_HashTable *ht;
18212
+ Jim_HashTableIterator htiter;
18213
+ Jim_HashEntry *he;
18214
+
18215
+ if (SetDictFromAny(interp, objv[i]) != JIM_OK) {
18216
+ Jim_FreeNewObj(interp, objPtr);
18217
+ return NULL;
18218
+ }
18219
+ ht = objv[i]->internalRep.ptr;
18220
+ JimInitHashTableIterator(ht, &htiter);
18221
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18222
+ Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he));
18223
+ }
18224
+ }
18225
+ return objPtr;
18226
+}
1853718227
1853818228
int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
1853918229
{
1854018230
Jim_HashTable *ht;
1854118231
unsigned int i;
18232
+ char buffer[100];
18233
+ int sum = 0;
18234
+ int nonzero_count = 0;
18235
+ Jim_Obj *output;
18236
+ int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1854218237
1854318238
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1854418239
return JIM_ERR;
1854518240
}
1854618241
1854718242
ht = (Jim_HashTable *)objPtr->internalRep.ptr;
1854818243
18549
-
18550
- printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18244
+
18245
+ snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
18246
+ output = Jim_NewStringObj(interp, buffer, -1);
1855118247
1855218248
for (i = 0; i < ht->size; i++) {
1855318249
Jim_HashEntry *he = ht->table[i];
18554
-
18555
- if (he) {
18556
- printf("%d: ", i);
18557
-
18558
- while (he) {
18559
- printf(" %s", Jim_String(he->key));
18560
- he = he->next;
18561
- }
18562
- printf("\n");
18250
+ int entries = 0;
18251
+ while (he) {
18252
+ entries++;
18253
+ he = he->next;
18254
+ }
18255
+ if (entries > 9) {
18256
+ bucket_counts[10]++;
18257
+ }
18258
+ else {
18259
+ bucket_counts[entries]++;
18260
+ }
18261
+ if (entries) {
18262
+ sum += entries;
18263
+ nonzero_count++;
1856318264
}
1856418265
}
18266
+ for (i = 0; i < 10; i++) {
18267
+ snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
18268
+ Jim_AppendString(interp, output, buffer, -1);
18269
+ }
18270
+ snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
18271
+ Jim_AppendString(interp, output, buffer, -1);
18272
+ snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
18273
+ Jim_AppendString(interp, output, buffer, -1);
18274
+ Jim_SetResult(interp, output);
1856518275
return JIM_OK;
1856618276
}
1856718277
1856818278
static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
1856918279
{
@@ -18573,14 +18283,67 @@
1857318283
Jim_AppendString(interp, prefixObj, subcmd, -1);
1857418284
1857518285
return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
1857618286
}
1857718287
18288
+static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj)
18289
+{
18290
+ int i;
18291
+ Jim_Obj *objPtr;
18292
+ Jim_Obj *dictObj;
18293
+ Jim_Obj **dictValues;
18294
+ int len;
18295
+ int ret = JIM_OK;
18296
+
18297
+
18298
+ dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG);
18299
+ if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) {
18300
+ return JIM_ERR;
18301
+ }
18302
+
18303
+ if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) {
18304
+ return JIM_ERR;
18305
+ }
18306
+ for (i = 0; i < len; i += 2) {
18307
+ if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) {
18308
+ Jim_Free(dictValues);
18309
+ return JIM_ERR;
18310
+ }
18311
+ }
18312
+
18313
+
18314
+ if (Jim_Length(scriptObj)) {
18315
+ ret = Jim_EvalObj(interp, scriptObj);
18316
+
18317
+
18318
+ if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) {
18319
+
18320
+ Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1));
18321
+ for (i = 0; i < keyc; i++) {
18322
+ newkeyv[i] = keyv[i];
18323
+ }
18324
+
18325
+ for (i = 0; i < len; i += 2) {
18326
+
18327
+ objPtr = Jim_GetVariable(interp, dictValues[i], 0);
18328
+ newkeyv[keyc] = dictValues[i];
18329
+ Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0);
18330
+ }
18331
+ Jim_Free(newkeyv);
18332
+ }
18333
+ }
18334
+
18335
+ Jim_Free(dictValues);
18336
+
18337
+ return ret;
18338
+}
18339
+
1857818340
1857918341
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1858018342
{
1858118343
Jim_Obj *objPtr;
18344
+ int types = JIM_DICTMATCH_KEYS;
1858218345
int option;
1858318346
static const char * const options[] = {
1858418347
"create", "get", "set", "unset", "exists", "keys", "size", "info",
1858518348
"merge", "with", "append", "lappend", "incr", "remove", "values", "for",
1858618349
"replace", "update", NULL
@@ -18596,11 +18359,11 @@
1859618359
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
1859718360
return JIM_ERR;
1859818361
}
1859918362
1860018363
if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18601
- return JIM_ERR;
18364
+ return Jim_CheckShowCommands(interp, argv[1], options);
1860218365
}
1860318366
1860418367
switch (option) {
1860518368
case OPT_GET:
1860618369
if (argc < 3) {
@@ -18643,16 +18406,19 @@
1864318406
if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
1864418407
return JIM_ERR;
1864518408
}
1864618409
return JIM_OK;
1864718410
18411
+ case OPT_VALUES:
18412
+ types = JIM_DICTMATCH_VALUES;
18413
+
1864818414
case OPT_KEYS:
1864918415
if (argc != 3 && argc != 4) {
1865018416
Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
1865118417
return JIM_ERR;
1865218418
}
18653
- return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18419
+ return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types);
1865418420
1865518421
case OPT_SIZE:
1865618422
if (argc != 3) {
1865718423
Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1865818424
return JIM_ERR;
@@ -18665,19 +18431,20 @@
1866518431
1866618432
case OPT_MERGE:
1866718433
if (argc == 2) {
1866818434
return JIM_OK;
1866918435
}
18670
- if (Jim_DictSize(interp, argv[2]) < 0) {
18436
+ objPtr = Jim_DictMerge(interp, argc - 2, argv + 2);
18437
+ if (objPtr == NULL) {
1867118438
return JIM_ERR;
1867218439
}
18673
-
18674
- break;
18440
+ Jim_SetResult(interp, objPtr);
18441
+ return JIM_OK;
1867518442
1867618443
case OPT_UPDATE:
1867718444
if (argc < 6 || argc % 2) {
18678
-
18445
+
1867918446
argc = 2;
1868018447
}
1868118448
break;
1868218449
1868318450
case OPT_CREATE:
@@ -18693,12 +18460,19 @@
1869318460
if (argc != 3) {
1869418461
Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1869518462
return JIM_ERR;
1869618463
}
1869718464
return Jim_DictInfo(interp, argv[2]);
18465
+
18466
+ case OPT_WITH:
18467
+ if (argc < 4) {
18468
+ Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18469
+ return JIM_ERR;
18470
+ }
18471
+ return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]);
1869818472
}
18699
-
18473
+
1870018474
return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
1870118475
}
1870218476
1870318477
1870418478
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18538,11 @@
1876418538
1876518539
#ifdef jim_ext_namespace
1876618540
int nons = 0;
1876718541
1876818542
if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18769
-
18543
+
1877018544
argc--;
1877118545
argv++;
1877218546
nons = 1;
1877318547
}
1877418548
#endif
@@ -18775,16 +18549,15 @@
1877518549
1877618550
if (argc < 2) {
1877718551
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
1877818552
return JIM_ERR;
1877918553
}
18780
- if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV)
18781
- != JIM_OK) {
18782
- return JIM_ERR;
18554
+ if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
18555
+ return Jim_CheckShowCommands(interp, argv[1], commands);
1878318556
}
1878418557
18785
-
18558
+
1878618559
switch (cmd) {
1878718560
case INFO_EXISTS:
1878818561
if (argc != 3) {
1878918562
Jim_WrongNumArgs(interp, 2, argv, "varName");
1879018563
return JIM_ERR;
@@ -18809,21 +18582,21 @@
1880918582
Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
1881018583
return JIM_OK;
1881118584
}
1881218585
1881318586
case INFO_CHANNELS:
18814
- mode++;
18587
+ mode++;
1881518588
#ifndef jim_ext_aio
1881618589
Jim_SetResultString(interp, "aio not enabled", -1);
1881718590
return JIM_ERR;
1881818591
#endif
18819
-
18592
+
1882018593
case INFO_PROCS:
18821
- mode++;
18822
-
18594
+ mode++;
18595
+
1882318596
case INFO_COMMANDS:
18824
-
18597
+
1882518598
if (argc != 2 && argc != 3) {
1882618599
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
1882718600
return JIM_ERR;
1882818601
}
1882918602
#ifdef jim_ext_namespace
@@ -18835,17 +18608,17 @@
1883518608
#endif
1883618609
Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
1883718610
break;
1883818611
1883918612
case INFO_VARS:
18840
- mode++;
18841
-
18613
+ mode++;
18614
+
1884218615
case INFO_LOCALS:
18843
- mode++;
18844
-
18616
+ mode++;
18617
+
1884518618
case INFO_GLOBALS:
18846
-
18619
+
1884718620
if (argc != 2 && argc != 3) {
1884818621
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
1884918622
return JIM_ERR;
1885018623
}
1885118624
#ifdef jim_ext_namespace
@@ -18951,13 +18724,12 @@
1895118724
case INFO_ARGS:
1895218725
Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
1895318726
break;
1895418727
case INFO_STATICS:
1895518728
if (cmdPtr->u.proc.staticVars) {
18956
- int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
1895718729
Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18958
- NULL, JimVariablesMatch, mode));
18730
+ NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES));
1895918731
}
1896018732
break;
1896118733
}
1896218734
break;
1896318735
}
@@ -18985,15 +18757,15 @@
1898518757
}
1898618758
}
1898718759
break;
1898818760
1898918761
case INFO_HOSTNAME:
18990
-
18762
+
1899118763
return Jim_Eval(interp, "os.gethostname");
1899218764
1899318765
case INFO_NAMEOFEXECUTABLE:
18994
-
18766
+
1899518767
return Jim_Eval(interp, "{info nameofexecutable}");
1899618768
1899718769
case INFO_RETURNCODES:
1899818770
if (argc == 2) {
1899918771
int i;
@@ -19070,11 +18842,11 @@
1907018842
1907118843
if (option == OPT_VAR) {
1907218844
result = Jim_GetVariable(interp, objPtr, 0) != NULL;
1907318845
}
1907418846
else {
19075
-
18847
+
1907618848
Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
1907718849
1907818850
if (cmd) {
1907918851
switch (option) {
1908018852
case OPT_COMMAND:
@@ -19113,11 +18885,11 @@
1911318885
if (len == 0) {
1911418886
return JIM_OK;
1911518887
}
1911618888
strLen = Jim_Utf8Length(interp, argv[1]);
1911718889
19118
-
18890
+
1911918891
if (argc == 2) {
1912018892
splitChars = " \n\t\r";
1912118893
splitLen = 4;
1912218894
}
1912318895
else {
@@ -19126,11 +18898,11 @@
1912618898
}
1912718899
1912818900
noMatchStart = str;
1912918901
resObjPtr = Jim_NewListObj(interp, NULL, 0);
1913018902
19131
-
18903
+
1913218904
if (splitLen) {
1913318905
Jim_Obj *objPtr;
1913418906
while (strLen--) {
1913518907
const char *sc = splitChars;
1913618908
int scLen = splitLen;
@@ -19155,11 +18927,11 @@
1915518927
#define NUM_COMMON (128 - 9)
1915618928
while (strLen--) {
1915718929
int n = utf8_tounicode(str, &c);
1915818930
#ifdef JIM_OPTIMIZATION
1915918931
if (c >= 9 && c < 128) {
19160
-
18932
+
1916118933
c -= 9;
1916218934
if (!commonObj) {
1916318935
commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
1916418936
memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
1916518937
}
@@ -19189,11 +18961,11 @@
1918918961
1919018962
if (argc != 2 && argc != 3) {
1919118963
Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
1919218964
return JIM_ERR;
1919318965
}
19194
-
18966
+
1919518967
if (argc == 2) {
1919618968
joinStr = " ";
1919718969
joinStrLen = 1;
1919818970
}
1919918971
else {
@@ -19468,13 +19240,13 @@
1946819240
return -1;
1946919241
else if (step < 0 && end > start)
1947019242
return -1;
1947119243
len = end - start;
1947219244
if (len < 0)
19473
- len = -len;
19245
+ len = -len;
1947419246
if (step < 0)
19475
- step = -step;
19247
+ step = -step;
1947619248
len = 1 + ((len - 1) / step);
1947719249
if (len > INT_MAX)
1947819250
len = INT_MAX;
1947919251
return (int)((len < 0) ? -1 : len);
1948019252
}
@@ -19644,57 +19416,102 @@
1964419416
argv[1] = interp->result;
1964519417
1964619418
Jim_EvalObjVector(interp, 2, argv);
1964719419
}
1964819420
19649
-static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19650
- const char *prefix, const char *const *tablePtr, const char *name)
19421
+static char **JimSortStringTable(const char *const *tablePtr)
1965119422
{
1965219423
int count;
1965319424
char **tablePtrSorted;
19654
- int i;
19425
+
1965519426
1965619427
for (count = 0; tablePtr[count]; count++) {
1965719428
}
1965819429
19430
+
19431
+ tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1));
19432
+ memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19433
+ qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19434
+ tablePtrSorted[count] = NULL;
19435
+
19436
+ return tablePtrSorted;
19437
+}
19438
+
19439
+static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19440
+ const char *prefix, const char *const *tablePtr, const char *name)
19441
+{
19442
+ char **tablePtrSorted;
19443
+ int i;
19444
+
1965919445
if (name == NULL) {
1966019446
name = "option";
1966119447
}
1966219448
1966319449
Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19664
- tablePtrSorted = Jim_Alloc(sizeof(char *) * count);
19665
- memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19666
- qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19667
- for (i = 0; i < count; i++) {
19668
- if (i + 1 == count && count > 1) {
19450
+ tablePtrSorted = JimSortStringTable(tablePtr);
19451
+ for (i = 0; tablePtrSorted[i]; i++) {
19452
+ if (tablePtrSorted[i + 1] == NULL && i > 0) {
1966919453
Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
1967019454
}
1967119455
Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19672
- if (i + 1 != count) {
19456
+ if (tablePtrSorted[i + 1]) {
1967319457
Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
1967419458
}
1967519459
}
1967619460
Jim_Free(tablePtrSorted);
1967719461
}
1967819462
19463
+
19464
+int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr)
19465
+{
19466
+ if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) {
19467
+ int i;
19468
+ char **tablePtrSorted = JimSortStringTable(tablePtr);
19469
+ Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
19470
+ for (i = 0; tablePtrSorted[i]; i++) {
19471
+ Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1));
19472
+ }
19473
+ Jim_Free(tablePtrSorted);
19474
+ return JIM_OK;
19475
+ }
19476
+ return JIM_ERR;
19477
+}
19478
+
19479
+static const Jim_ObjType getEnumObjType = {
19480
+ "get-enum",
19481
+ NULL,
19482
+ NULL,
19483
+ NULL,
19484
+ JIM_TYPE_REFERENCES
19485
+};
19486
+
1967919487
int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
1968019488
const char *const *tablePtr, int *indexPtr, const char *name, int flags)
1968119489
{
1968219490
const char *bad = "bad ";
1968319491
const char *const *entryPtr = NULL;
1968419492
int i;
1968519493
int match = -1;
1968619494
int arglen;
19687
- const char *arg = Jim_GetString(objPtr, &arglen);
19495
+ const char *arg;
19496
+
19497
+ if (objPtr->typePtr == &getEnumObjType) {
19498
+ if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) {
19499
+ *indexPtr = objPtr->internalRep.ptrIntValue.int2;
19500
+ return JIM_OK;
19501
+ }
19502
+ }
19503
+
19504
+ arg = Jim_GetString(objPtr, &arglen);
1968819505
1968919506
*indexPtr = -1;
1969019507
1969119508
for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
1969219509
if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19693
-
19694
- *indexPtr = i;
19695
- return JIM_OK;
19510
+
19511
+ match = i;
19512
+ goto found;
1969619513
}
1969719514
if (flags & JIM_ENUM_ABBREV) {
1969819515
if (strncmp(arg, *entryPtr, arglen) == 0) {
1969919516
if (*arg == '-' && arglen == 1) {
1970019517
break;
@@ -19706,12 +19523,20 @@
1970619523
match = i;
1970719524
}
1970819525
}
1970919526
}
1971019527
19711
-
19528
+
1971219529
if (match >= 0) {
19530
+ found:
19531
+
19532
+ Jim_FreeIntRep(interp, objPtr);
19533
+ objPtr->typePtr = &getEnumObjType;
19534
+ objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr;
19535
+ objPtr->internalRep.ptrIntValue.int1 = flags;
19536
+ objPtr->internalRep.ptrIntValue.int2 = match;
19537
+
1971319538
*indexPtr = match;
1971419539
return JIM_OK;
1971519540
}
1971619541
1971719542
ambiguous:
@@ -19743,15 +19568,17 @@
1974319568
return objPtr->typePtr == &listObjType;
1974419569
}
1974519570
1974619571
void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
1974719572
{
19748
-
19573
+
1974919574
int len = strlen(format);
1975019575
int extra = 0;
1975119576
int n = 0;
1975219577
const char *params[5];
19578
+ int nobjparam = 0;
19579
+ Jim_Obj *objparam[5];
1975319580
char *buf;
1975419581
va_list args;
1975519582
int i;
1975619583
1975719584
va_start(args, format);
@@ -19766,10 +19593,12 @@
1976619593
}
1976719594
else if (strncmp(format + i, "%#s", 3) == 0) {
1976819595
Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
1976919596
1977019597
params[n] = Jim_GetString(objPtr, &l);
19598
+ objparam[nobjparam++] = objPtr;
19599
+ Jim_IncrRefCount(objPtr);
1977119600
}
1977219601
else {
1977319602
if (format[i] == '%') {
1977419603
i++;
1977519604
}
@@ -19784,10 +19613,14 @@
1978419613
len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
1978519614
1978619615
va_end(args);
1978719616
1978819617
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19618
+
19619
+ for (i = 0; i < nobjparam; i++) {
19620
+ Jim_DecrRefCount(interp, objparam[i]);
19621
+ }
1978919622
}
1979019623
1979119624
1979219625
#ifndef jim_ext_package
1979319626
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19641,11 @@
1980819641
#include <string.h>
1980919642
1981019643
1981119644
static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1981219645
{
19813
-
19646
+
1981419647
return JIM_OK;
1981519648
}
1981619649
1981719650
static const jim_subcmd_type dummy_subcmd = {
1981819651
"dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19831,22 +19664,18 @@
1983119664
}
1983219665
1983319666
static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
1983419667
Jim_Obj *cmd, Jim_Obj *subcmd)
1983519668
{
19836
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19837
- Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type,
19838
- " command \"", Jim_String(subcmd), "\": should be ", NULL);
19669
+ Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd);
1983919670
add_commands(interp, command_table, ", ");
1984019671
}
1984119672
1984219673
static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
1984319674
Jim_Obj *const *argv)
1984419675
{
19845
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19846
- Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]),
19847
- " command ... \", where command is one of: ", NULL);
19676
+ Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]);
1984819677
add_commands(interp, command_table, ", ");
1984919678
}
1985019679
1985119680
static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
1985219681
{
@@ -19863,67 +19692,78 @@
1986319692
{
1986419693
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
1986519694
add_cmd_usage(interp, command_table, subcmd);
1986619695
Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
1986719696
}
19697
+
19698
+static const Jim_ObjType subcmdLookupObjType = {
19699
+ "subcmd-lookup",
19700
+ NULL,
19701
+ NULL,
19702
+ NULL,
19703
+ JIM_TYPE_REFERENCES
19704
+};
1986819705
1986919706
const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
1987019707
int argc, Jim_Obj *const *argv)
1987119708
{
1987219709
const jim_subcmd_type *ct;
1987319710
const jim_subcmd_type *partial = 0;
1987419711
int cmdlen;
1987519712
Jim_Obj *cmd;
1987619713
const char *cmdstr;
19877
- const char *cmdname;
1987819714
int help = 0;
1987919715
19880
- cmdname = Jim_String(argv[0]);
19881
-
1988219716
if (argc < 2) {
19883
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19884
- Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
19885
- " command ...\"\n", NULL);
19886
- Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL);
19717
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n"
19718
+ "Use \"%#s -help ?command?\" for help", argv[0], argv[0]);
1988719719
return 0;
1988819720
}
1988919721
1989019722
cmd = argv[1];
1989119723
19892
-
19724
+
19725
+ if (cmd->typePtr == &subcmdLookupObjType) {
19726
+ if (cmd->internalRep.ptrIntValue.ptr == command_table) {
19727
+ ct = command_table + cmd->internalRep.ptrIntValue.int1;
19728
+ goto found;
19729
+ }
19730
+ }
19731
+
19732
+
1989319733
if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
1989419734
if (argc == 2) {
19895
-
19735
+
1989619736
show_cmd_usage(interp, command_table, argc, argv);
1989719737
return &dummy_subcmd;
1989819738
}
1989919739
help = 1;
1990019740
19901
-
19741
+
1990219742
cmd = argv[2];
1990319743
}
1990419744
19905
-
19745
+
1990619746
if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19907
-
19747
+
1990819748
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
1990919749
add_commands(interp, command_table, " ");
1991019750
return &dummy_subcmd;
1991119751
}
1991219752
1991319753
cmdstr = Jim_GetString(cmd, &cmdlen);
1991419754
1991519755
for (ct = command_table; ct->cmd; ct++) {
1991619756
if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19917
-
19757
+
1991819758
break;
1991919759
}
1992019760
if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
1992119761
if (partial) {
19922
-
19762
+
1992319763
if (help) {
19924
-
19764
+
1992519765
show_cmd_usage(interp, command_table, argc, argv);
1992619766
return &dummy_subcmd;
1992719767
}
1992819768
bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
1992919769
return 0;
@@ -19931,44 +19771,51 @@
1993119771
partial = ct;
1993219772
}
1993319773
continue;
1993419774
}
1993519775
19936
-
19776
+
1993719777
if (partial && !ct->cmd) {
1993819778
ct = partial;
1993919779
}
1994019780
1994119781
if (!ct->cmd) {
19942
-
19782
+
1994319783
if (help) {
19944
-
19784
+
1994519785
show_cmd_usage(interp, command_table, argc, argv);
1994619786
return &dummy_subcmd;
1994719787
}
1994819788
bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
1994919789
return 0;
1995019790
}
1995119791
1995219792
if (help) {
1995319793
Jim_SetResultString(interp, "Usage: ", -1);
19954
-
19794
+
1995519795
add_cmd_usage(interp, ct, argv[0]);
1995619796
return &dummy_subcmd;
1995719797
}
1995819798
19959
-
19799
+
19800
+ Jim_FreeIntRep(interp, cmd);
19801
+ cmd->typePtr = &subcmdLookupObjType;
19802
+ cmd->internalRep.ptrIntValue.ptr = (void *)command_table;
19803
+ cmd->internalRep.ptrIntValue.int1 = ct - command_table;
19804
+
19805
+found:
19806
+
1996019807
if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
1996119808
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19962
-
19809
+
1996319810
add_cmd_usage(interp, ct, argv[0]);
1996419811
Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
1996519812
1996619813
return 0;
1996719814
}
1996819815
19969
-
19816
+
1997019817
return ct;
1997119818
}
1997219819
1997319820
int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
1997419821
{
@@ -20019,11 +19866,11 @@
2001919866
*p++ = 0xe0 | ((uc & 0xf000) >> 12);
2002019867
*p++ = 0x80 | ((uc & 0xfc0) >> 6);
2002119868
*p = 0x80 | (uc & 0x3f);
2002219869
return 3;
2002319870
}
20024
-
19871
+
2002519872
else {
2002619873
*p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
2002719874
*p++ = 0x80 | ((uc & 0x3f000) >> 12);
2002819875
*p++ = 0x80 | ((uc & 0xfc0) >> 6);
2002919876
*p = 0x80 | (uc & 0x3f);
@@ -20146,11 +19993,12 @@
2014619993
continue;
2014719994
}
2014819995
*p++ = ch;
2014919996
format += step;
2015019997
step = utf8_tounicode(format, &ch);
20151
- } while (sawFlag);
19998
+
19999
+ } while (sawFlag && (p - spec <= 5));
2015220000
2015320001
2015420002
width = 0;
2015520003
if (isdigit(ch)) {
2015620004
width = strtoul(format, &end, 10);
@@ -20210,11 +20058,11 @@
2021020058
if (ch == 'h') {
2021120059
useShort = 1;
2021220060
format += step;
2021320061
step = utf8_tounicode(format, &ch);
2021420062
} else if (ch == 'l') {
20215
-
20063
+
2021620064
format += step;
2021720065
step = utf8_tounicode(format, &ch);
2021820066
if (ch == 'l') {
2021920067
format += step;
2022020068
step = utf8_tounicode(format, &ch);
@@ -20237,11 +20085,11 @@
2023720085
goto errorMsg;
2023820086
case 's': {
2023920087
formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
2024020088
formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
2024120089
if (gotPrecision && (precision < formatted_chars)) {
20242
-
20090
+
2024320091
formatted_chars = precision;
2024420092
formatted_bytes = utf8_index(formatted_buf, precision);
2024520093
}
2024620094
break;
2024720095
}
@@ -20249,11 +20097,11 @@
2024920097
jim_wide code;
2025020098
2025120099
if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
2025220100
goto error;
2025320101
}
20254
-
20102
+
2025520103
formatted_bytes = utf8_getchars(spec, code);
2025620104
formatted_buf = spec;
2025720105
formatted_chars = 1;
2025820106
break;
2025920107
}
@@ -20267,11 +20115,11 @@
2026720115
goto error;
2026820116
}
2026920117
length = sizeof(w) * 8;
2027020118
2027120119
20272
-
20120
+
2027320121
if (num_buffer_size < length + 1) {
2027420122
num_buffer_size = length + 1;
2027520123
num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
2027620124
}
2027720125
@@ -20295,29 +20143,29 @@
2029520143
case 'E':
2029620144
case 'f':
2029720145
case 'g':
2029820146
case 'G':
2029920147
doubleType = 1;
20300
-
20148
+
2030120149
case 'd':
2030220150
case 'u':
2030320151
case 'o':
2030420152
case 'x':
2030520153
case 'X': {
2030620154
jim_wide w;
2030720155
double d;
2030820156
int length;
2030920157
20310
-
20158
+
2031120159
if (width) {
2031220160
p += sprintf(p, "%ld", width);
2031320161
}
2031420162
if (gotPrecision) {
2031520163
p += sprintf(p, ".%ld", precision);
2031620164
}
2031720165
20318
-
20166
+
2031920167
if (doubleType) {
2032020168
if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
2032120169
goto error;
2032220170
}
2032320171
length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20192,26 @@
2034420192
}
2034520193
2034620194
*p++ = (char) ch;
2034720195
*p = '\0';
2034820196
20349
-
20197
+
20198
+ if (width > 10000 || length > 10000 || precision > 10000) {
20199
+ Jim_SetResultString(interp, "format too long", -1);
20200
+ goto error;
20201
+ }
20202
+
20203
+
20204
+
2035020205
if (width > length) {
2035120206
length = width;
2035220207
}
2035320208
if (gotPrecision) {
2035420209
length += precision;
2035520210
}
2035620211
20357
-
20212
+
2035820213
if (num_buffer_size < length + 1) {
2035920214
num_buffer_size = length + 1;
2036020215
num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
2036120216
}
2036220217
@@ -20370,11 +20225,11 @@
2037020225
formatted_buf = num_buffer;
2037120226
break;
2037220227
}
2037320228
2037420229
default: {
20375
-
20230
+
2037620231
spec[0] = ch;
2037720232
spec[1] = '\0';
2037820233
Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
2037920234
goto error;
2038020235
}
@@ -20422,37 +20277,37 @@
2042220277
2042320278
#define REG_MAX_PAREN 100
2042420279
2042520280
2042620281
20427
-#define END 0
20428
-#define BOL 1
20429
-#define EOL 2
20430
-#define ANY 3
20431
-#define ANYOF 4
20432
-#define ANYBUT 5
20433
-#define BRANCH 6
20434
-#define BACK 7
20435
-#define EXACTLY 8
20436
-#define NOTHING 9
20437
-#define REP 10
20438
-#define REPMIN 11
20439
-#define REPX 12
20440
-#define REPXMIN 13
20441
-#define BOLX 14
20442
-#define EOLX 15
20443
-#define WORDA 16
20444
-#define WORDZ 17
20445
-
20446
-#define OPENNC 1000
20447
-#define OPEN 1001
20448
-
20449
-
20450
-
20451
-
20452
-#define CLOSENC 2000
20453
-#define CLOSE 2001
20282
+#define END 0
20283
+#define BOL 1
20284
+#define EOL 2
20285
+#define ANY 3
20286
+#define ANYOF 4
20287
+#define ANYBUT 5
20288
+#define BRANCH 6
20289
+#define BACK 7
20290
+#define EXACTLY 8
20291
+#define NOTHING 9
20292
+#define REP 10
20293
+#define REPMIN 11
20294
+#define REPX 12
20295
+#define REPXMIN 13
20296
+#define BOLX 14
20297
+#define EOLX 15
20298
+#define WORDA 16
20299
+#define WORDZ 17
20300
+
20301
+#define OPENNC 1000
20302
+#define OPEN 1001
20303
+
20304
+
20305
+
20306
+
20307
+#define CLOSENC 2000
20308
+#define CLOSE 2001
2045420309
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
2045520310
2045620311
#define REG_MAGIC 0xFADED00D
2045720312
2045820313
@@ -20465,18 +20320,18 @@
2046520320
2046620321
#define FAIL(R,M) { (R)->err = (M); return (M); }
2046720322
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
2046820323
#define META "^$.[()|?{+*"
2046920324
20470
-#define HASWIDTH 1
20471
-#define SIMPLE 2
20472
-#define SPSTART 4
20473
-#define WORST 0
20325
+#define HASWIDTH 1
20326
+#define SIMPLE 2
20327
+#define SPSTART 4
20328
+#define WORST 0
2047420329
2047520330
#define MAX_REP_COUNT 1000000
2047620331
20477
-static int reg(regex_t *preg, int paren , int *flagp );
20332
+static int reg(regex_t *preg, int paren, int *flagp );
2047820333
static int regpiece(regex_t *preg, int *flagp );
2047920334
static int regbranch(regex_t *preg, int *flagp );
2048020335
static int regatom(regex_t *preg, int *flagp );
2048120336
static int regnode(regex_t *preg, int op );
2048220337
static int regnext(regex_t *preg, int p );
@@ -20520,15 +20375,15 @@
2052020375
memset(preg, 0, sizeof(*preg));
2052120376
2052220377
if (exp == NULL)
2052320378
FAIL(preg, REG_ERR_NULL_ARGUMENT);
2052420379
20525
-
20380
+
2052620381
preg->cflags = cflags;
2052720382
preg->regparse = exp;
2052820383
20529
-
20384
+
2053020385
preg->proglen = (strlen(exp) + 1) * 5;
2053120386
preg->program = malloc(preg->proglen * sizeof(int));
2053220387
if (preg->program == NULL)
2053320388
FAIL(preg, REG_ERR_NOMEM);
2053420389
@@ -20535,24 +20390,24 @@
2053520390
regc(preg, REG_MAGIC);
2053620391
if (reg(preg, 0, &flags) == 0) {
2053720392
return preg->err;
2053820393
}
2053920394
20540
-
20541
- if (preg->re_nsub >= REG_MAX_PAREN)
20395
+
20396
+ if (preg->re_nsub >= REG_MAX_PAREN)
2054220397
FAIL(preg,REG_ERR_TOO_BIG);
2054320398
20544
-
20545
- preg->regstart = 0;
20399
+
20400
+ preg->regstart = 0;
2054620401
preg->reganch = 0;
2054720402
preg->regmust = 0;
2054820403
preg->regmlen = 0;
20549
- scan = 1;
20550
- if (OP(preg, regnext(preg, scan)) == END) {
20404
+ scan = 1;
20405
+ if (OP(preg, regnext(preg, scan)) == END) {
2055120406
scan = OPERAND(scan);
2055220407
20553
-
20408
+
2055420409
if (OP(preg, scan) == EXACTLY) {
2055520410
preg->regstart = preg->program[OPERAND(scan)];
2055620411
}
2055720412
else if (OP(preg, scan) == BOL)
2055820413
preg->reganch++;
@@ -20579,24 +20434,24 @@
2057920434
#endif
2058020435
2058120436
return 0;
2058220437
}
2058320438
20584
-static int reg(regex_t *preg, int paren , int *flagp )
20439
+static int reg(regex_t *preg, int paren, int *flagp )
2058520440
{
2058620441
int ret;
2058720442
int br;
2058820443
int ender;
2058920444
int parno = 0;
2059020445
int flags;
2059120446
20592
- *flagp = HASWIDTH;
20447
+ *flagp = HASWIDTH;
2059320448
20594
-
20449
+
2059520450
if (paren) {
2059620451
if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20597
-
20452
+
2059820453
preg->regparse += 2;
2059920454
parno = -1;
2060020455
}
2060120456
else {
2060220457
parno = ++preg->re_nsub;
@@ -20603,16 +20458,16 @@
2060320458
}
2060420459
ret = regnode(preg, OPEN+parno);
2060520460
} else
2060620461
ret = 0;
2060720462
20608
-
20463
+
2060920464
br = regbranch(preg, &flags);
2061020465
if (br == 0)
2061120466
return 0;
2061220467
if (ret != 0)
20613
- regtail(preg, ret, br);
20468
+ regtail(preg, ret, br);
2061420469
else
2061520470
ret = br;
2061620471
if (!(flags&HASWIDTH))
2061720472
*flagp &= ~HASWIDTH;
2061820473
*flagp |= flags&SPSTART;
@@ -20619,25 +20474,25 @@
2061920474
while (*preg->regparse == '|') {
2062020475
preg->regparse++;
2062120476
br = regbranch(preg, &flags);
2062220477
if (br == 0)
2062320478
return 0;
20624
- regtail(preg, ret, br);
20479
+ regtail(preg, ret, br);
2062520480
if (!(flags&HASWIDTH))
2062620481
*flagp &= ~HASWIDTH;
2062720482
*flagp |= flags&SPSTART;
2062820483
}
2062920484
20630
-
20485
+
2063120486
ender = regnode(preg, (paren) ? CLOSE+parno : END);
2063220487
regtail(preg, ret, ender);
2063320488
20634
-
20489
+
2063520490
for (br = ret; br != 0; br = regnext(preg, br))
2063620491
regoptail(preg, br, ender);
2063720492
20638
-
20493
+
2063920494
if (paren && *preg->regparse++ != ')') {
2064020495
preg->err = REG_ERR_UNMATCHED_PAREN;
2064120496
return 0;
2064220497
} else if (!paren && *preg->regparse != '\0') {
2064320498
if (*preg->regparse == ')') {
@@ -20657,11 +20512,11 @@
2065720512
int ret;
2065820513
int chain;
2065920514
int latest;
2066020515
int flags;
2066120516
20662
- *flagp = WORST;
20517
+ *flagp = WORST;
2066320518
2066420519
ret = regnode(preg, BRANCH);
2066520520
chain = 0;
2066620521
while (*preg->regparse != '\0' && *preg->regparse != ')' &&
2066720522
*preg->regparse != '|') {
@@ -20675,11 +20530,11 @@
2067520530
else {
2067620531
regtail(preg, chain, latest);
2067720532
}
2067820533
chain = latest;
2067920534
}
20680
- if (chain == 0)
20535
+ if (chain == 0)
2068120536
(void) regnode(preg, NOTHING);
2068220537
2068320538
return(ret);
2068420539
}
2068520540
@@ -20705,11 +20560,11 @@
2070520560
if (!(flags&HASWIDTH) && op != '?') {
2070620561
preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
2070720562
return 0;
2070820563
}
2070920564
20710
-
20565
+
2071120566
if (op == '{') {
2071220567
char *end;
2071320568
2071420569
min = strtoul(preg->regparse + 1, &end, 10);
2071520570
if (end == preg->regparse + 1) {
@@ -20716,10 +20571,14 @@
2071620571
preg->err = REG_ERR_BAD_COUNT;
2071720572
return 0;
2071820573
}
2071920574
if (*end == '}') {
2072020575
max = min;
20576
+ }
20577
+ else if (*end == '\0') {
20578
+ preg->err = REG_ERR_UNMATCHED_BRACES;
20579
+ return 0;
2072120580
}
2072220581
else {
2072320582
preg->regparse = end;
2072420583
max = strtoul(preg->regparse + 1, &end, 10);
2072520584
if (*end != '}') {
@@ -20777,11 +20636,11 @@
2077720636
static void reg_addrange(regex_t *preg, int lower, int upper)
2077820637
{
2077920638
if (lower > upper) {
2078020639
reg_addrange(preg, upper, lower);
2078120640
}
20782
-
20641
+
2078320642
regc(preg, upper - lower + 1);
2078420643
regc(preg, lower);
2078520644
}
2078620645
2078720646
static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20704,17 @@
2084520704
case 'r': *ch = '\r'; break;
2084620705
case 't': *ch = '\t'; break;
2084720706
case 'v': *ch = '\v'; break;
2084820707
case 'u':
2084920708
if (*s == '{') {
20850
-
20709
+
2085120710
n = parse_hex(s + 1, 6, ch);
2085220711
if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
2085320712
s += n + 2;
2085420713
}
2085520714
else {
20856
-
20715
+
2085720716
*ch = 'u';
2085820717
}
2085920718
}
2086020719
else if ((n = parse_hex(s, 4, ch)) > 0) {
2086120720
s += n;
@@ -20886,15 +20745,15 @@
2088620745
int nocase = (preg->cflags & REG_ICASE);
2088720746
2088820747
int ch;
2088920748
int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
2089020749
20891
- *flagp = WORST;
20750
+ *flagp = WORST;
2089220751
2089320752
preg->regparse += n;
2089420753
switch (ch) {
20895
-
20754
+
2089620755
case '^':
2089720756
ret = regnode(preg, BOL);
2089820757
break;
2089920758
case '$':
2090020759
ret = regnode(preg, EOL);
@@ -20904,37 +20763,60 @@
2090420763
*flagp |= HASWIDTH|SIMPLE;
2090520764
break;
2090620765
case '[': {
2090720766
const char *pattern = preg->regparse;
2090820767
20909
- if (*pattern == '^') {
20768
+ if (*pattern == '^') {
2091020769
ret = regnode(preg, ANYBUT);
2091120770
pattern++;
2091220771
} else
2091320772
ret = regnode(preg, ANYOF);
2091420773
20915
-
20774
+
2091620775
if (*pattern == ']' || *pattern == '-') {
2091720776
reg_addrange(preg, *pattern, *pattern);
2091820777
pattern++;
2091920778
}
2092020779
2092120780
while (*pattern && *pattern != ']') {
20922
-
20781
+
2092320782
int start;
2092420783
int end;
2092520784
20785
+ enum {
20786
+ CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
20787
+ CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
20788
+ CC_NUM
20789
+ };
20790
+ int cc;
20791
+
2092620792
pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
2092720793
if (start == '\\') {
20794
+
20795
+ switch (*pattern) {
20796
+ case 's':
20797
+ pattern++;
20798
+ cc = CC_SPACE;
20799
+ goto cc_switch;
20800
+ case 'd':
20801
+ pattern++;
20802
+ cc = CC_DIGIT;
20803
+ goto cc_switch;
20804
+ case 'w':
20805
+ pattern++;
20806
+ reg_addrange(preg, '_', '_');
20807
+ cc = CC_ALNUM;
20808
+ goto cc_switch;
20809
+ }
2092820810
pattern += reg_decode_escape(pattern, &start);
2092920811
if (start == 0) {
2093020812
preg->err = REG_ERR_NULL_CHAR;
2093120813
return 0;
2093220814
}
2093320815
}
2093420816
if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20935
-
20817
+
2093620818
pattern += utf8_tounicode(pattern, &end);
2093720819
pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
2093820820
if (end == '\\') {
2093920821
pattern += reg_decode_escape(pattern, &end);
2094020822
if (end == 0) {
@@ -20949,30 +20831,25 @@
2094920831
if (start == '[' && pattern[0] == ':') {
2095020832
static const char *character_class[] = {
2095120833
":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:",
2095220834
":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:",
2095320835
};
20954
- enum {
20955
- CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
20956
- CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
20957
- CC_NUM
20958
- };
20959
- int i;
20960
-
20961
- for (i = 0; i < CC_NUM; i++) {
20962
- int n = strlen(character_class[i]);
20963
- if (strncmp(pattern, character_class[i], n) == 0) {
20964
-
20836
+
20837
+ for (cc = 0; cc < CC_NUM; cc++) {
20838
+ n = strlen(character_class[cc]);
20839
+ if (strncmp(pattern, character_class[cc], n) == 0) {
20840
+
2096520841
pattern += n + 1;
2096620842
break;
2096720843
}
2096820844
}
20969
- if (i != CC_NUM) {
20970
- switch (i) {
20845
+ if (cc != CC_NUM) {
20846
+cc_switch:
20847
+ switch (cc) {
2097120848
case CC_ALNUM:
2097220849
reg_addrange(preg, '0', '9');
20973
-
20850
+
2097420851
case CC_ALPHA:
2097520852
if ((preg->cflags & REG_ICASE) == 0) {
2097620853
reg_addrange(preg, 'a', 'z');
2097720854
}
2097820855
reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20867,11 @@
2099020867
reg_addrange(preg, 'a', 'z');
2099120868
break;
2099220869
case CC_XDIGIT:
2099320870
reg_addrange(preg, 'a', 'f');
2099420871
reg_addrange(preg, 'A', 'F');
20995
-
20872
+
2099620873
case CC_DIGIT:
2099720874
reg_addrange(preg, '0', '9');
2099820875
break;
2099920876
case CC_CNTRL:
2100020877
reg_addrange(preg, 0, 31);
@@ -21014,11 +20891,11 @@
2101420891
break;
2101520892
}
2101620893
continue;
2101720894
}
2101820895
}
21019
-
20896
+
2102020897
reg_addrange(preg, start, start);
2102120898
}
2102220899
regc(preg, '\0');
2102320900
2102420901
if (*pattern) {
@@ -21037,11 +20914,11 @@
2103720914
break;
2103820915
case '\0':
2103920916
case '|':
2104020917
case ')':
2104120918
preg->err = REG_ERR_INTERNAL;
21042
- return 0;
20919
+ return 0;
2104320920
case '?':
2104420921
case '+':
2104520922
case '*':
2104620923
case '{':
2104720924
preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +20967,34 @@
2109020967
ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
2109120968
reg_addrange_str(preg," \t\r\n\f\v");
2109220969
regc(preg, '\0');
2109320970
*flagp |= HASWIDTH|SIMPLE;
2109420971
break;
21095
-
20972
+
2109620973
default:
21097
-
21098
-
20974
+
20975
+
2109920976
preg->regparse--;
2110020977
goto de_fault;
2110120978
}
2110220979
break;
2110320980
de_fault:
2110420981
default: {
2110520982
int added = 0;
2110620983
21107
-
20984
+
2110820985
preg->regparse -= n;
2110920986
2111020987
ret = regnode(preg, EXACTLY);
2111120988
2111220989
21113
-
20990
+
2111420991
while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
2111520992
n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
2111620993
if (ch == '\\' && preg->regparse[n]) {
2111720994
if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
21118
-
20995
+
2111920996
break;
2112020997
}
2112120998
n += reg_decode_escape(preg->regparse + n, &ch);
2112220999
if (ch == 0) {
2112321000
preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21002,23 @@
2112521002
}
2112621003
}
2112721004
2112821005
2112921006
if (ISMULT(preg->regparse[n])) {
21130
-
21007
+
2113121008
if (added) {
21132
-
21009
+
2113321010
break;
2113421011
}
21135
-
21012
+
2113621013
regc(preg, ch);
2113721014
added++;
2113821015
preg->regparse += n;
2113921016
break;
2114021017
}
2114121018
21142
-
21019
+
2114321020
regc(preg, ch);
2114421021
added++;
2114521022
preg->regparse += n;
2114621023
}
2114721024
regc(preg, '\0');
@@ -21168,15 +21045,15 @@
2116821045
2116921046
static int regnode(regex_t *preg, int op)
2117021047
{
2117121048
reg_grow(preg, 2);
2117221049
21173
-
21050
+
2117421051
preg->program[preg->p++] = op;
2117521052
preg->program[preg->p++] = 0;
2117621053
21177
-
21054
+
2117821055
return preg->p - 2;
2117921056
}
2118021057
2118121058
static void regc(regex_t *preg, int b )
2118221059
{
@@ -21186,13 +21063,13 @@
2118621063
2118721064
static int reginsert(regex_t *preg, int op, int size, int opnd )
2118821065
{
2118921066
reg_grow(preg, size);
2119021067
21191
-
21068
+
2119221069
memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21193
-
21070
+
2119421071
memset(preg->program + opnd, 0, sizeof(int) * size);
2119521072
2119621073
preg->program[opnd] = op;
2119721074
2119821075
preg->p += size;
@@ -21204,11 +21081,11 @@
2120421081
{
2120521082
int scan;
2120621083
int temp;
2120721084
int offset;
2120821085
21209
-
21086
+
2121021087
scan = p;
2121121088
for (;;) {
2121221089
temp = regnext(preg, scan);
2121321090
if (temp == 0)
2121421091
break;
@@ -21224,11 +21101,11 @@
2122421101
}
2122521102
2122621103
2122721104
static void regoptail(regex_t *preg, int p, int val )
2122821105
{
21229
-
21106
+
2123021107
if (p != 0 && OP(preg, p) == BRANCH) {
2123121108
regtail(preg, OPERAND(p), val);
2123221109
}
2123321110
}
2123421111
@@ -21240,16 +21117,16 @@
2124021117
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
2124121118
{
2124221119
const char *s;
2124321120
int scan;
2124421121
21245
-
21122
+
2124621123
if (preg == NULL || preg->program == NULL || string == NULL) {
2124721124
return REG_ERR_NULL_ARGUMENT;
2124821125
}
2124921126
21250
-
21127
+
2125121128
if (*preg->program != REG_MAGIC) {
2125221129
return REG_ERR_CORRUPTED;
2125321130
}
2125421131
2125521132
#ifdef DEBUG
@@ -21258,51 +21135,51 @@
2125821135
#endif
2125921136
2126021137
preg->eflags = eflags;
2126121138
preg->pmatch = pmatch;
2126221139
preg->nmatch = nmatch;
21263
- preg->start = string;
21140
+ preg->start = string;
2126421141
21265
-
21142
+
2126621143
for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
2126721144
int op = OP(preg, scan);
2126821145
if (op == END)
2126921146
break;
2127021147
if (op == REPX || op == REPXMIN)
2127121148
preg->program[scan + 4] = 0;
2127221149
}
2127321150
21274
-
21151
+
2127521152
if (preg->regmust != 0) {
2127621153
s = string;
2127721154
while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
2127821155
if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
2127921156
break;
2128021157
}
2128121158
s++;
2128221159
}
21283
- if (s == NULL)
21160
+ if (s == NULL)
2128421161
return REG_NOMATCH;
2128521162
}
2128621163
21287
-
21164
+
2128821165
preg->regbol = string;
2128921166
21290
-
21167
+
2129121168
if (preg->reganch) {
2129221169
if (eflags & REG_NOTBOL) {
21293
-
21170
+
2129421171
goto nextline;
2129521172
}
2129621173
while (1) {
2129721174
if (regtry(preg, string)) {
2129821175
return REG_NOERROR;
2129921176
}
2130021177
if (*string) {
2130121178
nextline:
2130221179
if (preg->cflags & REG_NEWLINE) {
21303
-
21180
+
2130421181
string = strchr(string, '\n');
2130521182
if (string) {
2130621183
preg->regbol = ++string;
2130721184
continue;
2130821185
}
@@ -21310,22 +21187,22 @@
2131021187
}
2131121188
return REG_NOMATCH;
2131221189
}
2131321190
}
2131421191
21315
-
21192
+
2131621193
s = string;
2131721194
if (preg->regstart != '\0') {
21318
-
21195
+
2131921196
while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
2132021197
if (regtry(preg, s))
2132121198
return REG_NOERROR;
2132221199
s++;
2132321200
}
2132421201
}
2132521202
else
21326
-
21203
+
2132721204
while (1) {
2132821205
if (regtry(preg, s))
2132921206
return REG_NOERROR;
2133021207
if (*s == '\0') {
2133121208
break;
@@ -21334,15 +21211,15 @@
2133421211
int c;
2133521212
s += utf8_tounicode(s, &c);
2133621213
}
2133721214
}
2133821215
21339
-
21216
+
2134021217
return REG_NOMATCH;
2134121218
}
2134221219
21343
-
21220
+
2134421221
static int regtry( regex_t *preg, const char *string )
2134521222
{
2134621223
int i;
2134721224
2134821225
preg->reginput = string;
@@ -21379,11 +21256,11 @@
2137921256
}
2138021257
2138121258
static int reg_range_find(const int *range, int c)
2138221259
{
2138321260
while (*range) {
21384
-
21261
+
2138521262
if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
2138621263
return 1;
2138721264
}
2138821265
range += 2;
2138921266
}
@@ -21391,11 +21268,11 @@
2139121268
}
2139221269
2139321270
static const char *str_find(const char *string, int c, int nocase)
2139421271
{
2139521272
if (nocase) {
21396
-
21273
+
2139721274
c = utf8_upper(c);
2139821275
}
2139921276
while (*string) {
2140021277
int ch;
2140121278
int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21312,15 @@
2143521312
no = regrepeat(preg, scan + 5, max);
2143621313
if (no < min) {
2143721314
return 0;
2143821315
}
2143921316
if (matchmin) {
21440
-
21317
+
2144121318
max = no;
2144221319
no = min;
2144321320
}
21444
-
21321
+
2144521322
while (1) {
2144621323
if (matchmin) {
2144721324
if (no > max) {
2144821325
break;
2144921326
}
@@ -21453,22 +21330,22 @@
2145321330
break;
2145421331
}
2145521332
}
2145621333
preg->reginput = save + utf8_index(save, no);
2145721334
reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21458
-
21335
+
2145921336
if (reg_iseol(preg, nextch) || c == nextch) {
2146021337
if (regmatch(preg, next)) {
2146121338
return(1);
2146221339
}
2146321340
}
2146421341
if (matchmin) {
21465
-
21342
+
2146621343
no++;
2146721344
}
2146821345
else {
21469
-
21346
+
2147021347
no--;
2147121348
}
2147221349
}
2147321350
return(0);
2147421351
}
@@ -21478,13 +21355,13 @@
2147821355
int *scanpt = preg->program + scan;
2147921356
2148021357
int max = scanpt[2];
2148121358
int min = scanpt[3];
2148221359
21483
-
21360
+
2148421361
if (scanpt[4] < min) {
21485
-
21362
+
2148621363
scanpt[4]++;
2148721364
if (regmatch(preg, scan + 5)) {
2148821365
return 1;
2148921366
}
2149021367
scanpt[4]--;
@@ -21493,39 +21370,39 @@
2149321370
if (scanpt[4] > max) {
2149421371
return 0;
2149521372
}
2149621373
2149721374
if (matchmin) {
21498
-
21375
+
2149921376
if (regmatch(preg, regnext(preg, scan))) {
2150021377
return 1;
2150121378
}
21502
-
21379
+
2150321380
scanpt[4]++;
2150421381
if (regmatch(preg, scan + 5)) {
2150521382
return 1;
2150621383
}
2150721384
scanpt[4]--;
2150821385
return 0;
2150921386
}
21510
-
21387
+
2151121388
if (scanpt[4] < max) {
2151221389
scanpt[4]++;
2151321390
if (regmatch(preg, scan + 5)) {
2151421391
return 1;
2151521392
}
2151621393
scanpt[4]--;
2151721394
}
21518
-
21395
+
2151921396
return regmatch(preg, regnext(preg, scan));
2152021397
}
2152121398
2152221399
2152321400
static int regmatch(regex_t *preg, int prog)
2152421401
{
21525
- int scan;
21526
- int next;
21402
+ int scan;
21403
+ int next;
2152721404
const char *save;
2152821405
2152921406
scan = prog;
2153021407
2153121408
#ifdef DEBUG
@@ -21535,11 +21412,11 @@
2153521412
while (scan != 0) {
2153621413
int n;
2153721414
int c;
2153821415
#ifdef DEBUG
2153921416
if (regnarrate) {
21540
- fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21417
+ fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
2154121418
}
2154221419
#endif
2154321420
next = regnext(preg, scan);
2154421421
n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
2154521422
@@ -21546,49 +21423,49 @@
2154621423
switch (OP(preg, scan)) {
2154721424
case BOLX:
2154821425
if ((preg->eflags & REG_NOTBOL)) {
2154921426
return(0);
2155021427
}
21551
-
21428
+
2155221429
case BOL:
2155321430
if (preg->reginput != preg->regbol) {
2155421431
return(0);
2155521432
}
2155621433
break;
2155721434
case EOLX:
2155821435
if (c != 0) {
21559
-
21436
+
2156021437
return 0;
2156121438
}
2156221439
break;
2156321440
case EOL:
2156421441
if (!reg_iseol(preg, c)) {
2156521442
return(0);
2156621443
}
2156721444
break;
2156821445
case WORDA:
21569
-
21446
+
2157021447
if ((!isalnum(UCHAR(c))) && c != '_')
2157121448
return(0);
21572
-
21449
+
2157321450
if (preg->reginput > preg->regbol &&
2157421451
(isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
2157521452
return(0);
2157621453
break;
2157721454
case WORDZ:
21578
-
21455
+
2157921456
if (preg->reginput > preg->regbol) {
21580
-
21457
+
2158121458
if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
2158221459
c = preg->reginput[-1];
21583
-
21460
+
2158421461
if (isalnum(UCHAR(c)) || c == '_') {
2158521462
break;
2158621463
}
2158721464
}
2158821465
}
21589
-
21466
+
2159021467
return(0);
2159121468
2159221469
case ANY:
2159321470
if (reg_iseol(preg, c))
2159421471
return 0;
@@ -21624,12 +21501,12 @@
2162421501
case NOTHING:
2162521502
break;
2162621503
case BACK:
2162721504
break;
2162821505
case BRANCH:
21629
- if (OP(preg, next) != BRANCH)
21630
- next = OPERAND(scan);
21506
+ if (OP(preg, next) != BRANCH)
21507
+ next = OPERAND(scan);
2163121508
else {
2163221509
do {
2163321510
save = preg->reginput;
2163421511
if (regmatch(preg, OPERAND(scan))) {
2163521512
return(1);
@@ -21636,11 +21513,11 @@
2163621513
}
2163721514
preg->reginput = save;
2163821515
scan = regnext(preg, scan);
2163921516
} while (scan != 0 && OP(preg, scan) == BRANCH);
2164021517
return(0);
21641
-
21518
+
2164221519
}
2164321520
break;
2164421521
case REP:
2164521522
case REPMIN:
2164621523
return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21525,11 @@
2164821525
case REPX:
2164921526
case REPXMIN:
2165021527
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
2165121528
2165221529
case END:
21653
- return 1;
21530
+ return 1;
2165421531
2165521532
case OPENNC:
2165621533
case CLOSENC:
2165721534
return regmatch(preg, next);
2165821535
@@ -21695,11 +21572,11 @@
2169521572
2169621573
scan = preg->reginput;
2169721574
opnd = OPERAND(p);
2169821575
switch (OP(preg, p)) {
2169921576
case ANY:
21700
-
21577
+
2170121578
while (!reg_iseol(preg, *scan) && count < max) {
2170221579
count++;
2170321580
scan++;
2170421581
}
2170521582
break;
@@ -21731,13 +21608,13 @@
2173121608
}
2173221609
count++;
2173321610
scan += n;
2173421611
}
2173521612
break;
21736
- default:
21613
+ default:
2173721614
preg->err = REG_ERR_INTERNAL;
21738
- count = 0;
21615
+ count = 0;
2173921616
break;
2174021617
}
2174121618
preg->reginput = scan;
2174221619
2174321620
return(count);
@@ -21758,11 +21635,11 @@
2175821635
return(p+offset);
2175921636
}
2176021637
2176121638
static int regopsize(regex_t *preg, int p )
2176221639
{
21763
-
21640
+
2176421641
switch (OP(preg, p)) {
2176521642
case REP:
2176621643
case REPMIN:
2176721644
case REPX:
2176821645
case REPXMIN:
@@ -21818,10 +21695,223 @@
2181821695
2181921696
void regfree(regex_t *preg)
2182021697
{
2182121698
free(preg->program);
2182221699
}
21700
+
21701
+#endif
21702
+#include <string.h>
21703
+
21704
+void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
21705
+{
21706
+ Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
21707
+}
21708
+
21709
+#if defined(__MINGW32__)
21710
+#include <sys/stat.h>
21711
+
21712
+int Jim_Errno(void)
21713
+{
21714
+ switch (GetLastError()) {
21715
+ case ERROR_FILE_NOT_FOUND: return ENOENT;
21716
+ case ERROR_PATH_NOT_FOUND: return ENOENT;
21717
+ case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
21718
+ case ERROR_ACCESS_DENIED: return EACCES;
21719
+ case ERROR_INVALID_HANDLE: return EBADF;
21720
+ case ERROR_BAD_ENVIRONMENT: return E2BIG;
21721
+ case ERROR_BAD_FORMAT: return ENOEXEC;
21722
+ case ERROR_INVALID_ACCESS: return EACCES;
21723
+ case ERROR_INVALID_DRIVE: return ENOENT;
21724
+ case ERROR_CURRENT_DIRECTORY: return EACCES;
21725
+ case ERROR_NOT_SAME_DEVICE: return EXDEV;
21726
+ case ERROR_NO_MORE_FILES: return ENOENT;
21727
+ case ERROR_WRITE_PROTECT: return EROFS;
21728
+ case ERROR_BAD_UNIT: return ENXIO;
21729
+ case ERROR_NOT_READY: return EBUSY;
21730
+ case ERROR_BAD_COMMAND: return EIO;
21731
+ case ERROR_CRC: return EIO;
21732
+ case ERROR_BAD_LENGTH: return EIO;
21733
+ case ERROR_SEEK: return EIO;
21734
+ case ERROR_WRITE_FAULT: return EIO;
21735
+ case ERROR_READ_FAULT: return EIO;
21736
+ case ERROR_GEN_FAILURE: return EIO;
21737
+ case ERROR_SHARING_VIOLATION: return EACCES;
21738
+ case ERROR_LOCK_VIOLATION: return EACCES;
21739
+ case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
21740
+ case ERROR_HANDLE_DISK_FULL: return ENOSPC;
21741
+ case ERROR_NOT_SUPPORTED: return ENODEV;
21742
+ case ERROR_REM_NOT_LIST: return EBUSY;
21743
+ case ERROR_DUP_NAME: return EEXIST;
21744
+ case ERROR_BAD_NETPATH: return ENOENT;
21745
+ case ERROR_NETWORK_BUSY: return EBUSY;
21746
+ case ERROR_DEV_NOT_EXIST: return ENODEV;
21747
+ case ERROR_TOO_MANY_CMDS: return EAGAIN;
21748
+ case ERROR_ADAP_HDW_ERR: return EIO;
21749
+ case ERROR_BAD_NET_RESP: return EIO;
21750
+ case ERROR_UNEXP_NET_ERR: return EIO;
21751
+ case ERROR_NETNAME_DELETED: return ENOENT;
21752
+ case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
21753
+ case ERROR_BAD_DEV_TYPE: return ENODEV;
21754
+ case ERROR_BAD_NET_NAME: return ENOENT;
21755
+ case ERROR_TOO_MANY_NAMES: return ENFILE;
21756
+ case ERROR_TOO_MANY_SESS: return EIO;
21757
+ case ERROR_SHARING_PAUSED: return EAGAIN;
21758
+ case ERROR_REDIR_PAUSED: return EAGAIN;
21759
+ case ERROR_FILE_EXISTS: return EEXIST;
21760
+ case ERROR_CANNOT_MAKE: return ENOSPC;
21761
+ case ERROR_OUT_OF_STRUCTURES: return ENFILE;
21762
+ case ERROR_ALREADY_ASSIGNED: return EEXIST;
21763
+ case ERROR_INVALID_PASSWORD: return EPERM;
21764
+ case ERROR_NET_WRITE_FAULT: return EIO;
21765
+ case ERROR_NO_PROC_SLOTS: return EAGAIN;
21766
+ case ERROR_DISK_CHANGE: return EXDEV;
21767
+ case ERROR_BROKEN_PIPE: return EPIPE;
21768
+ case ERROR_OPEN_FAILED: return ENOENT;
21769
+ case ERROR_DISK_FULL: return ENOSPC;
21770
+ case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
21771
+ case ERROR_INVALID_TARGET_HANDLE: return EBADF;
21772
+ case ERROR_INVALID_NAME: return ENOENT;
21773
+ case ERROR_PROC_NOT_FOUND: return ESRCH;
21774
+ case ERROR_WAIT_NO_CHILDREN: return ECHILD;
21775
+ case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
21776
+ case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
21777
+ case ERROR_SEEK_ON_DEVICE: return ESPIPE;
21778
+ case ERROR_BUSY_DRIVE: return EAGAIN;
21779
+ case ERROR_DIR_NOT_EMPTY: return EEXIST;
21780
+ case ERROR_NOT_LOCKED: return EACCES;
21781
+ case ERROR_BAD_PATHNAME: return ENOENT;
21782
+ case ERROR_LOCK_FAILED: return EACCES;
21783
+ case ERROR_ALREADY_EXISTS: return EEXIST;
21784
+ case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
21785
+ case ERROR_BAD_PIPE: return EPIPE;
21786
+ case ERROR_PIPE_BUSY: return EAGAIN;
21787
+ case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
21788
+ case ERROR_DIRECTORY: return ENOTDIR;
21789
+ }
21790
+ return EINVAL;
21791
+}
21792
+
21793
+pidtype waitpid(pidtype pid, int *status, int nohang)
21794
+{
21795
+ DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
21796
+ if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
21797
+
21798
+ return JIM_BAD_PID;
21799
+ }
21800
+ GetExitCodeProcess(pid, &ret);
21801
+ *status = ret;
21802
+ CloseHandle(pid);
21803
+ return pid;
21804
+}
21805
+
21806
+int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
21807
+{
21808
+ char name[MAX_PATH];
21809
+ HANDLE handle;
21810
+
21811
+ if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) {
21812
+ return -1;
21813
+ }
21814
+
21815
+ handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
21816
+ CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0),
21817
+ NULL);
21818
+
21819
+ if (handle == INVALID_HANDLE_VALUE) {
21820
+ goto error;
21821
+ }
21822
+
21823
+ Jim_SetResultString(interp, name, -1);
21824
+ return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT);
21825
+
21826
+ error:
21827
+ Jim_SetResultErrno(interp, name);
21828
+ DeleteFile(name);
21829
+ return -1;
21830
+}
21831
+
21832
+int Jim_OpenForWrite(const char *filename, int append)
21833
+{
21834
+ if (strcmp(filename, "/dev/null") == 0) {
21835
+ filename = "nul:";
21836
+ }
21837
+ int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE);
21838
+ if (fd >= 0 && append) {
21839
+
21840
+ _lseek(fd, 0L, SEEK_END);
21841
+ }
21842
+ return fd;
21843
+}
21844
+
21845
+int Jim_OpenForRead(const char *filename)
21846
+{
21847
+ if (strcmp(filename, "/dev/null") == 0) {
21848
+ filename = "nul:";
21849
+ }
21850
+ return _open(filename, _O_RDONLY | _O_TEXT, 0);
21851
+}
21852
+
21853
+#elif defined(HAVE_UNISTD_H)
21854
+
21855
+
21856
+
21857
+int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
21858
+{
21859
+ int fd;
21860
+ mode_t mask;
21861
+ Jim_Obj *filenameObj;
21862
+
21863
+ if (filename_template == NULL) {
21864
+ const char *tmpdir = getenv("TMPDIR");
21865
+ if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
21866
+ tmpdir = "/tmp/";
21867
+ }
21868
+ filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
21869
+ if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
21870
+ Jim_AppendString(interp, filenameObj, "/", 1);
21871
+ }
21872
+ Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
21873
+ }
21874
+ else {
21875
+ filenameObj = Jim_NewStringObj(interp, filename_template, -1);
21876
+ }
21877
+
21878
+
21879
+ mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
21880
+#ifdef HAVE_MKSTEMP
21881
+ fd = mkstemp(filenameObj->bytes);
21882
+#else
21883
+ if (mktemp(filenameObj->bytes) == NULL) {
21884
+ fd = -1;
21885
+ }
21886
+ else {
21887
+ fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC);
21888
+ }
21889
+#endif
21890
+ umask(mask);
21891
+ if (fd < 0) {
21892
+ Jim_SetResultErrno(interp, Jim_String(filenameObj));
21893
+ Jim_FreeNewObj(interp, filenameObj);
21894
+ return -1;
21895
+ }
21896
+ if (unlink_file) {
21897
+ remove(Jim_String(filenameObj));
21898
+ }
21899
+
21900
+ Jim_SetResult(interp, filenameObj);
21901
+ return fd;
21902
+}
21903
+
21904
+int Jim_OpenForWrite(const char *filename, int append)
21905
+{
21906
+ return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
21907
+}
21908
+
21909
+int Jim_OpenForRead(const char *filename)
21910
+{
21911
+ return open(filename, O_RDONLY, 0);
21912
+}
2182321913
2182421914
#endif
2182521915
2182621916
#if defined(_WIN32) || defined(WIN32)
2182721917
#ifndef STRICT
@@ -21879,26 +21969,26 @@
2187921969
{
2188021970
DIR *dir = 0;
2188121971
2188221972
if (name && name[0]) {
2188321973
size_t base_length = strlen(name);
21884
- const char *all =
21974
+ const char *all =
2188521975
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
2188621976
2188721977
if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
2188821978
(dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
2188921979
strcat(strcpy(dir->name, name), all);
2189021980
2189121981
if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
2189221982
dir->result.d_name = 0;
21893
- else {
21983
+ else {
2189421984
Jim_Free(dir->name);
2189521985
Jim_Free(dir);
2189621986
dir = 0;
2189721987
}
2189821988
}
21899
- else {
21989
+ else {
2190021990
Jim_Free(dir);
2190121991
dir = 0;
2190221992
errno = ENOMEM;
2190321993
}
2190421994
}
@@ -21916,11 +22006,11 @@
2191622006
if (dir->handle != -1)
2191722007
result = _findclose(dir->handle);
2191822008
Jim_Free(dir->name);
2191922009
Jim_Free(dir);
2192022010
}
21921
- if (result == -1)
22011
+ if (result == -1)
2192222012
errno = EBADF;
2192322013
return result;
2192422014
}
2192522015
2192622016
struct dirent *readdir(DIR * dir)
@@ -21938,28 +22028,77 @@
2193822028
}
2193922029
return result;
2194022030
}
2194122031
#endif
2194222032
#endif
22033
+#include <stdio.h>
22034
+#include <signal.h>
22035
+
22036
+
22037
+
22038
+
22039
+
22040
+
22041
+#ifndef SIGPIPE
22042
+#define SIGPIPE 13
22043
+#endif
22044
+#ifndef SIGINT
22045
+#define SIGINT 2
22046
+#endif
22047
+
22048
+const char *Jim_SignalId(int sig)
22049
+{
22050
+ static char buf[10];
22051
+ switch (sig) {
22052
+ case SIGINT: return "SIGINT";
22053
+ case SIGPIPE: return "SIGPIPE";
22054
+
22055
+ }
22056
+ snprintf(buf, sizeof(buf), "%d", sig);
22057
+ return buf;
22058
+}
2194322059
#ifndef JIM_BOOTSTRAP_LIB_ONLY
2194422060
#include <errno.h>
2194522061
#include <string.h>
2194622062
2194722063
2194822064
#ifdef USE_LINENOISE
2194922065
#ifdef HAVE_UNISTD_H
2195022066
#include <unistd.h>
2195122067
#endif
22068
+#ifdef HAVE_SYS_STAT_H
22069
+ #include <sys/stat.h>
22070
+#endif
2195222071
#include "linenoise.h"
2195322072
#else
2195422073
#define MAX_LINE_LEN 512
2195522074
#endif
2195622075
21957
-char *Jim_HistoryGetline(const char *prompt)
22076
+#ifdef USE_LINENOISE
22077
+static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata);
22078
+static const char completion_callback_assoc_key[] = "interactive-completion";
22079
+#endif
22080
+
22081
+char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt)
2195822082
{
2195922083
#ifdef USE_LINENOISE
21960
- return linenoise(prompt);
22084
+ struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key);
22085
+ char *result;
22086
+ Jim_Obj *objPtr;
22087
+ long mlmode = 0;
22088
+ if (compinfo) {
22089
+ linenoiseSetCompletionCallback(JimCompletionCallback, compinfo);
22090
+ }
22091
+ objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE);
22092
+ if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) {
22093
+ linenoiseSetMultiLine(mlmode);
22094
+ }
22095
+
22096
+ result = linenoise(prompt);
22097
+
22098
+ linenoiseSetCompletionCallback(NULL, NULL);
22099
+ return result;
2196122100
#else
2196222101
int len;
2196322102
char *line = malloc(MAX_LINE_LEN);
2196422103
2196522104
fputs(prompt, stdout);
@@ -21992,26 +22131,92 @@
2199222131
}
2199322132
2199422133
void Jim_HistorySave(const char *filename)
2199522134
{
2199622135
#ifdef USE_LINENOISE
22136
+#ifdef HAVE_UMASK
22137
+ mode_t mask;
22138
+
22139
+ mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
22140
+#endif
2199722141
linenoiseHistorySave(filename);
22142
+#ifdef HAVE_UMASK
22143
+ mask = umask(mask);
22144
+#endif
2199822145
#endif
2199922146
}
2200022147
2200122148
void Jim_HistoryShow(void)
2200222149
{
2200322150
#ifdef USE_LINENOISE
22004
-
22151
+
2200522152
int i;
2200622153
int len;
2200722154
char **history = linenoiseHistory(&len);
2200822155
for (i = 0; i < len; i++) {
2200922156
printf("%4d %s\n", i + 1, history[i]);
2201022157
}
2201122158
#endif
2201222159
}
22160
+
22161
+#ifdef USE_LINENOISE
22162
+struct JimCompletionInfo {
22163
+ Jim_Interp *interp;
22164
+ Jim_Obj *command;
22165
+};
22166
+
22167
+static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
22168
+{
22169
+ struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
22170
+ Jim_Obj *objv[2];
22171
+ int ret;
22172
+
22173
+ objv[0] = info->command;
22174
+ objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
22175
+
22176
+ ret = Jim_EvalObjVector(info->interp, 2, objv);
22177
+
22178
+
22179
+ if (ret == JIM_OK) {
22180
+ int i;
22181
+ Jim_Obj *listObj = Jim_GetResult(info->interp);
22182
+ int len = Jim_ListLength(info->interp, listObj);
22183
+ for (i = 0; i < len; i++) {
22184
+ linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i)));
22185
+ }
22186
+ }
22187
+}
22188
+
22189
+static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data)
22190
+{
22191
+ struct JimCompletionInfo *compinfo = data;
22192
+
22193
+ Jim_DecrRefCount(interp, compinfo->command);
22194
+
22195
+ Jim_Free(compinfo);
22196
+}
22197
+#endif
22198
+
22199
+void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj)
22200
+{
22201
+#ifdef USE_LINENOISE
22202
+ if (commandObj) {
22203
+
22204
+ Jim_IncrRefCount(commandObj);
22205
+ }
22206
+
22207
+ Jim_DeleteAssocData(interp, completion_callback_assoc_key);
22208
+
22209
+ if (commandObj) {
22210
+ struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo));
22211
+ compinfo->interp = interp;
22212
+ compinfo->command = commandObj;
22213
+
22214
+ Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo);
22215
+ }
22216
+#endif
22217
+}
2201322218
2201422219
int Jim_InteractivePrompt(Jim_Interp *interp)
2201522220
{
2201622221
int retcode = JIM_OK;
2201722222
char *history_file = NULL;
@@ -22023,10 +22228,12 @@
2202322228
int history_len = strlen(home) + sizeof("/.jim_history");
2202422229
history_file = Jim_Alloc(history_len);
2202522230
snprintf(history_file, history_len, "%s/.jim_history", home);
2202622231
Jim_HistoryLoad(history_file);
2202722232
}
22233
+
22234
+ Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1));
2202822235
#endif
2202922236
2203022237
printf("Welcome to Jim version %d.%d\n",
2203122238
JIM_VERSION / 100, JIM_VERSION % 100);
2203222239
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22055,21 +22262,21 @@
2205522262
Jim_IncrRefCount(scriptObjPtr);
2205622263
while (1) {
2205722264
char state;
2205822265
char *line;
2205922266
22060
- line = Jim_HistoryGetline(prompt);
22267
+ line = Jim_HistoryGetline(interp, prompt);
2206122268
if (line == NULL) {
2206222269
if (errno == EINTR) {
2206322270
continue;
2206422271
}
2206522272
Jim_DecrRefCount(interp, scriptObjPtr);
2206622273
retcode = JIM_OK;
2206722274
goto out;
2206822275
}
2206922276
if (Jim_Length(scriptObjPtr) != 0) {
22070
-
22277
+
2207122278
Jim_AppendString(interp, scriptObjPtr, "\n", 1);
2207222279
}
2207322280
Jim_AppendString(interp, scriptObjPtr, line, -1);
2207422281
free(line);
2207522282
if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22284,11 @@
2207722284
2207822285
snprintf(prompt, sizeof(prompt), "%c> ", state);
2207922286
}
2208022287
#ifdef USE_LINENOISE
2208122288
if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22082
-
22289
+
2208322290
Jim_HistoryShow();
2208422291
Jim_DecrRefCount(interp, scriptObjPtr);
2208522292
continue;
2208622293
}
2208722294
@@ -22104,10 +22311,11 @@
2210422311
printf("%s\n", result);
2210522312
}
2210622313
}
2210722314
out:
2210822315
Jim_Free(history_file);
22316
+
2210922317
return retcode;
2211022318
}
2211122319
2211222320
#include <stdio.h>
2211322321
#include <stdlib.h>
@@ -22120,11 +22328,11 @@
2212022328
static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
2212122329
{
2212222330
int n;
2212322331
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2212422332
22125
-
22333
+
2212622334
for (n = 0; n < argc; n++) {
2212722335
Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
2212822336
2212922337
Jim_ListAppendElement(interp, listObj, obj);
2213022338
}
@@ -22146,71 +22354,75 @@
2214622354
printf("or : %s [options] [filename]\n", executable_name);
2214722355
printf("\n");
2214822356
printf("Without options: Interactive mode\n");
2214922357
printf("\n");
2215022358
printf("Options:\n");
22151
- printf(" --version : prints the version string\n");
22152
- printf(" --help : prints this text\n");
22153
- printf(" -e CMD : executes command CMD\n");
22154
- printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22155
- printf(" [filename] : executes the script contained in the named file\n");
22156
- printf(" NOTE: all subsequent options will be passed to the script\n\n");
22359
+ printf(" --version : prints the version string\n");
22360
+ printf(" --help : prints this text\n");
22361
+ printf(" -e CMD : executes command CMD\n");
22362
+ printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22363
+ printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n");
22364
+ printf(" NOTE: all subsequent options will be passed to the script\n\n");
2215722365
}
2215822366
2215922367
int main(int argc, char *const argv[])
2216022368
{
2216122369
int retcode;
2216222370
Jim_Interp *interp;
2216322371
char *const orig_argv0 = argv[0];
2216422372
22165
-
22373
+
2216622374
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
2216722375
printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
2216822376
return 0;
2216922377
}
2217022378
else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
2217122379
usage(argv[0]);
2217222380
return 0;
2217322381
}
2217422382
22175
-
22383
+
2217622384
interp = Jim_CreateInterp();
2217722385
Jim_RegisterCoreCommands(interp);
2217822386
22179
-
22387
+
2218022388
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
2218122389
JimPrintErrorMessage(interp);
2218222390
}
2218322391
2218422392
Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
2218522393
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
2218622394
retcode = Jim_initjimshInit(interp);
2218722395
2218822396
if (argc == 1) {
22189
-
22397
+
2219022398
if (retcode == JIM_ERR) {
2219122399
JimPrintErrorMessage(interp);
2219222400
}
2219322401
if (retcode != JIM_EXIT) {
2219422402
JimSetArgv(interp, 0, NULL);
2219522403
retcode = Jim_InteractivePrompt(interp);
2219622404
}
2219722405
}
2219822406
else {
22199
-
22407
+
2220022408
if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22201
-
22409
+
2220222410
JimSetArgv(interp, argc - 3, argv + 3);
2220322411
retcode = Jim_Eval(interp, argv[2]);
2220422412
if (retcode != JIM_ERR) {
2220522413
printf("%s\n", Jim_String(Jim_GetResult(interp)));
2220622414
}
2220722415
}
2220822416
else {
2220922417
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
2221022418
JimSetArgv(interp, argc - 2, argv + 2);
22211
- retcode = Jim_EvalFile(interp, argv[1]);
22419
+ if (strcmp(argv[1], "-") == 0) {
22420
+ retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
22421
+ } else {
22422
+ retcode = Jim_EvalFile(interp, argv[1]);
22423
+ }
2221222424
}
2221322425
if (retcode == JIM_ERR) {
2221422426
JimPrintErrorMessage(interp);
2221522427
}
2221622428
}
2221722429
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
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
7 #define HAVE_NO_AUTOCONF
8 #define _JIMAUTOCONF_H
9 #define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
31 #define HAVE_MKDIR_ONE_ARG
32 #define HAVE_SYSTEM
33 #define HAVE_SYS_TIME_H
34 #define HAVE_DIRENT_H
35 #define HAVE_UNISTD_H
 
 
 
 
 
 
 
 
36 #else
37 #define TCL_PLATFORM_OS "unknown"
38 #define TCL_PLATFORM_PLATFORM "unix"
39 #define TCL_PLATFORM_PATH_SEPARATOR ":"
 
 
 
 
 
 
40 #define HAVE_VFORK
41 #define HAVE_WAITPID
42 #define HAVE_ISATTY
43 #define HAVE_MKSTEMP
44 #define HAVE_LINK
45 #define HAVE_SYS_TIME_H
46 #define HAVE_DIRENT_H
47 #define HAVE_UNISTD_H
 
48 #endif
49 #define JIM_VERSION 76
50 #ifndef JIM_WIN32COMPAT_H
51 #define JIM_WIN32COMPAT_H
52
53
54
@@ -88,11 +101,10 @@
88 #define JIM_WIDE_MIN LLONG_MIN
89 #define JIM_WIDE_MAX LLONG_MAX
90 #define JIM_WIDE_MODIFIER "I64d"
91 #define strcasecmp _stricmp
92 #define strtoull _strtoui64
93 #define snprintf _snprintf
94
95 #include <io.h>
96
97 struct timeval {
98 long tv_sec;
@@ -105,29 +117,24 @@
105 struct dirent {
106 char *d_name;
107 };
108
109 typedef struct DIR {
110 long handle;
111 struct _finddata_t info;
112 struct dirent result;
113 char *name;
114 } DIR;
115
116 DIR *opendir(const char *name);
117 int closedir(DIR *dir);
118 struct dirent *readdir(DIR *dir);
119
120 #elif defined(__MINGW32__)
121
122 #include <stdlib.h>
123 #define strtod __strtod
124
125 #endif
126
127 #endif
128
129 #ifdef __cplusplus
130 }
131 #endif
132
133 #endif
@@ -146,19 +153,21 @@
146
147 #ifndef JIM_UTF8
148 #include <ctype.h>
149
150
151 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
 
152 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
153 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
154 #define utf8_upper(C) toupper(C)
155 #define utf8_title(C) toupper(C)
156 #define utf8_lower(C) tolower(C)
157 #define utf8_index(C, I) (I)
158 #define utf8_charlen(C) 1
159 #define utf8_prev_len(S, L) 1
 
160
161 #else
162
163 #endif
164
@@ -175,13 +184,13 @@
175 extern "C" {
176 #endif
177
178 #include <time.h>
179 #include <limits.h>
180 #include <stdio.h>
181 #include <stdlib.h>
182 #include <stdarg.h>
183
184
185 #ifndef HAVE_NO_AUTOCONF
186 #endif
187
@@ -224,31 +233,31 @@
224 #define JIM_SIGNAL 5
225 #define JIM_EXIT 6
226
227 #define JIM_EVAL 7
228
229 #define JIM_MAX_CALLFRAME_DEPTH 1000
230 #define JIM_MAX_EVAL_DEPTH 2000
231
232
233 #define JIM_PRIV_FLAG_SHIFT 20
234
235 #define JIM_NONE 0
236 #define JIM_ERRMSG 1
237 #define JIM_ENUM_ABBREV 2
238 #define JIM_UNSHARED 4
239 #define JIM_MUSTEXIST 8
240
241
242 #define JIM_SUBST_NOVAR 1
243 #define JIM_SUBST_NOCMD 2
244 #define JIM_SUBST_NOESC 4
245 #define JIM_SUBST_FLAG 128
246
247
248 #define JIM_CASESENS 0
249 #define JIM_NOCASE 1
250
251
252 #define JIM_PATH_LEN 1024
253
254
@@ -339,79 +348,80 @@
339 #define Jim_GetHashTableSize(ht) ((ht)->size)
340 #define Jim_GetHashTableUsed(ht) ((ht)->used)
341
342
343 typedef struct Jim_Obj {
344 char *bytes;
345 const struct Jim_ObjType *typePtr;
346 int refCount;
347 int length;
348
349 union {
350
351 jim_wide wideValue;
352
353 int intValue;
354
355 double doubleValue;
356
357 void *ptr;
358
359 struct {
360 void *ptr1;
361 void *ptr2;
362 } twoPtrValue;
363
 
 
 
 
 
 
364 struct {
365 struct Jim_Var *varPtr;
366 unsigned long callFrameId;
367 int global;
368 } varValue;
369
370 struct {
371 struct Jim_Obj *nsObj;
372 struct Jim_Cmd *cmdPtr;
373 unsigned long procEpoch;
374 } cmdValue;
375
376 struct {
377 struct Jim_Obj **ele;
378 int len;
379 int maxLen;
380 } listValue;
381
382 struct {
383 int maxLength;
384 int charLength;
385 } strValue;
386
387 struct {
388 unsigned long id;
389 struct Jim_Reference *refPtr;
390 } refValue;
391
392 struct {
393 struct Jim_Obj *fileNameObj;
394 int lineNumber;
395 } sourceValue;
396
397 struct {
398 struct Jim_Obj *varNameObjPtr;
399 struct Jim_Obj *indexObjPtr;
400 } dictSubstValue;
401
402 struct {
403 void *compre;
404 unsigned flags;
405 } regexpValue;
406 struct {
407 int line;
408 int argc;
409 } scriptLineValue;
410 } internalRep;
411 struct Jim_Obj *prevObjPtr;
412 struct Jim_Obj *nextObjPtr;
413 } Jim_Obj;
414
415
416 #define Jim_IncrRefCount(objPtr) \
417 ++(objPtr)->refCount
@@ -442,40 +452,40 @@
442 typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
443 struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
444 typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
445
446 typedef struct Jim_ObjType {
447 const char *name;
448 Jim_FreeInternalRepProc *freeIntRepProc;
449 Jim_DupInternalRepProc *dupIntRepProc;
450 Jim_UpdateStringProc *updateStringProc;
451 int flags;
452 } Jim_ObjType;
453
454
455 #define JIM_TYPE_NONE 0
456 #define JIM_TYPE_REFERENCES 1
457
458
459
460 typedef struct Jim_CallFrame {
461 unsigned long id;
462 int level;
463 struct Jim_HashTable vars;
464 struct Jim_HashTable *staticVars;
465 struct Jim_CallFrame *parent;
466 Jim_Obj *const *argv;
467 int argc;
468 Jim_Obj *procArgsObjPtr;
469 Jim_Obj *procBodyObjPtr;
470 struct Jim_CallFrame *next;
471 Jim_Obj *nsObj;
472 Jim_Obj *fileNameObj;
473 int line;
474 Jim_Stack *localCommands;
475 struct Jim_Obj *tailcallObj;
476 struct Jim_Cmd *tailcallCmd;
477 } Jim_CallFrame;
478
479 typedef struct Jim_Var {
480 Jim_Obj *objPtr;
481 struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +497,35 @@
487 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
488
489
490
491 typedef struct Jim_Cmd {
492 int inUse;
493 int isproc;
494 struct Jim_Cmd *prevCmd;
495 union {
496 struct {
497
498 Jim_CmdProc *cmdProc;
499 Jim_DelCmdProc *delProc;
500 void *privData;
501 } native;
502 struct {
503
504 Jim_Obj *argListObjPtr;
505 Jim_Obj *bodyObjPtr;
506 Jim_HashTable *staticVars;
507 int argListLen;
508 int reqArity;
509 int optArity;
510 int argsPos;
511 int upcall;
512 struct Jim_ProcArg {
513 Jim_Obj *nameObjPtr;
514 Jim_Obj *defaultObjPtr;
515 } *arglist;
516 Jim_Obj *nsObj;
517 } proc;
518 } u;
519 } Jim_Cmd;
520
521
@@ -523,64 +533,64 @@
523 unsigned char sbox[256];
524 unsigned int i, j;
525 } Jim_PrngState;
526
527 typedef struct Jim_Interp {
528 Jim_Obj *result;
529 int errorLine;
530 Jim_Obj *errorFileNameObj;
531 int addStackTrace;
532 int maxCallFrameDepth;
533 int maxEvalDepth;
534 int evalDepth;
535 int returnCode;
536 int returnLevel;
537 int exitCode;
538 long id;
539 int signal_level;
540 jim_wide sigmask;
541 int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
542 Jim_CallFrame *framePtr;
543 Jim_CallFrame *topFramePtr;
544 struct Jim_HashTable commands;
545 unsigned long procEpoch; /* Incremented every time the result
546 of procedures names lookup caching
547 may no longer be valid. */
548 unsigned long callFrameEpoch; /* Incremented every time a new
549 callframe is created. This id is used for the
550 'ID' field contained in the Jim_CallFrame
551 structure. */
552 int local;
553 Jim_Obj *liveList;
554 Jim_Obj *freeList;
555 Jim_Obj *currentScriptObj;
556 Jim_Obj *nullScriptObj;
557 Jim_Obj *emptyObj;
558 Jim_Obj *trueObj;
559 Jim_Obj *falseObj;
560 unsigned long referenceNextId;
561 struct Jim_HashTable references;
562 unsigned long lastCollectId; /* reference max Id of the last GC
563 execution. It's set to -1 while the collection
564 is running as sentinel to avoid to recursive
565 calls via the [collect] command inside
566 finalizers. */
567 time_t lastCollectTime;
568 Jim_Obj *stackTrace;
569 Jim_Obj *errorProc;
570 Jim_Obj *unknown;
571 int unknown_called;
572 int errorFlag;
573 void *cmdPrivData; /* Used to pass the private data pointer to
574 a command. It is set to what the user specified
575 via Jim_CreateCommand(). */
576
577 struct Jim_CallFrame *freeFramesList;
578 struct Jim_HashTable assocData;
579 Jim_PrngState *prngState;
580 struct Jim_HashTable packages;
581 Jim_Stack *loadHandles;
582 } Jim_Interp;
583
584 #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
585 #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
586 #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +633,11 @@
623 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
624
625
626 JIM_EXPORT char **Jim_GetEnviron(void);
627 JIM_EXPORT void Jim_SetEnviron(char **env);
628 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
629
630
631 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
632
633
@@ -816,25 +826,33 @@
816 Jim_Obj *newObjPtr, int flags);
817 JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
818 Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
819 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
820 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
821 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
822 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
 
 
 
823 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
824 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
 
825
826
827 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
828 int *intPtr);
829
830
831 JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
832 Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
833 JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
834 Jim_Obj *exprObjPtr, int *boolPtr);
835
 
 
 
 
836
837 JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
838 jim_wide *widePtr);
839 JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
840 long *longPtr);
@@ -852,10 +870,12 @@
852
853 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
854 Jim_Obj *const *argv, const char *msg);
855 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
856 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
 
 
857 JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
858 Jim_Obj *scriptObj, char *stateCharPtr);
859
860 JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
861
@@ -878,11 +898,12 @@
878
879
880 JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
881 JIM_EXPORT void Jim_HistoryLoad(const char *filename);
882 JIM_EXPORT void Jim_HistorySave(const char *filename);
883 JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
 
884 JIM_EXPORT void Jim_HistoryAdd(const char *line);
885 JIM_EXPORT void Jim_HistoryShow(void);
886
887
888 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
@@ -904,11 +925,11 @@
904
905 #ifdef __cplusplus
906 }
907 #endif
908
909 #endif
910
911 #ifndef JIM_SUBCMD_H
912 #define JIM_SUBCMD_H
913
914
@@ -915,24 +936,24 @@
915 #ifdef __cplusplus
916 extern "C" {
917 #endif
918
919
920 #define JIM_MODFLAG_HIDDEN 0x0001
921 #define JIM_MODFLAG_FULLARGV 0x0002
922
923
924
925 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
926
927 typedef struct {
928 const char *cmd;
929 const char *args;
930 jim_subcmd_function *function;
931 short minargs;
932 short maxargs;
933 unsigned short flags;
934 } jim_subcmd_type;
935
936 const jim_subcmd_type *
937 Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
938
@@ -960,36 +981,36 @@
960 int rm_eo;
961 } regmatch_t;
962
963
964 typedef struct regexp {
965
966 int re_nsub;
967
968
969 int cflags;
970 int err;
971 int regstart;
972 int reganch;
973 int regmust;
974 int regmlen;
975 int *program;
976
977
978 const char *regparse;
979 int p;
980 int proglen;
981
982
983 int eflags;
984 const char *start;
985 const char *reginput;
986 const char *regbol;
987
988
989 regmatch_t *pmatch;
990 int nmatch;
991 } regexp;
992
993 typedef regexp regex_t;
994
995 #define REG_EXTENDED 0
@@ -997,13 +1018,13 @@
997 #define REG_ICASE 2
998
999 #define REG_NOTBOL 16
1000
1001 enum {
1002 REG_NOERROR,
1003 REG_NOMATCH,
1004 REG_BADPAT,
1005 REG_ERR_NULL_ARGUMENT,
1006 REG_ERR_UNKNOWN,
1007 REG_ERR_TOO_BIG,
1008 REG_ERR_NOMEM,
1009 REG_ERR_TOO_MANY_PAREN,
@@ -1027,10 +1048,83 @@
1027 void regfree(regex_t *preg);
1028
1029 #ifdef __cplusplus
1030 }
1031 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1032
1033 #endif
1034 int Jim_bootstrapInit(Jim_Interp *interp)
1035 {
1036 if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
@@ -1100,10 +1194,43 @@
1100 "\n"
1101 "if {$tcl_platform(platform) eq \"windows\"} {\n"
1102 " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
1103 "}\n"
1104 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105 "_jimsh_init\n"
1106 );
1107 }
1108 int Jim_globInit(Jim_Interp *interp)
1109 {
@@ -1315,10 +1442,17 @@
1315 return JIM_ERR;
1316
1317 return Jim_EvalSource(interp, "stdlib.tcl", 1,
1318 "\n"
1319 "\n"
 
 
 
 
 
 
 
1320 "\n"
1321 "proc lambda {arglist args} {\n"
1322 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1323 "}\n"
1324 "\n"
@@ -1375,10 +1509,17 @@
1375 " }\n"
1376 " join $lines \\n\n"
1377 "}\n"
1378 "\n"
1379 "\n"
 
 
 
 
 
 
 
1380 "\n"
1381 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1382 " if {$stacktrace eq \"\"} {\n"
1383 "\n"
1384 " set stacktrace [info stacktrace]\n"
@@ -1402,31 +1543,10 @@
1402 " if {[exists ::jim::exe]} {\n"
1403 " return $::jim::exe\n"
1404 " }\n"
1405 "}\n"
1406 "\n"
1407 "\n"
1408 "proc {dict with} {&dictVar {args key} script} {\n"
1409 " set keys {}\n"
1410 " foreach {n v} [dict get $dictVar {*}$key] {\n"
1411 " upvar $n var_$n\n"
1412 " set var_$n $v\n"
1413 " lappend keys $n\n"
1414 " }\n"
1415 " catch {uplevel 1 $script} msg opts\n"
1416 " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1417 " foreach n $keys {\n"
1418 " if {[info exists var_$n]} {\n"
1419 " dict set dictVar {*}$key $n [set var_$n]\n"
1420 " } else {\n"
1421 " dict unset dictVar {*}$key $n\n"
1422 " }\n"
1423 " }\n"
1424 " }\n"
1425 " return {*}$opts $msg\n"
1426 "}\n"
1427 "\n"
1428 "\n"
1429 "proc {dict update} {&varName args script} {\n"
1430 " set keys {}\n"
1431 " foreach {n v} $args {\n"
1432 " upvar $v var_$v\n"
@@ -1445,23 +1565,10 @@
1445 " }\n"
1446 " }\n"
1447 " return {*}$opts $msg\n"
1448 "}\n"
1449 "\n"
1450 "\n"
1451 "\n"
1452 "proc {dict merge} {dict args} {\n"
1453 " foreach d $args {\n"
1454 "\n"
1455 " dict size $d\n"
1456 " foreach {k v} $d {\n"
1457 " dict set dict $k $v\n"
1458 " }\n"
1459 " }\n"
1460 " return $dict\n"
1461 "}\n"
1462 "\n"
1463 "proc {dict replace} {dictionary {args {key value}}} {\n"
1464 " if {[llength ${key value}] % 2} {\n"
1465 " tailcall {dict replace}\n"
1466 " }\n"
1467 " tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1610,10 @@
1503 " dict unset dictionary $k\n"
1504 " }\n"
1505 " return $dictionary\n"
1506 "}\n"
1507 "\n"
1508 "\n"
1509 "proc {dict values} {dictionary {pattern *}} {\n"
1510 " dict keys [lreverse $dictionary] $pattern\n"
1511 "}\n"
1512 "\n"
1513 "\n"
1514 "proc {dict for} {vars dictionary script} {\n"
1515 " if {[llength $vars] != 2} {\n"
1516 " return -code error \"must have exactly two variable names\"\n"
1517 " }\n"
@@ -1591,11 +1693,10 @@
1591 " tailcall {*}$args\n"
1592 "}\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "proc parray {arrayname {pattern *} {puts puts}} {\n"
1598 " upvar $arrayname a\n"
1599 "\n"
1600 " set max 0\n"
1601 " foreach name [array names a $pattern]] {\n"
@@ -1647,11 +1748,11 @@
1647 "}\n"
1648 "\n"
1649 "\n"
1650 "\n"
1651 "proc popen {cmd {mode r}} {\n"
1652 " lassign [socket pipe] r w\n"
1653 " try {\n"
1654 " if {[string match \"w*\" $mode]} {\n"
1655 " lappend cmd <@$r &\n"
1656 " set pids [exec {*}$cmd]\n"
1657 " $r close\n"
@@ -1663,16 +1764,31 @@
1663 " set f $r\n"
1664 " }\n"
1665 " lambda {cmd args} {f pids} {\n"
1666 " if {$cmd eq \"pid\"} {\n"
1667 " return $pids\n"
 
 
 
1668 " }\n"
1669 " if {$cmd eq \"close\"} {\n"
1670 " $f close\n"
1671 "\n"
1672 " foreach p $pids { os.wait $p }\n"
1673 " return\n"
 
 
 
 
 
 
 
 
 
 
 
 
1674 " }\n"
1675 " tailcall $f $cmd {*}$args\n"
1676 " }\n"
1677 " } on error {error opts} {\n"
1678 " $r close\n"
@@ -1692,14 +1808,10 @@
1692 " if {[catch {$channelId pid} pids]} {\n"
1693 " return \"\"\n"
1694 " }\n"
1695 " return $pids\n"
1696 "}\n"
1697 "\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "\n"
1704 "\n"
1705 "\n"
@@ -1780,10 +1892,13 @@
1780 "}\n"
1781 );
1782 }
1783
1784
 
 
 
1785 #include <stdio.h>
1786 #include <string.h>
1787 #include <errno.h>
1788 #include <fcntl.h>
1789 #ifdef HAVE_UNISTD_H
@@ -1793,27 +1908,34 @@
1793
1794
1795 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1796 #include <sys/socket.h>
1797 #include <netinet/in.h>
 
1798 #include <arpa/inet.h>
1799 #include <netdb.h>
1800 #ifdef HAVE_SYS_UN_H
1801 #include <sys/un.h>
1802 #endif
 
 
 
1803 #else
1804 #define JIM_ANSIC
1805 #endif
1806
1807 #if defined(JIM_SSL)
1808 #include <openssl/ssl.h>
1809 #include <openssl/err.h>
1810 #endif
1811
 
 
1812
1813 #define AIO_CMD_LEN 32
1814 #define AIO_BUF_LEN 256
 
1815
1816 #ifndef HAVE_FTELLO
1817 #define ftello ftell
1818 #endif
1819 #ifndef HAVE_FSEEKO
@@ -1828,10 +1950,16 @@
1828 #define IPV6 0
1829 #ifndef PF_INET6
1830 #define PF_INET6 0
1831 #endif
1832 #endif
 
 
 
 
 
 
1833
1834 #define JimCheckStreamError(interp, af) af->fops->error(af)
1835
1836
1837 struct AioFile;
@@ -1848,11 +1976,11 @@
1848 typedef struct AioFile
1849 {
1850 FILE *fp;
1851 Jim_Obj *filename;
1852 int type;
1853 int openFlags;
1854 int fd;
1855 Jim_Obj *rEvent;
1856 Jim_Obj *wEvent;
1857 Jim_Obj *eEvent;
1858 int addr_family;
@@ -1879,21 +2007,21 @@
1879 {
1880 if (!ferror(af->fp)) {
1881 return JIM_OK;
1882 }
1883 clearerr(af->fp);
1884
1885 if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
1886 return JIM_OK;
1887 }
1888 #ifdef ECONNRESET
1889 if (errno == ECONNRESET) {
1890 return JIM_OK;
1891 }
1892 #endif
1893 #ifdef ECONNABORTED
1894 if (errno != ECONNABORTED) {
1895 return JIM_OK;
1896 }
1897 #endif
1898 return JIM_ERR;
1899 }
@@ -1945,20 +2073,19 @@
1945 JIM_NOTUSED(interp);
1946
1947 Jim_DecrRefCount(interp, af->filename);
1948
1949 #ifdef jim_ext_eventloop
1950
1951 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1952 #endif
1953
1954 #if defined(JIM_SSL)
1955 if (af->ssl != NULL) {
1956 SSL_free(af->ssl);
1957 }
1958 #endif
1959
1960 if (!(af->openFlags & AIO_KEEPOPEN)) {
1961 fclose(af->fp);
1962 }
1963
1964 Jim_Free(af);
@@ -1968,11 +2095,11 @@
1968 {
1969 AioFile *af = Jim_CmdPrivData(interp);
1970 char buf[AIO_BUF_LEN];
1971 Jim_Obj *objPtr;
1972 int nonewline = 0;
1973 jim_wide neededLen = -1;
1974
1975 if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
1976 nonewline = 1;
1977 argv++;
1978 argc--;
@@ -2007,11 +2134,11 @@
2007 }
2008 }
2009 if (retval != readlen)
2010 break;
2011 }
2012
2013 if (JimCheckStreamError(interp, af)) {
2014 Jim_FreeNewObj(interp, objPtr);
2015 return JIM_ERR;
2016 }
2017 if (nonewline) {
@@ -2029,11 +2156,11 @@
2029
2030 AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
2031 {
2032 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2033
2034
2035 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2036 return (AioFile *) cmdPtr->u.native.privData;
2037 }
2038 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2039 return NULL;
@@ -2048,10 +2175,20 @@
2048 return NULL;
2049 }
2050
2051 return af->fp;
2052 }
 
 
 
 
 
 
 
 
 
 
2053
2054 static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2055 {
2056 AioFile *af = Jim_CmdPrivData(interp);
2057 jim_wide count = 0;
@@ -2110,21 +2247,21 @@
2110 }
2111 else {
2112 len = strlen(buf);
2113
2114 if (len && (buf[len - 1] == '\n')) {
2115
2116 len--;
2117 }
2118
2119 Jim_AppendString(interp, objPtr, buf, len);
2120 break;
2121 }
2122 }
2123
2124 if (JimCheckStreamError(interp, af)) {
2125
2126 Jim_FreeNewObj(interp, objPtr);
2127 return JIM_ERR;
2128 }
2129
2130 if (argc) {
@@ -2134,11 +2271,11 @@
2134 }
2135
2136 len = Jim_Length(objPtr);
2137
2138 if (len == 0 && feof(af->fp)) {
2139
2140 len = -1;
2141 }
2142 Jim_SetResultInt(interp, len);
2143 }
2144 else {
@@ -2207,11 +2344,11 @@
2207 }
2208
2209 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2210 {
2211 if (argc == 3) {
2212 #if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2213 static const char * const options[] = { "r", "w", NULL };
2214 enum { OPT_R, OPT_W, };
2215 int option;
2216 AioFile *af = Jim_CmdPrivData(interp);
2217
@@ -2297,10 +2434,11 @@
2297 }
2298 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2299 return JIM_OK;
2300 }
2301 #endif
 
2302
2303 #ifdef HAVE_FSYNC
2304 static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2305 {
2306 AioFile *af = Jim_CmdPrivData(interp);
@@ -2364,33 +2502,33 @@
2364
2365 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2366 int argc, Jim_Obj * const *argv)
2367 {
2368 if (argc == 0) {
2369
2370 if (*scriptHandlerObj) {
2371 Jim_SetResult(interp, *scriptHandlerObj);
2372 }
2373 return JIM_OK;
2374 }
2375
2376 if (*scriptHandlerObj) {
2377
2378 Jim_DeleteFileHandler(interp, af->fp, mask);
2379 }
2380
2381
2382 if (Jim_Length(argv[0]) == 0) {
2383
2384 return JIM_OK;
2385 }
2386
2387
2388 Jim_IncrRefCount(argv[0]);
2389 *scriptHandlerObj = argv[0];
2390
2391 Jim_CreateFileHandler(interp, af->fp, mask,
2392 JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
2393
2394 return JIM_OK;
2395 }
2396
@@ -2414,136 +2552,145 @@
2414
2415 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2416 }
2417 #endif
2418
 
 
2419
2420 static const jim_subcmd_type aio_command_table[] = {
2421 { "read",
2422 "?-nonewline? ?len?",
2423 aio_cmd_read,
2424 0,
2425 2,
2426
2427 },
2428 { "copyto",
2429 "handle ?size?",
2430 aio_cmd_copy,
2431 1,
2432 2,
2433
 
 
 
 
 
 
 
2434 },
2435 { "gets",
2436 "?var?",
2437 aio_cmd_gets,
2438 0,
2439 1,
2440
2441 },
2442 { "puts",
2443 "?-nonewline? str",
2444 aio_cmd_puts,
2445 1,
2446 2,
2447
2448 },
2449 { "isatty",
2450 NULL,
2451 aio_cmd_isatty,
2452 0,
2453 0,
2454
2455 },
2456 { "flush",
2457 NULL,
2458 aio_cmd_flush,
2459 0,
2460 0,
2461
2462 },
2463 { "eof",
2464 NULL,
2465 aio_cmd_eof,
2466 0,
2467 0,
2468
2469 },
2470 { "close",
2471 "?r(ead)|w(rite)?",
2472 aio_cmd_close,
2473 0,
2474 1,
2475 JIM_MODFLAG_FULLARGV,
2476
2477 },
2478 { "seek",
2479 "offset ?start|current|end",
2480 aio_cmd_seek,
2481 1,
2482 2,
2483
2484 },
2485 { "tell",
2486 NULL,
2487 aio_cmd_tell,
2488 0,
2489 0,
2490
2491 },
2492 { "filename",
2493 NULL,
2494 aio_cmd_filename,
2495 0,
2496 0,
2497
2498 },
2499 #ifdef O_NDELAY
2500 { "ndelay",
2501 "?0|1?",
2502 aio_cmd_ndelay,
2503 0,
2504 1,
2505
2506 },
2507 #endif
2508 #ifdef HAVE_FSYNC
2509 { "sync",
2510 NULL,
2511 aio_cmd_sync,
2512 0,
2513 0,
2514
2515 },
2516 #endif
2517 { "buffering",
2518 "none|line|full",
2519 aio_cmd_buffering,
2520 1,
2521 1,
2522
2523 },
2524 #ifdef jim_ext_eventloop
2525 { "readable",
2526 "?readable-script?",
2527 aio_cmd_readable,
2528 0,
2529 1,
2530
2531 },
2532 { "writable",
2533 "?writable-script?",
2534 aio_cmd_writable,
2535 0,
2536 1,
2537
2538 },
2539 { "onexception",
2540 "?exception-script?",
2541 aio_cmd_onexception,
2542 0,
2543 1,
2544
2545 },
2546 #endif
2547 { NULL }
2548 };
2549
@@ -2566,11 +2713,11 @@
2566
2567 #ifdef jim_ext_tclcompat
2568 {
2569 const char *filename = Jim_String(argv[1]);
2570
2571
2572 if (*filename == '|') {
2573 Jim_Obj *evalObj[3];
2574
2575 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2576 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2603,35 +2750,37 @@
2603 }
2604
2605 Jim_IncrRefCount(filename);
2606
2607 if (fh == NULL) {
2608 #if !defined(JIM_ANSIC)
2609 if (fd >= 0) {
 
2610 fh = fdopen(fd, mode);
 
2611 }
2612 else
2613 #endif
2614 fh = fopen(Jim_String(filename), mode);
2615
2616 if (fh == NULL) {
2617 JimAioSetError(interp, filename);
2618 #if !defined(JIM_ANSIC)
2619 if (fd >= 0) {
2620 close(fd);
2621 }
2622 #endif
2623 Jim_DecrRefCount(interp, filename);
2624 return NULL;
2625 }
2626 }
2627
2628
2629 af = Jim_Alloc(sizeof(*af));
2630 memset(af, 0, sizeof(*af));
2631 af->fp = fh;
 
2632 af->fd = fileno(fh);
 
2633 af->filename = filename;
2634 #ifdef FD_CLOEXEC
2635 if ((openFlags & AIO_KEEPOPEN) == 0) {
2636 (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2637 }
@@ -2653,72 +2802,45 @@
2653 const char *hdlfmt, int family, const char *mode[2])
2654 {
2655 if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
2656 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2657 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2658
2659 if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) {
2660 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2661 Jim_SetResult(interp, objPtr);
2662 return JIM_OK;
2663 }
2664 }
2665
2666
2667 close(p[0]);
2668 close(p[1]);
2669 JimAioSetError(interp, NULL);
2670 return JIM_ERR;
2671 }
2672 #endif
2673
2674
2675 int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2676 {
2677 #ifdef HAVE_MKSTEMP
2678 int fd;
2679 mode_t mask;
2680 Jim_Obj *filenameObj;
2681
2682 if (template == NULL) {
2683 const char *tmpdir = getenv("TMPDIR");
2684 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2685 tmpdir = "/tmp/";
2686 }
2687 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2688 if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2689 Jim_AppendString(interp, filenameObj, "/", 1);
2690 }
2691 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2692 }
2693 else {
2694 filenameObj = Jim_NewStringObj(interp, template, -1);
2695 }
2696
2697 #if defined(S_IRWXG) && defined(S_IRWXO)
2698 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2699 #else
2700
2701 mask = umask(S_IXUSR);
2702 #endif
2703
2704
2705 fd = mkstemp(filenameObj->bytes);
2706 umask(mask);
2707 if (fd < 0) {
2708 JimAioSetError(interp, filenameObj);
2709 Jim_FreeNewObj(interp, filenameObj);
2710 return -1;
2711 }
2712
2713 Jim_SetResult(interp, filenameObj);
2714 return fd;
2715 #else
2716 Jim_SetResultString(interp, "platform has no tempfile support", -1);
2717 return -1;
2718 #endif
2719 }
2720
2721
2722 int Jim_aioInit(Jim_Interp *interp)
2723 {
2724 if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
@@ -2727,15 +2849,18 @@
2727 #if defined(JIM_SSL)
2728 Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL);
2729 #endif
2730
2731 Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
2732 #ifndef JIM_ANSIC
2733 Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
2734 #endif
 
 
 
2735
2736
2737 JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
2738 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2739 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2740
2741 return JIM_OK;
@@ -2813,12 +2938,12 @@
2813 #include <regex.h>
2814 #endif
2815
2816 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2817 {
2818 regfree(objPtr->internalRep.regexpValue.compre);
2819 Jim_Free(objPtr->internalRep.regexpValue.compre);
2820 }
2821
2822 static const Jim_ObjType regexpObjType = {
2823 "regexp",
2824 FreeRegexpInternalRep,
@@ -2831,20 +2956,20 @@
2831 {
2832 regex_t *compre;
2833 const char *pattern;
2834 int ret;
2835
2836
2837 if (objPtr->typePtr == &regexpObjType &&
2838 objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
2839
2840 return objPtr->internalRep.regexpValue.compre;
2841 }
2842
2843
2844
2845
 
2846 pattern = Jim_String(objPtr);
2847 compre = Jim_Alloc(sizeof(regex_t));
2848
2849 if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
2850 char buf[100];
@@ -2857,12 +2982,12 @@
2857 }
2858
2859 Jim_FreeIntRep(interp, objPtr);
2860
2861 objPtr->typePtr = &regexpObjType;
2862 objPtr->internalRep.regexpValue.flags = flags;
2863 objPtr->internalRep.regexpValue.compre = compre;
2864
2865 return compre;
2866 }
2867
2868 int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3001,11 +3126,11 @@
3001 }
3002
3003 num_matches++;
3004
3005 if (opt_all && !opt_inline) {
3006
3007 goto try_next_match;
3008 }
3009
3010
3011 j = 0;
@@ -3041,11 +3166,11 @@
3041
3042 if (opt_inline) {
3043 Jim_ListAppendElement(interp, resultListObj, resultObj);
3044 }
3045 else {
3046
3047 result = Jim_SetVariable(interp, argv[i], resultObj);
3048
3049 if (result != JIM_OK) {
3050 Jim_FreeObj(interp, resultObj);
3051 break;
@@ -3168,11 +3293,11 @@
3168
3169 source_str = Jim_GetString(argv[i + 1], &source_len);
3170 replace_str = Jim_GetString(argv[i + 2], &replace_len);
3171 varname = argv[i + 3];
3172
3173
3174 resultObj = Jim_NewStringObj(interp, "", 0);
3175
3176 if (offset) {
3177 if (offset < 0) {
3178 offset += source_len + 1;
@@ -3183,11 +3308,11 @@
3183 else if (offset < 0) {
3184 offset = 0;
3185 }
3186 }
3187
3188
3189 Jim_AppendString(interp, resultObj, source_str, offset);
3190
3191
3192 n = source_len - offset;
3193 p = source_str + offset;
@@ -3242,23 +3367,23 @@
3242 }
3243
3244 p += pmatch[0].rm_eo;
3245 n -= pmatch[0].rm_eo;
3246
3247
3248 if (!opt_all || n == 0) {
3249 break;
3250 }
3251
3252
3253 if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
3254 break;
3255 }
3256
3257
3258 if (pattern[0] == '\0' && n) {
3259
3260 Jim_AppendString(interp, resultObj, p, 1);
3261 p++;
3262 n--;
3263 }
3264
@@ -3265,11 +3390,11 @@
3265 regexec_flags |= REG_NOTBOL;
3266 } while (n);
3267
3268 Jim_AppendString(interp, resultObj, p, -1);
3269
3270
3271 if (argc - i == 4) {
3272 result = Jim_SetVariable(interp, varname, resultObj);
3273
3274 if (result == JIM_OK) {
3275 Jim_SetResultInt(interp, num_matches);
@@ -3320,11 +3445,11 @@
3320
3321 # ifndef MAXPATHLEN
3322 # define MAXPATHLEN JIM_PATH_LEN
3323 # endif
3324
3325 #if defined(__MINGW32__) || defined(_MSC_VER)
3326 #define ISWINDOWS 1
3327 #else
3328 #define ISWINDOWS 0
3329 #endif
3330
@@ -3371,11 +3496,11 @@
3371 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
3372 }
3373
3374 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3375 {
3376
3377 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3378
3379 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3380 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3381 AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3512,38 @@
3387 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3388 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3389 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3390 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3391
3392
3393 if (varName) {
3394 Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
 
 
3395 if (objPtr) {
3396 if (Jim_DictSize(interp, objPtr) < 0) {
3397
 
 
 
 
 
 
3398 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3399 Jim_FreeNewObj(interp, listObj);
3400 return JIM_ERR;
3401 }
3402
3403 if (Jim_IsShared(objPtr))
3404 objPtr = Jim_DuplicateObj(interp, objPtr);
3405
3406
3407 Jim_ListAppendList(interp, objPtr, listObj);
3408 Jim_DictSize(interp, objPtr);
3409 Jim_InvalidateStringRep(objPtr);
3410
3411 Jim_FreeNewObj(interp, listObj);
3412 listObj = objPtr;
3413 }
3414 Jim_SetVariable(interp, varName, listObj);
3415 }
3416
3417
3418 Jim_SetResult(interp, listObj);
3419
3420 return JIM_OK;
3421 }
3422
@@ -3432,11 +3559,11 @@
3432 }
3433 else if (p == path) {
3434 Jim_SetResultString(interp, "/", -1);
3435 }
3436 else if (ISWINDOWS && p[-1] == ':') {
3437
3438 Jim_SetResultString(interp, path, p - path + 1);
3439 }
3440 else {
3441 Jim_SetResultString(interp, path, p - path);
3442 }
@@ -3512,35 +3639,35 @@
3512 char *newname = Jim_Alloc(MAXPATHLEN + 1);
3513 char *last = newname;
3514
3515 *newname = 0;
3516
3517
3518 for (i = 0; i < argc; i++) {
3519 int len;
3520 const char *part = Jim_GetString(argv[i], &len);
3521
3522 if (*part == '/') {
3523
3524 last = newname;
3525 }
3526 else if (ISWINDOWS && strchr(part, ':')) {
3527
3528 last = newname;
3529 }
3530 else if (part[0] == '.') {
3531 if (part[1] == '/') {
3532 part += 2;
3533 len -= 2;
3534 }
3535 else if (part[1] == 0 && last != newname) {
3536
3537 continue;
3538 }
3539 }
3540
3541
3542 if (last != newname && last[-1] != '/') {
3543 *last++ = '/';
3544 }
3545
3546 if (len) {
@@ -3551,22 +3678,22 @@
3551 }
3552 memcpy(last, part, len);
3553 last += len;
3554 }
3555
3556
3557 if (last > newname + 1 && last[-1] == '/') {
3558
3559 if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
3560 *--last = 0;
3561 }
3562 }
3563 }
3564
3565 *last = 0;
3566
3567
3568
3569 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
3570
3571 return JIM_OK;
3572 }
@@ -3591,11 +3718,11 @@
3591 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3592 {
3593 #ifdef X_OK
3594 return file_access(interp, argv[0], X_OK);
3595 #else
3596
3597 Jim_SetResultBool(interp, 1);
3598 return JIM_OK;
3599 #endif
3600 }
3601
@@ -3616,11 +3743,11 @@
3616 while (argc--) {
3617 const char *path = Jim_String(argv[0]);
3618
3619 if (unlink(path) == -1 && errno != ENOENT) {
3620 if (rmdir(path) == -1) {
3621
3622 if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
3623 Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
3624 strerror(errno));
3625 return JIM_ERR;
3626 }
@@ -3639,15 +3766,15 @@
3639
3640 static int mkdir_all(char *path)
3641 {
3642 int ok = 1;
3643
3644
3645 goto first;
3646
3647 while (ok--) {
3648
3649 {
3650 char *slash = strrchr(path, '/');
3651
3652 if (slash && slash != path) {
3653 *slash = 0;
@@ -3660,24 +3787,24 @@
3660 first:
3661 if (MKDIR_DEFAULT(path) == 0) {
3662 return 0;
3663 }
3664 if (errno == ENOENT) {
3665
3666 continue;
3667 }
3668
3669 if (errno == EEXIST) {
3670 struct stat sb;
3671
3672 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
3673 return 0;
3674 }
3675
3676 errno = EEXIST;
3677 }
3678
3679 break;
3680 }
3681 return -1;
3682 }
3683
@@ -3698,11 +3825,11 @@
3698 return JIM_OK;
3699 }
3700
3701 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3702 {
3703 int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3704
3705 if (fd < 0) {
3706 return JIM_ERR;
3707 }
3708 close(fd);
@@ -3962,192 +4089,192 @@
3962 { "atime",
3963 "name",
3964 file_cmd_atime,
3965 1,
3966 1,
3967
3968 },
3969 { "mtime",
3970 "name ?time?",
3971 file_cmd_mtime,
3972 1,
3973 2,
3974
3975 },
3976 { "copy",
3977 "?-force? source dest",
3978 file_cmd_copy,
3979 2,
3980 3,
3981
3982 },
3983 { "dirname",
3984 "name",
3985 file_cmd_dirname,
3986 1,
3987 1,
3988
3989 },
3990 { "rootname",
3991 "name",
3992 file_cmd_rootname,
3993 1,
3994 1,
3995
3996 },
3997 { "extension",
3998 "name",
3999 file_cmd_extension,
4000 1,
4001 1,
4002
4003 },
4004 { "tail",
4005 "name",
4006 file_cmd_tail,
4007 1,
4008 1,
4009
4010 },
4011 { "normalize",
4012 "name",
4013 file_cmd_normalize,
4014 1,
4015 1,
4016
4017 },
4018 { "join",
4019 "name ?name ...?",
4020 file_cmd_join,
4021 1,
4022 -1,
4023
4024 },
4025 { "readable",
4026 "name",
4027 file_cmd_readable,
4028 1,
4029 1,
4030
4031 },
4032 { "writable",
4033 "name",
4034 file_cmd_writable,
4035 1,
4036 1,
4037
4038 },
4039 { "executable",
4040 "name",
4041 file_cmd_executable,
4042 1,
4043 1,
4044
4045 },
4046 { "exists",
4047 "name",
4048 file_cmd_exists,
4049 1,
4050 1,
4051
4052 },
4053 { "delete",
4054 "?-force|--? name ...",
4055 file_cmd_delete,
4056 1,
4057 -1,
4058
4059 },
4060 { "mkdir",
4061 "dir ...",
4062 file_cmd_mkdir,
4063 1,
4064 -1,
4065
4066 },
4067 { "tempfile",
4068 "?template?",
4069 file_cmd_tempfile,
4070 0,
4071 1,
4072
4073 },
4074 { "rename",
4075 "?-force? source dest",
4076 file_cmd_rename,
4077 2,
4078 3,
4079
4080 },
4081 #if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
4082 { "link",
4083 "?-symbolic|-hard? newname target",
4084 file_cmd_link,
4085 2,
4086 3,
4087
4088 },
4089 #endif
4090 #if defined(HAVE_READLINK)
4091 { "readlink",
4092 "name",
4093 file_cmd_readlink,
4094 1,
4095 1,
4096
4097 },
4098 #endif
4099 { "size",
4100 "name",
4101 file_cmd_size,
4102 1,
4103 1,
4104
4105 },
4106 { "stat",
4107 "name ?var?",
4108 file_cmd_stat,
4109 1,
4110 2,
4111
4112 },
4113 { "lstat",
4114 "name ?var?",
4115 file_cmd_lstat,
4116 1,
4117 2,
4118
4119 },
4120 { "type",
4121 "name",
4122 file_cmd_type,
4123 1,
4124 1,
4125
4126 },
4127 #ifdef HAVE_GETEUID
4128 { "owned",
4129 "name",
4130 file_cmd_owned,
4131 1,
4132 1,
4133
4134 },
4135 #endif
4136 { "isdirectory",
4137 "name",
4138 file_cmd_isdirectory,
4139 1,
4140 1,
4141
4142 },
4143 { "isfile",
4144 "name",
4145 file_cmd_isfile,
4146 1,
4147 1,
4148
4149 },
4150 {
4151 NULL
4152 }
4153 };
@@ -4179,11 +4306,11 @@
4179 Jim_SetResultString(interp, "Failed to get pwd", -1);
4180 Jim_Free(cwd);
4181 return JIM_ERR;
4182 }
4183 else if (ISWINDOWS) {
4184
4185 char *p = cwd;
4186 while ((p = strchr(p, '\\')) != NULL) {
4187 *p++ = '/';
4188 }
4189 }
@@ -4203,10 +4330,13 @@
4203 Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
4204 Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
4205 return JIM_OK;
4206 }
4207
 
 
 
4208 #include <string.h>
4209 #include <ctype.h>
4210
4211
4212 #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4344,20 @@
4214 {
4215 Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
4216 int i, j;
4217 int rc;
4218
4219
4220 for (i = 1; i < argc; i++) {
4221 int len;
4222 const char *arg = Jim_GetString(argv[i], &len);
4223
4224 if (i > 1) {
4225 Jim_AppendString(interp, cmdlineObj, " ", 1);
4226 }
4227 if (strpbrk(arg, "\\\" ") == NULL) {
4228
4229 Jim_AppendString(interp, cmdlineObj, arg, len);
4230 continue;
4231 }
4232
4233 Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4266,86 +4396,26 @@
4266 #else
4267
4268
4269 #include <errno.h>
4270 #include <signal.h>
4271
4272 #if defined(__MINGW32__)
4273
4274 #ifndef STRICT
4275 #define STRICT
4276 #endif
4277 #define WIN32_LEAN_AND_MEAN
4278 #include <windows.h>
4279 #include <fcntl.h>
4280
4281 typedef HANDLE fdtype;
4282 typedef HANDLE pidtype;
4283 #define JIM_BAD_FD INVALID_HANDLE_VALUE
4284 #define JIM_BAD_PID INVALID_HANDLE_VALUE
4285 #define JimCloseFd CloseHandle
4286
4287 #define WIFEXITED(STATUS) 1
4288 #define WEXITSTATUS(STATUS) (STATUS)
4289 #define WIFSIGNALED(STATUS) 0
4290 #define WTERMSIG(STATUS) 0
4291 #define WNOHANG 1
4292
4293 static fdtype JimFileno(FILE *fh);
4294 static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
4295 static fdtype JimDupFd(fdtype infd);
4296 static fdtype JimOpenForRead(const char *filename);
4297 static FILE *JimFdOpenForRead(fdtype fd);
4298 static int JimPipe(fdtype pipefd[2]);
4299 static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
4300 fdtype inputId, fdtype outputId, fdtype errorId);
4301 static int JimErrno(void);
4302 #else
4303 #include <unistd.h>
4304 #include <fcntl.h>
4305 #include <sys/wait.h>
4306 #include <sys/stat.h>
4307
4308 typedef int fdtype;
4309 typedef int pidtype;
4310 #define JimPipe pipe
4311 #define JimErrno() errno
4312 #define JIM_BAD_FD -1
4313 #define JIM_BAD_PID -1
4314 #define JimFileno fileno
4315 #define JimReadFd read
4316 #define JimCloseFd close
4317 #define JimWaitPid waitpid
4318 #define JimDupFd dup
4319 #define JimFdOpenForRead(FD) fdopen((FD), "r")
4320 #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
4321
4322 #ifndef HAVE_EXECVPE
4323 #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
4324 #endif
4325 #endif
4326
4327 static const char *JimStrError(void);
4328 static char **JimSaveEnv(char **env);
4329 static void JimRestoreEnv(char **env);
4330 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4331 pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4332 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
4333 static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj);
4334 static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
4335 static fdtype JimOpenForWrite(const char *filename, int append);
4336 static int JimRewindFd(fdtype fd);
4337
4338 static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
4339 {
4340 Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
4341 }
4342
4343 static const char *JimStrError(void)
4344 {
4345 return strerror(JimErrno());
4346 }
4347
4348 static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
4349 {
4350 int len;
4351 const char *s = Jim_GetString(objPtr, &len);
@@ -4354,14 +4424,14 @@
4354 objPtr->length--;
4355 objPtr->bytes[objPtr->length] = '\0';
4356 }
4357 }
4358
4359 static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj)
4360 {
4361 char buf[256];
4362 FILE *fh = JimFdOpenForRead(fd);
4363 int ret = 0;
4364
4365 if (fh == NULL) {
4366 return -1;
4367 }
@@ -4390,18 +4460,18 @@
4390 char *envdata;
4391
4392 Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
4393
4394 if (!objPtr) {
4395 return Jim_GetEnviron();
4396 }
4397
4398
4399
4400 num = Jim_ListLength(interp, objPtr);
4401 if (num % 2) {
4402
4403 num--;
4404 }
4405 size = Jim_Length(objPtr) + 2;
4406
4407 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4433,79 +4503,76 @@
4433 if (env != original_environ) {
4434 Jim_Free(env);
4435 }
4436 }
4437
4438 #ifndef jim_ext_signal
4439
4440 const char *Jim_SignalId(int sig)
4441 {
4442 static char buf[10];
4443 snprintf(buf, sizeof(buf), "%d", sig);
4444 return buf;
4445 }
4446
4447 const char *Jim_SignalName(int sig)
4448 {
4449 return Jim_SignalId(sig);
4450 }
4451 #endif
4452
4453 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4454 {
4455 Jim_Obj *errorCode;
4456
4457 if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
4458 return JIM_OK;
4459 }
4460 errorCode = Jim_NewListObj(interp, NULL, 0);
4461
4462 if (WIFEXITED(waitStatus)) {
4463 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
4464 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4465 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
4466 }
4467 else {
4468 const char *type;
4469 const char *action;
 
4470
4471 if (WIFSIGNALED(waitStatus)) {
4472 type = "CHILDKILLED";
4473 action = "killed";
 
4474 }
4475 else {
4476 type = "CHILDSUSP";
4477 action = "suspended";
 
4478 }
4479
4480 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
4481
4482 if (errStrObj) {
4483 Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL);
4484 }
4485
4486 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4487 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1));
4488 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1));
4489 }
4490 Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
 
 
 
 
 
 
 
 
4491
4492 return JIM_ERR;
4493 }
4494
4495
4496 struct WaitInfo
4497 {
4498 pidtype pid;
4499 int status;
4500 int flags;
4501 };
 
4502
4503 struct WaitInfoTable {
4504 struct WaitInfo *info;
4505 int size;
4506 int used;
 
4507 };
4508
4509
4510 #define WI_DETACHED 2
4511
@@ -4513,32 +4580,53 @@
4513
4514 static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData)
4515 {
4516 struct WaitInfoTable *table = privData;
4517
4518 Jim_Free(table->info);
4519 Jim_Free(table);
 
 
4520 }
4521
4522 static struct WaitInfoTable *JimAllocWaitInfoTable(void)
4523 {
4524 struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
4525 table->info = NULL;
4526 table->size = table->used = 0;
 
4527
4528 return table;
4529 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4530
4531 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4532 {
4533 fdtype outputId;
4534 fdtype errorId;
4535 pidtype *pidPtr;
4536 int numPids, result;
4537 int child_siginfo = 1;
4538 Jim_Obj *childErrObj;
4539 Jim_Obj *errStrObj;
 
4540
4541 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4542 Jim_Obj *listObj;
4543 int i;
4544
@@ -4545,17 +4633,17 @@
4545 argc--;
4546 numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
4547 if (numPids < 0) {
4548 return JIM_ERR;
4549 }
4550
4551 listObj = Jim_NewListObj(interp, NULL, 0);
4552 for (i = 0; i < numPids; i++) {
4553 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
4554 }
4555 Jim_SetResult(interp, listObj);
4556 JimDetachPids(interp, numPids, pidPtr);
4557 Jim_Free(pidPtr);
4558 return JIM_OK;
4559 }
4560
4561 numPids =
@@ -4567,54 +4655,98 @@
4567
4568 result = JIM_OK;
4569
4570 errStrObj = Jim_NewStringObj(interp, "", 0);
4571
4572
4573 if (outputId != JIM_BAD_FD) {
4574 if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
4575 result = JIM_ERR;
4576 Jim_SetResultErrno(interp, "error reading from output pipe");
4577 }
4578 }
4579
4580
4581 childErrObj = Jim_NewStringObj(interp, "", 0);
4582 Jim_IncrRefCount(childErrObj);
4583
4584 if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
4585 result = JIM_ERR;
4586 }
4587
4588 if (errorId != JIM_BAD_FD) {
4589 int ret;
4590 JimRewindFd(errorId);
4591 ret = JimAppendStreamToString(interp, errorId, errStrObj);
4592 if (ret < 0) {
4593 Jim_SetResultErrno(interp, "error reading from error pipe");
4594 result = JIM_ERR;
4595 }
4596 else if (ret > 0) {
4597
4598 child_siginfo = 0;
4599 }
4600 }
4601
4602 if (child_siginfo) {
4603
4604 Jim_AppendObj(interp, errStrObj, childErrObj);
4605 }
4606 Jim_DecrRefCount(interp, childErrObj);
4607
4608
4609 Jim_RemoveTrailingNewline(errStrObj);
4610
4611
4612 Jim_SetResult(interp, errStrObj);
4613
4614 return result;
4615 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4616
4617 static void JimReapDetachedPids(struct WaitInfoTable *table)
4618 {
4619 struct WaitInfo *waitPtr;
4620 int count;
@@ -4627,13 +4759,13 @@
4627 waitPtr = table->info;
4628 dest = 0;
4629 for (count = table->used; count > 0; waitPtr++, count--) {
4630 if (waitPtr->flags & WI_DETACHED) {
4631 int status;
4632 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4633 if (pid == waitPtr->pid) {
4634
4635 table->used--;
4636 continue;
4637 }
4638 }
4639 if (waitPtr != &table->info[dest]) {
@@ -4641,66 +4773,62 @@
4641 }
4642 dest++;
4643 }
4644 }
4645
4646 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4647 {
4648 int i;
4649
4650
4651 for (i = 0; i < table->used; i++) {
4652 if (pid == table->info[i].pid) {
4653
4654 JimWaitPid(pid, statusPtr, 0);
4655
4656
4657 if (i != table->used - 1) {
4658 table->info[i] = table->info[table->used - 1];
4659 }
4660 table->used--;
4661 return pid;
4662 }
4663 }
4664
4665
4666 return JIM_BAD_PID;
4667 }
4668
4669 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4670 {
4671 int j;
4672 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4673
4674 for (j = 0; j < numPids; j++) {
4675
4676 int i;
4677 for (i = 0; i < table->used; i++) {
4678 if (pidPtr[j] == table->info[i].pid) {
4679 table->info[i].flags |= WI_DETACHED;
4680 break;
4681 }
4682 }
4683 }
4684 }
4685
4686 static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name)
4687 {
4688 FILE *fh;
4689 Jim_Obj *fhObj;
4690
4691 fhObj = Jim_NewStringObj(interp, name, -1);
4692 Jim_IncrRefCount(fhObj);
4693 fh = Jim_AioFilehandle(interp, fhObj);
4694 Jim_DecrRefCount(interp, fhObj);
4695
4696 return fh;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4697 }
4698
4699 static int
4700 JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
4701 fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
4702 {
4703 pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all
4704 * the pids of child processes. */
4705 int numPids = 0; /* Actual number of processes that exist
4706 * at *pidPtr right now. */
@@ -4707,16 +4835,16 @@
4707 int cmdCount; /* Count of number of distinct commands
4708 * found in argc/argv. */
4709 const char *input = NULL; /* Describes input for pipeline, depending
4710 * on "inputFile". NULL means take input
4711 * from stdin/pipe. */
4712 int input_len = 0;
4713
4714 #define FILE_NAME 0
4715 #define FILE_APPEND 1
4716 #define FILE_HANDLE 2
4717 #define FILE_TEXT 3
4718
4719 int inputFile = FILE_NAME; /* 1 means input is name of input file.
4720 * 2 means input is filehandle name.
4721 * 0 means input holds actual
4722 * text to be input to command. */
@@ -4733,39 +4861,37 @@
4733 */
4734 const char *output = NULL; /* Holds name of output file to pipe to,
4735 * or NULL if output goes to stdout/pipe. */
4736 const char *error = NULL; /* Holds name of stderr file to pipe to,
4737 * or NULL if stderr goes to stderr/pipe. */
4738 fdtype inputId = JIM_BAD_FD;
4739 fdtype outputId = JIM_BAD_FD;
4740 fdtype errorId = JIM_BAD_FD;
4741 fdtype lastOutputId = JIM_BAD_FD;
4742 fdtype pipeIds[2];
4743 int firstArg, lastArg; /* Indexes of first and last arguments in
4744 * current command. */
4745 int lastBar;
4746 int i;
4747 pidtype pid;
4748 char **save_environ;
4749 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4750
4751
4752 char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
4753 int arg_count = 0;
4754
4755 JimReapDetachedPids(table);
4756
4757 if (inPipePtr != NULL) {
4758 *inPipePtr = JIM_BAD_FD;
4759 }
4760 if (outPipePtr != NULL) {
4761 *outPipePtr = JIM_BAD_FD;
4762 }
4763 if (errFilePtr != NULL) {
4764 *errFilePtr = JIM_BAD_FD;
4765 }
4766 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4767
4768 cmdCount = 1;
4769 lastBar = -1;
4770 for (i = 0; i < argc; i++) {
4771 const char *arg = Jim_String(argv[i]);
@@ -4796,11 +4922,11 @@
4796 if (*output == '>') {
4797 outputFile = FILE_APPEND;
4798 output++;
4799 }
4800 if (*output == '&') {
4801
4802 output++;
4803 dup_error = 1;
4804 }
4805 if (*output == '@') {
4806 outputFile = FILE_HANDLE;
@@ -4837,11 +4963,11 @@
4837 goto badargs;
4838 }
4839 lastBar = i;
4840 cmdCount++;
4841 }
4842
4843 arg_array[arg_count++] = (char *)arg;
4844 continue;
4845 }
4846
4847 if (i >= argc) {
@@ -4855,150 +4981,160 @@
4855 badargs:
4856 Jim_Free(arg_array);
4857 return -1;
4858 }
4859
4860
4861 save_environ = JimSaveEnv(JimBuildEnv(interp));
4862
4863 if (input != NULL) {
4864 if (inputFile == FILE_TEXT) {
4865 inputId = JimCreateTemp(interp, input, input_len);
4866 if (inputId == JIM_BAD_FD) {
 
 
 
 
 
4867 goto error;
4868 }
 
4869 }
4870 else if (inputFile == FILE_HANDLE) {
4871
4872 FILE *fh = JimGetAioFilehandle(interp, input);
4873
4874 if (fh == NULL) {
4875 goto error;
4876 }
4877 inputId = JimDupFd(JimFileno(fh));
4878 }
4879 else {
4880 inputId = JimOpenForRead(input);
4881 if (inputId == JIM_BAD_FD) {
4882 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
4883 goto error;
4884 }
4885 }
4886 }
4887 else if (inPipePtr != NULL) {
4888 if (JimPipe(pipeIds) != 0) {
4889 Jim_SetResultErrno(interp, "couldn't create input pipe for command");
4890 goto error;
4891 }
4892 inputId = pipeIds[0];
4893 *inPipePtr = pipeIds[1];
4894 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4895 }
4896
4897 if (output != NULL) {
4898 if (outputFile == FILE_HANDLE) {
4899 FILE *fh = JimGetAioFilehandle(interp, output);
4900 if (fh == NULL) {
4901 goto error;
4902 }
4903 fflush(fh);
4904 lastOutputId = JimDupFd(JimFileno(fh));
4905 }
4906 else {
4907 lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
4908 if (lastOutputId == JIM_BAD_FD) {
4909 Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
4910 goto error;
4911 }
4912 }
4913 }
4914 else if (outPipePtr != NULL) {
4915 if (JimPipe(pipeIds) != 0) {
4916 Jim_SetResultErrno(interp, "couldn't create output pipe");
4917 goto error;
4918 }
4919 lastOutputId = pipeIds[1];
4920 *outPipePtr = pipeIds[0];
4921 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4922 }
4923
4924 if (error != NULL) {
4925 if (errorFile == FILE_HANDLE) {
4926 if (strcmp(error, "1") == 0) {
4927
4928 if (lastOutputId != JIM_BAD_FD) {
4929 errorId = JimDupFd(lastOutputId);
4930 }
4931 else {
4932
4933 error = "stdout";
4934 }
4935 }
4936 if (errorId == JIM_BAD_FD) {
4937 FILE *fh = JimGetAioFilehandle(interp, error);
4938 if (fh == NULL) {
4939 goto error;
4940 }
4941 fflush(fh);
4942 errorId = JimDupFd(JimFileno(fh));
4943 }
4944 }
4945 else {
4946 errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
4947 if (errorId == JIM_BAD_FD) {
4948 Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
4949 goto error;
4950 }
4951 }
4952 }
4953 else if (errFilePtr != NULL) {
4954 errorId = JimCreateTemp(interp, NULL, 0);
4955 if (errorId == JIM_BAD_FD) {
4956 goto error;
4957 }
4958 *errFilePtr = JimDupFd(errorId);
4959 }
4960
4961
4962 pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
4963 for (i = 0; i < numPids; i++) {
4964 pidPtr[i] = JIM_BAD_PID;
4965 }
4966 for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
4967 int pipe_dup_err = 0;
4968 fdtype origErrorId = errorId;
4969
4970 for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
4971 if (arg_array[lastArg][0] == '|') {
4972 if (arg_array[lastArg][1] == '&') {
4973 pipe_dup_err = 1;
4974 }
 
4975 break;
4976 }
4977 }
4978
 
 
 
 
 
 
4979 arg_array[lastArg] = NULL;
4980 if (lastArg == arg_count) {
4981 outputId = lastOutputId;
4982 }
4983 else {
4984 if (JimPipe(pipeIds) != 0) {
4985 Jim_SetResultErrno(interp, "couldn't create pipe");
4986 goto error;
4987 }
4988 outputId = pipeIds[1];
4989 }
4990
4991
4992 if (pipe_dup_err) {
4993 errorId = outputId;
4994 }
4995
4996
4997
4998 #ifdef __MINGW32__
4999 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
5000 if (pid == JIM_BAD_PID) {
5001 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
5002 goto error;
5003 }
5004 #else
@@ -5006,32 +5142,37 @@
5006 if (pid < 0) {
5007 Jim_SetResultErrno(interp, "couldn't fork child process");
5008 goto error;
5009 }
5010 if (pid == 0) {
5011
5012
5013 if (inputId != -1) dup2(inputId, 0);
5014 if (outputId != -1) dup2(outputId, 1);
5015 if (errorId != -1) dup2(errorId, 2);
5016
5017 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
5018 close(i);
5019 }
5020
5021
5022 (void)signal(SIGPIPE, SIG_DFL);
5023
5024 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
5025
5026
5027 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
 
 
 
 
 
 
 
5028 _exit(127);
5029 }
5030 #endif
5031
5032
5033
5034 if (table->used == table->size) {
5035 table->size += WAIT_TABLE_GROW_BY;
5036 table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
5037 }
@@ -5040,66 +5181,67 @@
5040 table->info[table->used].flags = 0;
5041 table->used++;
5042
5043 pidPtr[numPids] = pid;
5044
5045
5046 errorId = origErrorId;
5047
5048
5049 if (inputId != JIM_BAD_FD) {
5050 JimCloseFd(inputId);
5051 }
5052 if (outputId != JIM_BAD_FD) {
5053 JimCloseFd(outputId);
 
5054 }
5055 inputId = pipeIds[0];
5056 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5057 }
5058 *pidArrayPtr = pidPtr;
5059
5060
5061 cleanup:
5062 if (inputId != JIM_BAD_FD) {
5063 JimCloseFd(inputId);
5064 }
5065 if (lastOutputId != JIM_BAD_FD) {
5066 JimCloseFd(lastOutputId);
5067 }
5068 if (errorId != JIM_BAD_FD) {
5069 JimCloseFd(errorId);
5070 }
5071 Jim_Free(arg_array);
5072
5073 JimRestoreEnv(save_environ);
5074
5075 return numPids;
5076
5077
5078 error:
5079 if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
5080 JimCloseFd(*inPipePtr);
5081 *inPipePtr = JIM_BAD_FD;
5082 }
5083 if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
5084 JimCloseFd(*outPipePtr);
5085 *outPipePtr = JIM_BAD_FD;
5086 }
5087 if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
5088 JimCloseFd(*errFilePtr);
5089 *errFilePtr = JIM_BAD_FD;
5090 }
5091 if (pipeIds[0] != JIM_BAD_FD) {
5092 JimCloseFd(pipeIds[0]);
5093 }
5094 if (pipeIds[1] != JIM_BAD_FD) {
5095 JimCloseFd(pipeIds[1]);
5096 }
5097 if (pidPtr != NULL) {
5098 for (i = 0; i < numPids; i++) {
5099 if (pidPtr[i] != JIM_BAD_PID) {
5100 JimDetachPids(interp, 1, &pidPtr[i]);
5101 }
5102 }
5103 Jim_Free(pidPtr);
5104 }
5105 numPids = -1;
@@ -5111,11 +5253,11 @@
5111 {
5112 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
5113 int result = JIM_OK;
5114 int i;
5115
5116
5117 for (i = 0; i < numPids; i++) {
5118 int waitStatus = 0;
5119 if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
5120 if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
5121 result = JIM_ERR;
@@ -5127,234 +5269,30 @@
5127 return result;
5128 }
5129
5130 int Jim_execInit(Jim_Interp *interp)
5131 {
 
5132 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
5133 return JIM_ERR;
5134
5135 #ifdef SIGPIPE
5136 (void)signal(SIGPIPE, SIG_IGN);
5137 #endif
5138
5139 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
 
 
 
 
 
5140 return JIM_OK;
5141 }
5142
5143 #if defined(__MINGW32__)
5144
5145
5146 static SECURITY_ATTRIBUTES *JimStdSecAttrs(void)
5147 {
5148 static SECURITY_ATTRIBUTES secAtts;
5149
5150 secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
5151 secAtts.lpSecurityDescriptor = NULL;
5152 secAtts.bInheritHandle = TRUE;
5153 return &secAtts;
5154 }
5155
5156 static int JimErrno(void)
5157 {
5158 switch (GetLastError()) {
5159 case ERROR_FILE_NOT_FOUND: return ENOENT;
5160 case ERROR_PATH_NOT_FOUND: return ENOENT;
5161 case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
5162 case ERROR_ACCESS_DENIED: return EACCES;
5163 case ERROR_INVALID_HANDLE: return EBADF;
5164 case ERROR_BAD_ENVIRONMENT: return E2BIG;
5165 case ERROR_BAD_FORMAT: return ENOEXEC;
5166 case ERROR_INVALID_ACCESS: return EACCES;
5167 case ERROR_INVALID_DRIVE: return ENOENT;
5168 case ERROR_CURRENT_DIRECTORY: return EACCES;
5169 case ERROR_NOT_SAME_DEVICE: return EXDEV;
5170 case ERROR_NO_MORE_FILES: return ENOENT;
5171 case ERROR_WRITE_PROTECT: return EROFS;
5172 case ERROR_BAD_UNIT: return ENXIO;
5173 case ERROR_NOT_READY: return EBUSY;
5174 case ERROR_BAD_COMMAND: return EIO;
5175 case ERROR_CRC: return EIO;
5176 case ERROR_BAD_LENGTH: return EIO;
5177 case ERROR_SEEK: return EIO;
5178 case ERROR_WRITE_FAULT: return EIO;
5179 case ERROR_READ_FAULT: return EIO;
5180 case ERROR_GEN_FAILURE: return EIO;
5181 case ERROR_SHARING_VIOLATION: return EACCES;
5182 case ERROR_LOCK_VIOLATION: return EACCES;
5183 case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
5184 case ERROR_HANDLE_DISK_FULL: return ENOSPC;
5185 case ERROR_NOT_SUPPORTED: return ENODEV;
5186 case ERROR_REM_NOT_LIST: return EBUSY;
5187 case ERROR_DUP_NAME: return EEXIST;
5188 case ERROR_BAD_NETPATH: return ENOENT;
5189 case ERROR_NETWORK_BUSY: return EBUSY;
5190 case ERROR_DEV_NOT_EXIST: return ENODEV;
5191 case ERROR_TOO_MANY_CMDS: return EAGAIN;
5192 case ERROR_ADAP_HDW_ERR: return EIO;
5193 case ERROR_BAD_NET_RESP: return EIO;
5194 case ERROR_UNEXP_NET_ERR: return EIO;
5195 case ERROR_NETNAME_DELETED: return ENOENT;
5196 case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
5197 case ERROR_BAD_DEV_TYPE: return ENODEV;
5198 case ERROR_BAD_NET_NAME: return ENOENT;
5199 case ERROR_TOO_MANY_NAMES: return ENFILE;
5200 case ERROR_TOO_MANY_SESS: return EIO;
5201 case ERROR_SHARING_PAUSED: return EAGAIN;
5202 case ERROR_REDIR_PAUSED: return EAGAIN;
5203 case ERROR_FILE_EXISTS: return EEXIST;
5204 case ERROR_CANNOT_MAKE: return ENOSPC;
5205 case ERROR_OUT_OF_STRUCTURES: return ENFILE;
5206 case ERROR_ALREADY_ASSIGNED: return EEXIST;
5207 case ERROR_INVALID_PASSWORD: return EPERM;
5208 case ERROR_NET_WRITE_FAULT: return EIO;
5209 case ERROR_NO_PROC_SLOTS: return EAGAIN;
5210 case ERROR_DISK_CHANGE: return EXDEV;
5211 case ERROR_BROKEN_PIPE: return EPIPE;
5212 case ERROR_OPEN_FAILED: return ENOENT;
5213 case ERROR_DISK_FULL: return ENOSPC;
5214 case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
5215 case ERROR_INVALID_TARGET_HANDLE: return EBADF;
5216 case ERROR_INVALID_NAME: return ENOENT;
5217 case ERROR_PROC_NOT_FOUND: return ESRCH;
5218 case ERROR_WAIT_NO_CHILDREN: return ECHILD;
5219 case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
5220 case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
5221 case ERROR_SEEK_ON_DEVICE: return ESPIPE;
5222 case ERROR_BUSY_DRIVE: return EAGAIN;
5223 case ERROR_DIR_NOT_EMPTY: return EEXIST;
5224 case ERROR_NOT_LOCKED: return EACCES;
5225 case ERROR_BAD_PATHNAME: return ENOENT;
5226 case ERROR_LOCK_FAILED: return EACCES;
5227 case ERROR_ALREADY_EXISTS: return EEXIST;
5228 case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
5229 case ERROR_BAD_PIPE: return EPIPE;
5230 case ERROR_PIPE_BUSY: return EAGAIN;
5231 case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
5232 case ERROR_DIRECTORY: return ENOTDIR;
5233 }
5234 return EINVAL;
5235 }
5236
5237 static int JimPipe(fdtype pipefd[2])
5238 {
5239 if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) {
5240 return 0;
5241 }
5242 return -1;
5243 }
5244
5245 static fdtype JimDupFd(fdtype infd)
5246 {
5247 fdtype dupfd;
5248 pidtype pid = GetCurrentProcess();
5249
5250 if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
5251 return dupfd;
5252 }
5253 return JIM_BAD_FD;
5254 }
5255
5256 static int JimRewindFd(fdtype fd)
5257 {
5258 return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0;
5259 }
5260
5261 #if 0
5262 static int JimReadFd(fdtype fd, char *buffer, size_t len)
5263 {
5264 DWORD num;
5265
5266 if (ReadFile(fd, buffer, len, &num, NULL)) {
5267 return num;
5268 }
5269 if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) {
5270 return 0;
5271 }
5272 return -1;
5273 }
5274 #endif
5275
5276 static FILE *JimFdOpenForRead(fdtype fd)
5277 {
5278 return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r");
5279 }
5280
5281 static fdtype JimFileno(FILE *fh)
5282 {
5283 return (fdtype)_get_osfhandle(_fileno(fh));
5284 }
5285
5286 static fdtype JimOpenForRead(const char *filename)
5287 {
5288 return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
5289 JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
5290 }
5291
5292 static fdtype JimOpenForWrite(const char *filename, int append)
5293 {
5294 return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5295 JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
5296 }
5297
5298 static FILE *JimFdOpenForWrite(fdtype fd)
5299 {
5300 return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
5301 }
5302
5303 static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
5304 {
5305 DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
5306 if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
5307
5308 return JIM_BAD_PID;
5309 }
5310 GetExitCodeProcess(pid, &ret);
5311 *status = ret;
5312 CloseHandle(pid);
5313 return pid;
5314 }
5315
5316 static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5317 {
5318 char name[MAX_PATH];
5319 HANDLE handle;
5320
5321 if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
5322 return JIM_BAD_FD;
5323 }
5324
5325 handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(),
5326 CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
5327 NULL);
5328
5329 if (handle == INVALID_HANDLE_VALUE) {
5330 goto error;
5331 }
5332
5333 if (contents != NULL) {
5334
5335 FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
5336 if (fh == NULL) {
5337 goto error;
5338 }
5339
5340 if (fwrite(contents, len, 1, fh) != 1) {
5341 fclose(fh);
5342 goto error;
5343 }
5344 fseek(fh, 0, SEEK_SET);
5345 fclose(fh);
5346 }
5347 return handle;
5348
5349 error:
5350 Jim_SetResultErrno(interp, "failed to create temp file");
5351 CloseHandle(handle);
5352 DeleteFile(name);
5353 return JIM_BAD_FD;
5354 }
5355
5356 static int
5357 JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
5358 {
5359 int i;
5360 static char extensions[][5] = {".exe", "", ".bat"};
@@ -5381,10 +5319,15 @@
5381
5382 static void JimRestoreEnv(char **env)
5383 {
5384 JimFreeEnv(env, Jim_GetEnviron());
5385 }
 
 
 
 
 
5386
5387 static Jim_Obj *
5388 JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
5389 {
5390 char *start, *special;
@@ -5455,18 +5398,19 @@
5455 }
5456 return strObj;
5457 }
5458
5459 static pidtype
5460 JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
5461 {
5462 STARTUPINFO startInfo;
5463 PROCESS_INFORMATION procInfo;
5464 HANDLE hProcess, h;
5465 char execPath[MAX_PATH];
5466 pidtype pid = JIM_BAD_PID;
5467 Jim_Obj *cmdLineObj;
 
5468
5469 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5470 return JIM_BAD_PID;
5471 }
5472 argv[0] = execPath;
@@ -5480,47 +5424,51 @@
5480 startInfo.dwFlags = STARTF_USESTDHANDLES;
5481 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5482 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5483 startInfo.hStdError = INVALID_HANDLE_VALUE;
5484
5485 if (inputId == JIM_BAD_FD) {
5486 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
5487 CloseHandle(h);
5488 }
5489 } else {
5490 DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
5491 0, TRUE, DUPLICATE_SAME_ACCESS);
5492 }
5493 if (startInfo.hStdInput == JIM_BAD_FD) {
5494 goto end;
5495 }
5496
5497 if (outputId == JIM_BAD_FD) {
5498 startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
5499 JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
5500 } else {
5501 DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
5502 0, TRUE, DUPLICATE_SAME_ACCESS);
5503 }
5504 if (startInfo.hStdOutput == JIM_BAD_FD) {
5505 goto end;
5506 }
5507
5508 if (errorId == JIM_BAD_FD) {
5509
5510 startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
5511 JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
5512 } else {
5513 DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
5514 0, TRUE, DUPLICATE_SAME_ACCESS);
5515 }
5516 if (startInfo.hStdError == JIM_BAD_FD) {
5517 goto end;
5518 }
5519
5520 if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5521 0, env, NULL, &startInfo, &procInfo)) {
 
 
 
 
5522 goto end;
5523 }
5524
5525
5526 WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5528,49 +5476,27 @@
5528
5529 pid = procInfo.hProcess;
5530
5531 end:
5532 Jim_FreeNewObj(interp, cmdLineObj);
5533 if (startInfo.hStdInput != JIM_BAD_FD) {
5534 CloseHandle(startInfo.hStdInput);
5535 }
5536 if (startInfo.hStdOutput != JIM_BAD_FD) {
5537 CloseHandle(startInfo.hStdOutput);
5538 }
5539 if (startInfo.hStdError != JIM_BAD_FD) {
5540 CloseHandle(startInfo.hStdError);
5541 }
5542 return pid;
5543 }
 
5544 #else
5545
5546 static int JimOpenForWrite(const char *filename, int append)
5547 {
5548 return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
5549 }
5550
5551 static int JimRewindFd(int fd)
5552 {
5553 return lseek(fd, 0L, SEEK_SET);
5554 }
5555
5556 static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5557 {
5558 int fd = Jim_MakeTempFile(interp, NULL);
5559
5560 if (fd != JIM_BAD_FD) {
5561 unlink(Jim_String(Jim_GetResult(interp)));
5562 if (contents) {
5563 if (write(fd, contents, len) != len) {
5564 Jim_SetResultErrno(interp, "couldn't write temp file");
5565 close(fd);
5566 return -1;
5567 }
5568 lseek(fd, 0L, SEEK_SET);
5569 }
5570 }
5571 return fd;
5572 }
5573
5574 static char **JimSaveEnv(char **env)
5575 {
5576 char **saveenv = Jim_GetEnviron();
@@ -5585,13 +5511,21 @@
5585 }
5586 #endif
5587 #endif
5588
5589
 
 
5590 #ifndef _XOPEN_SOURCE
5591 #define _XOPEN_SOURCE 500
5592 #endif
 
 
 
 
 
 
5593
5594 #include <stdlib.h>
5595 #include <string.h>
5596 #include <stdio.h>
5597 #include <time.h>
@@ -5598,65 +5532,126 @@
5598
5599
5600 #ifdef HAVE_SYS_TIME_H
5601 #include <sys/time.h>
5602 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5603
5604 static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5605 {
5606
5607 char buf[100];
5608 time_t t;
5609 long seconds;
 
 
5610
5611 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5612
5613 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
 
5614 return -1;
5615 }
5616
5617 if (argc == 3) {
5618 format = Jim_String(argv[2]);
5619 }
5620
5621 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5622 return JIM_ERR;
5623 }
5624 t = seconds;
 
5625
5626 if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5627 Jim_SetResultString(interp, "format string too long", -1);
5628 return JIM_ERR;
5629 }
5630
5631 Jim_SetResultString(interp, buf, -1);
5632
5633 return JIM_OK;
5634 }
5635
5636 #ifdef HAVE_STRPTIME
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5637 static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5638 {
5639 char *pt;
5640 struct tm tm;
5641 time_t now = time(0);
5642
5643 if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
 
 
 
 
 
 
 
 
 
 
5644 return -1;
5645 }
5646
5647
5648 localtime_r(&now, &tm);
5649
5650 pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
 
 
 
 
5651 if (pt == 0 || *pt != 0) {
5652 Jim_SetResultString(interp, "Failed to parse time according to format", -1);
5653 return JIM_ERR;
5654 }
5655
5656
5657 Jim_SetResultInt(interp, mktime(&tm));
5658
5659 return JIM_OK;
5660 }
5661 #endif
5662
@@ -5688,54 +5683,54 @@
5688
5689 return JIM_OK;
5690 }
5691
5692 static const jim_subcmd_type clock_command_table[] = {
5693 { "seconds",
5694 NULL,
5695 clock_cmd_seconds,
5696 0,
5697 0,
5698
5699 },
5700 { "clicks",
5701 NULL,
5702 clock_cmd_micros,
5703 0,
5704 0,
5705
 
 
 
 
 
 
 
5706 },
5707 { "microseconds",
5708 NULL,
5709 clock_cmd_micros,
5710 0,
5711 0,
5712
5713 },
5714 { "milliseconds",
5715 NULL,
5716 clock_cmd_millis,
5717 0,
5718 0,
5719
5720 },
5721 { "format",
5722 "seconds ?-format format?",
5723 clock_cmd_format,
5724 1,
5725 3,
5726
5727 },
5728 #ifdef HAVE_STRPTIME
5729 { "scan",
5730 "str -format format",
5731 clock_cmd_scan,
5732 3,
5733 3,
5734
5735 },
5736 #endif
 
 
 
 
 
 
 
5737 { NULL }
5738 };
5739
5740 int Jim_clockInit(Jim_Interp *interp)
5741 {
@@ -5753,12 +5748,13 @@
5753 #include <errno.h>
5754
5755
5756 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5757 {
5758
5759 Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
 
5760 return JIM_OK;
5761 }
5762
5763 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5764 {
@@ -5769,21 +5765,20 @@
5769 return JIM_OK;
5770 }
5771
5772 patternObj = (argc == 1) ? NULL : argv[1];
5773
5774
5775 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5776 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5777
5778 Jim_SetResult(interp, objPtr);
5779 return JIM_OK;
5780 }
5781 }
5782
5783
5784 return Jim_DictValues(interp, objPtr, patternObj);
5785 }
5786
5787 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5788 {
5789 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5785,11 @@
5790
5791 if (!objPtr) {
5792 return JIM_OK;
5793 }
5794
5795 return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
5796 }
5797
5798 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5799 {
5800 int i;
@@ -5802,27 +5797,29 @@
5802 Jim_Obj *resultObj;
5803 Jim_Obj *objPtr;
5804 Jim_Obj **dictValuesObj;
5805
5806 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5807
5808 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5809 return JIM_OK;
5810 }
5811
5812 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5813
5814 if (objPtr == NULL) {
5815
5816 return JIM_OK;
5817 }
5818
5819 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5820 return JIM_ERR;
 
 
5821 }
5822
5823
5824 resultObj = Jim_NewDictObj(interp, NULL, 0);
5825
5826 for (i = 0; i < len; i += 2) {
5827 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
5828 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5834,18 @@
5837 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5838 {
5839 Jim_Obj *objPtr;
5840 int len = 0;
5841
5842
5843 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5844 if (objPtr) {
5845 len = Jim_DictSize(interp, objPtr);
5846 if (len < 0) {
5847 return JIM_ERR;
 
 
5848 }
5849 }
5850
5851 Jim_SetResultInt(interp, len);
5852
@@ -5876,11 +5875,11 @@
5876 return JIM_ERR;
5877 }
5878
5879 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5880 if (!dictObj) {
5881
5882 return Jim_SetVariable(interp, argv[0], listObj);
5883 }
5884 else if (Jim_DictSize(interp, dictObj) < 0) {
5885 return JIM_ERR;
5886 }
@@ -5905,53 +5904,53 @@
5905 { "exists",
5906 "arrayName",
5907 array_cmd_exists,
5908 1,
5909 1,
5910
5911 },
5912 { "get",
5913 "arrayName ?pattern?",
5914 array_cmd_get,
5915 1,
5916 2,
5917
5918 },
5919 { "names",
5920 "arrayName ?pattern?",
5921 array_cmd_names,
5922 1,
5923 2,
5924
5925 },
5926 { "set",
5927 "arrayName list",
5928 array_cmd_set,
5929 2,
5930 2,
5931
5932 },
5933 { "size",
5934 "arrayName",
5935 array_cmd_size,
5936 1,
5937 1,
5938
5939 },
5940 { "stat",
5941 "arrayName",
5942 array_cmd_stat,
5943 1,
5944 1,
5945
5946 },
5947 { "unset",
5948 "arrayName ?pattern?",
5949 array_cmd_unset,
5950 1,
5951 2,
5952
5953 },
5954 { NULL
5955 }
5956 };
5957
@@ -5987,11 +5986,14 @@
5987 Jim_arrayInit(interp);
5988 Jim_stdlibInit(interp);
5989 Jim_tclcompatInit(interp);
5990 return JIM_OK;
5991 }
5992 #define JIM_OPTIMIZATION
 
 
 
5993
5994 #include <stdio.h>
5995 #include <stdlib.h>
5996
5997 #include <string.h>
@@ -6056,10 +6058,16 @@
6056 #define JimPanic(X) JimPanicDump X
6057 #else
6058 #define JimPanic(X)
6059 #endif
6060
 
 
 
 
 
 
6061
6062 static char JimEmptyStringRep[] = "";
6063
6064 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
6065 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6120,34 @@
6112 if (*pattern == '^') {
6113 not++;
6114 pattern++;
6115 }
6116
6117
6118 if (*pattern == ']') {
6119 goto first;
6120 }
6121 }
6122
6123 while (*pattern && *pattern != ']') {
6124
6125 if (pattern[0] == '\\') {
6126 first:
6127 pattern += utf8_tounicode_case(pattern, &pchar, nocase);
6128 }
6129 else {
6130
6131 int start;
6132 int end;
6133
6134 pattern += utf8_tounicode_case(pattern, &start, nocase);
6135 if (pattern[0] == '-' && pattern[1]) {
6136
6137 pattern += utf8_tounicode(pattern, &pchar);
6138 pattern += utf8_tounicode_case(pattern, &end, nocase);
6139
6140
6141 if ((c >= start && c <= end) || (c >= end && c <= start)) {
6142 match = 1;
6143 }
6144 continue;
6145 }
@@ -6169,19 +6177,19 @@
6169 while (pattern[1] == '*') {
6170 pattern++;
6171 }
6172 pattern++;
6173 if (!pattern[0]) {
6174 return 1;
6175 }
6176 while (*string) {
6177
6178 if (JimGlobMatch(pattern, string, nocase))
6179 return 1;
6180 string += utf8_tounicode(string, &c);
6181 }
6182 return 0;
6183
6184 case '?':
6185 string += utf8_tounicode(string, &c);
6186 break;
6187
@@ -6190,20 +6198,20 @@
6190 pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
6191 if (!pattern) {
6192 return 0;
6193 }
6194 if (!*pattern) {
6195
6196 continue;
6197 }
6198 break;
6199 }
6200 case '\\':
6201 if (pattern[1]) {
6202 pattern++;
6203 }
6204
6205 default:
6206 string += utf8_tounicode_case(string, &c, nocase);
6207 utf8_tounicode_case(pattern, &pchar, nocase);
6208 if (pchar != c) {
6209 return 0;
@@ -6249,11 +6257,11 @@
6249 maxchars--;
6250 }
6251 if (!maxchars) {
6252 return 0;
6253 }
6254
6255 if (*s1) {
6256 return 1;
6257 }
6258 if (*s2) {
6259 return -1;
@@ -6290,11 +6298,11 @@
6290 const char *p;
6291
6292 if (!l1 || !l2 || l1 > l2)
6293 return -1;
6294
6295
6296 for (p = s2 + l2 - 1; p != s2 - 1; p--) {
6297 if (*p == *s1 && memcmp(s1, p, l1) == 0) {
6298 return p - s2;
6299 }
6300 }
@@ -6349,28 +6357,28 @@
6349 }
6350 *sign = 1;
6351 }
6352
6353 if (str[i] != '0') {
6354
6355 return 0;
6356 }
6357
6358
6359 switch (str[i + 1]) {
6360 case 'x': case 'X': *base = 16; break;
6361 case 'o': case 'O': *base = 8; break;
6362 case 'b': case 'B': *base = 2; break;
6363 default: return 0;
6364 }
6365 i += 2;
6366
6367 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6368
6369 return i;
6370 }
6371
6372 *base = 10;
6373 return 0;
6374 }
6375
6376 static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6392,11 @@
6384 if (endptr == NULL || *endptr != str + i) {
6385 return value * sign;
6386 }
6387 }
6388
6389
6390 return strtol(str, endptr, 10);
6391 }
6392
6393
6394 static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6411,11 @@
6403 if (endptr == NULL || *endptr != str + i) {
6404 return value * sign;
6405 }
6406 }
6407
6408
6409 return strtoull(str, endptr, 10);
6410 #else
6411 return (unsigned long)jim_strtol(str, endptr);
6412 #endif
6413 }
@@ -6428,26 +6436,40 @@
6428
6429 int Jim_StringToDouble(const char *str, double *doublePtr)
6430 {
6431 char *endptr;
6432
6433
6434 errno = 0;
6435
6436 *doublePtr = strtod(str, &endptr);
6437
6438 return JimCheckConversion(str, endptr);
6439 }
6440
6441 static jim_wide JimPowWide(jim_wide b, jim_wide e)
6442 {
6443 jim_wide i, res = 1;
6444
6445 if ((b == 0 && e != 0) || (e < 0))
6446 return 0;
6447 for (i = 0; i < e; i++) {
6448 res *= b;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6449 }
6450 return res;
6451 }
6452
6453 #ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6531,11 @@
6509 char *Jim_StrDupLen(const char *s, int l)
6510 {
6511 char *copy = Jim_Alloc(l + 1);
6512
6513 memcpy(copy, s, l + 1);
6514 copy[l] = 0;
6515 return copy;
6516 }
6517
6518
6519
@@ -6598,52 +6620,52 @@
6598 }
6599
6600
6601 void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
6602 {
6603 Jim_HashTable n;
6604 unsigned int realsize = JimHashTableNextPower(size), i;
6605
6606 if (size <= ht->used)
6607 return;
6608
6609 Jim_InitHashTable(&n, ht->type, ht->privdata);
6610 n.size = realsize;
6611 n.sizemask = realsize - 1;
6612 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6613
6614 n.uniq = ht->uniq;
6615
6616
6617 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6618
6619 n.used = ht->used;
6620 for (i = 0; ht->used > 0; i++) {
6621 Jim_HashEntry *he, *nextHe;
6622
6623 if (ht->table[i] == NULL)
6624 continue;
6625
6626
6627 he = ht->table[i];
6628 while (he) {
6629 unsigned int h;
6630
6631 nextHe = he->next;
6632
6633 h = Jim_HashKey(ht, he->key) & n.sizemask;
6634 he->next = n.table[h];
6635 n.table[h] = he;
6636 ht->used--;
6637
6638 he = nextHe;
6639 }
6640 }
6641 assert(ht->used == 0);
6642 Jim_Free(ht->table);
6643
6644
6645 *ht = n;
6646 }
6647
6648
6649 int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6674,11 @@
6652
6653 entry = JimInsertHashEntry(ht, key, 0);
6654 if (entry == NULL)
6655 return JIM_ERR;
6656
6657
6658 Jim_SetHashKey(ht, entry, key);
6659 Jim_SetHashVal(ht, entry, val);
6660 return JIM_OK;
6661 }
6662
@@ -6678,11 +6700,11 @@
6678 Jim_SetHashVal(ht, entry, val);
6679 }
6680 existed = 1;
6681 }
6682 else {
6683
6684 Jim_SetHashKey(ht, entry, key);
6685 Jim_SetHashVal(ht, entry, val);
6686 existed = 0;
6687 }
6688
@@ -6701,11 +6723,11 @@
6701 he = ht->table[h];
6702
6703 prevHe = NULL;
6704 while (he) {
6705 if (Jim_CompareHashKeys(ht, key, he->key)) {
6706
6707 if (prevHe)
6708 prevHe->next = he->next;
6709 else
6710 ht->table[h] = he->next;
6711 Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6737,19 @@
6715 return JIM_OK;
6716 }
6717 prevHe = he;
6718 he = he->next;
6719 }
6720 return JIM_ERR;
6721 }
6722
6723
6724 int Jim_FreeHashTable(Jim_HashTable *ht)
6725 {
6726 unsigned int i;
6727
6728
6729 for (i = 0; ht->used > 0; i++) {
6730 Jim_HashEntry *he, *nextHe;
6731
6732 if ((he = ht->table[i]) == NULL)
6733 continue;
@@ -6738,15 +6760,15 @@
6738 Jim_Free(he);
6739 ht->used--;
6740 he = nextHe;
6741 }
6742 }
6743
6744 Jim_Free(ht->table);
6745
6746 JimResetHashTable(ht);
6747 return JIM_OK;
6748 }
6749
6750 Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
6751 {
6752 Jim_HashEntry *he;
@@ -6819,24 +6841,24 @@
6819 static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
6820 {
6821 unsigned int h;
6822 Jim_HashEntry *he;
6823
6824
6825 JimExpandHashTableIfNeeded(ht);
6826
6827
6828 h = Jim_HashKey(ht, key) & ht->sizemask;
6829
6830 he = ht->table[h];
6831 while (he) {
6832 if (Jim_CompareHashKeys(ht, key, he->key))
6833 return replace ? he : NULL;
6834 he = he->next;
6835 }
6836
6837
6838 he = Jim_Alloc(sizeof(*he));
6839 he->next = ht->table[h];
6840 ht->table[h] = he;
6841 ht->used++;
6842 he->key = NULL;
@@ -6865,16 +6887,16 @@
6865 {
6866 Jim_Free(key);
6867 }
6868
6869 static const Jim_HashTableType JimPackageHashTableType = {
6870 JimStringCopyHTHashFunction,
6871 JimStringCopyHTDup,
6872 NULL,
6873 JimStringCopyHTKeyCompare,
6874 JimStringCopyHTKeyDestructor,
6875 NULL
6876 };
6877
6878 typedef struct AssocDataValue
6879 {
6880 Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6911,16 @@
6889 assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
6890 Jim_Free(data);
6891 }
6892
6893 static const Jim_HashTableType JimAssocDataHashTableType = {
6894 JimStringCopyHTHashFunction,
6895 JimStringCopyHTDup,
6896 NULL,
6897 JimStringCopyHTKeyCompare,
6898 JimStringCopyHTKeyDestructor,
6899 JimAssocDataHashTableValueDestructor
6900 };
6901
6902 void Jim_InitStack(Jim_Stack *stack)
6903 {
6904 stack->len = 0;
@@ -6951,56 +6973,61 @@
6951 freeFunc(stack->vector[i]);
6952 }
6953
6954
6955
6956 #define JIM_TT_NONE 0
6957 #define JIM_TT_STR 1
6958 #define JIM_TT_ESC 2
6959 #define JIM_TT_VAR 3
6960 #define JIM_TT_DICTSUGAR 4
6961 #define JIM_TT_CMD 5
6962
6963 #define JIM_TT_SEP 6
6964 #define JIM_TT_EOL 7
6965 #define JIM_TT_EOF 8
6966
6967 #define JIM_TT_LINE 9
6968 #define JIM_TT_WORD 10
6969
6970
6971 #define JIM_TT_SUBEXPR_START 11
6972 #define JIM_TT_SUBEXPR_END 12
6973 #define JIM_TT_SUBEXPR_COMMA 13
6974 #define JIM_TT_EXPR_INT 14
6975 #define JIM_TT_EXPR_DOUBLE 15
 
6976
6977 #define JIM_TT_EXPRSUGAR 16
6978
6979
6980 #define JIM_TT_EXPR_OP 20
6981
6982 #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
6983
 
 
 
 
6984 struct JimParseMissing {
6985 int ch;
6986 int line;
6987 };
6988
6989 struct JimParserCtx
6990 {
6991 const char *p;
6992 int len;
6993 int linenr;
6994 const char *tstart;
6995 const char *tend;
6996 int tline;
6997 int tt;
6998 int eof;
6999 int inquote;
7000 int comment;
7001 struct JimParseMissing missing;
7002 };
7003
7004 static int JimParseScript(struct JimParserCtx *pc);
7005 static int JimParseSep(struct JimParserCtx *pc);
7006 static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7057,11 @@
7030 pc->missing.line = linenr;
7031 }
7032
7033 static int JimParseScript(struct JimParserCtx *pc)
7034 {
7035 while (1) {
7036 if (!pc->len) {
7037 pc->tstart = pc->p;
7038 pc->tend = pc->p - 1;
7039 pc->tline = pc->linenr;
7040 pc->tt = JIM_TT_EOL;
@@ -7066,11 +7093,11 @@
7066 pc->comment = 0;
7067 return JimParseCmd(pc);
7068 case '$':
7069 pc->comment = 0;
7070 if (JimParseVar(pc) == JIM_ERR) {
7071
7072 pc->tstart = pc->tend = pc->p++;
7073 pc->len--;
7074 pc->tt = JIM_TT_ESC;
7075 }
7076 return JIM_OK;
@@ -7127,11 +7154,11 @@
7127
7128 static void JimParseSubBrace(struct JimParserCtx *pc)
7129 {
7130 int level = 1;
7131
7132
7133 pc->p++;
7134 pc->len--;
7135 while (pc->len) {
7136 switch (*pc->p) {
7137 case '\\':
@@ -7171,11 +7198,11 @@
7171 static int JimParseSubQuote(struct JimParserCtx *pc)
7172 {
7173 int tt = JIM_TT_STR;
7174 int line = pc->tline;
7175
7176
7177 pc->p++;
7178 pc->len--;
7179 while (pc->len) {
7180 switch (*pc->p) {
7181 case '\\':
@@ -7220,11 +7247,11 @@
7220 {
7221 int level = 1;
7222 int startofword = 1;
7223 int line = pc->tline;
7224
7225
7226 pc->p++;
7227 pc->len--;
7228 while (pc->len) {
7229 switch (*pc->p) {
7230 case '\\':
@@ -7300,17 +7327,17 @@
7300 return JIM_OK;
7301 }
7302
7303 static int JimParseVar(struct JimParserCtx *pc)
7304 {
7305
7306 pc->p++;
7307 pc->len--;
7308
7309 #ifdef EXPRSUGAR_BRACKET
7310 if (*pc->p == '[') {
7311
7312 JimParseCmd(pc);
7313 pc->tt = JIM_TT_EXPRSUGAR;
7314 return JIM_OK;
7315 }
7316 #endif
@@ -7336,11 +7363,11 @@
7336 pc->len--;
7337 }
7338 }
7339 else {
7340 while (1) {
7341
7342 if (pc->p[0] == ':' && pc->p[1] == ':') {
7343 while (*pc->p == ':') {
7344 pc->p++;
7345 pc->len--;
7346 }
@@ -7351,11 +7378,11 @@
7351 pc->len--;
7352 continue;
7353 }
7354 break;
7355 }
7356
7357 if (*pc->p == '(') {
7358 int count = 1;
7359 const char *paren = NULL;
7360
7361 pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7405,11 @@
7378 if (count == 0) {
7379 pc->p++;
7380 pc->len--;
7381 }
7382 else if (paren) {
7383
7384 paren++;
7385 pc->len += (pc->p - paren);
7386 pc->p = paren;
7387 }
7388 #ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7430,19 @@
7403
7404 static int JimParseStr(struct JimParserCtx *pc)
7405 {
7406 if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
7407 pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7408
7409 if (*pc->p == '{') {
7410 return JimParseBrace(pc);
7411 }
7412 if (*pc->p == '"') {
7413 pc->inquote = 1;
7414 pc->p++;
7415 pc->len--;
7416
7417 pc->missing.line = pc->tline;
7418 }
7419 }
7420 pc->tstart = pc->p;
7421 pc->tline = pc->linenr;
@@ -7441,25 +7468,25 @@
7441 }
7442 pc->p++;
7443 pc->len--;
7444 }
7445 else if (pc->len == 1) {
7446
7447 pc->missing.ch = '\\';
7448 }
7449 break;
7450 case '(':
7451
7452 if (pc->len > 1 && pc->p[1] != '$') {
7453 break;
7454 }
7455
7456 case ')':
7457
7458 if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
7459 if (pc->p == pc->tstart) {
7460
7461 pc->p++;
7462 pc->len--;
7463 }
7464 pc->tend = pc->p - 1;
7465 pc->tt = JIM_TT_ESC;
@@ -7499,11 +7526,11 @@
7499 break;
7500 }
7501 pc->p++;
7502 pc->len--;
7503 }
7504 return JIM_OK;
7505 }
7506
7507 static int JimParseComment(struct JimParserCtx *pc)
7508 {
7509 while (*pc->p) {
@@ -7610,34 +7637,34 @@
7610 if (c == -1) {
7611 break;
7612 }
7613 val = (val << 4) | c;
7614 }
7615
7616 if (s[i] == '{') {
7617 if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7618
7619 i--;
7620 k = 0;
7621 }
7622 else {
7623
7624 k++;
7625 }
7626 }
7627 if (k) {
7628
7629 if (s[i] == 'x') {
7630 *p++ = val;
7631 }
7632 else {
7633 p += utf8_fromunicode(p, val);
7634 }
7635 i += k;
7636 break;
7637 }
7638
7639 *p++ = s[i];
7640 }
7641 break;
7642 case 'v':
7643 *p++ = 0xb;
@@ -7646,11 +7673,11 @@
7646 case '\0':
7647 *p++ = '\\';
7648 i++;
7649 break;
7650 case '\n':
7651
7652 *p++ = ' ';
7653 do {
7654 i++;
7655 } while (s[i + 1] == ' ' || s[i + 1] == '\t');
7656 break;
@@ -7660,11 +7687,11 @@
7660 case '3':
7661 case '4':
7662 case '5':
7663 case '6':
7664 case '7':
7665
7666 {
7667 int val = 0;
7668 int c = odigitval(s[i + 1]);
7669
7670 val = c;
@@ -7708,27 +7735,23 @@
7708 char *token;
7709 int len;
7710
7711 start = pc->tstart;
7712 end = pc->tend;
7713 if (start > end) {
 
7714 len = 0;
7715 token = Jim_Alloc(1);
7716 token[0] = '\0';
7717 }
7718 else {
7719 len = (end - start) + 1;
7720 token = Jim_Alloc(len + 1);
7721 if (pc->tt != JIM_TT_ESC) {
7722
7723 memcpy(token, start, len);
7724 token[len] = '\0';
7725 }
7726 else {
7727
7728 len = JimEscape(token, start, len);
7729 }
7730 }
7731
7732 return Jim_NewStringObjNoAlloc(interp, token, len);
7733 }
7734
@@ -7790,11 +7813,11 @@
7790 while (pc->len) {
7791 switch (*pc->p) {
7792 case '\\':
7793 pc->tt = JIM_TT_ESC;
7794 if (--pc->len == 0) {
7795
7796 pc->tend = pc->p;
7797 return JIM_OK;
7798 }
7799 pc->p++;
7800 break;
@@ -7826,11 +7849,11 @@
7826 pc->tend = pc->p - 1;
7827 return JIM_OK;
7828 }
7829 if (*pc->p == '\\') {
7830 if (--pc->len == 0) {
7831
7832 pc->tend = pc->p;
7833 return JIM_OK;
7834 }
7835 pc->tt = JIM_TT_ESC;
7836 pc->p++;
@@ -7846,24 +7869,24 @@
7846
7847 Jim_Obj *Jim_NewObj(Jim_Interp *interp)
7848 {
7849 Jim_Obj *objPtr;
7850
7851
7852 if (interp->freeList != NULL) {
7853
7854 objPtr = interp->freeList;
7855 interp->freeList = objPtr->nextObjPtr;
7856 }
7857 else {
7858
7859 objPtr = Jim_Alloc(sizeof(*objPtr));
7860 }
7861
7862 objPtr->refCount = 0;
7863
7864
7865 objPtr->prevObjPtr = NULL;
7866 objPtr->nextObjPtr = interp->liveList;
7867 if (interp->liveList)
7868 interp->liveList->prevObjPtr = objPtr;
7869 interp->liveList = objPtr;
@@ -7871,32 +7894,32 @@
7871 return objPtr;
7872 }
7873
7874 void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
7875 {
7876
7877 JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
7878 objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
7879
7880
7881 Jim_FreeIntRep(interp, objPtr);
7882
7883 if (objPtr->bytes != NULL) {
7884 if (objPtr->bytes != JimEmptyStringRep)
7885 Jim_Free(objPtr->bytes);
7886 }
7887
7888 if (objPtr->prevObjPtr)
7889 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7890 if (objPtr->nextObjPtr)
7891 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7892 if (interp->liveList == objPtr)
7893 interp->liveList = objPtr->nextObjPtr;
7894 #ifdef JIM_DISABLE_OBJECT_POOL
7895 Jim_Free(objPtr);
7896 #else
7897
7898 objPtr->prevObjPtr = NULL;
7899 objPtr->nextObjPtr = interp->freeList;
7900 if (interp->freeList)
7901 interp->freeList->prevObjPtr = objPtr;
7902 interp->freeList = objPtr;
@@ -7919,45 +7942,44 @@
7919 {
7920 Jim_Obj *dupPtr;
7921
7922 dupPtr = Jim_NewObj(interp);
7923 if (objPtr->bytes == NULL) {
7924
7925 dupPtr->bytes = NULL;
7926 }
7927 else if (objPtr->length == 0) {
7928
7929 dupPtr->bytes = JimEmptyStringRep;
7930 dupPtr->length = 0;
7931 dupPtr->typePtr = NULL;
7932 return dupPtr;
7933 }
7934 else {
7935 dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
7936 dupPtr->length = objPtr->length;
7937
7938 memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
7939 }
7940
7941
7942 dupPtr->typePtr = objPtr->typePtr;
7943 if (objPtr->typePtr != NULL) {
7944 if (objPtr->typePtr->dupIntRepProc == NULL) {
7945 dupPtr->internalRep = objPtr->internalRep;
7946 }
7947 else {
7948
7949 objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
7950 }
7951 }
7952 return dupPtr;
7953 }
7954
7955 const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
7956 {
7957 if (objPtr->bytes == NULL) {
7958
7959 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7960 objPtr->typePtr->updateStringProc(objPtr);
7961 }
7962 if (lenPtr)
7963 *lenPtr = objPtr->length;
@@ -7966,25 +7988,22 @@
7966
7967
7968 int Jim_Length(Jim_Obj *objPtr)
7969 {
7970 if (objPtr->bytes == NULL) {
7971
7972 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7973 objPtr->typePtr->updateStringProc(objPtr);
7974 }
7975 return objPtr->length;
7976 }
7977
7978
7979 const char *Jim_String(Jim_Obj *objPtr)
7980 {
7981 if (objPtr->bytes == NULL) {
7982
7983 JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
7984 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7985 objPtr->typePtr->updateStringProc(objPtr);
7986 }
7987 return objPtr->bytes;
7988 }
7989
7990 static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
@@ -8001,23 +8020,34 @@
8001 FreeDictSubstInternalRep,
8002 DupDictSubstInternalRep,
8003 NULL,
8004 JIM_TYPE_NONE,
8005 };
 
 
 
 
 
 
 
 
 
 
 
8006
8007 static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8008 {
8009 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
8010 }
8011
8012 static const Jim_ObjType interpolatedObjType = {
8013 "interpolated",
8014 FreeInterpolatedInternalRep,
8015 NULL,
8016 NULL,
8017 JIM_TYPE_NONE,
8018 };
8019
8020 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8021 static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8022
8023 static const Jim_ObjType stringObjType = {
@@ -8037,22 +8067,22 @@
8037 }
8038
8039 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
8040 {
8041 if (objPtr->typePtr != &stringObjType) {
8042
8043 if (objPtr->bytes == NULL) {
8044
8045 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8046 objPtr->typePtr->updateStringProc(objPtr);
8047 }
8048
8049 Jim_FreeIntRep(interp, objPtr);
8050
8051 objPtr->typePtr = &stringObjType;
8052 objPtr->internalRep.strValue.maxLength = objPtr->length;
8053
8054 objPtr->internalRep.strValue.charLength = -1;
8055 }
8056 return JIM_OK;
8057 }
8058
@@ -8073,39 +8103,37 @@
8073
8074 Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
8075 {
8076 Jim_Obj *objPtr = Jim_NewObj(interp);
8077
8078
8079 if (len == -1)
8080 len = strlen(s);
8081
8082 if (len == 0) {
8083 objPtr->bytes = JimEmptyStringRep;
8084 }
8085 else {
8086 objPtr->bytes = Jim_Alloc(len + 1);
8087 memcpy(objPtr->bytes, s, len);
8088 objPtr->bytes[len] = '\0';
8089 }
8090 objPtr->length = len;
8091
8092
8093 objPtr->typePtr = NULL;
8094 return objPtr;
8095 }
8096
8097
8098 Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
8099 {
8100 #ifdef JIM_UTF8
8101
8102 int bytelen = utf8_index(s, charlen);
8103
8104 Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
8105
8106
8107 objPtr->typePtr = &stringObjType;
8108 objPtr->internalRep.strValue.maxLength = bytelen;
8109 objPtr->internalRep.strValue.charLength = charlen;
8110
8111 return objPtr;
@@ -8132,11 +8160,11 @@
8132 len = strlen(str);
8133 needlen = objPtr->length + len;
8134 if (objPtr->internalRep.strValue.maxLength < needlen ||
8135 objPtr->internalRep.strValue.maxLength == 0) {
8136 needlen *= 2;
8137
8138 if (needlen < 7) {
8139 needlen = 7;
8140 }
8141 if (objPtr->bytes == JimEmptyStringRep) {
8142 objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8176,11 @@
8148 }
8149 memcpy(objPtr->bytes + objPtr->length, str, len);
8150 objPtr->bytes[objPtr->length + len] = '\0';
8151
8152 if (objPtr->internalRep.strValue.charLength >= 0) {
8153
8154 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
8155 }
8156 objPtr->length += len;
8157 }
8158
@@ -8210,11 +8238,11 @@
8210 int l1, l2;
8211 const char *s1 = Jim_GetString(firstObjPtr, &l1);
8212 const char *s2 = Jim_GetString(secondObjPtr, &l2);
8213
8214 if (nocase) {
8215
8216 return JimStringCompareLen(s1, s2, -1, nocase);
8217 }
8218 return JimStringCompare(s1, l1, s2, l2);
8219 }
8220
@@ -8312,11 +8340,11 @@
8312
8313 if (first == 0 && rangeLen == len) {
8314 return strObjPtr;
8315 }
8316 if (len == bytelen) {
8317
8318 return Jim_NewStringObj(interp, str + first, rangeLen);
8319 }
8320 return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
8321 #else
8322 return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8369,19 @@
8341 return strObjPtr;
8342 }
8343
8344 str = Jim_String(strObjPtr);
8345
8346
8347 objPtr = Jim_NewStringObjUtf8(interp, str, first);
8348
8349
8350 if (newStrObj) {
8351 Jim_AppendObj(interp, objPtr, newStrObj);
8352 }
8353
8354
8355 Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
8356
8357 return objPtr;
8358 }
8359
@@ -8371,12 +8399,10 @@
8371 {
8372 char *buf;
8373 int len;
8374 const char *str;
8375
8376 SetStringFromAny(interp, strObjPtr);
8377
8378 str = Jim_GetString(strObjPtr, &len);
8379
8380 #ifdef JIM_UTF8
8381 len *= 2;
8382 #endif
@@ -8389,14 +8415,10 @@
8389 {
8390 char *buf;
8391 const char *str;
8392 int len;
8393
8394 if (strObjPtr->typePtr != &stringObjType) {
8395 SetStringFromAny(interp, strObjPtr);
8396 }
8397
8398 str = Jim_GetString(strObjPtr, &len);
8399
8400 #ifdef JIM_UTF8
8401 len *= 2;
8402 #endif
@@ -8411,13 +8433,11 @@
8411 int len;
8412 int c;
8413 const char *str;
8414
8415 str = Jim_GetString(strObjPtr, &len);
8416 if (len == 0) {
8417 return strObjPtr;
8418 }
8419 #ifdef JIM_UTF8
8420 len *= 2;
8421 #endif
8422 buf = p = Jim_Alloc(len + 1);
8423
@@ -8452,11 +8472,11 @@
8452 while (len) {
8453 int c;
8454 int n = utf8_tounicode(str, &c);
8455
8456 if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8457
8458 break;
8459 }
8460 str += n;
8461 len -= n;
8462 }
@@ -8523,41 +8543,41 @@
8523
8524 len = Jim_Length(strObjPtr);
8525 nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
8526
8527 if (nontrim == NULL) {
8528
8529 return Jim_NewEmptyStringObj(interp);
8530 }
8531 if (nontrim == strObjPtr->bytes + len) {
8532
8533 return strObjPtr;
8534 }
8535
8536 if (Jim_IsShared(strObjPtr)) {
8537 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
8538 }
8539 else {
8540
8541 strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
8542 strObjPtr->length = (nontrim - strObjPtr->bytes);
8543 }
8544
8545 return strObjPtr;
8546 }
8547
8548 static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
8549 {
8550
8551 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8552
8553
8554 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8555
8556
8557 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8558
8559 Jim_FreeNewObj(interp, objPtr);
8560 }
8561
8562 return strObjPtr;
8563 }
@@ -8575,17 +8595,17 @@
8575 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8576 {
8577 static const char * const strclassnames[] = {
8578 "integer", "alpha", "alnum", "ascii", "digit",
8579 "double", "lower", "upper", "space", "xdigit",
8580 "control", "print", "graph", "punct",
8581 NULL
8582 };
8583 enum {
8584 STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
8585 STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8586 STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT
8587 };
8588 int strclass;
8589 int len;
8590 int i;
8591 const char *str;
@@ -8613,10 +8633,17 @@
8613 {
8614 double d;
8615 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8616 return JIM_OK;
8617 }
 
 
 
 
 
 
 
8618
8619 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8620 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8621 case STR_IS_ASCII: isclassfunc = jim_isascii; break;
8622 case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8658,11 @@
8631 default:
8632 return JIM_ERR;
8633 }
8634
8635 for (i = 0; i < len; i++) {
8636 if (!isclassfunc(str[i])) {
8637 Jim_SetResultBool(interp, 0);
8638 return JIM_OK;
8639 }
8640 }
8641 Jim_SetResultBool(interp, 1);
@@ -8656,20 +8683,18 @@
8656 {
8657 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
8658 return 1;
8659 }
8660 else {
8661 const char *objStr = Jim_String(objPtr);
8662
8663 if (strcmp(str, objStr) != 0)
8664 return 0;
8665
8666 if (objPtr->typePtr != &comparedStringObjType) {
8667 Jim_FreeIntRep(interp, objPtr);
8668 objPtr->typePtr = &comparedStringObjType;
8669 }
8670 objPtr->internalRep.ptr = (char *)str;
8671 return 1;
8672 }
8673 }
8674
8675 static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8783,20 @@
8758 int type;
8759 } ScriptToken;
8760
8761 typedef struct ScriptObj
8762 {
8763 ScriptToken *token;
8764 Jim_Obj *fileNameObj;
8765 int len;
8766 int substFlags;
8767 int inUse; /* Used to share a ScriptObj. Currently
8768 only used by Jim_EvalObj() as protection against
8769 shimmering of the currently evaluated object. */
8770 int firstline;
8771 int linenr;
8772 int missing;
8773 } ScriptObj;
8774
8775 static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8776 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8777 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8824,23 @@
8799 dupPtr->typePtr = NULL;
8800 }
8801
8802 typedef struct
8803 {
8804 const char *token;
8805 int len;
8806 int type;
8807 int line;
8808 } ParseToken;
8809
8810 typedef struct
8811 {
8812
8813 ParseToken *list;
8814 int size;
8815 int count;
8816 ParseToken static_list[20];
8817 } ParseTokenList;
8818
8819 static void ScriptTokenListInit(ParseTokenList *tokenlist)
8820 {
8821 tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8859,18 @@
8834 int line)
8835 {
8836 ParseToken *t;
8837
8838 if (tokenlist->count == tokenlist->size) {
8839
8840 tokenlist->size *= 2;
8841 if (tokenlist->list != tokenlist->static_list) {
8842 tokenlist->list =
8843 Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
8844 }
8845 else {
8846
8847 tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
8848 memcpy(tokenlist->list, tokenlist->static_list,
8849 tokenlist->count * sizeof(*tokenlist->list));
8850 }
8851 }
@@ -8854,25 +8879,32 @@
8854 t->len = len;
8855 t->type = type;
8856 t->line = line;
8857 }
8858
8859 static int JimCountWordTokens(ParseToken *t)
8860 {
8861 int expand = 1;
8862 int count = 0;
8863
8864
8865 if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
8866 if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8867
8868 expand = -1;
8869 t++;
8870 }
 
 
 
 
 
 
 
8871 }
8872
8873
8874 while (!TOKEN_IS_SEP(t->type)) {
8875 t++;
8876 count++;
8877 }
8878
@@ -8882,11 +8914,11 @@
8882 static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
8883 {
8884 Jim_Obj *objPtr;
8885
8886 if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8887
8888 int len = t->len;
8889 char *str = Jim_Alloc(len + 1);
8890 len = JimEscape(str, t->token, len);
8891 objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
8892 }
@@ -8899,13 +8931,13 @@
8899 static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8900 ParseTokenList *tokenlist)
8901 {
8902 int i;
8903 struct ScriptToken *token;
8904
8905 int lineargs = 0;
8906
8907 ScriptToken *linefirst;
8908 int count;
8909 int linenr;
8910
8911 #ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +8946,11 @@
8914 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
8915 tokenlist->list[i].len, tokenlist->list[i].token);
8916 }
8917 #endif
8918
8919
8920 count = tokenlist->count;
8921 for (i = 0; i < tokenlist->count; i++) {
8922 if (tokenlist->list[i].type == JIM_TT_EOL) {
8923 count++;
8924 }
@@ -8925,59 +8957,59 @@
8925 }
8926 linenr = script->firstline = tokenlist->list[0].line;
8927
8928 token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
8929
8930
8931 linefirst = token++;
8932
8933 for (i = 0; i < tokenlist->count; ) {
8934
8935 int wordtokens;
8936
8937
8938 while (tokenlist->list[i].type == JIM_TT_SEP) {
8939 i++;
8940 }
8941
8942 wordtokens = JimCountWordTokens(tokenlist->list + i);
8943
8944 if (wordtokens == 0) {
8945
8946 if (lineargs) {
8947 linefirst->type = JIM_TT_LINE;
8948 linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
8949 Jim_IncrRefCount(linefirst->objPtr);
8950
8951
8952 lineargs = 0;
8953 linefirst = token++;
8954 }
8955 i++;
8956 continue;
8957 }
8958 else if (wordtokens != 1) {
8959
8960 token->type = JIM_TT_WORD;
8961 token->objPtr = Jim_NewIntObj(interp, wordtokens);
8962 Jim_IncrRefCount(token->objPtr);
8963 token++;
8964 if (wordtokens < 0) {
8965
8966 i++;
8967 wordtokens = -wordtokens - 1;
8968 lineargs--;
8969 }
8970 }
8971
8972 if (lineargs == 0) {
8973
8974 linenr = tokenlist->list[i].line;
8975 }
8976 lineargs++;
8977
8978
8979 while (wordtokens--) {
8980 const ParseToken *t = &tokenlist->list[i++];
8981
8982 token->type = t->type;
8983 token->objPtr = JimMakeScriptObj(interp, t);
@@ -9010,11 +9042,11 @@
9010 {
9011 ScriptObj *script = JimGetScript(interp, scriptObj);
9012 if (stateCharPtr) {
9013 *stateCharPtr = script->missing;
9014 }
9015 return (script->missing == ' ');
9016 }
9017
9018 static int JimParseCheckMissing(Jim_Interp *interp, int ch)
9019 {
9020 const char *msg;
@@ -9028,10 +9060,13 @@
9028 msg = "unmatched \"[\"";
9029 break;
9030 case '{':
9031 msg = "missing close-brace";
9032 break;
 
 
 
9033 case '"':
9034 default:
9035 msg = "missing quote";
9036 break;
9037 }
@@ -9049,11 +9084,11 @@
9049 token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
9050
9051 for (i = 0; i < tokenlist->count; i++) {
9052 const ParseToken *t = &tokenlist->list[i];
9053
9054
9055 token->type = t->type;
9056 token->objPtr = JimMakeScriptObj(interp, t);
9057 Jim_IncrRefCount(token->objPtr);
9058 token++;
9059 }
@@ -9068,29 +9103,29 @@
9068 struct JimParserCtx parser;
9069 struct ScriptObj *script;
9070 ParseTokenList tokenlist;
9071 int line = 1;
9072
9073
9074 if (objPtr->typePtr == &sourceObjType) {
9075 line = objPtr->internalRep.sourceValue.lineNumber;
9076 }
9077
9078
9079 ScriptTokenListInit(&tokenlist);
9080
9081 JimParserInit(&parser, scriptText, scriptTextLen, line);
9082 while (!parser.eof) {
9083 JimParseScript(&parser);
9084 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
9085 parser.tline);
9086 }
9087
9088
9089 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
9090
9091
9092 script = Jim_Alloc(sizeof(*script));
9093 memset(script, 0, sizeof(*script));
9094 script->inUse = 1;
9095 if (objPtr->typePtr == &sourceObjType) {
9096 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9137,14 @@
9102 script->missing = parser.missing.ch;
9103 script->linenr = parser.missing.line;
9104
9105 ScriptObjAddTokens(interp, script, &tokenlist);
9106
9107
9108 ScriptTokenListFree(&tokenlist);
9109
9110
9111 Jim_FreeIntRep(interp, objPtr);
9112 Jim_SetIntRepPtr(objPtr, script);
9113 objPtr->typePtr = &scriptObjType;
9114 }
9115
@@ -9116,11 +9151,11 @@
9116 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
9117
9118 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
9119 {
9120 if (objPtr == interp->emptyObj) {
9121
9122 objPtr = interp->nullScriptObj;
9123 }
9124
9125 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
9126 JimSetScriptFromAny(interp, objPtr);
@@ -9155,67 +9190,66 @@
9155 Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
9156 Jim_Free(cmdPtr->u.proc.staticVars);
9157 }
9158 }
9159 else {
9160
9161 if (cmdPtr->u.native.delProc) {
9162 cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
9163 }
9164 }
9165 if (cmdPtr->prevCmd) {
9166
9167 JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
9168 }
9169 Jim_Free(cmdPtr);
9170 }
9171 }
9172
9173
9174 static void JimVariablesHTValDestructor(void *interp, void *val)
9175 {
9176 Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
9177 Jim_Free(val);
9178 }
9179
9180 static const Jim_HashTableType JimVariablesHashTableType = {
9181 JimStringCopyHTHashFunction,
9182 JimStringCopyHTDup,
9183 NULL,
9184 JimStringCopyHTKeyCompare,
9185 JimStringCopyHTKeyDestructor,
9186 JimVariablesHTValDestructor
9187 };
9188
9189 static void JimCommandsHT_ValDestructor(void *interp, void *val)
9190 {
9191 JimDecrCmdRefCount(interp, val);
9192 }
9193
9194 static const Jim_HashTableType JimCommandsHashTableType = {
9195 JimStringCopyHTHashFunction,
9196 JimStringCopyHTDup,
9197 NULL,
9198 JimStringCopyHTKeyCompare,
9199 JimStringCopyHTKeyDestructor,
9200 JimCommandsHT_ValDestructor
9201 };
9202
9203
9204
9205 #ifdef jim_ext_namespace
9206 static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
9207 {
9208 const char *name = Jim_String(nsObj);
9209 if (name[0] == ':' && name[1] == ':') {
9210
9211 while (*++name == ':') {
9212 }
9213 nsObj = Jim_NewStringObj(interp, name, -1);
9214 }
9215 else if (Jim_Length(interp->framePtr->nsObj)) {
9216
9217 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9218 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
9219 }
9220 return nsObj;
9221 }
@@ -9239,16 +9273,16 @@
9239 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9240 {
9241 Jim_Obj *objPtr = interp->emptyObj;
9242
9243 if (name[0] == ':' && name[1] == ':') {
9244
9245 while (*++name == ':') {
9246 }
9247 }
9248 else if (Jim_Length(interp->framePtr->nsObj)) {
9249
9250 objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9251 Jim_AppendStrings(interp, objPtr, "::", name, NULL);
9252 name = Jim_String(objPtr);
9253 }
9254 Jim_IncrRefCount(objPtr);
@@ -9257,11 +9291,11 @@
9257 }
9258
9259 #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
9260
9261 #else
9262
9263 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9264 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9265
9266 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9267 {
@@ -9276,17 +9310,17 @@
9276
9277 Jim_InterpIncrProcEpoch(interp);
9278 }
9279
9280 if (he && interp->local) {
9281
9282 cmd->prevCmd = Jim_GetHashEntryVal(he);
9283 Jim_SetHashVal(&interp->commands, he, cmd);
9284 }
9285 else {
9286 if (he) {
9287
9288 Jim_DeleteHashEntry(&interp->commands, name);
9289 }
9290
9291 Jim_AddHashEntry(&interp->commands, name, cmd);
9292 }
@@ -9297,11 +9331,11 @@
9297 int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
9298 Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
9299 {
9300 Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
9301
9302
9303 memset(cmdPtr, 0, sizeof(*cmdPtr));
9304 cmdPtr->inUse = 1;
9305 cmdPtr->u.native.delProc = delProc;
9306 cmdPtr->u.native.cmdProc = cmdProc;
9307 cmdPtr->u.native.privData = privData;
@@ -9326,11 +9360,11 @@
9326 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9327 Jim_Var *varPtr;
9328 int subLen;
9329
9330 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9331
9332 subLen = Jim_ListLength(interp, objPtr);
9333 if (subLen == 1 || subLen == 2) {
9334 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9335 if (subLen == 1) {
9336 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9406,19 @@
9372
9373 static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
9374 {
9375 #ifdef jim_ext_namespace
9376 if (cmdPtr->isproc) {
9377
9378 const char *pt = strrchr(cmdname, ':');
9379 if (pt && pt != cmdname && pt[-1] == ':') {
9380 Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
9381 cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
9382 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9383
9384 if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9385
9386 Jim_InterpIncrProcEpoch(interp);
9387 }
9388 }
9389 }
9390 #endif
@@ -9397,11 +9431,11 @@
9397 int argListLen;
9398 int i;
9399
9400 argListLen = Jim_ListLength(interp, argListObjPtr);
9401
9402
9403 cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
9404 memset(cmdPtr, 0, sizeof(*cmdPtr));
9405 cmdPtr->inUse = 1;
9406 cmdPtr->isproc = 1;
9407 cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9446,24 @@
9412 cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
9413 Jim_IncrRefCount(argListObjPtr);
9414 Jim_IncrRefCount(bodyObjPtr);
9415 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9416
9417
9418 if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
9419 goto err;
9420 }
9421
9422
9423
9424 for (i = 0; i < argListLen; i++) {
9425 Jim_Obj *argPtr;
9426 Jim_Obj *nameObjPtr;
9427 Jim_Obj *defaultObjPtr;
9428 int len;
9429
9430
9431 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9432 len = Jim_ListLength(interp, argPtr);
9433 if (len == 0) {
9434 Jim_SetResultString(interp, "argument with no name", -1);
9435 err:
@@ -9440,16 +9474,16 @@
9440 Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
9441 goto err;
9442 }
9443
9444 if (len == 2) {
9445
9446 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9447 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9448 }
9449 else {
9450
9451 nameObjPtr = argPtr;
9452 defaultObjPtr = NULL;
9453 }
9454
9455
@@ -9510,29 +9544,29 @@
9510 }
9511
9512 fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
9513 fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
9514
9515
9516 he = Jim_FindHashEntry(&interp->commands, fqold);
9517 if (he == NULL) {
9518 Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
9519 }
9520 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9521 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9522 }
9523 else {
9524
9525 cmdPtr = Jim_GetHashEntryVal(he);
9526 JimIncrCmdRefCount(cmdPtr);
9527 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9528 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9529
9530
9531 Jim_DeleteHashEntry(&interp->commands, fqold);
9532
9533
9534 Jim_InterpIncrProcEpoch(interp);
9535
9536 ret = JIM_OK;
9537 }
9538
@@ -9571,23 +9605,23 @@
9571 objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
9572 #ifdef jim_ext_namespace
9573 || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
9574 #endif
9575 ) {
9576
9577
9578
 
9579 const char *name = Jim_String(objPtr);
9580 Jim_HashEntry *he;
9581
9582 if (name[0] == ':' && name[1] == ':') {
9583 while (*++name == ':') {
9584 }
9585 }
9586 #ifdef jim_ext_namespace
9587 else if (Jim_Length(interp->framePtr->nsObj)) {
9588
9589 Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9590 Jim_AppendStrings(interp, nameObj, "::", name, NULL);
9591 he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
9592 Jim_FreeNewObj(interp, nameObj);
9593 if (he) {
@@ -9594,11 +9628,11 @@
9594 goto found;
9595 }
9596 }
9597 #endif
9598
9599
9600 he = Jim_FindHashEntry(&interp->commands, name);
9601 if (he == NULL) {
9602 if (flags & JIM_ERRMSG) {
9603 Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
9604 }
@@ -9607,11 +9641,11 @@
9607 #ifdef jim_ext_namespace
9608 found:
9609 #endif
9610 cmd = Jim_GetHashEntryVal(he);
9611
9612
9613 Jim_FreeIntRep(interp, objPtr);
9614 objPtr->typePtr = &commandObjType;
9615 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
9616 objPtr->internalRep.cmdValue.cmdPtr = cmd;
9617 objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9660,11 @@
9626 return cmd;
9627 }
9628
9629
9630
9631 #define JIM_DICT_SUGAR 100
9632
9633 static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
9634
9635 static const Jim_ObjType variableObjType = {
9636 "variable",
@@ -9640,11 +9674,11 @@
9640 JIM_TYPE_REFERENCES,
9641 };
9642
9643 static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
9644 {
9645
9646 if (nameObjPtr->typePtr != &variableObjType) {
9647 int len;
9648 const char *str = Jim_GetString(nameObjPtr, &len);
9649 if (memchr(str, '\0', len)) {
9650 Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9694,18 @@
9660 Jim_CallFrame *framePtr;
9661 Jim_HashEntry *he;
9662 int global;
9663 int len;
9664
9665
9666 if (objPtr->typePtr == &variableObjType) {
9667 framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
9668 if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9669
9670 return JIM_OK;
9671 }
9672
9673 }
9674 else if (objPtr->typePtr == &dictSubstObjType) {
9675 return JIM_DICT_SUGAR;
9676 }
9677 else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9713,11 @@
9679 }
9680
9681
9682 varName = Jim_GetString(objPtr, &len);
9683
9684
9685 if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
9686 return JIM_DICT_SUGAR;
9687 }
9688
9689 if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9729,23 @@
9695 else {
9696 global = 0;
9697 framePtr = interp->framePtr;
9698 }
9699
9700
9701 he = Jim_FindHashEntry(&framePtr->vars, varName);
9702 if (he == NULL) {
9703 if (!global && framePtr->staticVars) {
9704
9705 he = Jim_FindHashEntry(framePtr->staticVars, varName);
9706 }
9707 if (he == NULL) {
9708 return JIM_ERR;
9709 }
9710 }
9711
9712
9713 Jim_FreeIntRep(interp, objPtr);
9714 objPtr->typePtr = &variableObjType;
9715 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9716 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9717 objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9760,11 @@
9726 {
9727 const char *name;
9728 Jim_CallFrame *framePtr;
9729 int global;
9730
9731
9732 Jim_Var *var = Jim_Alloc(sizeof(*var));
9733
9734 var->objPtr = valObjPtr;
9735 Jim_IncrRefCount(valObjPtr);
9736 var->linkFramePtr = NULL;
@@ -9745,14 +9779,14 @@
9745 else {
9746 framePtr = interp->framePtr;
9747 global = 0;
9748 }
9749
9750
9751 Jim_AddHashEntry(&framePtr->vars, name, var);
9752
9753
9754 Jim_FreeIntRep(interp, nameObjPtr);
9755 nameObjPtr->typePtr = &variableObjType;
9756 nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
9757 nameObjPtr->internalRep.varValue.varPtr = var;
9758 nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9816,11 @@
9782 if (var->linkFramePtr == NULL) {
9783 Jim_IncrRefCount(valObjPtr);
9784 Jim_DecrRefCount(interp, var->objPtr);
9785 var->objPtr = valObjPtr;
9786 }
9787 else {
9788 Jim_CallFrame *savedCallFrame;
9789
9790 savedCallFrame = interp->framePtr;
9791 interp->framePtr = var->linkFramePtr;
9792 err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9822,19 +9856,16 @@
9822 return result;
9823 }
9824
9825 int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val)
9826 {
9827 Jim_Obj *nameObjPtr, *valObjPtr;
9828 int result;
9829
9830 nameObjPtr = Jim_NewStringObj(interp, name, -1);
9831 valObjPtr = Jim_NewStringObj(interp, val, -1);
9832 Jim_IncrRefCount(nameObjPtr);
9833 Jim_IncrRefCount(valObjPtr);
9834 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
9835 Jim_DecrRefCount(interp, nameObjPtr);
9836 Jim_DecrRefCount(interp, valObjPtr);
9837 return result;
9838 }
9839
9840 int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
@@ -9843,14 +9874,14 @@
9843 const char *varName;
9844 const char *targetName;
9845 Jim_CallFrame *framePtr;
9846 Jim_Var *varPtr;
9847
9848
9849 switch (SetVariableFromAny(interp, nameObjPtr)) {
9850 case JIM_DICT_SUGAR:
9851
9852 Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
9853 return JIM_ERR;
9854
9855 case JIM_OK:
9856 varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9889,23 @@
9858 if (varPtr->linkFramePtr == NULL) {
9859 Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
9860 return JIM_ERR;
9861 }
9862
9863
9864 varPtr->linkFramePtr = NULL;
9865 break;
9866 }
9867
9868
9869
9870 varName = Jim_String(nameObjPtr);
9871
9872 if (varName[0] == ':' && varName[1] == ':') {
9873 while (*++varName == ':') {
9874 }
9875
9876 framePtr = interp->topFramePtr;
9877 }
9878 else {
9879 framePtr = interp->framePtr;
9880 }
@@ -9894,15 +9925,15 @@
9894 nameObjPtr);
9895 Jim_DecrRefCount(interp, targetNameObjPtr);
9896 return JIM_ERR;
9897 }
9898
9899
9900 if (framePtr == targetCallFrame) {
9901 Jim_Obj *objPtr = targetNameObjPtr;
9902
9903
9904 while (1) {
9905 if (strcmp(Jim_String(objPtr), varName) == 0) {
9906 Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
9907 Jim_DecrRefCount(interp, targetNameObjPtr);
9908 return JIM_ERR;
@@ -9914,13 +9945,13 @@
9914 break;
9915 objPtr = varPtr->objPtr;
9916 }
9917 }
9918
9919
9920 Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
9921
9922 nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
9923 Jim_DecrRefCount(interp, targetNameObjPtr);
9924 return JIM_OK;
9925 }
9926
@@ -9934,26 +9965,26 @@
9934 return varPtr->objPtr;
9935 }
9936 else {
9937 Jim_Obj *objPtr;
9938
9939
9940 Jim_CallFrame *savedCallFrame = interp->framePtr;
9941
9942 interp->framePtr = varPtr->linkFramePtr;
9943 objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
9944 interp->framePtr = savedCallFrame;
9945 if (objPtr) {
9946 return objPtr;
9947 }
9948
9949 }
9950 }
9951 break;
9952
9953 case JIM_DICT_SUGAR:
9954
9955 return JimDictSugarGet(interp, nameObjPtr, flags);
9956 }
9957 if (flags & JIM_ERRMSG) {
9958 Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
9959 }
@@ -10003,17 +10034,17 @@
10003 int retval;
10004 Jim_CallFrame *framePtr;
10005
10006 retval = SetVariableFromAny(interp, nameObjPtr);
10007 if (retval == JIM_DICT_SUGAR) {
10008
10009 return JimDictSugarSet(interp, nameObjPtr, NULL);
10010 }
10011 else if (retval == JIM_OK) {
10012 varPtr = nameObjPtr->internalRep.varValue.varPtr;
10013
10014
10015 if (varPtr->linkFramePtr) {
10016 framePtr = interp->framePtr;
10017 interp->framePtr = varPtr->linkFramePtr;
10018 retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
10019 interp->framePtr = framePtr;
@@ -10028,11 +10059,11 @@
10028 framePtr = interp->framePtr;
10029 }
10030
10031 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
10032 if (retval == JIM_OK) {
10033
10034 framePtr->id = interp->callFrameEpoch++;
10035 }
10036 }
10037 }
10038 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10092,11 @@
10061 keyLen = (str + len) - p;
10062 if (str[len - 1] == ')') {
10063 keyLen--;
10064 }
10065
10066
10067 keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
10068
10069 Jim_IncrRefCount(varObjPtr);
10070 Jim_IncrRefCount(keyObjPtr);
10071 *varPtrPtr = varObjPtr;
@@ -10080,23 +10111,23 @@
10080
10081 err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
10082 &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
10083
10084 if (err == JIM_OK) {
10085
10086 Jim_SetEmptyResult(interp);
10087 }
10088 else {
10089 if (!valObjPtr) {
10090
10091 if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
10092 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
10093 objPtr);
10094 return err;
10095 }
10096 }
10097
10098 Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
10099 (valObjPtr ? "set" : "unset"), objPtr);
10100 }
10101 return err;
10102 }
@@ -10118,11 +10149,11 @@
10118 Jim_SetResultFormatted(interp,
10119 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
10120 ret < 0 ? "variable isn't" : "no such element in");
10121 }
10122 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10123
10124 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
10125 }
10126
10127 return resObjPtr;
10128 }
@@ -10143,28 +10174,27 @@
10143 {
10144 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr);
10145 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
10146 }
10147
10148 void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
10149 {
10150 JIM_NOTUSED(interp);
10151
10152 dupPtr->internalRep.dictSubstValue.varNameObjPtr =
10153 srcPtr->internalRep.dictSubstValue.varNameObjPtr;
10154 dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr;
10155 dupPtr->typePtr = &dictSubstObjType;
10156 }
10157
10158
10159 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10160 {
10161 if (objPtr->typePtr != &dictSubstObjType) {
10162 Jim_Obj *varObjPtr, *keyObjPtr;
10163
10164 if (objPtr->typePtr == &interpolatedObjType) {
10165
10166
10167 varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
10168 keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
10169
10170 Jim_IncrRefCount(varObjPtr);
@@ -10202,16 +10232,12 @@
10202 return resObjPtr;
10203 }
10204
10205 static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
10206 {
10207 Jim_Obj *resultObjPtr;
10208
10209 if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
10210
10211 resultObjPtr->refCount--;
10212 return resultObjPtr;
10213 }
10214 return NULL;
10215 }
10216
10217
@@ -10249,11 +10275,11 @@
10249 return cf;
10250 }
10251
10252 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10253 {
10254
10255 if (localCommands) {
10256 Jim_Obj *cmdNameObj;
10257
10258 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10259 Jim_HashEntry *he;
@@ -10268,20 +10294,20 @@
10268 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10269 if (cmd->prevCmd) {
10270 Jim_Cmd *prevCmd = cmd->prevCmd;
10271 cmd->prevCmd = NULL;
10272
10273
10274 JimDecrCmdRefCount(interp, cmd);
10275
10276
10277 Jim_SetHashVal(ht, he, prevCmd);
10278 }
10279 else {
10280 Jim_DeleteHashEntry(ht, fqname);
10281 Jim_InterpIncrProcEpoch(interp);
10282 }
 
10283 }
10284 Jim_DecrRefCount(interp, cmdNameObj);
10285 JimFreeQualifiedName(interp, fqObjName);
10286 }
10287 Jim_FreeStack(localCommands);
@@ -10288,13 +10314,59 @@
10288 Jim_Free(localCommands);
10289 }
10290 return JIM_OK;
10291 }
10292
 
 
 
10293
10294 #define JIM_FCF_FULL 0
10295 #define JIM_FCF_REUSE 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10296 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10297 {
10298 JimDeleteLocalProcs(interp, cf->localCommands);
10299
10300 if (cf->procArgsObjPtr)
@@ -10327,263 +10399,10 @@
10327 cf->next = interp->freeFramesList;
10328 interp->freeFramesList = cf;
10329 }
10330
10331
10332 #ifdef JIM_REFERENCES
10333
10334 static void JimReferencesHTValDestructor(void *interp, void *val)
10335 {
10336 Jim_Reference *refPtr = (void *)val;
10337
10338 Jim_DecrRefCount(interp, refPtr->objPtr);
10339 if (refPtr->finalizerCmdNamePtr != NULL) {
10340 Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10341 }
10342 Jim_Free(val);
10343 }
10344
10345 static unsigned int JimReferencesHTHashFunction(const void *key)
10346 {
10347
10348 const unsigned long *widePtr = key;
10349 unsigned int intValue = (unsigned int)*widePtr;
10350
10351 return Jim_IntHashFunction(intValue);
10352 }
10353
10354 static void *JimReferencesHTKeyDup(void *privdata, const void *key)
10355 {
10356 void *copy = Jim_Alloc(sizeof(unsigned long));
10357
10358 JIM_NOTUSED(privdata);
10359
10360 memcpy(copy, key, sizeof(unsigned long));
10361 return copy;
10362 }
10363
10364 static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2)
10365 {
10366 JIM_NOTUSED(privdata);
10367
10368 return memcmp(key1, key2, sizeof(unsigned long)) == 0;
10369 }
10370
10371 static void JimReferencesHTKeyDestructor(void *privdata, void *key)
10372 {
10373 JIM_NOTUSED(privdata);
10374
10375 Jim_Free(key);
10376 }
10377
10378 static const Jim_HashTableType JimReferencesHashTableType = {
10379 JimReferencesHTHashFunction,
10380 JimReferencesHTKeyDup,
10381 NULL,
10382 JimReferencesHTKeyCompare,
10383 JimReferencesHTKeyDestructor,
10384 JimReferencesHTValDestructor
10385 };
10386
10387
10388
10389 #define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
10390
10391 static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
10392 {
10393 const char *fmt = "<reference.<%s>.%020lu>";
10394
10395 sprintf(buf, fmt, refPtr->tag, id);
10396 return JIM_REFERENCE_SPACE;
10397 }
10398
10399 static void UpdateStringOfReference(struct Jim_Obj *objPtr);
10400
10401 static const Jim_ObjType referenceObjType = {
10402 "reference",
10403 NULL,
10404 NULL,
10405 UpdateStringOfReference,
10406 JIM_TYPE_REFERENCES,
10407 };
10408
10409 static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10410 {
10411 char buf[JIM_REFERENCE_SPACE + 1];
10412
10413 JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10414 JimSetStringBytes(objPtr, buf);
10415 }
10416
10417 static int isrefchar(int c)
10418 {
10419 return (c == '_' || isalnum(c));
10420 }
10421
10422 static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10423 {
10424 unsigned long value;
10425 int i, len;
10426 const char *str, *start, *end;
10427 char refId[21];
10428 Jim_Reference *refPtr;
10429 Jim_HashEntry *he;
10430 char *endptr;
10431
10432
10433 str = Jim_GetString(objPtr, &len);
10434
10435 if (len < JIM_REFERENCE_SPACE)
10436 goto badformat;
10437
10438 start = str;
10439 end = str + len - 1;
10440 while (*start == ' ')
10441 start++;
10442 while (*end == ' ' && end > start)
10443 end--;
10444 if (end - start + 1 != JIM_REFERENCE_SPACE)
10445 goto badformat;
10446
10447 if (memcmp(start, "<reference.<", 12) != 0)
10448 goto badformat;
10449 if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
10450 goto badformat;
10451
10452 for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10453 if (!isrefchar(start[12 + i]))
10454 goto badformat;
10455 }
10456
10457 memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
10458 refId[20] = '\0';
10459
10460 value = strtoul(refId, &endptr, 10);
10461 if (JimCheckConversion(refId, endptr) != JIM_OK)
10462 goto badformat;
10463
10464 he = Jim_FindHashEntry(&interp->references, &value);
10465 if (he == NULL) {
10466 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10467 return JIM_ERR;
10468 }
10469 refPtr = Jim_GetHashEntryVal(he);
10470
10471 Jim_FreeIntRep(interp, objPtr);
10472 objPtr->typePtr = &referenceObjType;
10473 objPtr->internalRep.refValue.id = value;
10474 objPtr->internalRep.refValue.refPtr = refPtr;
10475 return JIM_OK;
10476
10477 badformat:
10478 Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr);
10479 return JIM_ERR;
10480 }
10481
10482 Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
10483 {
10484 struct Jim_Reference *refPtr;
10485 unsigned long id;
10486 Jim_Obj *refObjPtr;
10487 const char *tag;
10488 int tagLen, i;
10489
10490
10491 Jim_CollectIfNeeded(interp);
10492
10493 refPtr = Jim_Alloc(sizeof(*refPtr));
10494 refPtr->objPtr = objPtr;
10495 Jim_IncrRefCount(objPtr);
10496 refPtr->finalizerCmdNamePtr = cmdNamePtr;
10497 if (cmdNamePtr)
10498 Jim_IncrRefCount(cmdNamePtr);
10499 id = interp->referenceNextId++;
10500 Jim_AddHashEntry(&interp->references, &id, refPtr);
10501 refObjPtr = Jim_NewObj(interp);
10502 refObjPtr->typePtr = &referenceObjType;
10503 refObjPtr->bytes = NULL;
10504 refObjPtr->internalRep.refValue.id = id;
10505 refObjPtr->internalRep.refValue.refPtr = refPtr;
10506 interp->referenceNextId++;
10507 tag = Jim_GetString(tagPtr, &tagLen);
10508 if (tagLen > JIM_REFERENCE_TAGLEN)
10509 tagLen = JIM_REFERENCE_TAGLEN;
10510 for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10511 if (i < tagLen && isrefchar(tag[i]))
10512 refPtr->tag[i] = tag[i];
10513 else
10514 refPtr->tag[i] = '_';
10515 }
10516 refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0';
10517 return refObjPtr;
10518 }
10519
10520 Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr)
10521 {
10522 if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR)
10523 return NULL;
10524 return objPtr->internalRep.refValue.refPtr;
10525 }
10526
10527 int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr)
10528 {
10529 Jim_Reference *refPtr;
10530
10531 if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10532 return JIM_ERR;
10533 Jim_IncrRefCount(cmdNamePtr);
10534 if (refPtr->finalizerCmdNamePtr)
10535 Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10536 refPtr->finalizerCmdNamePtr = cmdNamePtr;
10537 return JIM_OK;
10538 }
10539
10540 int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr)
10541 {
10542 Jim_Reference *refPtr;
10543
10544 if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10545 return JIM_ERR;
10546 *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr;
10547 return JIM_OK;
10548 }
10549
10550
10551
10552 static const Jim_HashTableType JimRefMarkHashTableType = {
10553 JimReferencesHTHashFunction,
10554 JimReferencesHTKeyDup,
10555 NULL,
10556 JimReferencesHTKeyCompare,
10557 JimReferencesHTKeyDestructor,
10558 NULL
10559 };
10560
10561
10562 int Jim_Collect(Jim_Interp *interp)
10563 {
10564 int collected = 0;
10565 return collected;
10566 }
10567
10568 #define JIM_COLLECT_ID_PERIOD 5000
10569 #define JIM_COLLECT_TIME_PERIOD 300
10570
10571 void Jim_CollectIfNeeded(Jim_Interp *interp)
10572 {
10573 unsigned long elapsedId;
10574 int elapsedTime;
10575
10576 elapsedId = interp->referenceNextId - interp->lastCollectId;
10577 elapsedTime = time(NULL) - interp->lastCollectTime;
10578
10579
10580 if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
10581 Jim_Collect(interp);
10582 }
10583 }
10584 #endif
10585
10586 int Jim_IsBigEndian(void)
10587 {
10588 union {
10589 unsigned short s;
@@ -10630,11 +10449,11 @@
10630 Jim_IncrRefCount(i->nullScriptObj);
10631 Jim_IncrRefCount(i->errorProc);
10632 Jim_IncrRefCount(i->trueObj);
10633 Jim_IncrRefCount(i->falseObj);
10634
10635
10636 Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
10637 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10638
10639 Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
10640 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,12 +10471,14 @@
10652 {
10653 Jim_CallFrame *cf, *cfx;
10654
10655 Jim_Obj *objPtr, *nextObjPtr;
10656
10657
10658 for (cf = i->framePtr; cf; cf = cfx) {
 
 
10659 cfx = cf->parent;
10660 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10661 }
10662
10663 Jim_DecrRefCount(i, i->emptyObj);
@@ -10684,10 +10505,11 @@
10684
10685 printf("\n-------------------------------------\n");
10686 printf("Objects still in the free list:\n");
10687 while (objPtr) {
10688 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
 
10689
10690 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10691 printf("%p (%d) %-10s: '%.20s...'\n",
10692 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10693 }
@@ -10705,27 +10527,27 @@
10705 printf("-------------------------------------\n\n");
10706 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10707 }
10708 #endif
10709
10710
10711 objPtr = i->freeList;
10712 while (objPtr) {
10713 nextObjPtr = objPtr->nextObjPtr;
10714 Jim_Free(objPtr);
10715 objPtr = nextObjPtr;
10716 }
10717
10718
10719 for (cf = i->freeFramesList; cf; cf = cfx) {
10720 cfx = cf->next;
10721 if (cf->vars.table)
10722 Jim_FreeHashTable(&cf->vars);
10723 Jim_Free(cf);
10724 }
10725
10726
10727 Jim_Free(i);
10728 }
10729
10730 Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
10731 {
@@ -10746,25 +10568,25 @@
10746 else {
10747 if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
10748 level = -1;
10749 }
10750 else {
10751
10752 level = interp->framePtr->level - level;
10753 }
10754 }
10755 }
10756 else {
10757 str = "1";
10758 level = interp->framePtr->level - 1;
10759 }
10760
10761 if (level == 0) {
10762 return interp->topFramePtr;
10763 }
10764 if (level > 0) {
10765
10766 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10767 if (framePtr->level == level) {
10768 return framePtr;
10769 }
10770 }
@@ -10779,19 +10601,19 @@
10779 long level;
10780 Jim_CallFrame *framePtr;
10781
10782 if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
10783 if (level <= 0) {
10784
10785 level = interp->framePtr->level + level;
10786 }
10787
10788 if (level == 0) {
10789 return interp->topFramePtr;
10790 }
10791
10792
10793 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10794 if (framePtr->level == level) {
10795 return framePtr;
10796 }
10797 }
@@ -10810,11 +10632,11 @@
10810
10811 static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
10812 {
10813 int len;
10814
10815
10816 Jim_IncrRefCount(stackTraceObj);
10817 Jim_DecrRefCount(interp, interp->stackTrace);
10818 interp->stackTrace = stackTraceObj;
10819 interp->errorFlag = 1;
10820
@@ -10831,32 +10653,32 @@
10831 {
10832 if (strcmp(procname, "unknown") == 0) {
10833 procname = "";
10834 }
10835 if (!*procname && !Jim_Length(fileNameObj)) {
10836
10837 return;
10838 }
10839
10840 if (Jim_IsShared(interp->stackTrace)) {
10841 Jim_DecrRefCount(interp, interp->stackTrace);
10842 interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
10843 Jim_IncrRefCount(interp->stackTrace);
10844 }
10845
10846
10847 if (!*procname && Jim_Length(fileNameObj)) {
10848
10849 int len = Jim_ListLength(interp, interp->stackTrace);
10850
10851 if (len >= 3) {
10852 Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10853 if (Jim_Length(objPtr)) {
10854
10855 objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10856 if (Jim_Length(objPtr) == 0) {
10857
10858 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10859 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10860 return;
10861 }
10862 }
@@ -10958,18 +10780,18 @@
10958 {
10959 jim_wide wideValue;
10960 const char *str;
10961
10962 if (objPtr->typePtr == &coercedDoubleObjType) {
10963
10964 objPtr->typePtr = &intObjType;
10965 return JIM_OK;
10966 }
10967
10968
10969 str = Jim_String(objPtr);
10970
10971 if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
10972 if (flags & JIM_ERRMSG) {
10973 Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
10974 }
10975 return JIM_ERR;
@@ -10976,11 +10798,11 @@
10976 }
10977 if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
10978 Jim_SetResultString(interp, "Integer value too big to be represented", -1);
10979 return JIM_ERR;
10980 }
10981
10982 Jim_FreeIntRep(interp, objPtr);
10983 objPtr->typePtr = &intObjType;
10984 objPtr->internalRep.wideValue = wideValue;
10985 return JIM_OK;
10986 }
@@ -11075,17 +10897,17 @@
11075 {
11076 char buf[JIM_DOUBLE_SPACE + 1];
11077 int i;
11078 int len = sprintf(buf, "%.12g", value);
11079
11080
11081 for (i = 0; i < len; i++) {
11082 if (buf[i] == '.' || buf[i] == 'e') {
11083 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
11084 char *e = strchr(buf, 'e');
11085 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
11086
11087 e += 2;
11088 memmove(e, e + 1, len - (e - buf));
11089 }
11090 #endif
11091 break;
@@ -11104,41 +10926,40 @@
11104 {
11105 double doubleValue;
11106 jim_wide wideValue;
11107 const char *str;
11108
11109 str = Jim_String(objPtr);
11110
11111 #ifdef HAVE_LONG_LONG
11112
11113 #define MIN_INT_IN_DOUBLE -(1LL << 53)
11114 #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
11115
11116 if (objPtr->typePtr == &intObjType
11117 && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
11118 && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
11119
11120
11121 objPtr->typePtr = &coercedDoubleObjType;
11122 return JIM_OK;
11123 }
11124 else
11125 #endif
 
 
11126 if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
11127
11128 Jim_FreeIntRep(interp, objPtr);
11129 objPtr->typePtr = &coercedDoubleObjType;
11130 objPtr->internalRep.wideValue = wideValue;
11131 return JIM_OK;
11132 }
11133 else {
11134
11135 if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
11136 Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
11137 return JIM_ERR;
11138 }
11139
11140 Jim_FreeIntRep(interp, objPtr);
11141 }
11142 objPtr->typePtr = &doubleObjType;
11143 objPtr->internalRep.doubleValue = doubleValue;
11144 return JIM_OK;
@@ -11170,10 +10991,50 @@
11170 objPtr->typePtr = &doubleObjType;
11171 objPtr->bytes = NULL;
11172 objPtr->internalRep.doubleValue = doubleValue;
11173 return objPtr;
11174 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11175
11176 static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
11177 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
11178 static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
11179 static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11082,11 @@
11221 #define JIM_ELESTR_QUOTE 2
11222 static unsigned char ListElementQuotingType(const char *s, int len)
11223 {
11224 int i, level, blevel, trySimple = 1;
11225
11226
11227 if (len == 0)
11228 return JIM_ELESTR_BRACE;
11229 if (s[0] == '"' || s[0] == '{') {
11230 trySimple = 0;
11231 goto testbrace;
@@ -11243,20 +11104,20 @@
11243 case '\n':
11244 case '\t':
11245 case '\f':
11246 case '\v':
11247 trySimple = 0;
11248
11249 case '{':
11250 case '}':
11251 goto testbrace;
11252 }
11253 }
11254 return JIM_ELESTR_SIMPLE;
11255
11256 testbrace:
11257
11258 if (s[len - 1] == '\\')
11259 return JIM_ELESTR_QUOTE;
11260 level = 0;
11261 blevel = 0;
11262 for (i = 0; i < len; i++) {
@@ -11372,11 +11233,11 @@
11372 int i, bufLen, realLength;
11373 const char *strRep;
11374 char *p;
11375 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
11376
11377
11378 if (objc > STATIC_QUOTING_LEN) {
11379 quotingType = Jim_Alloc(objc);
11380 }
11381 else {
11382 quotingType = staticQuoting;
@@ -11391,25 +11252,25 @@
11391 case JIM_ELESTR_SIMPLE:
11392 if (i != 0 || strRep[0] != '#') {
11393 bufLen += len;
11394 break;
11395 }
11396
11397 quotingType[i] = JIM_ELESTR_BRACE;
11398
11399 case JIM_ELESTR_BRACE:
11400 bufLen += len + 2;
11401 break;
11402 case JIM_ELESTR_QUOTE:
11403 bufLen += len * 2;
11404 break;
11405 }
11406 bufLen++;
11407 }
11408 bufLen++;
11409
11410
11411 p = objPtr->bytes = Jim_Alloc(bufLen + 1);
11412 realLength = 0;
11413 for (i = 0; i < objc; i++) {
11414 int len, qlen;
11415
@@ -11436,17 +11297,17 @@
11436 qlen = BackslashQuoteString(strRep, len, p);
11437 p += qlen;
11438 realLength += qlen;
11439 break;
11440 }
11441
11442 if (i + 1 != objc) {
11443 *p++ = ' ';
11444 realLength++;
11445 }
11446 }
11447 *p = '\0';
11448 objPtr->length = realLength;
11449
11450 if (quotingType != staticQuoting) {
11451 Jim_Free(quotingType);
11452 }
@@ -11477,21 +11338,21 @@
11477 listObjPtrPtr = JimDictPairs(objPtr, &len);
11478 for (i = 0; i < len; i++) {
11479 Jim_IncrRefCount(listObjPtrPtr[i]);
11480 }
11481
11482
11483 Jim_FreeIntRep(interp, objPtr);
11484 objPtr->typePtr = &listObjType;
11485 objPtr->internalRep.listValue.len = len;
11486 objPtr->internalRep.listValue.maxLen = len;
11487 objPtr->internalRep.listValue.ele = listObjPtrPtr;
11488
11489 return JIM_OK;
11490 }
11491
11492
11493 if (objPtr->typePtr == &sourceObjType) {
11494 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
11495 linenr = objPtr->internalRep.sourceValue.lineNumber;
11496 }
11497 else {
@@ -11498,20 +11359,20 @@
11498 fileNameObj = interp->emptyObj;
11499 linenr = 1;
11500 }
11501 Jim_IncrRefCount(fileNameObj);
11502
11503
11504 str = Jim_GetString(objPtr, &strLen);
11505
11506 Jim_FreeIntRep(interp, objPtr);
11507 objPtr->typePtr = &listObjType;
11508 objPtr->internalRep.listValue.len = 0;
11509 objPtr->internalRep.listValue.maxLen = 0;
11510 objPtr->internalRep.listValue.ele = NULL;
11511
11512
11513 if (strLen) {
11514 JimParserInit(&parser, str, strLen, linenr);
11515 while (!parser.eof) {
11516 Jim_Obj *elementPtr;
11517
@@ -11641,11 +11502,11 @@
11641 Jim_Obj *compare_script;
11642 int rc;
11643
11644 jim_wide ret = 0;
11645
11646
11647 compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
11648 Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
11649 Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
11650
11651 rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11524,27 @@
11663 int dst = 0;
11664 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11665
11666 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11667 if (comp(&ele[dst], &ele[src]) == 0) {
11668
11669 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11670 }
11671 else {
11672
11673 dst++;
11674 }
11675 ele[dst] = ele[src];
11676 }
11677
11678 ele[++dst] = ele[src];
11679
11680
 
 
 
 
 
 
11681 listObjPtr->internalRep.listValue.len = dst;
11682 }
11683
11684
11685 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11558,11 @@
11693 int rc;
11694
11695 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11696 SetListFromAny(interp, listObjPtr);
11697
11698
11699 prev_info = sort_info;
11700 sort_info = info;
11701
11702 vector = listObjPtr->internalRep.listValue.ele;
11703 len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11581,17 @@
11716 break;
11717 case JIM_LSORT_COMMAND:
11718 fn = ListSortCommand;
11719 break;
11720 default:
11721 fn = NULL;
11722 JimPanic((1, "ListSort called with invalid sort type"));
11723 return -1;
11724 }
11725
11726 if (info->indexed) {
11727
11728 info->subfn = fn;
11729 fn = ListSortIndexHelper;
11730 }
11731
11732 if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11615,11 @@
11750 int i;
11751 Jim_Obj **point;
11752
11753 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11754 if (requiredLen < 2) {
11755
11756 requiredLen = 4;
11757 }
11758 else {
11759 requiredLen *= 2;
11760 }
@@ -11936,34 +11801,34 @@
11936 for (i = 0; i < objc; i++)
11937 ListAppendList(objPtr, objv[i]);
11938 return objPtr;
11939 }
11940 else {
11941
11942 int len = 0, objLen;
11943 char *bytes, *p;
11944
11945
11946 for (i = 0; i < objc; i++) {
11947 len += Jim_Length(objv[i]);
11948 }
11949 if (objc)
11950 len += objc - 1;
11951
11952 p = bytes = Jim_Alloc(len + 1);
11953 for (i = 0; i < objc; i++) {
11954 const char *s = Jim_GetString(objv[i], &objLen);
11955
11956
11957 while (objLen && isspace(UCHAR(*s))) {
11958 s++;
11959 objLen--;
11960 len--;
11961 }
11962
11963 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11964
11965 if (objLen > 1 && s[objLen - 2] == '\\') {
11966 break;
11967 }
11968 objLen--;
11969 len--;
@@ -11990,11 +11855,11 @@
11990 int len, rangeLen;
11991
11992 if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
11993 Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
11994 return NULL;
11995 len = Jim_ListLength(interp, listObjPtr);
11996 first = JimRelToAbsIndex(len, first);
11997 last = JimRelToAbsIndex(len, last);
11998 JimRelToAbsRange(len, &first, &last, &rangeLen);
11999 if (first == 0 && last == len) {
12000 return listObjPtr;
@@ -12030,16 +11895,16 @@
12030 {
12031 Jim_DecrRefCount(interp, (Jim_Obj *)val);
12032 }
12033
12034 static const Jim_HashTableType JimDictHashTableType = {
12035 JimObjectHTHashFunction,
12036 JimObjectHTKeyValDup,
12037 JimObjectHTKeyValDup,
12038 JimObjectHTKeyCompare,
12039 JimObjectHTKeyValDestructor,
12040 JimObjectHTKeyValDestructor
12041 };
12042
12043 static const Jim_ObjType dictObjType = {
12044 "dict",
12045 FreeDictInternalRep,
@@ -12060,17 +11925,17 @@
12060 {
12061 Jim_HashTable *ht, *dupHt;
12062 Jim_HashTableIterator htiter;
12063 Jim_HashEntry *he;
12064
12065
12066 ht = srcPtr->internalRep.ptr;
12067 dupHt = Jim_Alloc(sizeof(*dupHt));
12068 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
12069 if (ht->size != 0)
12070 Jim_ExpandHashTable(dupHt, ht->size);
12071
12072 JimInitHashTableIterator(ht, &htiter);
12073 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
12074 Jim_AddHashEntry(dupHt, he->key, he->u.val);
12075 }
12076
@@ -12086,11 +11951,11 @@
12086 Jim_Obj **objv;
12087 int i;
12088
12089 ht = dictPtr->internalRep.ptr;
12090
12091
12092 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
12093 JimInitHashTableIterator(ht, &htiter);
12094 i = 0;
12095 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
12096 objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11965,15 @@
12100 return objv;
12101 }
12102
12103 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
12104 {
12105
12106 int len;
12107 Jim_Obj **objv = JimDictPairs(objPtr, &len);
12108
12109
12110 JimMakeListStringRep(objPtr, objv, len);
12111
12112 Jim_Free(objv);
12113 }
12114
@@ -12122,18 +11987,18 @@
12122
12123 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
12124 Jim_String(objPtr);
12125 }
12126
12127
12128 listlen = Jim_ListLength(interp, objPtr);
12129 if (listlen % 2) {
12130 Jim_SetResultString(interp, "missing value to go with key", -1);
12131 return JIM_ERR;
12132 }
12133 else {
12134
12135 Jim_HashTable *ht;
12136 int i;
12137
12138 ht = Jim_Alloc(sizeof(*ht));
12139 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12023,11 @@
12158 static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
12159 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
12160 {
12161 Jim_HashTable *ht = objPtr->internalRep.ptr;
12162
12163 if (valueObjPtr == NULL) {
12164 return Jim_DeleteHashEntry(ht, keyObjPtr);
12165 }
12166 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
12167 return JIM_OK;
12168 }
@@ -12209,12 +12074,14 @@
12209 if (flags & JIM_ERRMSG) {
12210 Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
12211 }
12212 return JIM_ERR;
12213 }
12214 *objPtrPtr = he->u.val;
12215 return JIM_OK;
 
 
12216 }
12217
12218
12219 int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
12220 {
@@ -12258,11 +12125,11 @@
12258 int shared, i;
12259
12260 varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
12261 if (objPtr == NULL) {
12262 if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12263
12264 return JIM_ERR;
12265 }
12266 varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
12267 if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
12268 Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12139,26 @@
12272 if ((shared = Jim_IsShared(objPtr)))
12273 varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
12274 for (i = 0; i < keyc; i++) {
12275 dictObjPtr = objPtr;
12276
12277
12278 if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
12279 goto err;
12280 }
12281
12282 if (i == keyc - 1) {
12283
12284 if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
12285 if (newObjPtr || (flags & JIM_MUSTEXIST)) {
12286 goto err;
12287 }
12288 }
12289 break;
12290 }
12291
12292
12293 Jim_InvalidateStringRep(dictObjPtr);
12294 if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
12295 newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
12296 if (Jim_IsShared(objPtr)) {
12297 objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12171,11 @@
12304 }
12305 objPtr = Jim_NewDictObj(interp, NULL, 0);
12306 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12307 }
12308 }
12309
12310 Jim_InvalidateStringRep(objPtr);
12311 Jim_InvalidateStringRep(varObjPtr);
12312 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12313 goto err;
12314 }
@@ -12341,11 +12208,11 @@
12341 char buf[JIM_INTEGER_SPACE + 1];
12342 if (objPtr->internalRep.intValue >= 0) {
12343 sprintf(buf, "%d", objPtr->internalRep.intValue);
12344 }
12345 else {
12346
12347 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12348 }
12349 JimSetStringBytes(objPtr, buf);
12350 }
12351 }
@@ -12354,14 +12221,14 @@
12354 {
12355 int idx, end = 0;
12356 const char *str;
12357 char *endptr;
12358
12359
12360 str = Jim_String(objPtr);
12361
12362
12363 if (strncmp(str, "end", 3) == 0) {
12364 end = 1;
12365 str += 3;
12366 idx = 0;
12367 }
@@ -12372,21 +12239,21 @@
12372 goto badindex;
12373 }
12374 str = endptr;
12375 }
12376
12377
12378 if (*str == '+' || *str == '-') {
12379 int sign = (*str == '+' ? 1 : -1);
12380
12381 idx += sign * jim_strtol(++str, &endptr);
12382 if (str == endptr || *endptr) {
12383 goto badindex;
12384 }
12385 str = endptr;
12386 }
12387
12388 while (isspace(UCHAR(*str))) {
12389 str++;
12390 }
12391 if (*str) {
12392 goto badindex;
@@ -12394,19 +12261,19 @@
12394 if (end) {
12395 if (idx > 0) {
12396 idx = INT_MAX;
12397 }
12398 else {
12399
12400 idx--;
12401 }
12402 }
12403 else if (idx < 0) {
12404 idx = -INT_MAX;
12405 }
12406
12407
12408 Jim_FreeIntRep(interp, objPtr);
12409 objPtr->typePtr = &indexObjType;
12410 objPtr->internalRep.intValue = idx;
12411 return JIM_OK;
12412
@@ -12416,11 +12283,11 @@
12416 return JIM_ERR;
12417 }
12418
12419 int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
12420 {
12421
12422 if (objPtr->typePtr == &intObjType) {
12423 jim_wide val = JimWideValue(objPtr);
12424
12425 if (val < 0)
12426 *indexPtr = -INT_MAX;
@@ -12448,11 +12315,11 @@
12448 "exit",
12449 "eval",
12450 NULL
12451 };
12452
12453 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
12454
12455 static const Jim_ObjType returnCodeObjType = {
12456 "return-code",
12457 NULL,
12458 NULL,
@@ -12473,18 +12340,18 @@
12473 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12474 {
12475 int returnCode;
12476 jim_wide wideValue;
12477
12478
12479 if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
12480 returnCode = (int)wideValue;
12481 else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
12482 Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
12483 return JIM_ERR;
12484 }
12485
12486 Jim_FreeIntRep(interp, objPtr);
12487 objPtr->typePtr = &returnCodeObjType;
12488 objPtr->internalRep.intValue = returnCode;
12489 return JIM_OK;
12490 }
@@ -12498,19 +12365,19 @@
12498 }
12499
12500 static int JimParseExprOperator(struct JimParserCtx *pc);
12501 static int JimParseExprNumber(struct JimParserCtx *pc);
12502 static int JimParseExprIrrational(struct JimParserCtx *pc);
12503
12504
12505
12506
12507 enum
12508 {
12509
12510
12511 JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
 
12512 JIM_EXPROP_DIV,
12513 JIM_EXPROP_MOD,
12514 JIM_EXPROP_SUB,
12515 JIM_EXPROP_ADD,
12516 JIM_EXPROP_LSHIFT,
@@ -12521,66 +12388,48 @@
12521 JIM_EXPROP_GT,
12522 JIM_EXPROP_LTE,
12523 JIM_EXPROP_GTE,
12524 JIM_EXPROP_NUMEQ,
12525 JIM_EXPROP_NUMNE,
12526 JIM_EXPROP_BITAND,
12527 JIM_EXPROP_BITXOR,
12528 JIM_EXPROP_BITOR,
12529
12530
12531 JIM_EXPROP_LOGICAND,
12532 JIM_EXPROP_LOGICAND_LEFT,
12533 JIM_EXPROP_LOGICAND_RIGHT,
12534
12535
12536 JIM_EXPROP_LOGICOR,
12537 JIM_EXPROP_LOGICOR_LEFT,
12538 JIM_EXPROP_LOGICOR_RIGHT,
12539
12540
12541
12542 JIM_EXPROP_TERNARY,
12543 JIM_EXPROP_TERNARY_LEFT,
12544 JIM_EXPROP_TERNARY_RIGHT,
12545
12546
12547 JIM_EXPROP_COLON,
12548 JIM_EXPROP_COLON_LEFT,
12549 JIM_EXPROP_COLON_RIGHT,
12550
12551 JIM_EXPROP_POW,
12552
12553
12554 JIM_EXPROP_STREQ,
12555 JIM_EXPROP_STRNE,
12556 JIM_EXPROP_STRIN,
12557 JIM_EXPROP_STRNI,
12558
12559
12560 JIM_EXPROP_NOT,
12561 JIM_EXPROP_BITNOT,
12562 JIM_EXPROP_UNARYMINUS,
12563 JIM_EXPROP_UNARYPLUS,
12564
12565
12566 JIM_EXPROP_FUNC_FIRST,
12567 JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
12568 JIM_EXPROP_FUNC_WIDE,
12569 JIM_EXPROP_FUNC_ABS,
12570 JIM_EXPROP_FUNC_DOUBLE,
12571 JIM_EXPROP_FUNC_ROUND,
12572 JIM_EXPROP_FUNC_RAND,
12573 JIM_EXPROP_FUNC_SRAND,
12574
12575
12576 JIM_EXPROP_FUNC_SIN,
12577 JIM_EXPROP_FUNC_COS,
12578 JIM_EXPROP_FUNC_TAN,
12579 JIM_EXPROP_FUNC_ASIN,
12580 JIM_EXPROP_FUNC_ACOS,
12581 JIM_EXPROP_FUNC_ATAN,
 
12582 JIM_EXPROP_FUNC_SINH,
12583 JIM_EXPROP_FUNC_COSH,
12584 JIM_EXPROP_FUNC_TANH,
12585 JIM_EXPROP_FUNC_CEIL,
12586 JIM_EXPROP_FUNC_FLOOR,
@@ -12587,52 +12436,52 @@
12587 JIM_EXPROP_FUNC_EXP,
12588 JIM_EXPROP_FUNC_LOG,
12589 JIM_EXPROP_FUNC_LOG10,
12590 JIM_EXPROP_FUNC_SQRT,
12591 JIM_EXPROP_FUNC_POW,
 
 
12592 };
12593
12594 struct JimExprState
12595 {
12596 Jim_Obj **stack;
12597 int stacklen;
12598 int opcode;
12599 int skip;
 
12600 };
12601
12602
12603 typedef struct Jim_ExprOperator
12604 {
12605 const char *name;
12606 int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12607 unsigned char precedence;
12608 unsigned char arity;
12609 unsigned char lazy;
12610 unsigned char namelen;
12611 } Jim_ExprOperator;
12612
12613 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12614 {
12615 Jim_IncrRefCount(obj);
12616 e->stack[e->stacklen++] = obj;
12617 }
12618
12619 static Jim_Obj *ExprPop(struct JimExprState *e)
12620 {
12621 return e->stack[--e->stacklen];
12622 }
12623
12624 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12625 {
12626 int intresult = 1;
12627 int rc = JIM_OK;
12628 Jim_Obj *A = ExprPop(e);
12629 double dA, dC = 0;
12630 jim_wide wA, wC = 0;
 
 
 
 
 
12631
12632 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12633 switch (e->opcode) {
12634 case JIM_EXPROP_FUNC_INT:
12635 case JIM_EXPROP_FUNC_WIDE:
12636 case JIM_EXPROP_FUNC_ROUND:
12637 case JIM_EXPROP_UNARYPLUS:
12638 wC = wA;
@@ -12653,11 +12502,11 @@
12653 default:
12654 abort();
12655 }
12656 }
12657 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12658 switch (e->opcode) {
12659 case JIM_EXPROP_FUNC_INT:
12660 case JIM_EXPROP_FUNC_WIDE:
12661 wC = dA;
12662 break;
12663 case JIM_EXPROP_FUNC_ROUND:
@@ -12667,11 +12516,15 @@
12667 case JIM_EXPROP_UNARYPLUS:
12668 dC = dA;
12669 intresult = 0;
12670 break;
12671 case JIM_EXPROP_FUNC_ABS:
 
 
 
12672 dC = dA >= 0 ? dA : -dA;
 
12673 intresult = 0;
12674 break;
12675 case JIM_EXPROP_UNARYMINUS:
12676 dC = -dA;
12677 intresult = 0;
@@ -12684,14 +12537,14 @@
12684 }
12685 }
12686
12687 if (rc == JIM_OK) {
12688 if (intresult) {
12689 ExprPush(e, Jim_NewIntObj(interp, wC));
12690 }
12691 else {
12692 ExprPush(e, Jim_NewDoubleObj(interp, dC));
12693 }
12694 }
12695
12696 Jim_DecrRefCount(interp, A);
12697
@@ -12704,24 +12557,29 @@
12704 JimRandomBytes(interp, &x, sizeof(x));
12705
12706 return (double)x / (unsigned long)~0;
12707 }
12708
12709 static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
12710 {
12711 Jim_Obj *A = ExprPop(e);
12712 jim_wide wA;
 
 
12713
12714 int rc = Jim_GetWide(interp, A, &wA);
 
 
 
 
12715 if (rc == JIM_OK) {
12716 switch (e->opcode) {
12717 case JIM_EXPROP_BITNOT:
12718 ExprPush(e, Jim_NewIntObj(interp, ~wA));
12719 break;
12720 case JIM_EXPROP_FUNC_SRAND:
12721 JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
12722 ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12723 break;
12724 default:
12725 abort();
12726 }
12727 }
@@ -12729,29 +12587,33 @@
12729 Jim_DecrRefCount(interp, A);
12730
12731 return rc;
12732 }
12733
12734 static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
12735 {
12736 JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
12737
12738 ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12739
12740 return JIM_OK;
12741 }
12742
12743 #ifdef JIM_MATH_FUNCTIONS
12744 static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
12745 {
12746 int rc;
12747 Jim_Obj *A = ExprPop(e);
12748 double dA, dC;
 
 
 
 
 
12749
12750 rc = Jim_GetDouble(interp, A, &dA);
12751 if (rc == JIM_OK) {
12752 switch (e->opcode) {
12753 case JIM_EXPROP_FUNC_SIN:
12754 dC = sin(dA);
12755 break;
12756 case JIM_EXPROP_FUNC_COS:
12757 dC = cos(dA);
@@ -12796,33 +12658,42 @@
12796 dC = sqrt(dA);
12797 break;
12798 default:
12799 abort();
12800 }
12801 ExprPush(e, Jim_NewDoubleObj(interp, dC));
12802 }
12803
12804 Jim_DecrRefCount(interp, A);
12805
12806 return rc;
12807 }
12808 #endif
12809
12810
12811 static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
12812 {
12813 Jim_Obj *B = ExprPop(e);
12814 Jim_Obj *A = ExprPop(e);
12815 jim_wide wA, wB;
12816 int rc = JIM_ERR;
 
 
 
 
 
 
 
 
 
 
 
12817
12818 if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) {
12819 jim_wide wC;
12820
12821 rc = JIM_OK;
12822
12823 switch (e->opcode) {
12824 case JIM_EXPROP_LSHIFT:
12825 wC = wA << wB;
12826 break;
12827 case JIM_EXPROP_RSHIFT:
12828 wC = wA >> wB;
@@ -12859,29 +12730,28 @@
12859 }
12860 }
12861 break;
12862 case JIM_EXPROP_ROTL:
12863 case JIM_EXPROP_ROTR:{
12864
12865 unsigned long uA = (unsigned long)wA;
12866 unsigned long uB = (unsigned long)wB;
12867 const unsigned int S = sizeof(unsigned long) * 8;
12868
12869
12870 uB %= S;
12871
12872 if (e->opcode == JIM_EXPROP_ROTR) {
12873 uB = S - uB;
12874 }
12875 wC = (unsigned long)(uA << uB) | (uA >> (S - uB));
12876 break;
12877 }
12878 default:
12879 abort();
12880 }
12881 ExprPush(e, Jim_NewIntObj(interp, wC));
12882
12883 }
12884
12885 Jim_DecrRefCount(interp, A);
12886 Jim_DecrRefCount(interp, B);
12887
@@ -12888,44 +12758,55 @@
12888 return rc;
12889 }
12890
12891
12892
12893 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12894 {
12895 int intresult = 1;
12896 int rc = JIM_OK;
12897 double dA, dB, dC = 0;
12898 jim_wide wA, wB, wC = 0;
 
12899
12900 Jim_Obj *B = ExprPop(e);
12901 Jim_Obj *A = ExprPop(e);
 
 
 
 
 
12902
12903 if ((A->typePtr != &doubleObjType || A->bytes) &&
12904 (B->typePtr != &doubleObjType || B->bytes) &&
12905 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12906
12907
12908
12909 switch (e->opcode) {
 
12910 case JIM_EXPROP_POW:
12911 case JIM_EXPROP_FUNC_POW:
 
 
 
 
 
12912 wC = JimPowWide(wA, wB);
12913 break;
12914 case JIM_EXPROP_ADD:
12915 wC = wA + wB;
12916 break;
12917 case JIM_EXPROP_SUB:
12918 wC = wA - wB;
12919 break;
12920 case JIM_EXPROP_MUL:
12921 wC = wA * wB;
12922 break;
12923 case JIM_EXPROP_DIV:
12924 if (wB == 0) {
12925 Jim_SetResultString(interp, "Division by zero", -1);
12926 rc = JIM_ERR;
 
12927 }
12928 else {
12929 if (wB < 0) {
12930 wB = -wB;
12931 wA = -wA;
@@ -12932,55 +12813,67 @@
12932 }
12933 wC = wA / wB;
12934 if (wA % wB < 0) {
12935 wC--;
12936 }
 
12937 }
12938 break;
12939 case JIM_EXPROP_LT:
12940 wC = wA < wB;
12941 break;
12942 case JIM_EXPROP_GT:
12943 wC = wA > wB;
12944 break;
12945 case JIM_EXPROP_LTE:
12946 wC = wA <= wB;
12947 break;
12948 case JIM_EXPROP_GTE:
12949 wC = wA >= wB;
12950 break;
12951 case JIM_EXPROP_NUMEQ:
12952 wC = wA == wB;
12953 break;
12954 case JIM_EXPROP_NUMNE:
12955 wC = wA != wB;
12956 break;
12957 default:
12958 abort();
12959 }
12960 }
12961 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12962 intresult = 0;
12963 switch (e->opcode) {
12964 case JIM_EXPROP_POW:
12965 case JIM_EXPROP_FUNC_POW:
12966 #ifdef JIM_MATH_FUNCTIONS
12967 dC = pow(dA, dB);
12968 #else
12969 Jim_SetResultString(interp, "unsupported", -1);
12970 rc = JIM_ERR;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12971 #endif
12972 break;
12973 case JIM_EXPROP_ADD:
12974 dC = dA + dB;
12975 break;
12976 case JIM_EXPROP_SUB:
12977 dC = dA - dB;
12978 break;
12979 case JIM_EXPROP_MUL:
12980 dC = dA * dB;
12981 break;
12982 case JIM_EXPROP_DIV:
12983 if (dB == 0) {
12984 #ifdef INFINITY
12985 dC = dA < 0 ? -INFINITY : INFINITY;
12986 #else
@@ -12988,83 +12881,70 @@
12988 #endif
12989 }
12990 else {
12991 dC = dA / dB;
12992 }
12993 break;
12994 case JIM_EXPROP_LT:
12995 wC = dA < dB;
12996 intresult = 1;
12997 break;
12998 case JIM_EXPROP_GT:
12999 wC = dA > dB;
13000 intresult = 1;
13001 break;
13002 case JIM_EXPROP_LTE:
13003 wC = dA <= dB;
13004 intresult = 1;
13005 break;
13006 case JIM_EXPROP_GTE:
13007 wC = dA >= dB;
13008 intresult = 1;
13009 break;
13010 case JIM_EXPROP_NUMEQ:
13011 wC = dA == dB;
13012 intresult = 1;
13013 break;
13014 case JIM_EXPROP_NUMNE:
13015 wC = dA != dB;
13016 intresult = 1;
13017 break;
13018 default:
13019 abort();
13020 }
13021 }
13022 else {
13023
13024
13025
 
13026 int i = Jim_StringCompareObj(interp, A, B, 0);
13027
13028 switch (e->opcode) {
13029 case JIM_EXPROP_LT:
13030 wC = i < 0;
13031 break;
13032 case JIM_EXPROP_GT:
13033 wC = i > 0;
13034 break;
13035 case JIM_EXPROP_LTE:
13036 wC = i <= 0;
13037 break;
13038 case JIM_EXPROP_GTE:
13039 wC = i >= 0;
13040 break;
13041 case JIM_EXPROP_NUMEQ:
13042 wC = i == 0;
13043 break;
13044 case JIM_EXPROP_NUMNE:
13045 wC = i != 0;
13046 break;
13047 default:
13048 rc = JIM_ERR;
13049 break;
13050 }
13051 }
13052
13053 if (rc == JIM_OK) {
13054 if (intresult) {
13055 ExprPush(e, Jim_NewIntObj(interp, wC));
13056 }
13057 else {
13058 ExprPush(e, Jim_NewDoubleObj(interp, dC));
13059 }
13060 }
13061
13062 Jim_DecrRefCount(interp, A);
13063 Jim_DecrRefCount(interp, B);
13064
13065 return rc;
 
 
 
 
 
 
13066 }
13067
13068 static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
13069 {
13070 int listlen;
@@ -13077,22 +12957,31 @@
13077 }
13078 }
13079 return 0;
13080 }
13081
13082 static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
 
 
13083 {
13084 Jim_Obj *B = ExprPop(e);
13085 Jim_Obj *A = ExprPop(e);
13086
13087 jim_wide wC;
 
13088
13089 switch (e->opcode) {
 
 
 
 
 
 
 
 
13090 case JIM_EXPROP_STREQ:
13091 case JIM_EXPROP_STRNE:
13092 wC = Jim_StringEqObj(A, B);
13093 if (e->opcode == JIM_EXPROP_STRNE) {
13094 wC = !wC;
13095 }
13096 break;
13097 case JIM_EXPROP_STRIN:
13098 wC = JimSearchList(interp, B, A);
@@ -13101,178 +12990,99 @@
13101 wC = !JimSearchList(interp, B, A);
13102 break;
13103 default:
13104 abort();
13105 }
13106 ExprPush(e, Jim_NewIntObj(interp, wC));
13107
13108 Jim_DecrRefCount(interp, A);
13109 Jim_DecrRefCount(interp, B);
13110
13111 return JIM_OK;
13112 }
13113
13114 static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
13115 {
13116 long l;
13117 double d;
 
 
 
 
 
13118
13119 if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
13120 return l != 0;
13121 }
13122 if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13123 return d != 0;
13124 }
13125 return -1;
13126 }
13127
13128 static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
13129 {
13130 Jim_Obj *skip = ExprPop(e);
13131 Jim_Obj *A = ExprPop(e);
13132 int rc = JIM_OK;
13133
13134 switch (ExprBool(interp, A)) {
13135 case 0:
13136
13137 e->skip = JimWideValue(skip);
13138 ExprPush(e, Jim_NewIntObj(interp, 0));
13139 break;
13140
13141 case 1:
13142
13143 break;
13144
13145 case -1:
13146
13147 rc = JIM_ERR;
13148 }
13149 Jim_DecrRefCount(interp, A);
13150 Jim_DecrRefCount(interp, skip);
13151
13152 return rc;
13153 }
13154
13155 static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e)
13156 {
13157 Jim_Obj *skip = ExprPop(e);
13158 Jim_Obj *A = ExprPop(e);
13159 int rc = JIM_OK;
13160
13161 switch (ExprBool(interp, A)) {
13162 case 0:
13163
13164 break;
13165
13166 case 1:
13167
13168 e->skip = JimWideValue(skip);
13169 ExprPush(e, Jim_NewIntObj(interp, 1));
13170 break;
13171
13172 case -1:
13173
13174 rc = JIM_ERR;
13175 break;
13176 }
13177 Jim_DecrRefCount(interp, A);
13178 Jim_DecrRefCount(interp, skip);
13179
13180 return rc;
13181 }
13182
13183 static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e)
13184 {
13185 Jim_Obj *A = ExprPop(e);
13186 int rc = JIM_OK;
13187
13188 switch (ExprBool(interp, A)) {
13189 case 0:
13190 ExprPush(e, Jim_NewIntObj(interp, 0));
13191 break;
13192
13193 case 1:
13194 ExprPush(e, Jim_NewIntObj(interp, 1));
13195 break;
13196
13197 case -1:
13198
13199 rc = JIM_ERR;
13200 break;
13201 }
13202 Jim_DecrRefCount(interp, A);
13203
13204 return rc;
13205 }
13206
13207 static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e)
13208 {
13209 Jim_Obj *skip = ExprPop(e);
13210 Jim_Obj *A = ExprPop(e);
13211 int rc = JIM_OK;
13212
13213
13214 ExprPush(e, A);
13215
13216 switch (ExprBool(interp, A)) {
13217 case 0:
13218
13219 e->skip = JimWideValue(skip);
13220
13221 ExprPush(e, Jim_NewIntObj(interp, 0));
13222 break;
13223
13224 case 1:
13225
13226 break;
13227
13228 case -1:
13229
13230 rc = JIM_ERR;
13231 break;
13232 }
13233 Jim_DecrRefCount(interp, A);
13234 Jim_DecrRefCount(interp, skip);
13235
13236 return rc;
13237 }
13238
13239 static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e)
13240 {
13241 Jim_Obj *skip = ExprPop(e);
13242 Jim_Obj *B = ExprPop(e);
13243 Jim_Obj *A = ExprPop(e);
13244
13245
13246 if (ExprBool(interp, A)) {
13247
13248 e->skip = JimWideValue(skip);
13249
13250 ExprPush(e, B);
13251 }
13252
13253 Jim_DecrRefCount(interp, skip);
13254 Jim_DecrRefCount(interp, A);
13255 Jim_DecrRefCount(interp, B);
13256 return JIM_OK;
13257 }
13258
13259 static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e)
13260 {
13261 return JIM_OK;
13262 }
13263
13264 enum
13265 {
13266 LAZY_NONE,
13267 LAZY_OP,
13268 LAZY_LEFT,
13269 LAZY_RIGHT
13270 };
13271
13272 #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13273 #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13274
13275 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13276 OPRINIT("*", 110, 2, JimExprOpBin),
13277 OPRINIT("/", 110, 2, JimExprOpBin),
13278 OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,86 +13106,79 @@
13296
13297 OPRINIT("&", 50, 2, JimExprOpIntBin),
13298 OPRINIT("^", 49, 2, JimExprOpIntBin),
13299 OPRINIT("|", 48, 2, JimExprOpIntBin),
13300
13301 OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13302 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13303 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13304
13305 OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13306 OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13307 OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13308
13309 OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13310 OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13311 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13312
13313 OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13314 OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13315 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13316
13317 OPRINIT("**", 250, 2, JimExprOpBin),
13318
13319 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13320 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13321
13322 OPRINIT("in", 55, 2, JimExprOpStrBin),
13323 OPRINIT("ni", 55, 2, JimExprOpStrBin),
13324
13325 OPRINIT("!", 150, 1, JimExprOpNumUnary),
13326 OPRINIT("~", 150, 1, JimExprOpIntUnary),
13327 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13328 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13329
13330
13331
13332 OPRINIT("int", 200, 1, JimExprOpNumUnary),
13333 OPRINIT("wide", 200, 1, JimExprOpNumUnary),
13334 OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13335 OPRINIT("double", 200, 1, JimExprOpNumUnary),
13336 OPRINIT("round", 200, 1, JimExprOpNumUnary),
13337 OPRINIT("rand", 200, 0, JimExprOpNone),
13338 OPRINIT("srand", 200, 1, JimExprOpIntUnary),
13339
13340 #ifdef JIM_MATH_FUNCTIONS
13341 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13342 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13343 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13344 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13345 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13346 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13347 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13348 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13349 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13350 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13351 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13352 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13353 OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13354 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13355 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13356 OPRINIT("pow", 200, 2, JimExprOpBin),
 
 
 
13357 #endif
13358 };
13359 #undef OPRINIT
13360 #undef OPRINIT_LAZY
13361
13362 #define JIM_EXPR_OPERATORS_NUM \
13363 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13364
13365 static int JimParseExpression(struct JimParserCtx *pc)
13366 {
13367
13368 while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
13369 if (*pc->p == '\n') {
13370 pc->linenr++;
13371 }
13372 pc->p++;
13373 pc->len--;
13374 }
13375
13376
13377 pc->tline = pc->linenr;
13378 pc->tstart = pc->p;
13379
13380 if (pc->len == 0) {
13381 pc->tend = pc->p;
@@ -13401,11 +13204,11 @@
13401 return JimParseCmd(pc);
13402 case '$':
13403 if (JimParseVar(pc) == JIM_ERR)
13404 return JimParseExprOperator(pc);
13405 else {
13406
13407 if (pc->tt == JIM_TT_EXPRSUGAR) {
13408 return JIM_ERR;
13409 }
13410 return JIM_OK;
13411 }
@@ -13430,10 +13233,18 @@
13430 case 'N':
13431 case 'I':
13432 case 'n':
13433 case 'i':
13434 if (JimParseExprIrrational(pc) == JIM_ERR)
 
 
 
 
 
 
 
 
13435 return JimParseExprOperator(pc);
13436 break;
13437 default:
13438 return JimParseExprOperator(pc);
13439 break;
@@ -13443,21 +13254,21 @@
13443
13444 static int JimParseExprNumber(struct JimParserCtx *pc)
13445 {
13446 char *end;
13447
13448
13449 pc->tt = JIM_TT_EXPR_INT;
13450
13451 jim_strtoull(pc->p, (char **)&pc->p);
13452
13453 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13454 if (strtod(pc->tstart, &end)) { }
13455 if (end == pc->tstart)
13456 return JIM_ERR;
13457 if (end > pc->p) {
13458
13459 pc->tt = JIM_TT_EXPR_DOUBLE;
13460 pc->p = end;
13461 }
13462 }
13463 pc->tend = pc->p - 1;
@@ -13481,36 +13292,66 @@
13481 return JIM_OK;
13482 }
13483 }
13484 return JIM_ERR;
13485 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13486
13487 static int JimParseExprOperator(struct JimParserCtx *pc)
13488 {
13489 int i;
13490 int bestIdx = -1, bestLen = 0;
 
13491
13492
13493 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13494 const char * const opname = Jim_ExprOperators[i].name;
13495 const int oplen = Jim_ExprOperators[i].namelen;
13496
13497 if (opname == NULL || opname[0] != pc->p[0]) {
13498 continue;
13499 }
13500
13501 if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
13502 bestIdx = i + JIM_TT_EXPR_OP;
13503 bestLen = oplen;
13504 }
13505 }
13506 if (bestIdx == -1) {
13507 return JIM_ERR;
13508 }
13509
13510
13511 if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
13512 const char *p = pc->p + bestLen;
13513 int len = pc->len - bestLen;
13514
13515 while (len && isspace(UCHAR(*p))) {
13516 len--;
@@ -13522,30 +13363,27 @@
13522 }
13523 pc->tend = pc->p + bestLen - 1;
13524 pc->p += bestLen;
13525 pc->len -= bestLen;
13526
13527 pc->tt = bestIdx;
13528 return JIM_OK;
13529 }
13530
13531 static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
13532 {
13533 static Jim_ExprOperator dummy_op;
13534 if (opcode < JIM_TT_EXPR_OP) {
13535 return &dummy_op;
13536 }
13537 return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
13538 }
13539
13540 const char *jim_tt_name(int type)
13541 {
13542 static const char * const tt_names[JIM_TT_EXPR_OP] =
13543 { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13544 "DBL", "$()" };
13545 if (type < JIM_TT_EXPR_OP) {
13546 return tt_names[type];
 
 
 
 
 
 
13547 }
13548 else {
13549 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
13550 static char buf[20];
13551
@@ -13568,432 +13406,400 @@
13568 NULL,
13569 JIM_TYPE_REFERENCES,
13570 };
13571
13572
13573 typedef struct ExprByteCode
13574 {
13575 ScriptToken *token;
13576 int len;
13577 int inUse;
13578 } ExprByteCode;
13579
13580 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
 
13581 {
13582 int i;
 
 
 
 
 
 
 
13583
13584 for (i = 0; i < expr->len; i++) {
13585 Jim_DecrRefCount(interp, expr->token[i].objPtr);
13586 }
13587 Jim_Free(expr->token);
13588 Jim_Free(expr);
13589 }
13590
13591 static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
13592 {
13593 ExprByteCode *expr = (void *)objPtr->internalRep.ptr;
13594
13595 if (expr) {
13596 if (--expr->inUse != 0) {
13597 return;
13598 }
13599
13600 ExprFreeByteCode(interp, expr);
13601 }
13602 }
13603
13604 static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
13605 {
13606 JIM_NOTUSED(interp);
13607 JIM_NOTUSED(srcPtr);
13608
13609
13610 dupPtr->typePtr = NULL;
13611 }
13612
13613
13614 static int ExprCheckCorrectness(ExprByteCode * expr)
13615 {
13616 int i;
13617 int stacklen = 0;
13618 int ternary = 0;
13619
13620 for (i = 0; i < expr->len; i++) {
13621 ScriptToken *t = &expr->token[i];
13622 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13623
13624 stacklen -= op->arity;
13625 if (stacklen < 0) {
13626 break;
13627 }
13628 if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
13629 ternary++;
13630 }
13631 else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
13632 ternary--;
13633 }
13634
13635
13636 stacklen++;
13637 }
13638 if (stacklen != 1 || ternary != 0) {
13639 return JIM_ERR;
13640 }
13641 return JIM_OK;
13642 }
13643
13644 static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13645 {
13646 int i;
13647
13648 int leftindex, arity, offset;
13649
13650
13651 leftindex = expr->len - 1;
13652
13653 arity = 1;
13654 while (arity) {
13655 ScriptToken *tt = &expr->token[leftindex];
13656
13657 if (tt->type >= JIM_TT_EXPR_OP) {
13658 arity += JimExprOperatorInfoByOpcode(tt->type)->arity;
13659 }
13660 arity--;
13661 if (--leftindex < 0) {
13662 return JIM_ERR;
13663 }
13664 }
13665 leftindex++;
13666
13667
13668 memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
13669 sizeof(*expr->token) * (expr->len - leftindex));
13670 expr->len += 2;
13671 offset = (expr->len - leftindex) - 1;
13672
13673 expr->token[leftindex + 1].type = t->type + 1;
13674 expr->token[leftindex + 1].objPtr = interp->emptyObj;
13675
13676 expr->token[leftindex].type = JIM_TT_EXPR_INT;
13677 expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
13678
13679
13680 expr->token[expr->len].objPtr = interp->emptyObj;
13681 expr->token[expr->len].type = t->type + 2;
13682 expr->len++;
13683
13684
13685 for (i = leftindex - 1; i > 0; i--) {
13686 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
13687 if (op->lazy == LAZY_LEFT) {
13688 if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
13689 JimWideValue(expr->token[i - 1].objPtr) += 2;
13690 }
13691 }
13692 }
13693 return JIM_OK;
13694 }
13695
13696 static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13697 {
13698 struct ScriptToken *token = &expr->token[expr->len];
13699 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13700
13701 if (op->lazy == LAZY_OP) {
13702 if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) {
13703 Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name);
13704 return JIM_ERR;
13705 }
13706 }
13707 else {
13708 token->objPtr = interp->emptyObj;
13709 token->type = t->type;
13710 expr->len++;
13711 }
13712 return JIM_OK;
13713 }
13714
13715 static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
13716 {
13717 int ternary_count = 1;
13718
13719 right_index--;
13720
13721 while (right_index > 1) {
13722 if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) {
13723 ternary_count--;
13724 }
13725 else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) {
13726 ternary_count++;
13727 }
13728 else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) {
13729 return right_index;
13730 }
13731 right_index--;
13732 }
13733
13734
13735 return -1;
13736 }
13737
13738 static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
13739 {
13740 int i = right_index - 1;
13741 int ternary_count = 1;
13742
13743 while (i > 1) {
13744 if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) {
13745 if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) {
13746 *prev_right_index = i - 2;
13747 *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index);
13748 return 1;
13749 }
13750 }
13751 else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) {
13752 if (ternary_count == 0) {
13753 return 0;
13754 }
13755 ternary_count++;
13756 }
13757 i--;
13758 }
13759 return 0;
13760 }
13761
13762 static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
13763 {
13764 int i;
13765
13766 for (i = expr->len - 1; i > 1; i--) {
13767 int prev_right_index;
13768 int prev_left_index;
13769 int j;
13770 ScriptToken tmp;
13771
13772 if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
13773 continue;
13774 }
13775
13776
13777 if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
13778 continue;
13779 }
13780
13781 tmp = expr->token[prev_right_index];
13782 for (j = prev_right_index; j < i; j++) {
13783 expr->token[j] = expr->token[j + 1];
13784 }
13785 expr->token[i] = tmp;
13786
13787 JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
13788
13789
13790 i++;
13791 }
13792 }
13793
13794 static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
13795 {
13796 Jim_Stack stack;
13797 ExprByteCode *expr;
13798 int ok = 1;
 
 
 
 
 
 
 
13799 int i;
13800 int prevtt = JIM_TT_NONE;
13801 int have_ternary = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13802
13803
13804 int count = tokenlist->count - 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13805
13806 expr = Jim_Alloc(sizeof(*expr));
13807 expr->inUse = 1;
13808 expr->len = 0;
13809
13810 Jim_InitStack(&stack);
13811
13812 for (i = 0; i < tokenlist->count; i++) {
13813 ParseToken *t = &tokenlist->list[i];
13814 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13815
13816 if (op->lazy == LAZY_OP) {
13817 count += 2;
13818
13819 if (t->type == JIM_EXPROP_TERNARY) {
13820 have_ternary = 1;
13821 }
13822 }
13823 }
13824
13825 expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
13826
13827 for (i = 0; i < tokenlist->count && ok; i++) {
13828 ParseToken *t = &tokenlist->list[i];
13829
13830
13831 struct ScriptToken *token = &expr->token[expr->len];
13832
13833 if (t->type == JIM_TT_EOL) {
13834 break;
13835 }
13836
13837 switch (t->type) {
13838 case JIM_TT_STR:
13839 case JIM_TT_ESC:
13840 case JIM_TT_VAR:
13841 case JIM_TT_DICTSUGAR:
13842 case JIM_TT_EXPRSUGAR:
13843 case JIM_TT_CMD:
13844 token->type = t->type;
13845 strexpr:
13846 token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13847 if (t->type == JIM_TT_CMD) {
13848
13849 JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13850 }
13851 expr->len++;
13852 break;
13853
13854 case JIM_TT_EXPR_INT:
13855 case JIM_TT_EXPR_DOUBLE:
13856 {
13857 char *endptr;
13858 if (t->type == JIM_TT_EXPR_INT) {
13859 token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13860 }
13861 else {
13862 token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13863 }
13864 if (endptr != t->token + t->len) {
13865
13866 Jim_FreeNewObj(interp, token->objPtr);
13867 token->type = JIM_TT_STR;
13868 goto strexpr;
13869 }
13870 token->type = t->type;
13871 expr->len++;
13872 }
13873 break;
13874
13875 case JIM_TT_SUBEXPR_START:
13876 Jim_StackPush(&stack, t);
13877 prevtt = JIM_TT_NONE;
13878 continue;
13879
13880 case JIM_TT_SUBEXPR_COMMA:
13881
13882 continue;
13883
13884 case JIM_TT_SUBEXPR_END:
13885 ok = 0;
13886 while (Jim_StackLen(&stack)) {
13887 ParseToken *tt = Jim_StackPop(&stack);
13888
13889 if (tt->type == JIM_TT_SUBEXPR_START) {
13890 ok = 1;
13891 break;
13892 }
13893
13894 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13895 goto err;
13896 }
13897 }
13898 if (!ok) {
13899 Jim_SetResultString(interp, "Unexpected close parenthesis", -1);
13900 goto err;
13901 }
13902 break;
13903
13904
13905 default:{
13906
13907 const struct Jim_ExprOperator *op;
13908 ParseToken *tt;
13909
13910
13911 if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
13912 if (t->type == JIM_EXPROP_SUB) {
13913 t->type = JIM_EXPROP_UNARYMINUS;
13914 }
13915 else if (t->type == JIM_EXPROP_ADD) {
13916 t->type = JIM_EXPROP_UNARYPLUS;
13917 }
13918 }
13919
13920 op = JimExprOperatorInfoByOpcode(t->type);
13921
13922
13923 while ((tt = Jim_StackPeek(&stack)) != NULL) {
13924 const struct Jim_ExprOperator *tt_op =
13925 JimExprOperatorInfoByOpcode(tt->type);
13926
13927
13928
13929 if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13930 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13931 ok = 0;
13932 goto err;
13933 }
13934 Jim_StackPop(&stack);
13935 }
13936 else {
13937 break;
13938 }
13939 }
13940 Jim_StackPush(&stack, t);
13941 break;
13942 }
13943 }
13944 prevtt = t->type;
13945 }
13946
13947
13948 while (Jim_StackLen(&stack)) {
13949 ParseToken *tt = Jim_StackPop(&stack);
13950
13951 if (tt->type == JIM_TT_SUBEXPR_START) {
13952 ok = 0;
13953 Jim_SetResultString(interp, "Missing close parenthesis", -1);
13954 goto err;
13955 }
13956 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13957 ok = 0;
13958 goto err;
13959 }
13960 }
13961
13962 if (have_ternary) {
13963 ExprTernaryReorderExpression(interp, expr);
13964 }
13965
13966 err:
13967
13968 Jim_FreeStack(&stack);
13969
13970 for (i = 0; i < expr->len; i++) {
13971 Jim_IncrRefCount(expr->token[i].objPtr);
13972 }
13973
13974 if (!ok) {
13975 ExprFreeByteCode(interp, expr);
13976 return NULL;
13977 }
13978
13979 return expr;
13980 }
13981
13982
13983 static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
13984 {
13985 int exprTextLen;
13986 const char *exprText;
13987 struct JimParserCtx parser;
13988 struct ExprByteCode *expr;
13989 ParseTokenList tokenlist;
13990 int line;
13991 Jim_Obj *fileNameObj;
13992 int rc = JIM_ERR;
13993
13994
13995 if (objPtr->typePtr == &sourceObjType) {
13996 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
13997 line = objPtr->internalRep.sourceValue.lineNumber;
13998 }
13999 else {
@@ -14002,18 +13808,17 @@
14002 }
14003 Jim_IncrRefCount(fileNameObj);
14004
14005 exprText = Jim_GetString(objPtr, &exprTextLen);
14006
14007
14008 ScriptTokenListInit(&tokenlist);
14009
14010 JimParserInit(&parser, exprText, exprTextLen, line);
14011 while (!parser.eof) {
14012 if (JimParseExpression(&parser) != JIM_OK) {
14013 ScriptTokenListFree(&tokenlist);
14014 invalidexpr:
14015 Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
14016 expr = NULL;
14017 goto err;
14018 }
14019
@@ -14036,125 +13841,174 @@
14036 ScriptTokenListFree(&tokenlist);
14037 Jim_DecrRefCount(interp, fileNameObj);
14038 return JIM_ERR;
14039 }
14040
14041
14042 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
14043
14044
 
 
14045 ScriptTokenListFree(&tokenlist);
14046
14047 if (!expr) {
14048 goto err;
14049 }
14050
14051 #ifdef DEBUG_SHOW_EXPR
14052 {
14053 int i;
14054
14055 printf("==== Expr ====\n");
14056 for (i = 0; i < expr->len; i++) {
14057 ScriptToken *t = &expr->token[i];
14058
14059 printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
14060 }
14061 }
14062 #endif
14063
14064
14065 if (ExprCheckCorrectness(expr) != JIM_OK) {
14066 ExprFreeByteCode(interp, expr);
14067 goto invalidexpr;
14068 }
14069
14070 rc = JIM_OK;
14071
14072 err:
14073
14074 Jim_DecrRefCount(interp, fileNameObj);
14075 Jim_FreeIntRep(interp, objPtr);
14076 Jim_SetIntRepPtr(objPtr, expr);
14077 objPtr->typePtr = &exprObjType;
14078 return rc;
14079 }
14080
14081 static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
14082 {
14083 if (objPtr->typePtr != &exprObjType) {
14084 if (SetExprFromAny(interp, objPtr) != JIM_OK) {
14085 return NULL;
14086 }
14087 }
14088 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
14089 }
14090
14091 #ifdef JIM_OPTIMIZATION
14092 static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
14093 {
14094 if (token->type == JIM_TT_EXPR_INT)
14095 return token->objPtr;
14096 else if (token->type == JIM_TT_VAR)
14097 return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
14098 else if (token->type == JIM_TT_DICTSUGAR)
14099 return JimExpandDictSugar(interp, token->objPtr);
14100 else
14101 return NULL;
14102 }
14103 #endif
14104
14105 #define JIM_EE_STATICSTACK_LEN 10
14106
14107 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
14108 {
14109 ExprByteCode *expr;
14110 Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];
14111 int i;
14112 int retcode = JIM_OK;
14113 struct JimExprState e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14114
14115 expr = JimGetExpression(interp, exprObjPtr);
14116 if (!expr) {
14117 return JIM_ERR;
14118 }
14119
14120 #ifdef JIM_OPTIMIZATION
14121 {
14122 Jim_Obj *objPtr;
14123
14124
14125 switch (expr->len) {
14126 case 1:
14127 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
14128 if (objPtr) {
14129 Jim_IncrRefCount(objPtr);
14130 *exprResultPtrPtr = objPtr;
14131 return JIM_OK;
14132 }
14133 break;
14134
14135 case 2:
14136 if (expr->token[1].type == JIM_EXPROP_NOT) {
14137 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
14138
14139 if (objPtr && JimIsWide(objPtr)) {
14140 *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
14141 Jim_IncrRefCount(*exprResultPtrPtr);
14142 return JIM_OK;
14143 }
14144 }
14145 break;
14146
14147 case 3:
14148 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
14149 if (objPtr && JimIsWide(objPtr)) {
14150 Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
14151 if (objPtr2 && JimIsWide(objPtr2)) {
14152 jim_wide wideValueA = JimWideValue(objPtr);
14153 jim_wide wideValueB = JimWideValue(objPtr2);
14154 int cmpRes;
14155 switch (expr->token[2].type) {
14156 case JIM_EXPROP_LT:
14157 cmpRes = wideValueA < wideValueB;
14158 break;
14159 case JIM_EXPROP_LTE:
14160 cmpRes = wideValueA <= wideValueB;
@@ -14172,12 +14026,11 @@
14172 cmpRes = wideValueA != wideValueB;
14173 break;
14174 default:
14175 goto noopt;
14176 }
14177 *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
14178 Jim_IncrRefCount(*exprResultPtrPtr);
14179 return JIM_OK;
14180 }
14181 }
14182 break;
14183 }
@@ -14185,145 +14038,64 @@
14185 noopt:
14186 #endif
14187
14188 expr->inUse++;
14189
14190
14191
14192 if (expr->len > JIM_EE_STATICSTACK_LEN)
14193 e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
14194 else
14195 e.stack = staticStack;
14196
14197 e.stacklen = 0;
14198
14199
14200 for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
14201 Jim_Obj *objPtr;
14202
14203 switch (expr->token[i].type) {
14204 case JIM_TT_EXPR_INT:
14205 case JIM_TT_EXPR_DOUBLE:
14206 case JIM_TT_STR:
14207 ExprPush(&e, expr->token[i].objPtr);
14208 break;
14209
14210 case JIM_TT_VAR:
14211 objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG);
14212 if (objPtr) {
14213 ExprPush(&e, objPtr);
14214 }
14215 else {
14216 retcode = JIM_ERR;
14217 }
14218 break;
14219
14220 case JIM_TT_DICTSUGAR:
14221 objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr);
14222 if (objPtr) {
14223 ExprPush(&e, objPtr);
14224 }
14225 else {
14226 retcode = JIM_ERR;
14227 }
14228 break;
14229
14230 case JIM_TT_ESC:
14231 retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE);
14232 if (retcode == JIM_OK) {
14233 ExprPush(&e, objPtr);
14234 }
14235 break;
14236
14237 case JIM_TT_CMD:
14238 retcode = Jim_EvalObj(interp, expr->token[i].objPtr);
14239 if (retcode == JIM_OK) {
14240 ExprPush(&e, Jim_GetResult(interp));
14241 }
14242 break;
14243
14244 default:{
14245
14246 e.skip = 0;
14247 e.opcode = expr->token[i].type;
14248
14249 retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
14250
14251 i += e.skip;
14252 continue;
14253 }
14254 }
14255 }
14256
14257 expr->inUse--;
14258
14259 if (retcode == JIM_OK) {
14260 *exprResultPtrPtr = ExprPop(&e);
14261 }
14262 else {
14263 for (i = 0; i < e.stacklen; i++) {
14264 Jim_DecrRefCount(interp, e.stack[i]);
14265 }
14266 }
14267 if (e.stack != staticStack) {
14268 Jim_Free(e.stack);
14269 }
14270 return retcode;
14271 }
14272
14273 int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
14274 {
14275 int retcode;
14276 jim_wide wideValue;
14277 double doubleValue;
14278 Jim_Obj *exprResultPtr;
14279
14280 retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
14281 if (retcode != JIM_OK)
14282 return retcode;
14283
14284 if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
14285 if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
14286 Jim_DecrRefCount(interp, exprResultPtr);
14287 return JIM_ERR;
14288 }
14289 else {
14290 Jim_DecrRefCount(interp, exprResultPtr);
14291 *boolPtr = doubleValue != 0;
14292 return JIM_OK;
14293 }
14294 }
14295 *boolPtr = wideValue != 0;
14296
14297 Jim_DecrRefCount(interp, exprResultPtr);
14298 return JIM_OK;
14299 }
14300
14301
14302
14303
14304 typedef struct ScanFmtPartDescr
14305 {
14306 char *arg;
14307 char *prefix;
14308 size_t width;
14309 int pos;
14310 char type;
14311 char modifier;
14312 } ScanFmtPartDescr;
14313
14314
14315 typedef struct ScanFmtStringObj
14316 {
14317 jim_wide size;
14318 char *stringRep;
14319 size_t count;
14320 size_t convCount;
14321 size_t maxPos;
14322 const char *error;
14323 char *scratch;
14324 ScanFmtPartDescr descr[1];
14325 } ScanFmtStringObj;
14326
14327
14328 static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
14329 static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14364,28 +14136,28 @@
14364 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
14365 {
14366 ScanFmtStringObj *fmtObj;
14367 char *buffer;
14368 int maxCount, i, approxSize, lastPos = -1;
14369 const char *fmt = objPtr->bytes;
14370 int maxFmtLen = objPtr->length;
14371 const char *fmtEnd = fmt + maxFmtLen;
14372 int curr;
14373
14374 Jim_FreeIntRep(interp, objPtr);
14375
14376 for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
14377 if (fmt[i] == '%')
14378 ++maxCount;
14379
14380 approxSize = sizeof(ScanFmtStringObj)
14381 +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14382 +maxFmtLen * sizeof(char) + 3 + 1
14383 + maxFmtLen * sizeof(char) + 1
14384 + maxFmtLen * sizeof(char)
14385 +(maxCount + 1) * sizeof(char)
14386 +1;
14387 fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
14388 memset(fmtObj, 0, approxSize);
14389 fmtObj->size = approxSize;
14390 fmtObj->maxPos = 0;
14391 fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14169,12 @@
14397 for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
14398 int width = 0, skip;
14399 ScanFmtPartDescr *descr = &fmtObj->descr[curr];
14400
14401 fmtObj->count++;
14402 descr->width = 0;
14403
14404 if (*fmt != '%' || fmt[1] == '%') {
14405 descr->type = 0;
14406 descr->prefix = &buffer[i];
14407 for (; fmt < fmtEnd; ++fmt) {
14408 if (*fmt == '%') {
@@ -14412,65 +14184,70 @@
14412 }
14413 buffer[i++] = *fmt;
14414 }
14415 buffer[i++] = 0;
14416 }
14417
14418 ++fmt;
14419
14420 if (fmt >= fmtEnd)
14421 goto done;
14422 descr->pos = 0;
14423 if (*fmt == '*') {
14424 descr->pos = -1;
14425 ++fmt;
14426 }
14427 else
14428 fmtObj->convCount++;
14429
14430 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14431 fmt += skip;
14432
14433 if (descr->pos != -1 && *fmt == '$') {
14434 int prev;
14435
14436 ++fmt;
14437 descr->pos = width;
14438 width = 0;
14439
14440 if ((lastPos == 0 && descr->pos > 0)
14441 || (lastPos > 0 && descr->pos == 0)) {
14442 fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
14443 return JIM_ERR;
14444 }
14445
14446 for (prev = 0; prev < curr; ++prev) {
14447 if (fmtObj->descr[prev].pos == -1)
14448 continue;
14449 if (fmtObj->descr[prev].pos == descr->pos) {
14450 fmtObj->error =
14451 "variable is assigned by multiple \"%n$\" conversion specifiers";
14452 return JIM_ERR;
14453 }
14454 }
14455
 
 
 
 
 
14456 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14457 descr->width = width;
14458 fmt += skip;
14459 }
14460 if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
14461 fmtObj->maxPos = descr->pos;
14462 }
14463 else {
14464
14465 descr->width = width;
14466 }
14467 }
14468
14469 if (lastPos == -1)
14470 lastPos = descr->pos;
14471
14472 if (*fmt == '[') {
14473 int swapped = 1, beg = i, end, j;
14474
14475 descr->type = '[';
14476 descr->arg = &buffer[i];
@@ -14485,11 +14262,11 @@
14485 fmtObj->error = "unmatched [ in format string";
14486 return JIM_ERR;
14487 }
14488 end = i;
14489 buffer[i++] = 0;
14490
14491 while (swapped) {
14492 swapped = 0;
14493 for (j = beg + 1; j < end - 1; ++j) {
14494 if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
14495 char tmp = buffer[j - 1];
@@ -14500,13 +14277,18 @@
14500 }
14501 }
14502 }
14503 }
14504 else {
14505
14506 if (strchr("hlL", *fmt) != 0)
14507 descr->modifier = tolower((int)*fmt++);
 
 
 
 
 
14508
14509 descr->type = *fmt;
14510 if (strchr("efgcsndoxui", *fmt) == 0) {
14511 fmtObj->error = "bad scan conversion character";
14512 return JIM_ERR;
@@ -14543,11 +14325,11 @@
14543 while (*str) {
14544 int c;
14545 int n;
14546
14547 if (!sdescr && isspace(UCHAR(*str)))
14548 break;
14549
14550 n = utf8_tounicode(str, &c);
14551 if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
14552 break;
14553 while (n--)
@@ -14566,89 +14348,89 @@
14566 size_t scanned = 0;
14567 size_t anchor = pos;
14568 int i;
14569 Jim_Obj *tmpObj = NULL;
14570
14571
14572 *valObjPtr = 0;
14573 if (descr->prefix) {
14574 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14575
14576 if (isspace(UCHAR(descr->prefix[i])))
14577 while (pos < strLen && isspace(UCHAR(str[pos])))
14578 ++pos;
14579 else if (descr->prefix[i] != str[pos])
14580 break;
14581 else
14582 ++pos;
14583 }
14584 if (pos >= strLen) {
14585 return -1;
14586 }
14587 else if (descr->prefix[i] != 0)
14588 return 0;
14589 }
14590
14591 if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
14592 while (isspace(UCHAR(str[pos])))
14593 ++pos;
14594
14595 scanned = pos - anchor;
14596
14597
14598 if (descr->type == 'n') {
14599
14600 *valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
14601 }
14602 else if (pos >= strLen) {
14603
14604 return -1;
14605 }
14606 else if (descr->type == 'c') {
14607 int c;
14608 scanned += utf8_tounicode(&str[pos], &c);
14609 *valObjPtr = Jim_NewIntObj(interp, c);
14610 return scanned;
14611 }
14612 else {
14613
14614 if (descr->width > 0) {
14615 size_t sLen = utf8_strlen(&str[pos], strLen - pos);
14616 size_t tLen = descr->width > sLen ? sLen : descr->width;
14617
14618 tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
14619 tok = tmpObj->bytes;
14620 }
14621 else {
14622
14623 tok = &str[pos];
14624 }
14625 switch (descr->type) {
14626 case 'd':
14627 case 'o':
14628 case 'x':
14629 case 'u':
14630 case 'i':{
14631 char *endp;
14632 jim_wide w;
14633
14634 int base = descr->type == 'o' ? 8
14635 : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
14636
14637
14638 if (base == 0) {
14639 w = jim_strtoull(tok, &endp);
14640 }
14641 else {
14642 w = strtoull(tok, &endp, base);
14643 }
14644
14645 if (endp != tok) {
14646
14647 *valObjPtr = Jim_NewIntObj(interp, w);
14648
14649
14650 scanned += endp - tok;
14651 }
14652 else {
14653 scanned = *tok ? 0 : -1;
14654 }
@@ -14665,13 +14447,13 @@
14665 case 'g':{
14666 char *endp;
14667 double value = strtod(tok, &endp);
14668
14669 if (endp != tok) {
14670
14671 *valObjPtr = Jim_NewDoubleObj(interp, value);
14672
14673 scanned += endp - tok;
14674 }
14675 else {
14676 scanned = *tok ? 0 : -1;
14677 }
@@ -14696,65 +14478,65 @@
14696 Jim_Obj **resultVec = 0;
14697 int resultc;
14698 Jim_Obj *emptyStr = 0;
14699 ScanFmtStringObj *fmtObj;
14700
14701
14702 JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
14703
14704 fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14705
14706 if (fmtObj->error != 0) {
14707 if (flags & JIM_ERRMSG)
14708 Jim_SetResultString(interp, fmtObj->error, -1);
14709 return 0;
14710 }
14711
14712 emptyStr = Jim_NewEmptyStringObj(interp);
14713 Jim_IncrRefCount(emptyStr);
14714
14715 resultList = Jim_NewListObj(interp, NULL, 0);
14716 if (fmtObj->maxPos > 0) {
14717 for (i = 0; i < fmtObj->maxPos; ++i)
14718 Jim_ListAppendElement(interp, resultList, emptyStr);
14719 JimListGetElements(interp, resultList, &resultc, &resultVec);
14720 }
14721
14722 for (i = 0, pos = 0; i < fmtObj->count; ++i) {
14723 ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
14724 Jim_Obj *value = 0;
14725
14726
14727 if (descr->type == 0)
14728 continue;
14729
14730 if (scanned > 0)
14731 scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14732
14733 if (scanned == -1 && i == 0)
14734 goto eof;
14735
14736 pos += scanned;
14737
14738
14739 if (value == 0)
14740 value = Jim_NewEmptyStringObj(interp);
14741
14742 if (descr->pos == -1) {
14743 Jim_FreeNewObj(interp, value);
14744 }
14745 else if (descr->pos == 0)
14746
14747 Jim_ListAppendElement(interp, resultList, value);
14748 else if (resultVec[descr->pos - 1] == emptyStr) {
14749
14750 Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
14751 Jim_IncrRefCount(value);
14752 resultVec[descr->pos - 1] = value;
14753 }
14754 else {
14755
14756 Jim_FreeNewObj(interp, value);
14757 goto err;
14758 }
14759 }
14760 Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14574,15 @@
14792 {
14793 Jim_PrngState *prng;
14794 unsigned char *destByte = (unsigned char *)dest;
14795 unsigned int si, sj, x;
14796
14797
14798 if (interp->prngState == NULL)
14799 JimPrngInit(interp);
14800 prng = interp->prngState;
14801
14802 for (x = 0; x < len; x++) {
14803 prng->i = (prng->i + 1) & 0xff;
14804 si = prng->sbox[prng->i];
14805 prng->j = (prng->j + si) & 0xff;
14806 sj = prng->sbox[prng->j];
@@ -14814,19 +14596,19 @@
14814 static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
14815 {
14816 int i;
14817 Jim_PrngState *prng;
14818
14819
14820 if (interp->prngState == NULL)
14821 JimPrngInit(interp);
14822 prng = interp->prngState;
14823
14824
14825 for (i = 0; i < 256; i++)
14826 prng->sbox[i] = i;
14827
14828 for (i = 0; i < seedLen; i++) {
14829 unsigned char t;
14830
14831 t = prng->sbox[i & 0xFF];
14832 prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14635,11 @@
14853 if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
14854 return JIM_ERR;
14855 }
14856 intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
14857 if (!intObjPtr) {
14858
14859 wideValue = 0;
14860 }
14861 else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
14862 return JIM_ERR;
14863 }
@@ -14867,26 +14649,26 @@
14867 Jim_FreeNewObj(interp, intObjPtr);
14868 return JIM_ERR;
14869 }
14870 }
14871 else {
14872
14873 Jim_InvalidateStringRep(intObjPtr);
14874 JimWideValue(intObjPtr) = wideValue + increment;
14875
14876 if (argv[1]->typePtr != &variableObjType) {
14877
14878 Jim_SetVariable(interp, argv[1], intObjPtr);
14879 }
14880 }
14881 Jim_SetResult(interp, intObjPtr);
14882 return JIM_OK;
14883 }
14884
14885
14886 #define JIM_EVAL_SARGV_LEN 8
14887 #define JIM_EVAL_SINTV_LEN 8
14888
14889
14890 static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
14891 {
14892 int retcode;
@@ -14894,16 +14676,16 @@
14894 if (interp->unknown_called > 50) {
14895 return JIM_ERR;
14896 }
14897
14898
14899
14900 if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
14901 return JIM_ERR;
14902
14903 interp->unknown_called++;
14904
14905 retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
14906 interp->unknown_called--;
14907
14908 return retcode;
14909 }
@@ -14910,10 +14692,11 @@
14910
14911 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14912 {
14913 int retcode;
14914 Jim_Cmd *cmdPtr;
 
14915
14916 #if 0
14917 printf("invoke");
14918 int j;
14919 for (j = 0; j < objc; j++) {
@@ -14921,11 +14704,11 @@
14921 }
14922 printf("\n");
14923 #endif
14924
14925 if (interp->framePtr->tailcallCmd) {
14926
14927 cmdPtr = interp->framePtr->tailcallCmd;
14928 interp->framePtr->tailcallCmd = NULL;
14929 }
14930 else {
14931 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14939,20 +14722,22 @@
14939 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14940 retcode = JIM_ERR;
14941 goto out;
14942 }
14943 interp->evalDepth++;
 
14944
14945
14946 Jim_SetEmptyResult(interp);
14947 if (cmdPtr->isproc) {
14948 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14949 }
14950 else {
14951 interp->cmdPrivData = cmdPtr->u.native.privData;
14952 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14953 }
 
14954 interp->evalDepth--;
14955
14956 out:
14957 JimDecrCmdRefCount(interp, cmdPtr);
14958
@@ -14961,17 +14746,17 @@
14961
14962 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14963 {
14964 int i, retcode;
14965
14966
14967 for (i = 0; i < objc; i++)
14968 Jim_IncrRefCount(objv[i]);
14969
14970 retcode = JimInvokeCommand(interp, objc, objv);
14971
14972
14973 for (i = 0; i < objc; i++)
14974 Jim_DecrRefCount(interp, objv[i]);
14975
14976 return retcode;
14977 }
@@ -14989,25 +14774,25 @@
14989 }
14990
14991 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
14992 {
14993 if (!interp->errorFlag) {
14994
14995 interp->errorFlag = 1;
14996 Jim_IncrRefCount(script->fileNameObj);
14997 Jim_DecrRefCount(interp, interp->errorFileNameObj);
14998 interp->errorFileNameObj = script->fileNameObj;
14999 interp->errorLine = script->linenr;
15000
15001 JimResetStackTrace(interp);
15002
15003 interp->addStackTrace++;
15004 }
15005
15006
15007 if (interp->addStackTrace > 0) {
15008
15009
15010 JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
15011
15012 if (Jim_Length(script->fileNameObj)) {
15013 interp->addStackTrace = 0;
@@ -15042,14 +14827,14 @@
15042 case JIM_OK:
15043 case JIM_RETURN:
15044 objPtr = interp->result;
15045 break;
15046 case JIM_BREAK:
15047
15048 return JIM_BREAK;
15049 case JIM_CONTINUE:
15050
15051 return JIM_CONTINUE;
15052 default:
15053 return JIM_ERR;
15054 }
15055 break;
@@ -15084,23 +14869,23 @@
15084 case JIM_OK:
15085 case JIM_RETURN:
15086 break;
15087 case JIM_BREAK:
15088 if (flags & JIM_SUBST_FLAG) {
15089
15090 tokens = i;
15091 continue;
15092 }
15093
15094
15095 case JIM_CONTINUE:
15096 if (flags & JIM_SUBST_FLAG) {
15097 intv[i] = NULL;
15098 continue;
15099 }
15100
15101
15102 default:
15103 while (i--) {
15104 Jim_DecrRefCount(interp, intv[i]);
15105 }
15106 if (intv != sintv) {
@@ -15111,28 +14896,29 @@
15111 Jim_IncrRefCount(intv[i]);
15112 Jim_String(intv[i]);
15113 totlen += intv[i]->length;
15114 }
15115
15116
15117 if (tokens == 1 && intv[0] && intv == sintv) {
15118 Jim_DecrRefCount(interp, intv[0]);
 
15119 return intv[0];
15120 }
15121
15122 objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
15123
15124 if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
15125 && token[2].type == JIM_TT_VAR) {
15126
15127 objPtr->typePtr = &interpolatedObjType;
15128 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
15129 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
15130 Jim_IncrRefCount(intv[2]);
15131 }
15132 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
15133
15134 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
15135 }
15136
15137
15138 s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +14929,11 @@
15143 s += intv[i]->length;
15144 Jim_DecrRefCount(interp, intv[i]);
15145 }
15146 }
15147 objPtr->bytes[totlen] = '\0';
15148
15149 if (intv != sintv) {
15150 Jim_Free(intv);
15151 }
15152
15153 return objPtr;
@@ -15187,11 +14973,11 @@
15187
15188 if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
15189 return JimEvalObjList(interp, scriptObjPtr);
15190 }
15191
15192 Jim_IncrRefCount(scriptObjPtr);
15193 script = JimGetScript(interp, scriptObjPtr);
15194 if (!JimScriptValid(interp, script)) {
15195 Jim_DecrRefCount(interp, scriptObjPtr);
15196 return JIM_ERR;
15197 }
@@ -15223,11 +15009,11 @@
15223 }
15224 #endif
15225
15226 script->inUse++;
15227
15228
15229 prevScriptObj = interp->currentScriptObj;
15230 interp->currentScriptObj = scriptObjPtr;
15231
15232 interp->errorFlag = 0;
15233 argv = sargv;
@@ -15234,19 +15020,19 @@
15234
15235 for (i = 0; i < script->len && retcode == JIM_OK; ) {
15236 int argc;
15237 int j;
15238
15239
15240 argc = token[i].objPtr->internalRep.scriptLineValue.argc;
15241 script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
15242
15243
15244 if (argc > JIM_EVAL_SARGV_LEN)
15245 argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
15246
15247
15248 i++;
15249
15250 for (j = 0; j < argc; j++) {
15251 long wordtokens = 1;
15252 int expand = 0;
@@ -15302,11 +15088,11 @@
15302
15303 if (!expand) {
15304 argv[j] = wordObjPtr;
15305 }
15306 else {
15307
15308 int len = Jim_ListLength(interp, wordObjPtr);
15309 int newargc = argc + len - 1;
15310 int k;
15311
15312 if (len > 1) {
@@ -15315,39 +15101,39 @@
15315 argv = Jim_Alloc(sizeof(*argv) * newargc);
15316 memcpy(argv, sargv, sizeof(*argv) * j);
15317 }
15318 }
15319 else {
15320
15321 argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
15322 }
15323 }
15324
15325
15326 for (k = 0; k < len; k++) {
15327 argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
15328 Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
15329 }
15330
15331 Jim_DecrRefCount(interp, wordObjPtr);
15332
15333
15334 j--;
15335 argc += len - 1;
15336 }
15337 }
15338
15339 if (retcode == JIM_OK && argc) {
15340
15341 retcode = JimInvokeCommand(interp, argc, argv);
15342
15343 if (Jim_CheckSignal(interp)) {
15344 retcode = JIM_SIGNAL;
15345 }
15346 }
15347
15348
15349 while (j-- > 0) {
15350 Jim_DecrRefCount(interp, argv[j]);
15351 }
15352
15353 if (argv != sargv) {
@@ -15354,21 +15140,21 @@
15354 Jim_Free(argv);
15355 argv = sargv;
15356 }
15357 }
15358
15359
15360 if (retcode == JIM_ERR) {
15361 JimAddErrorToStack(interp, script);
15362 }
15363
15364 else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15365
15366 interp->addStackTrace = 0;
15367 }
15368
15369
15370 interp->currentScriptObj = prevScriptObj;
15371
15372 Jim_FreeIntRep(interp, scriptObjPtr);
15373 scriptObjPtr->typePtr = &scriptObjType;
15374 Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15164,14 @@
15378 }
15379
15380 static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
15381 {
15382 int retcode;
15383
15384 const char *varname = Jim_String(argNameObj);
15385 if (*varname == '&') {
15386
15387 Jim_Obj *objPtr;
15388 Jim_CallFrame *savedCallFrame = interp->framePtr;
15389
15390 interp->framePtr = interp->framePtr->parent;
15391 objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15178,11 @@
15392 interp->framePtr = savedCallFrame;
15393 if (!objPtr) {
15394 return JIM_ERR;
15395 }
15396
15397
15398 objPtr = Jim_NewStringObj(interp, varname + 1, -1);
15399 Jim_IncrRefCount(objPtr);
15400 retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
15401 Jim_DecrRefCount(interp, objPtr);
15402 }
@@ -15406,26 +15192,26 @@
15406 return retcode;
15407 }
15408
15409 static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
15410 {
15411
15412 Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
15413 int i;
15414
15415 for (i = 0; i < cmd->u.proc.argListLen; i++) {
15416 Jim_AppendString(interp, argmsg, " ", 1);
15417
15418 if (i == cmd->u.proc.argsPos) {
15419 if (cmd->u.proc.arglist[i].defaultObjPtr) {
15420
15421 Jim_AppendString(interp, argmsg, "?", 1);
15422 Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
15423 Jim_AppendString(interp, argmsg, " ...?", -1);
15424 }
15425 else {
15426
15427 Jim_AppendString(interp, argmsg, "?arg...?", -1);
15428 }
15429 }
15430 else {
15431 if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15227,19 @@
15441 Jim_AppendString(interp, argmsg, arg, -1);
15442 }
15443 }
15444 }
15445 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
15446 Jim_FreeNewObj(interp, argmsg);
15447 }
15448
15449 #ifdef jim_ext_namespace
15450 int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
15451 {
15452 Jim_CallFrame *callFramePtr;
15453 int retcode;
15454
15455
15456 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
15457 callFramePtr->argv = &interp->emptyObj;
15458 callFramePtr->argc = 0;
15459 callFramePtr->procArgsObjPtr = NULL;
15460 callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15247,21 @@
15462 callFramePtr->fileNameObj = interp->emptyObj;
15463 callFramePtr->line = 0;
15464 Jim_IncrRefCount(scriptObj);
15465 interp->framePtr = callFramePtr;
15466
15467
15468 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15469 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15470 retcode = JIM_ERR;
15471 }
15472 else {
15473
15474 retcode = Jim_EvalObj(interp, scriptObj);
15475 }
15476
15477
15478 interp->framePtr = interp->framePtr->parent;
15479 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15480
15481 return retcode;
15482 }
@@ -15486,62 +15271,62 @@
15486 {
15487 Jim_CallFrame *callFramePtr;
15488 int i, d, retcode, optargs;
15489 ScriptObj *script;
15490
15491
15492 if (argc - 1 < cmd->u.proc.reqArity ||
15493 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
15494 JimSetProcWrongArgs(interp, argv[0], cmd);
15495 return JIM_ERR;
15496 }
15497
15498 if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15499
15500 return JIM_OK;
15501 }
15502
15503
15504 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15505 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15506 return JIM_ERR;
15507 }
15508
15509
15510 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
15511 callFramePtr->argv = argv;
15512 callFramePtr->argc = argc;
15513 callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
15514 callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
15515 callFramePtr->staticVars = cmd->u.proc.staticVars;
15516
15517
15518 script = JimGetScript(interp, interp->currentScriptObj);
15519 callFramePtr->fileNameObj = script->fileNameObj;
15520 callFramePtr->line = script->linenr;
15521
15522 Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
15523 Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
15524 interp->framePtr = callFramePtr;
15525
15526
15527 optargs = (argc - 1 - cmd->u.proc.reqArity);
15528
15529
15530 i = 1;
15531 for (d = 0; d < cmd->u.proc.argListLen; d++) {
15532 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
15533 if (d == cmd->u.proc.argsPos) {
15534
15535 Jim_Obj *listObjPtr;
15536 int argsLen = 0;
15537 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
15538 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
15539 }
15540 listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
15541
15542
15543 if (cmd->u.proc.arglist[d].defaultObjPtr) {
15544 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
15545 }
15546 retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
15547 if (retcode != JIM_OK) {
@@ -15550,33 +15335,34 @@
15550
15551 i += argsLen;
15552 continue;
15553 }
15554
15555
15556 if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
15557 retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
15558 }
15559 else {
15560
15561 retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
15562 }
15563 if (retcode != JIM_OK) {
15564 goto badargset;
15565 }
15566 }
15567
15568
15569 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15570
15571 badargset:
15572
15573
 
15574 interp->framePtr = interp->framePtr->parent;
15575 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15576
15577
15578 if (interp->framePtr->tailcallObj) {
15579 do {
15580 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15581
15582 interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15374,18 @@
15588 }
15589 }
15590 Jim_DecrRefCount(interp, tailcallObj);
15591 } while (interp->framePtr->tailcallObj);
15592
15593
15594 if (interp->framePtr->tailcallCmd) {
15595 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15596 interp->framePtr->tailcallCmd = NULL;
15597 }
15598 }
15599
15600
15601 if (retcode == JIM_RETURN) {
15602 if (--interp->returnLevel <= 0) {
15603 retcode = interp->returnCode;
15604 interp->returnCode = JIM_OK;
15605 interp->returnLevel = 0;
@@ -15711,20 +15497,20 @@
15711 prevScriptObj = interp->currentScriptObj;
15712 interp->currentScriptObj = scriptObjPtr;
15713
15714 retcode = Jim_EvalObj(interp, scriptObjPtr);
15715
15716
15717 if (retcode == JIM_RETURN) {
15718 if (--interp->returnLevel <= 0) {
15719 retcode = interp->returnCode;
15720 interp->returnCode = JIM_OK;
15721 interp->returnLevel = 0;
15722 }
15723 }
15724 if (retcode == JIM_ERR) {
15725
15726 interp->addStackTrace++;
15727 }
15728
15729 interp->currentScriptObj = prevScriptObj;
15730
@@ -15750,11 +15536,11 @@
15750 }
15751 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
15752 if (JimParseVar(pc) == JIM_OK) {
15753 return;
15754 }
15755
15756 pc->tstart = pc->p;
15757 flags |= JIM_SUBST_NOVAR;
15758 }
15759 while (pc->len) {
15760 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15567,32 @@
15781 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
15782 struct JimParserCtx parser;
15783 struct ScriptObj *script = Jim_Alloc(sizeof(*script));
15784 ParseTokenList tokenlist;
15785
15786
15787 ScriptTokenListInit(&tokenlist);
15788
15789 JimParserInit(&parser, scriptText, scriptTextLen, 1);
15790 while (1) {
15791 JimParseSubst(&parser, flags);
15792 if (parser.eof) {
15793
15794 break;
15795 }
15796 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
15797 parser.tline);
15798 }
15799
15800
15801 script->inUse = 1;
15802 script->substFlags = flags;
15803 script->fileNameObj = interp->emptyObj;
15804 Jim_IncrRefCount(script->fileNameObj);
15805 SubstObjAddTokens(interp, script, &tokenlist);
15806
15807
15808 ScriptTokenListFree(&tokenlist);
15809
15810 #ifdef DEBUG_SHOW_SUBST
15811 {
15812 int i;
@@ -15817,11 +15603,11 @@
15817 Jim_String(script->token[i].objPtr));
15818 }
15819 }
15820 #endif
15821
15822
15823 Jim_FreeIntRep(interp, objPtr);
15824 Jim_SetIntRepPtr(objPtr, script);
15825 objPtr->typePtr = &scriptObjType;
15826 return JIM_OK;
15827 }
@@ -15835,11 +15621,11 @@
15835
15836 int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
15837 {
15838 ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
15839
15840 Jim_IncrRefCount(substObjPtr);
15841 script->inUse++;
15842
15843 *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
15844
15845 script->inUse--;
@@ -15851,22 +15637,24 @@
15851 }
15852
15853 void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
15854 {
15855 Jim_Obj *objPtr;
15856 Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
15857
15858 if (*msg) {
 
 
 
 
15859 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
15860 }
15861 Jim_IncrRefCount(listObjPtr);
15862 objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
15863 Jim_DecrRefCount(interp, listObjPtr);
15864
15865 Jim_IncrRefCount(objPtr);
15866 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
15867 Jim_DecrRefCount(interp, objPtr);
15868 }
15869
15870 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15871 Jim_HashEntry *he, int type);
15872
@@ -15876,11 +15664,11 @@
15876 JimHashtableIteratorCallbackType *callback, int type)
15877 {
15878 Jim_HashEntry *he;
15879 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
15880
15881
15882 if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
15883 he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
15884 if (he) {
15885 callback(interp, listObjPtr, he, type);
15886 }
@@ -15907,11 +15695,11 @@
15907 {
15908 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15909 Jim_Obj *objPtr;
15910
15911 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15912
15913 return;
15914 }
15915
15916 objPtr = Jim_NewStringObj(interp, he->key, -1);
15917 Jim_IncrRefCount(objPtr);
@@ -15967,11 +15755,11 @@
15967
15968 targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
15969 if (targetCallFrame == NULL) {
15970 return JIM_ERR;
15971 }
15972
15973 if (targetCallFrame == interp->topFramePtr) {
15974 Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
15975 return JIM_ERR;
15976 }
15977 if (info_level_cmd) {
@@ -16095,12 +15883,17 @@
16095 doubleRes = (double)res;
16096 goto trydouble;
16097 }
16098 if (op == JIM_EXPROP_SUB)
16099 res -= wideValue;
16100 else
 
 
 
 
16101 res /= wideValue;
 
16102 }
16103 Jim_SetResultInt(interp, res);
16104 return JIM_OK;
16105 trydouble:
16106 for (; i < argc; i++) {
@@ -16154,11 +15947,11 @@
16154 if (!objPtr)
16155 return JIM_ERR;
16156 Jim_SetResult(interp, objPtr);
16157 return JIM_OK;
16158 }
16159
16160 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16161 return JIM_ERR;
16162 Jim_SetResult(interp, argv[2]);
16163 return JIM_OK;
16164 }
@@ -16197,11 +15990,11 @@
16197 if (argc != 3) {
16198 Jim_WrongNumArgs(interp, 1, argv, "condition body");
16199 return JIM_ERR;
16200 }
16201
16202
16203 while (1) {
16204 int boolean, retval;
16205
16206 if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
16207 return retval;
@@ -16237,11 +16030,11 @@
16237 if (argc != 5) {
16238 Jim_WrongNumArgs(interp, 1, argv, "start test next body");
16239 return JIM_ERR;
16240 }
16241
16242
16243 if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
16244 return retval;
16245 }
16246
16247 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16248,78 +16041,84 @@
16248
16249
16250 #ifdef JIM_OPTIMIZATION
16251 if (retval == JIM_OK && boolean) {
16252 ScriptObj *incrScript;
16253 ExprByteCode *expr;
16254 jim_wide stop, currentVal;
16255 Jim_Obj *objPtr;
16256 int cmpOffset;
16257
16258
16259 expr = JimGetExpression(interp, argv[2]);
16260 incrScript = JimGetScript(interp, argv[3]);
16261
16262
16263 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16264 goto evalstart;
16265 }
16266
16267 if (incrScript->token[1].type != JIM_TT_ESC ||
16268 expr->token[0].type != JIM_TT_VAR ||
16269 (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
16270 goto evalstart;
16271 }
16272
16273 if (expr->token[2].type == JIM_EXPROP_LT) {
16274 cmpOffset = 0;
16275 }
16276 else if (expr->token[2].type == JIM_EXPROP_LTE) {
16277 cmpOffset = 1;
16278 }
16279 else {
16280 goto evalstart;
16281 }
16282
16283
 
 
 
 
 
 
 
 
16284 if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
16285 goto evalstart;
16286 }
16287
16288
16289 if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
16290 goto evalstart;
16291 }
16292
16293
16294 if (expr->token[1].type == JIM_TT_EXPR_INT) {
16295 if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
16296 goto evalstart;
16297 }
16298 }
16299 else {
16300 stopVarNamePtr = expr->token[1].objPtr;
16301 Jim_IncrRefCount(stopVarNamePtr);
16302
16303 stop = 0;
16304 }
16305
16306
16307 varNamePtr = expr->token[0].objPtr;
16308 Jim_IncrRefCount(varNamePtr);
16309
16310 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
16311 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
16312 goto testcond;
16313 }
16314
16315
16316 while (retval == JIM_OK) {
16317
16318
16319
16320
 
 
16321 if (stopVarNamePtr) {
16322 objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
16323 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
16324 goto testcond;
16325 }
@@ -16327,18 +16126,18 @@
16327
16328 if (currentVal >= stop + cmpOffset) {
16329 break;
16330 }
16331
16332
16333 retval = Jim_EvalObj(interp, argv[4]);
16334 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16335 retval = JIM_OK;
16336
16337 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
16338
16339
16340 if (objPtr == NULL) {
16341 retval = JIM_ERR;
16342 goto out;
16343 }
16344 if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16157,25 @@
16358 }
16359 evalstart:
16360 #endif
16361
16362 while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16363
16364 retval = Jim_EvalObj(interp, argv[4]);
16365
16366 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16367
16368 evalnext:
16369 retval = Jim_EvalObj(interp, argv[3]);
16370 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16371
16372 testcond:
16373 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
16374 }
16375 }
16376 }
16377 out:
16378 if (stopVarNamePtr) {
16379 Jim_DecrRefCount(interp, stopVarNamePtr);
16380 }
16381 if (varNamePtr) {
16382 Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16217,11 @@
16418 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16419 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
16420
16421 retval = JIM_OK;
16422
16423
16424 i += incr;
16425
16426 if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
16427 if (argv[1]->typePtr != &variableObjType) {
16428 if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16282,21 @@
16483
16484 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16485 {
16486 int result = JIM_OK;
16487 int i, numargs;
16488 Jim_ListIter twoiters[2];
16489 Jim_ListIter *iters;
16490 Jim_Obj *script;
16491 Jim_Obj *resultObj;
16492
16493 if (argc < 4 || argc % 2 != 0) {
16494 Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
16495 return JIM_ERR;
16496 }
16497 script = argv[argc - 1];
16498 numargs = (argc - 1 - 1);
16499
16500 if (numargs == 2) {
16501 iters = twoiters;
16502 }
16503 else {
@@ -16521,34 +16320,34 @@
16521 resultObj = interp->emptyObj;
16522 }
16523 Jim_IncrRefCount(resultObj);
16524
16525 while (1) {
16526
16527 for (i = 0; i < numargs; i += 2) {
16528 if (!JimListIterDone(interp, &iters[i + 1])) {
16529 break;
16530 }
16531 }
16532 if (i == numargs) {
16533
16534 break;
16535 }
16536
16537
16538 for (i = 0; i < numargs; i += 2) {
16539 Jim_Obj *varName;
16540
16541
16542 JimListIterInit(&iters[i], argv[i + 1]);
16543 while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
16544 Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
16545 if (!valObj) {
16546
16547 valObj = interp->emptyObj;
16548 }
16549
16550 Jim_IncrRefCount(valObj);
16551 result = Jim_SetVariable(interp, varName, valObj);
16552 Jim_DecrRefCount(interp, valObj);
16553 if (result != JIM_OK) {
16554 goto err;
@@ -16630,41 +16429,41 @@
16630 {
16631 int boolean, retval, current = 1, falsebody = 0;
16632
16633 if (argc >= 3) {
16634 while (1) {
16635
16636 if (current >= argc)
16637 goto err;
16638 if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
16639 != JIM_OK)
16640 return retval;
16641
16642 if (current >= argc)
16643 goto err;
16644 if (Jim_CompareStringImmediate(interp, argv[current], "then"))
16645 current++;
16646
16647 if (current >= argc)
16648 goto err;
16649 if (boolean)
16650 return Jim_EvalObj(interp, argv[current]);
16651
16652 if (++current >= argc) {
16653 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
16654 return JIM_OK;
16655 }
16656 falsebody = current++;
16657 if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16658
16659 if (current != argc - 1)
16660 goto err;
16661 return Jim_EvalObj(interp, argv[current]);
16662 }
16663 else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
16664 continue;
16665
16666 else if (falsebody != argc - 1)
16667 goto err;
16668 return Jim_EvalObj(interp, argv[falsebody]);
16669 }
16670 return JIM_OK;
@@ -16698,19 +16497,17 @@
16698 }
16699
16700 return eq;
16701 }
16702
16703 enum
16704 { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
16705
16706
16707 static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
16708 {
 
16709 int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
16710 Jim_Obj *command = 0, *const *caseList = 0, *strObj;
16711 Jim_Obj *script = 0;
16712
16713 if (argc < 3) {
16714 wrongnumargs:
16715 Jim_WrongNumArgs(interp, 1, argv, "?options? string "
16716 "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}");
@@ -16747,68 +16544,62 @@
16747 goto wrongnumargs;
16748 }
16749 strObj = argv[opt++];
16750 patCount = argc - opt;
16751 if (patCount == 1) {
16752 Jim_Obj **vector;
16753
16754 JimListGetElements(interp, argv[opt], &patCount, &vector);
16755 caseList = vector;
16756 }
16757 else
16758 caseList = &argv[opt];
16759 if (patCount == 0 || patCount % 2 != 0)
16760 goto wrongnumargs;
16761 for (i = 0; script == 0 && i < patCount; i += 2) {
16762 Jim_Obj *patObj = caseList[i];
16763
16764 if (!Jim_CompareStringImmediate(interp, patObj, "default")
16765 || i < (patCount - 2)) {
16766 switch (matchOpt) {
16767 case SWITCH_EXACT:
16768 if (Jim_StringEqObj(strObj, patObj))
16769 script = caseList[i + 1];
16770 break;
16771 case SWITCH_GLOB:
16772 if (Jim_StringMatchObj(interp, patObj, strObj, 0))
16773 script = caseList[i + 1];
16774 break;
16775 case SWITCH_RE:
16776 command = Jim_NewStringObj(interp, "regexp", -1);
16777
16778 case SWITCH_CMD:{
16779 int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
16780
16781 if (argc - opt == 1) {
16782 Jim_Obj **vector;
16783
16784 JimListGetElements(interp, argv[opt], &patCount, &vector);
16785 caseList = vector;
16786 }
16787
16788 if (rc < 0) {
16789 return -rc;
16790 }
16791 if (rc)
16792 script = caseList[i + 1];
16793 break;
16794 }
16795 }
16796 }
16797 else {
16798 script = caseList[i + 1];
16799 }
16800 }
16801 for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2)
16802 script = caseList[i + 1];
16803 if (script && Jim_CompareStringImmediate(interp, script, "-")) {
16804 Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]);
16805 return JIM_ERR;
16806 }
16807 Jim_SetEmptyResult(interp);
16808 if (script) {
16809 return Jim_EvalObj(interp, script);
16810 }
16811 return JIM_OK;
16812 }
16813
16814
@@ -16920,11 +16711,11 @@
16920 case OPT_COMMAND:
16921 if (i >= argc - 2) {
16922 goto wrongargs;
16923 }
16924 commandObj = argv[++i];
16925
16926 case OPT_EXACT:
16927 case OPT_GLOB:
16928 case OPT_REGEXP:
16929 opt_match = option;
16930 break;
@@ -16968,17 +16759,17 @@
16968 goto done;
16969 }
16970 break;
16971 }
16972
16973
16974 if (!eq && opt_bool && opt_not && !opt_all) {
16975 continue;
16976 }
16977
16978 if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16979
16980 Jim_Obj *resultObj;
16981
16982 if (opt_bool) {
16983 resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
16984 }
@@ -17001,11 +16792,11 @@
17001
17002 if (opt_all) {
17003 Jim_SetResult(interp, listObjPtr);
17004 }
17005 else {
17006
17007 if (opt_bool) {
17008 Jim_SetResultBool(interp, opt_not);
17009 }
17010 else if (!opt_inline) {
17011 Jim_SetResultInt(interp, -1);
@@ -17030,11 +16821,11 @@
17030 Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
17031 return JIM_ERR;
17032 }
17033 listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17034 if (!listObjPtr) {
17035
17036 listObjPtr = Jim_NewListObj(interp, NULL, 0);
17037 new_obj = 1;
17038 }
17039 else if (Jim_IsShared(listObjPtr)) {
17040 listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +16894,31 @@
17103 first = JimRelToAbsIndex(len, first);
17104 last = JimRelToAbsIndex(len, last);
17105 JimRelToAbsRange(len, &first, &last, &rangeLen);
17106
17107
17108
17109 if (first < len) {
17110
17111 }
17112 else if (len == 0) {
17113
17114 first = 0;
17115 }
17116 else {
17117 Jim_SetResultString(interp, "list doesn't contain element ", -1);
17118 Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
17119 return JIM_ERR;
17120 }
17121
17122
17123 newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
17124
17125
17126 ListInsertElements(newListObj, -1, argc - 4, argv + 4);
17127
17128
17129 ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
17130
17131 Jim_SetResult(interp, newListObj);
17132 return JIM_OK;
17133 }
@@ -17138,11 +16929,11 @@
17138 if (argc < 3) {
17139 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
17140 return JIM_ERR;
17141 }
17142 else if (argc == 3) {
17143
17144 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
17145 return JIM_ERR;
17146 Jim_SetResult(interp, argv[2]);
17147 return JIM_OK;
17148 }
@@ -17158,10 +16949,11 @@
17158 enum
17159 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
17160 Jim_Obj *resObj;
17161 int i;
17162 int retCode;
 
17163
17164 struct lsort_info info;
17165
17166 if (argc < 2) {
17167 Jim_WrongNumArgs(interp, 1, argv, "?options? list");
@@ -17223,16 +17015,18 @@
17223 info.indexed = 1;
17224 i++;
17225 break;
17226 }
17227 }
17228 resObj = Jim_DuplicateObj(interp, argv[argc - 1]);
 
 
17229 retCode = ListSortElements(interp, resObj, &info);
17230 if (retCode == JIM_OK) {
17231 Jim_SetResult(interp, resObj);
17232 }
17233 else {
17234 Jim_FreeNewObj(interp, resObj);
17235 }
17236 return retCode;
17237 }
17238
@@ -17253,11 +17047,11 @@
17253 }
17254 else {
17255 int new_obj = 0;
17256 stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17257 if (!stringObjPtr) {
17258
17259 stringObjPtr = Jim_NewEmptyStringObj(interp);
17260 new_obj = 1;
17261 }
17262 else if (Jim_IsShared(stringObjPtr)) {
17263 new_obj = 1;
@@ -17274,10 +17068,11 @@
17274 }
17275 }
17276 Jim_SetResult(interp, stringObjPtr);
17277 return JIM_OK;
17278 }
 
17279
17280
17281 static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17282 {
17283 #if !defined(JIM_DEBUG_COMMAND)
@@ -17302,11 +17097,11 @@
17302 else {
17303 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
17304 }
17305
17306 if (rc == JIM_ERR) {
17307
17308 interp->addStackTrace++;
17309 }
17310 return rc;
17311 }
17312
@@ -17316,14 +17111,14 @@
17316 if (argc >= 2) {
17317 int retcode;
17318 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17319 const char *str;
17320
17321
17322 savedCallFrame = interp->framePtr;
17323
17324
17325 str = Jim_String(argv[1]);
17326 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17327 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17328 argc--;
17329 argv++;
@@ -17336,11 +17131,11 @@
17336 }
17337 if (argc < 2) {
17338 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
17339 return JIM_ERR;
17340 }
17341
17342 interp->framePtr = targetCallFrame;
17343 if (argc == 2) {
17344 retcode = Jim_EvalObj(interp, argv[1]);
17345 }
17346 else {
@@ -17356,32 +17151,29 @@
17356 }
17357
17358
17359 static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17360 {
17361 Jim_Obj *exprResultPtr;
17362 int retcode;
17363
17364 if (argc == 2) {
17365 retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr);
17366 }
17367 else if (argc > 2) {
17368 Jim_Obj *objPtr;
17369
17370 objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
17371 Jim_IncrRefCount(objPtr);
17372 retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr);
17373 Jim_DecrRefCount(interp, objPtr);
17374 }
17375 else {
17376 Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
17377 return JIM_ERR;
17378 }
17379 if (retcode != JIM_OK)
17380 return retcode;
17381 Jim_SetResult(interp, exprResultPtr);
17382 Jim_DecrRefCount(interp, exprResultPtr);
17383 return JIM_OK;
17384 }
17385
17386
17387 static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -17438,15 +17230,15 @@
17438 if (i != argc - 1 && i != argc) {
17439 Jim_WrongNumArgs(interp, 1, argv,
17440 "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
17441 }
17442
17443
17444 if (stackTraceObj && returnCode == JIM_ERR) {
17445 JimSetStackTrace(interp, stackTraceObj);
17446 }
17447
17448 if (errorCodeObj && returnCode == JIM_ERR) {
17449 Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
17450 }
17451 interp->returnCode = returnCode;
17452 interp->returnLevel = level;
@@ -17463,31 +17255,31 @@
17463 if (interp->framePtr->level == 0) {
17464 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17465 return JIM_ERR;
17466 }
17467 else if (argc >= 2) {
17468
17469 Jim_CallFrame *cf = interp->framePtr->parent;
17470
17471 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17472 if (cmdPtr == NULL) {
17473 return JIM_ERR;
17474 }
17475
17476 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17477
17478
17479 JimIncrCmdRefCount(cmdPtr);
17480 cf->tailcallCmd = cmdPtr;
17481
17482
17483 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17484
17485 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17486 Jim_IncrRefCount(cf->tailcallObj);
17487
17488
17489 return JIM_EVAL;
17490 }
17491 return JIM_OK;
17492 }
17493
@@ -17494,11 +17286,11 @@
17494 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17495 {
17496 Jim_Obj *cmdList;
17497 Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
17498
17499
17500 cmdList = Jim_DuplicateObj(interp, prefixListObj);
17501 Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
17502
17503 return JimEvalObjList(interp, cmdList);
17504 }
@@ -17552,22 +17344,22 @@
17552 else {
17553 cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
17554 }
17555
17556 if (cmd) {
17557
17558 Jim_Obj *qualifiedCmdNameObj;
17559 const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
17560
17561 JimCreateCommand(interp, cmdname, cmd);
17562
17563
17564 JimUpdateProcNamespace(interp, cmd, cmdname);
17565
17566 JimFreeQualifiedName(interp, qualifiedCmdNameObj);
17567
17568
17569 Jim_SetResult(interp, argv[1]);
17570 return JIM_OK;
17571 }
17572 return JIM_ERR;
17573 }
@@ -17580,17 +17372,17 @@
17580 if (argc < 2) {
17581 Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17582 return JIM_ERR;
17583 }
17584
17585
17586 interp->local++;
17587 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17588 interp->local--;
17589
17590
17591
17592 if (retcode == 0) {
17593 Jim_Obj *cmdNameObj = Jim_GetResult(interp);
17594
17595 if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
17596 return JIM_ERR;
@@ -17619,18 +17411,18 @@
17619 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17620 if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
17621 Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
17622 return JIM_ERR;
17623 }
17624
17625 cmdPtr->u.proc.upcall++;
17626 JimIncrCmdRefCount(cmdPtr);
17627
17628
17629 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17630
17631
17632 cmdPtr->u.proc.upcall--;
17633 JimDecrCmdRefCount(interp, cmdPtr);
17634
17635 return retcode;
17636 }
@@ -17657,11 +17449,11 @@
17657 return JIM_ERR;
17658 }
17659
17660 if (len == 3) {
17661 #ifdef jim_ext_namespace
17662
17663 nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
17664 #else
17665 Jim_SetResultString(interp, "namespaces not enabled", -1);
17666 return JIM_ERR;
17667 #endif
@@ -17670,11 +17462,11 @@
17670 bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
17671
17672 cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
17673
17674 if (cmd) {
17675
17676 nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
17677 nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
17678 Jim_IncrRefCount(nargv[0]);
17679 memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
17680 ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17492,11 @@
17700 static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17701 {
17702 int i;
17703 Jim_CallFrame *targetCallFrame;
17704
17705
17706 if (argc > 3 && (argc % 2 == 0)) {
17707 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17708 argc--;
17709 argv++;
17710 }
@@ -17713,17 +17505,17 @@
17713 }
17714 if (targetCallFrame == NULL) {
17715 return JIM_ERR;
17716 }
17717
17718
17719 if (argc < 3) {
17720 Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
17721 return JIM_ERR;
17722 }
17723
17724
17725 for (i = 1; i < argc; i += 2) {
17726 if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
17727 return JIM_ERR;
17728 }
17729 return JIM_OK;
@@ -17736,15 +17528,15 @@
17736
17737 if (argc < 2) {
17738 Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
17739 return JIM_ERR;
17740 }
17741
17742 if (interp->framePtr->level == 0)
17743 return JIM_OK;
17744 for (i = 1; i < argc; i++) {
17745
17746 const char *name = Jim_String(argv[i]);
17747 if (name[0] != ':' || name[1] != ':') {
17748 if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
17749 return JIM_ERR;
17750 }
@@ -17767,21 +17559,21 @@
17767 }
17768
17769 str = Jim_String(objPtr);
17770 strLen = Jim_Utf8Length(interp, objPtr);
17771
17772
17773 resultObjPtr = Jim_NewStringObj(interp, "", 0);
17774 while (strLen) {
17775 for (i = 0; i < numMaps; i += 2) {
17776 Jim_Obj *objPtr;
17777 const char *k;
17778 int kl;
17779
17780 objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17781 k = Jim_String(objPtr);
17782 kl = Jim_Utf8Length(interp, objPtr);
17783
17784 if (strLen >= kl && kl) {
17785 int rc;
17786 rc = JimStringCompareLen(str, k, kl, nocase);
17787 if (rc == 0) {
@@ -17794,11 +17586,11 @@
17794 strLen -= kl;
17795 break;
17796 }
17797 }
17798 }
17799 if (i == numMaps) {
17800 int c;
17801 if (noMatchStart == NULL)
17802 noMatchStart = str;
17803 str += utf8_tounicode(str, &c);
17804 strLen--;
@@ -17838,11 +17630,11 @@
17838 Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
17839 return JIM_ERR;
17840 }
17841 if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
17842 JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17843 return JIM_ERR;
17844
17845 switch (option) {
17846 case OPT_LENGTH:
17847 case OPT_BYTELENGTH:
17848 if (argc != 3) {
@@ -17859,11 +17651,11 @@
17859 return JIM_OK;
17860
17861 case OPT_CAT:{
17862 Jim_Obj *objPtr;
17863 if (argc == 3) {
17864
17865 objPtr = argv[2];
17866 }
17867 else {
17868 int i;
17869
@@ -17878,11 +17670,11 @@
17878 }
17879
17880 case OPT_COMPARE:
17881 case OPT_EQUAL:
17882 {
17883
17884 long opt_length = -1;
17885 int n = argc - 4;
17886 int i = 2;
17887 while (n > 0) {
17888 int subopt;
@@ -17891,16 +17683,16 @@
17891 badcompareargs:
17892 Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
17893 return JIM_ERR;
17894 }
17895 if (subopt == 0) {
17896
17897 opt_case = 0;
17898 n--;
17899 }
17900 else {
17901
17902 if (n < 2) {
17903 goto badcompareargs;
17904 }
17905 if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
17906 return JIM_ERR;
@@ -17911,11 +17703,11 @@
17911 if (n) {
17912 goto badcompareargs;
17913 }
17914 argv += argc - 2;
17915 if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17916
17917 Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
17918 }
17919 else {
17920 if (opt_length >= 0) {
17921 n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17817,10 @@
18025 }
18026
18027 case OPT_REVERSE:{
18028 char *buf, *p;
18029 const char *str;
18030 int len;
18031 int i;
18032
18033 if (argc != 3) {
18034 Jim_WrongNumArgs(interp, 2, argv, "string");
18035 return JIM_ERR;
@@ -18069,11 +17860,11 @@
18069 }
18070 if (idx < 0 || idx >= len || str == NULL) {
18071 Jim_SetResultString(interp, "", 0);
18072 }
18073 else if (len == Jim_Length(argv[2])) {
18074
18075 Jim_SetResultString(interp, str + idx, 1);
18076 }
18077 else {
18078 int c;
18079 int i = utf8_index(str, idx);
@@ -18223,11 +18014,11 @@
18223 {
18224 int exitCode = 0;
18225 int i;
18226 int sig = 0;
18227
18228
18229 jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
18230 static const int max_ignore_code = sizeof(ignore_mask) * 8;
18231
18232 Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
18233
@@ -18234,11 +18025,11 @@
18234 for (i = 1; i < argc - 1; i++) {
18235 const char *arg = Jim_String(argv[i]);
18236 jim_wide option;
18237 int ignore;
18238
18239
18240 if (strcmp(arg, "--") == 0) {
18241 i++;
18242 break;
18243 }
18244 if (*arg != '-') {
@@ -18285,28 +18076,28 @@
18285 sig++;
18286 }
18287
18288 interp->signal_level += sig;
18289 if (Jim_CheckSignal(interp)) {
18290
18291 exitCode = JIM_SIGNAL;
18292 }
18293 else {
18294 exitCode = Jim_EvalObj(interp, argv[0]);
18295
18296 interp->errorFlag = 0;
18297 }
18298 interp->signal_level -= sig;
18299
18300
18301 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18302
18303 return exitCode;
18304 }
18305
18306 if (sig && exitCode == JIM_SIGNAL) {
18307
18308 if (interp->signal_set_result) {
18309 interp->signal_set_result(interp, interp->sigmask);
18310 }
18311 else {
18312 Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18136,10 @@
18345 }
18346 Jim_SetResultInt(interp, exitCode);
18347 return JIM_OK;
18348 }
18349
18350 #ifdef JIM_REFERENCES
18351
18352
18353 static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18354 {
18355 if (argc != 3 && argc != 4) {
18356 Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?");
18357 return JIM_ERR;
18358 }
18359 if (argc == 3) {
18360 Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL));
18361 }
18362 else {
18363 Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3]));
18364 }
18365 return JIM_OK;
18366 }
18367
18368
18369 static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18370 {
18371 Jim_Reference *refPtr;
18372
18373 if (argc != 2) {
18374 Jim_WrongNumArgs(interp, 1, argv, "reference");
18375 return JIM_ERR;
18376 }
18377 if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18378 return JIM_ERR;
18379 Jim_SetResult(interp, refPtr->objPtr);
18380 return JIM_OK;
18381 }
18382
18383
18384 static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18385 {
18386 Jim_Reference *refPtr;
18387
18388 if (argc != 3) {
18389 Jim_WrongNumArgs(interp, 1, argv, "reference newValue");
18390 return JIM_ERR;
18391 }
18392 if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18393 return JIM_ERR;
18394 Jim_IncrRefCount(argv[2]);
18395 Jim_DecrRefCount(interp, refPtr->objPtr);
18396 refPtr->objPtr = argv[2];
18397 Jim_SetResult(interp, argv[2]);
18398 return JIM_OK;
18399 }
18400
18401
18402 static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18403 {
18404 if (argc != 1) {
18405 Jim_WrongNumArgs(interp, 1, argv, "");
18406 return JIM_ERR;
18407 }
18408 Jim_SetResultInt(interp, Jim_Collect(interp));
18409
18410
18411 while (interp->freeList) {
18412 Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
18413 Jim_Free(interp->freeList);
18414 interp->freeList = nextObjPtr;
18415 }
18416
18417 return JIM_OK;
18418 }
18419
18420
18421 static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18422 {
18423 if (argc != 2 && argc != 3) {
18424 Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?");
18425 return JIM_ERR;
18426 }
18427 if (argc == 2) {
18428 Jim_Obj *cmdNamePtr;
18429
18430 if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
18431 return JIM_ERR;
18432 if (cmdNamePtr != NULL)
18433 Jim_SetResult(interp, cmdNamePtr);
18434 }
18435 else {
18436 if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK)
18437 return JIM_ERR;
18438 Jim_SetResult(interp, argv[2]);
18439 }
18440 return JIM_OK;
18441 }
18442
18443
18444 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18445 {
18446 Jim_Obj *listObjPtr;
18447 Jim_HashTableIterator htiter;
18448 Jim_HashEntry *he;
18449
18450 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18451
18452 JimInitHashTableIterator(&interp->references, &htiter);
18453 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18454 char buf[JIM_REFERENCE_SPACE + 1];
18455 Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18456 const unsigned long *refId = he->key;
18457
18458 JimFormatReference(buf, refPtr, *refId);
18459 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18460 }
18461 Jim_SetResult(interp, listObjPtr);
18462 return JIM_OK;
18463 }
18464 #endif
18465
18466
18467 static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18468 {
18469 if (argc != 3) {
@@ -18476,56 +18152,43 @@
18476 }
18477
18478 return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
18479 }
18480
18481 #define JIM_DICTMATCH_VALUES 0x0001
18482
18483 typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
18484
18485 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18486 {
18487 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18488 if (type & JIM_DICTMATCH_VALUES) {
18489 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18490 }
18491 }
18492
18493 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18494 JimDictMatchCallbackType *callback, int type)
18495 {
18496 Jim_HashEntry *he;
18497 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18498
18499
18500 Jim_HashTableIterator htiter;
18501 JimInitHashTableIterator(ht, &htiter);
18502 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18503 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18504 callback(interp, listObjPtr, he, type);
18505 }
18506 }
18507
18508 return listObjPtr;
18509 }
18510
18511
18512 int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18513 {
18514 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18515 return JIM_ERR;
18516 }
18517 Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
18518 return JIM_OK;
18519 }
18520
18521 int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18522 {
18523 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18524 return JIM_ERR;
18525 }
18526 Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
18527 return JIM_OK;
18528 }
18529
18530 int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
18531 {
@@ -18532,38 +18195,85 @@
18532 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18533 return -1;
18534 }
18535 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18536 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18537
18538 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18539 {
18540 Jim_HashTable *ht;
18541 unsigned int i;
 
 
 
 
 
18542
18543 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18544 return JIM_ERR;
18545 }
18546
18547 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18548
18549
18550 printf("%d entries in table, %d buckets\n", ht->used, ht->size);
 
18551
18552 for (i = 0; i < ht->size; i++) {
18553 Jim_HashEntry *he = ht->table[i];
18554
18555 if (he) {
18556 printf("%d: ", i);
18557
18558 while (he) {
18559 printf(" %s", Jim_String(he->key));
18560 he = he->next;
18561 }
18562 printf("\n");
 
 
 
 
 
18563 }
18564 }
 
 
 
 
 
 
 
 
 
18565 return JIM_OK;
18566 }
18567
18568 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18569 {
@@ -18573,14 +18283,67 @@
18573 Jim_AppendString(interp, prefixObj, subcmd, -1);
18574
18575 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18576 }
18577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18578
18579 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18580 {
18581 Jim_Obj *objPtr;
 
18582 int option;
18583 static const char * const options[] = {
18584 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18585 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18586 "replace", "update", NULL
@@ -18596,11 +18359,11 @@
18596 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18597 return JIM_ERR;
18598 }
18599
18600 if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18601 return JIM_ERR;
18602 }
18603
18604 switch (option) {
18605 case OPT_GET:
18606 if (argc < 3) {
@@ -18643,16 +18406,19 @@
18643 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18644 return JIM_ERR;
18645 }
18646 return JIM_OK;
18647
 
 
 
18648 case OPT_KEYS:
18649 if (argc != 3 && argc != 4) {
18650 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18651 return JIM_ERR;
18652 }
18653 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18654
18655 case OPT_SIZE:
18656 if (argc != 3) {
18657 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18658 return JIM_ERR;
@@ -18665,19 +18431,20 @@
18665
18666 case OPT_MERGE:
18667 if (argc == 2) {
18668 return JIM_OK;
18669 }
18670 if (Jim_DictSize(interp, argv[2]) < 0) {
 
18671 return JIM_ERR;
18672 }
18673
18674 break;
18675
18676 case OPT_UPDATE:
18677 if (argc < 6 || argc % 2) {
18678
18679 argc = 2;
18680 }
18681 break;
18682
18683 case OPT_CREATE:
@@ -18693,12 +18460,19 @@
18693 if (argc != 3) {
18694 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18695 return JIM_ERR;
18696 }
18697 return Jim_DictInfo(interp, argv[2]);
 
 
 
 
 
 
 
18698 }
18699
18700 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18701 }
18702
18703
18704 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18538,11 @@
18764
18765 #ifdef jim_ext_namespace
18766 int nons = 0;
18767
18768 if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18769
18770 argc--;
18771 argv++;
18772 nons = 1;
18773 }
18774 #endif
@@ -18775,16 +18549,15 @@
18775
18776 if (argc < 2) {
18777 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
18778 return JIM_ERR;
18779 }
18780 if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV)
18781 != JIM_OK) {
18782 return JIM_ERR;
18783 }
18784
18785
18786 switch (cmd) {
18787 case INFO_EXISTS:
18788 if (argc != 3) {
18789 Jim_WrongNumArgs(interp, 2, argv, "varName");
18790 return JIM_ERR;
@@ -18809,21 +18582,21 @@
18809 Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
18810 return JIM_OK;
18811 }
18812
18813 case INFO_CHANNELS:
18814 mode++;
18815 #ifndef jim_ext_aio
18816 Jim_SetResultString(interp, "aio not enabled", -1);
18817 return JIM_ERR;
18818 #endif
18819
18820 case INFO_PROCS:
18821 mode++;
18822
18823 case INFO_COMMANDS:
18824
18825 if (argc != 2 && argc != 3) {
18826 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18827 return JIM_ERR;
18828 }
18829 #ifdef jim_ext_namespace
@@ -18835,17 +18608,17 @@
18835 #endif
18836 Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
18837 break;
18838
18839 case INFO_VARS:
18840 mode++;
18841
18842 case INFO_LOCALS:
18843 mode++;
18844
18845 case INFO_GLOBALS:
18846
18847 if (argc != 2 && argc != 3) {
18848 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18849 return JIM_ERR;
18850 }
18851 #ifdef jim_ext_namespace
@@ -18951,13 +18724,12 @@
18951 case INFO_ARGS:
18952 Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
18953 break;
18954 case INFO_STATICS:
18955 if (cmdPtr->u.proc.staticVars) {
18956 int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
18957 Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18958 NULL, JimVariablesMatch, mode));
18959 }
18960 break;
18961 }
18962 break;
18963 }
@@ -18985,15 +18757,15 @@
18985 }
18986 }
18987 break;
18988
18989 case INFO_HOSTNAME:
18990
18991 return Jim_Eval(interp, "os.gethostname");
18992
18993 case INFO_NAMEOFEXECUTABLE:
18994
18995 return Jim_Eval(interp, "{info nameofexecutable}");
18996
18997 case INFO_RETURNCODES:
18998 if (argc == 2) {
18999 int i;
@@ -19070,11 +18842,11 @@
19070
19071 if (option == OPT_VAR) {
19072 result = Jim_GetVariable(interp, objPtr, 0) != NULL;
19073 }
19074 else {
19075
19076 Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
19077
19078 if (cmd) {
19079 switch (option) {
19080 case OPT_COMMAND:
@@ -19113,11 +18885,11 @@
19113 if (len == 0) {
19114 return JIM_OK;
19115 }
19116 strLen = Jim_Utf8Length(interp, argv[1]);
19117
19118
19119 if (argc == 2) {
19120 splitChars = " \n\t\r";
19121 splitLen = 4;
19122 }
19123 else {
@@ -19126,11 +18898,11 @@
19126 }
19127
19128 noMatchStart = str;
19129 resObjPtr = Jim_NewListObj(interp, NULL, 0);
19130
19131
19132 if (splitLen) {
19133 Jim_Obj *objPtr;
19134 while (strLen--) {
19135 const char *sc = splitChars;
19136 int scLen = splitLen;
@@ -19155,11 +18927,11 @@
19155 #define NUM_COMMON (128 - 9)
19156 while (strLen--) {
19157 int n = utf8_tounicode(str, &c);
19158 #ifdef JIM_OPTIMIZATION
19159 if (c >= 9 && c < 128) {
19160
19161 c -= 9;
19162 if (!commonObj) {
19163 commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
19164 memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
19165 }
@@ -19189,11 +18961,11 @@
19189
19190 if (argc != 2 && argc != 3) {
19191 Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
19192 return JIM_ERR;
19193 }
19194
19195 if (argc == 2) {
19196 joinStr = " ";
19197 joinStrLen = 1;
19198 }
19199 else {
@@ -19468,13 +19240,13 @@
19468 return -1;
19469 else if (step < 0 && end > start)
19470 return -1;
19471 len = end - start;
19472 if (len < 0)
19473 len = -len;
19474 if (step < 0)
19475 step = -step;
19476 len = 1 + ((len - 1) / step);
19477 if (len > INT_MAX)
19478 len = INT_MAX;
19479 return (int)((len < 0) ? -1 : len);
19480 }
@@ -19644,57 +19416,102 @@
19644 argv[1] = interp->result;
19645
19646 Jim_EvalObjVector(interp, 2, argv);
19647 }
19648
19649 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19650 const char *prefix, const char *const *tablePtr, const char *name)
19651 {
19652 int count;
19653 char **tablePtrSorted;
19654 int i;
19655
19656 for (count = 0; tablePtr[count]; count++) {
19657 }
19658
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19659 if (name == NULL) {
19660 name = "option";
19661 }
19662
19663 Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19664 tablePtrSorted = Jim_Alloc(sizeof(char *) * count);
19665 memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19666 qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19667 for (i = 0; i < count; i++) {
19668 if (i + 1 == count && count > 1) {
19669 Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
19670 }
19671 Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19672 if (i + 1 != count) {
19673 Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
19674 }
19675 }
19676 Jim_Free(tablePtrSorted);
19677 }
19678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19679 int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
19680 const char *const *tablePtr, int *indexPtr, const char *name, int flags)
19681 {
19682 const char *bad = "bad ";
19683 const char *const *entryPtr = NULL;
19684 int i;
19685 int match = -1;
19686 int arglen;
19687 const char *arg = Jim_GetString(objPtr, &arglen);
 
 
 
 
 
 
 
 
 
19688
19689 *indexPtr = -1;
19690
19691 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
19692 if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19693
19694 *indexPtr = i;
19695 return JIM_OK;
19696 }
19697 if (flags & JIM_ENUM_ABBREV) {
19698 if (strncmp(arg, *entryPtr, arglen) == 0) {
19699 if (*arg == '-' && arglen == 1) {
19700 break;
@@ -19706,12 +19523,20 @@
19706 match = i;
19707 }
19708 }
19709 }
19710
19711
19712 if (match >= 0) {
 
 
 
 
 
 
 
 
19713 *indexPtr = match;
19714 return JIM_OK;
19715 }
19716
19717 ambiguous:
@@ -19743,15 +19568,17 @@
19743 return objPtr->typePtr == &listObjType;
19744 }
19745
19746 void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
19747 {
19748
19749 int len = strlen(format);
19750 int extra = 0;
19751 int n = 0;
19752 const char *params[5];
 
 
19753 char *buf;
19754 va_list args;
19755 int i;
19756
19757 va_start(args, format);
@@ -19766,10 +19593,12 @@
19766 }
19767 else if (strncmp(format + i, "%#s", 3) == 0) {
19768 Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
19769
19770 params[n] = Jim_GetString(objPtr, &l);
 
 
19771 }
19772 else {
19773 if (format[i] == '%') {
19774 i++;
19775 }
@@ -19784,10 +19613,14 @@
19784 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19785
19786 va_end(args);
19787
19788 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
 
 
 
 
19789 }
19790
19791
19792 #ifndef jim_ext_package
19793 int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19641,11 @@
19808 #include <string.h>
19809
19810
19811 static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19812 {
19813
19814 return JIM_OK;
19815 }
19816
19817 static const jim_subcmd_type dummy_subcmd = {
19818 "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19831,22 +19664,18 @@
19831 }
19832
19833 static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
19834 Jim_Obj *cmd, Jim_Obj *subcmd)
19835 {
19836 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19837 Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type,
19838 " command \"", Jim_String(subcmd), "\": should be ", NULL);
19839 add_commands(interp, command_table, ", ");
19840 }
19841
19842 static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
19843 Jim_Obj *const *argv)
19844 {
19845 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19846 Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]),
19847 " command ... \", where command is one of: ", NULL);
19848 add_commands(interp, command_table, ", ");
19849 }
19850
19851 static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
19852 {
@@ -19863,67 +19692,78 @@
19863 {
19864 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19865 add_cmd_usage(interp, command_table, subcmd);
19866 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19867 }
 
 
 
 
 
 
 
 
19868
19869 const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
19870 int argc, Jim_Obj *const *argv)
19871 {
19872 const jim_subcmd_type *ct;
19873 const jim_subcmd_type *partial = 0;
19874 int cmdlen;
19875 Jim_Obj *cmd;
19876 const char *cmdstr;
19877 const char *cmdname;
19878 int help = 0;
19879
19880 cmdname = Jim_String(argv[0]);
19881
19882 if (argc < 2) {
19883 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19884 Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
19885 " command ...\"\n", NULL);
19886 Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL);
19887 return 0;
19888 }
19889
19890 cmd = argv[1];
19891
19892
 
 
 
 
 
 
 
 
19893 if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
19894 if (argc == 2) {
19895
19896 show_cmd_usage(interp, command_table, argc, argv);
19897 return &dummy_subcmd;
19898 }
19899 help = 1;
19900
19901
19902 cmd = argv[2];
19903 }
19904
19905
19906 if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19907
19908 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19909 add_commands(interp, command_table, " ");
19910 return &dummy_subcmd;
19911 }
19912
19913 cmdstr = Jim_GetString(cmd, &cmdlen);
19914
19915 for (ct = command_table; ct->cmd; ct++) {
19916 if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19917
19918 break;
19919 }
19920 if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
19921 if (partial) {
19922
19923 if (help) {
19924
19925 show_cmd_usage(interp, command_table, argc, argv);
19926 return &dummy_subcmd;
19927 }
19928 bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
19929 return 0;
@@ -19931,44 +19771,51 @@
19931 partial = ct;
19932 }
19933 continue;
19934 }
19935
19936
19937 if (partial && !ct->cmd) {
19938 ct = partial;
19939 }
19940
19941 if (!ct->cmd) {
19942
19943 if (help) {
19944
19945 show_cmd_usage(interp, command_table, argc, argv);
19946 return &dummy_subcmd;
19947 }
19948 bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
19949 return 0;
19950 }
19951
19952 if (help) {
19953 Jim_SetResultString(interp, "Usage: ", -1);
19954
19955 add_cmd_usage(interp, ct, argv[0]);
19956 return &dummy_subcmd;
19957 }
19958
19959
 
 
 
 
 
 
 
19960 if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
19961 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19962
19963 add_cmd_usage(interp, ct, argv[0]);
19964 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19965
19966 return 0;
19967 }
19968
19969
19970 return ct;
19971 }
19972
19973 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
19974 {
@@ -20019,11 +19866,11 @@
20019 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
20020 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20021 *p = 0x80 | (uc & 0x3f);
20022 return 3;
20023 }
20024
20025 else {
20026 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
20027 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
20028 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20029 *p = 0x80 | (uc & 0x3f);
@@ -20146,11 +19993,12 @@
20146 continue;
20147 }
20148 *p++ = ch;
20149 format += step;
20150 step = utf8_tounicode(format, &ch);
20151 } while (sawFlag);
 
20152
20153
20154 width = 0;
20155 if (isdigit(ch)) {
20156 width = strtoul(format, &end, 10);
@@ -20210,11 +20058,11 @@
20210 if (ch == 'h') {
20211 useShort = 1;
20212 format += step;
20213 step = utf8_tounicode(format, &ch);
20214 } else if (ch == 'l') {
20215
20216 format += step;
20217 step = utf8_tounicode(format, &ch);
20218 if (ch == 'l') {
20219 format += step;
20220 step = utf8_tounicode(format, &ch);
@@ -20237,11 +20085,11 @@
20237 goto errorMsg;
20238 case 's': {
20239 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
20240 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
20241 if (gotPrecision && (precision < formatted_chars)) {
20242
20243 formatted_chars = precision;
20244 formatted_bytes = utf8_index(formatted_buf, precision);
20245 }
20246 break;
20247 }
@@ -20249,11 +20097,11 @@
20249 jim_wide code;
20250
20251 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20252 goto error;
20253 }
20254
20255 formatted_bytes = utf8_getchars(spec, code);
20256 formatted_buf = spec;
20257 formatted_chars = 1;
20258 break;
20259 }
@@ -20267,11 +20115,11 @@
20267 goto error;
20268 }
20269 length = sizeof(w) * 8;
20270
20271
20272
20273 if (num_buffer_size < length + 1) {
20274 num_buffer_size = length + 1;
20275 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20276 }
20277
@@ -20295,29 +20143,29 @@
20295 case 'E':
20296 case 'f':
20297 case 'g':
20298 case 'G':
20299 doubleType = 1;
20300
20301 case 'd':
20302 case 'u':
20303 case 'o':
20304 case 'x':
20305 case 'X': {
20306 jim_wide w;
20307 double d;
20308 int length;
20309
20310
20311 if (width) {
20312 p += sprintf(p, "%ld", width);
20313 }
20314 if (gotPrecision) {
20315 p += sprintf(p, ".%ld", precision);
20316 }
20317
20318
20319 if (doubleType) {
20320 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20321 goto error;
20322 }
20323 length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20192,26 @@
20344 }
20345
20346 *p++ = (char) ch;
20347 *p = '\0';
20348
20349
 
 
 
 
 
 
 
20350 if (width > length) {
20351 length = width;
20352 }
20353 if (gotPrecision) {
20354 length += precision;
20355 }
20356
20357
20358 if (num_buffer_size < length + 1) {
20359 num_buffer_size = length + 1;
20360 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20361 }
20362
@@ -20370,11 +20225,11 @@
20370 formatted_buf = num_buffer;
20371 break;
20372 }
20373
20374 default: {
20375
20376 spec[0] = ch;
20377 spec[1] = '\0';
20378 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20379 goto error;
20380 }
@@ -20422,37 +20277,37 @@
20422
20423 #define REG_MAX_PAREN 100
20424
20425
20426
20427 #define END 0
20428 #define BOL 1
20429 #define EOL 2
20430 #define ANY 3
20431 #define ANYOF 4
20432 #define ANYBUT 5
20433 #define BRANCH 6
20434 #define BACK 7
20435 #define EXACTLY 8
20436 #define NOTHING 9
20437 #define REP 10
20438 #define REPMIN 11
20439 #define REPX 12
20440 #define REPXMIN 13
20441 #define BOLX 14
20442 #define EOLX 15
20443 #define WORDA 16
20444 #define WORDZ 17
20445
20446 #define OPENNC 1000
20447 #define OPEN 1001
20448
20449
20450
20451
20452 #define CLOSENC 2000
20453 #define CLOSE 2001
20454 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
20455
20456 #define REG_MAGIC 0xFADED00D
20457
20458
@@ -20465,18 +20320,18 @@
20465
20466 #define FAIL(R,M) { (R)->err = (M); return (M); }
20467 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20468 #define META "^$.[()|?{+*"
20469
20470 #define HASWIDTH 1
20471 #define SIMPLE 2
20472 #define SPSTART 4
20473 #define WORST 0
20474
20475 #define MAX_REP_COUNT 1000000
20476
20477 static int reg(regex_t *preg, int paren , int *flagp );
20478 static int regpiece(regex_t *preg, int *flagp );
20479 static int regbranch(regex_t *preg, int *flagp );
20480 static int regatom(regex_t *preg, int *flagp );
20481 static int regnode(regex_t *preg, int op );
20482 static int regnext(regex_t *preg, int p );
@@ -20520,15 +20375,15 @@
20520 memset(preg, 0, sizeof(*preg));
20521
20522 if (exp == NULL)
20523 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20524
20525
20526 preg->cflags = cflags;
20527 preg->regparse = exp;
20528
20529
20530 preg->proglen = (strlen(exp) + 1) * 5;
20531 preg->program = malloc(preg->proglen * sizeof(int));
20532 if (preg->program == NULL)
20533 FAIL(preg, REG_ERR_NOMEM);
20534
@@ -20535,24 +20390,24 @@
20535 regc(preg, REG_MAGIC);
20536 if (reg(preg, 0, &flags) == 0) {
20537 return preg->err;
20538 }
20539
20540
20541 if (preg->re_nsub >= REG_MAX_PAREN)
20542 FAIL(preg,REG_ERR_TOO_BIG);
20543
20544
20545 preg->regstart = 0;
20546 preg->reganch = 0;
20547 preg->regmust = 0;
20548 preg->regmlen = 0;
20549 scan = 1;
20550 if (OP(preg, regnext(preg, scan)) == END) {
20551 scan = OPERAND(scan);
20552
20553
20554 if (OP(preg, scan) == EXACTLY) {
20555 preg->regstart = preg->program[OPERAND(scan)];
20556 }
20557 else if (OP(preg, scan) == BOL)
20558 preg->reganch++;
@@ -20579,24 +20434,24 @@
20579 #endif
20580
20581 return 0;
20582 }
20583
20584 static int reg(regex_t *preg, int paren , int *flagp )
20585 {
20586 int ret;
20587 int br;
20588 int ender;
20589 int parno = 0;
20590 int flags;
20591
20592 *flagp = HASWIDTH;
20593
20594
20595 if (paren) {
20596 if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20597
20598 preg->regparse += 2;
20599 parno = -1;
20600 }
20601 else {
20602 parno = ++preg->re_nsub;
@@ -20603,16 +20458,16 @@
20603 }
20604 ret = regnode(preg, OPEN+parno);
20605 } else
20606 ret = 0;
20607
20608
20609 br = regbranch(preg, &flags);
20610 if (br == 0)
20611 return 0;
20612 if (ret != 0)
20613 regtail(preg, ret, br);
20614 else
20615 ret = br;
20616 if (!(flags&HASWIDTH))
20617 *flagp &= ~HASWIDTH;
20618 *flagp |= flags&SPSTART;
@@ -20619,25 +20474,25 @@
20619 while (*preg->regparse == '|') {
20620 preg->regparse++;
20621 br = regbranch(preg, &flags);
20622 if (br == 0)
20623 return 0;
20624 regtail(preg, ret, br);
20625 if (!(flags&HASWIDTH))
20626 *flagp &= ~HASWIDTH;
20627 *flagp |= flags&SPSTART;
20628 }
20629
20630
20631 ender = regnode(preg, (paren) ? CLOSE+parno : END);
20632 regtail(preg, ret, ender);
20633
20634
20635 for (br = ret; br != 0; br = regnext(preg, br))
20636 regoptail(preg, br, ender);
20637
20638
20639 if (paren && *preg->regparse++ != ')') {
20640 preg->err = REG_ERR_UNMATCHED_PAREN;
20641 return 0;
20642 } else if (!paren && *preg->regparse != '\0') {
20643 if (*preg->regparse == ')') {
@@ -20657,11 +20512,11 @@
20657 int ret;
20658 int chain;
20659 int latest;
20660 int flags;
20661
20662 *flagp = WORST;
20663
20664 ret = regnode(preg, BRANCH);
20665 chain = 0;
20666 while (*preg->regparse != '\0' && *preg->regparse != ')' &&
20667 *preg->regparse != '|') {
@@ -20675,11 +20530,11 @@
20675 else {
20676 regtail(preg, chain, latest);
20677 }
20678 chain = latest;
20679 }
20680 if (chain == 0)
20681 (void) regnode(preg, NOTHING);
20682
20683 return(ret);
20684 }
20685
@@ -20705,11 +20560,11 @@
20705 if (!(flags&HASWIDTH) && op != '?') {
20706 preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
20707 return 0;
20708 }
20709
20710
20711 if (op == '{') {
20712 char *end;
20713
20714 min = strtoul(preg->regparse + 1, &end, 10);
20715 if (end == preg->regparse + 1) {
@@ -20716,10 +20571,14 @@
20716 preg->err = REG_ERR_BAD_COUNT;
20717 return 0;
20718 }
20719 if (*end == '}') {
20720 max = min;
 
 
 
 
20721 }
20722 else {
20723 preg->regparse = end;
20724 max = strtoul(preg->regparse + 1, &end, 10);
20725 if (*end != '}') {
@@ -20777,11 +20636,11 @@
20777 static void reg_addrange(regex_t *preg, int lower, int upper)
20778 {
20779 if (lower > upper) {
20780 reg_addrange(preg, upper, lower);
20781 }
20782
20783 regc(preg, upper - lower + 1);
20784 regc(preg, lower);
20785 }
20786
20787 static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20704,17 @@
20845 case 'r': *ch = '\r'; break;
20846 case 't': *ch = '\t'; break;
20847 case 'v': *ch = '\v'; break;
20848 case 'u':
20849 if (*s == '{') {
20850
20851 n = parse_hex(s + 1, 6, ch);
20852 if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
20853 s += n + 2;
20854 }
20855 else {
20856
20857 *ch = 'u';
20858 }
20859 }
20860 else if ((n = parse_hex(s, 4, ch)) > 0) {
20861 s += n;
@@ -20886,15 +20745,15 @@
20886 int nocase = (preg->cflags & REG_ICASE);
20887
20888 int ch;
20889 int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
20890
20891 *flagp = WORST;
20892
20893 preg->regparse += n;
20894 switch (ch) {
20895
20896 case '^':
20897 ret = regnode(preg, BOL);
20898 break;
20899 case '$':
20900 ret = regnode(preg, EOL);
@@ -20904,37 +20763,60 @@
20904 *flagp |= HASWIDTH|SIMPLE;
20905 break;
20906 case '[': {
20907 const char *pattern = preg->regparse;
20908
20909 if (*pattern == '^') {
20910 ret = regnode(preg, ANYBUT);
20911 pattern++;
20912 } else
20913 ret = regnode(preg, ANYOF);
20914
20915
20916 if (*pattern == ']' || *pattern == '-') {
20917 reg_addrange(preg, *pattern, *pattern);
20918 pattern++;
20919 }
20920
20921 while (*pattern && *pattern != ']') {
20922
20923 int start;
20924 int end;
20925
 
 
 
 
 
 
 
20926 pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
20927 if (start == '\\') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20928 pattern += reg_decode_escape(pattern, &start);
20929 if (start == 0) {
20930 preg->err = REG_ERR_NULL_CHAR;
20931 return 0;
20932 }
20933 }
20934 if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20935
20936 pattern += utf8_tounicode(pattern, &end);
20937 pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
20938 if (end == '\\') {
20939 pattern += reg_decode_escape(pattern, &end);
20940 if (end == 0) {
@@ -20949,30 +20831,25 @@
20949 if (start == '[' && pattern[0] == ':') {
20950 static const char *character_class[] = {
20951 ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:",
20952 ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:",
20953 };
20954 enum {
20955 CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
20956 CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
20957 CC_NUM
20958 };
20959 int i;
20960
20961 for (i = 0; i < CC_NUM; i++) {
20962 int n = strlen(character_class[i]);
20963 if (strncmp(pattern, character_class[i], n) == 0) {
20964
20965 pattern += n + 1;
20966 break;
20967 }
20968 }
20969 if (i != CC_NUM) {
20970 switch (i) {
 
20971 case CC_ALNUM:
20972 reg_addrange(preg, '0', '9');
20973
20974 case CC_ALPHA:
20975 if ((preg->cflags & REG_ICASE) == 0) {
20976 reg_addrange(preg, 'a', 'z');
20977 }
20978 reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20867,11 @@
20990 reg_addrange(preg, 'a', 'z');
20991 break;
20992 case CC_XDIGIT:
20993 reg_addrange(preg, 'a', 'f');
20994 reg_addrange(preg, 'A', 'F');
20995
20996 case CC_DIGIT:
20997 reg_addrange(preg, '0', '9');
20998 break;
20999 case CC_CNTRL:
21000 reg_addrange(preg, 0, 31);
@@ -21014,11 +20891,11 @@
21014 break;
21015 }
21016 continue;
21017 }
21018 }
21019
21020 reg_addrange(preg, start, start);
21021 }
21022 regc(preg, '\0');
21023
21024 if (*pattern) {
@@ -21037,11 +20914,11 @@
21037 break;
21038 case '\0':
21039 case '|':
21040 case ')':
21041 preg->err = REG_ERR_INTERNAL;
21042 return 0;
21043 case '?':
21044 case '+':
21045 case '*':
21046 case '{':
21047 preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +20967,34 @@
21090 ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
21091 reg_addrange_str(preg," \t\r\n\f\v");
21092 regc(preg, '\0');
21093 *flagp |= HASWIDTH|SIMPLE;
21094 break;
21095
21096 default:
21097
21098
21099 preg->regparse--;
21100 goto de_fault;
21101 }
21102 break;
21103 de_fault:
21104 default: {
21105 int added = 0;
21106
21107
21108 preg->regparse -= n;
21109
21110 ret = regnode(preg, EXACTLY);
21111
21112
21113
21114 while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
21115 n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
21116 if (ch == '\\' && preg->regparse[n]) {
21117 if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
21118
21119 break;
21120 }
21121 n += reg_decode_escape(preg->regparse + n, &ch);
21122 if (ch == 0) {
21123 preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21002,23 @@
21125 }
21126 }
21127
21128
21129 if (ISMULT(preg->regparse[n])) {
21130
21131 if (added) {
21132
21133 break;
21134 }
21135
21136 regc(preg, ch);
21137 added++;
21138 preg->regparse += n;
21139 break;
21140 }
21141
21142
21143 regc(preg, ch);
21144 added++;
21145 preg->regparse += n;
21146 }
21147 regc(preg, '\0');
@@ -21168,15 +21045,15 @@
21168
21169 static int regnode(regex_t *preg, int op)
21170 {
21171 reg_grow(preg, 2);
21172
21173
21174 preg->program[preg->p++] = op;
21175 preg->program[preg->p++] = 0;
21176
21177
21178 return preg->p - 2;
21179 }
21180
21181 static void regc(regex_t *preg, int b )
21182 {
@@ -21186,13 +21063,13 @@
21186
21187 static int reginsert(regex_t *preg, int op, int size, int opnd )
21188 {
21189 reg_grow(preg, size);
21190
21191
21192 memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21193
21194 memset(preg->program + opnd, 0, sizeof(int) * size);
21195
21196 preg->program[opnd] = op;
21197
21198 preg->p += size;
@@ -21204,11 +21081,11 @@
21204 {
21205 int scan;
21206 int temp;
21207 int offset;
21208
21209
21210 scan = p;
21211 for (;;) {
21212 temp = regnext(preg, scan);
21213 if (temp == 0)
21214 break;
@@ -21224,11 +21101,11 @@
21224 }
21225
21226
21227 static void regoptail(regex_t *preg, int p, int val )
21228 {
21229
21230 if (p != 0 && OP(preg, p) == BRANCH) {
21231 regtail(preg, OPERAND(p), val);
21232 }
21233 }
21234
@@ -21240,16 +21117,16 @@
21240 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
21241 {
21242 const char *s;
21243 int scan;
21244
21245
21246 if (preg == NULL || preg->program == NULL || string == NULL) {
21247 return REG_ERR_NULL_ARGUMENT;
21248 }
21249
21250
21251 if (*preg->program != REG_MAGIC) {
21252 return REG_ERR_CORRUPTED;
21253 }
21254
21255 #ifdef DEBUG
@@ -21258,51 +21135,51 @@
21258 #endif
21259
21260 preg->eflags = eflags;
21261 preg->pmatch = pmatch;
21262 preg->nmatch = nmatch;
21263 preg->start = string;
21264
21265
21266 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
21267 int op = OP(preg, scan);
21268 if (op == END)
21269 break;
21270 if (op == REPX || op == REPXMIN)
21271 preg->program[scan + 4] = 0;
21272 }
21273
21274
21275 if (preg->regmust != 0) {
21276 s = string;
21277 while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
21278 if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
21279 break;
21280 }
21281 s++;
21282 }
21283 if (s == NULL)
21284 return REG_NOMATCH;
21285 }
21286
21287
21288 preg->regbol = string;
21289
21290
21291 if (preg->reganch) {
21292 if (eflags & REG_NOTBOL) {
21293
21294 goto nextline;
21295 }
21296 while (1) {
21297 if (regtry(preg, string)) {
21298 return REG_NOERROR;
21299 }
21300 if (*string) {
21301 nextline:
21302 if (preg->cflags & REG_NEWLINE) {
21303
21304 string = strchr(string, '\n');
21305 if (string) {
21306 preg->regbol = ++string;
21307 continue;
21308 }
@@ -21310,22 +21187,22 @@
21310 }
21311 return REG_NOMATCH;
21312 }
21313 }
21314
21315
21316 s = string;
21317 if (preg->regstart != '\0') {
21318
21319 while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
21320 if (regtry(preg, s))
21321 return REG_NOERROR;
21322 s++;
21323 }
21324 }
21325 else
21326
21327 while (1) {
21328 if (regtry(preg, s))
21329 return REG_NOERROR;
21330 if (*s == '\0') {
21331 break;
@@ -21334,15 +21211,15 @@
21334 int c;
21335 s += utf8_tounicode(s, &c);
21336 }
21337 }
21338
21339
21340 return REG_NOMATCH;
21341 }
21342
21343
21344 static int regtry( regex_t *preg, const char *string )
21345 {
21346 int i;
21347
21348 preg->reginput = string;
@@ -21379,11 +21256,11 @@
21379 }
21380
21381 static int reg_range_find(const int *range, int c)
21382 {
21383 while (*range) {
21384
21385 if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
21386 return 1;
21387 }
21388 range += 2;
21389 }
@@ -21391,11 +21268,11 @@
21391 }
21392
21393 static const char *str_find(const char *string, int c, int nocase)
21394 {
21395 if (nocase) {
21396
21397 c = utf8_upper(c);
21398 }
21399 while (*string) {
21400 int ch;
21401 int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21312,15 @@
21435 no = regrepeat(preg, scan + 5, max);
21436 if (no < min) {
21437 return 0;
21438 }
21439 if (matchmin) {
21440
21441 max = no;
21442 no = min;
21443 }
21444
21445 while (1) {
21446 if (matchmin) {
21447 if (no > max) {
21448 break;
21449 }
@@ -21453,22 +21330,22 @@
21453 break;
21454 }
21455 }
21456 preg->reginput = save + utf8_index(save, no);
21457 reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21458
21459 if (reg_iseol(preg, nextch) || c == nextch) {
21460 if (regmatch(preg, next)) {
21461 return(1);
21462 }
21463 }
21464 if (matchmin) {
21465
21466 no++;
21467 }
21468 else {
21469
21470 no--;
21471 }
21472 }
21473 return(0);
21474 }
@@ -21478,13 +21355,13 @@
21478 int *scanpt = preg->program + scan;
21479
21480 int max = scanpt[2];
21481 int min = scanpt[3];
21482
21483
21484 if (scanpt[4] < min) {
21485
21486 scanpt[4]++;
21487 if (regmatch(preg, scan + 5)) {
21488 return 1;
21489 }
21490 scanpt[4]--;
@@ -21493,39 +21370,39 @@
21493 if (scanpt[4] > max) {
21494 return 0;
21495 }
21496
21497 if (matchmin) {
21498
21499 if (regmatch(preg, regnext(preg, scan))) {
21500 return 1;
21501 }
21502
21503 scanpt[4]++;
21504 if (regmatch(preg, scan + 5)) {
21505 return 1;
21506 }
21507 scanpt[4]--;
21508 return 0;
21509 }
21510
21511 if (scanpt[4] < max) {
21512 scanpt[4]++;
21513 if (regmatch(preg, scan + 5)) {
21514 return 1;
21515 }
21516 scanpt[4]--;
21517 }
21518
21519 return regmatch(preg, regnext(preg, scan));
21520 }
21521
21522
21523 static int regmatch(regex_t *preg, int prog)
21524 {
21525 int scan;
21526 int next;
21527 const char *save;
21528
21529 scan = prog;
21530
21531 #ifdef DEBUG
@@ -21535,11 +21412,11 @@
21535 while (scan != 0) {
21536 int n;
21537 int c;
21538 #ifdef DEBUG
21539 if (regnarrate) {
21540 fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21541 }
21542 #endif
21543 next = regnext(preg, scan);
21544 n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21545
@@ -21546,49 +21423,49 @@
21546 switch (OP(preg, scan)) {
21547 case BOLX:
21548 if ((preg->eflags & REG_NOTBOL)) {
21549 return(0);
21550 }
21551
21552 case BOL:
21553 if (preg->reginput != preg->regbol) {
21554 return(0);
21555 }
21556 break;
21557 case EOLX:
21558 if (c != 0) {
21559
21560 return 0;
21561 }
21562 break;
21563 case EOL:
21564 if (!reg_iseol(preg, c)) {
21565 return(0);
21566 }
21567 break;
21568 case WORDA:
21569
21570 if ((!isalnum(UCHAR(c))) && c != '_')
21571 return(0);
21572
21573 if (preg->reginput > preg->regbol &&
21574 (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
21575 return(0);
21576 break;
21577 case WORDZ:
21578
21579 if (preg->reginput > preg->regbol) {
21580
21581 if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
21582 c = preg->reginput[-1];
21583
21584 if (isalnum(UCHAR(c)) || c == '_') {
21585 break;
21586 }
21587 }
21588 }
21589
21590 return(0);
21591
21592 case ANY:
21593 if (reg_iseol(preg, c))
21594 return 0;
@@ -21624,12 +21501,12 @@
21624 case NOTHING:
21625 break;
21626 case BACK:
21627 break;
21628 case BRANCH:
21629 if (OP(preg, next) != BRANCH)
21630 next = OPERAND(scan);
21631 else {
21632 do {
21633 save = preg->reginput;
21634 if (regmatch(preg, OPERAND(scan))) {
21635 return(1);
@@ -21636,11 +21513,11 @@
21636 }
21637 preg->reginput = save;
21638 scan = regnext(preg, scan);
21639 } while (scan != 0 && OP(preg, scan) == BRANCH);
21640 return(0);
21641
21642 }
21643 break;
21644 case REP:
21645 case REPMIN:
21646 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21525,11 @@
21648 case REPX:
21649 case REPXMIN:
21650 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21651
21652 case END:
21653 return 1;
21654
21655 case OPENNC:
21656 case CLOSENC:
21657 return regmatch(preg, next);
21658
@@ -21695,11 +21572,11 @@
21695
21696 scan = preg->reginput;
21697 opnd = OPERAND(p);
21698 switch (OP(preg, p)) {
21699 case ANY:
21700
21701 while (!reg_iseol(preg, *scan) && count < max) {
21702 count++;
21703 scan++;
21704 }
21705 break;
@@ -21731,13 +21608,13 @@
21731 }
21732 count++;
21733 scan += n;
21734 }
21735 break;
21736 default:
21737 preg->err = REG_ERR_INTERNAL;
21738 count = 0;
21739 break;
21740 }
21741 preg->reginput = scan;
21742
21743 return(count);
@@ -21758,11 +21635,11 @@
21758 return(p+offset);
21759 }
21760
21761 static int regopsize(regex_t *preg, int p )
21762 {
21763
21764 switch (OP(preg, p)) {
21765 case REP:
21766 case REPMIN:
21767 case REPX:
21768 case REPXMIN:
@@ -21818,10 +21695,223 @@
21818
21819 void regfree(regex_t *preg)
21820 {
21821 free(preg->program);
21822 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21823
21824 #endif
21825
21826 #if defined(_WIN32) || defined(WIN32)
21827 #ifndef STRICT
@@ -21879,26 +21969,26 @@
21879 {
21880 DIR *dir = 0;
21881
21882 if (name && name[0]) {
21883 size_t base_length = strlen(name);
21884 const char *all =
21885 strchr("/\\", name[base_length - 1]) ? "*" : "/*";
21886
21887 if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
21888 (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
21889 strcat(strcpy(dir->name, name), all);
21890
21891 if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
21892 dir->result.d_name = 0;
21893 else {
21894 Jim_Free(dir->name);
21895 Jim_Free(dir);
21896 dir = 0;
21897 }
21898 }
21899 else {
21900 Jim_Free(dir);
21901 dir = 0;
21902 errno = ENOMEM;
21903 }
21904 }
@@ -21916,11 +22006,11 @@
21916 if (dir->handle != -1)
21917 result = _findclose(dir->handle);
21918 Jim_Free(dir->name);
21919 Jim_Free(dir);
21920 }
21921 if (result == -1)
21922 errno = EBADF;
21923 return result;
21924 }
21925
21926 struct dirent *readdir(DIR * dir)
@@ -21938,28 +22028,77 @@
21938 }
21939 return result;
21940 }
21941 #endif
21942 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21943 #ifndef JIM_BOOTSTRAP_LIB_ONLY
21944 #include <errno.h>
21945 #include <string.h>
21946
21947
21948 #ifdef USE_LINENOISE
21949 #ifdef HAVE_UNISTD_H
21950 #include <unistd.h>
21951 #endif
 
 
 
21952 #include "linenoise.h"
21953 #else
21954 #define MAX_LINE_LEN 512
21955 #endif
21956
21957 char *Jim_HistoryGetline(const char *prompt)
 
 
 
 
 
21958 {
21959 #ifdef USE_LINENOISE
21960 return linenoise(prompt);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21961 #else
21962 int len;
21963 char *line = malloc(MAX_LINE_LEN);
21964
21965 fputs(prompt, stdout);
@@ -21992,26 +22131,92 @@
21992 }
21993
21994 void Jim_HistorySave(const char *filename)
21995 {
21996 #ifdef USE_LINENOISE
 
 
 
 
 
21997 linenoiseHistorySave(filename);
 
 
 
21998 #endif
21999 }
22000
22001 void Jim_HistoryShow(void)
22002 {
22003 #ifdef USE_LINENOISE
22004
22005 int i;
22006 int len;
22007 char **history = linenoiseHistory(&len);
22008 for (i = 0; i < len; i++) {
22009 printf("%4d %s\n", i + 1, history[i]);
22010 }
22011 #endif
22012 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22013
22014 int Jim_InteractivePrompt(Jim_Interp *interp)
22015 {
22016 int retcode = JIM_OK;
22017 char *history_file = NULL;
@@ -22023,10 +22228,12 @@
22023 int history_len = strlen(home) + sizeof("/.jim_history");
22024 history_file = Jim_Alloc(history_len);
22025 snprintf(history_file, history_len, "%s/.jim_history", home);
22026 Jim_HistoryLoad(history_file);
22027 }
 
 
22028 #endif
22029
22030 printf("Welcome to Jim version %d.%d\n",
22031 JIM_VERSION / 100, JIM_VERSION % 100);
22032 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22055,21 +22262,21 @@
22055 Jim_IncrRefCount(scriptObjPtr);
22056 while (1) {
22057 char state;
22058 char *line;
22059
22060 line = Jim_HistoryGetline(prompt);
22061 if (line == NULL) {
22062 if (errno == EINTR) {
22063 continue;
22064 }
22065 Jim_DecrRefCount(interp, scriptObjPtr);
22066 retcode = JIM_OK;
22067 goto out;
22068 }
22069 if (Jim_Length(scriptObjPtr) != 0) {
22070
22071 Jim_AppendString(interp, scriptObjPtr, "\n", 1);
22072 }
22073 Jim_AppendString(interp, scriptObjPtr, line, -1);
22074 free(line);
22075 if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22284,11 @@
22077
22078 snprintf(prompt, sizeof(prompt), "%c> ", state);
22079 }
22080 #ifdef USE_LINENOISE
22081 if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22082
22083 Jim_HistoryShow();
22084 Jim_DecrRefCount(interp, scriptObjPtr);
22085 continue;
22086 }
22087
@@ -22104,10 +22311,11 @@
22104 printf("%s\n", result);
22105 }
22106 }
22107 out:
22108 Jim_Free(history_file);
 
22109 return retcode;
22110 }
22111
22112 #include <stdio.h>
22113 #include <stdlib.h>
@@ -22120,11 +22328,11 @@
22120 static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
22121 {
22122 int n;
22123 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
22124
22125
22126 for (n = 0; n < argc; n++) {
22127 Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
22128
22129 Jim_ListAppendElement(interp, listObj, obj);
22130 }
@@ -22146,71 +22354,75 @@
22146 printf("or : %s [options] [filename]\n", executable_name);
22147 printf("\n");
22148 printf("Without options: Interactive mode\n");
22149 printf("\n");
22150 printf("Options:\n");
22151 printf(" --version : prints the version string\n");
22152 printf(" --help : prints this text\n");
22153 printf(" -e CMD : executes command CMD\n");
22154 printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22155 printf(" [filename] : executes the script contained in the named file\n");
22156 printf(" NOTE: all subsequent options will be passed to the script\n\n");
22157 }
22158
22159 int main(int argc, char *const argv[])
22160 {
22161 int retcode;
22162 Jim_Interp *interp;
22163 char *const orig_argv0 = argv[0];
22164
22165
22166 if (argc > 1 && strcmp(argv[1], "--version") == 0) {
22167 printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
22168 return 0;
22169 }
22170 else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
22171 usage(argv[0]);
22172 return 0;
22173 }
22174
22175
22176 interp = Jim_CreateInterp();
22177 Jim_RegisterCoreCommands(interp);
22178
22179
22180 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
22181 JimPrintErrorMessage(interp);
22182 }
22183
22184 Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
22185 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
22186 retcode = Jim_initjimshInit(interp);
22187
22188 if (argc == 1) {
22189
22190 if (retcode == JIM_ERR) {
22191 JimPrintErrorMessage(interp);
22192 }
22193 if (retcode != JIM_EXIT) {
22194 JimSetArgv(interp, 0, NULL);
22195 retcode = Jim_InteractivePrompt(interp);
22196 }
22197 }
22198 else {
22199
22200 if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22201
22202 JimSetArgv(interp, argc - 3, argv + 3);
22203 retcode = Jim_Eval(interp, argv[2]);
22204 if (retcode != JIM_ERR) {
22205 printf("%s\n", Jim_String(Jim_GetResult(interp)));
22206 }
22207 }
22208 else {
22209 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
22210 JimSetArgv(interp, argc - 2, argv + 2);
22211 retcode = Jim_EvalFile(interp, argv[1]);
 
 
 
 
22212 }
22213 if (retcode == JIM_ERR) {
22214 JimPrintErrorMessage(interp);
22215 }
22216 }
22217
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
 
2 #define JIM_TCL_COMPAT
 
3 #define JIM_ANSIC
4 #define JIM_REGEXP
5 #define HAVE_NO_AUTOCONF
6 #define _JIMAUTOCONF_H
7 #define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
29 #define HAVE_MKDIR_ONE_ARG
30 #define HAVE_SYSTEM
31 #define HAVE_SYS_TIME_H
32 #define HAVE_DIRENT_H
33 #define HAVE_UNISTD_H
34 #define HAVE_UMASK
35 #include <sys/stat.h>
36 #ifndef S_IRWXG
37 #define S_IRWXG 0
38 #endif
39 #ifndef S_IRWXO
40 #define S_IRWXO 0
41 #endif
42 #else
43 #define TCL_PLATFORM_OS "unknown"
44 #define TCL_PLATFORM_PLATFORM "unix"
45 #define TCL_PLATFORM_PATH_SEPARATOR ":"
46 #ifdef _MINIX
47 #define vfork fork
48 #define _POSIX_SOURCE
49 #else
50 #define _GNU_SOURCE
51 #endif
52 #define HAVE_VFORK
53 #define HAVE_WAITPID
54 #define HAVE_ISATTY
55 #define HAVE_MKSTEMP
56 #define HAVE_LINK
57 #define HAVE_SYS_TIME_H
58 #define HAVE_DIRENT_H
59 #define HAVE_UNISTD_H
60 #define HAVE_UMASK
61 #endif
62 #define JIM_VERSION 78
63 #ifndef JIM_WIN32COMPAT_H
64 #define JIM_WIN32COMPAT_H
65
66
67
@@ -88,11 +101,10 @@
101 #define JIM_WIDE_MIN LLONG_MIN
102 #define JIM_WIDE_MAX LLONG_MAX
103 #define JIM_WIDE_MODIFIER "I64d"
104 #define strcasecmp _stricmp
105 #define strtoull _strtoui64
 
106
107 #include <io.h>
108
109 struct timeval {
110 long tv_sec;
@@ -105,29 +117,24 @@
117 struct dirent {
118 char *d_name;
119 };
120
121 typedef struct DIR {
122 long handle;
123 struct _finddata_t info;
124 struct dirent result;
125 char *name;
126 } DIR;
127
128 DIR *opendir(const char *name);
129 int closedir(DIR *dir);
130 struct dirent *readdir(DIR *dir);
131
132 #endif
 
 
 
133
134 #endif
135
 
 
136 #ifdef __cplusplus
137 }
138 #endif
139
140 #endif
@@ -146,19 +153,21 @@
153
154 #ifndef JIM_UTF8
155 #include <ctype.h>
156
157
158 #define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
159 #define utf8_strwidth(S, B) utf8_strlen((S), (B))
160 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
161 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
162 #define utf8_upper(C) toupper(C)
163 #define utf8_title(C) toupper(C)
164 #define utf8_lower(C) tolower(C)
165 #define utf8_index(C, I) (I)
166 #define utf8_charlen(C) 1
167 #define utf8_prev_len(S, L) 1
168 #define utf8_width(C) 1
169
170 #else
171
172 #endif
173
@@ -175,13 +184,13 @@
184 extern "C" {
185 #endif
186
187 #include <time.h>
188 #include <limits.h>
189 #include <stdio.h>
190 #include <stdlib.h>
191 #include <stdarg.h>
192
193
194 #ifndef HAVE_NO_AUTOCONF
195 #endif
196
@@ -224,31 +233,31 @@
233 #define JIM_SIGNAL 5
234 #define JIM_EXIT 6
235
236 #define JIM_EVAL 7
237
238 #define JIM_MAX_CALLFRAME_DEPTH 1000
239 #define JIM_MAX_EVAL_DEPTH 2000
240
241
242 #define JIM_PRIV_FLAG_SHIFT 20
243
244 #define JIM_NONE 0
245 #define JIM_ERRMSG 1
246 #define JIM_ENUM_ABBREV 2
247 #define JIM_UNSHARED 4
248 #define JIM_MUSTEXIST 8
249
250
251 #define JIM_SUBST_NOVAR 1
252 #define JIM_SUBST_NOCMD 2
253 #define JIM_SUBST_NOESC 4
254 #define JIM_SUBST_FLAG 128
255
256
257 #define JIM_CASESENS 0
258 #define JIM_NOCASE 1
259
260
261 #define JIM_PATH_LEN 1024
262
263
@@ -339,79 +348,80 @@
348 #define Jim_GetHashTableSize(ht) ((ht)->size)
349 #define Jim_GetHashTableUsed(ht) ((ht)->used)
350
351
352 typedef struct Jim_Obj {
353 char *bytes;
354 const struct Jim_ObjType *typePtr;
355 int refCount;
356 int length;
357
358 union {
359
360 jim_wide wideValue;
361
362 int intValue;
363
364 double doubleValue;
365
366 void *ptr;
367
368 struct {
369 void *ptr1;
370 void *ptr2;
371 } twoPtrValue;
372
373 struct {
374 void *ptr;
375 int int1;
376 int int2;
377 } ptrIntValue;
378
379 struct {
380 struct Jim_Var *varPtr;
381 unsigned long callFrameId;
382 int global;
383 } varValue;
384
385 struct {
386 struct Jim_Obj *nsObj;
387 struct Jim_Cmd *cmdPtr;
388 unsigned long procEpoch;
389 } cmdValue;
390
391 struct {
392 struct Jim_Obj **ele;
393 int len;
394 int maxLen;
395 } listValue;
396
397 struct {
398 int maxLength;
399 int charLength;
400 } strValue;
401
402 struct {
403 unsigned long id;
404 struct Jim_Reference *refPtr;
405 } refValue;
406
407 struct {
408 struct Jim_Obj *fileNameObj;
409 int lineNumber;
410 } sourceValue;
411
412 struct {
413 struct Jim_Obj *varNameObjPtr;
414 struct Jim_Obj *indexObjPtr;
415 } dictSubstValue;
 
 
 
 
 
416 struct {
417 int line;
418 int argc;
419 } scriptLineValue;
420 } internalRep;
421 struct Jim_Obj *prevObjPtr;
422 struct Jim_Obj *nextObjPtr;
423 } Jim_Obj;
424
425
426 #define Jim_IncrRefCount(objPtr) \
427 ++(objPtr)->refCount
@@ -442,40 +452,40 @@
452 typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
453 struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
454 typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
455
456 typedef struct Jim_ObjType {
457 const char *name;
458 Jim_FreeInternalRepProc *freeIntRepProc;
459 Jim_DupInternalRepProc *dupIntRepProc;
460 Jim_UpdateStringProc *updateStringProc;
461 int flags;
462 } Jim_ObjType;
463
464
465 #define JIM_TYPE_NONE 0
466 #define JIM_TYPE_REFERENCES 1
467
468
469
470 typedef struct Jim_CallFrame {
471 unsigned long id;
472 int level;
473 struct Jim_HashTable vars;
474 struct Jim_HashTable *staticVars;
475 struct Jim_CallFrame *parent;
476 Jim_Obj *const *argv;
477 int argc;
478 Jim_Obj *procArgsObjPtr;
479 Jim_Obj *procBodyObjPtr;
480 struct Jim_CallFrame *next;
481 Jim_Obj *nsObj;
482 Jim_Obj *fileNameObj;
483 int line;
484 Jim_Stack *localCommands;
485 struct Jim_Obj *tailcallObj;
486 struct Jim_Cmd *tailcallCmd;
487 } Jim_CallFrame;
488
489 typedef struct Jim_Var {
490 Jim_Obj *objPtr;
491 struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +497,35 @@
497 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
498
499
500
501 typedef struct Jim_Cmd {
502 int inUse;
503 int isproc;
504 struct Jim_Cmd *prevCmd;
505 union {
506 struct {
507
508 Jim_CmdProc *cmdProc;
509 Jim_DelCmdProc *delProc;
510 void *privData;
511 } native;
512 struct {
513
514 Jim_Obj *argListObjPtr;
515 Jim_Obj *bodyObjPtr;
516 Jim_HashTable *staticVars;
517 int argListLen;
518 int reqArity;
519 int optArity;
520 int argsPos;
521 int upcall;
522 struct Jim_ProcArg {
523 Jim_Obj *nameObjPtr;
524 Jim_Obj *defaultObjPtr;
525 } *arglist;
526 Jim_Obj *nsObj;
527 } proc;
528 } u;
529 } Jim_Cmd;
530
531
@@ -523,64 +533,64 @@
533 unsigned char sbox[256];
534 unsigned int i, j;
535 } Jim_PrngState;
536
537 typedef struct Jim_Interp {
538 Jim_Obj *result;
539 int errorLine;
540 Jim_Obj *errorFileNameObj;
541 int addStackTrace;
542 int maxCallFrameDepth;
543 int maxEvalDepth;
544 int evalDepth;
545 int returnCode;
546 int returnLevel;
547 int exitCode;
548 long id;
549 int signal_level;
550 jim_wide sigmask;
551 int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
552 Jim_CallFrame *framePtr;
553 Jim_CallFrame *topFramePtr;
554 struct Jim_HashTable commands;
555 unsigned long procEpoch; /* Incremented every time the result
556 of procedures names lookup caching
557 may no longer be valid. */
558 unsigned long callFrameEpoch; /* Incremented every time a new
559 callframe is created. This id is used for the
560 'ID' field contained in the Jim_CallFrame
561 structure. */
562 int local;
563 Jim_Obj *liveList;
564 Jim_Obj *freeList;
565 Jim_Obj *currentScriptObj;
566 Jim_Obj *nullScriptObj;
567 Jim_Obj *emptyObj;
568 Jim_Obj *trueObj;
569 Jim_Obj *falseObj;
570 unsigned long referenceNextId;
571 struct Jim_HashTable references;
572 unsigned long lastCollectId; /* reference max Id of the last GC
573 execution. It's set to -1 while the collection
574 is running as sentinel to avoid to recursive
575 calls via the [collect] command inside
576 finalizers. */
577 time_t lastCollectTime;
578 Jim_Obj *stackTrace;
579 Jim_Obj *errorProc;
580 Jim_Obj *unknown;
581 int unknown_called;
582 int errorFlag;
583 void *cmdPrivData; /* Used to pass the private data pointer to
584 a command. It is set to what the user specified
585 via Jim_CreateCommand(). */
586
587 struct Jim_CallFrame *freeFramesList;
588 struct Jim_HashTable assocData;
589 Jim_PrngState *prngState;
590 struct Jim_HashTable packages;
591 Jim_Stack *loadHandles;
592 } Jim_Interp;
593
594 #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
595 #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
596 #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +633,11 @@
633 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
634
635
636 JIM_EXPORT char **Jim_GetEnviron(void);
637 JIM_EXPORT void Jim_SetEnviron(char **env);
638 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file);
639
640
641 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
642
643
@@ -816,25 +826,33 @@
826 Jim_Obj *newObjPtr, int flags);
827 JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
828 Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
829 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
830 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
831
832 #define JIM_DICTMATCH_KEYS 0x0001
833 #define JIM_DICTMATCH_VALUES 0x002
834
835 JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types);
836 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
837 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
838 JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv);
839
840
841 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
842 int *intPtr);
843
844
845 JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
846 Jim_Obj *exprObjPtr);
847 JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
848 Jim_Obj *exprObjPtr, int *boolPtr);
849
850
851 JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr,
852 int *booleanPtr);
853
854
855 JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
856 jim_wide *widePtr);
857 JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
858 long *longPtr);
@@ -852,10 +870,12 @@
870
871 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
872 Jim_Obj *const *argv, const char *msg);
873 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
874 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
875 JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr,
876 const char *const *tablePtr);
877 JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
878 Jim_Obj *scriptObj, char *stateCharPtr);
879
880 JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
881
@@ -878,11 +898,12 @@
898
899
900 JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
901 JIM_EXPORT void Jim_HistoryLoad(const char *filename);
902 JIM_EXPORT void Jim_HistorySave(const char *filename);
903 JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt);
904 JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj);
905 JIM_EXPORT void Jim_HistoryAdd(const char *line);
906 JIM_EXPORT void Jim_HistoryShow(void);
907
908
909 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
@@ -904,11 +925,11 @@
925
926 #ifdef __cplusplus
927 }
928 #endif
929
930 #endif
931
932 #ifndef JIM_SUBCMD_H
933 #define JIM_SUBCMD_H
934
935
@@ -915,24 +936,24 @@
936 #ifdef __cplusplus
937 extern "C" {
938 #endif
939
940
941 #define JIM_MODFLAG_HIDDEN 0x0001
942 #define JIM_MODFLAG_FULLARGV 0x0002
943
944
945
946 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
947
948 typedef struct {
949 const char *cmd;
950 const char *args;
951 jim_subcmd_function *function;
952 short minargs;
953 short maxargs;
954 unsigned short flags;
955 } jim_subcmd_type;
956
957 const jim_subcmd_type *
958 Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
959
@@ -960,36 +981,36 @@
981 int rm_eo;
982 } regmatch_t;
983
984
985 typedef struct regexp {
986
987 int re_nsub;
988
989
990 int cflags;
991 int err;
992 int regstart;
993 int reganch;
994 int regmust;
995 int regmlen;
996 int *program;
997
998
999 const char *regparse;
1000 int p;
1001 int proglen;
1002
1003
1004 int eflags;
1005 const char *start;
1006 const char *reginput;
1007 const char *regbol;
1008
1009
1010 regmatch_t *pmatch;
1011 int nmatch;
1012 } regexp;
1013
1014 typedef regexp regex_t;
1015
1016 #define REG_EXTENDED 0
@@ -997,13 +1018,13 @@
1018 #define REG_ICASE 2
1019
1020 #define REG_NOTBOL 16
1021
1022 enum {
1023 REG_NOERROR,
1024 REG_NOMATCH,
1025 REG_BADPAT,
1026 REG_ERR_NULL_ARGUMENT,
1027 REG_ERR_UNKNOWN,
1028 REG_ERR_TOO_BIG,
1029 REG_ERR_NOMEM,
1030 REG_ERR_TOO_MANY_PAREN,
@@ -1027,10 +1048,83 @@
1048 void regfree(regex_t *preg);
1049
1050 #ifdef __cplusplus
1051 }
1052 #endif
1053
1054 #endif
1055 #ifndef JIM_SIGNAL_H
1056 #define JIM_SIGNAL_H
1057
1058 #ifdef __cplusplus
1059 extern "C" {
1060 #endif
1061
1062 const char *Jim_SignalId(int sig);
1063
1064 #ifdef __cplusplus
1065 }
1066 #endif
1067
1068 #endif
1069 #ifndef JIMIOCOMPAT_H
1070 #define JIMIOCOMPAT_H
1071
1072
1073 #include <stdio.h>
1074 #include <errno.h>
1075
1076
1077 void Jim_SetResultErrno(Jim_Interp *interp, const char *msg);
1078
1079 int Jim_OpenForWrite(const char *filename, int append);
1080
1081 int Jim_OpenForRead(const char *filename);
1082
1083 #if defined(__MINGW32__)
1084 #ifndef STRICT
1085 #define STRICT
1086 #endif
1087 #define WIN32_LEAN_AND_MEAN
1088 #include <windows.h>
1089 #include <fcntl.h>
1090 #include <io.h>
1091 #include <process.h>
1092
1093 typedef HANDLE pidtype;
1094 #define JIM_BAD_PID INVALID_HANDLE_VALUE
1095
1096 #define JIM_NO_PID INVALID_HANDLE_VALUE
1097
1098
1099 #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0)
1100 #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff)
1101 #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0)
1102 #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff)
1103 #define WNOHANG 1
1104
1105 int Jim_Errno(void);
1106 pidtype waitpid(pidtype pid, int *status, int nohang);
1107
1108 #define HAVE_PIPE
1109 #define pipe(P) _pipe((P), 0, O_NOINHERIT)
1110
1111 #elif defined(HAVE_UNISTD_H)
1112 #include <unistd.h>
1113 #include <fcntl.h>
1114 #include <sys/wait.h>
1115 #include <sys/stat.h>
1116
1117 typedef int pidtype;
1118 #define Jim_Errno() errno
1119 #define JIM_BAD_PID -1
1120 #define JIM_NO_PID 0
1121
1122 #ifndef HAVE_EXECVPE
1123 #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
1124 #endif
1125 #endif
1126
1127 #endif
1128 int Jim_bootstrapInit(Jim_Interp *interp)
1129 {
1130 if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
@@ -1100,10 +1194,43 @@
1194 "\n"
1195 "if {$tcl_platform(platform) eq \"windows\"} {\n"
1196 " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
1197 "}\n"
1198 "\n"
1199 "\n"
1200 "set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n"
1201 "\n"
1202 "\n"
1203 "\n"
1204 "proc tcl::autocomplete {prefix} {\n"
1205 " if {[set space [string first \" \" $prefix]] != -1} {\n"
1206 " set cmd [string range $prefix 0 $space-1]\n"
1207 " if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n"
1208 " set arg [string range $prefix $space+1 end]\n"
1209 "\n"
1210 " return [lmap p [$cmd -commands] {\n"
1211 " if {![string match \"${arg}*\" $p]} continue\n"
1212 " function \"$cmd $p\"\n"
1213 " }]\n"
1214 " }\n"
1215 " }\n"
1216 "\n"
1217 " if {[string match \"source *\" $prefix]} {\n"
1218 " set path [string range $prefix 7 end]\n"
1219 " return [lmap p [glob -nocomplain \"${path}*\"] {\n"
1220 " function \"source $p\"\n"
1221 " }]\n"
1222 " }\n"
1223 "\n"
1224 " return [lmap p [lsort [info commands $prefix*]] {\n"
1225 " if {[string match \"* *\" $p]} {\n"
1226 " continue\n"
1227 " }\n"
1228 " function $p\n"
1229 " }]\n"
1230 "}\n"
1231 "\n"
1232 "_jimsh_init\n"
1233 );
1234 }
1235 int Jim_globInit(Jim_Interp *interp)
1236 {
@@ -1315,10 +1442,17 @@
1442 return JIM_ERR;
1443
1444 return Jim_EvalSource(interp, "stdlib.tcl", 1,
1445 "\n"
1446 "\n"
1447 "if {![exists -command ref]} {\n"
1448 "\n"
1449 " proc ref {args} {{count 0}} {\n"
1450 " format %08x [incr count]\n"
1451 " }\n"
1452 "}\n"
1453 "\n"
1454 "\n"
1455 "proc lambda {arglist args} {\n"
1456 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1457 "}\n"
1458 "\n"
@@ -1375,10 +1509,17 @@
1509 " }\n"
1510 " join $lines \\n\n"
1511 "}\n"
1512 "\n"
1513 "\n"
1514 "\n"
1515 "proc defer {script} {\n"
1516 " upvar jim::defer v\n"
1517 " lappend v $script\n"
1518 "}\n"
1519 "\n"
1520 "\n"
1521 "\n"
1522 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1523 " if {$stacktrace eq \"\"} {\n"
1524 "\n"
1525 " set stacktrace [info stacktrace]\n"
@@ -1402,31 +1543,10 @@
1543 " if {[exists ::jim::exe]} {\n"
1544 " return $::jim::exe\n"
1545 " }\n"
1546 "}\n"
1547 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1548 "\n"
1549 "proc {dict update} {&varName args script} {\n"
1550 " set keys {}\n"
1551 " foreach {n v} $args {\n"
1552 " upvar $v var_$v\n"
@@ -1445,23 +1565,10 @@
1565 " }\n"
1566 " }\n"
1567 " return {*}$opts $msg\n"
1568 "}\n"
1569 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
1570 "proc {dict replace} {dictionary {args {key value}}} {\n"
1571 " if {[llength ${key value}] % 2} {\n"
1572 " tailcall {dict replace}\n"
1573 " }\n"
1574 " tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1610,10 @@
1610 " dict unset dictionary $k\n"
1611 " }\n"
1612 " return $dictionary\n"
1613 "}\n"
1614 "\n"
 
 
 
 
 
1615 "\n"
1616 "proc {dict for} {vars dictionary script} {\n"
1617 " if {[llength $vars] != 2} {\n"
1618 " return -code error \"must have exactly two variable names\"\n"
1619 " }\n"
@@ -1591,11 +1693,10 @@
1693 " tailcall {*}$args\n"
1694 "}\n"
1695 "\n"
1696 "\n"
1697 "\n"
 
1698 "proc parray {arrayname {pattern *} {puts puts}} {\n"
1699 " upvar $arrayname a\n"
1700 "\n"
1701 " set max 0\n"
1702 " foreach name [array names a $pattern]] {\n"
@@ -1647,11 +1748,11 @@
1748 "}\n"
1749 "\n"
1750 "\n"
1751 "\n"
1752 "proc popen {cmd {mode r}} {\n"
1753 " lassign [pipe] r w\n"
1754 " try {\n"
1755 " if {[string match \"w*\" $mode]} {\n"
1756 " lappend cmd <@$r &\n"
1757 " set pids [exec {*}$cmd]\n"
1758 " $r close\n"
@@ -1663,16 +1764,31 @@
1764 " set f $r\n"
1765 " }\n"
1766 " lambda {cmd args} {f pids} {\n"
1767 " if {$cmd eq \"pid\"} {\n"
1768 " return $pids\n"
1769 " }\n"
1770 " if {$cmd eq \"getfd\"} {\n"
1771 " $f getfd\n"
1772 " }\n"
1773 " if {$cmd eq \"close\"} {\n"
1774 " $f close\n"
1775 "\n"
1776 " set retopts {}\n"
1777 " foreach p $pids {\n"
1778 " lassign [wait $p] status - rc\n"
1779 " if {$status eq \"CHILDSTATUS\"} {\n"
1780 " if {$rc == 0} {\n"
1781 " continue\n"
1782 " }\n"
1783 " set msg \"child process exited abnormally\"\n"
1784 " } else {\n"
1785 " set msg \"child killed: received signal\"\n"
1786 " }\n"
1787 " set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n"
1788 " }\n"
1789 " return {*}$retopts\n"
1790 " }\n"
1791 " tailcall $f $cmd {*}$args\n"
1792 " }\n"
1793 " } on error {error opts} {\n"
1794 " $r close\n"
@@ -1692,14 +1808,10 @@
1808 " if {[catch {$channelId pid} pids]} {\n"
1809 " return \"\"\n"
1810 " }\n"
1811 " return $pids\n"
1812 "}\n"
 
 
 
 
1813 "\n"
1814 "\n"
1815 "\n"
1816 "\n"
1817 "\n"
@@ -1780,10 +1892,13 @@
1892 "}\n"
1893 );
1894 }
1895
1896
1897 #ifndef _GNU_SOURCE
1898 #define _GNU_SOURCE
1899 #endif
1900 #include <stdio.h>
1901 #include <string.h>
1902 #include <errno.h>
1903 #include <fcntl.h>
1904 #ifdef HAVE_UNISTD_H
@@ -1793,27 +1908,34 @@
1908
1909
1910 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1911 #include <sys/socket.h>
1912 #include <netinet/in.h>
1913 #include <netinet/tcp.h>
1914 #include <arpa/inet.h>
1915 #include <netdb.h>
1916 #ifdef HAVE_SYS_UN_H
1917 #include <sys/un.h>
1918 #endif
1919 #define HAVE_SOCKETS
1920 #elif defined (__MINGW32__)
1921
1922 #else
1923 #define JIM_ANSIC
1924 #endif
1925
1926 #if defined(JIM_SSL)
1927 #include <openssl/ssl.h>
1928 #include <openssl/err.h>
1929 #endif
1930
1931 #ifdef HAVE_TERMIOS_H
1932 #endif
1933
1934
1935 #define AIO_CMD_LEN 32
1936 #define AIO_BUF_LEN 256
1937
1938 #ifndef HAVE_FTELLO
1939 #define ftello ftell
1940 #endif
1941 #ifndef HAVE_FSEEKO
@@ -1828,10 +1950,16 @@
1950 #define IPV6 0
1951 #ifndef PF_INET6
1952 #define PF_INET6 0
1953 #endif
1954 #endif
1955
1956 #ifdef JIM_ANSIC
1957
1958 #undef HAVE_PIPE
1959 #undef HAVE_SOCKETPAIR
1960 #endif
1961
1962 #define JimCheckStreamError(interp, af) af->fops->error(af)
1963
1964
1965 struct AioFile;
@@ -1848,11 +1976,11 @@
1976 typedef struct AioFile
1977 {
1978 FILE *fp;
1979 Jim_Obj *filename;
1980 int type;
1981 int openFlags;
1982 int fd;
1983 Jim_Obj *rEvent;
1984 Jim_Obj *wEvent;
1985 Jim_Obj *eEvent;
1986 int addr_family;
@@ -1879,21 +2007,21 @@
2007 {
2008 if (!ferror(af->fp)) {
2009 return JIM_OK;
2010 }
2011 clearerr(af->fp);
2012
2013 if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
2014 return JIM_OK;
2015 }
2016 #ifdef ECONNRESET
2017 if (errno == ECONNRESET) {
2018 return JIM_OK;
2019 }
2020 #endif
2021 #ifdef ECONNABORTED
2022 if (errno == ECONNABORTED) {
2023 return JIM_OK;
2024 }
2025 #endif
2026 return JIM_ERR;
2027 }
@@ -1945,20 +2073,19 @@
2073 JIM_NOTUSED(interp);
2074
2075 Jim_DecrRefCount(interp, af->filename);
2076
2077 #ifdef jim_ext_eventloop
2078
2079 Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
2080 #endif
2081
2082 #if defined(JIM_SSL)
2083 if (af->ssl != NULL) {
2084 SSL_free(af->ssl);
2085 }
2086 #endif
 
2087 if (!(af->openFlags & AIO_KEEPOPEN)) {
2088 fclose(af->fp);
2089 }
2090
2091 Jim_Free(af);
@@ -1968,11 +2095,11 @@
2095 {
2096 AioFile *af = Jim_CmdPrivData(interp);
2097 char buf[AIO_BUF_LEN];
2098 Jim_Obj *objPtr;
2099 int nonewline = 0;
2100 jim_wide neededLen = -1;
2101
2102 if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
2103 nonewline = 1;
2104 argv++;
2105 argc--;
@@ -2007,11 +2134,11 @@
2134 }
2135 }
2136 if (retval != readlen)
2137 break;
2138 }
2139
2140 if (JimCheckStreamError(interp, af)) {
2141 Jim_FreeNewObj(interp, objPtr);
2142 return JIM_ERR;
2143 }
2144 if (nonewline) {
@@ -2029,11 +2156,11 @@
2156
2157 AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
2158 {
2159 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2160
2161
2162 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2163 return (AioFile *) cmdPtr->u.native.privData;
2164 }
2165 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2166 return NULL;
@@ -2048,10 +2175,20 @@
2175 return NULL;
2176 }
2177
2178 return af->fp;
2179 }
2180
2181 static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2182 {
2183 AioFile *af = Jim_CmdPrivData(interp);
2184
2185 fflush(af->fp);
2186 Jim_SetResultInt(interp, fileno(af->fp));
2187
2188 return JIM_OK;
2189 }
2190
2191 static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2192 {
2193 AioFile *af = Jim_CmdPrivData(interp);
2194 jim_wide count = 0;
@@ -2110,21 +2247,21 @@
2247 }
2248 else {
2249 len = strlen(buf);
2250
2251 if (len && (buf[len - 1] == '\n')) {
2252
2253 len--;
2254 }
2255
2256 Jim_AppendString(interp, objPtr, buf, len);
2257 break;
2258 }
2259 }
2260
2261 if (JimCheckStreamError(interp, af)) {
2262
2263 Jim_FreeNewObj(interp, objPtr);
2264 return JIM_ERR;
2265 }
2266
2267 if (argc) {
@@ -2134,11 +2271,11 @@
2271 }
2272
2273 len = Jim_Length(objPtr);
2274
2275 if (len == 0 && feof(af->fp)) {
2276
2277 len = -1;
2278 }
2279 Jim_SetResultInt(interp, len);
2280 }
2281 else {
@@ -2207,11 +2344,11 @@
2344 }
2345
2346 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2347 {
2348 if (argc == 3) {
2349 #if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN)
2350 static const char * const options[] = { "r", "w", NULL };
2351 enum { OPT_R, OPT_W, };
2352 int option;
2353 AioFile *af = Jim_CmdPrivData(interp);
2354
@@ -2297,10 +2434,11 @@
2434 }
2435 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2436 return JIM_OK;
2437 }
2438 #endif
2439
2440
2441 #ifdef HAVE_FSYNC
2442 static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2443 {
2444 AioFile *af = Jim_CmdPrivData(interp);
@@ -2364,33 +2502,33 @@
2502
2503 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2504 int argc, Jim_Obj * const *argv)
2505 {
2506 if (argc == 0) {
2507
2508 if (*scriptHandlerObj) {
2509 Jim_SetResult(interp, *scriptHandlerObj);
2510 }
2511 return JIM_OK;
2512 }
2513
2514 if (*scriptHandlerObj) {
2515
2516 Jim_DeleteFileHandler(interp, af->fd, mask);
2517 }
2518
2519
2520 if (Jim_Length(argv[0]) == 0) {
2521
2522 return JIM_OK;
2523 }
2524
2525
2526 Jim_IncrRefCount(argv[0]);
2527 *scriptHandlerObj = argv[0];
2528
2529 Jim_CreateFileHandler(interp, af->fd, mask,
2530 JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
2531
2532 return JIM_OK;
2533 }
2534
@@ -2414,136 +2552,145 @@
2552
2553 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2554 }
2555 #endif
2556
2557
2558
2559
2560 static const jim_subcmd_type aio_command_table[] = {
2561 { "read",
2562 "?-nonewline? ?len?",
2563 aio_cmd_read,
2564 0,
2565 2,
2566
2567 },
2568 { "copyto",
2569 "handle ?size?",
2570 aio_cmd_copy,
2571 1,
2572 2,
2573
2574 },
2575 { "getfd",
2576 NULL,
2577 aio_cmd_getfd,
2578 0,
2579 0,
2580
2581 },
2582 { "gets",
2583 "?var?",
2584 aio_cmd_gets,
2585 0,
2586 1,
2587
2588 },
2589 { "puts",
2590 "?-nonewline? str",
2591 aio_cmd_puts,
2592 1,
2593 2,
2594
2595 },
2596 { "isatty",
2597 NULL,
2598 aio_cmd_isatty,
2599 0,
2600 0,
2601
2602 },
2603 { "flush",
2604 NULL,
2605 aio_cmd_flush,
2606 0,
2607 0,
2608
2609 },
2610 { "eof",
2611 NULL,
2612 aio_cmd_eof,
2613 0,
2614 0,
2615
2616 },
2617 { "close",
2618 "?r(ead)|w(rite)?",
2619 aio_cmd_close,
2620 0,
2621 1,
2622 JIM_MODFLAG_FULLARGV,
2623
2624 },
2625 { "seek",
2626 "offset ?start|current|end",
2627 aio_cmd_seek,
2628 1,
2629 2,
2630
2631 },
2632 { "tell",
2633 NULL,
2634 aio_cmd_tell,
2635 0,
2636 0,
2637
2638 },
2639 { "filename",
2640 NULL,
2641 aio_cmd_filename,
2642 0,
2643 0,
2644
2645 },
2646 #ifdef O_NDELAY
2647 { "ndelay",
2648 "?0|1?",
2649 aio_cmd_ndelay,
2650 0,
2651 1,
2652
2653 },
2654 #endif
2655 #ifdef HAVE_FSYNC
2656 { "sync",
2657 NULL,
2658 aio_cmd_sync,
2659 0,
2660 0,
2661
2662 },
2663 #endif
2664 { "buffering",
2665 "none|line|full",
2666 aio_cmd_buffering,
2667 1,
2668 1,
2669
2670 },
2671 #ifdef jim_ext_eventloop
2672 { "readable",
2673 "?readable-script?",
2674 aio_cmd_readable,
2675 0,
2676 1,
2677
2678 },
2679 { "writable",
2680 "?writable-script?",
2681 aio_cmd_writable,
2682 0,
2683 1,
2684
2685 },
2686 { "onexception",
2687 "?exception-script?",
2688 aio_cmd_onexception,
2689 0,
2690 1,
2691
2692 },
2693 #endif
2694 { NULL }
2695 };
2696
@@ -2566,11 +2713,11 @@
2713
2714 #ifdef jim_ext_tclcompat
2715 {
2716 const char *filename = Jim_String(argv[1]);
2717
2718
2719 if (*filename == '|') {
2720 Jim_Obj *evalObj[3];
2721
2722 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2723 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2603,35 +2750,37 @@
2750 }
2751
2752 Jim_IncrRefCount(filename);
2753
2754 if (fh == NULL) {
 
2755 if (fd >= 0) {
2756 #ifndef JIM_ANSIC
2757 fh = fdopen(fd, mode);
2758 #endif
2759 }
2760 else
 
2761 fh = fopen(Jim_String(filename), mode);
2762
2763 if (fh == NULL) {
2764 JimAioSetError(interp, filename);
2765 #ifndef JIM_ANSIC
2766 if (fd >= 0) {
2767 close(fd);
2768 }
2769 #endif
2770 Jim_DecrRefCount(interp, filename);
2771 return NULL;
2772 }
2773 }
2774
2775
2776 af = Jim_Alloc(sizeof(*af));
2777 memset(af, 0, sizeof(*af));
2778 af->fp = fh;
2779 #ifndef JIM_ANSIC
2780 af->fd = fileno(fh);
2781 #endif
2782 af->filename = filename;
2783 #ifdef FD_CLOEXEC
2784 if ((openFlags & AIO_KEEPOPEN) == 0) {
2785 (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2786 }
@@ -2653,72 +2802,45 @@
2802 const char *hdlfmt, int family, const char *mode[2])
2803 {
2804 if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
2805 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2806 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
 
2807 if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) {
2808 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2809 Jim_SetResult(interp, objPtr);
2810 return JIM_OK;
2811 }
2812 }
2813
2814
2815 close(p[0]);
2816 close(p[1]);
2817 JimAioSetError(interp, NULL);
2818 return JIM_ERR;
2819 }
2820 #endif
2821
2822 #ifdef HAVE_PIPE
2823 static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2824 {
2825 int p[2];
2826 static const char *mode[2] = { "r", "w" };
2827
2828 if (argc != 1) {
2829 Jim_WrongNumArgs(interp, 1, argv, "");
2830 return JIM_ERR;
2831 }
2832
2833 if (pipe(p) != 0) {
2834 JimAioSetError(interp, NULL);
2835 return JIM_ERR;
2836 }
2837
2838 return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode);
2839 }
2840 #endif
2841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2842
2843
2844 int Jim_aioInit(Jim_Interp *interp)
2845 {
2846 if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
@@ -2727,15 +2849,18 @@
2849 #if defined(JIM_SSL)
2850 Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL);
2851 #endif
2852
2853 Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
2854 #ifdef HAVE_SOCKETS
2855 Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
2856 #endif
2857 #ifdef HAVE_PIPE
2858 Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL);
2859 #endif
2860
2861
2862 JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
2863 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2864 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2865
2866 return JIM_OK;
@@ -2813,12 +2938,12 @@
2938 #include <regex.h>
2939 #endif
2940
2941 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2942 {
2943 regfree(objPtr->internalRep.ptrIntValue.ptr);
2944 Jim_Free(objPtr->internalRep.ptrIntValue.ptr);
2945 }
2946
2947 static const Jim_ObjType regexpObjType = {
2948 "regexp",
2949 FreeRegexpInternalRep,
@@ -2831,20 +2956,20 @@
2956 {
2957 regex_t *compre;
2958 const char *pattern;
2959 int ret;
2960
2961
2962 if (objPtr->typePtr == &regexpObjType &&
2963 objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) {
2964
2965 return objPtr->internalRep.ptrIntValue.ptr;
2966 }
2967
 
2968
2969
2970
2971 pattern = Jim_String(objPtr);
2972 compre = Jim_Alloc(sizeof(regex_t));
2973
2974 if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
2975 char buf[100];
@@ -2857,12 +2982,12 @@
2982 }
2983
2984 Jim_FreeIntRep(interp, objPtr);
2985
2986 objPtr->typePtr = &regexpObjType;
2987 objPtr->internalRep.ptrIntValue.int1 = flags;
2988 objPtr->internalRep.ptrIntValue.ptr = compre;
2989
2990 return compre;
2991 }
2992
2993 int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3001,11 +3126,11 @@
3126 }
3127
3128 num_matches++;
3129
3130 if (opt_all && !opt_inline) {
3131
3132 goto try_next_match;
3133 }
3134
3135
3136 j = 0;
@@ -3041,11 +3166,11 @@
3166
3167 if (opt_inline) {
3168 Jim_ListAppendElement(interp, resultListObj, resultObj);
3169 }
3170 else {
3171
3172 result = Jim_SetVariable(interp, argv[i], resultObj);
3173
3174 if (result != JIM_OK) {
3175 Jim_FreeObj(interp, resultObj);
3176 break;
@@ -3168,11 +3293,11 @@
3293
3294 source_str = Jim_GetString(argv[i + 1], &source_len);
3295 replace_str = Jim_GetString(argv[i + 2], &replace_len);
3296 varname = argv[i + 3];
3297
3298
3299 resultObj = Jim_NewStringObj(interp, "", 0);
3300
3301 if (offset) {
3302 if (offset < 0) {
3303 offset += source_len + 1;
@@ -3183,11 +3308,11 @@
3308 else if (offset < 0) {
3309 offset = 0;
3310 }
3311 }
3312
3313
3314 Jim_AppendString(interp, resultObj, source_str, offset);
3315
3316
3317 n = source_len - offset;
3318 p = source_str + offset;
@@ -3242,23 +3367,23 @@
3367 }
3368
3369 p += pmatch[0].rm_eo;
3370 n -= pmatch[0].rm_eo;
3371
3372
3373 if (!opt_all || n == 0) {
3374 break;
3375 }
3376
3377
3378 if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
3379 break;
3380 }
3381
3382
3383 if (pattern[0] == '\0' && n) {
3384
3385 Jim_AppendString(interp, resultObj, p, 1);
3386 p++;
3387 n--;
3388 }
3389
@@ -3265,11 +3390,11 @@
3390 regexec_flags |= REG_NOTBOL;
3391 } while (n);
3392
3393 Jim_AppendString(interp, resultObj, p, -1);
3394
3395
3396 if (argc - i == 4) {
3397 result = Jim_SetVariable(interp, varname, resultObj);
3398
3399 if (result == JIM_OK) {
3400 Jim_SetResultInt(interp, num_matches);
@@ -3320,11 +3445,11 @@
3445
3446 # ifndef MAXPATHLEN
3447 # define MAXPATHLEN JIM_PATH_LEN
3448 # endif
3449
3450 #if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
3451 #define ISWINDOWS 1
3452 #else
3453 #define ISWINDOWS 0
3454 #endif
3455
@@ -3371,11 +3496,11 @@
3496 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
3497 }
3498
3499 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3500 {
3501
3502 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3503
3504 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3505 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3506 AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3512,38 @@
3512 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3513 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3514 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3515 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3516
3517
3518 if (varName) {
3519 Jim_Obj *objPtr;
3520 objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3521
3522 if (objPtr) {
3523 Jim_Obj *objv[2];
3524
3525 objv[0] = objPtr;
3526 objv[1] = listObj;
3527
3528 objPtr = Jim_DictMerge(interp, 2, objv);
3529 if (objPtr == NULL) {
3530
3531 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3532 Jim_FreeNewObj(interp, listObj);
3533 return JIM_ERR;
3534 }
3535
 
 
 
 
 
 
3536 Jim_InvalidateStringRep(objPtr);
3537
3538 Jim_FreeNewObj(interp, listObj);
3539 listObj = objPtr;
3540 }
3541 Jim_SetVariable(interp, varName, listObj);
3542 }
3543
3544
3545 Jim_SetResult(interp, listObj);
3546
3547 return JIM_OK;
3548 }
3549
@@ -3432,11 +3559,11 @@
3559 }
3560 else if (p == path) {
3561 Jim_SetResultString(interp, "/", -1);
3562 }
3563 else if (ISWINDOWS && p[-1] == ':') {
3564
3565 Jim_SetResultString(interp, path, p - path + 1);
3566 }
3567 else {
3568 Jim_SetResultString(interp, path, p - path);
3569 }
@@ -3512,35 +3639,35 @@
3639 char *newname = Jim_Alloc(MAXPATHLEN + 1);
3640 char *last = newname;
3641
3642 *newname = 0;
3643
3644
3645 for (i = 0; i < argc; i++) {
3646 int len;
3647 const char *part = Jim_GetString(argv[i], &len);
3648
3649 if (*part == '/') {
3650
3651 last = newname;
3652 }
3653 else if (ISWINDOWS && strchr(part, ':')) {
3654
3655 last = newname;
3656 }
3657 else if (part[0] == '.') {
3658 if (part[1] == '/') {
3659 part += 2;
3660 len -= 2;
3661 }
3662 else if (part[1] == 0 && last != newname) {
3663
3664 continue;
3665 }
3666 }
3667
3668
3669 if (last != newname && last[-1] != '/') {
3670 *last++ = '/';
3671 }
3672
3673 if (len) {
@@ -3551,22 +3678,22 @@
3678 }
3679 memcpy(last, part, len);
3680 last += len;
3681 }
3682
3683
3684 if (last > newname + 1 && last[-1] == '/') {
3685
3686 if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
3687 *--last = 0;
3688 }
3689 }
3690 }
3691
3692 *last = 0;
3693
3694
3695
3696 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
3697
3698 return JIM_OK;
3699 }
@@ -3591,11 +3718,11 @@
3718 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3719 {
3720 #ifdef X_OK
3721 return file_access(interp, argv[0], X_OK);
3722 #else
3723
3724 Jim_SetResultBool(interp, 1);
3725 return JIM_OK;
3726 #endif
3727 }
3728
@@ -3616,11 +3743,11 @@
3743 while (argc--) {
3744 const char *path = Jim_String(argv[0]);
3745
3746 if (unlink(path) == -1 && errno != ENOENT) {
3747 if (rmdir(path) == -1) {
3748
3749 if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
3750 Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
3751 strerror(errno));
3752 return JIM_ERR;
3753 }
@@ -3639,15 +3766,15 @@
3766
3767 static int mkdir_all(char *path)
3768 {
3769 int ok = 1;
3770
3771
3772 goto first;
3773
3774 while (ok--) {
3775
3776 {
3777 char *slash = strrchr(path, '/');
3778
3779 if (slash && slash != path) {
3780 *slash = 0;
@@ -3660,24 +3787,24 @@
3787 first:
3788 if (MKDIR_DEFAULT(path) == 0) {
3789 return 0;
3790 }
3791 if (errno == ENOENT) {
3792
3793 continue;
3794 }
3795
3796 if (errno == EEXIST) {
3797 struct stat sb;
3798
3799 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
3800 return 0;
3801 }
3802
3803 errno = EEXIST;
3804 }
3805
3806 break;
3807 }
3808 return -1;
3809 }
3810
@@ -3698,11 +3825,11 @@
3825 return JIM_OK;
3826 }
3827
3828 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3829 {
3830 int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0);
3831
3832 if (fd < 0) {
3833 return JIM_ERR;
3834 }
3835 close(fd);
@@ -3962,192 +4089,192 @@
4089 { "atime",
4090 "name",
4091 file_cmd_atime,
4092 1,
4093 1,
4094
4095 },
4096 { "mtime",
4097 "name ?time?",
4098 file_cmd_mtime,
4099 1,
4100 2,
4101
4102 },
4103 { "copy",
4104 "?-force? source dest",
4105 file_cmd_copy,
4106 2,
4107 3,
4108
4109 },
4110 { "dirname",
4111 "name",
4112 file_cmd_dirname,
4113 1,
4114 1,
4115
4116 },
4117 { "rootname",
4118 "name",
4119 file_cmd_rootname,
4120 1,
4121 1,
4122
4123 },
4124 { "extension",
4125 "name",
4126 file_cmd_extension,
4127 1,
4128 1,
4129
4130 },
4131 { "tail",
4132 "name",
4133 file_cmd_tail,
4134 1,
4135 1,
4136
4137 },
4138 { "normalize",
4139 "name",
4140 file_cmd_normalize,
4141 1,
4142 1,
4143
4144 },
4145 { "join",
4146 "name ?name ...?",
4147 file_cmd_join,
4148 1,
4149 -1,
4150
4151 },
4152 { "readable",
4153 "name",
4154 file_cmd_readable,
4155 1,
4156 1,
4157
4158 },
4159 { "writable",
4160 "name",
4161 file_cmd_writable,
4162 1,
4163 1,
4164
4165 },
4166 { "executable",
4167 "name",
4168 file_cmd_executable,
4169 1,
4170 1,
4171
4172 },
4173 { "exists",
4174 "name",
4175 file_cmd_exists,
4176 1,
4177 1,
4178
4179 },
4180 { "delete",
4181 "?-force|--? name ...",
4182 file_cmd_delete,
4183 1,
4184 -1,
4185
4186 },
4187 { "mkdir",
4188 "dir ...",
4189 file_cmd_mkdir,
4190 1,
4191 -1,
4192
4193 },
4194 { "tempfile",
4195 "?template?",
4196 file_cmd_tempfile,
4197 0,
4198 1,
4199
4200 },
4201 { "rename",
4202 "?-force? source dest",
4203 file_cmd_rename,
4204 2,
4205 3,
4206
4207 },
4208 #if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
4209 { "link",
4210 "?-symbolic|-hard? newname target",
4211 file_cmd_link,
4212 2,
4213 3,
4214
4215 },
4216 #endif
4217 #if defined(HAVE_READLINK)
4218 { "readlink",
4219 "name",
4220 file_cmd_readlink,
4221 1,
4222 1,
4223
4224 },
4225 #endif
4226 { "size",
4227 "name",
4228 file_cmd_size,
4229 1,
4230 1,
4231
4232 },
4233 { "stat",
4234 "name ?var?",
4235 file_cmd_stat,
4236 1,
4237 2,
4238
4239 },
4240 { "lstat",
4241 "name ?var?",
4242 file_cmd_lstat,
4243 1,
4244 2,
4245
4246 },
4247 { "type",
4248 "name",
4249 file_cmd_type,
4250 1,
4251 1,
4252
4253 },
4254 #ifdef HAVE_GETEUID
4255 { "owned",
4256 "name",
4257 file_cmd_owned,
4258 1,
4259 1,
4260
4261 },
4262 #endif
4263 { "isdirectory",
4264 "name",
4265 file_cmd_isdirectory,
4266 1,
4267 1,
4268
4269 },
4270 { "isfile",
4271 "name",
4272 file_cmd_isfile,
4273 1,
4274 1,
4275
4276 },
4277 {
4278 NULL
4279 }
4280 };
@@ -4179,11 +4306,11 @@
4306 Jim_SetResultString(interp, "Failed to get pwd", -1);
4307 Jim_Free(cwd);
4308 return JIM_ERR;
4309 }
4310 else if (ISWINDOWS) {
4311
4312 char *p = cwd;
4313 while ((p = strchr(p, '\\')) != NULL) {
4314 *p++ = '/';
4315 }
4316 }
@@ -4203,10 +4330,13 @@
4330 Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
4331 Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
4332 return JIM_OK;
4333 }
4334
4335 #ifndef _GNU_SOURCE
4336 #define _GNU_SOURCE
4337 #endif
4338 #include <string.h>
4339 #include <ctype.h>
4340
4341
4342 #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4344,20 @@
4344 {
4345 Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
4346 int i, j;
4347 int rc;
4348
4349
4350 for (i = 1; i < argc; i++) {
4351 int len;
4352 const char *arg = Jim_GetString(argv[i], &len);
4353
4354 if (i > 1) {
4355 Jim_AppendString(interp, cmdlineObj, " ", 1);
4356 }
4357 if (strpbrk(arg, "\\\" ") == NULL) {
4358
4359 Jim_AppendString(interp, cmdlineObj, arg, len);
4360 continue;
4361 }
4362
4363 Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4266,86 +4396,26 @@
4396 #else
4397
4398
4399 #include <errno.h>
4400 #include <signal.h>
4401 #include <sys/stat.h>
4402
4403 struct WaitInfoTable;
4404
4405 static char **JimOriginalEnviron(void);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4406 static char **JimSaveEnv(char **env);
4407 static void JimRestoreEnv(char **env);
4408 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4409 pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
4410 static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr);
4411 static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj);
4412 static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
4413
4414 #if defined(__MINGW32__)
4415 static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId);
4416 #endif
 
 
 
 
 
 
 
 
4417
4418 static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
4419 {
4420 int len;
4421 const char *s = Jim_GetString(objPtr, &len);
@@ -4354,14 +4424,14 @@
4424 objPtr->length--;
4425 objPtr->bytes[objPtr->length] = '\0';
4426 }
4427 }
4428
4429 static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj)
4430 {
4431 char buf[256];
4432 FILE *fh = fdopen(fd, "r");
4433 int ret = 0;
4434
4435 if (fh == NULL) {
4436 return -1;
4437 }
@@ -4390,18 +4460,18 @@
4460 char *envdata;
4461
4462 Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
4463
4464 if (!objPtr) {
4465 return JimOriginalEnviron();
4466 }
4467
4468
4469
4470 num = Jim_ListLength(interp, objPtr);
4471 if (num % 2) {
4472
4473 num--;
4474 }
4475 size = Jim_Length(objPtr) + 2;
4476
4477 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4433,79 +4503,76 @@
4503 if (env != original_environ) {
4504 Jim_Free(env);
4505 }
4506 }
4507
4508 static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4509 {
4510 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
4511
4512 if (pid == JIM_BAD_PID || pid == JIM_NO_PID) {
4513 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1));
4514 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4515 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1));
4516 }
4517 else if (WIFEXITED(waitStatus)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4518 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
4519 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4520 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
4521 }
4522 else {
4523 const char *type;
4524 const char *action;
4525 const char *signame;
4526
4527 if (WIFSIGNALED(waitStatus)) {
4528 type = "CHILDKILLED";
4529 action = "killed";
4530 signame = Jim_SignalId(WTERMSIG(waitStatus));
4531 }
4532 else {
4533 type = "CHILDSUSP";
4534 action = "suspended";
4535 signame = "none";
4536 }
4537
4538 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
4539
4540 if (errStrObj) {
4541 Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL);
4542 }
4543
4544 Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
4545 Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1));
 
4546 }
4547 return errorCode;
4548 }
4549
4550 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
4551 {
4552 if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
4553 return JIM_OK;
4554 }
4555 Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj));
4556
4557 return JIM_ERR;
4558 }
4559
4560
4561 struct WaitInfo
4562 {
4563 pidtype pid;
4564 int status;
4565 int flags;
4566 };
4567
4568
4569 struct WaitInfoTable {
4570 struct WaitInfo *info;
4571 int size;
4572 int used;
4573 int refcount;
4574 };
4575
4576
4577 #define WI_DETACHED 2
4578
@@ -4513,32 +4580,53 @@
4580
4581 static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData)
4582 {
4583 struct WaitInfoTable *table = privData;
4584
4585 if (--table->refcount == 0) {
4586 Jim_Free(table->info);
4587 Jim_Free(table);
4588 }
4589 }
4590
4591 static struct WaitInfoTable *JimAllocWaitInfoTable(void)
4592 {
4593 struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
4594 table->info = NULL;
4595 table->size = table->used = 0;
4596 table->refcount = 1;
4597
4598 return table;
4599 }
4600
4601 static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid)
4602 {
4603 int i;
4604
4605
4606 for (i = 0; i < table->used; i++) {
4607 if (pid == table->info[i].pid) {
4608 if (i != table->used - 1) {
4609 table->info[i] = table->info[table->used - 1];
4610 }
4611 table->used--;
4612 return 0;
4613 }
4614 }
4615 return -1;
4616 }
4617
4618 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4619 {
4620 int outputId;
4621 int errorId;
4622 pidtype *pidPtr;
4623 int numPids, result;
4624 int child_siginfo = 1;
4625 Jim_Obj *childErrObj;
4626 Jim_Obj *errStrObj;
4627 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4628
4629 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4630 Jim_Obj *listObj;
4631 int i;
4632
@@ -4545,17 +4633,17 @@
4633 argc--;
4634 numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
4635 if (numPids < 0) {
4636 return JIM_ERR;
4637 }
4638
4639 listObj = Jim_NewListObj(interp, NULL, 0);
4640 for (i = 0; i < numPids; i++) {
4641 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
4642 }
4643 Jim_SetResult(interp, listObj);
4644 JimDetachPids(table, numPids, pidPtr);
4645 Jim_Free(pidPtr);
4646 return JIM_OK;
4647 }
4648
4649 numPids =
@@ -4567,54 +4655,98 @@
4655
4656 result = JIM_OK;
4657
4658 errStrObj = Jim_NewStringObj(interp, "", 0);
4659
4660
4661 if (outputId != -1) {
4662 if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
4663 result = JIM_ERR;
4664 Jim_SetResultErrno(interp, "error reading from output pipe");
4665 }
4666 }
4667
4668
4669 childErrObj = Jim_NewStringObj(interp, "", 0);
4670 Jim_IncrRefCount(childErrObj);
4671
4672 if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
4673 result = JIM_ERR;
4674 }
4675
4676 if (errorId != -1) {
4677 int ret;
4678 lseek(errorId, 0, SEEK_SET);
4679 ret = JimAppendStreamToString(interp, errorId, errStrObj);
4680 if (ret < 0) {
4681 Jim_SetResultErrno(interp, "error reading from error pipe");
4682 result = JIM_ERR;
4683 }
4684 else if (ret > 0) {
4685
4686 child_siginfo = 0;
4687 }
4688 }
4689
4690 if (child_siginfo) {
4691
4692 Jim_AppendObj(interp, errStrObj, childErrObj);
4693 }
4694 Jim_DecrRefCount(interp, childErrObj);
4695
4696
4697 Jim_RemoveTrailingNewline(errStrObj);
4698
4699
4700 Jim_SetResult(interp, errStrObj);
4701
4702 return result;
4703 }
4704
4705 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4706 {
4707 if (JimWaitRemove(table, pid) == 0) {
4708
4709 waitpid(pid, statusPtr, 0);
4710 return pid;
4711 }
4712
4713
4714 return JIM_BAD_PID;
4715 }
4716
4717 static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr)
4718 {
4719 int j;
4720
4721 for (j = 0; j < numPids; j++) {
4722
4723 int i;
4724 for (i = 0; i < table->used; i++) {
4725 if (pidPtr[j] == table->info[i].pid) {
4726 table->info[i].flags |= WI_DETACHED;
4727 break;
4728 }
4729 }
4730 }
4731 }
4732
4733 static int JimGetChannelFd(Jim_Interp *interp, const char *name)
4734 {
4735 Jim_Obj *objv[2];
4736
4737 objv[0] = Jim_NewStringObj(interp, name, -1);
4738 objv[1] = Jim_NewStringObj(interp, "getfd", -1);
4739
4740 if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) {
4741 jim_wide fd;
4742 if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) {
4743 return fd;
4744 }
4745 }
4746 return -1;
4747 }
4748
4749 static void JimReapDetachedPids(struct WaitInfoTable *table)
4750 {
4751 struct WaitInfo *waitPtr;
4752 int count;
@@ -4627,13 +4759,13 @@
4759 waitPtr = table->info;
4760 dest = 0;
4761 for (count = table->used; count > 0; waitPtr++, count--) {
4762 if (waitPtr->flags & WI_DETACHED) {
4763 int status;
4764 pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG);
4765 if (pid == waitPtr->pid) {
4766
4767 table->used--;
4768 continue;
4769 }
4770 }
4771 if (waitPtr != &table->info[dest]) {
@@ -4641,66 +4773,62 @@
4773 }
4774 dest++;
4775 }
4776 }
4777
4778 static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4779 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4780 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4781 int nohang = 0;
4782 pidtype pid;
4783 long pidarg;
4784 int status;
4785 Jim_Obj *errCodeObj;
4786
4787
4788 if (argc == 1) {
4789 JimReapDetachedPids(table);
4790 return JIM_OK;
4791 }
4792
4793 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) {
4794 nohang = 1;
4795 }
4796 if (argc != nohang + 2) {
4797 Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?");
4798 return JIM_ERR;
4799 }
4800 if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) {
4801 return JIM_ERR;
4802 }
4803
4804 pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0);
4805
4806 errCodeObj = JimMakeErrorCode(interp, pid, status, NULL);
4807
4808 if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) {
4809
4810 JimWaitRemove(table, pid);
4811 }
4812 Jim_SetResult(interp, errCodeObj);
4813 return JIM_OK;
4814 }
4815
4816 static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4817 {
4818 if (argc != 1) {
4819 Jim_WrongNumArgs(interp, 1, argv, "");
4820 return JIM_ERR;
4821 }
4822
4823 Jim_SetResultInt(interp, (jim_wide)getpid());
4824 return JIM_OK;
4825 }
4826
4827 static int
4828 JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
4829 int *inPipePtr, int *outPipePtr, int *errFilePtr)
4830 {
4831 pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all
4832 * the pids of child processes. */
4833 int numPids = 0; /* Actual number of processes that exist
4834 * at *pidPtr right now. */
@@ -4707,16 +4835,16 @@
4835 int cmdCount; /* Count of number of distinct commands
4836 * found in argc/argv. */
4837 const char *input = NULL; /* Describes input for pipeline, depending
4838 * on "inputFile". NULL means take input
4839 * from stdin/pipe. */
4840 int input_len = 0;
4841
4842 #define FILE_NAME 0
4843 #define FILE_APPEND 1
4844 #define FILE_HANDLE 2
4845 #define FILE_TEXT 3
4846
4847 int inputFile = FILE_NAME; /* 1 means input is name of input file.
4848 * 2 means input is filehandle name.
4849 * 0 means input holds actual
4850 * text to be input to command. */
@@ -4733,39 +4861,37 @@
4861 */
4862 const char *output = NULL; /* Holds name of output file to pipe to,
4863 * or NULL if output goes to stdout/pipe. */
4864 const char *error = NULL; /* Holds name of stderr file to pipe to,
4865 * or NULL if stderr goes to stderr/pipe. */
4866 int inputId = -1;
4867 int outputId = -1;
4868 int errorId = -1;
4869 int lastOutputId = -1;
4870 int pipeIds[2];
4871 int firstArg, lastArg; /* Indexes of first and last arguments in
4872 * current command. */
4873 int lastBar;
4874 int i;
4875 pidtype pid;
4876 char **save_environ;
4877 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4878
4879
4880 char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
4881 int arg_count = 0;
4882
 
 
4883 if (inPipePtr != NULL) {
4884 *inPipePtr = -1;
4885 }
4886 if (outPipePtr != NULL) {
4887 *outPipePtr = -1;
4888 }
4889 if (errFilePtr != NULL) {
4890 *errFilePtr = -1;
4891 }
4892 pipeIds[0] = pipeIds[1] = -1;
4893
4894 cmdCount = 1;
4895 lastBar = -1;
4896 for (i = 0; i < argc; i++) {
4897 const char *arg = Jim_String(argv[i]);
@@ -4796,11 +4922,11 @@
4922 if (*output == '>') {
4923 outputFile = FILE_APPEND;
4924 output++;
4925 }
4926 if (*output == '&') {
4927
4928 output++;
4929 dup_error = 1;
4930 }
4931 if (*output == '@') {
4932 outputFile = FILE_HANDLE;
@@ -4837,11 +4963,11 @@
4963 goto badargs;
4964 }
4965 lastBar = i;
4966 cmdCount++;
4967 }
4968
4969 arg_array[arg_count++] = (char *)arg;
4970 continue;
4971 }
4972
4973 if (i >= argc) {
@@ -4855,150 +4981,160 @@
4981 badargs:
4982 Jim_Free(arg_array);
4983 return -1;
4984 }
4985
4986
4987 save_environ = JimSaveEnv(JimBuildEnv(interp));
4988
4989 if (input != NULL) {
4990 if (inputFile == FILE_TEXT) {
4991 inputId = Jim_MakeTempFile(interp, NULL, 1);
4992 if (inputId == -1) {
4993 goto error;
4994 }
4995 if (write(inputId, input, input_len) != input_len) {
4996 Jim_SetResultErrno(interp, "couldn't write temp file");
4997 close(inputId);
4998 goto error;
4999 }
5000 lseek(inputId, 0L, SEEK_SET);
5001 }
5002 else if (inputFile == FILE_HANDLE) {
5003 int fd = JimGetChannelFd(interp, input);
 
5004
5005 if (fd < 0) {
5006 goto error;
5007 }
5008 inputId = dup(fd);
5009 }
5010 else {
5011 inputId = Jim_OpenForRead(input);
5012 if (inputId == -1) {
5013 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno()));
5014 goto error;
5015 }
5016 }
5017 }
5018 else if (inPipePtr != NULL) {
5019 if (pipe(pipeIds) != 0) {
5020 Jim_SetResultErrno(interp, "couldn't create input pipe for command");
5021 goto error;
5022 }
5023 inputId = pipeIds[0];
5024 *inPipePtr = pipeIds[1];
5025 pipeIds[0] = pipeIds[1] = -1;
5026 }
5027
5028 if (output != NULL) {
5029 if (outputFile == FILE_HANDLE) {
5030 int fd = JimGetChannelFd(interp, output);
5031 if (fd < 0) {
5032 goto error;
5033 }
5034 lastOutputId = dup(fd);
 
5035 }
5036 else {
5037 lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND);
5038 if (lastOutputId == -1) {
5039 Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno()));
5040 goto error;
5041 }
5042 }
5043 }
5044 else if (outPipePtr != NULL) {
5045 if (pipe(pipeIds) != 0) {
5046 Jim_SetResultErrno(interp, "couldn't create output pipe");
5047 goto error;
5048 }
5049 lastOutputId = pipeIds[1];
5050 *outPipePtr = pipeIds[0];
5051 pipeIds[0] = pipeIds[1] = -1;
5052 }
5053
5054 if (error != NULL) {
5055 if (errorFile == FILE_HANDLE) {
5056 if (strcmp(error, "1") == 0) {
5057
5058 if (lastOutputId != -1) {
5059 errorId = dup(lastOutputId);
5060 }
5061 else {
5062
5063 error = "stdout";
5064 }
5065 }
5066 if (errorId == -1) {
5067 int fd = JimGetChannelFd(interp, error);
5068 if (fd < 0) {
5069 goto error;
5070 }
5071 errorId = dup(fd);
 
5072 }
5073 }
5074 else {
5075 errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND);
5076 if (errorId == -1) {
5077 Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno()));
5078 goto error;
5079 }
5080 }
5081 }
5082 else if (errFilePtr != NULL) {
5083 errorId = Jim_MakeTempFile(interp, NULL, 1);
5084 if (errorId == -1) {
5085 goto error;
5086 }
5087 *errFilePtr = dup(errorId);
5088 }
5089
5090
5091 pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
5092 for (i = 0; i < numPids; i++) {
5093 pidPtr[i] = JIM_BAD_PID;
5094 }
5095 for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
5096 int pipe_dup_err = 0;
5097 int origErrorId = errorId;
5098
5099 for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
5100 if (strcmp(arg_array[lastArg], "|") == 0) {
5101 break;
5102 }
5103 if (strcmp(arg_array[lastArg], "|&") == 0) {
5104 pipe_dup_err = 1;
5105 break;
5106 }
5107 }
5108
5109 if (lastArg == firstArg) {
5110 Jim_SetResultString(interp, "missing command to exec", -1);
5111 goto error;
5112 }
5113
5114
5115 arg_array[lastArg] = NULL;
5116 if (lastArg == arg_count) {
5117 outputId = lastOutputId;
5118 }
5119 else {
5120 if (pipe(pipeIds) != 0) {
5121 Jim_SetResultErrno(interp, "couldn't create pipe");
5122 goto error;
5123 }
5124 outputId = pipeIds[1];
5125 }
5126
5127
5128 if (pipe_dup_err) {
5129 errorId = outputId;
5130 }
5131
5132
5133
5134 #ifdef __MINGW32__
5135 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
5136 if (pid == JIM_BAD_PID) {
5137 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
5138 goto error;
5139 }
5140 #else
@@ -5006,32 +5142,37 @@
5142 if (pid < 0) {
5143 Jim_SetResultErrno(interp, "couldn't fork child process");
5144 goto error;
5145 }
5146 if (pid == 0) {
 
5147
5148 if (inputId != -1) dup2(inputId, fileno(stdin));
5149 if (outputId != -1) dup2(outputId, fileno(stdout));
5150 if (errorId != -1) dup2(errorId, fileno(stderr));
5151
5152 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
5153 close(i);
5154 }
5155
5156
5157 (void)signal(SIGPIPE, SIG_DFL);
5158
5159 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
5160
 
5161 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
5162 #ifdef JIM_MAINTAINER
5163 {
5164
5165 static char *const false_argv[2] = {"false", NULL};
5166 execvp(false_argv[0],false_argv);
5167 }
5168 #endif
5169 _exit(127);
5170 }
5171 #endif
5172
5173
5174
5175 if (table->used == table->size) {
5176 table->size += WAIT_TABLE_GROW_BY;
5177 table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
5178 }
@@ -5040,66 +5181,67 @@
5181 table->info[table->used].flags = 0;
5182 table->used++;
5183
5184 pidPtr[numPids] = pid;
5185
5186
5187 errorId = origErrorId;
5188
5189
5190 if (inputId != -1) {
5191 close(inputId);
5192 }
5193 if (outputId != -1) {
5194 close(outputId);
5195 outputId = -1;
5196 }
5197 inputId = pipeIds[0];
5198 pipeIds[0] = pipeIds[1] = -1;
5199 }
5200 *pidArrayPtr = pidPtr;
5201
5202
5203 cleanup:
5204 if (inputId != -1) {
5205 close(inputId);
5206 }
5207 if (lastOutputId != -1) {
5208 close(lastOutputId);
5209 }
5210 if (errorId != -1) {
5211 close(errorId);
5212 }
5213 Jim_Free(arg_array);
5214
5215 JimRestoreEnv(save_environ);
5216
5217 return numPids;
5218
5219
5220 error:
5221 if ((inPipePtr != NULL) && (*inPipePtr != -1)) {
5222 close(*inPipePtr);
5223 *inPipePtr = -1;
5224 }
5225 if ((outPipePtr != NULL) && (*outPipePtr != -1)) {
5226 close(*outPipePtr);
5227 *outPipePtr = -1;
5228 }
5229 if ((errFilePtr != NULL) && (*errFilePtr != -1)) {
5230 close(*errFilePtr);
5231 *errFilePtr = -1;
5232 }
5233 if (pipeIds[0] != -1) {
5234 close(pipeIds[0]);
5235 }
5236 if (pipeIds[1] != -1) {
5237 close(pipeIds[1]);
5238 }
5239 if (pidPtr != NULL) {
5240 for (i = 0; i < numPids; i++) {
5241 if (pidPtr[i] != JIM_BAD_PID) {
5242 JimDetachPids(table, 1, &pidPtr[i]);
5243 }
5244 }
5245 Jim_Free(pidPtr);
5246 }
5247 numPids = -1;
@@ -5111,11 +5253,11 @@
5253 {
5254 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
5255 int result = JIM_OK;
5256 int i;
5257
5258
5259 for (i = 0; i < numPids; i++) {
5260 int waitStatus = 0;
5261 if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
5262 if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
5263 result = JIM_ERR;
@@ -5127,234 +5269,30 @@
5269 return result;
5270 }
5271
5272 int Jim_execInit(Jim_Interp *interp)
5273 {
5274 struct WaitInfoTable *waitinfo;
5275 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
5276 return JIM_ERR;
5277
5278 #ifdef SIGPIPE
5279 (void)signal(SIGPIPE, SIG_IGN);
5280 #endif
5281
5282 waitinfo = JimAllocWaitInfoTable();
5283 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable);
5284 waitinfo->refcount++;
5285 Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable);
5286 Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0);
5287
5288 return JIM_OK;
5289 }
5290
5291 #if defined(__MINGW32__)
5292
5293
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5294 static int
5295 JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
5296 {
5297 int i;
5298 static char extensions[][5] = {".exe", "", ".bat"};
@@ -5381,10 +5319,15 @@
5319
5320 static void JimRestoreEnv(char **env)
5321 {
5322 JimFreeEnv(env, Jim_GetEnviron());
5323 }
5324
5325 static char **JimOriginalEnviron(void)
5326 {
5327 return NULL;
5328 }
5329
5330 static Jim_Obj *
5331 JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
5332 {
5333 char *start, *special;
@@ -5455,18 +5398,19 @@
5398 }
5399 return strObj;
5400 }
5401
5402 static pidtype
5403 JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId)
5404 {
5405 STARTUPINFO startInfo;
5406 PROCESS_INFORMATION procInfo;
5407 HANDLE hProcess;
5408 char execPath[MAX_PATH];
5409 pidtype pid = JIM_BAD_PID;
5410 Jim_Obj *cmdLineObj;
5411 char *winenv;
5412
5413 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5414 return JIM_BAD_PID;
5415 }
5416 argv[0] = execPath;
@@ -5480,47 +5424,51 @@
5424 startInfo.dwFlags = STARTF_USESTDHANDLES;
5425 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5426 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5427 startInfo.hStdError = INVALID_HANDLE_VALUE;
5428
5429 if (inputId == -1) {
5430 inputId = _fileno(stdin);
5431 }
5432 DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput,
5433 0, TRUE, DUPLICATE_SAME_ACCESS);
5434 if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {
5435 goto end;
5436 }
5437
5438 if (outputId == -1) {
5439 outputId = _fileno(stdout);
5440 }
5441 DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput,
5442 0, TRUE, DUPLICATE_SAME_ACCESS);
5443 if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) {
5444 goto end;
5445 }
5446
5447
5448 if (errorId == -1) {
5449 errorId = _fileno(stderr);
5450 }
5451 DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError,
5452 0, TRUE, DUPLICATE_SAME_ACCESS);
5453 if (startInfo.hStdError == INVALID_HANDLE_VALUE) {
5454 goto end;
5455 }
5456
5457 if (env == NULL) {
5458
5459 winenv = NULL;
5460 }
5461 else if (env[0] == NULL) {
5462 winenv = (char *)"\0";
5463 }
5464 else {
5465 winenv = env[0];
5466 }
5467
5468 if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5469 0, winenv, NULL, &startInfo, &procInfo)) {
5470 goto end;
5471 }
5472
5473
5474 WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5528,49 +5476,27 @@
5476
5477 pid = procInfo.hProcess;
5478
5479 end:
5480 Jim_FreeNewObj(interp, cmdLineObj);
5481 if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
5482 CloseHandle(startInfo.hStdInput);
5483 }
5484 if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) {
5485 CloseHandle(startInfo.hStdOutput);
5486 }
5487 if (startInfo.hStdError != INVALID_HANDLE_VALUE) {
5488 CloseHandle(startInfo.hStdError);
5489 }
5490 return pid;
5491 }
5492
5493 #else
5494
5495 static char **JimOriginalEnviron(void)
5496 {
5497 return Jim_GetEnviron();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5498 }
5499
5500 static char **JimSaveEnv(char **env)
5501 {
5502 char **saveenv = Jim_GetEnviron();
@@ -5585,13 +5511,21 @@
5511 }
5512 #endif
5513 #endif
5514
5515
5516
5517 #ifdef STRPTIME_NEEDS_XOPEN_SOURCE
5518 #ifndef _XOPEN_SOURCE
5519 #define _XOPEN_SOURCE 500
5520 #endif
5521 #endif
5522
5523
5524 #ifndef _GNU_SOURCE
5525 #define _GNU_SOURCE
5526 #endif
5527
5528 #include <stdlib.h>
5529 #include <string.h>
5530 #include <stdio.h>
5531 #include <time.h>
@@ -5598,65 +5532,126 @@
5532
5533
5534 #ifdef HAVE_SYS_TIME_H
5535 #include <sys/time.h>
5536 #endif
5537
5538 struct clock_options {
5539 int gmt;
5540 const char *format;
5541 };
5542
5543 static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts)
5544 {
5545 static const char * const options[] = { "-gmt", "-format", NULL };
5546 enum { OPT_GMT, OPT_FORMAT, };
5547 int i;
5548
5549 for (i = 0; i < argc; i += 2) {
5550 int option;
5551 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
5552 return JIM_ERR;
5553 }
5554 switch (option) {
5555 case OPT_GMT:
5556 if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) {
5557 return JIM_ERR;
5558 }
5559 break;
5560 case OPT_FORMAT:
5561 opts->format = Jim_String(argv[i + 1]);
5562 break;
5563 }
5564 }
5565 return JIM_OK;
5566 }
5567
5568 static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5569 {
5570
5571 char buf[100];
5572 time_t t;
5573 jim_wide seconds;
5574 struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" };
5575 struct tm *tm;
5576
5577 if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) {
5578 return JIM_ERR;
5579 }
5580 if (argc % 2 == 0) {
5581 return -1;
5582 }
5583 if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
5584 return JIM_ERR;
 
5585 }
5586
 
 
 
5587 t = seconds;
5588 tm = options.gmt ? gmtime(&t) : localtime(&t);
5589
5590 if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) {
5591 Jim_SetResultString(interp, "format string too long or invalid time", -1);
5592 return JIM_ERR;
5593 }
5594
5595 Jim_SetResultString(interp, buf, -1);
5596
5597 return JIM_OK;
5598 }
5599
5600 #ifdef HAVE_STRPTIME
5601 #ifndef HAVE_TIMEGM
5602
5603 static time_t timegm(struct tm *tm)
5604 {
5605 time_t t;
5606 const char *tz = getenv("TZ");
5607 setenv("TZ", "", 1);
5608 tzset();
5609 t = mktime(tm);
5610 if (tz) {
5611 setenv("TZ", tz, 1);
5612 }
5613 else {
5614 unsetenv("TZ");
5615 }
5616 tzset();
5617 return t;
5618 }
5619 #endif
5620
5621 static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5622 {
5623 char *pt;
5624 struct tm tm;
 
5625
5626
5627 struct clock_options options = { 0, NULL };
5628
5629 if (argc % 2 == 0) {
5630 return -1;
5631 }
5632
5633 if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
5634 return JIM_ERR;
5635 }
5636 if (options.format == NULL) {
5637 return -1;
5638 }
5639
 
 
5640
5641 memset(&tm, 0, sizeof(tm));
5642
5643 tm.tm_mday = 1;
5644
5645 pt = strptime(Jim_String(argv[0]), options.format, &tm);
5646 if (pt == 0 || *pt != 0) {
5647 Jim_SetResultString(interp, "Failed to parse time according to format", -1);
5648 return JIM_ERR;
5649 }
5650
5651
5652 Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm));
5653
5654 return JIM_OK;
5655 }
5656 #endif
5657
@@ -5688,54 +5683,54 @@
5683
5684 return JIM_OK;
5685 }
5686
5687 static const jim_subcmd_type clock_command_table[] = {
 
 
 
 
 
 
 
5688 { "clicks",
5689 NULL,
5690 clock_cmd_micros,
5691 0,
5692 0,
5693
5694 },
5695 { "format",
5696 "seconds ?-format string? ?-gmt boolean?",
5697 clock_cmd_format,
5698 1,
5699 5,
5700
5701 },
5702 { "microseconds",
5703 NULL,
5704 clock_cmd_micros,
5705 0,
5706 0,
5707
5708 },
5709 { "milliseconds",
5710 NULL,
5711 clock_cmd_millis,
5712 0,
5713 0,
5714
 
 
 
 
 
 
 
5715 },
5716 #ifdef HAVE_STRPTIME
5717 { "scan",
5718 "str -format format ?-gmt boolean?",
5719 clock_cmd_scan,
5720 3,
5721 5,
5722
5723 },
5724 #endif
5725 { "seconds",
5726 NULL,
5727 clock_cmd_seconds,
5728 0,
5729 0,
5730
5731 },
5732 { NULL }
5733 };
5734
5735 int Jim_clockInit(Jim_Interp *interp)
5736 {
@@ -5753,12 +5748,13 @@
5748 #include <errno.h>
5749
5750
5751 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5752 {
5753
5754 Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5755 Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
5756 return JIM_OK;
5757 }
5758
5759 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5760 {
@@ -5769,21 +5765,20 @@
5765 return JIM_OK;
5766 }
5767
5768 patternObj = (argc == 1) ? NULL : argv[1];
5769
5770
5771 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5772 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5773
5774 Jim_SetResult(interp, objPtr);
5775 return JIM_OK;
5776 }
5777 }
5778
5779 return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES);
 
5780 }
5781
5782 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5783 {
5784 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5785,11 @@
5785
5786 if (!objPtr) {
5787 return JIM_OK;
5788 }
5789
5790 return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS);
5791 }
5792
5793 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5794 {
5795 int i;
@@ -5802,27 +5797,29 @@
5797 Jim_Obj *resultObj;
5798 Jim_Obj *objPtr;
5799 Jim_Obj **dictValuesObj;
5800
5801 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5802
5803 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5804 return JIM_OK;
5805 }
5806
5807 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5808
5809 if (objPtr == NULL) {
5810
5811 return JIM_OK;
5812 }
5813
5814 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5815
5816 Jim_SetResultString(interp, "", -1);
5817 return JIM_OK;
5818 }
5819
5820
5821 resultObj = Jim_NewDictObj(interp, NULL, 0);
5822
5823 for (i = 0; i < len; i += 2) {
5824 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
5825 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5834,18 @@
5834 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5835 {
5836 Jim_Obj *objPtr;
5837 int len = 0;
5838
5839
5840 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5841 if (objPtr) {
5842 len = Jim_DictSize(interp, objPtr);
5843 if (len < 0) {
5844
5845 Jim_SetResultInt(interp, 0);
5846 return JIM_OK;
5847 }
5848 }
5849
5850 Jim_SetResultInt(interp, len);
5851
@@ -5876,11 +5875,11 @@
5875 return JIM_ERR;
5876 }
5877
5878 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5879 if (!dictObj) {
5880
5881 return Jim_SetVariable(interp, argv[0], listObj);
5882 }
5883 else if (Jim_DictSize(interp, dictObj) < 0) {
5884 return JIM_ERR;
5885 }
@@ -5905,53 +5904,53 @@
5904 { "exists",
5905 "arrayName",
5906 array_cmd_exists,
5907 1,
5908 1,
5909
5910 },
5911 { "get",
5912 "arrayName ?pattern?",
5913 array_cmd_get,
5914 1,
5915 2,
5916
5917 },
5918 { "names",
5919 "arrayName ?pattern?",
5920 array_cmd_names,
5921 1,
5922 2,
5923
5924 },
5925 { "set",
5926 "arrayName list",
5927 array_cmd_set,
5928 2,
5929 2,
5930
5931 },
5932 { "size",
5933 "arrayName",
5934 array_cmd_size,
5935 1,
5936 1,
5937
5938 },
5939 { "stat",
5940 "arrayName",
5941 array_cmd_stat,
5942 1,
5943 1,
5944
5945 },
5946 { "unset",
5947 "arrayName ?pattern?",
5948 array_cmd_unset,
5949 1,
5950 2,
5951
5952 },
5953 { NULL
5954 }
5955 };
5956
@@ -5987,11 +5986,14 @@
5986 Jim_arrayInit(interp);
5987 Jim_stdlibInit(interp);
5988 Jim_tclcompatInit(interp);
5989 return JIM_OK;
5990 }
5991 #define JIM_OPTIMIZATION
5992 #ifndef _GNU_SOURCE
5993 #define _GNU_SOURCE
5994 #endif
5995
5996 #include <stdio.h>
5997 #include <stdlib.h>
5998
5999 #include <string.h>
@@ -6056,10 +6058,16 @@
6058 #define JimPanic(X) JimPanicDump X
6059 #else
6060 #define JimPanic(X)
6061 #endif
6062
6063 #ifdef JIM_OPTIMIZATION
6064 #define JIM_IF_OPTIM(X) X
6065 #else
6066 #define JIM_IF_OPTIM(X)
6067 #endif
6068
6069
6070 static char JimEmptyStringRep[] = "";
6071
6072 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
6073 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6120,34 @@
6120 if (*pattern == '^') {
6121 not++;
6122 pattern++;
6123 }
6124
6125
6126 if (*pattern == ']') {
6127 goto first;
6128 }
6129 }
6130
6131 while (*pattern && *pattern != ']') {
6132
6133 if (pattern[0] == '\\') {
6134 first:
6135 pattern += utf8_tounicode_case(pattern, &pchar, nocase);
6136 }
6137 else {
6138
6139 int start;
6140 int end;
6141
6142 pattern += utf8_tounicode_case(pattern, &start, nocase);
6143 if (pattern[0] == '-' && pattern[1]) {
6144
6145 pattern++;
6146 pattern += utf8_tounicode_case(pattern, &end, nocase);
6147
6148
6149 if ((c >= start && c <= end) || (c >= end && c <= start)) {
6150 match = 1;
6151 }
6152 continue;
6153 }
@@ -6169,19 +6177,19 @@
6177 while (pattern[1] == '*') {
6178 pattern++;
6179 }
6180 pattern++;
6181 if (!pattern[0]) {
6182 return 1;
6183 }
6184 while (*string) {
6185
6186 if (JimGlobMatch(pattern, string, nocase))
6187 return 1;
6188 string += utf8_tounicode(string, &c);
6189 }
6190 return 0;
6191
6192 case '?':
6193 string += utf8_tounicode(string, &c);
6194 break;
6195
@@ -6190,20 +6198,20 @@
6198 pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
6199 if (!pattern) {
6200 return 0;
6201 }
6202 if (!*pattern) {
6203
6204 continue;
6205 }
6206 break;
6207 }
6208 case '\\':
6209 if (pattern[1]) {
6210 pattern++;
6211 }
6212
6213 default:
6214 string += utf8_tounicode_case(string, &c, nocase);
6215 utf8_tounicode_case(pattern, &pchar, nocase);
6216 if (pchar != c) {
6217 return 0;
@@ -6249,11 +6257,11 @@
6257 maxchars--;
6258 }
6259 if (!maxchars) {
6260 return 0;
6261 }
6262
6263 if (*s1) {
6264 return 1;
6265 }
6266 if (*s2) {
6267 return -1;
@@ -6290,11 +6298,11 @@
6298 const char *p;
6299
6300 if (!l1 || !l2 || l1 > l2)
6301 return -1;
6302
6303
6304 for (p = s2 + l2 - 1; p != s2 - 1; p--) {
6305 if (*p == *s1 && memcmp(s1, p, l1) == 0) {
6306 return p - s2;
6307 }
6308 }
@@ -6349,28 +6357,28 @@
6357 }
6358 *sign = 1;
6359 }
6360
6361 if (str[i] != '0') {
6362
6363 return 0;
6364 }
6365
6366
6367 switch (str[i + 1]) {
6368 case 'x': case 'X': *base = 16; break;
6369 case 'o': case 'O': *base = 8; break;
6370 case 'b': case 'B': *base = 2; break;
6371 default: return 0;
6372 }
6373 i += 2;
6374
6375 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6376
6377 return i;
6378 }
6379
6380 *base = 10;
6381 return 0;
6382 }
6383
6384 static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6392,11 @@
6392 if (endptr == NULL || *endptr != str + i) {
6393 return value * sign;
6394 }
6395 }
6396
6397
6398 return strtol(str, endptr, 10);
6399 }
6400
6401
6402 static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6411,11 @@
6411 if (endptr == NULL || *endptr != str + i) {
6412 return value * sign;
6413 }
6414 }
6415
6416
6417 return strtoull(str, endptr, 10);
6418 #else
6419 return (unsigned long)jim_strtol(str, endptr);
6420 #endif
6421 }
@@ -6428,26 +6436,40 @@
6436
6437 int Jim_StringToDouble(const char *str, double *doublePtr)
6438 {
6439 char *endptr;
6440
6441
6442 errno = 0;
6443
6444 *doublePtr = strtod(str, &endptr);
6445
6446 return JimCheckConversion(str, endptr);
6447 }
6448
6449 static jim_wide JimPowWide(jim_wide b, jim_wide e)
6450 {
6451 jim_wide res = 1;
6452
6453
6454 if (b == 1) {
6455
6456 return 1;
6457 }
6458 if (e < 0) {
6459 if (b != -1) {
6460 return 0;
6461 }
6462 e = -e;
6463 }
6464 while (e)
6465 {
6466 if (e & 1) {
6467 res *= b;
6468 }
6469 e >>= 1;
6470 b *= b;
6471 }
6472 return res;
6473 }
6474
6475 #ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6531,11 @@
6531 char *Jim_StrDupLen(const char *s, int l)
6532 {
6533 char *copy = Jim_Alloc(l + 1);
6534
6535 memcpy(copy, s, l + 1);
6536 copy[l] = 0;
6537 return copy;
6538 }
6539
6540
6541
@@ -6598,52 +6620,52 @@
6620 }
6621
6622
6623 void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
6624 {
6625 Jim_HashTable n;
6626 unsigned int realsize = JimHashTableNextPower(size), i;
6627
6628 if (size <= ht->used)
6629 return;
6630
6631 Jim_InitHashTable(&n, ht->type, ht->privdata);
6632 n.size = realsize;
6633 n.sizemask = realsize - 1;
6634 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6635
6636 n.uniq = ht->uniq;
6637
6638
6639 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6640
6641 n.used = ht->used;
6642 for (i = 0; ht->used > 0; i++) {
6643 Jim_HashEntry *he, *nextHe;
6644
6645 if (ht->table[i] == NULL)
6646 continue;
6647
6648
6649 he = ht->table[i];
6650 while (he) {
6651 unsigned int h;
6652
6653 nextHe = he->next;
6654
6655 h = Jim_HashKey(ht, he->key) & n.sizemask;
6656 he->next = n.table[h];
6657 n.table[h] = he;
6658 ht->used--;
6659
6660 he = nextHe;
6661 }
6662 }
6663 assert(ht->used == 0);
6664 Jim_Free(ht->table);
6665
6666
6667 *ht = n;
6668 }
6669
6670
6671 int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6674,11 @@
6674
6675 entry = JimInsertHashEntry(ht, key, 0);
6676 if (entry == NULL)
6677 return JIM_ERR;
6678
6679
6680 Jim_SetHashKey(ht, entry, key);
6681 Jim_SetHashVal(ht, entry, val);
6682 return JIM_OK;
6683 }
6684
@@ -6678,11 +6700,11 @@
6700 Jim_SetHashVal(ht, entry, val);
6701 }
6702 existed = 1;
6703 }
6704 else {
6705
6706 Jim_SetHashKey(ht, entry, key);
6707 Jim_SetHashVal(ht, entry, val);
6708 existed = 0;
6709 }
6710
@@ -6701,11 +6723,11 @@
6723 he = ht->table[h];
6724
6725 prevHe = NULL;
6726 while (he) {
6727 if (Jim_CompareHashKeys(ht, key, he->key)) {
6728
6729 if (prevHe)
6730 prevHe->next = he->next;
6731 else
6732 ht->table[h] = he->next;
6733 Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6737,19 @@
6737 return JIM_OK;
6738 }
6739 prevHe = he;
6740 he = he->next;
6741 }
6742 return JIM_ERR;
6743 }
6744
6745
6746 int Jim_FreeHashTable(Jim_HashTable *ht)
6747 {
6748 unsigned int i;
6749
6750
6751 for (i = 0; ht->used > 0; i++) {
6752 Jim_HashEntry *he, *nextHe;
6753
6754 if ((he = ht->table[i]) == NULL)
6755 continue;
@@ -6738,15 +6760,15 @@
6760 Jim_Free(he);
6761 ht->used--;
6762 he = nextHe;
6763 }
6764 }
6765
6766 Jim_Free(ht->table);
6767
6768 JimResetHashTable(ht);
6769 return JIM_OK;
6770 }
6771
6772 Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
6773 {
6774 Jim_HashEntry *he;
@@ -6819,24 +6841,24 @@
6841 static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
6842 {
6843 unsigned int h;
6844 Jim_HashEntry *he;
6845
6846
6847 JimExpandHashTableIfNeeded(ht);
6848
6849
6850 h = Jim_HashKey(ht, key) & ht->sizemask;
6851
6852 he = ht->table[h];
6853 while (he) {
6854 if (Jim_CompareHashKeys(ht, key, he->key))
6855 return replace ? he : NULL;
6856 he = he->next;
6857 }
6858
6859
6860 he = Jim_Alloc(sizeof(*he));
6861 he->next = ht->table[h];
6862 ht->table[h] = he;
6863 ht->used++;
6864 he->key = NULL;
@@ -6865,16 +6887,16 @@
6887 {
6888 Jim_Free(key);
6889 }
6890
6891 static const Jim_HashTableType JimPackageHashTableType = {
6892 JimStringCopyHTHashFunction,
6893 JimStringCopyHTDup,
6894 NULL,
6895 JimStringCopyHTKeyCompare,
6896 JimStringCopyHTKeyDestructor,
6897 NULL
6898 };
6899
6900 typedef struct AssocDataValue
6901 {
6902 Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6911,16 @@
6911 assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
6912 Jim_Free(data);
6913 }
6914
6915 static const Jim_HashTableType JimAssocDataHashTableType = {
6916 JimStringCopyHTHashFunction,
6917 JimStringCopyHTDup,
6918 NULL,
6919 JimStringCopyHTKeyCompare,
6920 JimStringCopyHTKeyDestructor,
6921 JimAssocDataHashTableValueDestructor
6922 };
6923
6924 void Jim_InitStack(Jim_Stack *stack)
6925 {
6926 stack->len = 0;
@@ -6951,56 +6973,61 @@
6973 freeFunc(stack->vector[i]);
6974 }
6975
6976
6977
6978 #define JIM_TT_NONE 0
6979 #define JIM_TT_STR 1
6980 #define JIM_TT_ESC 2
6981 #define JIM_TT_VAR 3
6982 #define JIM_TT_DICTSUGAR 4
6983 #define JIM_TT_CMD 5
6984
6985 #define JIM_TT_SEP 6
6986 #define JIM_TT_EOL 7
6987 #define JIM_TT_EOF 8
6988
6989 #define JIM_TT_LINE 9
6990 #define JIM_TT_WORD 10
6991
6992
6993 #define JIM_TT_SUBEXPR_START 11
6994 #define JIM_TT_SUBEXPR_END 12
6995 #define JIM_TT_SUBEXPR_COMMA 13
6996 #define JIM_TT_EXPR_INT 14
6997 #define JIM_TT_EXPR_DOUBLE 15
6998 #define JIM_TT_EXPR_BOOLEAN 16
6999
7000 #define JIM_TT_EXPRSUGAR 17
7001
7002
7003 #define JIM_TT_EXPR_OP 20
7004
7005 #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
7006
7007 #define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA)
7008
7009 #define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP)
7010
7011 struct JimParseMissing {
7012 int ch;
7013 int line;
7014 };
7015
7016 struct JimParserCtx
7017 {
7018 const char *p;
7019 int len;
7020 int linenr;
7021 const char *tstart;
7022 const char *tend;
7023 int tline;
7024 int tt;
7025 int eof;
7026 int inquote;
7027 int comment;
7028 struct JimParseMissing missing;
7029 };
7030
7031 static int JimParseScript(struct JimParserCtx *pc);
7032 static int JimParseSep(struct JimParserCtx *pc);
7033 static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7057,11 @@
7057 pc->missing.line = linenr;
7058 }
7059
7060 static int JimParseScript(struct JimParserCtx *pc)
7061 {
7062 while (1) {
7063 if (!pc->len) {
7064 pc->tstart = pc->p;
7065 pc->tend = pc->p - 1;
7066 pc->tline = pc->linenr;
7067 pc->tt = JIM_TT_EOL;
@@ -7066,11 +7093,11 @@
7093 pc->comment = 0;
7094 return JimParseCmd(pc);
7095 case '$':
7096 pc->comment = 0;
7097 if (JimParseVar(pc) == JIM_ERR) {
7098
7099 pc->tstart = pc->tend = pc->p++;
7100 pc->len--;
7101 pc->tt = JIM_TT_ESC;
7102 }
7103 return JIM_OK;
@@ -7127,11 +7154,11 @@
7154
7155 static void JimParseSubBrace(struct JimParserCtx *pc)
7156 {
7157 int level = 1;
7158
7159
7160 pc->p++;
7161 pc->len--;
7162 while (pc->len) {
7163 switch (*pc->p) {
7164 case '\\':
@@ -7171,11 +7198,11 @@
7198 static int JimParseSubQuote(struct JimParserCtx *pc)
7199 {
7200 int tt = JIM_TT_STR;
7201 int line = pc->tline;
7202
7203
7204 pc->p++;
7205 pc->len--;
7206 while (pc->len) {
7207 switch (*pc->p) {
7208 case '\\':
@@ -7220,11 +7247,11 @@
7247 {
7248 int level = 1;
7249 int startofword = 1;
7250 int line = pc->tline;
7251
7252
7253 pc->p++;
7254 pc->len--;
7255 while (pc->len) {
7256 switch (*pc->p) {
7257 case '\\':
@@ -7300,17 +7327,17 @@
7327 return JIM_OK;
7328 }
7329
7330 static int JimParseVar(struct JimParserCtx *pc)
7331 {
7332
7333 pc->p++;
7334 pc->len--;
7335
7336 #ifdef EXPRSUGAR_BRACKET
7337 if (*pc->p == '[') {
7338
7339 JimParseCmd(pc);
7340 pc->tt = JIM_TT_EXPRSUGAR;
7341 return JIM_OK;
7342 }
7343 #endif
@@ -7336,11 +7363,11 @@
7363 pc->len--;
7364 }
7365 }
7366 else {
7367 while (1) {
7368
7369 if (pc->p[0] == ':' && pc->p[1] == ':') {
7370 while (*pc->p == ':') {
7371 pc->p++;
7372 pc->len--;
7373 }
@@ -7351,11 +7378,11 @@
7378 pc->len--;
7379 continue;
7380 }
7381 break;
7382 }
7383
7384 if (*pc->p == '(') {
7385 int count = 1;
7386 const char *paren = NULL;
7387
7388 pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7405,11 @@
7405 if (count == 0) {
7406 pc->p++;
7407 pc->len--;
7408 }
7409 else if (paren) {
7410
7411 paren++;
7412 pc->len += (pc->p - paren);
7413 pc->p = paren;
7414 }
7415 #ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7430,19 @@
7430
7431 static int JimParseStr(struct JimParserCtx *pc)
7432 {
7433 if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
7434 pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7435
7436 if (*pc->p == '{') {
7437 return JimParseBrace(pc);
7438 }
7439 if (*pc->p == '"') {
7440 pc->inquote = 1;
7441 pc->p++;
7442 pc->len--;
7443
7444 pc->missing.line = pc->tline;
7445 }
7446 }
7447 pc->tstart = pc->p;
7448 pc->tline = pc->linenr;
@@ -7441,25 +7468,25 @@
7468 }
7469 pc->p++;
7470 pc->len--;
7471 }
7472 else if (pc->len == 1) {
7473
7474 pc->missing.ch = '\\';
7475 }
7476 break;
7477 case '(':
7478
7479 if (pc->len > 1 && pc->p[1] != '$') {
7480 break;
7481 }
7482
7483 case ')':
7484
7485 if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
7486 if (pc->p == pc->tstart) {
7487
7488 pc->p++;
7489 pc->len--;
7490 }
7491 pc->tend = pc->p - 1;
7492 pc->tt = JIM_TT_ESC;
@@ -7499,11 +7526,11 @@
7526 break;
7527 }
7528 pc->p++;
7529 pc->len--;
7530 }
7531 return JIM_OK;
7532 }
7533
7534 static int JimParseComment(struct JimParserCtx *pc)
7535 {
7536 while (*pc->p) {
@@ -7610,34 +7637,34 @@
7637 if (c == -1) {
7638 break;
7639 }
7640 val = (val << 4) | c;
7641 }
7642
7643 if (s[i] == '{') {
7644 if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7645
7646 i--;
7647 k = 0;
7648 }
7649 else {
7650
7651 k++;
7652 }
7653 }
7654 if (k) {
7655
7656 if (s[i] == 'x') {
7657 *p++ = val;
7658 }
7659 else {
7660 p += utf8_fromunicode(p, val);
7661 }
7662 i += k;
7663 break;
7664 }
7665
7666 *p++ = s[i];
7667 }
7668 break;
7669 case 'v':
7670 *p++ = 0xb;
@@ -7646,11 +7673,11 @@
7673 case '\0':
7674 *p++ = '\\';
7675 i++;
7676 break;
7677 case '\n':
7678
7679 *p++ = ' ';
7680 do {
7681 i++;
7682 } while (s[i + 1] == ' ' || s[i + 1] == '\t');
7683 break;
@@ -7660,11 +7687,11 @@
7687 case '3':
7688 case '4':
7689 case '5':
7690 case '6':
7691 case '7':
7692
7693 {
7694 int val = 0;
7695 int c = odigitval(s[i + 1]);
7696
7697 val = c;
@@ -7708,27 +7735,23 @@
7735 char *token;
7736 int len;
7737
7738 start = pc->tstart;
7739 end = pc->tend;
7740 len = (end - start) + 1;
7741 if (len < 0) {
7742 len = 0;
7743 }
7744 token = Jim_Alloc(len + 1);
7745 if (pc->tt != JIM_TT_ESC) {
7746
7747 memcpy(token, start, len);
7748 token[len] = '\0';
7749 }
7750 else {
7751
7752 len = JimEscape(token, start, len);
 
 
 
 
 
7753 }
7754
7755 return Jim_NewStringObjNoAlloc(interp, token, len);
7756 }
7757
@@ -7790,11 +7813,11 @@
7813 while (pc->len) {
7814 switch (*pc->p) {
7815 case '\\':
7816 pc->tt = JIM_TT_ESC;
7817 if (--pc->len == 0) {
7818
7819 pc->tend = pc->p;
7820 return JIM_OK;
7821 }
7822 pc->p++;
7823 break;
@@ -7826,11 +7849,11 @@
7849 pc->tend = pc->p - 1;
7850 return JIM_OK;
7851 }
7852 if (*pc->p == '\\') {
7853 if (--pc->len == 0) {
7854
7855 pc->tend = pc->p;
7856 return JIM_OK;
7857 }
7858 pc->tt = JIM_TT_ESC;
7859 pc->p++;
@@ -7846,24 +7869,24 @@
7869
7870 Jim_Obj *Jim_NewObj(Jim_Interp *interp)
7871 {
7872 Jim_Obj *objPtr;
7873
7874
7875 if (interp->freeList != NULL) {
7876
7877 objPtr = interp->freeList;
7878 interp->freeList = objPtr->nextObjPtr;
7879 }
7880 else {
7881
7882 objPtr = Jim_Alloc(sizeof(*objPtr));
7883 }
7884
7885 objPtr->refCount = 0;
7886
7887
7888 objPtr->prevObjPtr = NULL;
7889 objPtr->nextObjPtr = interp->liveList;
7890 if (interp->liveList)
7891 interp->liveList->prevObjPtr = objPtr;
7892 interp->liveList = objPtr;
@@ -7871,32 +7894,32 @@
7894 return objPtr;
7895 }
7896
7897 void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
7898 {
7899
7900 JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
7901 objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
7902
7903
7904 Jim_FreeIntRep(interp, objPtr);
7905
7906 if (objPtr->bytes != NULL) {
7907 if (objPtr->bytes != JimEmptyStringRep)
7908 Jim_Free(objPtr->bytes);
7909 }
7910
7911 if (objPtr->prevObjPtr)
7912 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7913 if (objPtr->nextObjPtr)
7914 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7915 if (interp->liveList == objPtr)
7916 interp->liveList = objPtr->nextObjPtr;
7917 #ifdef JIM_DISABLE_OBJECT_POOL
7918 Jim_Free(objPtr);
7919 #else
7920
7921 objPtr->prevObjPtr = NULL;
7922 objPtr->nextObjPtr = interp->freeList;
7923 if (interp->freeList)
7924 interp->freeList->prevObjPtr = objPtr;
7925 interp->freeList = objPtr;
@@ -7919,45 +7942,44 @@
7942 {
7943 Jim_Obj *dupPtr;
7944
7945 dupPtr = Jim_NewObj(interp);
7946 if (objPtr->bytes == NULL) {
7947
7948 dupPtr->bytes = NULL;
7949 }
7950 else if (objPtr->length == 0) {
 
7951 dupPtr->bytes = JimEmptyStringRep;
7952 dupPtr->length = 0;
7953 dupPtr->typePtr = NULL;
7954 return dupPtr;
7955 }
7956 else {
7957 dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
7958 dupPtr->length = objPtr->length;
7959
7960 memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
7961 }
7962
7963
7964 dupPtr->typePtr = objPtr->typePtr;
7965 if (objPtr->typePtr != NULL) {
7966 if (objPtr->typePtr->dupIntRepProc == NULL) {
7967 dupPtr->internalRep = objPtr->internalRep;
7968 }
7969 else {
7970
7971 objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
7972 }
7973 }
7974 return dupPtr;
7975 }
7976
7977 const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
7978 {
7979 if (objPtr->bytes == NULL) {
7980
7981 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7982 objPtr->typePtr->updateStringProc(objPtr);
7983 }
7984 if (lenPtr)
7985 *lenPtr = objPtr->length;
@@ -7966,25 +7988,22 @@
7988
7989
7990 int Jim_Length(Jim_Obj *objPtr)
7991 {
7992 if (objPtr->bytes == NULL) {
7993
7994 Jim_GetString(objPtr, NULL);
 
7995 }
7996 return objPtr->length;
7997 }
7998
7999
8000 const char *Jim_String(Jim_Obj *objPtr)
8001 {
8002 if (objPtr->bytes == NULL) {
8003
8004 Jim_GetString(objPtr, NULL);
 
 
8005 }
8006 return objPtr->bytes;
8007 }
8008
8009 static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
@@ -8001,23 +8020,34 @@
8020 FreeDictSubstInternalRep,
8021 DupDictSubstInternalRep,
8022 NULL,
8023 JIM_TYPE_NONE,
8024 };
8025
8026 static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8027 static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8028
8029 static const Jim_ObjType interpolatedObjType = {
8030 "interpolated",
8031 FreeInterpolatedInternalRep,
8032 DupInterpolatedInternalRep,
8033 NULL,
8034 JIM_TYPE_NONE,
8035 };
8036
8037 static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8038 {
8039 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
8040 }
8041
8042 static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8043 {
8044
8045 dupPtr->internalRep = srcPtr->internalRep;
8046
8047 Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
8048 }
8049
8050 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8051 static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8052
8053 static const Jim_ObjType stringObjType = {
@@ -8037,22 +8067,22 @@
8067 }
8068
8069 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
8070 {
8071 if (objPtr->typePtr != &stringObjType) {
8072
8073 if (objPtr->bytes == NULL) {
8074
8075 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8076 objPtr->typePtr->updateStringProc(objPtr);
8077 }
8078
8079 Jim_FreeIntRep(interp, objPtr);
8080
8081 objPtr->typePtr = &stringObjType;
8082 objPtr->internalRep.strValue.maxLength = objPtr->length;
8083
8084 objPtr->internalRep.strValue.charLength = -1;
8085 }
8086 return JIM_OK;
8087 }
8088
@@ -8073,39 +8103,37 @@
8103
8104 Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
8105 {
8106 Jim_Obj *objPtr = Jim_NewObj(interp);
8107
8108
8109 if (len == -1)
8110 len = strlen(s);
8111
8112 if (len == 0) {
8113 objPtr->bytes = JimEmptyStringRep;
8114 }
8115 else {
8116 objPtr->bytes = Jim_StrDupLen(s, len);
 
 
8117 }
8118 objPtr->length = len;
8119
8120
8121 objPtr->typePtr = NULL;
8122 return objPtr;
8123 }
8124
8125
8126 Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
8127 {
8128 #ifdef JIM_UTF8
8129
8130 int bytelen = utf8_index(s, charlen);
8131
8132 Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
8133
8134
8135 objPtr->typePtr = &stringObjType;
8136 objPtr->internalRep.strValue.maxLength = bytelen;
8137 objPtr->internalRep.strValue.charLength = charlen;
8138
8139 return objPtr;
@@ -8132,11 +8160,11 @@
8160 len = strlen(str);
8161 needlen = objPtr->length + len;
8162 if (objPtr->internalRep.strValue.maxLength < needlen ||
8163 objPtr->internalRep.strValue.maxLength == 0) {
8164 needlen *= 2;
8165
8166 if (needlen < 7) {
8167 needlen = 7;
8168 }
8169 if (objPtr->bytes == JimEmptyStringRep) {
8170 objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8176,11 @@
8176 }
8177 memcpy(objPtr->bytes + objPtr->length, str, len);
8178 objPtr->bytes[objPtr->length + len] = '\0';
8179
8180 if (objPtr->internalRep.strValue.charLength >= 0) {
8181
8182 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
8183 }
8184 objPtr->length += len;
8185 }
8186
@@ -8210,11 +8238,11 @@
8238 int l1, l2;
8239 const char *s1 = Jim_GetString(firstObjPtr, &l1);
8240 const char *s2 = Jim_GetString(secondObjPtr, &l2);
8241
8242 if (nocase) {
8243
8244 return JimStringCompareLen(s1, s2, -1, nocase);
8245 }
8246 return JimStringCompare(s1, l1, s2, l2);
8247 }
8248
@@ -8312,11 +8340,11 @@
8340
8341 if (first == 0 && rangeLen == len) {
8342 return strObjPtr;
8343 }
8344 if (len == bytelen) {
8345
8346 return Jim_NewStringObj(interp, str + first, rangeLen);
8347 }
8348 return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
8349 #else
8350 return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8369,19 @@
8369 return strObjPtr;
8370 }
8371
8372 str = Jim_String(strObjPtr);
8373
8374
8375 objPtr = Jim_NewStringObjUtf8(interp, str, first);
8376
8377
8378 if (newStrObj) {
8379 Jim_AppendObj(interp, objPtr, newStrObj);
8380 }
8381
8382
8383 Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
8384
8385 return objPtr;
8386 }
8387
@@ -8371,12 +8399,10 @@
8399 {
8400 char *buf;
8401 int len;
8402 const char *str;
8403
 
 
8404 str = Jim_GetString(strObjPtr, &len);
8405
8406 #ifdef JIM_UTF8
8407 len *= 2;
8408 #endif
@@ -8389,14 +8415,10 @@
8415 {
8416 char *buf;
8417 const char *str;
8418 int len;
8419
 
 
 
 
8420 str = Jim_GetString(strObjPtr, &len);
8421
8422 #ifdef JIM_UTF8
8423 len *= 2;
8424 #endif
@@ -8411,13 +8433,11 @@
8433 int len;
8434 int c;
8435 const char *str;
8436
8437 str = Jim_GetString(strObjPtr, &len);
8438
 
 
8439 #ifdef JIM_UTF8
8440 len *= 2;
8441 #endif
8442 buf = p = Jim_Alloc(len + 1);
8443
@@ -8452,11 +8472,11 @@
8472 while (len) {
8473 int c;
8474 int n = utf8_tounicode(str, &c);
8475
8476 if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8477
8478 break;
8479 }
8480 str += n;
8481 len -= n;
8482 }
@@ -8523,41 +8543,41 @@
8543
8544 len = Jim_Length(strObjPtr);
8545 nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
8546
8547 if (nontrim == NULL) {
8548
8549 return Jim_NewEmptyStringObj(interp);
8550 }
8551 if (nontrim == strObjPtr->bytes + len) {
8552
8553 return strObjPtr;
8554 }
8555
8556 if (Jim_IsShared(strObjPtr)) {
8557 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
8558 }
8559 else {
8560
8561 strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
8562 strObjPtr->length = (nontrim - strObjPtr->bytes);
8563 }
8564
8565 return strObjPtr;
8566 }
8567
8568 static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
8569 {
8570
8571 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8572
8573
8574 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8575
8576
8577 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8578
8579 Jim_FreeNewObj(interp, objPtr);
8580 }
8581
8582 return strObjPtr;
8583 }
@@ -8575,17 +8595,17 @@
8595 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8596 {
8597 static const char * const strclassnames[] = {
8598 "integer", "alpha", "alnum", "ascii", "digit",
8599 "double", "lower", "upper", "space", "xdigit",
8600 "control", "print", "graph", "punct", "boolean",
8601 NULL
8602 };
8603 enum {
8604 STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
8605 STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8606 STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN,
8607 };
8608 int strclass;
8609 int len;
8610 int i;
8611 const char *str;
@@ -8613,10 +8633,17 @@
8633 {
8634 double d;
8635 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8636 return JIM_OK;
8637 }
8638
8639 case STR_IS_BOOLEAN:
8640 {
8641 int b;
8642 Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK);
8643 return JIM_OK;
8644 }
8645
8646 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8647 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8648 case STR_IS_ASCII: isclassfunc = jim_isascii; break;
8649 case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8658,11 @@
8658 default:
8659 return JIM_ERR;
8660 }
8661
8662 for (i = 0; i < len; i++) {
8663 if (!isclassfunc(UCHAR(str[i]))) {
8664 Jim_SetResultBool(interp, 0);
8665 return JIM_OK;
8666 }
8667 }
8668 Jim_SetResultBool(interp, 1);
@@ -8656,20 +8683,18 @@
8683 {
8684 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
8685 return 1;
8686 }
8687 else {
8688 if (strcmp(str, Jim_String(objPtr)) != 0)
 
 
8689 return 0;
8690
8691 if (objPtr->typePtr != &comparedStringObjType) {
8692 Jim_FreeIntRep(interp, objPtr);
8693 objPtr->typePtr = &comparedStringObjType;
8694 }
8695 objPtr->internalRep.ptr = (char *)str;
8696 return 1;
8697 }
8698 }
8699
8700 static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8783,20 @@
8783 int type;
8784 } ScriptToken;
8785
8786 typedef struct ScriptObj
8787 {
8788 ScriptToken *token;
8789 Jim_Obj *fileNameObj;
8790 int len;
8791 int substFlags;
8792 int inUse; /* Used to share a ScriptObj. Currently
8793 only used by Jim_EvalObj() as protection against
8794 shimmering of the currently evaluated object. */
8795 int firstline;
8796 int linenr;
8797 int missing;
8798 } ScriptObj;
8799
8800 static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8801 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8802 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8824,23 @@
8824 dupPtr->typePtr = NULL;
8825 }
8826
8827 typedef struct
8828 {
8829 const char *token;
8830 int len;
8831 int type;
8832 int line;
8833 } ParseToken;
8834
8835 typedef struct
8836 {
8837
8838 ParseToken *list;
8839 int size;
8840 int count;
8841 ParseToken static_list[20];
8842 } ParseTokenList;
8843
8844 static void ScriptTokenListInit(ParseTokenList *tokenlist)
8845 {
8846 tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8859,18 @@
8859 int line)
8860 {
8861 ParseToken *t;
8862
8863 if (tokenlist->count == tokenlist->size) {
8864
8865 tokenlist->size *= 2;
8866 if (tokenlist->list != tokenlist->static_list) {
8867 tokenlist->list =
8868 Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
8869 }
8870 else {
8871
8872 tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
8873 memcpy(tokenlist->list, tokenlist->static_list,
8874 tokenlist->count * sizeof(*tokenlist->list));
8875 }
8876 }
@@ -8854,25 +8879,32 @@
8879 t->len = len;
8880 t->type = type;
8881 t->line = line;
8882 }
8883
8884 static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t)
8885 {
8886 int expand = 1;
8887 int count = 0;
8888
8889
8890 if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
8891 if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8892
8893 expand = -1;
8894 t++;
8895 }
8896 else {
8897 if (script->missing == ' ') {
8898
8899 script->missing = '}';
8900 script->linenr = t[1].line;
8901 }
8902 }
8903 }
8904
8905
8906 while (!TOKEN_IS_SEP(t->type)) {
8907 t++;
8908 count++;
8909 }
8910
@@ -8882,11 +8914,11 @@
8914 static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
8915 {
8916 Jim_Obj *objPtr;
8917
8918 if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8919
8920 int len = t->len;
8921 char *str = Jim_Alloc(len + 1);
8922 len = JimEscape(str, t->token, len);
8923 objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
8924 }
@@ -8899,13 +8931,13 @@
8931 static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8932 ParseTokenList *tokenlist)
8933 {
8934 int i;
8935 struct ScriptToken *token;
8936
8937 int lineargs = 0;
8938
8939 ScriptToken *linefirst;
8940 int count;
8941 int linenr;
8942
8943 #ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +8946,11 @@
8946 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
8947 tokenlist->list[i].len, tokenlist->list[i].token);
8948 }
8949 #endif
8950
8951
8952 count = tokenlist->count;
8953 for (i = 0; i < tokenlist->count; i++) {
8954 if (tokenlist->list[i].type == JIM_TT_EOL) {
8955 count++;
8956 }
@@ -8925,59 +8957,59 @@
8957 }
8958 linenr = script->firstline = tokenlist->list[0].line;
8959
8960 token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
8961
8962
8963 linefirst = token++;
8964
8965 for (i = 0; i < tokenlist->count; ) {
8966
8967 int wordtokens;
8968
8969
8970 while (tokenlist->list[i].type == JIM_TT_SEP) {
8971 i++;
8972 }
8973
8974 wordtokens = JimCountWordTokens(script, tokenlist->list + i);
8975
8976 if (wordtokens == 0) {
8977
8978 if (lineargs) {
8979 linefirst->type = JIM_TT_LINE;
8980 linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
8981 Jim_IncrRefCount(linefirst->objPtr);
8982
8983
8984 lineargs = 0;
8985 linefirst = token++;
8986 }
8987 i++;
8988 continue;
8989 }
8990 else if (wordtokens != 1) {
8991
8992 token->type = JIM_TT_WORD;
8993 token->objPtr = Jim_NewIntObj(interp, wordtokens);
8994 Jim_IncrRefCount(token->objPtr);
8995 token++;
8996 if (wordtokens < 0) {
8997
8998 i++;
8999 wordtokens = -wordtokens - 1;
9000 lineargs--;
9001 }
9002 }
9003
9004 if (lineargs == 0) {
9005
9006 linenr = tokenlist->list[i].line;
9007 }
9008 lineargs++;
9009
9010
9011 while (wordtokens--) {
9012 const ParseToken *t = &tokenlist->list[i++];
9013
9014 token->type = t->type;
9015 token->objPtr = JimMakeScriptObj(interp, t);
@@ -9010,11 +9042,11 @@
9042 {
9043 ScriptObj *script = JimGetScript(interp, scriptObj);
9044 if (stateCharPtr) {
9045 *stateCharPtr = script->missing;
9046 }
9047 return script->missing == ' ' || script->missing == '}';
9048 }
9049
9050 static int JimParseCheckMissing(Jim_Interp *interp, int ch)
9051 {
9052 const char *msg;
@@ -9028,10 +9060,13 @@
9060 msg = "unmatched \"[\"";
9061 break;
9062 case '{':
9063 msg = "missing close-brace";
9064 break;
9065 case '}':
9066 msg = "extra characters after close-brace";
9067 break;
9068 case '"':
9069 default:
9070 msg = "missing quote";
9071 break;
9072 }
@@ -9049,11 +9084,11 @@
9084 token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
9085
9086 for (i = 0; i < tokenlist->count; i++) {
9087 const ParseToken *t = &tokenlist->list[i];
9088
9089
9090 token->type = t->type;
9091 token->objPtr = JimMakeScriptObj(interp, t);
9092 Jim_IncrRefCount(token->objPtr);
9093 token++;
9094 }
@@ -9068,29 +9103,29 @@
9103 struct JimParserCtx parser;
9104 struct ScriptObj *script;
9105 ParseTokenList tokenlist;
9106 int line = 1;
9107
9108
9109 if (objPtr->typePtr == &sourceObjType) {
9110 line = objPtr->internalRep.sourceValue.lineNumber;
9111 }
9112
9113
9114 ScriptTokenListInit(&tokenlist);
9115
9116 JimParserInit(&parser, scriptText, scriptTextLen, line);
9117 while (!parser.eof) {
9118 JimParseScript(&parser);
9119 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
9120 parser.tline);
9121 }
9122
9123
9124 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
9125
9126
9127 script = Jim_Alloc(sizeof(*script));
9128 memset(script, 0, sizeof(*script));
9129 script->inUse = 1;
9130 if (objPtr->typePtr == &sourceObjType) {
9131 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9137,14 @@
9137 script->missing = parser.missing.ch;
9138 script->linenr = parser.missing.line;
9139
9140 ScriptObjAddTokens(interp, script, &tokenlist);
9141
9142
9143 ScriptTokenListFree(&tokenlist);
9144
9145
9146 Jim_FreeIntRep(interp, objPtr);
9147 Jim_SetIntRepPtr(objPtr, script);
9148 objPtr->typePtr = &scriptObjType;
9149 }
9150
@@ -9116,11 +9151,11 @@
9151 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
9152
9153 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
9154 {
9155 if (objPtr == interp->emptyObj) {
9156
9157 objPtr = interp->nullScriptObj;
9158 }
9159
9160 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
9161 JimSetScriptFromAny(interp, objPtr);
@@ -9155,67 +9190,66 @@
9190 Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
9191 Jim_Free(cmdPtr->u.proc.staticVars);
9192 }
9193 }
9194 else {
9195
9196 if (cmdPtr->u.native.delProc) {
9197 cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
9198 }
9199 }
9200 if (cmdPtr->prevCmd) {
9201
9202 JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
9203 }
9204 Jim_Free(cmdPtr);
9205 }
9206 }
 
9207
9208 static void JimVariablesHTValDestructor(void *interp, void *val)
9209 {
9210 Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
9211 Jim_Free(val);
9212 }
9213
9214 static const Jim_HashTableType JimVariablesHashTableType = {
9215 JimStringCopyHTHashFunction,
9216 JimStringCopyHTDup,
9217 NULL,
9218 JimStringCopyHTKeyCompare,
9219 JimStringCopyHTKeyDestructor,
9220 JimVariablesHTValDestructor
9221 };
9222
9223 static void JimCommandsHT_ValDestructor(void *interp, void *val)
9224 {
9225 JimDecrCmdRefCount(interp, val);
9226 }
9227
9228 static const Jim_HashTableType JimCommandsHashTableType = {
9229 JimStringCopyHTHashFunction,
9230 JimStringCopyHTDup,
9231 NULL,
9232 JimStringCopyHTKeyCompare,
9233 JimStringCopyHTKeyDestructor,
9234 JimCommandsHT_ValDestructor
9235 };
9236
9237
9238
9239 #ifdef jim_ext_namespace
9240 static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
9241 {
9242 const char *name = Jim_String(nsObj);
9243 if (name[0] == ':' && name[1] == ':') {
9244
9245 while (*++name == ':') {
9246 }
9247 nsObj = Jim_NewStringObj(interp, name, -1);
9248 }
9249 else if (Jim_Length(interp->framePtr->nsObj)) {
9250
9251 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9252 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
9253 }
9254 return nsObj;
9255 }
@@ -9239,16 +9273,16 @@
9273 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9274 {
9275 Jim_Obj *objPtr = interp->emptyObj;
9276
9277 if (name[0] == ':' && name[1] == ':') {
9278
9279 while (*++name == ':') {
9280 }
9281 }
9282 else if (Jim_Length(interp->framePtr->nsObj)) {
9283
9284 objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9285 Jim_AppendStrings(interp, objPtr, "::", name, NULL);
9286 name = Jim_String(objPtr);
9287 }
9288 Jim_IncrRefCount(objPtr);
@@ -9257,11 +9291,11 @@
9291 }
9292
9293 #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
9294
9295 #else
9296
9297 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9298 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9299
9300 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9301 {
@@ -9276,17 +9310,17 @@
9310
9311 Jim_InterpIncrProcEpoch(interp);
9312 }
9313
9314 if (he && interp->local) {
9315
9316 cmd->prevCmd = Jim_GetHashEntryVal(he);
9317 Jim_SetHashVal(&interp->commands, he, cmd);
9318 }
9319 else {
9320 if (he) {
9321
9322 Jim_DeleteHashEntry(&interp->commands, name);
9323 }
9324
9325 Jim_AddHashEntry(&interp->commands, name, cmd);
9326 }
@@ -9297,11 +9331,11 @@
9331 int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
9332 Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
9333 {
9334 Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
9335
9336
9337 memset(cmdPtr, 0, sizeof(*cmdPtr));
9338 cmdPtr->inUse = 1;
9339 cmdPtr->u.native.delProc = delProc;
9340 cmdPtr->u.native.cmdProc = cmdProc;
9341 cmdPtr->u.native.privData = privData;
@@ -9326,11 +9360,11 @@
9360 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9361 Jim_Var *varPtr;
9362 int subLen;
9363
9364 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9365
9366 subLen = Jim_ListLength(interp, objPtr);
9367 if (subLen == 1 || subLen == 2) {
9368 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9369 if (subLen == 1) {
9370 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9406,19 @@
9406
9407 static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
9408 {
9409 #ifdef jim_ext_namespace
9410 if (cmdPtr->isproc) {
9411
9412 const char *pt = strrchr(cmdname, ':');
9413 if (pt && pt != cmdname && pt[-1] == ':') {
9414 Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
9415 cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
9416 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9417
9418 if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9419
9420 Jim_InterpIncrProcEpoch(interp);
9421 }
9422 }
9423 }
9424 #endif
@@ -9397,11 +9431,11 @@
9431 int argListLen;
9432 int i;
9433
9434 argListLen = Jim_ListLength(interp, argListObjPtr);
9435
9436
9437 cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
9438 memset(cmdPtr, 0, sizeof(*cmdPtr));
9439 cmdPtr->inUse = 1;
9440 cmdPtr->isproc = 1;
9441 cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9446,24 @@
9446 cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
9447 Jim_IncrRefCount(argListObjPtr);
9448 Jim_IncrRefCount(bodyObjPtr);
9449 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9450
9451
9452 if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
9453 goto err;
9454 }
9455
9456
9457
9458 for (i = 0; i < argListLen; i++) {
9459 Jim_Obj *argPtr;
9460 Jim_Obj *nameObjPtr;
9461 Jim_Obj *defaultObjPtr;
9462 int len;
9463
9464
9465 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9466 len = Jim_ListLength(interp, argPtr);
9467 if (len == 0) {
9468 Jim_SetResultString(interp, "argument with no name", -1);
9469 err:
@@ -9440,16 +9474,16 @@
9474 Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
9475 goto err;
9476 }
9477
9478 if (len == 2) {
9479
9480 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9481 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9482 }
9483 else {
9484
9485 nameObjPtr = argPtr;
9486 defaultObjPtr = NULL;
9487 }
9488
9489
@@ -9510,29 +9544,29 @@
9544 }
9545
9546 fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
9547 fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
9548
9549
9550 he = Jim_FindHashEntry(&interp->commands, fqold);
9551 if (he == NULL) {
9552 Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
9553 }
9554 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9555 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9556 }
9557 else {
9558
9559 cmdPtr = Jim_GetHashEntryVal(he);
9560 JimIncrCmdRefCount(cmdPtr);
9561 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9562 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9563
9564
9565 Jim_DeleteHashEntry(&interp->commands, fqold);
9566
9567
9568 Jim_InterpIncrProcEpoch(interp);
9569
9570 ret = JIM_OK;
9571 }
9572
@@ -9571,23 +9605,23 @@
9605 objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
9606 #ifdef jim_ext_namespace
9607 || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
9608 #endif
9609 ) {
 
9610
9611
9612
9613 const char *name = Jim_String(objPtr);
9614 Jim_HashEntry *he;
9615
9616 if (name[0] == ':' && name[1] == ':') {
9617 while (*++name == ':') {
9618 }
9619 }
9620 #ifdef jim_ext_namespace
9621 else if (Jim_Length(interp->framePtr->nsObj)) {
9622
9623 Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9624 Jim_AppendStrings(interp, nameObj, "::", name, NULL);
9625 he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
9626 Jim_FreeNewObj(interp, nameObj);
9627 if (he) {
@@ -9594,11 +9628,11 @@
9628 goto found;
9629 }
9630 }
9631 #endif
9632
9633
9634 he = Jim_FindHashEntry(&interp->commands, name);
9635 if (he == NULL) {
9636 if (flags & JIM_ERRMSG) {
9637 Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
9638 }
@@ -9607,11 +9641,11 @@
9641 #ifdef jim_ext_namespace
9642 found:
9643 #endif
9644 cmd = Jim_GetHashEntryVal(he);
9645
9646
9647 Jim_FreeIntRep(interp, objPtr);
9648 objPtr->typePtr = &commandObjType;
9649 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
9650 objPtr->internalRep.cmdValue.cmdPtr = cmd;
9651 objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9660,11 @@
9660 return cmd;
9661 }
9662
9663
9664
9665 #define JIM_DICT_SUGAR 100
9666
9667 static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
9668
9669 static const Jim_ObjType variableObjType = {
9670 "variable",
@@ -9640,11 +9674,11 @@
9674 JIM_TYPE_REFERENCES,
9675 };
9676
9677 static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
9678 {
9679
9680 if (nameObjPtr->typePtr != &variableObjType) {
9681 int len;
9682 const char *str = Jim_GetString(nameObjPtr, &len);
9683 if (memchr(str, '\0', len)) {
9684 Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9694,18 @@
9694 Jim_CallFrame *framePtr;
9695 Jim_HashEntry *he;
9696 int global;
9697 int len;
9698
9699
9700 if (objPtr->typePtr == &variableObjType) {
9701 framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
9702 if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9703
9704 return JIM_OK;
9705 }
9706
9707 }
9708 else if (objPtr->typePtr == &dictSubstObjType) {
9709 return JIM_DICT_SUGAR;
9710 }
9711 else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9713,11 @@
9713 }
9714
9715
9716 varName = Jim_GetString(objPtr, &len);
9717
9718
9719 if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
9720 return JIM_DICT_SUGAR;
9721 }
9722
9723 if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9729,23 @@
9729 else {
9730 global = 0;
9731 framePtr = interp->framePtr;
9732 }
9733
9734
9735 he = Jim_FindHashEntry(&framePtr->vars, varName);
9736 if (he == NULL) {
9737 if (!global && framePtr->staticVars) {
9738
9739 he = Jim_FindHashEntry(framePtr->staticVars, varName);
9740 }
9741 if (he == NULL) {
9742 return JIM_ERR;
9743 }
9744 }
9745
9746
9747 Jim_FreeIntRep(interp, objPtr);
9748 objPtr->typePtr = &variableObjType;
9749 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9750 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9751 objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9760,11 @@
9760 {
9761 const char *name;
9762 Jim_CallFrame *framePtr;
9763 int global;
9764
9765
9766 Jim_Var *var = Jim_Alloc(sizeof(*var));
9767
9768 var->objPtr = valObjPtr;
9769 Jim_IncrRefCount(valObjPtr);
9770 var->linkFramePtr = NULL;
@@ -9745,14 +9779,14 @@
9779 else {
9780 framePtr = interp->framePtr;
9781 global = 0;
9782 }
9783
9784
9785 Jim_AddHashEntry(&framePtr->vars, name, var);
9786
9787
9788 Jim_FreeIntRep(interp, nameObjPtr);
9789 nameObjPtr->typePtr = &variableObjType;
9790 nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
9791 nameObjPtr->internalRep.varValue.varPtr = var;
9792 nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9816,11 @@
9816 if (var->linkFramePtr == NULL) {
9817 Jim_IncrRefCount(valObjPtr);
9818 Jim_DecrRefCount(interp, var->objPtr);
9819 var->objPtr = valObjPtr;
9820 }
9821 else {
9822 Jim_CallFrame *savedCallFrame;
9823
9824 savedCallFrame = interp->framePtr;
9825 interp->framePtr = var->linkFramePtr;
9826 err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9822,19 +9856,16 @@
9856 return result;
9857 }
9858
9859 int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val)
9860 {
9861 Jim_Obj *valObjPtr;
9862 int result;
9863
 
9864 valObjPtr = Jim_NewStringObj(interp, val, -1);
 
9865 Jim_IncrRefCount(valObjPtr);
9866 result = Jim_SetVariableStr(interp, name, valObjPtr);
 
9867 Jim_DecrRefCount(interp, valObjPtr);
9868 return result;
9869 }
9870
9871 int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
@@ -9843,14 +9874,14 @@
9874 const char *varName;
9875 const char *targetName;
9876 Jim_CallFrame *framePtr;
9877 Jim_Var *varPtr;
9878
9879
9880 switch (SetVariableFromAny(interp, nameObjPtr)) {
9881 case JIM_DICT_SUGAR:
9882
9883 Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
9884 return JIM_ERR;
9885
9886 case JIM_OK:
9887 varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9889,23 @@
9889 if (varPtr->linkFramePtr == NULL) {
9890 Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
9891 return JIM_ERR;
9892 }
9893
9894
9895 varPtr->linkFramePtr = NULL;
9896 break;
9897 }
9898
9899
9900
9901 varName = Jim_String(nameObjPtr);
9902
9903 if (varName[0] == ':' && varName[1] == ':') {
9904 while (*++varName == ':') {
9905 }
9906
9907 framePtr = interp->topFramePtr;
9908 }
9909 else {
9910 framePtr = interp->framePtr;
9911 }
@@ -9894,15 +9925,15 @@
9925 nameObjPtr);
9926 Jim_DecrRefCount(interp, targetNameObjPtr);
9927 return JIM_ERR;
9928 }
9929
9930
9931 if (framePtr == targetCallFrame) {
9932 Jim_Obj *objPtr = targetNameObjPtr;
9933
9934
9935 while (1) {
9936 if (strcmp(Jim_String(objPtr), varName) == 0) {
9937 Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
9938 Jim_DecrRefCount(interp, targetNameObjPtr);
9939 return JIM_ERR;
@@ -9914,13 +9945,13 @@
9945 break;
9946 objPtr = varPtr->objPtr;
9947 }
9948 }
9949
9950
9951 Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
9952
9953 nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
9954 Jim_DecrRefCount(interp, targetNameObjPtr);
9955 return JIM_OK;
9956 }
9957
@@ -9934,26 +9965,26 @@
9965 return varPtr->objPtr;
9966 }
9967 else {
9968 Jim_Obj *objPtr;
9969
9970
9971 Jim_CallFrame *savedCallFrame = interp->framePtr;
9972
9973 interp->framePtr = varPtr->linkFramePtr;
9974 objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
9975 interp->framePtr = savedCallFrame;
9976 if (objPtr) {
9977 return objPtr;
9978 }
9979
9980 }
9981 }
9982 break;
9983
9984 case JIM_DICT_SUGAR:
9985
9986 return JimDictSugarGet(interp, nameObjPtr, flags);
9987 }
9988 if (flags & JIM_ERRMSG) {
9989 Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
9990 }
@@ -10003,17 +10034,17 @@
10034 int retval;
10035 Jim_CallFrame *framePtr;
10036
10037 retval = SetVariableFromAny(interp, nameObjPtr);
10038 if (retval == JIM_DICT_SUGAR) {
10039
10040 return JimDictSugarSet(interp, nameObjPtr, NULL);
10041 }
10042 else if (retval == JIM_OK) {
10043 varPtr = nameObjPtr->internalRep.varValue.varPtr;
10044
10045
10046 if (varPtr->linkFramePtr) {
10047 framePtr = interp->framePtr;
10048 interp->framePtr = varPtr->linkFramePtr;
10049 retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
10050 interp->framePtr = framePtr;
@@ -10028,11 +10059,11 @@
10059 framePtr = interp->framePtr;
10060 }
10061
10062 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
10063 if (retval == JIM_OK) {
10064
10065 framePtr->id = interp->callFrameEpoch++;
10066 }
10067 }
10068 }
10069 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10092,11 @@
10092 keyLen = (str + len) - p;
10093 if (str[len - 1] == ')') {
10094 keyLen--;
10095 }
10096
10097
10098 keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
10099
10100 Jim_IncrRefCount(varObjPtr);
10101 Jim_IncrRefCount(keyObjPtr);
10102 *varPtrPtr = varObjPtr;
@@ -10080,23 +10111,23 @@
10111
10112 err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
10113 &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
10114
10115 if (err == JIM_OK) {
10116
10117 Jim_SetEmptyResult(interp);
10118 }
10119 else {
10120 if (!valObjPtr) {
10121
10122 if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
10123 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
10124 objPtr);
10125 return err;
10126 }
10127 }
10128
10129 Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
10130 (valObjPtr ? "set" : "unset"), objPtr);
10131 }
10132 return err;
10133 }
@@ -10118,11 +10149,11 @@
10149 Jim_SetResultFormatted(interp,
10150 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
10151 ret < 0 ? "variable isn't" : "no such element in");
10152 }
10153 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10154
10155 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
10156 }
10157
10158 return resObjPtr;
10159 }
@@ -10143,28 +10174,27 @@
10174 {
10175 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr);
10176 Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
10177 }
10178
10179 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
10180 {
10181
10182 dupPtr->internalRep = srcPtr->internalRep;
10183
10184 Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr);
10185 Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
 
10186 }
10187
10188
10189 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10190 {
10191 if (objPtr->typePtr != &dictSubstObjType) {
10192 Jim_Obj *varObjPtr, *keyObjPtr;
10193
10194 if (objPtr->typePtr == &interpolatedObjType) {
10195
10196
10197 varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
10198 keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
10199
10200 Jim_IncrRefCount(varObjPtr);
@@ -10202,16 +10232,12 @@
10232 return resObjPtr;
10233 }
10234
10235 static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
10236 {
10237 if (Jim_EvalExpression(interp, objPtr) == JIM_OK) {
10238 return Jim_GetResult(interp);
 
 
 
 
10239 }
10240 return NULL;
10241 }
10242
10243
@@ -10249,11 +10275,11 @@
10275 return cf;
10276 }
10277
10278 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10279 {
10280
10281 if (localCommands) {
10282 Jim_Obj *cmdNameObj;
10283
10284 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10285 Jim_HashEntry *he;
@@ -10268,20 +10294,20 @@
10294 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10295 if (cmd->prevCmd) {
10296 Jim_Cmd *prevCmd = cmd->prevCmd;
10297 cmd->prevCmd = NULL;
10298
10299
10300 JimDecrCmdRefCount(interp, cmd);
10301
10302
10303 Jim_SetHashVal(ht, he, prevCmd);
10304 }
10305 else {
10306 Jim_DeleteHashEntry(ht, fqname);
 
10307 }
10308 Jim_InterpIncrProcEpoch(interp);
10309 }
10310 Jim_DecrRefCount(interp, cmdNameObj);
10311 JimFreeQualifiedName(interp, fqObjName);
10312 }
10313 Jim_FreeStack(localCommands);
@@ -10288,13 +10314,59 @@
10314 Jim_Free(localCommands);
10315 }
10316 return JIM_OK;
10317 }
10318
10319 static int JimInvokeDefer(Jim_Interp *interp, int retcode)
10320 {
10321 Jim_Obj *objPtr;
10322
10323
10324 if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) {
10325 return retcode;
10326 }
10327
10328 objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE);
10329
10330 if (objPtr) {
10331 int ret = JIM_OK;
10332 int i;
10333 int listLen = Jim_ListLength(interp, objPtr);
10334 Jim_Obj *resultObjPtr;
10335
10336 Jim_IncrRefCount(objPtr);
10337
10338 resultObjPtr = Jim_GetResult(interp);
10339 Jim_IncrRefCount(resultObjPtr);
10340 Jim_SetEmptyResult(interp);
10341
10342
10343 for (i = listLen; i > 0; i--) {
10344
10345 Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1);
10346 ret = Jim_EvalObj(interp, scriptObjPtr);
10347 if (ret != JIM_OK) {
10348 break;
10349 }
10350 }
10351
10352 if (ret == JIM_OK || retcode == JIM_ERR) {
10353
10354 Jim_SetResult(interp, resultObjPtr);
10355 }
10356 else {
10357 retcode = ret;
10358 }
10359
10360 Jim_DecrRefCount(interp, resultObjPtr);
10361 Jim_DecrRefCount(interp, objPtr);
10362 }
10363 return retcode;
10364 }
10365
10366 #define JIM_FCF_FULL 0
10367 #define JIM_FCF_REUSE 1
10368 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10369 {
10370 JimDeleteLocalProcs(interp, cf->localCommands);
10371
10372 if (cf->procArgsObjPtr)
@@ -10327,263 +10399,10 @@
10399 cf->next = interp->freeFramesList;
10400 interp->freeFramesList = cf;
10401 }
10402
10403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10404
10405 int Jim_IsBigEndian(void)
10406 {
10407 union {
10408 unsigned short s;
@@ -10630,11 +10449,11 @@
10449 Jim_IncrRefCount(i->nullScriptObj);
10450 Jim_IncrRefCount(i->errorProc);
10451 Jim_IncrRefCount(i->trueObj);
10452 Jim_IncrRefCount(i->falseObj);
10453
10454
10455 Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
10456 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10457
10458 Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
10459 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,12 +10471,14 @@
10471 {
10472 Jim_CallFrame *cf, *cfx;
10473
10474 Jim_Obj *objPtr, *nextObjPtr;
10475
10476
10477 for (cf = i->framePtr; cf; cf = cfx) {
10478
10479 JimInvokeDefer(i, JIM_OK);
10480 cfx = cf->parent;
10481 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10482 }
10483
10484 Jim_DecrRefCount(i, i->emptyObj);
@@ -10684,10 +10505,11 @@
10505
10506 printf("\n-------------------------------------\n");
10507 printf("Objects still in the free list:\n");
10508 while (objPtr) {
10509 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10510 Jim_String(objPtr);
10511
10512 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10513 printf("%p (%d) %-10s: '%.20s...'\n",
10514 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10515 }
@@ -10705,27 +10527,27 @@
10527 printf("-------------------------------------\n\n");
10528 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10529 }
10530 #endif
10531
10532
10533 objPtr = i->freeList;
10534 while (objPtr) {
10535 nextObjPtr = objPtr->nextObjPtr;
10536 Jim_Free(objPtr);
10537 objPtr = nextObjPtr;
10538 }
10539
10540
10541 for (cf = i->freeFramesList; cf; cf = cfx) {
10542 cfx = cf->next;
10543 if (cf->vars.table)
10544 Jim_FreeHashTable(&cf->vars);
10545 Jim_Free(cf);
10546 }
10547
10548
10549 Jim_Free(i);
10550 }
10551
10552 Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
10553 {
@@ -10746,25 +10568,25 @@
10568 else {
10569 if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
10570 level = -1;
10571 }
10572 else {
10573
10574 level = interp->framePtr->level - level;
10575 }
10576 }
10577 }
10578 else {
10579 str = "1";
10580 level = interp->framePtr->level - 1;
10581 }
10582
10583 if (level == 0) {
10584 return interp->topFramePtr;
10585 }
10586 if (level > 0) {
10587
10588 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10589 if (framePtr->level == level) {
10590 return framePtr;
10591 }
10592 }
@@ -10779,19 +10601,19 @@
10601 long level;
10602 Jim_CallFrame *framePtr;
10603
10604 if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
10605 if (level <= 0) {
10606
10607 level = interp->framePtr->level + level;
10608 }
10609
10610 if (level == 0) {
10611 return interp->topFramePtr;
10612 }
10613
10614
10615 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10616 if (framePtr->level == level) {
10617 return framePtr;
10618 }
10619 }
@@ -10810,11 +10632,11 @@
10632
10633 static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
10634 {
10635 int len;
10636
10637
10638 Jim_IncrRefCount(stackTraceObj);
10639 Jim_DecrRefCount(interp, interp->stackTrace);
10640 interp->stackTrace = stackTraceObj;
10641 interp->errorFlag = 1;
10642
@@ -10831,32 +10653,32 @@
10653 {
10654 if (strcmp(procname, "unknown") == 0) {
10655 procname = "";
10656 }
10657 if (!*procname && !Jim_Length(fileNameObj)) {
10658
10659 return;
10660 }
10661
10662 if (Jim_IsShared(interp->stackTrace)) {
10663 Jim_DecrRefCount(interp, interp->stackTrace);
10664 interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
10665 Jim_IncrRefCount(interp->stackTrace);
10666 }
10667
10668
10669 if (!*procname && Jim_Length(fileNameObj)) {
10670
10671 int len = Jim_ListLength(interp, interp->stackTrace);
10672
10673 if (len >= 3) {
10674 Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10675 if (Jim_Length(objPtr)) {
10676
10677 objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10678 if (Jim_Length(objPtr) == 0) {
10679
10680 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10681 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10682 return;
10683 }
10684 }
@@ -10958,18 +10780,18 @@
10780 {
10781 jim_wide wideValue;
10782 const char *str;
10783
10784 if (objPtr->typePtr == &coercedDoubleObjType) {
10785
10786 objPtr->typePtr = &intObjType;
10787 return JIM_OK;
10788 }
10789
10790
10791 str = Jim_String(objPtr);
10792
10793 if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
10794 if (flags & JIM_ERRMSG) {
10795 Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
10796 }
10797 return JIM_ERR;
@@ -10976,11 +10798,11 @@
10798 }
10799 if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
10800 Jim_SetResultString(interp, "Integer value too big to be represented", -1);
10801 return JIM_ERR;
10802 }
10803
10804 Jim_FreeIntRep(interp, objPtr);
10805 objPtr->typePtr = &intObjType;
10806 objPtr->internalRep.wideValue = wideValue;
10807 return JIM_OK;
10808 }
@@ -11075,17 +10897,17 @@
10897 {
10898 char buf[JIM_DOUBLE_SPACE + 1];
10899 int i;
10900 int len = sprintf(buf, "%.12g", value);
10901
10902
10903 for (i = 0; i < len; i++) {
10904 if (buf[i] == '.' || buf[i] == 'e') {
10905 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10906 char *e = strchr(buf, 'e');
10907 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10908
10909 e += 2;
10910 memmove(e, e + 1, len - (e - buf));
10911 }
10912 #endif
10913 break;
@@ -11104,41 +10926,40 @@
10926 {
10927 double doubleValue;
10928 jim_wide wideValue;
10929 const char *str;
10930
 
 
10931 #ifdef HAVE_LONG_LONG
10932
10933 #define MIN_INT_IN_DOUBLE -(1LL << 53)
10934 #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
10935
10936 if (objPtr->typePtr == &intObjType
10937 && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
10938 && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
10939
10940
10941 objPtr->typePtr = &coercedDoubleObjType;
10942 return JIM_OK;
10943 }
 
10944 #endif
10945 str = Jim_String(objPtr);
10946
10947 if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
10948
10949 Jim_FreeIntRep(interp, objPtr);
10950 objPtr->typePtr = &coercedDoubleObjType;
10951 objPtr->internalRep.wideValue = wideValue;
10952 return JIM_OK;
10953 }
10954 else {
10955
10956 if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
10957 Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
10958 return JIM_ERR;
10959 }
10960
10961 Jim_FreeIntRep(interp, objPtr);
10962 }
10963 objPtr->typePtr = &doubleObjType;
10964 objPtr->internalRep.doubleValue = doubleValue;
10965 return JIM_OK;
@@ -11170,10 +10991,50 @@
10991 objPtr->typePtr = &doubleObjType;
10992 objPtr->bytes = NULL;
10993 objPtr->internalRep.doubleValue = doubleValue;
10994 return objPtr;
10995 }
10996
10997 static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10998
10999 int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr)
11000 {
11001 if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR)
11002 return JIM_ERR;
11003 *booleanPtr = (int) JimWideValue(objPtr);
11004 return JIM_OK;
11005 }
11006
11007 static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
11008 {
11009 static const char * const falses[] = {
11010 "0", "false", "no", "off", NULL
11011 };
11012 static const char * const trues[] = {
11013 "1", "true", "yes", "on", NULL
11014 };
11015
11016 int boolean;
11017
11018 int index;
11019 if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) {
11020 boolean = 0;
11021 } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) {
11022 boolean = 1;
11023 } else {
11024 if (flags & JIM_ERRMSG) {
11025 Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr);
11026 }
11027 return JIM_ERR;
11028 }
11029
11030
11031 Jim_FreeIntRep(interp, objPtr);
11032 objPtr->typePtr = &intObjType;
11033 objPtr->internalRep.wideValue = boolean;
11034 return JIM_OK;
11035 }
11036
11037 static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
11038 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
11039 static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
11040 static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11082,11 @@
11082 #define JIM_ELESTR_QUOTE 2
11083 static unsigned char ListElementQuotingType(const char *s, int len)
11084 {
11085 int i, level, blevel, trySimple = 1;
11086
11087
11088 if (len == 0)
11089 return JIM_ELESTR_BRACE;
11090 if (s[0] == '"' || s[0] == '{') {
11091 trySimple = 0;
11092 goto testbrace;
@@ -11243,20 +11104,20 @@
11104 case '\n':
11105 case '\t':
11106 case '\f':
11107 case '\v':
11108 trySimple = 0;
11109
11110 case '{':
11111 case '}':
11112 goto testbrace;
11113 }
11114 }
11115 return JIM_ELESTR_SIMPLE;
11116
11117 testbrace:
11118
11119 if (s[len - 1] == '\\')
11120 return JIM_ELESTR_QUOTE;
11121 level = 0;
11122 blevel = 0;
11123 for (i = 0; i < len; i++) {
@@ -11372,11 +11233,11 @@
11233 int i, bufLen, realLength;
11234 const char *strRep;
11235 char *p;
11236 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
11237
11238
11239 if (objc > STATIC_QUOTING_LEN) {
11240 quotingType = Jim_Alloc(objc);
11241 }
11242 else {
11243 quotingType = staticQuoting;
@@ -11391,25 +11252,25 @@
11252 case JIM_ELESTR_SIMPLE:
11253 if (i != 0 || strRep[0] != '#') {
11254 bufLen += len;
11255 break;
11256 }
11257
11258 quotingType[i] = JIM_ELESTR_BRACE;
11259
11260 case JIM_ELESTR_BRACE:
11261 bufLen += len + 2;
11262 break;
11263 case JIM_ELESTR_QUOTE:
11264 bufLen += len * 2;
11265 break;
11266 }
11267 bufLen++;
11268 }
11269 bufLen++;
11270
11271
11272 p = objPtr->bytes = Jim_Alloc(bufLen + 1);
11273 realLength = 0;
11274 for (i = 0; i < objc; i++) {
11275 int len, qlen;
11276
@@ -11436,17 +11297,17 @@
11297 qlen = BackslashQuoteString(strRep, len, p);
11298 p += qlen;
11299 realLength += qlen;
11300 break;
11301 }
11302
11303 if (i + 1 != objc) {
11304 *p++ = ' ';
11305 realLength++;
11306 }
11307 }
11308 *p = '\0';
11309 objPtr->length = realLength;
11310
11311 if (quotingType != staticQuoting) {
11312 Jim_Free(quotingType);
11313 }
@@ -11477,21 +11338,21 @@
11338 listObjPtrPtr = JimDictPairs(objPtr, &len);
11339 for (i = 0; i < len; i++) {
11340 Jim_IncrRefCount(listObjPtrPtr[i]);
11341 }
11342
11343
11344 Jim_FreeIntRep(interp, objPtr);
11345 objPtr->typePtr = &listObjType;
11346 objPtr->internalRep.listValue.len = len;
11347 objPtr->internalRep.listValue.maxLen = len;
11348 objPtr->internalRep.listValue.ele = listObjPtrPtr;
11349
11350 return JIM_OK;
11351 }
11352
11353
11354 if (objPtr->typePtr == &sourceObjType) {
11355 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
11356 linenr = objPtr->internalRep.sourceValue.lineNumber;
11357 }
11358 else {
@@ -11498,20 +11359,20 @@
11359 fileNameObj = interp->emptyObj;
11360 linenr = 1;
11361 }
11362 Jim_IncrRefCount(fileNameObj);
11363
11364
11365 str = Jim_GetString(objPtr, &strLen);
11366
11367 Jim_FreeIntRep(interp, objPtr);
11368 objPtr->typePtr = &listObjType;
11369 objPtr->internalRep.listValue.len = 0;
11370 objPtr->internalRep.listValue.maxLen = 0;
11371 objPtr->internalRep.listValue.ele = NULL;
11372
11373
11374 if (strLen) {
11375 JimParserInit(&parser, str, strLen, linenr);
11376 while (!parser.eof) {
11377 Jim_Obj *elementPtr;
11378
@@ -11641,11 +11502,11 @@
11502 Jim_Obj *compare_script;
11503 int rc;
11504
11505 jim_wide ret = 0;
11506
11507
11508 compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
11509 Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
11510 Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
11511
11512 rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11524,27 @@
11524 int dst = 0;
11525 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11526
11527 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11528 if (comp(&ele[dst], &ele[src]) == 0) {
11529
11530 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11531 }
11532 else {
11533
11534 dst++;
11535 }
11536 ele[dst] = ele[src];
11537 }
 
 
11538
11539
11540 dst++;
11541 if (dst < listObjPtr->internalRep.listValue.len) {
11542 ele[dst] = ele[src];
11543 }
11544
11545
11546 listObjPtr->internalRep.listValue.len = dst;
11547 }
11548
11549
11550 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11558,11 @@
11558 int rc;
11559
11560 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11561 SetListFromAny(interp, listObjPtr);
11562
11563
11564 prev_info = sort_info;
11565 sort_info = info;
11566
11567 vector = listObjPtr->internalRep.listValue.ele;
11568 len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11581,17 @@
11581 break;
11582 case JIM_LSORT_COMMAND:
11583 fn = ListSortCommand;
11584 break;
11585 default:
11586 fn = NULL;
11587 JimPanic((1, "ListSort called with invalid sort type"));
11588 return -1;
11589 }
11590
11591 if (info->indexed) {
11592
11593 info->subfn = fn;
11594 fn = ListSortIndexHelper;
11595 }
11596
11597 if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11615,11 @@
11615 int i;
11616 Jim_Obj **point;
11617
11618 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11619 if (requiredLen < 2) {
11620
11621 requiredLen = 4;
11622 }
11623 else {
11624 requiredLen *= 2;
11625 }
@@ -11936,34 +11801,34 @@
11801 for (i = 0; i < objc; i++)
11802 ListAppendList(objPtr, objv[i]);
11803 return objPtr;
11804 }
11805 else {
11806
11807 int len = 0, objLen;
11808 char *bytes, *p;
11809
11810
11811 for (i = 0; i < objc; i++) {
11812 len += Jim_Length(objv[i]);
11813 }
11814 if (objc)
11815 len += objc - 1;
11816
11817 p = bytes = Jim_Alloc(len + 1);
11818 for (i = 0; i < objc; i++) {
11819 const char *s = Jim_GetString(objv[i], &objLen);
11820
11821
11822 while (objLen && isspace(UCHAR(*s))) {
11823 s++;
11824 objLen--;
11825 len--;
11826 }
11827
11828 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11829
11830 if (objLen > 1 && s[objLen - 2] == '\\') {
11831 break;
11832 }
11833 objLen--;
11834 len--;
@@ -11990,11 +11855,11 @@
11855 int len, rangeLen;
11856
11857 if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
11858 Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
11859 return NULL;
11860 len = Jim_ListLength(interp, listObjPtr);
11861 first = JimRelToAbsIndex(len, first);
11862 last = JimRelToAbsIndex(len, last);
11863 JimRelToAbsRange(len, &first, &last, &rangeLen);
11864 if (first == 0 && last == len) {
11865 return listObjPtr;
@@ -12030,16 +11895,16 @@
11895 {
11896 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11897 }
11898
11899 static const Jim_HashTableType JimDictHashTableType = {
11900 JimObjectHTHashFunction,
11901 JimObjectHTKeyValDup,
11902 JimObjectHTKeyValDup,
11903 JimObjectHTKeyCompare,
11904 JimObjectHTKeyValDestructor,
11905 JimObjectHTKeyValDestructor
11906 };
11907
11908 static const Jim_ObjType dictObjType = {
11909 "dict",
11910 FreeDictInternalRep,
@@ -12060,17 +11925,17 @@
11925 {
11926 Jim_HashTable *ht, *dupHt;
11927 Jim_HashTableIterator htiter;
11928 Jim_HashEntry *he;
11929
11930
11931 ht = srcPtr->internalRep.ptr;
11932 dupHt = Jim_Alloc(sizeof(*dupHt));
11933 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11934 if (ht->size != 0)
11935 Jim_ExpandHashTable(dupHt, ht->size);
11936
11937 JimInitHashTableIterator(ht, &htiter);
11938 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11939 Jim_AddHashEntry(dupHt, he->key, he->u.val);
11940 }
11941
@@ -12086,11 +11951,11 @@
11951 Jim_Obj **objv;
11952 int i;
11953
11954 ht = dictPtr->internalRep.ptr;
11955
11956
11957 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11958 JimInitHashTableIterator(ht, &htiter);
11959 i = 0;
11960 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11961 objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11965,15 @@
11965 return objv;
11966 }
11967
11968 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11969 {
11970
11971 int len;
11972 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11973
11974
11975 JimMakeListStringRep(objPtr, objv, len);
11976
11977 Jim_Free(objv);
11978 }
11979
@@ -12122,18 +11987,18 @@
11987
11988 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11989 Jim_String(objPtr);
11990 }
11991
11992
11993 listlen = Jim_ListLength(interp, objPtr);
11994 if (listlen % 2) {
11995 Jim_SetResultString(interp, "missing value to go with key", -1);
11996 return JIM_ERR;
11997 }
11998 else {
11999
12000 Jim_HashTable *ht;
12001 int i;
12002
12003 ht = Jim_Alloc(sizeof(*ht));
12004 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12023,11 @@
12023 static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
12024 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
12025 {
12026 Jim_HashTable *ht = objPtr->internalRep.ptr;
12027
12028 if (valueObjPtr == NULL) {
12029 return Jim_DeleteHashEntry(ht, keyObjPtr);
12030 }
12031 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
12032 return JIM_OK;
12033 }
@@ -12209,12 +12074,14 @@
12074 if (flags & JIM_ERRMSG) {
12075 Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
12076 }
12077 return JIM_ERR;
12078 }
12079 else {
12080 *objPtrPtr = Jim_GetHashEntryVal(he);
12081 return JIM_OK;
12082 }
12083 }
12084
12085
12086 int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
12087 {
@@ -12258,11 +12125,11 @@
12125 int shared, i;
12126
12127 varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
12128 if (objPtr == NULL) {
12129 if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12130
12131 return JIM_ERR;
12132 }
12133 varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
12134 if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
12135 Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12139,26 @@
12139 if ((shared = Jim_IsShared(objPtr)))
12140 varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
12141 for (i = 0; i < keyc; i++) {
12142 dictObjPtr = objPtr;
12143
12144
12145 if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
12146 goto err;
12147 }
12148
12149 if (i == keyc - 1) {
12150
12151 if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
12152 if (newObjPtr || (flags & JIM_MUSTEXIST)) {
12153 goto err;
12154 }
12155 }
12156 break;
12157 }
12158
12159
12160 Jim_InvalidateStringRep(dictObjPtr);
12161 if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
12162 newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
12163 if (Jim_IsShared(objPtr)) {
12164 objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12171,11 @@
12171 }
12172 objPtr = Jim_NewDictObj(interp, NULL, 0);
12173 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12174 }
12175 }
12176
12177 Jim_InvalidateStringRep(objPtr);
12178 Jim_InvalidateStringRep(varObjPtr);
12179 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12180 goto err;
12181 }
@@ -12341,11 +12208,11 @@
12208 char buf[JIM_INTEGER_SPACE + 1];
12209 if (objPtr->internalRep.intValue >= 0) {
12210 sprintf(buf, "%d", objPtr->internalRep.intValue);
12211 }
12212 else {
12213
12214 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12215 }
12216 JimSetStringBytes(objPtr, buf);
12217 }
12218 }
@@ -12354,14 +12221,14 @@
12221 {
12222 int idx, end = 0;
12223 const char *str;
12224 char *endptr;
12225
12226
12227 str = Jim_String(objPtr);
12228
12229
12230 if (strncmp(str, "end", 3) == 0) {
12231 end = 1;
12232 str += 3;
12233 idx = 0;
12234 }
@@ -12372,21 +12239,21 @@
12239 goto badindex;
12240 }
12241 str = endptr;
12242 }
12243
12244
12245 if (*str == '+' || *str == '-') {
12246 int sign = (*str == '+' ? 1 : -1);
12247
12248 idx += sign * jim_strtol(++str, &endptr);
12249 if (str == endptr || *endptr) {
12250 goto badindex;
12251 }
12252 str = endptr;
12253 }
12254
12255 while (isspace(UCHAR(*str))) {
12256 str++;
12257 }
12258 if (*str) {
12259 goto badindex;
@@ -12394,19 +12261,19 @@
12261 if (end) {
12262 if (idx > 0) {
12263 idx = INT_MAX;
12264 }
12265 else {
12266
12267 idx--;
12268 }
12269 }
12270 else if (idx < 0) {
12271 idx = -INT_MAX;
12272 }
12273
12274
12275 Jim_FreeIntRep(interp, objPtr);
12276 objPtr->typePtr = &indexObjType;
12277 objPtr->internalRep.intValue = idx;
12278 return JIM_OK;
12279
@@ -12416,11 +12283,11 @@
12283 return JIM_ERR;
12284 }
12285
12286 int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
12287 {
12288
12289 if (objPtr->typePtr == &intObjType) {
12290 jim_wide val = JimWideValue(objPtr);
12291
12292 if (val < 0)
12293 *indexPtr = -INT_MAX;
@@ -12448,11 +12315,11 @@
12315 "exit",
12316 "eval",
12317 NULL
12318 };
12319
12320 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1)
12321
12322 static const Jim_ObjType returnCodeObjType = {
12323 "return-code",
12324 NULL,
12325 NULL,
@@ -12473,18 +12340,18 @@
12340 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12341 {
12342 int returnCode;
12343 jim_wide wideValue;
12344
12345
12346 if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
12347 returnCode = (int)wideValue;
12348 else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
12349 Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
12350 return JIM_ERR;
12351 }
12352
12353 Jim_FreeIntRep(interp, objPtr);
12354 objPtr->typePtr = &returnCodeObjType;
12355 objPtr->internalRep.intValue = returnCode;
12356 return JIM_OK;
12357 }
@@ -12498,19 +12365,19 @@
12365 }
12366
12367 static int JimParseExprOperator(struct JimParserCtx *pc);
12368 static int JimParseExprNumber(struct JimParserCtx *pc);
12369 static int JimParseExprIrrational(struct JimParserCtx *pc);
12370 static int JimParseExprBoolean(struct JimParserCtx *pc);
 
12371
12372
12373 enum
12374 {
12375
12376
12377
12378 JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
12379 JIM_EXPROP_DIV,
12380 JIM_EXPROP_MOD,
12381 JIM_EXPROP_SUB,
12382 JIM_EXPROP_ADD,
12383 JIM_EXPROP_LSHIFT,
@@ -12521,66 +12388,48 @@
12388 JIM_EXPROP_GT,
12389 JIM_EXPROP_LTE,
12390 JIM_EXPROP_GTE,
12391 JIM_EXPROP_NUMEQ,
12392 JIM_EXPROP_NUMNE,
12393 JIM_EXPROP_BITAND,
12394 JIM_EXPROP_BITXOR,
12395 JIM_EXPROP_BITOR,
12396 JIM_EXPROP_LOGICAND,
12397 JIM_EXPROP_LOGICOR,
12398 JIM_EXPROP_TERNARY,
12399 JIM_EXPROP_COLON,
12400 JIM_EXPROP_POW,
12401
12402
12403 JIM_EXPROP_STREQ,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12404 JIM_EXPROP_STRNE,
12405 JIM_EXPROP_STRIN,
12406 JIM_EXPROP_STRNI,
12407
12408
12409 JIM_EXPROP_NOT,
12410 JIM_EXPROP_BITNOT,
12411 JIM_EXPROP_UNARYMINUS,
12412 JIM_EXPROP_UNARYPLUS,
12413
12414
12415 JIM_EXPROP_FUNC_INT,
 
12416 JIM_EXPROP_FUNC_WIDE,
12417 JIM_EXPROP_FUNC_ABS,
12418 JIM_EXPROP_FUNC_DOUBLE,
12419 JIM_EXPROP_FUNC_ROUND,
12420 JIM_EXPROP_FUNC_RAND,
12421 JIM_EXPROP_FUNC_SRAND,
12422
12423
12424 JIM_EXPROP_FUNC_SIN,
12425 JIM_EXPROP_FUNC_COS,
12426 JIM_EXPROP_FUNC_TAN,
12427 JIM_EXPROP_FUNC_ASIN,
12428 JIM_EXPROP_FUNC_ACOS,
12429 JIM_EXPROP_FUNC_ATAN,
12430 JIM_EXPROP_FUNC_ATAN2,
12431 JIM_EXPROP_FUNC_SINH,
12432 JIM_EXPROP_FUNC_COSH,
12433 JIM_EXPROP_FUNC_TANH,
12434 JIM_EXPROP_FUNC_CEIL,
12435 JIM_EXPROP_FUNC_FLOOR,
@@ -12587,52 +12436,52 @@
12436 JIM_EXPROP_FUNC_EXP,
12437 JIM_EXPROP_FUNC_LOG,
12438 JIM_EXPROP_FUNC_LOG10,
12439 JIM_EXPROP_FUNC_SQRT,
12440 JIM_EXPROP_FUNC_POW,
12441 JIM_EXPROP_FUNC_HYPOT,
12442 JIM_EXPROP_FUNC_FMOD,
12443 };
12444
12445 struct JimExprNode {
12446 int type;
12447 struct Jim_Obj *objPtr;
12448
12449 struct JimExprNode *left;
12450 struct JimExprNode *right;
12451 struct JimExprNode *ternary;
12452 };
12453
12454
12455 typedef struct Jim_ExprOperator
12456 {
12457 const char *name;
12458 int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode);
12459 unsigned char precedence;
12460 unsigned char arity;
12461 unsigned char attr;
12462 unsigned char namelen;
12463 } Jim_ExprOperator;
12464
12465 static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr);
12466 static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node);
12467 static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node);
12468
12469 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
 
 
 
 
 
 
 
12470 {
12471 int intresult = 1;
12472 int rc;
 
12473 double dA, dC = 0;
12474 jim_wide wA, wC = 0;
12475 Jim_Obj *A;
12476
12477 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12478 return rc;
12479 }
12480
12481 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12482 switch (node->type) {
12483 case JIM_EXPROP_FUNC_INT:
12484 case JIM_EXPROP_FUNC_WIDE:
12485 case JIM_EXPROP_FUNC_ROUND:
12486 case JIM_EXPROP_UNARYPLUS:
12487 wC = wA;
@@ -12653,11 +12502,11 @@
12502 default:
12503 abort();
12504 }
12505 }
12506 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12507 switch (node->type) {
12508 case JIM_EXPROP_FUNC_INT:
12509 case JIM_EXPROP_FUNC_WIDE:
12510 wC = dA;
12511 break;
12512 case JIM_EXPROP_FUNC_ROUND:
@@ -12667,11 +12516,15 @@
12516 case JIM_EXPROP_UNARYPLUS:
12517 dC = dA;
12518 intresult = 0;
12519 break;
12520 case JIM_EXPROP_FUNC_ABS:
12521 #ifdef JIM_MATH_FUNCTIONS
12522 dC = fabs(dA);
12523 #else
12524 dC = dA >= 0 ? dA : -dA;
12525 #endif
12526 intresult = 0;
12527 break;
12528 case JIM_EXPROP_UNARYMINUS:
12529 dC = -dA;
12530 intresult = 0;
@@ -12684,14 +12537,14 @@
12537 }
12538 }
12539
12540 if (rc == JIM_OK) {
12541 if (intresult) {
12542 Jim_SetResultInt(interp, wC);
12543 }
12544 else {
12545 Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
12546 }
12547 }
12548
12549 Jim_DecrRefCount(interp, A);
12550
@@ -12704,24 +12557,29 @@
12557 JimRandomBytes(interp, &x, sizeof(x));
12558
12559 return (double)x / (unsigned long)~0;
12560 }
12561
12562 static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node)
12563 {
 
12564 jim_wide wA;
12565 Jim_Obj *A;
12566 int rc;
12567
12568 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12569 return rc;
12570 }
12571
12572 rc = Jim_GetWide(interp, A, &wA);
12573 if (rc == JIM_OK) {
12574 switch (node->type) {
12575 case JIM_EXPROP_BITNOT:
12576 Jim_SetResultInt(interp, ~wA);
12577 break;
12578 case JIM_EXPROP_FUNC_SRAND:
12579 JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
12580 Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12581 break;
12582 default:
12583 abort();
12584 }
12585 }
@@ -12729,29 +12587,33 @@
12587 Jim_DecrRefCount(interp, A);
12588
12589 return rc;
12590 }
12591
12592 static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node)
12593 {
12594 JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
12595
12596 Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
12597
12598 return JIM_OK;
12599 }
12600
12601 #ifdef JIM_MATH_FUNCTIONS
12602 static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node)
12603 {
12604 int rc;
 
12605 double dA, dC;
12606 Jim_Obj *A;
12607
12608 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12609 return rc;
12610 }
12611
12612 rc = Jim_GetDouble(interp, A, &dA);
12613 if (rc == JIM_OK) {
12614 switch (node->type) {
12615 case JIM_EXPROP_FUNC_SIN:
12616 dC = sin(dA);
12617 break;
12618 case JIM_EXPROP_FUNC_COS:
12619 dC = cos(dA);
@@ -12796,33 +12658,42 @@
12658 dC = sqrt(dA);
12659 break;
12660 default:
12661 abort();
12662 }
12663 Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
12664 }
12665
12666 Jim_DecrRefCount(interp, A);
12667
12668 return rc;
12669 }
12670 #endif
12671
12672
12673 static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node)
12674 {
 
 
12675 jim_wide wA, wB;
12676 int rc;
12677 Jim_Obj *A, *B;
12678
12679 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12680 return rc;
12681 }
12682 if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12683 Jim_DecrRefCount(interp, A);
12684 return rc;
12685 }
12686
12687 rc = JIM_ERR;
12688
12689 if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) {
12690 jim_wide wC;
12691
12692 rc = JIM_OK;
12693
12694 switch (node->type) {
12695 case JIM_EXPROP_LSHIFT:
12696 wC = wA << wB;
12697 break;
12698 case JIM_EXPROP_RSHIFT:
12699 wC = wA >> wB;
@@ -12859,29 +12730,28 @@
12730 }
12731 }
12732 break;
12733 case JIM_EXPROP_ROTL:
12734 case JIM_EXPROP_ROTR:{
12735
12736 unsigned long uA = (unsigned long)wA;
12737 unsigned long uB = (unsigned long)wB;
12738 const unsigned int S = sizeof(unsigned long) * 8;
12739
12740
12741 uB %= S;
12742
12743 if (node->type == JIM_EXPROP_ROTR) {
12744 uB = S - uB;
12745 }
12746 wC = (unsigned long)(uA << uB) | (uA >> (S - uB));
12747 break;
12748 }
12749 default:
12750 abort();
12751 }
12752 Jim_SetResultInt(interp, wC);
 
12753 }
12754
12755 Jim_DecrRefCount(interp, A);
12756 Jim_DecrRefCount(interp, B);
12757
@@ -12888,44 +12758,55 @@
12758 return rc;
12759 }
12760
12761
12762
12763 static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node)
12764 {
 
12765 int rc = JIM_OK;
12766 double dA, dB, dC = 0;
12767 jim_wide wA, wB, wC = 0;
12768 Jim_Obj *A, *B;
12769
12770 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12771 return rc;
12772 }
12773 if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12774 Jim_DecrRefCount(interp, A);
12775 return rc;
12776 }
12777
12778 if ((A->typePtr != &doubleObjType || A->bytes) &&
12779 (B->typePtr != &doubleObjType || B->bytes) &&
12780 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12781
 
12782
12783
12784 switch (node->type) {
12785 case JIM_EXPROP_POW:
12786 case JIM_EXPROP_FUNC_POW:
12787 if (wA == 0 && wB < 0) {
12788 Jim_SetResultString(interp, "exponentiation of zero by negative power", -1);
12789 rc = JIM_ERR;
12790 goto done;
12791 }
12792 wC = JimPowWide(wA, wB);
12793 goto intresult;
12794 case JIM_EXPROP_ADD:
12795 wC = wA + wB;
12796 goto intresult;
12797 case JIM_EXPROP_SUB:
12798 wC = wA - wB;
12799 goto intresult;
12800 case JIM_EXPROP_MUL:
12801 wC = wA * wB;
12802 goto intresult;
12803 case JIM_EXPROP_DIV:
12804 if (wB == 0) {
12805 Jim_SetResultString(interp, "Division by zero", -1);
12806 rc = JIM_ERR;
12807 goto done;
12808 }
12809 else {
12810 if (wB < 0) {
12811 wB = -wB;
12812 wA = -wA;
@@ -12932,55 +12813,67 @@
12813 }
12814 wC = wA / wB;
12815 if (wA % wB < 0) {
12816 wC--;
12817 }
12818 goto intresult;
12819 }
 
12820 case JIM_EXPROP_LT:
12821 wC = wA < wB;
12822 goto intresult;
12823 case JIM_EXPROP_GT:
12824 wC = wA > wB;
12825 goto intresult;
12826 case JIM_EXPROP_LTE:
12827 wC = wA <= wB;
12828 goto intresult;
12829 case JIM_EXPROP_GTE:
12830 wC = wA >= wB;
12831 goto intresult;
12832 case JIM_EXPROP_NUMEQ:
12833 wC = wA == wB;
12834 goto intresult;
12835 case JIM_EXPROP_NUMNE:
12836 wC = wA != wB;
12837 goto intresult;
 
 
12838 }
12839 }
12840 if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12841 switch (node->type) {
12842 #ifndef JIM_MATH_FUNCTIONS
12843 case JIM_EXPROP_POW:
12844 case JIM_EXPROP_FUNC_POW:
12845 case JIM_EXPROP_FUNC_ATAN2:
12846 case JIM_EXPROP_FUNC_HYPOT:
12847 case JIM_EXPROP_FUNC_FMOD:
12848 Jim_SetResultString(interp, "unsupported", -1);
12849 rc = JIM_ERR;
12850 goto done;
12851 #else
12852 case JIM_EXPROP_POW:
12853 case JIM_EXPROP_FUNC_POW:
12854 dC = pow(dA, dB);
12855 goto doubleresult;
12856 case JIM_EXPROP_FUNC_ATAN2:
12857 dC = atan2(dA, dB);
12858 goto doubleresult;
12859 case JIM_EXPROP_FUNC_HYPOT:
12860 dC = hypot(dA, dB);
12861 goto doubleresult;
12862 case JIM_EXPROP_FUNC_FMOD:
12863 dC = fmod(dA, dB);
12864 goto doubleresult;
12865 #endif
 
12866 case JIM_EXPROP_ADD:
12867 dC = dA + dB;
12868 goto doubleresult;
12869 case JIM_EXPROP_SUB:
12870 dC = dA - dB;
12871 goto doubleresult;
12872 case JIM_EXPROP_MUL:
12873 dC = dA * dB;
12874 goto doubleresult;
12875 case JIM_EXPROP_DIV:
12876 if (dB == 0) {
12877 #ifdef INFINITY
12878 dC = dA < 0 ? -INFINITY : INFINITY;
12879 #else
@@ -12988,83 +12881,70 @@
12881 #endif
12882 }
12883 else {
12884 dC = dA / dB;
12885 }
12886 goto doubleresult;
12887 case JIM_EXPROP_LT:
12888 wC = dA < dB;
12889 goto intresult;
 
12890 case JIM_EXPROP_GT:
12891 wC = dA > dB;
12892 goto intresult;
 
12893 case JIM_EXPROP_LTE:
12894 wC = dA <= dB;
12895 goto intresult;
 
12896 case JIM_EXPROP_GTE:
12897 wC = dA >= dB;
12898 goto intresult;
 
12899 case JIM_EXPROP_NUMEQ:
12900 wC = dA == dB;
12901 goto intresult;
 
12902 case JIM_EXPROP_NUMNE:
12903 wC = dA != dB;
12904 goto intresult;
 
 
 
12905 }
12906 }
12907 else {
 
12908
12909
12910
12911 int i = Jim_StringCompareObj(interp, A, B, 0);
12912
12913 switch (node->type) {
12914 case JIM_EXPROP_LT:
12915 wC = i < 0;
12916 goto intresult;
12917 case JIM_EXPROP_GT:
12918 wC = i > 0;
12919 goto intresult;
12920 case JIM_EXPROP_LTE:
12921 wC = i <= 0;
12922 goto intresult;
12923 case JIM_EXPROP_GTE:
12924 wC = i >= 0;
12925 goto intresult;
12926 case JIM_EXPROP_NUMEQ:
12927 wC = i == 0;
12928 goto intresult;
12929 case JIM_EXPROP_NUMNE:
12930 wC = i != 0;
12931 goto intresult;
 
 
 
12932 }
12933 }
12934
12935 rc = JIM_ERR;
12936 done:
 
 
 
 
 
 
 
12937 Jim_DecrRefCount(interp, A);
12938 Jim_DecrRefCount(interp, B);
 
12939 return rc;
12940 intresult:
12941 Jim_SetResultInt(interp, wC);
12942 goto done;
12943 doubleresult:
12944 Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
12945 goto done;
12946 }
12947
12948 static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
12949 {
12950 int listlen;
@@ -13077,22 +12957,31 @@
12957 }
12958 }
12959 return 0;
12960 }
12961
12962
12963
12964 static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
12965 {
12966 Jim_Obj *A, *B;
 
 
12967 jim_wide wC;
12968 int rc;
12969
12970 if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
12971 return rc;
12972 }
12973 if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
12974 Jim_DecrRefCount(interp, A);
12975 return rc;
12976 }
12977
12978 switch (node->type) {
12979 case JIM_EXPROP_STREQ:
12980 case JIM_EXPROP_STRNE:
12981 wC = Jim_StringEqObj(A, B);
12982 if (node->type == JIM_EXPROP_STRNE) {
12983 wC = !wC;
12984 }
12985 break;
12986 case JIM_EXPROP_STRIN:
12987 wC = JimSearchList(interp, B, A);
@@ -13101,178 +12990,99 @@
12990 wC = !JimSearchList(interp, B, A);
12991 break;
12992 default:
12993 abort();
12994 }
12995 Jim_SetResultInt(interp, wC);
12996
12997 Jim_DecrRefCount(interp, A);
12998 Jim_DecrRefCount(interp, B);
12999
13000 return rc;
13001 }
13002
13003 static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
13004 {
13005 long l;
13006 double d;
13007 int b;
13008 int ret = -1;
13009
13010
13011 Jim_IncrRefCount(obj);
13012
13013 if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
13014 ret = (l != 0);
13015 }
13016 else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13017 ret = (d != 0);
13018 }
13019 else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
13020 ret = (b != 0);
13021 }
13022
13023 Jim_DecrRefCount(interp, obj);
13024 return ret;
13025 }
13026
13027 static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node)
13028 {
13029
13030 int result = JimExprGetTermBoolean(interp, node->left);
13031
13032 if (result == 1) {
13033
13034 result = JimExprGetTermBoolean(interp, node->right);
13035 }
13036 if (result == -1) {
13037 return JIM_ERR;
13038 }
13039 Jim_SetResultInt(interp, result);
13040 return JIM_OK;
13041 }
13042
13043 static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node)
13044 {
13045
13046 int result = JimExprGetTermBoolean(interp, node->left);
13047
13048 if (result == 0) {
13049
13050 result = JimExprGetTermBoolean(interp, node->right);
13051 }
13052 if (result == -1) {
13053 return JIM_ERR;
13054 }
13055 Jim_SetResultInt(interp, result);
13056 return JIM_OK;
13057 }
13058
13059 static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node)
13060 {
13061
13062 int result = JimExprGetTermBoolean(interp, node->left);
13063
13064 if (result == 1) {
13065
13066 return JimExprEvalTermNode(interp, node->right);
13067 }
13068 else if (result == 0) {
13069
13070 return JimExprEvalTermNode(interp, node->ternary);
13071 }
13072
13073 return JIM_ERR;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13074 }
13075
13076 enum
13077 {
13078 OP_FUNC = 0x0001,
13079 OP_RIGHT_ASSOC = 0x0002,
 
 
13080 };
13081
13082 #define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1}
13083 #define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0)
13084
13085 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13086 OPRINIT("*", 110, 2, JimExprOpBin),
13087 OPRINIT("/", 110, 2, JimExprOpBin),
13088 OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,86 +13106,79 @@
13106
13107 OPRINIT("&", 50, 2, JimExprOpIntBin),
13108 OPRINIT("^", 49, 2, JimExprOpIntBin),
13109 OPRINIT("|", 48, 2, JimExprOpIntBin),
13110
13111 OPRINIT("&&", 10, 2, JimExprOpAnd),
13112 OPRINIT("||", 9, 2, JimExprOpOr),
13113 OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC),
13114 OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC),
13115
13116
13117 OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC),
 
 
 
 
 
 
 
 
 
 
13118
13119 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13120 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13121
13122 OPRINIT("in", 55, 2, JimExprOpStrBin),
13123 OPRINIT("ni", 55, 2, JimExprOpStrBin),
13124
13125 OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
13126 OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC),
13127 OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
13128 OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
13129
13130
13131
13132 OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC),
13133 OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC),
13134 OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC),
13135 OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC),
13136 OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC),
13137 OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC),
13138 OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC),
13139
13140 #ifdef JIM_MATH_FUNCTIONS
13141 OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13142 OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13143 OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13144 OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13145 OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13146 OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13147 OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC),
13148 OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13149 OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13150 OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13151 OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13152 OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13153 OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13154 OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13155 OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13156 OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
13157 OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC),
13158 OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC),
13159 OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC),
13160 #endif
13161 };
13162 #undef OPRINIT
13163 #undef OPRINIT_ATTR
13164
13165 #define JIM_EXPR_OPERATORS_NUM \
13166 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13167
13168 static int JimParseExpression(struct JimParserCtx *pc)
13169 {
13170
13171 while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
13172 if (*pc->p == '\n') {
13173 pc->linenr++;
13174 }
13175 pc->p++;
13176 pc->len--;
13177 }
13178
13179
13180 pc->tline = pc->linenr;
13181 pc->tstart = pc->p;
13182
13183 if (pc->len == 0) {
13184 pc->tend = pc->p;
@@ -13401,11 +13204,11 @@
13204 return JimParseCmd(pc);
13205 case '$':
13206 if (JimParseVar(pc) == JIM_ERR)
13207 return JimParseExprOperator(pc);
13208 else {
13209
13210 if (pc->tt == JIM_TT_EXPRSUGAR) {
13211 return JIM_ERR;
13212 }
13213 return JIM_OK;
13214 }
@@ -13430,10 +13233,18 @@
13233 case 'N':
13234 case 'I':
13235 case 'n':
13236 case 'i':
13237 if (JimParseExprIrrational(pc) == JIM_ERR)
13238 if (JimParseExprBoolean(pc) == JIM_ERR)
13239 return JimParseExprOperator(pc);
13240 break;
13241 case 't':
13242 case 'f':
13243 case 'o':
13244 case 'y':
13245 if (JimParseExprBoolean(pc) == JIM_ERR)
13246 return JimParseExprOperator(pc);
13247 break;
13248 default:
13249 return JimParseExprOperator(pc);
13250 break;
@@ -13443,21 +13254,21 @@
13254
13255 static int JimParseExprNumber(struct JimParserCtx *pc)
13256 {
13257 char *end;
13258
13259
13260 pc->tt = JIM_TT_EXPR_INT;
13261
13262 jim_strtoull(pc->p, (char **)&pc->p);
13263
13264 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13265 if (strtod(pc->tstart, &end)) { }
13266 if (end == pc->tstart)
13267 return JIM_ERR;
13268 if (end > pc->p) {
13269
13270 pc->tt = JIM_TT_EXPR_DOUBLE;
13271 pc->p = end;
13272 }
13273 }
13274 pc->tend = pc->p - 1;
@@ -13481,36 +13292,66 @@
13292 return JIM_OK;
13293 }
13294 }
13295 return JIM_ERR;
13296 }
13297
13298 static int JimParseExprBoolean(struct JimParserCtx *pc)
13299 {
13300 const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL };
13301 const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 };
13302 int i;
13303
13304 for (i = 0; booleans[i]; i++) {
13305 const char *boolean = booleans[i];
13306 int length = lengths[i];
13307
13308 if (strncmp(boolean, pc->p, length) == 0) {
13309 pc->p += length;
13310 pc->len -= length;
13311 pc->tend = pc->p - 1;
13312 pc->tt = JIM_TT_EXPR_BOOLEAN;
13313 return JIM_OK;
13314 }
13315 }
13316 return JIM_ERR;
13317 }
13318
13319 static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
13320 {
13321 static Jim_ExprOperator dummy_op;
13322 if (opcode < JIM_TT_EXPR_OP) {
13323 return &dummy_op;
13324 }
13325 return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
13326 }
13327
13328 static int JimParseExprOperator(struct JimParserCtx *pc)
13329 {
13330 int i;
13331 const struct Jim_ExprOperator *bestOp = NULL;
13332 int bestLen = 0;
13333
13334
13335 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13336 const struct Jim_ExprOperator *op = &Jim_ExprOperators[i];
 
13337
13338 if (op->name[0] != pc->p[0]) {
13339 continue;
13340 }
13341
13342 if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) {
13343 bestOp = op;
13344 bestLen = op->namelen;
13345 }
13346 }
13347 if (bestOp == NULL) {
13348 return JIM_ERR;
13349 }
13350
13351
13352 if (bestOp->attr & OP_FUNC) {
13353 const char *p = pc->p + bestLen;
13354 int len = pc->len - bestLen;
13355
13356 while (len && isspace(UCHAR(*p))) {
13357 len--;
@@ -13522,30 +13363,27 @@
13363 }
13364 pc->tend = pc->p + bestLen - 1;
13365 pc->p += bestLen;
13366 pc->len -= bestLen;
13367
13368 pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP;
13369 return JIM_OK;
13370 }
13371
 
 
 
 
 
 
 
 
 
13372 const char *jim_tt_name(int type)
13373 {
13374 static const char * const tt_names[JIM_TT_EXPR_OP] =
13375 { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13376 "DBL", "BOO", "$()" };
13377 if (type < JIM_TT_EXPR_OP) {
13378 return tt_names[type];
13379 }
13380 else if (type == JIM_EXPROP_UNARYMINUS) {
13381 return "-VE";
13382 }
13383 else if (type == JIM_EXPROP_UNARYPLUS) {
13384 return "+VE";
13385 }
13386 else {
13387 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
13388 static char buf[20];
13389
@@ -13568,432 +13406,400 @@
13406 NULL,
13407 JIM_TYPE_REFERENCES,
13408 };
13409
13410
13411 struct ExprTree
13412 {
13413 struct JimExprNode *expr;
13414 struct JimExprNode *nodes;
13415 int len;
13416 int inUse;
13417 };
13418
13419 static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num)
13420 {
13421 int i;
13422 for (i = 0; i < num; i++) {
13423 if (nodes[i].objPtr) {
13424 Jim_DecrRefCount(interp, nodes[i].objPtr);
13425 }
13426 }
13427 Jim_Free(nodes);
13428 }
13429
13430 static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr)
13431 {
13432 ExprTreeFreeNodes(interp, expr->nodes, expr->len);
 
13433 Jim_Free(expr);
13434 }
13435
13436 static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
13437 {
13438 struct ExprTree *expr = (void *)objPtr->internalRep.ptr;
13439
13440 if (expr) {
13441 if (--expr->inUse != 0) {
13442 return;
13443 }
13444
13445 ExprTreeFree(interp, expr);
13446 }
13447 }
13448
13449 static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
13450 {
13451 JIM_NOTUSED(interp);
13452 JIM_NOTUSED(srcPtr);
13453
13454
13455 dupPtr->typePtr = NULL;
13456 }
13457
13458 struct ExprBuilder {
13459 int parencount;
13460 int level;
13461 ParseToken *token;
13462 ParseToken *first_token;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13463 Jim_Stack stack;
13464 Jim_Obj *exprObjPtr;
13465 Jim_Obj *fileNameObj;
13466 struct JimExprNode *nodes;
13467 struct JimExprNode *next;
13468 };
13469
13470 #ifdef DEBUG_SHOW_EXPR
13471 static void JimShowExprNode(struct JimExprNode *node, int level)
13472 {
13473 int i;
13474 for (i = 0; i < level; i++) {
13475 printf(" ");
13476 }
13477 if (TOKEN_IS_EXPR_OP(node->type)) {
13478 printf("%s\n", jim_tt_name(node->type));
13479 if (node->left) {
13480 JimShowExprNode(node->left, level + 1);
13481 }
13482 if (node->right) {
13483 JimShowExprNode(node->right, level + 1);
13484 }
13485 if (node->ternary) {
13486 JimShowExprNode(node->ternary, level + 1);
13487 }
13488 }
13489 else {
13490 printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr));
13491 }
13492 }
13493 #endif
13494
13495 #define EXPR_UNTIL_CLOSE 0x0001
13496 #define EXPR_FUNC_ARGS 0x0002
13497 #define EXPR_TERNARY 0x0004
13498
13499 static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms)
13500 {
13501 int rc;
13502 struct JimExprNode *node;
13503
13504 int exp_stacklen = builder->stack.len + exp_numterms;
13505
13506 if (builder->level++ > 200) {
13507 Jim_SetResultString(interp, "Expression too complex", -1);
13508 return JIM_ERR;
13509 }
13510
13511 while (builder->token->type != JIM_TT_EOL) {
13512 ParseToken *t = builder->token++;
13513 int prevtt;
13514
13515 if (t == builder->first_token) {
13516 prevtt = JIM_TT_NONE;
13517 }
13518 else {
13519 prevtt = t[-1].type;
13520 }
13521
13522 if (t->type == JIM_TT_SUBEXPR_START) {
13523 if (builder->stack.len == exp_stacklen) {
13524 Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr);
13525 return JIM_ERR;
13526 }
13527 builder->parencount++;
13528 rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1);
13529 if (rc != JIM_OK) {
13530 return rc;
13531 }
13532
13533 }
13534 else if (t->type == JIM_TT_SUBEXPR_END) {
13535 if (!(flags & EXPR_UNTIL_CLOSE)) {
13536 if (builder->stack.len == exp_stacklen && builder->level > 1) {
13537 builder->token--;
13538 builder->level--;
13539 return JIM_OK;
13540 }
13541 Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr);
13542 return JIM_ERR;
13543 }
13544 builder->parencount--;
13545 if (builder->stack.len == exp_stacklen) {
13546
13547 break;
13548 }
13549 }
13550 else if (t->type == JIM_TT_SUBEXPR_COMMA) {
13551 if (!(flags & EXPR_FUNC_ARGS)) {
13552 if (builder->stack.len == exp_stacklen) {
13553
13554 builder->token--;
13555 builder->level--;
13556 return JIM_OK;
13557 }
13558 Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr);
13559 return JIM_ERR;
13560 }
13561 else {
13562
13563 if (builder->stack.len > exp_stacklen) {
13564 Jim_SetResultFormatted(interp, "too many arguments to math function");
13565 return JIM_ERR;
13566 }
13567 }
13568
13569 }
13570 else if (t->type == JIM_EXPROP_COLON) {
13571 if (!(flags & EXPR_TERNARY)) {
13572 if (builder->level != 1) {
13573
13574 builder->token--;
13575 builder->level--;
13576 return JIM_OK;
13577 }
13578 Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr);
13579 return JIM_ERR;
13580 }
13581 if (builder->stack.len == exp_stacklen) {
13582
13583 builder->token--;
13584 builder->level--;
13585 return JIM_OK;
13586 }
13587
13588 }
13589 else if (TOKEN_IS_EXPR_OP(t->type)) {
13590 const struct Jim_ExprOperator *op;
13591
13592
13593 if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) {
13594 if (t->type == JIM_EXPROP_SUB) {
13595 t->type = JIM_EXPROP_UNARYMINUS;
13596 }
13597 else if (t->type == JIM_EXPROP_ADD) {
13598 t->type = JIM_EXPROP_UNARYPLUS;
13599 }
13600 }
13601
13602 op = JimExprOperatorInfoByOpcode(t->type);
13603
13604 if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) {
13605
13606 builder->token--;
13607 break;
13608 }
13609
13610 if (op->attr & OP_FUNC) {
13611 if (builder->token->type != JIM_TT_SUBEXPR_START) {
13612 Jim_SetResultString(interp, "missing arguments for math function", -1);
13613 return JIM_ERR;
13614 }
13615 builder->token++;
13616 if (op->arity == 0) {
13617 if (builder->token->type != JIM_TT_SUBEXPR_END) {
13618 Jim_SetResultString(interp, "too many arguments for math function", -1);
13619 return JIM_ERR;
13620 }
13621 builder->token++;
13622 goto noargs;
13623 }
13624 builder->parencount++;
13625
13626
13627 rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity);
13628 }
13629 else if (t->type == JIM_EXPROP_TERNARY) {
13630
13631 rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2);
13632 }
13633 else {
13634 rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1);
13635 }
13636
13637 if (rc != JIM_OK) {
13638 return rc;
13639 }
13640
13641 noargs:
13642 node = builder->next++;
13643 node->type = t->type;
13644
13645 if (op->arity >= 3) {
13646 node->ternary = Jim_StackPop(&builder->stack);
13647 if (node->ternary == NULL) {
13648 goto missingoperand;
13649 }
13650 }
13651 if (op->arity >= 2) {
13652 node->right = Jim_StackPop(&builder->stack);
13653 if (node->right == NULL) {
13654 goto missingoperand;
13655 }
13656 }
13657 if (op->arity >= 1) {
13658 node->left = Jim_StackPop(&builder->stack);
13659 if (node->left == NULL) {
13660 missingoperand:
13661 Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr);
13662 builder->next--;
13663 return JIM_ERR;
13664
13665 }
13666 }
13667
13668
13669 Jim_StackPush(&builder->stack, node);
13670 }
13671 else {
13672 Jim_Obj *objPtr = NULL;
13673
13674
13675
13676
13677 if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) {
13678 Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr);
13679 return JIM_ERR;
13680 }
13681
13682
13683 if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) {
13684 char *endptr;
13685 if (t->type == JIM_TT_EXPR_INT) {
13686 objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13687 }
13688 else {
13689 objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13690 }
13691 if (endptr != t->token + t->len) {
13692
13693 Jim_FreeNewObj(interp, objPtr);
13694 objPtr = NULL;
13695 }
13696 }
13697
13698 if (!objPtr) {
13699
13700 objPtr = Jim_NewStringObj(interp, t->token, t->len);
13701 if (t->type == JIM_TT_CMD) {
13702
13703 JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line);
13704 }
13705 }
13706
13707
13708 node = builder->next++;
13709 node->objPtr = objPtr;
13710 Jim_IncrRefCount(node->objPtr);
13711 node->type = t->type;
13712 Jim_StackPush(&builder->stack, node);
13713 }
13714 }
13715
13716 if (builder->stack.len == exp_stacklen) {
13717 builder->level--;
13718 return JIM_OK;
13719 }
13720
13721 if ((flags & EXPR_FUNC_ARGS)) {
13722 Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many");
13723 }
13724 else {
13725 if (builder->stack.len < exp_stacklen) {
13726 if (builder->level == 0) {
13727 Jim_SetResultFormatted(interp, "empty expression");
13728 }
13729 else {
13730 Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr);
13731 }
13732 }
13733 else {
13734 Jim_SetResultFormatted(interp, "extra terms after expression");
13735 }
13736 }
13737
13738 return JIM_ERR;
13739 }
13740
13741 static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
13742 {
13743 struct ExprTree *expr;
13744 struct ExprBuilder builder;
13745 int rc;
13746 struct JimExprNode *top;
13747
13748 builder.parencount = 0;
13749 builder.level = 0;
13750 builder.token = builder.first_token = tokenlist->list;
13751 builder.exprObjPtr = exprObjPtr;
13752 builder.fileNameObj = fileNameObj;
13753
13754 builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
13755 memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1));
13756 builder.next = builder.nodes;
13757 Jim_InitStack(&builder.stack);
13758
13759 rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1);
13760
13761 if (rc == JIM_OK) {
13762 top = Jim_StackPop(&builder.stack);
13763
13764 if (builder.parencount) {
13765 Jim_SetResultString(interp, "missing close parenthesis", -1);
13766 rc = JIM_ERR;
13767 }
13768 }
13769
13770
13771 Jim_FreeStack(&builder.stack);
13772
13773 if (rc != JIM_OK) {
13774 ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes);
13775 return NULL;
13776 }
13777
13778 expr = Jim_Alloc(sizeof(*expr));
13779 expr->inUse = 1;
13780 expr->expr = top;
13781 expr->nodes = builder.nodes;
13782 expr->len = builder.next - builder.nodes;
13783
13784 assert(expr->len <= tokenlist->count - 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13785
13786 return expr;
13787 }
 
13788
13789 static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
13790 {
13791 int exprTextLen;
13792 const char *exprText;
13793 struct JimParserCtx parser;
13794 struct ExprTree *expr;
13795 ParseTokenList tokenlist;
13796 int line;
13797 Jim_Obj *fileNameObj;
13798 int rc = JIM_ERR;
13799
13800
13801 if (objPtr->typePtr == &sourceObjType) {
13802 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
13803 line = objPtr->internalRep.sourceValue.lineNumber;
13804 }
13805 else {
@@ -14002,18 +13808,17 @@
13808 }
13809 Jim_IncrRefCount(fileNameObj);
13810
13811 exprText = Jim_GetString(objPtr, &exprTextLen);
13812
13813
13814 ScriptTokenListInit(&tokenlist);
13815
13816 JimParserInit(&parser, exprText, exprTextLen, line);
13817 while (!parser.eof) {
13818 if (JimParseExpression(&parser) != JIM_OK) {
13819 ScriptTokenListFree(&tokenlist);
 
13820 Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
13821 expr = NULL;
13822 goto err;
13823 }
13824
@@ -14036,125 +13841,174 @@
13841 ScriptTokenListFree(&tokenlist);
13842 Jim_DecrRefCount(interp, fileNameObj);
13843 return JIM_ERR;
13844 }
13845
 
 
13846
13847 expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj);
13848
13849
13850 ScriptTokenListFree(&tokenlist);
13851
13852 if (!expr) {
13853 goto err;
13854 }
13855
13856 #ifdef DEBUG_SHOW_EXPR
13857 printf("==== Expr ====\n");
13858 JimShowExprNode(expr->expr, 0);
 
 
 
 
 
 
 
 
13859 #endif
13860
 
 
 
 
 
 
13861 rc = JIM_OK;
13862
13863 err:
13864
13865 Jim_DecrRefCount(interp, fileNameObj);
13866 Jim_FreeIntRep(interp, objPtr);
13867 Jim_SetIntRepPtr(objPtr, expr);
13868 objPtr->typePtr = &exprObjType;
13869 return rc;
13870 }
13871
13872 static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
13873 {
13874 if (objPtr->typePtr != &exprObjType) {
13875 if (SetExprFromAny(interp, objPtr) != JIM_OK) {
13876 return NULL;
13877 }
13878 }
13879 return (struct ExprTree *) Jim_GetIntRepPtr(objPtr);
13880 }
13881
13882 #ifdef JIM_OPTIMIZATION
13883 static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node)
13884 {
13885 if (node->type == JIM_TT_EXPR_INT)
13886 return node->objPtr;
13887 else if (node->type == JIM_TT_VAR)
13888 return Jim_GetVariable(interp, node->objPtr, JIM_NONE);
13889 else if (node->type == JIM_TT_DICTSUGAR)
13890 return JimExpandDictSugar(interp, node->objPtr);
13891 else
13892 return NULL;
13893 }
13894 #endif
13895
13896
13897 static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node)
13898 {
13899 if (TOKEN_IS_EXPR_OP(node->type)) {
13900 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type);
13901 return op->funcop(interp, node);
13902 }
13903 else {
13904 Jim_Obj *objPtr;
13905
13906
13907 switch (node->type) {
13908 case JIM_TT_EXPR_INT:
13909 case JIM_TT_EXPR_DOUBLE:
13910 case JIM_TT_EXPR_BOOLEAN:
13911 case JIM_TT_STR:
13912 Jim_SetResult(interp, node->objPtr);
13913 return JIM_OK;
13914
13915 case JIM_TT_VAR:
13916 objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG);
13917 if (objPtr) {
13918 Jim_SetResult(interp, objPtr);
13919 return JIM_OK;
13920 }
13921 return JIM_ERR;
13922
13923 case JIM_TT_DICTSUGAR:
13924 objPtr = JimExpandDictSugar(interp, node->objPtr);
13925 if (objPtr) {
13926 Jim_SetResult(interp, objPtr);
13927 return JIM_OK;
13928 }
13929 return JIM_ERR;
13930
13931 case JIM_TT_ESC:
13932 if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) {
13933 Jim_SetResult(interp, objPtr);
13934 return JIM_OK;
13935 }
13936 return JIM_ERR;
13937
13938 case JIM_TT_CMD:
13939 return Jim_EvalObj(interp, node->objPtr);
13940
13941 default:
13942
13943 return JIM_ERR;
13944 }
13945 }
13946 }
13947
13948 static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr)
13949 {
13950 int rc = JimExprEvalTermNode(interp, node);
13951 if (rc == JIM_OK) {
13952 *objPtrPtr = Jim_GetResult(interp);
13953 Jim_IncrRefCount(*objPtrPtr);
13954 }
13955 return rc;
13956 }
13957
13958 static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node)
13959 {
13960 if (JimExprEvalTermNode(interp, node) == JIM_OK) {
13961 return ExprBool(interp, Jim_GetResult(interp));
13962 }
13963 return -1;
13964 }
13965
13966 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
13967 {
13968 struct ExprTree *expr;
13969 int retcode = JIM_OK;
13970
13971 expr = JimGetExpression(interp, exprObjPtr);
13972 if (!expr) {
13973 return JIM_ERR;
13974 }
13975
13976 #ifdef JIM_OPTIMIZATION
13977 {
13978 Jim_Obj *objPtr;
13979
13980
13981 switch (expr->len) {
13982 case 1:
13983 objPtr = JimExprIntValOrVar(interp, expr->expr);
13984 if (objPtr) {
13985 Jim_SetResult(interp, objPtr);
 
13986 return JIM_OK;
13987 }
13988 break;
13989
13990 case 2:
13991 if (expr->expr->type == JIM_EXPROP_NOT) {
13992 objPtr = JimExprIntValOrVar(interp, expr->expr->left);
13993
13994 if (objPtr && JimIsWide(objPtr)) {
13995 Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj);
 
13996 return JIM_OK;
13997 }
13998 }
13999 break;
14000
14001 case 3:
14002 objPtr = JimExprIntValOrVar(interp, expr->expr->left);
14003 if (objPtr && JimIsWide(objPtr)) {
14004 Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right);
14005 if (objPtr2 && JimIsWide(objPtr2)) {
14006 jim_wide wideValueA = JimWideValue(objPtr);
14007 jim_wide wideValueB = JimWideValue(objPtr2);
14008 int cmpRes;
14009 switch (expr->expr->type) {
14010 case JIM_EXPROP_LT:
14011 cmpRes = wideValueA < wideValueB;
14012 break;
14013 case JIM_EXPROP_LTE:
14014 cmpRes = wideValueA <= wideValueB;
@@ -14172,12 +14026,11 @@
14026 cmpRes = wideValueA != wideValueB;
14027 break;
14028 default:
14029 goto noopt;
14030 }
14031 Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj);
 
14032 return JIM_OK;
14033 }
14034 }
14035 break;
14036 }
@@ -14185,145 +14038,64 @@
14038 noopt:
14039 #endif
14040
14041 expr->inUse++;
14042
14043
14044 retcode = JimExprEvalTermNode(interp, expr->expr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14045
14046 expr->inUse--;
14047
 
 
 
 
 
 
 
 
 
 
 
14048 return retcode;
14049 }
14050
14051 int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
14052 {
14053 int retcode = Jim_EvalExpression(interp, exprObjPtr);
14054
14055 if (retcode == JIM_OK) {
14056 switch (ExprBool(interp, Jim_GetResult(interp))) {
14057 case 0:
14058 *boolPtr = 0;
14059 break;
14060
14061 case 1:
14062 *boolPtr = 1;
14063 break;
14064
14065 case -1:
14066 retcode = JIM_ERR;
14067 break;
14068 }
14069 }
14070 return retcode;
 
 
 
 
 
 
14071 }
14072
14073
14074
14075
14076 typedef struct ScanFmtPartDescr
14077 {
14078 const char *arg;
14079 const char *prefix;
14080 size_t width;
14081 int pos;
14082 char type;
14083 char modifier;
14084 } ScanFmtPartDescr;
14085
14086
14087 typedef struct ScanFmtStringObj
14088 {
14089 jim_wide size;
14090 char *stringRep;
14091 size_t count;
14092 size_t convCount;
14093 size_t maxPos;
14094 const char *error;
14095 char *scratch;
14096 ScanFmtPartDescr descr[1];
14097 } ScanFmtStringObj;
14098
14099
14100 static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
14101 static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14364,28 +14136,28 @@
14136 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
14137 {
14138 ScanFmtStringObj *fmtObj;
14139 char *buffer;
14140 int maxCount, i, approxSize, lastPos = -1;
14141 const char *fmt = Jim_String(objPtr);
14142 int maxFmtLen = Jim_Length(objPtr);
14143 const char *fmtEnd = fmt + maxFmtLen;
14144 int curr;
14145
14146 Jim_FreeIntRep(interp, objPtr);
14147
14148 for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
14149 if (fmt[i] == '%')
14150 ++maxCount;
14151
14152 approxSize = sizeof(ScanFmtStringObj)
14153 +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14154 +maxFmtLen * sizeof(char) + 3 + 1
14155 + maxFmtLen * sizeof(char) + 1
14156 + maxFmtLen * sizeof(char)
14157 +(maxCount + 1) * sizeof(char)
14158 +1;
14159 fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
14160 memset(fmtObj, 0, approxSize);
14161 fmtObj->size = approxSize;
14162 fmtObj->maxPos = 0;
14163 fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14169,12 @@
14169 for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
14170 int width = 0, skip;
14171 ScanFmtPartDescr *descr = &fmtObj->descr[curr];
14172
14173 fmtObj->count++;
14174 descr->width = 0;
14175
14176 if (*fmt != '%' || fmt[1] == '%') {
14177 descr->type = 0;
14178 descr->prefix = &buffer[i];
14179 for (; fmt < fmtEnd; ++fmt) {
14180 if (*fmt == '%') {
@@ -14412,65 +14184,70 @@
14184 }
14185 buffer[i++] = *fmt;
14186 }
14187 buffer[i++] = 0;
14188 }
14189
14190 ++fmt;
14191
14192 if (fmt >= fmtEnd)
14193 goto done;
14194 descr->pos = 0;
14195 if (*fmt == '*') {
14196 descr->pos = -1;
14197 ++fmt;
14198 }
14199 else
14200 fmtObj->convCount++;
14201
14202 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14203 fmt += skip;
14204
14205 if (descr->pos != -1 && *fmt == '$') {
14206 int prev;
14207
14208 ++fmt;
14209 descr->pos = width;
14210 width = 0;
14211
14212 if ((lastPos == 0 && descr->pos > 0)
14213 || (lastPos > 0 && descr->pos == 0)) {
14214 fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
14215 return JIM_ERR;
14216 }
14217
14218 for (prev = 0; prev < curr; ++prev) {
14219 if (fmtObj->descr[prev].pos == -1)
14220 continue;
14221 if (fmtObj->descr[prev].pos == descr->pos) {
14222 fmtObj->error =
14223 "variable is assigned by multiple \"%n$\" conversion specifiers";
14224 return JIM_ERR;
14225 }
14226 }
14227 if (descr->pos < 0) {
14228 fmtObj->error =
14229 "\"%n$\" conversion specifier is negative";
14230 return JIM_ERR;
14231 }
14232
14233 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14234 descr->width = width;
14235 fmt += skip;
14236 }
14237 if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
14238 fmtObj->maxPos = descr->pos;
14239 }
14240 else {
14241
14242 descr->width = width;
14243 }
14244 }
14245
14246 if (lastPos == -1)
14247 lastPos = descr->pos;
14248
14249 if (*fmt == '[') {
14250 int swapped = 1, beg = i, end, j;
14251
14252 descr->type = '[';
14253 descr->arg = &buffer[i];
@@ -14485,11 +14262,11 @@
14262 fmtObj->error = "unmatched [ in format string";
14263 return JIM_ERR;
14264 }
14265 end = i;
14266 buffer[i++] = 0;
14267
14268 while (swapped) {
14269 swapped = 0;
14270 for (j = beg + 1; j < end - 1; ++j) {
14271 if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
14272 char tmp = buffer[j - 1];
@@ -14500,13 +14277,18 @@
14277 }
14278 }
14279 }
14280 }
14281 else {
14282
14283 if (fmt < fmtEnd && strchr("hlL", *fmt))
14284 descr->modifier = tolower((int)*fmt++);
14285
14286 if (fmt >= fmtEnd) {
14287 fmtObj->error = "missing scan conversion character";
14288 return JIM_ERR;
14289 }
14290
14291 descr->type = *fmt;
14292 if (strchr("efgcsndoxui", *fmt) == 0) {
14293 fmtObj->error = "bad scan conversion character";
14294 return JIM_ERR;
@@ -14543,11 +14325,11 @@
14325 while (*str) {
14326 int c;
14327 int n;
14328
14329 if (!sdescr && isspace(UCHAR(*str)))
14330 break;
14331
14332 n = utf8_tounicode(str, &c);
14333 if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
14334 break;
14335 while (n--)
@@ -14566,89 +14348,89 @@
14348 size_t scanned = 0;
14349 size_t anchor = pos;
14350 int i;
14351 Jim_Obj *tmpObj = NULL;
14352
14353
14354 *valObjPtr = 0;
14355 if (descr->prefix) {
14356 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14357
14358 if (isspace(UCHAR(descr->prefix[i])))
14359 while (pos < strLen && isspace(UCHAR(str[pos])))
14360 ++pos;
14361 else if (descr->prefix[i] != str[pos])
14362 break;
14363 else
14364 ++pos;
14365 }
14366 if (pos >= strLen) {
14367 return -1;
14368 }
14369 else if (descr->prefix[i] != 0)
14370 return 0;
14371 }
14372
14373 if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
14374 while (isspace(UCHAR(str[pos])))
14375 ++pos;
14376
14377 scanned = pos - anchor;
14378
14379
14380 if (descr->type == 'n') {
14381
14382 *valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
14383 }
14384 else if (pos >= strLen) {
14385
14386 return -1;
14387 }
14388 else if (descr->type == 'c') {
14389 int c;
14390 scanned += utf8_tounicode(&str[pos], &c);
14391 *valObjPtr = Jim_NewIntObj(interp, c);
14392 return scanned;
14393 }
14394 else {
14395
14396 if (descr->width > 0) {
14397 size_t sLen = utf8_strlen(&str[pos], strLen - pos);
14398 size_t tLen = descr->width > sLen ? sLen : descr->width;
14399
14400 tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
14401 tok = tmpObj->bytes;
14402 }
14403 else {
14404
14405 tok = &str[pos];
14406 }
14407 switch (descr->type) {
14408 case 'd':
14409 case 'o':
14410 case 'x':
14411 case 'u':
14412 case 'i':{
14413 char *endp;
14414 jim_wide w;
14415
14416 int base = descr->type == 'o' ? 8
14417 : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
14418
14419
14420 if (base == 0) {
14421 w = jim_strtoull(tok, &endp);
14422 }
14423 else {
14424 w = strtoull(tok, &endp, base);
14425 }
14426
14427 if (endp != tok) {
14428
14429 *valObjPtr = Jim_NewIntObj(interp, w);
14430
14431
14432 scanned += endp - tok;
14433 }
14434 else {
14435 scanned = *tok ? 0 : -1;
14436 }
@@ -14665,13 +14447,13 @@
14447 case 'g':{
14448 char *endp;
14449 double value = strtod(tok, &endp);
14450
14451 if (endp != tok) {
14452
14453 *valObjPtr = Jim_NewDoubleObj(interp, value);
14454
14455 scanned += endp - tok;
14456 }
14457 else {
14458 scanned = *tok ? 0 : -1;
14459 }
@@ -14696,65 +14478,65 @@
14478 Jim_Obj **resultVec = 0;
14479 int resultc;
14480 Jim_Obj *emptyStr = 0;
14481 ScanFmtStringObj *fmtObj;
14482
14483
14484 JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
14485
14486 fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14487
14488 if (fmtObj->error != 0) {
14489 if (flags & JIM_ERRMSG)
14490 Jim_SetResultString(interp, fmtObj->error, -1);
14491 return 0;
14492 }
14493
14494 emptyStr = Jim_NewEmptyStringObj(interp);
14495 Jim_IncrRefCount(emptyStr);
14496
14497 resultList = Jim_NewListObj(interp, NULL, 0);
14498 if (fmtObj->maxPos > 0) {
14499 for (i = 0; i < fmtObj->maxPos; ++i)
14500 Jim_ListAppendElement(interp, resultList, emptyStr);
14501 JimListGetElements(interp, resultList, &resultc, &resultVec);
14502 }
14503
14504 for (i = 0, pos = 0; i < fmtObj->count; ++i) {
14505 ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
14506 Jim_Obj *value = 0;
14507
14508
14509 if (descr->type == 0)
14510 continue;
14511
14512 if (scanned > 0)
14513 scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14514
14515 if (scanned == -1 && i == 0)
14516 goto eof;
14517
14518 pos += scanned;
14519
14520
14521 if (value == 0)
14522 value = Jim_NewEmptyStringObj(interp);
14523
14524 if (descr->pos == -1) {
14525 Jim_FreeNewObj(interp, value);
14526 }
14527 else if (descr->pos == 0)
14528
14529 Jim_ListAppendElement(interp, resultList, value);
14530 else if (resultVec[descr->pos - 1] == emptyStr) {
14531
14532 Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
14533 Jim_IncrRefCount(value);
14534 resultVec[descr->pos - 1] = value;
14535 }
14536 else {
14537
14538 Jim_FreeNewObj(interp, value);
14539 goto err;
14540 }
14541 }
14542 Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14574,15 @@
14574 {
14575 Jim_PrngState *prng;
14576 unsigned char *destByte = (unsigned char *)dest;
14577 unsigned int si, sj, x;
14578
14579
14580 if (interp->prngState == NULL)
14581 JimPrngInit(interp);
14582 prng = interp->prngState;
14583
14584 for (x = 0; x < len; x++) {
14585 prng->i = (prng->i + 1) & 0xff;
14586 si = prng->sbox[prng->i];
14587 prng->j = (prng->j + si) & 0xff;
14588 sj = prng->sbox[prng->j];
@@ -14814,19 +14596,19 @@
14596 static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
14597 {
14598 int i;
14599 Jim_PrngState *prng;
14600
14601
14602 if (interp->prngState == NULL)
14603 JimPrngInit(interp);
14604 prng = interp->prngState;
14605
14606
14607 for (i = 0; i < 256; i++)
14608 prng->sbox[i] = i;
14609
14610 for (i = 0; i < seedLen; i++) {
14611 unsigned char t;
14612
14613 t = prng->sbox[i & 0xFF];
14614 prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14635,11 @@
14635 if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
14636 return JIM_ERR;
14637 }
14638 intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
14639 if (!intObjPtr) {
14640
14641 wideValue = 0;
14642 }
14643 else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
14644 return JIM_ERR;
14645 }
@@ -14867,26 +14649,26 @@
14649 Jim_FreeNewObj(interp, intObjPtr);
14650 return JIM_ERR;
14651 }
14652 }
14653 else {
14654
14655 Jim_InvalidateStringRep(intObjPtr);
14656 JimWideValue(intObjPtr) = wideValue + increment;
14657
14658 if (argv[1]->typePtr != &variableObjType) {
14659
14660 Jim_SetVariable(interp, argv[1], intObjPtr);
14661 }
14662 }
14663 Jim_SetResult(interp, intObjPtr);
14664 return JIM_OK;
14665 }
14666
14667
14668 #define JIM_EVAL_SARGV_LEN 8
14669 #define JIM_EVAL_SINTV_LEN 8
14670
14671
14672 static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
14673 {
14674 int retcode;
@@ -14894,16 +14676,16 @@
14676 if (interp->unknown_called > 50) {
14677 return JIM_ERR;
14678 }
14679
14680
14681
14682 if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
14683 return JIM_ERR;
14684
14685 interp->unknown_called++;
14686
14687 retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
14688 interp->unknown_called--;
14689
14690 return retcode;
14691 }
@@ -14910,10 +14692,11 @@
14692
14693 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14694 {
14695 int retcode;
14696 Jim_Cmd *cmdPtr;
14697 void *prevPrivData;
14698
14699 #if 0
14700 printf("invoke");
14701 int j;
14702 for (j = 0; j < objc; j++) {
@@ -14921,11 +14704,11 @@
14704 }
14705 printf("\n");
14706 #endif
14707
14708 if (interp->framePtr->tailcallCmd) {
14709
14710 cmdPtr = interp->framePtr->tailcallCmd;
14711 interp->framePtr->tailcallCmd = NULL;
14712 }
14713 else {
14714 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14939,20 +14722,22 @@
14722 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14723 retcode = JIM_ERR;
14724 goto out;
14725 }
14726 interp->evalDepth++;
14727 prevPrivData = interp->cmdPrivData;
14728
14729
14730 Jim_SetEmptyResult(interp);
14731 if (cmdPtr->isproc) {
14732 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14733 }
14734 else {
14735 interp->cmdPrivData = cmdPtr->u.native.privData;
14736 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14737 }
14738 interp->cmdPrivData = prevPrivData;
14739 interp->evalDepth--;
14740
14741 out:
14742 JimDecrCmdRefCount(interp, cmdPtr);
14743
@@ -14961,17 +14746,17 @@
14746
14747 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14748 {
14749 int i, retcode;
14750
14751
14752 for (i = 0; i < objc; i++)
14753 Jim_IncrRefCount(objv[i]);
14754
14755 retcode = JimInvokeCommand(interp, objc, objv);
14756
14757
14758 for (i = 0; i < objc; i++)
14759 Jim_DecrRefCount(interp, objv[i]);
14760
14761 return retcode;
14762 }
@@ -14989,25 +14774,25 @@
14774 }
14775
14776 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
14777 {
14778 if (!interp->errorFlag) {
14779
14780 interp->errorFlag = 1;
14781 Jim_IncrRefCount(script->fileNameObj);
14782 Jim_DecrRefCount(interp, interp->errorFileNameObj);
14783 interp->errorFileNameObj = script->fileNameObj;
14784 interp->errorLine = script->linenr;
14785
14786 JimResetStackTrace(interp);
14787
14788 interp->addStackTrace++;
14789 }
14790
14791
14792 if (interp->addStackTrace > 0) {
14793
14794
14795 JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
14796
14797 if (Jim_Length(script->fileNameObj)) {
14798 interp->addStackTrace = 0;
@@ -15042,14 +14827,14 @@
14827 case JIM_OK:
14828 case JIM_RETURN:
14829 objPtr = interp->result;
14830 break;
14831 case JIM_BREAK:
14832
14833 return JIM_BREAK;
14834 case JIM_CONTINUE:
14835
14836 return JIM_CONTINUE;
14837 default:
14838 return JIM_ERR;
14839 }
14840 break;
@@ -15084,23 +14869,23 @@
14869 case JIM_OK:
14870 case JIM_RETURN:
14871 break;
14872 case JIM_BREAK:
14873 if (flags & JIM_SUBST_FLAG) {
14874
14875 tokens = i;
14876 continue;
14877 }
14878
14879
14880 case JIM_CONTINUE:
14881 if (flags & JIM_SUBST_FLAG) {
14882 intv[i] = NULL;
14883 continue;
14884 }
14885
14886
14887 default:
14888 while (i--) {
14889 Jim_DecrRefCount(interp, intv[i]);
14890 }
14891 if (intv != sintv) {
@@ -15111,28 +14896,29 @@
14896 Jim_IncrRefCount(intv[i]);
14897 Jim_String(intv[i]);
14898 totlen += intv[i]->length;
14899 }
14900
14901
14902 if (tokens == 1 && intv[0] && intv == sintv) {
14903
14904 intv[0]->refCount--;
14905 return intv[0];
14906 }
14907
14908 objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
14909
14910 if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
14911 && token[2].type == JIM_TT_VAR) {
14912
14913 objPtr->typePtr = &interpolatedObjType;
14914 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14915 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14916 Jim_IncrRefCount(intv[2]);
14917 }
14918 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
14919
14920 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
14921 }
14922
14923
14924 s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +14929,11 @@
14929 s += intv[i]->length;
14930 Jim_DecrRefCount(interp, intv[i]);
14931 }
14932 }
14933 objPtr->bytes[totlen] = '\0';
14934
14935 if (intv != sintv) {
14936 Jim_Free(intv);
14937 }
14938
14939 return objPtr;
@@ -15187,11 +14973,11 @@
14973
14974 if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
14975 return JimEvalObjList(interp, scriptObjPtr);
14976 }
14977
14978 Jim_IncrRefCount(scriptObjPtr);
14979 script = JimGetScript(interp, scriptObjPtr);
14980 if (!JimScriptValid(interp, script)) {
14981 Jim_DecrRefCount(interp, scriptObjPtr);
14982 return JIM_ERR;
14983 }
@@ -15223,11 +15009,11 @@
15009 }
15010 #endif
15011
15012 script->inUse++;
15013
15014
15015 prevScriptObj = interp->currentScriptObj;
15016 interp->currentScriptObj = scriptObjPtr;
15017
15018 interp->errorFlag = 0;
15019 argv = sargv;
@@ -15234,19 +15020,19 @@
15020
15021 for (i = 0; i < script->len && retcode == JIM_OK; ) {
15022 int argc;
15023 int j;
15024
15025
15026 argc = token[i].objPtr->internalRep.scriptLineValue.argc;
15027 script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
15028
15029
15030 if (argc > JIM_EVAL_SARGV_LEN)
15031 argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
15032
15033
15034 i++;
15035
15036 for (j = 0; j < argc; j++) {
15037 long wordtokens = 1;
15038 int expand = 0;
@@ -15302,11 +15088,11 @@
15088
15089 if (!expand) {
15090 argv[j] = wordObjPtr;
15091 }
15092 else {
15093
15094 int len = Jim_ListLength(interp, wordObjPtr);
15095 int newargc = argc + len - 1;
15096 int k;
15097
15098 if (len > 1) {
@@ -15315,39 +15101,39 @@
15101 argv = Jim_Alloc(sizeof(*argv) * newargc);
15102 memcpy(argv, sargv, sizeof(*argv) * j);
15103 }
15104 }
15105 else {
15106
15107 argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
15108 }
15109 }
15110
15111
15112 for (k = 0; k < len; k++) {
15113 argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
15114 Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
15115 }
15116
15117 Jim_DecrRefCount(interp, wordObjPtr);
15118
15119
15120 j--;
15121 argc += len - 1;
15122 }
15123 }
15124
15125 if (retcode == JIM_OK && argc) {
15126
15127 retcode = JimInvokeCommand(interp, argc, argv);
15128
15129 if (Jim_CheckSignal(interp)) {
15130 retcode = JIM_SIGNAL;
15131 }
15132 }
15133
15134
15135 while (j-- > 0) {
15136 Jim_DecrRefCount(interp, argv[j]);
15137 }
15138
15139 if (argv != sargv) {
@@ -15354,21 +15140,21 @@
15140 Jim_Free(argv);
15141 argv = sargv;
15142 }
15143 }
15144
15145
15146 if (retcode == JIM_ERR) {
15147 JimAddErrorToStack(interp, script);
15148 }
15149
15150 else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15151
15152 interp->addStackTrace = 0;
15153 }
15154
15155
15156 interp->currentScriptObj = prevScriptObj;
15157
15158 Jim_FreeIntRep(interp, scriptObjPtr);
15159 scriptObjPtr->typePtr = &scriptObjType;
15160 Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15164,14 @@
15164 }
15165
15166 static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
15167 {
15168 int retcode;
15169
15170 const char *varname = Jim_String(argNameObj);
15171 if (*varname == '&') {
15172
15173 Jim_Obj *objPtr;
15174 Jim_CallFrame *savedCallFrame = interp->framePtr;
15175
15176 interp->framePtr = interp->framePtr->parent;
15177 objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15178,11 @@
15178 interp->framePtr = savedCallFrame;
15179 if (!objPtr) {
15180 return JIM_ERR;
15181 }
15182
15183
15184 objPtr = Jim_NewStringObj(interp, varname + 1, -1);
15185 Jim_IncrRefCount(objPtr);
15186 retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
15187 Jim_DecrRefCount(interp, objPtr);
15188 }
@@ -15406,26 +15192,26 @@
15192 return retcode;
15193 }
15194
15195 static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
15196 {
15197
15198 Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
15199 int i;
15200
15201 for (i = 0; i < cmd->u.proc.argListLen; i++) {
15202 Jim_AppendString(interp, argmsg, " ", 1);
15203
15204 if (i == cmd->u.proc.argsPos) {
15205 if (cmd->u.proc.arglist[i].defaultObjPtr) {
15206
15207 Jim_AppendString(interp, argmsg, "?", 1);
15208 Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
15209 Jim_AppendString(interp, argmsg, " ...?", -1);
15210 }
15211 else {
15212
15213 Jim_AppendString(interp, argmsg, "?arg...?", -1);
15214 }
15215 }
15216 else {
15217 if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15227,19 @@
15227 Jim_AppendString(interp, argmsg, arg, -1);
15228 }
15229 }
15230 }
15231 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
 
15232 }
15233
15234 #ifdef jim_ext_namespace
15235 int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
15236 {
15237 Jim_CallFrame *callFramePtr;
15238 int retcode;
15239
15240
15241 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
15242 callFramePtr->argv = &interp->emptyObj;
15243 callFramePtr->argc = 0;
15244 callFramePtr->procArgsObjPtr = NULL;
15245 callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15247,21 @@
15247 callFramePtr->fileNameObj = interp->emptyObj;
15248 callFramePtr->line = 0;
15249 Jim_IncrRefCount(scriptObj);
15250 interp->framePtr = callFramePtr;
15251
15252
15253 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15254 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15255 retcode = JIM_ERR;
15256 }
15257 else {
15258
15259 retcode = Jim_EvalObj(interp, scriptObj);
15260 }
15261
15262
15263 interp->framePtr = interp->framePtr->parent;
15264 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15265
15266 return retcode;
15267 }
@@ -15486,62 +15271,62 @@
15271 {
15272 Jim_CallFrame *callFramePtr;
15273 int i, d, retcode, optargs;
15274 ScriptObj *script;
15275
15276
15277 if (argc - 1 < cmd->u.proc.reqArity ||
15278 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
15279 JimSetProcWrongArgs(interp, argv[0], cmd);
15280 return JIM_ERR;
15281 }
15282
15283 if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15284
15285 return JIM_OK;
15286 }
15287
15288
15289 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15290 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15291 return JIM_ERR;
15292 }
15293
15294
15295 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
15296 callFramePtr->argv = argv;
15297 callFramePtr->argc = argc;
15298 callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
15299 callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
15300 callFramePtr->staticVars = cmd->u.proc.staticVars;
15301
15302
15303 script = JimGetScript(interp, interp->currentScriptObj);
15304 callFramePtr->fileNameObj = script->fileNameObj;
15305 callFramePtr->line = script->linenr;
15306
15307 Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
15308 Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
15309 interp->framePtr = callFramePtr;
15310
15311
15312 optargs = (argc - 1 - cmd->u.proc.reqArity);
15313
15314
15315 i = 1;
15316 for (d = 0; d < cmd->u.proc.argListLen; d++) {
15317 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
15318 if (d == cmd->u.proc.argsPos) {
15319
15320 Jim_Obj *listObjPtr;
15321 int argsLen = 0;
15322 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
15323 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
15324 }
15325 listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
15326
15327
15328 if (cmd->u.proc.arglist[d].defaultObjPtr) {
15329 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
15330 }
15331 retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
15332 if (retcode != JIM_OK) {
@@ -15550,33 +15335,34 @@
15335
15336 i += argsLen;
15337 continue;
15338 }
15339
15340
15341 if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
15342 retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
15343 }
15344 else {
15345
15346 retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
15347 }
15348 if (retcode != JIM_OK) {
15349 goto badargset;
15350 }
15351 }
15352
15353
15354 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15355
15356 badargset:
15357
15358
15359 retcode = JimInvokeDefer(interp, retcode);
15360 interp->framePtr = interp->framePtr->parent;
15361 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15362
15363
15364 if (interp->framePtr->tailcallObj) {
15365 do {
15366 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15367
15368 interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15374,18 @@
15374 }
15375 }
15376 Jim_DecrRefCount(interp, tailcallObj);
15377 } while (interp->framePtr->tailcallObj);
15378
15379
15380 if (interp->framePtr->tailcallCmd) {
15381 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15382 interp->framePtr->tailcallCmd = NULL;
15383 }
15384 }
15385
15386
15387 if (retcode == JIM_RETURN) {
15388 if (--interp->returnLevel <= 0) {
15389 retcode = interp->returnCode;
15390 interp->returnCode = JIM_OK;
15391 interp->returnLevel = 0;
@@ -15711,20 +15497,20 @@
15497 prevScriptObj = interp->currentScriptObj;
15498 interp->currentScriptObj = scriptObjPtr;
15499
15500 retcode = Jim_EvalObj(interp, scriptObjPtr);
15501
15502
15503 if (retcode == JIM_RETURN) {
15504 if (--interp->returnLevel <= 0) {
15505 retcode = interp->returnCode;
15506 interp->returnCode = JIM_OK;
15507 interp->returnLevel = 0;
15508 }
15509 }
15510 if (retcode == JIM_ERR) {
15511
15512 interp->addStackTrace++;
15513 }
15514
15515 interp->currentScriptObj = prevScriptObj;
15516
@@ -15750,11 +15536,11 @@
15536 }
15537 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
15538 if (JimParseVar(pc) == JIM_OK) {
15539 return;
15540 }
15541
15542 pc->tstart = pc->p;
15543 flags |= JIM_SUBST_NOVAR;
15544 }
15545 while (pc->len) {
15546 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15567,32 @@
15567 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
15568 struct JimParserCtx parser;
15569 struct ScriptObj *script = Jim_Alloc(sizeof(*script));
15570 ParseTokenList tokenlist;
15571
15572
15573 ScriptTokenListInit(&tokenlist);
15574
15575 JimParserInit(&parser, scriptText, scriptTextLen, 1);
15576 while (1) {
15577 JimParseSubst(&parser, flags);
15578 if (parser.eof) {
15579
15580 break;
15581 }
15582 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
15583 parser.tline);
15584 }
15585
15586
15587 script->inUse = 1;
15588 script->substFlags = flags;
15589 script->fileNameObj = interp->emptyObj;
15590 Jim_IncrRefCount(script->fileNameObj);
15591 SubstObjAddTokens(interp, script, &tokenlist);
15592
15593
15594 ScriptTokenListFree(&tokenlist);
15595
15596 #ifdef DEBUG_SHOW_SUBST
15597 {
15598 int i;
@@ -15817,11 +15603,11 @@
15603 Jim_String(script->token[i].objPtr));
15604 }
15605 }
15606 #endif
15607
15608
15609 Jim_FreeIntRep(interp, objPtr);
15610 Jim_SetIntRepPtr(objPtr, script);
15611 objPtr->typePtr = &scriptObjType;
15612 return JIM_OK;
15613 }
@@ -15835,11 +15621,11 @@
15621
15622 int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
15623 {
15624 ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
15625
15626 Jim_IncrRefCount(substObjPtr);
15627 script->inUse++;
15628
15629 *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
15630
15631 script->inUse--;
@@ -15851,22 +15637,24 @@
15637 }
15638
15639 void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
15640 {
15641 Jim_Obj *objPtr;
15642 Jim_Obj *listObjPtr;
15643
15644 JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0"));
15645
15646 listObjPtr = Jim_NewListObj(interp, argv, argc);
15647
15648 if (msg && *msg) {
15649 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
15650 }
15651 Jim_IncrRefCount(listObjPtr);
15652 objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
15653 Jim_DecrRefCount(interp, listObjPtr);
15654
 
15655 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
 
15656 }
15657
15658 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15659 Jim_HashEntry *he, int type);
15660
@@ -15876,11 +15664,11 @@
15664 JimHashtableIteratorCallbackType *callback, int type)
15665 {
15666 Jim_HashEntry *he;
15667 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
15668
15669
15670 if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
15671 he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
15672 if (he) {
15673 callback(interp, listObjPtr, he, type);
15674 }
@@ -15907,11 +15695,11 @@
15695 {
15696 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15697 Jim_Obj *objPtr;
15698
15699 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15700
15701 return;
15702 }
15703
15704 objPtr = Jim_NewStringObj(interp, he->key, -1);
15705 Jim_IncrRefCount(objPtr);
@@ -15967,11 +15755,11 @@
15755
15756 targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
15757 if (targetCallFrame == NULL) {
15758 return JIM_ERR;
15759 }
15760
15761 if (targetCallFrame == interp->topFramePtr) {
15762 Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
15763 return JIM_ERR;
15764 }
15765 if (info_level_cmd) {
@@ -16095,12 +15883,17 @@
15883 doubleRes = (double)res;
15884 goto trydouble;
15885 }
15886 if (op == JIM_EXPROP_SUB)
15887 res -= wideValue;
15888 else {
15889 if (wideValue == 0) {
15890 Jim_SetResultString(interp, "Division by zero", -1);
15891 return JIM_ERR;
15892 }
15893 res /= wideValue;
15894 }
15895 }
15896 Jim_SetResultInt(interp, res);
15897 return JIM_OK;
15898 trydouble:
15899 for (; i < argc; i++) {
@@ -16154,11 +15947,11 @@
15947 if (!objPtr)
15948 return JIM_ERR;
15949 Jim_SetResult(interp, objPtr);
15950 return JIM_OK;
15951 }
15952
15953 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
15954 return JIM_ERR;
15955 Jim_SetResult(interp, argv[2]);
15956 return JIM_OK;
15957 }
@@ -16197,11 +15990,11 @@
15990 if (argc != 3) {
15991 Jim_WrongNumArgs(interp, 1, argv, "condition body");
15992 return JIM_ERR;
15993 }
15994
15995
15996 while (1) {
15997 int boolean, retval;
15998
15999 if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
16000 return retval;
@@ -16237,11 +16030,11 @@
16030 if (argc != 5) {
16031 Jim_WrongNumArgs(interp, 1, argv, "start test next body");
16032 return JIM_ERR;
16033 }
16034
16035
16036 if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
16037 return retval;
16038 }
16039
16040 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16248,78 +16041,84 @@
16041
16042
16043 #ifdef JIM_OPTIMIZATION
16044 if (retval == JIM_OK && boolean) {
16045 ScriptObj *incrScript;
16046 struct ExprTree *expr;
16047 jim_wide stop, currentVal;
16048 Jim_Obj *objPtr;
16049 int cmpOffset;
16050
16051
16052 expr = JimGetExpression(interp, argv[2]);
16053 incrScript = JimGetScript(interp, argv[3]);
16054
16055
16056 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16057 goto evalstart;
16058 }
16059
16060 if (incrScript->token[1].type != JIM_TT_ESC) {
 
 
16061 goto evalstart;
16062 }
16063
16064 if (expr->expr->type == JIM_EXPROP_LT) {
16065 cmpOffset = 0;
16066 }
16067 else if (expr->expr->type == JIM_EXPROP_LTE) {
16068 cmpOffset = 1;
16069 }
16070 else {
16071 goto evalstart;
16072 }
16073
16074 if (expr->expr->left->type != JIM_TT_VAR) {
16075 goto evalstart;
16076 }
16077
16078 if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) {
16079 goto evalstart;
16080 }
16081
16082
16083 if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
16084 goto evalstart;
16085 }
16086
16087
16088 if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) {
16089 goto evalstart;
16090 }
16091
16092
16093 if (expr->expr->right->type == JIM_TT_EXPR_INT) {
16094 if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) {
16095 goto evalstart;
16096 }
16097 }
16098 else {
16099 stopVarNamePtr = expr->expr->right->objPtr;
16100 Jim_IncrRefCount(stopVarNamePtr);
16101
16102 stop = 0;
16103 }
16104
16105
16106 varNamePtr = expr->expr->left->objPtr;
16107 Jim_IncrRefCount(varNamePtr);
16108
16109 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
16110 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
16111 goto testcond;
16112 }
16113
16114
16115 while (retval == JIM_OK) {
 
 
16116
16117
16118
16119
16120 if (stopVarNamePtr) {
16121 objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
16122 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
16123 goto testcond;
16124 }
@@ -16327,18 +16126,18 @@
16126
16127 if (currentVal >= stop + cmpOffset) {
16128 break;
16129 }
16130
16131
16132 retval = Jim_EvalObj(interp, argv[4]);
16133 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16134 retval = JIM_OK;
16135
16136 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
16137
16138
16139 if (objPtr == NULL) {
16140 retval = JIM_ERR;
16141 goto out;
16142 }
16143 if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16157,25 @@
16157 }
16158 evalstart:
16159 #endif
16160
16161 while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16162
16163 retval = Jim_EvalObj(interp, argv[4]);
16164
16165 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16166
16167 JIM_IF_OPTIM(evalnext:)
16168 retval = Jim_EvalObj(interp, argv[3]);
16169 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16170
16171 JIM_IF_OPTIM(testcond:)
16172 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
16173 }
16174 }
16175 }
16176 JIM_IF_OPTIM(out:)
16177 if (stopVarNamePtr) {
16178 Jim_DecrRefCount(interp, stopVarNamePtr);
16179 }
16180 if (varNamePtr) {
16181 Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16217,11 @@
16217 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16218 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
16219
16220 retval = JIM_OK;
16221
16222
16223 i += incr;
16224
16225 if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
16226 if (argv[1]->typePtr != &variableObjType) {
16227 if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16282,21 @@
16282
16283 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16284 {
16285 int result = JIM_OK;
16286 int i, numargs;
16287 Jim_ListIter twoiters[2];
16288 Jim_ListIter *iters;
16289 Jim_Obj *script;
16290 Jim_Obj *resultObj;
16291
16292 if (argc < 4 || argc % 2 != 0) {
16293 Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
16294 return JIM_ERR;
16295 }
16296 script = argv[argc - 1];
16297 numargs = (argc - 1 - 1);
16298
16299 if (numargs == 2) {
16300 iters = twoiters;
16301 }
16302 else {
@@ -16521,34 +16320,34 @@
16320 resultObj = interp->emptyObj;
16321 }
16322 Jim_IncrRefCount(resultObj);
16323
16324 while (1) {
16325
16326 for (i = 0; i < numargs; i += 2) {
16327 if (!JimListIterDone(interp, &iters[i + 1])) {
16328 break;
16329 }
16330 }
16331 if (i == numargs) {
16332
16333 break;
16334 }
16335
16336
16337 for (i = 0; i < numargs; i += 2) {
16338 Jim_Obj *varName;
16339
16340
16341 JimListIterInit(&iters[i], argv[i + 1]);
16342 while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
16343 Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
16344 if (!valObj) {
16345
16346 valObj = interp->emptyObj;
16347 }
16348
16349 Jim_IncrRefCount(valObj);
16350 result = Jim_SetVariable(interp, varName, valObj);
16351 Jim_DecrRefCount(interp, valObj);
16352 if (result != JIM_OK) {
16353 goto err;
@@ -16630,41 +16429,41 @@
16429 {
16430 int boolean, retval, current = 1, falsebody = 0;
16431
16432 if (argc >= 3) {
16433 while (1) {
16434
16435 if (current >= argc)
16436 goto err;
16437 if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
16438 != JIM_OK)
16439 return retval;
16440
16441 if (current >= argc)
16442 goto err;
16443 if (Jim_CompareStringImmediate(interp, argv[current], "then"))
16444 current++;
16445
16446 if (current >= argc)
16447 goto err;
16448 if (boolean)
16449 return Jim_EvalObj(interp, argv[current]);
16450
16451 if (++current >= argc) {
16452 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
16453 return JIM_OK;
16454 }
16455 falsebody = current++;
16456 if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16457
16458 if (current != argc - 1)
16459 goto err;
16460 return Jim_EvalObj(interp, argv[current]);
16461 }
16462 else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
16463 continue;
16464
16465 else if (falsebody != argc - 1)
16466 goto err;
16467 return Jim_EvalObj(interp, argv[falsebody]);
16468 }
16469 return JIM_OK;
@@ -16698,19 +16497,17 @@
16497 }
16498
16499 return eq;
16500 }
16501
 
 
 
16502
16503 static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
16504 {
16505 enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
16506 int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
16507 Jim_Obj *command = NULL, *scriptObj = NULL, *strObj;
16508 Jim_Obj **caseList;
16509
16510 if (argc < 3) {
16511 wrongnumargs:
16512 Jim_WrongNumArgs(interp, 1, argv, "?options? string "
16513 "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}");
@@ -16747,68 +16544,62 @@
16544 goto wrongnumargs;
16545 }
16546 strObj = argv[opt++];
16547 patCount = argc - opt;
16548 if (patCount == 1) {
16549 JimListGetElements(interp, argv[opt], &patCount, &caseList);
 
 
 
16550 }
16551 else
16552 caseList = (Jim_Obj **)&argv[opt];
16553 if (patCount == 0 || patCount % 2 != 0)
16554 goto wrongnumargs;
16555 for (i = 0; scriptObj == NULL && i < patCount; i += 2) {
16556 Jim_Obj *patObj = caseList[i];
16557
16558 if (!Jim_CompareStringImmediate(interp, patObj, "default")
16559 || i < (patCount - 2)) {
16560 switch (matchOpt) {
16561 case SWITCH_EXACT:
16562 if (Jim_StringEqObj(strObj, patObj))
16563 scriptObj = caseList[i + 1];
16564 break;
16565 case SWITCH_GLOB:
16566 if (Jim_StringMatchObj(interp, patObj, strObj, 0))
16567 scriptObj = caseList[i + 1];
16568 break;
16569 case SWITCH_RE:
16570 command = Jim_NewStringObj(interp, "regexp", -1);
16571
16572 case SWITCH_CMD:{
16573 int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
16574
16575 if (argc - opt == 1) {
16576 JimListGetElements(interp, argv[opt], &patCount, &caseList);
 
 
 
16577 }
16578
16579 if (rc < 0) {
16580 return -rc;
16581 }
16582 if (rc)
16583 scriptObj = caseList[i + 1];
16584 break;
16585 }
16586 }
16587 }
16588 else {
16589 scriptObj = caseList[i + 1];
16590 }
16591 }
16592 for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2)
16593 scriptObj = caseList[i + 1];
16594 if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) {
16595 Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]);
16596 return JIM_ERR;
16597 }
16598 Jim_SetEmptyResult(interp);
16599 if (scriptObj) {
16600 return Jim_EvalObj(interp, scriptObj);
16601 }
16602 return JIM_OK;
16603 }
16604
16605
@@ -16920,11 +16711,11 @@
16711 case OPT_COMMAND:
16712 if (i >= argc - 2) {
16713 goto wrongargs;
16714 }
16715 commandObj = argv[++i];
16716
16717 case OPT_EXACT:
16718 case OPT_GLOB:
16719 case OPT_REGEXP:
16720 opt_match = option;
16721 break;
@@ -16968,17 +16759,17 @@
16759 goto done;
16760 }
16761 break;
16762 }
16763
16764
16765 if (!eq && opt_bool && opt_not && !opt_all) {
16766 continue;
16767 }
16768
16769 if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16770
16771 Jim_Obj *resultObj;
16772
16773 if (opt_bool) {
16774 resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
16775 }
@@ -17001,11 +16792,11 @@
16792
16793 if (opt_all) {
16794 Jim_SetResult(interp, listObjPtr);
16795 }
16796 else {
16797
16798 if (opt_bool) {
16799 Jim_SetResultBool(interp, opt_not);
16800 }
16801 else if (!opt_inline) {
16802 Jim_SetResultInt(interp, -1);
@@ -17030,11 +16821,11 @@
16821 Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
16822 return JIM_ERR;
16823 }
16824 listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
16825 if (!listObjPtr) {
16826
16827 listObjPtr = Jim_NewListObj(interp, NULL, 0);
16828 new_obj = 1;
16829 }
16830 else if (Jim_IsShared(listObjPtr)) {
16831 listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +16894,31 @@
16894 first = JimRelToAbsIndex(len, first);
16895 last = JimRelToAbsIndex(len, last);
16896 JimRelToAbsRange(len, &first, &last, &rangeLen);
16897
16898
16899
16900 if (first < len) {
16901
16902 }
16903 else if (len == 0) {
16904
16905 first = 0;
16906 }
16907 else {
16908 Jim_SetResultString(interp, "list doesn't contain element ", -1);
16909 Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
16910 return JIM_ERR;
16911 }
16912
16913
16914 newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
16915
16916
16917 ListInsertElements(newListObj, -1, argc - 4, argv + 4);
16918
16919
16920 ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
16921
16922 Jim_SetResult(interp, newListObj);
16923 return JIM_OK;
16924 }
@@ -17138,11 +16929,11 @@
16929 if (argc < 3) {
16930 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16931 return JIM_ERR;
16932 }
16933 else if (argc == 3) {
16934
16935 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16936 return JIM_ERR;
16937 Jim_SetResult(interp, argv[2]);
16938 return JIM_OK;
16939 }
@@ -17158,10 +16949,11 @@
16949 enum
16950 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
16951 Jim_Obj *resObj;
16952 int i;
16953 int retCode;
16954 int shared;
16955
16956 struct lsort_info info;
16957
16958 if (argc < 2) {
16959 Jim_WrongNumArgs(interp, 1, argv, "?options? list");
@@ -17223,16 +17015,18 @@
17015 info.indexed = 1;
17016 i++;
17017 break;
17018 }
17019 }
17020 resObj = argv[argc - 1];
17021 if ((shared = Jim_IsShared(resObj)))
17022 resObj = Jim_DuplicateObj(interp, resObj);
17023 retCode = ListSortElements(interp, resObj, &info);
17024 if (retCode == JIM_OK) {
17025 Jim_SetResult(interp, resObj);
17026 }
17027 else if (shared) {
17028 Jim_FreeNewObj(interp, resObj);
17029 }
17030 return retCode;
17031 }
17032
@@ -17253,11 +17047,11 @@
17047 }
17048 else {
17049 int new_obj = 0;
17050 stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17051 if (!stringObjPtr) {
17052
17053 stringObjPtr = Jim_NewEmptyStringObj(interp);
17054 new_obj = 1;
17055 }
17056 else if (Jim_IsShared(stringObjPtr)) {
17057 new_obj = 1;
@@ -17274,10 +17068,11 @@
17068 }
17069 }
17070 Jim_SetResult(interp, stringObjPtr);
17071 return JIM_OK;
17072 }
17073
17074
17075
17076 static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17077 {
17078 #if !defined(JIM_DEBUG_COMMAND)
@@ -17302,11 +17097,11 @@
17097 else {
17098 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
17099 }
17100
17101 if (rc == JIM_ERR) {
17102
17103 interp->addStackTrace++;
17104 }
17105 return rc;
17106 }
17107
@@ -17316,14 +17111,14 @@
17111 if (argc >= 2) {
17112 int retcode;
17113 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17114 const char *str;
17115
17116
17117 savedCallFrame = interp->framePtr;
17118
17119
17120 str = Jim_String(argv[1]);
17121 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17122 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17123 argc--;
17124 argv++;
@@ -17336,11 +17131,11 @@
17131 }
17132 if (argc < 2) {
17133 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
17134 return JIM_ERR;
17135 }
17136
17137 interp->framePtr = targetCallFrame;
17138 if (argc == 2) {
17139 retcode = Jim_EvalObj(interp, argv[1]);
17140 }
17141 else {
@@ -17356,32 +17151,29 @@
17151 }
17152
17153
17154 static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17155 {
 
17156 int retcode;
17157
17158 if (argc == 2) {
17159 retcode = Jim_EvalExpression(interp, argv[1]);
17160 }
17161 else if (argc > 2) {
17162 Jim_Obj *objPtr;
17163
17164 objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
17165 Jim_IncrRefCount(objPtr);
17166 retcode = Jim_EvalExpression(interp, objPtr);
17167 Jim_DecrRefCount(interp, objPtr);
17168 }
17169 else {
17170 Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
17171 return JIM_ERR;
17172 }
17173 if (retcode != JIM_OK)
17174 return retcode;
 
 
17175 return JIM_OK;
17176 }
17177
17178
17179 static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -17438,15 +17230,15 @@
17230 if (i != argc - 1 && i != argc) {
17231 Jim_WrongNumArgs(interp, 1, argv,
17232 "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
17233 }
17234
17235
17236 if (stackTraceObj && returnCode == JIM_ERR) {
17237 JimSetStackTrace(interp, stackTraceObj);
17238 }
17239
17240 if (errorCodeObj && returnCode == JIM_ERR) {
17241 Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
17242 }
17243 interp->returnCode = returnCode;
17244 interp->returnLevel = level;
@@ -17463,31 +17255,31 @@
17255 if (interp->framePtr->level == 0) {
17256 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17257 return JIM_ERR;
17258 }
17259 else if (argc >= 2) {
17260
17261 Jim_CallFrame *cf = interp->framePtr->parent;
17262
17263 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17264 if (cmdPtr == NULL) {
17265 return JIM_ERR;
17266 }
17267
17268 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17269
17270
17271 JimIncrCmdRefCount(cmdPtr);
17272 cf->tailcallCmd = cmdPtr;
17273
17274
17275 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17276
17277 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17278 Jim_IncrRefCount(cf->tailcallObj);
17279
17280
17281 return JIM_EVAL;
17282 }
17283 return JIM_OK;
17284 }
17285
@@ -17494,11 +17286,11 @@
17286 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17287 {
17288 Jim_Obj *cmdList;
17289 Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
17290
17291
17292 cmdList = Jim_DuplicateObj(interp, prefixListObj);
17293 Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
17294
17295 return JimEvalObjList(interp, cmdList);
17296 }
@@ -17552,22 +17344,22 @@
17344 else {
17345 cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
17346 }
17347
17348 if (cmd) {
17349
17350 Jim_Obj *qualifiedCmdNameObj;
17351 const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
17352
17353 JimCreateCommand(interp, cmdname, cmd);
17354
17355
17356 JimUpdateProcNamespace(interp, cmd, cmdname);
17357
17358 JimFreeQualifiedName(interp, qualifiedCmdNameObj);
17359
17360
17361 Jim_SetResult(interp, argv[1]);
17362 return JIM_OK;
17363 }
17364 return JIM_ERR;
17365 }
@@ -17580,17 +17372,17 @@
17372 if (argc < 2) {
17373 Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17374 return JIM_ERR;
17375 }
17376
17377
17378 interp->local++;
17379 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17380 interp->local--;
17381
17382
17383
17384 if (retcode == 0) {
17385 Jim_Obj *cmdNameObj = Jim_GetResult(interp);
17386
17387 if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
17388 return JIM_ERR;
@@ -17619,18 +17411,18 @@
17411 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17412 if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
17413 Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
17414 return JIM_ERR;
17415 }
17416
17417 cmdPtr->u.proc.upcall++;
17418 JimIncrCmdRefCount(cmdPtr);
17419
17420
17421 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17422
17423
17424 cmdPtr->u.proc.upcall--;
17425 JimDecrCmdRefCount(interp, cmdPtr);
17426
17427 return retcode;
17428 }
@@ -17657,11 +17449,11 @@
17449 return JIM_ERR;
17450 }
17451
17452 if (len == 3) {
17453 #ifdef jim_ext_namespace
17454
17455 nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
17456 #else
17457 Jim_SetResultString(interp, "namespaces not enabled", -1);
17458 return JIM_ERR;
17459 #endif
@@ -17670,11 +17462,11 @@
17462 bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
17463
17464 cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
17465
17466 if (cmd) {
17467
17468 nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
17469 nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
17470 Jim_IncrRefCount(nargv[0]);
17471 memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
17472 ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17492,11 @@
17492 static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17493 {
17494 int i;
17495 Jim_CallFrame *targetCallFrame;
17496
17497
17498 if (argc > 3 && (argc % 2 == 0)) {
17499 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17500 argc--;
17501 argv++;
17502 }
@@ -17713,17 +17505,17 @@
17505 }
17506 if (targetCallFrame == NULL) {
17507 return JIM_ERR;
17508 }
17509
17510
17511 if (argc < 3) {
17512 Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
17513 return JIM_ERR;
17514 }
17515
17516
17517 for (i = 1; i < argc; i += 2) {
17518 if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
17519 return JIM_ERR;
17520 }
17521 return JIM_OK;
@@ -17736,15 +17528,15 @@
17528
17529 if (argc < 2) {
17530 Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
17531 return JIM_ERR;
17532 }
17533
17534 if (interp->framePtr->level == 0)
17535 return JIM_OK;
17536 for (i = 1; i < argc; i++) {
17537
17538 const char *name = Jim_String(argv[i]);
17539 if (name[0] != ':' || name[1] != ':') {
17540 if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
17541 return JIM_ERR;
17542 }
@@ -17767,21 +17559,21 @@
17559 }
17560
17561 str = Jim_String(objPtr);
17562 strLen = Jim_Utf8Length(interp, objPtr);
17563
17564
17565 resultObjPtr = Jim_NewStringObj(interp, "", 0);
17566 while (strLen) {
17567 for (i = 0; i < numMaps; i += 2) {
17568 Jim_Obj *eachObjPtr;
17569 const char *k;
17570 int kl;
17571
17572 eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17573 k = Jim_String(eachObjPtr);
17574 kl = Jim_Utf8Length(interp, eachObjPtr);
17575
17576 if (strLen >= kl && kl) {
17577 int rc;
17578 rc = JimStringCompareLen(str, k, kl, nocase);
17579 if (rc == 0) {
@@ -17794,11 +17586,11 @@
17586 strLen -= kl;
17587 break;
17588 }
17589 }
17590 }
17591 if (i == numMaps) {
17592 int c;
17593 if (noMatchStart == NULL)
17594 noMatchStart = str;
17595 str += utf8_tounicode(str, &c);
17596 strLen--;
@@ -17838,11 +17630,11 @@
17630 Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
17631 return JIM_ERR;
17632 }
17633 if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
17634 JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17635 return Jim_CheckShowCommands(interp, argv[1], options);
17636
17637 switch (option) {
17638 case OPT_LENGTH:
17639 case OPT_BYTELENGTH:
17640 if (argc != 3) {
@@ -17859,11 +17651,11 @@
17651 return JIM_OK;
17652
17653 case OPT_CAT:{
17654 Jim_Obj *objPtr;
17655 if (argc == 3) {
17656
17657 objPtr = argv[2];
17658 }
17659 else {
17660 int i;
17661
@@ -17878,11 +17670,11 @@
17670 }
17671
17672 case OPT_COMPARE:
17673 case OPT_EQUAL:
17674 {
17675
17676 long opt_length = -1;
17677 int n = argc - 4;
17678 int i = 2;
17679 while (n > 0) {
17680 int subopt;
@@ -17891,16 +17683,16 @@
17683 badcompareargs:
17684 Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
17685 return JIM_ERR;
17686 }
17687 if (subopt == 0) {
17688
17689 opt_case = 0;
17690 n--;
17691 }
17692 else {
17693
17694 if (n < 2) {
17695 goto badcompareargs;
17696 }
17697 if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
17698 return JIM_ERR;
@@ -17911,11 +17703,11 @@
17703 if (n) {
17704 goto badcompareargs;
17705 }
17706 argv += argc - 2;
17707 if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17708
17709 Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
17710 }
17711 else {
17712 if (opt_length >= 0) {
17713 n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17817,10 @@
17817 }
17818
17819 case OPT_REVERSE:{
17820 char *buf, *p;
17821 const char *str;
 
17822 int i;
17823
17824 if (argc != 3) {
17825 Jim_WrongNumArgs(interp, 2, argv, "string");
17826 return JIM_ERR;
@@ -18069,11 +17860,11 @@
17860 }
17861 if (idx < 0 || idx >= len || str == NULL) {
17862 Jim_SetResultString(interp, "", 0);
17863 }
17864 else if (len == Jim_Length(argv[2])) {
17865
17866 Jim_SetResultString(interp, str + idx, 1);
17867 }
17868 else {
17869 int c;
17870 int i = utf8_index(str, idx);
@@ -18223,11 +18014,11 @@
18014 {
18015 int exitCode = 0;
18016 int i;
18017 int sig = 0;
18018
18019
18020 jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
18021 static const int max_ignore_code = sizeof(ignore_mask) * 8;
18022
18023 Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
18024
@@ -18234,11 +18025,11 @@
18025 for (i = 1; i < argc - 1; i++) {
18026 const char *arg = Jim_String(argv[i]);
18027 jim_wide option;
18028 int ignore;
18029
18030
18031 if (strcmp(arg, "--") == 0) {
18032 i++;
18033 break;
18034 }
18035 if (*arg != '-') {
@@ -18285,28 +18076,28 @@
18076 sig++;
18077 }
18078
18079 interp->signal_level += sig;
18080 if (Jim_CheckSignal(interp)) {
18081
18082 exitCode = JIM_SIGNAL;
18083 }
18084 else {
18085 exitCode = Jim_EvalObj(interp, argv[0]);
18086
18087 interp->errorFlag = 0;
18088 }
18089 interp->signal_level -= sig;
18090
18091
18092 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18093
18094 return exitCode;
18095 }
18096
18097 if (sig && exitCode == JIM_SIGNAL) {
18098
18099 if (interp->signal_set_result) {
18100 interp->signal_set_result(interp, interp->sigmask);
18101 }
18102 else {
18103 Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18136,10 @@
18136 }
18137 Jim_SetResultInt(interp, exitCode);
18138 return JIM_OK;
18139 }
18140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18141
18142
18143 static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18144 {
18145 if (argc != 3) {
@@ -18476,56 +18152,43 @@
18152 }
18153
18154 return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
18155 }
18156
18157 #define JIM_DICTMATCH_KEYS 0x0001
18158 #define JIM_DICTMATCH_VALUES 0x002
18159
18160 int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types)
18161 {
18162 Jim_HashEntry *he;
18163 Jim_Obj *listObjPtr;
18164 Jim_HashTableIterator htiter;
18165
18166 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18167 return JIM_ERR;
18168 }
18169
18170 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18171
18172 JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter);
18173 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18174 if (patternObj) {
18175 Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
18176 if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
18177
18178 continue;
18179 }
18180 }
18181 if (return_types & JIM_DICTMATCH_KEYS) {
18182 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18183 }
18184 if (return_types & JIM_DICTMATCH_VALUES) {
18185 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18186 }
18187 }
18188
18189 Jim_SetResult(interp, listObjPtr);
 
 
 
 
 
 
 
 
 
 
 
 
 
18190 return JIM_OK;
18191 }
18192
18193 int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
18194 {
@@ -18532,38 +18195,85 @@
18195 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18196 return -1;
18197 }
18198 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18199 }
18200
18201 Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
18202 {
18203 Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0);
18204 int i;
18205
18206 JimPanic((objc == 0, "Jim_DictMerge called with objc=0"));
18207
18208
18209
18210 for (i = 0; i < objc; i++) {
18211 Jim_HashTable *ht;
18212 Jim_HashTableIterator htiter;
18213 Jim_HashEntry *he;
18214
18215 if (SetDictFromAny(interp, objv[i]) != JIM_OK) {
18216 Jim_FreeNewObj(interp, objPtr);
18217 return NULL;
18218 }
18219 ht = objv[i]->internalRep.ptr;
18220 JimInitHashTableIterator(ht, &htiter);
18221 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18222 Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he));
18223 }
18224 }
18225 return objPtr;
18226 }
18227
18228 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18229 {
18230 Jim_HashTable *ht;
18231 unsigned int i;
18232 char buffer[100];
18233 int sum = 0;
18234 int nonzero_count = 0;
18235 Jim_Obj *output;
18236 int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
18237
18238 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18239 return JIM_ERR;
18240 }
18241
18242 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18243
18244
18245 snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
18246 output = Jim_NewStringObj(interp, buffer, -1);
18247
18248 for (i = 0; i < ht->size; i++) {
18249 Jim_HashEntry *he = ht->table[i];
18250 int entries = 0;
18251 while (he) {
18252 entries++;
18253 he = he->next;
18254 }
18255 if (entries > 9) {
18256 bucket_counts[10]++;
18257 }
18258 else {
18259 bucket_counts[entries]++;
18260 }
18261 if (entries) {
18262 sum += entries;
18263 nonzero_count++;
18264 }
18265 }
18266 for (i = 0; i < 10; i++) {
18267 snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
18268 Jim_AppendString(interp, output, buffer, -1);
18269 }
18270 snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
18271 Jim_AppendString(interp, output, buffer, -1);
18272 snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
18273 Jim_AppendString(interp, output, buffer, -1);
18274 Jim_SetResult(interp, output);
18275 return JIM_OK;
18276 }
18277
18278 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18279 {
@@ -18573,14 +18283,67 @@
18283 Jim_AppendString(interp, prefixObj, subcmd, -1);
18284
18285 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18286 }
18287
18288 static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj)
18289 {
18290 int i;
18291 Jim_Obj *objPtr;
18292 Jim_Obj *dictObj;
18293 Jim_Obj **dictValues;
18294 int len;
18295 int ret = JIM_OK;
18296
18297
18298 dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG);
18299 if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) {
18300 return JIM_ERR;
18301 }
18302
18303 if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) {
18304 return JIM_ERR;
18305 }
18306 for (i = 0; i < len; i += 2) {
18307 if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) {
18308 Jim_Free(dictValues);
18309 return JIM_ERR;
18310 }
18311 }
18312
18313
18314 if (Jim_Length(scriptObj)) {
18315 ret = Jim_EvalObj(interp, scriptObj);
18316
18317
18318 if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) {
18319
18320 Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1));
18321 for (i = 0; i < keyc; i++) {
18322 newkeyv[i] = keyv[i];
18323 }
18324
18325 for (i = 0; i < len; i += 2) {
18326
18327 objPtr = Jim_GetVariable(interp, dictValues[i], 0);
18328 newkeyv[keyc] = dictValues[i];
18329 Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0);
18330 }
18331 Jim_Free(newkeyv);
18332 }
18333 }
18334
18335 Jim_Free(dictValues);
18336
18337 return ret;
18338 }
18339
18340
18341 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18342 {
18343 Jim_Obj *objPtr;
18344 int types = JIM_DICTMATCH_KEYS;
18345 int option;
18346 static const char * const options[] = {
18347 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18348 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18349 "replace", "update", NULL
@@ -18596,11 +18359,11 @@
18359 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18360 return JIM_ERR;
18361 }
18362
18363 if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18364 return Jim_CheckShowCommands(interp, argv[1], options);
18365 }
18366
18367 switch (option) {
18368 case OPT_GET:
18369 if (argc < 3) {
@@ -18643,16 +18406,19 @@
18406 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18407 return JIM_ERR;
18408 }
18409 return JIM_OK;
18410
18411 case OPT_VALUES:
18412 types = JIM_DICTMATCH_VALUES;
18413
18414 case OPT_KEYS:
18415 if (argc != 3 && argc != 4) {
18416 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18417 return JIM_ERR;
18418 }
18419 return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types);
18420
18421 case OPT_SIZE:
18422 if (argc != 3) {
18423 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18424 return JIM_ERR;
@@ -18665,19 +18431,20 @@
18431
18432 case OPT_MERGE:
18433 if (argc == 2) {
18434 return JIM_OK;
18435 }
18436 objPtr = Jim_DictMerge(interp, argc - 2, argv + 2);
18437 if (objPtr == NULL) {
18438 return JIM_ERR;
18439 }
18440 Jim_SetResult(interp, objPtr);
18441 return JIM_OK;
18442
18443 case OPT_UPDATE:
18444 if (argc < 6 || argc % 2) {
18445
18446 argc = 2;
18447 }
18448 break;
18449
18450 case OPT_CREATE:
@@ -18693,12 +18460,19 @@
18460 if (argc != 3) {
18461 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18462 return JIM_ERR;
18463 }
18464 return Jim_DictInfo(interp, argv[2]);
18465
18466 case OPT_WITH:
18467 if (argc < 4) {
18468 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18469 return JIM_ERR;
18470 }
18471 return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]);
18472 }
18473
18474 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18475 }
18476
18477
18478 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18538,11 @@
18538
18539 #ifdef jim_ext_namespace
18540 int nons = 0;
18541
18542 if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18543
18544 argc--;
18545 argv++;
18546 nons = 1;
18547 }
18548 #endif
@@ -18775,16 +18549,15 @@
18549
18550 if (argc < 2) {
18551 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
18552 return JIM_ERR;
18553 }
18554 if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
18555 return Jim_CheckShowCommands(interp, argv[1], commands);
 
18556 }
18557
18558
18559 switch (cmd) {
18560 case INFO_EXISTS:
18561 if (argc != 3) {
18562 Jim_WrongNumArgs(interp, 2, argv, "varName");
18563 return JIM_ERR;
@@ -18809,21 +18582,21 @@
18582 Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
18583 return JIM_OK;
18584 }
18585
18586 case INFO_CHANNELS:
18587 mode++;
18588 #ifndef jim_ext_aio
18589 Jim_SetResultString(interp, "aio not enabled", -1);
18590 return JIM_ERR;
18591 #endif
18592
18593 case INFO_PROCS:
18594 mode++;
18595
18596 case INFO_COMMANDS:
18597
18598 if (argc != 2 && argc != 3) {
18599 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18600 return JIM_ERR;
18601 }
18602 #ifdef jim_ext_namespace
@@ -18835,17 +18608,17 @@
18608 #endif
18609 Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
18610 break;
18611
18612 case INFO_VARS:
18613 mode++;
18614
18615 case INFO_LOCALS:
18616 mode++;
18617
18618 case INFO_GLOBALS:
18619
18620 if (argc != 2 && argc != 3) {
18621 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18622 return JIM_ERR;
18623 }
18624 #ifdef jim_ext_namespace
@@ -18951,13 +18724,12 @@
18724 case INFO_ARGS:
18725 Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
18726 break;
18727 case INFO_STATICS:
18728 if (cmdPtr->u.proc.staticVars) {
 
18729 Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18730 NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES));
18731 }
18732 break;
18733 }
18734 break;
18735 }
@@ -18985,15 +18757,15 @@
18757 }
18758 }
18759 break;
18760
18761 case INFO_HOSTNAME:
18762
18763 return Jim_Eval(interp, "os.gethostname");
18764
18765 case INFO_NAMEOFEXECUTABLE:
18766
18767 return Jim_Eval(interp, "{info nameofexecutable}");
18768
18769 case INFO_RETURNCODES:
18770 if (argc == 2) {
18771 int i;
@@ -19070,11 +18842,11 @@
18842
18843 if (option == OPT_VAR) {
18844 result = Jim_GetVariable(interp, objPtr, 0) != NULL;
18845 }
18846 else {
18847
18848 Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
18849
18850 if (cmd) {
18851 switch (option) {
18852 case OPT_COMMAND:
@@ -19113,11 +18885,11 @@
18885 if (len == 0) {
18886 return JIM_OK;
18887 }
18888 strLen = Jim_Utf8Length(interp, argv[1]);
18889
18890
18891 if (argc == 2) {
18892 splitChars = " \n\t\r";
18893 splitLen = 4;
18894 }
18895 else {
@@ -19126,11 +18898,11 @@
18898 }
18899
18900 noMatchStart = str;
18901 resObjPtr = Jim_NewListObj(interp, NULL, 0);
18902
18903
18904 if (splitLen) {
18905 Jim_Obj *objPtr;
18906 while (strLen--) {
18907 const char *sc = splitChars;
18908 int scLen = splitLen;
@@ -19155,11 +18927,11 @@
18927 #define NUM_COMMON (128 - 9)
18928 while (strLen--) {
18929 int n = utf8_tounicode(str, &c);
18930 #ifdef JIM_OPTIMIZATION
18931 if (c >= 9 && c < 128) {
18932
18933 c -= 9;
18934 if (!commonObj) {
18935 commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
18936 memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
18937 }
@@ -19189,11 +18961,11 @@
18961
18962 if (argc != 2 && argc != 3) {
18963 Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
18964 return JIM_ERR;
18965 }
18966
18967 if (argc == 2) {
18968 joinStr = " ";
18969 joinStrLen = 1;
18970 }
18971 else {
@@ -19468,13 +19240,13 @@
19240 return -1;
19241 else if (step < 0 && end > start)
19242 return -1;
19243 len = end - start;
19244 if (len < 0)
19245 len = -len;
19246 if (step < 0)
19247 step = -step;
19248 len = 1 + ((len - 1) / step);
19249 if (len > INT_MAX)
19250 len = INT_MAX;
19251 return (int)((len < 0) ? -1 : len);
19252 }
@@ -19644,57 +19416,102 @@
19416 argv[1] = interp->result;
19417
19418 Jim_EvalObjVector(interp, 2, argv);
19419 }
19420
19421 static char **JimSortStringTable(const char *const *tablePtr)
 
19422 {
19423 int count;
19424 char **tablePtrSorted;
19425
19426
19427 for (count = 0; tablePtr[count]; count++) {
19428 }
19429
19430
19431 tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1));
19432 memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19433 qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19434 tablePtrSorted[count] = NULL;
19435
19436 return tablePtrSorted;
19437 }
19438
19439 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19440 const char *prefix, const char *const *tablePtr, const char *name)
19441 {
19442 char **tablePtrSorted;
19443 int i;
19444
19445 if (name == NULL) {
19446 name = "option";
19447 }
19448
19449 Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19450 tablePtrSorted = JimSortStringTable(tablePtr);
19451 for (i = 0; tablePtrSorted[i]; i++) {
19452 if (tablePtrSorted[i + 1] == NULL && i > 0) {
 
 
19453 Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
19454 }
19455 Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19456 if (tablePtrSorted[i + 1]) {
19457 Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
19458 }
19459 }
19460 Jim_Free(tablePtrSorted);
19461 }
19462
19463
19464 int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr)
19465 {
19466 if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) {
19467 int i;
19468 char **tablePtrSorted = JimSortStringTable(tablePtr);
19469 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
19470 for (i = 0; tablePtrSorted[i]; i++) {
19471 Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1));
19472 }
19473 Jim_Free(tablePtrSorted);
19474 return JIM_OK;
19475 }
19476 return JIM_ERR;
19477 }
19478
19479 static const Jim_ObjType getEnumObjType = {
19480 "get-enum",
19481 NULL,
19482 NULL,
19483 NULL,
19484 JIM_TYPE_REFERENCES
19485 };
19486
19487 int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
19488 const char *const *tablePtr, int *indexPtr, const char *name, int flags)
19489 {
19490 const char *bad = "bad ";
19491 const char *const *entryPtr = NULL;
19492 int i;
19493 int match = -1;
19494 int arglen;
19495 const char *arg;
19496
19497 if (objPtr->typePtr == &getEnumObjType) {
19498 if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) {
19499 *indexPtr = objPtr->internalRep.ptrIntValue.int2;
19500 return JIM_OK;
19501 }
19502 }
19503
19504 arg = Jim_GetString(objPtr, &arglen);
19505
19506 *indexPtr = -1;
19507
19508 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
19509 if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19510
19511 match = i;
19512 goto found;
19513 }
19514 if (flags & JIM_ENUM_ABBREV) {
19515 if (strncmp(arg, *entryPtr, arglen) == 0) {
19516 if (*arg == '-' && arglen == 1) {
19517 break;
@@ -19706,12 +19523,20 @@
19523 match = i;
19524 }
19525 }
19526 }
19527
19528
19529 if (match >= 0) {
19530 found:
19531
19532 Jim_FreeIntRep(interp, objPtr);
19533 objPtr->typePtr = &getEnumObjType;
19534 objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr;
19535 objPtr->internalRep.ptrIntValue.int1 = flags;
19536 objPtr->internalRep.ptrIntValue.int2 = match;
19537
19538 *indexPtr = match;
19539 return JIM_OK;
19540 }
19541
19542 ambiguous:
@@ -19743,15 +19568,17 @@
19568 return objPtr->typePtr == &listObjType;
19569 }
19570
19571 void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
19572 {
19573
19574 int len = strlen(format);
19575 int extra = 0;
19576 int n = 0;
19577 const char *params[5];
19578 int nobjparam = 0;
19579 Jim_Obj *objparam[5];
19580 char *buf;
19581 va_list args;
19582 int i;
19583
19584 va_start(args, format);
@@ -19766,10 +19593,12 @@
19593 }
19594 else if (strncmp(format + i, "%#s", 3) == 0) {
19595 Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
19596
19597 params[n] = Jim_GetString(objPtr, &l);
19598 objparam[nobjparam++] = objPtr;
19599 Jim_IncrRefCount(objPtr);
19600 }
19601 else {
19602 if (format[i] == '%') {
19603 i++;
19604 }
@@ -19784,10 +19613,14 @@
19613 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19614
19615 va_end(args);
19616
19617 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19618
19619 for (i = 0; i < nobjparam; i++) {
19620 Jim_DecrRefCount(interp, objparam[i]);
19621 }
19622 }
19623
19624
19625 #ifndef jim_ext_package
19626 int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19641,11 @@
19641 #include <string.h>
19642
19643
19644 static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19645 {
19646
19647 return JIM_OK;
19648 }
19649
19650 static const jim_subcmd_type dummy_subcmd = {
19651 "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19831,22 +19664,18 @@
19664 }
19665
19666 static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
19667 Jim_Obj *cmd, Jim_Obj *subcmd)
19668 {
19669 Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd);
 
 
19670 add_commands(interp, command_table, ", ");
19671 }
19672
19673 static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
19674 Jim_Obj *const *argv)
19675 {
19676 Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]);
 
 
19677 add_commands(interp, command_table, ", ");
19678 }
19679
19680 static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
19681 {
@@ -19863,67 +19692,78 @@
19692 {
19693 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19694 add_cmd_usage(interp, command_table, subcmd);
19695 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19696 }
19697
19698 static const Jim_ObjType subcmdLookupObjType = {
19699 "subcmd-lookup",
19700 NULL,
19701 NULL,
19702 NULL,
19703 JIM_TYPE_REFERENCES
19704 };
19705
19706 const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
19707 int argc, Jim_Obj *const *argv)
19708 {
19709 const jim_subcmd_type *ct;
19710 const jim_subcmd_type *partial = 0;
19711 int cmdlen;
19712 Jim_Obj *cmd;
19713 const char *cmdstr;
 
19714 int help = 0;
19715
 
 
19716 if (argc < 2) {
19717 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n"
19718 "Use \"%#s -help ?command?\" for help", argv[0], argv[0]);
 
 
19719 return 0;
19720 }
19721
19722 cmd = argv[1];
19723
19724
19725 if (cmd->typePtr == &subcmdLookupObjType) {
19726 if (cmd->internalRep.ptrIntValue.ptr == command_table) {
19727 ct = command_table + cmd->internalRep.ptrIntValue.int1;
19728 goto found;
19729 }
19730 }
19731
19732
19733 if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
19734 if (argc == 2) {
19735
19736 show_cmd_usage(interp, command_table, argc, argv);
19737 return &dummy_subcmd;
19738 }
19739 help = 1;
19740
19741
19742 cmd = argv[2];
19743 }
19744
19745
19746 if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19747
19748 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19749 add_commands(interp, command_table, " ");
19750 return &dummy_subcmd;
19751 }
19752
19753 cmdstr = Jim_GetString(cmd, &cmdlen);
19754
19755 for (ct = command_table; ct->cmd; ct++) {
19756 if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19757
19758 break;
19759 }
19760 if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
19761 if (partial) {
19762
19763 if (help) {
19764
19765 show_cmd_usage(interp, command_table, argc, argv);
19766 return &dummy_subcmd;
19767 }
19768 bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
19769 return 0;
@@ -19931,44 +19771,51 @@
19771 partial = ct;
19772 }
19773 continue;
19774 }
19775
19776
19777 if (partial && !ct->cmd) {
19778 ct = partial;
19779 }
19780
19781 if (!ct->cmd) {
19782
19783 if (help) {
19784
19785 show_cmd_usage(interp, command_table, argc, argv);
19786 return &dummy_subcmd;
19787 }
19788 bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
19789 return 0;
19790 }
19791
19792 if (help) {
19793 Jim_SetResultString(interp, "Usage: ", -1);
19794
19795 add_cmd_usage(interp, ct, argv[0]);
19796 return &dummy_subcmd;
19797 }
19798
19799
19800 Jim_FreeIntRep(interp, cmd);
19801 cmd->typePtr = &subcmdLookupObjType;
19802 cmd->internalRep.ptrIntValue.ptr = (void *)command_table;
19803 cmd->internalRep.ptrIntValue.int1 = ct - command_table;
19804
19805 found:
19806
19807 if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
19808 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19809
19810 add_cmd_usage(interp, ct, argv[0]);
19811 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19812
19813 return 0;
19814 }
19815
19816
19817 return ct;
19818 }
19819
19820 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
19821 {
@@ -20019,11 +19866,11 @@
19866 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
19867 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
19868 *p = 0x80 | (uc & 0x3f);
19869 return 3;
19870 }
19871
19872 else {
19873 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
19874 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
19875 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
19876 *p = 0x80 | (uc & 0x3f);
@@ -20146,11 +19993,12 @@
19993 continue;
19994 }
19995 *p++ = ch;
19996 format += step;
19997 step = utf8_tounicode(format, &ch);
19998
19999 } while (sawFlag && (p - spec <= 5));
20000
20001
20002 width = 0;
20003 if (isdigit(ch)) {
20004 width = strtoul(format, &end, 10);
@@ -20210,11 +20058,11 @@
20058 if (ch == 'h') {
20059 useShort = 1;
20060 format += step;
20061 step = utf8_tounicode(format, &ch);
20062 } else if (ch == 'l') {
20063
20064 format += step;
20065 step = utf8_tounicode(format, &ch);
20066 if (ch == 'l') {
20067 format += step;
20068 step = utf8_tounicode(format, &ch);
@@ -20237,11 +20085,11 @@
20085 goto errorMsg;
20086 case 's': {
20087 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
20088 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
20089 if (gotPrecision && (precision < formatted_chars)) {
20090
20091 formatted_chars = precision;
20092 formatted_bytes = utf8_index(formatted_buf, precision);
20093 }
20094 break;
20095 }
@@ -20249,11 +20097,11 @@
20097 jim_wide code;
20098
20099 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20100 goto error;
20101 }
20102
20103 formatted_bytes = utf8_getchars(spec, code);
20104 formatted_buf = spec;
20105 formatted_chars = 1;
20106 break;
20107 }
@@ -20267,11 +20115,11 @@
20115 goto error;
20116 }
20117 length = sizeof(w) * 8;
20118
20119
20120
20121 if (num_buffer_size < length + 1) {
20122 num_buffer_size = length + 1;
20123 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20124 }
20125
@@ -20295,29 +20143,29 @@
20143 case 'E':
20144 case 'f':
20145 case 'g':
20146 case 'G':
20147 doubleType = 1;
20148
20149 case 'd':
20150 case 'u':
20151 case 'o':
20152 case 'x':
20153 case 'X': {
20154 jim_wide w;
20155 double d;
20156 int length;
20157
20158
20159 if (width) {
20160 p += sprintf(p, "%ld", width);
20161 }
20162 if (gotPrecision) {
20163 p += sprintf(p, ".%ld", precision);
20164 }
20165
20166
20167 if (doubleType) {
20168 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20169 goto error;
20170 }
20171 length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20192,26 @@
20192 }
20193
20194 *p++ = (char) ch;
20195 *p = '\0';
20196
20197
20198 if (width > 10000 || length > 10000 || precision > 10000) {
20199 Jim_SetResultString(interp, "format too long", -1);
20200 goto error;
20201 }
20202
20203
20204
20205 if (width > length) {
20206 length = width;
20207 }
20208 if (gotPrecision) {
20209 length += precision;
20210 }
20211
20212
20213 if (num_buffer_size < length + 1) {
20214 num_buffer_size = length + 1;
20215 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20216 }
20217
@@ -20370,11 +20225,11 @@
20225 formatted_buf = num_buffer;
20226 break;
20227 }
20228
20229 default: {
20230
20231 spec[0] = ch;
20232 spec[1] = '\0';
20233 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20234 goto error;
20235 }
@@ -20422,37 +20277,37 @@
20277
20278 #define REG_MAX_PAREN 100
20279
20280
20281
20282 #define END 0
20283 #define BOL 1
20284 #define EOL 2
20285 #define ANY 3
20286 #define ANYOF 4
20287 #define ANYBUT 5
20288 #define BRANCH 6
20289 #define BACK 7
20290 #define EXACTLY 8
20291 #define NOTHING 9
20292 #define REP 10
20293 #define REPMIN 11
20294 #define REPX 12
20295 #define REPXMIN 13
20296 #define BOLX 14
20297 #define EOLX 15
20298 #define WORDA 16
20299 #define WORDZ 17
20300
20301 #define OPENNC 1000
20302 #define OPEN 1001
20303
20304
20305
20306
20307 #define CLOSENC 2000
20308 #define CLOSE 2001
20309 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
20310
20311 #define REG_MAGIC 0xFADED00D
20312
20313
@@ -20465,18 +20320,18 @@
20320
20321 #define FAIL(R,M) { (R)->err = (M); return (M); }
20322 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20323 #define META "^$.[()|?{+*"
20324
20325 #define HASWIDTH 1
20326 #define SIMPLE 2
20327 #define SPSTART 4
20328 #define WORST 0
20329
20330 #define MAX_REP_COUNT 1000000
20331
20332 static int reg(regex_t *preg, int paren, int *flagp );
20333 static int regpiece(regex_t *preg, int *flagp );
20334 static int regbranch(regex_t *preg, int *flagp );
20335 static int regatom(regex_t *preg, int *flagp );
20336 static int regnode(regex_t *preg, int op );
20337 static int regnext(regex_t *preg, int p );
@@ -20520,15 +20375,15 @@
20375 memset(preg, 0, sizeof(*preg));
20376
20377 if (exp == NULL)
20378 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20379
20380
20381 preg->cflags = cflags;
20382 preg->regparse = exp;
20383
20384
20385 preg->proglen = (strlen(exp) + 1) * 5;
20386 preg->program = malloc(preg->proglen * sizeof(int));
20387 if (preg->program == NULL)
20388 FAIL(preg, REG_ERR_NOMEM);
20389
@@ -20535,24 +20390,24 @@
20390 regc(preg, REG_MAGIC);
20391 if (reg(preg, 0, &flags) == 0) {
20392 return preg->err;
20393 }
20394
20395
20396 if (preg->re_nsub >= REG_MAX_PAREN)
20397 FAIL(preg,REG_ERR_TOO_BIG);
20398
20399
20400 preg->regstart = 0;
20401 preg->reganch = 0;
20402 preg->regmust = 0;
20403 preg->regmlen = 0;
20404 scan = 1;
20405 if (OP(preg, regnext(preg, scan)) == END) {
20406 scan = OPERAND(scan);
20407
20408
20409 if (OP(preg, scan) == EXACTLY) {
20410 preg->regstart = preg->program[OPERAND(scan)];
20411 }
20412 else if (OP(preg, scan) == BOL)
20413 preg->reganch++;
@@ -20579,24 +20434,24 @@
20434 #endif
20435
20436 return 0;
20437 }
20438
20439 static int reg(regex_t *preg, int paren, int *flagp )
20440 {
20441 int ret;
20442 int br;
20443 int ender;
20444 int parno = 0;
20445 int flags;
20446
20447 *flagp = HASWIDTH;
20448
20449
20450 if (paren) {
20451 if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20452
20453 preg->regparse += 2;
20454 parno = -1;
20455 }
20456 else {
20457 parno = ++preg->re_nsub;
@@ -20603,16 +20458,16 @@
20458 }
20459 ret = regnode(preg, OPEN+parno);
20460 } else
20461 ret = 0;
20462
20463
20464 br = regbranch(preg, &flags);
20465 if (br == 0)
20466 return 0;
20467 if (ret != 0)
20468 regtail(preg, ret, br);
20469 else
20470 ret = br;
20471 if (!(flags&HASWIDTH))
20472 *flagp &= ~HASWIDTH;
20473 *flagp |= flags&SPSTART;
@@ -20619,25 +20474,25 @@
20474 while (*preg->regparse == '|') {
20475 preg->regparse++;
20476 br = regbranch(preg, &flags);
20477 if (br == 0)
20478 return 0;
20479 regtail(preg, ret, br);
20480 if (!(flags&HASWIDTH))
20481 *flagp &= ~HASWIDTH;
20482 *flagp |= flags&SPSTART;
20483 }
20484
20485
20486 ender = regnode(preg, (paren) ? CLOSE+parno : END);
20487 regtail(preg, ret, ender);
20488
20489
20490 for (br = ret; br != 0; br = regnext(preg, br))
20491 regoptail(preg, br, ender);
20492
20493
20494 if (paren && *preg->regparse++ != ')') {
20495 preg->err = REG_ERR_UNMATCHED_PAREN;
20496 return 0;
20497 } else if (!paren && *preg->regparse != '\0') {
20498 if (*preg->regparse == ')') {
@@ -20657,11 +20512,11 @@
20512 int ret;
20513 int chain;
20514 int latest;
20515 int flags;
20516
20517 *flagp = WORST;
20518
20519 ret = regnode(preg, BRANCH);
20520 chain = 0;
20521 while (*preg->regparse != '\0' && *preg->regparse != ')' &&
20522 *preg->regparse != '|') {
@@ -20675,11 +20530,11 @@
20530 else {
20531 regtail(preg, chain, latest);
20532 }
20533 chain = latest;
20534 }
20535 if (chain == 0)
20536 (void) regnode(preg, NOTHING);
20537
20538 return(ret);
20539 }
20540
@@ -20705,11 +20560,11 @@
20560 if (!(flags&HASWIDTH) && op != '?') {
20561 preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
20562 return 0;
20563 }
20564
20565
20566 if (op == '{') {
20567 char *end;
20568
20569 min = strtoul(preg->regparse + 1, &end, 10);
20570 if (end == preg->regparse + 1) {
@@ -20716,10 +20571,14 @@
20571 preg->err = REG_ERR_BAD_COUNT;
20572 return 0;
20573 }
20574 if (*end == '}') {
20575 max = min;
20576 }
20577 else if (*end == '\0') {
20578 preg->err = REG_ERR_UNMATCHED_BRACES;
20579 return 0;
20580 }
20581 else {
20582 preg->regparse = end;
20583 max = strtoul(preg->regparse + 1, &end, 10);
20584 if (*end != '}') {
@@ -20777,11 +20636,11 @@
20636 static void reg_addrange(regex_t *preg, int lower, int upper)
20637 {
20638 if (lower > upper) {
20639 reg_addrange(preg, upper, lower);
20640 }
20641
20642 regc(preg, upper - lower + 1);
20643 regc(preg, lower);
20644 }
20645
20646 static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20704,17 @@
20704 case 'r': *ch = '\r'; break;
20705 case 't': *ch = '\t'; break;
20706 case 'v': *ch = '\v'; break;
20707 case 'u':
20708 if (*s == '{') {
20709
20710 n = parse_hex(s + 1, 6, ch);
20711 if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
20712 s += n + 2;
20713 }
20714 else {
20715
20716 *ch = 'u';
20717 }
20718 }
20719 else if ((n = parse_hex(s, 4, ch)) > 0) {
20720 s += n;
@@ -20886,15 +20745,15 @@
20745 int nocase = (preg->cflags & REG_ICASE);
20746
20747 int ch;
20748 int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
20749
20750 *flagp = WORST;
20751
20752 preg->regparse += n;
20753 switch (ch) {
20754
20755 case '^':
20756 ret = regnode(preg, BOL);
20757 break;
20758 case '$':
20759 ret = regnode(preg, EOL);
@@ -20904,37 +20763,60 @@
20763 *flagp |= HASWIDTH|SIMPLE;
20764 break;
20765 case '[': {
20766 const char *pattern = preg->regparse;
20767
20768 if (*pattern == '^') {
20769 ret = regnode(preg, ANYBUT);
20770 pattern++;
20771 } else
20772 ret = regnode(preg, ANYOF);
20773
20774
20775 if (*pattern == ']' || *pattern == '-') {
20776 reg_addrange(preg, *pattern, *pattern);
20777 pattern++;
20778 }
20779
20780 while (*pattern && *pattern != ']') {
20781
20782 int start;
20783 int end;
20784
20785 enum {
20786 CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
20787 CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
20788 CC_NUM
20789 };
20790 int cc;
20791
20792 pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
20793 if (start == '\\') {
20794
20795 switch (*pattern) {
20796 case 's':
20797 pattern++;
20798 cc = CC_SPACE;
20799 goto cc_switch;
20800 case 'd':
20801 pattern++;
20802 cc = CC_DIGIT;
20803 goto cc_switch;
20804 case 'w':
20805 pattern++;
20806 reg_addrange(preg, '_', '_');
20807 cc = CC_ALNUM;
20808 goto cc_switch;
20809 }
20810 pattern += reg_decode_escape(pattern, &start);
20811 if (start == 0) {
20812 preg->err = REG_ERR_NULL_CHAR;
20813 return 0;
20814 }
20815 }
20816 if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20817
20818 pattern += utf8_tounicode(pattern, &end);
20819 pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
20820 if (end == '\\') {
20821 pattern += reg_decode_escape(pattern, &end);
20822 if (end == 0) {
@@ -20949,30 +20831,25 @@
20831 if (start == '[' && pattern[0] == ':') {
20832 static const char *character_class[] = {
20833 ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:",
20834 ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:",
20835 };
20836
20837 for (cc = 0; cc < CC_NUM; cc++) {
20838 n = strlen(character_class[cc]);
20839 if (strncmp(pattern, character_class[cc], n) == 0) {
20840
 
 
 
 
 
 
20841 pattern += n + 1;
20842 break;
20843 }
20844 }
20845 if (cc != CC_NUM) {
20846 cc_switch:
20847 switch (cc) {
20848 case CC_ALNUM:
20849 reg_addrange(preg, '0', '9');
20850
20851 case CC_ALPHA:
20852 if ((preg->cflags & REG_ICASE) == 0) {
20853 reg_addrange(preg, 'a', 'z');
20854 }
20855 reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20867,11 @@
20867 reg_addrange(preg, 'a', 'z');
20868 break;
20869 case CC_XDIGIT:
20870 reg_addrange(preg, 'a', 'f');
20871 reg_addrange(preg, 'A', 'F');
20872
20873 case CC_DIGIT:
20874 reg_addrange(preg, '0', '9');
20875 break;
20876 case CC_CNTRL:
20877 reg_addrange(preg, 0, 31);
@@ -21014,11 +20891,11 @@
20891 break;
20892 }
20893 continue;
20894 }
20895 }
20896
20897 reg_addrange(preg, start, start);
20898 }
20899 regc(preg, '\0');
20900
20901 if (*pattern) {
@@ -21037,11 +20914,11 @@
20914 break;
20915 case '\0':
20916 case '|':
20917 case ')':
20918 preg->err = REG_ERR_INTERNAL;
20919 return 0;
20920 case '?':
20921 case '+':
20922 case '*':
20923 case '{':
20924 preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +20967,34 @@
20967 ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
20968 reg_addrange_str(preg," \t\r\n\f\v");
20969 regc(preg, '\0');
20970 *flagp |= HASWIDTH|SIMPLE;
20971 break;
20972
20973 default:
20974
20975
20976 preg->regparse--;
20977 goto de_fault;
20978 }
20979 break;
20980 de_fault:
20981 default: {
20982 int added = 0;
20983
20984
20985 preg->regparse -= n;
20986
20987 ret = regnode(preg, EXACTLY);
20988
20989
20990
20991 while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
20992 n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
20993 if (ch == '\\' && preg->regparse[n]) {
20994 if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
20995
20996 break;
20997 }
20998 n += reg_decode_escape(preg->regparse + n, &ch);
20999 if (ch == 0) {
21000 preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21002,23 @@
21002 }
21003 }
21004
21005
21006 if (ISMULT(preg->regparse[n])) {
21007
21008 if (added) {
21009
21010 break;
21011 }
21012
21013 regc(preg, ch);
21014 added++;
21015 preg->regparse += n;
21016 break;
21017 }
21018
21019
21020 regc(preg, ch);
21021 added++;
21022 preg->regparse += n;
21023 }
21024 regc(preg, '\0');
@@ -21168,15 +21045,15 @@
21045
21046 static int regnode(regex_t *preg, int op)
21047 {
21048 reg_grow(preg, 2);
21049
21050
21051 preg->program[preg->p++] = op;
21052 preg->program[preg->p++] = 0;
21053
21054
21055 return preg->p - 2;
21056 }
21057
21058 static void regc(regex_t *preg, int b )
21059 {
@@ -21186,13 +21063,13 @@
21063
21064 static int reginsert(regex_t *preg, int op, int size, int opnd )
21065 {
21066 reg_grow(preg, size);
21067
21068
21069 memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21070
21071 memset(preg->program + opnd, 0, sizeof(int) * size);
21072
21073 preg->program[opnd] = op;
21074
21075 preg->p += size;
@@ -21204,11 +21081,11 @@
21081 {
21082 int scan;
21083 int temp;
21084 int offset;
21085
21086
21087 scan = p;
21088 for (;;) {
21089 temp = regnext(preg, scan);
21090 if (temp == 0)
21091 break;
@@ -21224,11 +21101,11 @@
21101 }
21102
21103
21104 static void regoptail(regex_t *preg, int p, int val )
21105 {
21106
21107 if (p != 0 && OP(preg, p) == BRANCH) {
21108 regtail(preg, OPERAND(p), val);
21109 }
21110 }
21111
@@ -21240,16 +21117,16 @@
21117 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
21118 {
21119 const char *s;
21120 int scan;
21121
21122
21123 if (preg == NULL || preg->program == NULL || string == NULL) {
21124 return REG_ERR_NULL_ARGUMENT;
21125 }
21126
21127
21128 if (*preg->program != REG_MAGIC) {
21129 return REG_ERR_CORRUPTED;
21130 }
21131
21132 #ifdef DEBUG
@@ -21258,51 +21135,51 @@
21135 #endif
21136
21137 preg->eflags = eflags;
21138 preg->pmatch = pmatch;
21139 preg->nmatch = nmatch;
21140 preg->start = string;
21141
21142
21143 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
21144 int op = OP(preg, scan);
21145 if (op == END)
21146 break;
21147 if (op == REPX || op == REPXMIN)
21148 preg->program[scan + 4] = 0;
21149 }
21150
21151
21152 if (preg->regmust != 0) {
21153 s = string;
21154 while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
21155 if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
21156 break;
21157 }
21158 s++;
21159 }
21160 if (s == NULL)
21161 return REG_NOMATCH;
21162 }
21163
21164
21165 preg->regbol = string;
21166
21167
21168 if (preg->reganch) {
21169 if (eflags & REG_NOTBOL) {
21170
21171 goto nextline;
21172 }
21173 while (1) {
21174 if (regtry(preg, string)) {
21175 return REG_NOERROR;
21176 }
21177 if (*string) {
21178 nextline:
21179 if (preg->cflags & REG_NEWLINE) {
21180
21181 string = strchr(string, '\n');
21182 if (string) {
21183 preg->regbol = ++string;
21184 continue;
21185 }
@@ -21310,22 +21187,22 @@
21187 }
21188 return REG_NOMATCH;
21189 }
21190 }
21191
21192
21193 s = string;
21194 if (preg->regstart != '\0') {
21195
21196 while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
21197 if (regtry(preg, s))
21198 return REG_NOERROR;
21199 s++;
21200 }
21201 }
21202 else
21203
21204 while (1) {
21205 if (regtry(preg, s))
21206 return REG_NOERROR;
21207 if (*s == '\0') {
21208 break;
@@ -21334,15 +21211,15 @@
21211 int c;
21212 s += utf8_tounicode(s, &c);
21213 }
21214 }
21215
21216
21217 return REG_NOMATCH;
21218 }
21219
21220
21221 static int regtry( regex_t *preg, const char *string )
21222 {
21223 int i;
21224
21225 preg->reginput = string;
@@ -21379,11 +21256,11 @@
21256 }
21257
21258 static int reg_range_find(const int *range, int c)
21259 {
21260 while (*range) {
21261
21262 if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
21263 return 1;
21264 }
21265 range += 2;
21266 }
@@ -21391,11 +21268,11 @@
21268 }
21269
21270 static const char *str_find(const char *string, int c, int nocase)
21271 {
21272 if (nocase) {
21273
21274 c = utf8_upper(c);
21275 }
21276 while (*string) {
21277 int ch;
21278 int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21312,15 @@
21312 no = regrepeat(preg, scan + 5, max);
21313 if (no < min) {
21314 return 0;
21315 }
21316 if (matchmin) {
21317
21318 max = no;
21319 no = min;
21320 }
21321
21322 while (1) {
21323 if (matchmin) {
21324 if (no > max) {
21325 break;
21326 }
@@ -21453,22 +21330,22 @@
21330 break;
21331 }
21332 }
21333 preg->reginput = save + utf8_index(save, no);
21334 reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21335
21336 if (reg_iseol(preg, nextch) || c == nextch) {
21337 if (regmatch(preg, next)) {
21338 return(1);
21339 }
21340 }
21341 if (matchmin) {
21342
21343 no++;
21344 }
21345 else {
21346
21347 no--;
21348 }
21349 }
21350 return(0);
21351 }
@@ -21478,13 +21355,13 @@
21355 int *scanpt = preg->program + scan;
21356
21357 int max = scanpt[2];
21358 int min = scanpt[3];
21359
21360
21361 if (scanpt[4] < min) {
21362
21363 scanpt[4]++;
21364 if (regmatch(preg, scan + 5)) {
21365 return 1;
21366 }
21367 scanpt[4]--;
@@ -21493,39 +21370,39 @@
21370 if (scanpt[4] > max) {
21371 return 0;
21372 }
21373
21374 if (matchmin) {
21375
21376 if (regmatch(preg, regnext(preg, scan))) {
21377 return 1;
21378 }
21379
21380 scanpt[4]++;
21381 if (regmatch(preg, scan + 5)) {
21382 return 1;
21383 }
21384 scanpt[4]--;
21385 return 0;
21386 }
21387
21388 if (scanpt[4] < max) {
21389 scanpt[4]++;
21390 if (regmatch(preg, scan + 5)) {
21391 return 1;
21392 }
21393 scanpt[4]--;
21394 }
21395
21396 return regmatch(preg, regnext(preg, scan));
21397 }
21398
21399
21400 static int regmatch(regex_t *preg, int prog)
21401 {
21402 int scan;
21403 int next;
21404 const char *save;
21405
21406 scan = prog;
21407
21408 #ifdef DEBUG
@@ -21535,11 +21412,11 @@
21412 while (scan != 0) {
21413 int n;
21414 int c;
21415 #ifdef DEBUG
21416 if (regnarrate) {
21417 fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21418 }
21419 #endif
21420 next = regnext(preg, scan);
21421 n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21422
@@ -21546,49 +21423,49 @@
21423 switch (OP(preg, scan)) {
21424 case BOLX:
21425 if ((preg->eflags & REG_NOTBOL)) {
21426 return(0);
21427 }
21428
21429 case BOL:
21430 if (preg->reginput != preg->regbol) {
21431 return(0);
21432 }
21433 break;
21434 case EOLX:
21435 if (c != 0) {
21436
21437 return 0;
21438 }
21439 break;
21440 case EOL:
21441 if (!reg_iseol(preg, c)) {
21442 return(0);
21443 }
21444 break;
21445 case WORDA:
21446
21447 if ((!isalnum(UCHAR(c))) && c != '_')
21448 return(0);
21449
21450 if (preg->reginput > preg->regbol &&
21451 (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
21452 return(0);
21453 break;
21454 case WORDZ:
21455
21456 if (preg->reginput > preg->regbol) {
21457
21458 if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
21459 c = preg->reginput[-1];
21460
21461 if (isalnum(UCHAR(c)) || c == '_') {
21462 break;
21463 }
21464 }
21465 }
21466
21467 return(0);
21468
21469 case ANY:
21470 if (reg_iseol(preg, c))
21471 return 0;
@@ -21624,12 +21501,12 @@
21501 case NOTHING:
21502 break;
21503 case BACK:
21504 break;
21505 case BRANCH:
21506 if (OP(preg, next) != BRANCH)
21507 next = OPERAND(scan);
21508 else {
21509 do {
21510 save = preg->reginput;
21511 if (regmatch(preg, OPERAND(scan))) {
21512 return(1);
@@ -21636,11 +21513,11 @@
21513 }
21514 preg->reginput = save;
21515 scan = regnext(preg, scan);
21516 } while (scan != 0 && OP(preg, scan) == BRANCH);
21517 return(0);
21518
21519 }
21520 break;
21521 case REP:
21522 case REPMIN:
21523 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21525,11 @@
21525 case REPX:
21526 case REPXMIN:
21527 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21528
21529 case END:
21530 return 1;
21531
21532 case OPENNC:
21533 case CLOSENC:
21534 return regmatch(preg, next);
21535
@@ -21695,11 +21572,11 @@
21572
21573 scan = preg->reginput;
21574 opnd = OPERAND(p);
21575 switch (OP(preg, p)) {
21576 case ANY:
21577
21578 while (!reg_iseol(preg, *scan) && count < max) {
21579 count++;
21580 scan++;
21581 }
21582 break;
@@ -21731,13 +21608,13 @@
21608 }
21609 count++;
21610 scan += n;
21611 }
21612 break;
21613 default:
21614 preg->err = REG_ERR_INTERNAL;
21615 count = 0;
21616 break;
21617 }
21618 preg->reginput = scan;
21619
21620 return(count);
@@ -21758,11 +21635,11 @@
21635 return(p+offset);
21636 }
21637
21638 static int regopsize(regex_t *preg, int p )
21639 {
21640
21641 switch (OP(preg, p)) {
21642 case REP:
21643 case REPMIN:
21644 case REPX:
21645 case REPXMIN:
@@ -21818,10 +21695,223 @@
21695
21696 void regfree(regex_t *preg)
21697 {
21698 free(preg->program);
21699 }
21700
21701 #endif
21702 #include <string.h>
21703
21704 void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
21705 {
21706 Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
21707 }
21708
21709 #if defined(__MINGW32__)
21710 #include <sys/stat.h>
21711
21712 int Jim_Errno(void)
21713 {
21714 switch (GetLastError()) {
21715 case ERROR_FILE_NOT_FOUND: return ENOENT;
21716 case ERROR_PATH_NOT_FOUND: return ENOENT;
21717 case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
21718 case ERROR_ACCESS_DENIED: return EACCES;
21719 case ERROR_INVALID_HANDLE: return EBADF;
21720 case ERROR_BAD_ENVIRONMENT: return E2BIG;
21721 case ERROR_BAD_FORMAT: return ENOEXEC;
21722 case ERROR_INVALID_ACCESS: return EACCES;
21723 case ERROR_INVALID_DRIVE: return ENOENT;
21724 case ERROR_CURRENT_DIRECTORY: return EACCES;
21725 case ERROR_NOT_SAME_DEVICE: return EXDEV;
21726 case ERROR_NO_MORE_FILES: return ENOENT;
21727 case ERROR_WRITE_PROTECT: return EROFS;
21728 case ERROR_BAD_UNIT: return ENXIO;
21729 case ERROR_NOT_READY: return EBUSY;
21730 case ERROR_BAD_COMMAND: return EIO;
21731 case ERROR_CRC: return EIO;
21732 case ERROR_BAD_LENGTH: return EIO;
21733 case ERROR_SEEK: return EIO;
21734 case ERROR_WRITE_FAULT: return EIO;
21735 case ERROR_READ_FAULT: return EIO;
21736 case ERROR_GEN_FAILURE: return EIO;
21737 case ERROR_SHARING_VIOLATION: return EACCES;
21738 case ERROR_LOCK_VIOLATION: return EACCES;
21739 case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
21740 case ERROR_HANDLE_DISK_FULL: return ENOSPC;
21741 case ERROR_NOT_SUPPORTED: return ENODEV;
21742 case ERROR_REM_NOT_LIST: return EBUSY;
21743 case ERROR_DUP_NAME: return EEXIST;
21744 case ERROR_BAD_NETPATH: return ENOENT;
21745 case ERROR_NETWORK_BUSY: return EBUSY;
21746 case ERROR_DEV_NOT_EXIST: return ENODEV;
21747 case ERROR_TOO_MANY_CMDS: return EAGAIN;
21748 case ERROR_ADAP_HDW_ERR: return EIO;
21749 case ERROR_BAD_NET_RESP: return EIO;
21750 case ERROR_UNEXP_NET_ERR: return EIO;
21751 case ERROR_NETNAME_DELETED: return ENOENT;
21752 case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
21753 case ERROR_BAD_DEV_TYPE: return ENODEV;
21754 case ERROR_BAD_NET_NAME: return ENOENT;
21755 case ERROR_TOO_MANY_NAMES: return ENFILE;
21756 case ERROR_TOO_MANY_SESS: return EIO;
21757 case ERROR_SHARING_PAUSED: return EAGAIN;
21758 case ERROR_REDIR_PAUSED: return EAGAIN;
21759 case ERROR_FILE_EXISTS: return EEXIST;
21760 case ERROR_CANNOT_MAKE: return ENOSPC;
21761 case ERROR_OUT_OF_STRUCTURES: return ENFILE;
21762 case ERROR_ALREADY_ASSIGNED: return EEXIST;
21763 case ERROR_INVALID_PASSWORD: return EPERM;
21764 case ERROR_NET_WRITE_FAULT: return EIO;
21765 case ERROR_NO_PROC_SLOTS: return EAGAIN;
21766 case ERROR_DISK_CHANGE: return EXDEV;
21767 case ERROR_BROKEN_PIPE: return EPIPE;
21768 case ERROR_OPEN_FAILED: return ENOENT;
21769 case ERROR_DISK_FULL: return ENOSPC;
21770 case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
21771 case ERROR_INVALID_TARGET_HANDLE: return EBADF;
21772 case ERROR_INVALID_NAME: return ENOENT;
21773 case ERROR_PROC_NOT_FOUND: return ESRCH;
21774 case ERROR_WAIT_NO_CHILDREN: return ECHILD;
21775 case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
21776 case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
21777 case ERROR_SEEK_ON_DEVICE: return ESPIPE;
21778 case ERROR_BUSY_DRIVE: return EAGAIN;
21779 case ERROR_DIR_NOT_EMPTY: return EEXIST;
21780 case ERROR_NOT_LOCKED: return EACCES;
21781 case ERROR_BAD_PATHNAME: return ENOENT;
21782 case ERROR_LOCK_FAILED: return EACCES;
21783 case ERROR_ALREADY_EXISTS: return EEXIST;
21784 case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
21785 case ERROR_BAD_PIPE: return EPIPE;
21786 case ERROR_PIPE_BUSY: return EAGAIN;
21787 case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
21788 case ERROR_DIRECTORY: return ENOTDIR;
21789 }
21790 return EINVAL;
21791 }
21792
21793 pidtype waitpid(pidtype pid, int *status, int nohang)
21794 {
21795 DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
21796 if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
21797
21798 return JIM_BAD_PID;
21799 }
21800 GetExitCodeProcess(pid, &ret);
21801 *status = ret;
21802 CloseHandle(pid);
21803 return pid;
21804 }
21805
21806 int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
21807 {
21808 char name[MAX_PATH];
21809 HANDLE handle;
21810
21811 if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) {
21812 return -1;
21813 }
21814
21815 handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
21816 CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0),
21817 NULL);
21818
21819 if (handle == INVALID_HANDLE_VALUE) {
21820 goto error;
21821 }
21822
21823 Jim_SetResultString(interp, name, -1);
21824 return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT);
21825
21826 error:
21827 Jim_SetResultErrno(interp, name);
21828 DeleteFile(name);
21829 return -1;
21830 }
21831
21832 int Jim_OpenForWrite(const char *filename, int append)
21833 {
21834 if (strcmp(filename, "/dev/null") == 0) {
21835 filename = "nul:";
21836 }
21837 int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE);
21838 if (fd >= 0 && append) {
21839
21840 _lseek(fd, 0L, SEEK_END);
21841 }
21842 return fd;
21843 }
21844
21845 int Jim_OpenForRead(const char *filename)
21846 {
21847 if (strcmp(filename, "/dev/null") == 0) {
21848 filename = "nul:";
21849 }
21850 return _open(filename, _O_RDONLY | _O_TEXT, 0);
21851 }
21852
21853 #elif defined(HAVE_UNISTD_H)
21854
21855
21856
21857 int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
21858 {
21859 int fd;
21860 mode_t mask;
21861 Jim_Obj *filenameObj;
21862
21863 if (filename_template == NULL) {
21864 const char *tmpdir = getenv("TMPDIR");
21865 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
21866 tmpdir = "/tmp/";
21867 }
21868 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
21869 if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
21870 Jim_AppendString(interp, filenameObj, "/", 1);
21871 }
21872 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
21873 }
21874 else {
21875 filenameObj = Jim_NewStringObj(interp, filename_template, -1);
21876 }
21877
21878
21879 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
21880 #ifdef HAVE_MKSTEMP
21881 fd = mkstemp(filenameObj->bytes);
21882 #else
21883 if (mktemp(filenameObj->bytes) == NULL) {
21884 fd = -1;
21885 }
21886 else {
21887 fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC);
21888 }
21889 #endif
21890 umask(mask);
21891 if (fd < 0) {
21892 Jim_SetResultErrno(interp, Jim_String(filenameObj));
21893 Jim_FreeNewObj(interp, filenameObj);
21894 return -1;
21895 }
21896 if (unlink_file) {
21897 remove(Jim_String(filenameObj));
21898 }
21899
21900 Jim_SetResult(interp, filenameObj);
21901 return fd;
21902 }
21903
21904 int Jim_OpenForWrite(const char *filename, int append)
21905 {
21906 return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
21907 }
21908
21909 int Jim_OpenForRead(const char *filename)
21910 {
21911 return open(filename, O_RDONLY, 0);
21912 }
21913
21914 #endif
21915
21916 #if defined(_WIN32) || defined(WIN32)
21917 #ifndef STRICT
@@ -21879,26 +21969,26 @@
21969 {
21970 DIR *dir = 0;
21971
21972 if (name && name[0]) {
21973 size_t base_length = strlen(name);
21974 const char *all =
21975 strchr("/\\", name[base_length - 1]) ? "*" : "/*";
21976
21977 if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
21978 (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
21979 strcat(strcpy(dir->name, name), all);
21980
21981 if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
21982 dir->result.d_name = 0;
21983 else {
21984 Jim_Free(dir->name);
21985 Jim_Free(dir);
21986 dir = 0;
21987 }
21988 }
21989 else {
21990 Jim_Free(dir);
21991 dir = 0;
21992 errno = ENOMEM;
21993 }
21994 }
@@ -21916,11 +22006,11 @@
22006 if (dir->handle != -1)
22007 result = _findclose(dir->handle);
22008 Jim_Free(dir->name);
22009 Jim_Free(dir);
22010 }
22011 if (result == -1)
22012 errno = EBADF;
22013 return result;
22014 }
22015
22016 struct dirent *readdir(DIR * dir)
@@ -21938,28 +22028,77 @@
22028 }
22029 return result;
22030 }
22031 #endif
22032 #endif
22033 #include <stdio.h>
22034 #include <signal.h>
22035
22036
22037
22038
22039
22040
22041 #ifndef SIGPIPE
22042 #define SIGPIPE 13
22043 #endif
22044 #ifndef SIGINT
22045 #define SIGINT 2
22046 #endif
22047
22048 const char *Jim_SignalId(int sig)
22049 {
22050 static char buf[10];
22051 switch (sig) {
22052 case SIGINT: return "SIGINT";
22053 case SIGPIPE: return "SIGPIPE";
22054
22055 }
22056 snprintf(buf, sizeof(buf), "%d", sig);
22057 return buf;
22058 }
22059 #ifndef JIM_BOOTSTRAP_LIB_ONLY
22060 #include <errno.h>
22061 #include <string.h>
22062
22063
22064 #ifdef USE_LINENOISE
22065 #ifdef HAVE_UNISTD_H
22066 #include <unistd.h>
22067 #endif
22068 #ifdef HAVE_SYS_STAT_H
22069 #include <sys/stat.h>
22070 #endif
22071 #include "linenoise.h"
22072 #else
22073 #define MAX_LINE_LEN 512
22074 #endif
22075
22076 #ifdef USE_LINENOISE
22077 static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata);
22078 static const char completion_callback_assoc_key[] = "interactive-completion";
22079 #endif
22080
22081 char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt)
22082 {
22083 #ifdef USE_LINENOISE
22084 struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key);
22085 char *result;
22086 Jim_Obj *objPtr;
22087 long mlmode = 0;
22088 if (compinfo) {
22089 linenoiseSetCompletionCallback(JimCompletionCallback, compinfo);
22090 }
22091 objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE);
22092 if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) {
22093 linenoiseSetMultiLine(mlmode);
22094 }
22095
22096 result = linenoise(prompt);
22097
22098 linenoiseSetCompletionCallback(NULL, NULL);
22099 return result;
22100 #else
22101 int len;
22102 char *line = malloc(MAX_LINE_LEN);
22103
22104 fputs(prompt, stdout);
@@ -21992,26 +22131,92 @@
22131 }
22132
22133 void Jim_HistorySave(const char *filename)
22134 {
22135 #ifdef USE_LINENOISE
22136 #ifdef HAVE_UMASK
22137 mode_t mask;
22138
22139 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
22140 #endif
22141 linenoiseHistorySave(filename);
22142 #ifdef HAVE_UMASK
22143 mask = umask(mask);
22144 #endif
22145 #endif
22146 }
22147
22148 void Jim_HistoryShow(void)
22149 {
22150 #ifdef USE_LINENOISE
22151
22152 int i;
22153 int len;
22154 char **history = linenoiseHistory(&len);
22155 for (i = 0; i < len; i++) {
22156 printf("%4d %s\n", i + 1, history[i]);
22157 }
22158 #endif
22159 }
22160
22161 #ifdef USE_LINENOISE
22162 struct JimCompletionInfo {
22163 Jim_Interp *interp;
22164 Jim_Obj *command;
22165 };
22166
22167 static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
22168 {
22169 struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
22170 Jim_Obj *objv[2];
22171 int ret;
22172
22173 objv[0] = info->command;
22174 objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
22175
22176 ret = Jim_EvalObjVector(info->interp, 2, objv);
22177
22178
22179 if (ret == JIM_OK) {
22180 int i;
22181 Jim_Obj *listObj = Jim_GetResult(info->interp);
22182 int len = Jim_ListLength(info->interp, listObj);
22183 for (i = 0; i < len; i++) {
22184 linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i)));
22185 }
22186 }
22187 }
22188
22189 static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data)
22190 {
22191 struct JimCompletionInfo *compinfo = data;
22192
22193 Jim_DecrRefCount(interp, compinfo->command);
22194
22195 Jim_Free(compinfo);
22196 }
22197 #endif
22198
22199 void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj)
22200 {
22201 #ifdef USE_LINENOISE
22202 if (commandObj) {
22203
22204 Jim_IncrRefCount(commandObj);
22205 }
22206
22207 Jim_DeleteAssocData(interp, completion_callback_assoc_key);
22208
22209 if (commandObj) {
22210 struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo));
22211 compinfo->interp = interp;
22212 compinfo->command = commandObj;
22213
22214 Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo);
22215 }
22216 #endif
22217 }
22218
22219 int Jim_InteractivePrompt(Jim_Interp *interp)
22220 {
22221 int retcode = JIM_OK;
22222 char *history_file = NULL;
@@ -22023,10 +22228,12 @@
22228 int history_len = strlen(home) + sizeof("/.jim_history");
22229 history_file = Jim_Alloc(history_len);
22230 snprintf(history_file, history_len, "%s/.jim_history", home);
22231 Jim_HistoryLoad(history_file);
22232 }
22233
22234 Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1));
22235 #endif
22236
22237 printf("Welcome to Jim version %d.%d\n",
22238 JIM_VERSION / 100, JIM_VERSION % 100);
22239 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22055,21 +22262,21 @@
22262 Jim_IncrRefCount(scriptObjPtr);
22263 while (1) {
22264 char state;
22265 char *line;
22266
22267 line = Jim_HistoryGetline(interp, prompt);
22268 if (line == NULL) {
22269 if (errno == EINTR) {
22270 continue;
22271 }
22272 Jim_DecrRefCount(interp, scriptObjPtr);
22273 retcode = JIM_OK;
22274 goto out;
22275 }
22276 if (Jim_Length(scriptObjPtr) != 0) {
22277
22278 Jim_AppendString(interp, scriptObjPtr, "\n", 1);
22279 }
22280 Jim_AppendString(interp, scriptObjPtr, line, -1);
22281 free(line);
22282 if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22284,11 @@
22284
22285 snprintf(prompt, sizeof(prompt), "%c> ", state);
22286 }
22287 #ifdef USE_LINENOISE
22288 if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22289
22290 Jim_HistoryShow();
22291 Jim_DecrRefCount(interp, scriptObjPtr);
22292 continue;
22293 }
22294
@@ -22104,10 +22311,11 @@
22311 printf("%s\n", result);
22312 }
22313 }
22314 out:
22315 Jim_Free(history_file);
22316
22317 return retcode;
22318 }
22319
22320 #include <stdio.h>
22321 #include <stdlib.h>
@@ -22120,11 +22328,11 @@
22328 static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
22329 {
22330 int n;
22331 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
22332
22333
22334 for (n = 0; n < argc; n++) {
22335 Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
22336
22337 Jim_ListAppendElement(interp, listObj, obj);
22338 }
@@ -22146,71 +22354,75 @@
22354 printf("or : %s [options] [filename]\n", executable_name);
22355 printf("\n");
22356 printf("Without options: Interactive mode\n");
22357 printf("\n");
22358 printf("Options:\n");
22359 printf(" --version : prints the version string\n");
22360 printf(" --help : prints this text\n");
22361 printf(" -e CMD : executes command CMD\n");
22362 printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22363 printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n");
22364 printf(" NOTE: all subsequent options will be passed to the script\n\n");
22365 }
22366
22367 int main(int argc, char *const argv[])
22368 {
22369 int retcode;
22370 Jim_Interp *interp;
22371 char *const orig_argv0 = argv[0];
22372
22373
22374 if (argc > 1 && strcmp(argv[1], "--version") == 0) {
22375 printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
22376 return 0;
22377 }
22378 else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
22379 usage(argv[0]);
22380 return 0;
22381 }
22382
22383
22384 interp = Jim_CreateInterp();
22385 Jim_RegisterCoreCommands(interp);
22386
22387
22388 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
22389 JimPrintErrorMessage(interp);
22390 }
22391
22392 Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
22393 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
22394 retcode = Jim_initjimshInit(interp);
22395
22396 if (argc == 1) {
22397
22398 if (retcode == JIM_ERR) {
22399 JimPrintErrorMessage(interp);
22400 }
22401 if (retcode != JIM_EXIT) {
22402 JimSetArgv(interp, 0, NULL);
22403 retcode = Jim_InteractivePrompt(interp);
22404 }
22405 }
22406 else {
22407
22408 if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22409
22410 JimSetArgv(interp, argc - 3, argv + 3);
22411 retcode = Jim_Eval(interp, argv[2]);
22412 if (retcode != JIM_ERR) {
22413 printf("%s\n", Jim_String(Jim_GetResult(interp)));
22414 }
22415 }
22416 else {
22417 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
22418 JimSetArgv(interp, argc - 2, argv + 2);
22419 if (strcmp(argv[1], "-") == 0) {
22420 retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
22421 } else {
22422 retcode = Jim_EvalFile(interp, argv[1]);
22423 }
22424 }
22425 if (retcode == JIM_ERR) {
22426 JimPrintErrorMessage(interp);
22427 }
22428 }
22429

Keyboard Shortcuts

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