Fossil SCM
Merge the latest Jim Tcl code to trunk, post-0.75 with the 'glob.tcl' fix included. Approved by Jim Tcl release manager Steve Bennett.
Commit
9d7d6775595aab786aa0b37f30d81414e5389dc8
Parent
bfacd6df6df6064…
1 file changed
+1787
-1501
+1787
-1501
| --- autosetup/jimsh0.c | ||
| +++ autosetup/jimsh0.c | ||
| @@ -1,6 +1,6 @@ | ||
| 1 | -/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */ | |
| 1 | +/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ | |
| 2 | 2 | #define _GNU_SOURCE |
| 3 | 3 | #define JIM_TCL_COMPAT |
| 4 | 4 | #define JIM_REFERENCES |
| 5 | 5 | #define JIM_ANSIC |
| 6 | 6 | #define JIM_REGEXP |
| @@ -47,10 +47,14 @@ | ||
| 47 | 47 | #define JIM_VERSION 75 |
| 48 | 48 | #ifndef JIM_WIN32COMPAT_H |
| 49 | 49 | #define JIM_WIN32COMPAT_H |
| 50 | 50 | |
| 51 | 51 | |
| 52 | + | |
| 53 | +#ifdef __cplusplus | |
| 54 | +extern "C" { | |
| 55 | +#endif | |
| 52 | 56 | |
| 53 | 57 | |
| 54 | 58 | #if defined(_WIN32) || defined(WIN32) |
| 55 | 59 | |
| 56 | 60 | #define HAVE_DLOPEN |
| @@ -106,17 +110,31 @@ | ||
| 106 | 110 | } DIR; |
| 107 | 111 | |
| 108 | 112 | DIR *opendir(const char *name); |
| 109 | 113 | int closedir(DIR *dir); |
| 110 | 114 | struct dirent *readdir(DIR *dir); |
| 111 | -#endif | |
| 115 | + | |
| 116 | +#elif defined(__MINGW32__) | |
| 117 | + | |
| 118 | +#define strtod __strtod | |
| 119 | + | |
| 120 | +#endif | |
| 112 | 121 | |
| 113 | 122 | #endif |
| 123 | + | |
| 124 | +#ifdef __cplusplus | |
| 125 | +} | |
| 126 | +#endif | |
| 114 | 127 | |
| 115 | 128 | #endif |
| 116 | 129 | #ifndef UTF8_UTIL_H |
| 117 | 130 | #define UTF8_UTIL_H |
| 131 | + | |
| 132 | +#ifdef __cplusplus | |
| 133 | +extern "C" { | |
| 134 | +#endif | |
| 135 | + | |
| 118 | 136 | |
| 119 | 137 | |
| 120 | 138 | #define MAX_UTF8_LEN 4 |
| 121 | 139 | |
| 122 | 140 | int utf8_fromunicode(char *p, unsigned uc); |
| @@ -125,10 +143,11 @@ | ||
| 125 | 143 | #include <ctype.h> |
| 126 | 144 | |
| 127 | 145 | |
| 128 | 146 | #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) |
| 129 | 147 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 148 | +#define utf8_getchars(CP, C) (*(CP) = (C), 1) | |
| 130 | 149 | #define utf8_upper(C) toupper(C) |
| 131 | 150 | #define utf8_title(C) toupper(C) |
| 132 | 151 | #define utf8_lower(C) tolower(C) |
| 133 | 152 | #define utf8_index(C, I) (I) |
| 134 | 153 | #define utf8_charlen(C) 1 |
| @@ -135,10 +154,14 @@ | ||
| 135 | 154 | #define utf8_prev_len(S, L) 1 |
| 136 | 155 | |
| 137 | 156 | #else |
| 138 | 157 | |
| 139 | 158 | #endif |
| 159 | + | |
| 160 | +#ifdef __cplusplus | |
| 161 | +} | |
| 162 | +#endif | |
| 140 | 163 | |
| 141 | 164 | #endif |
| 142 | 165 | |
| 143 | 166 | #ifndef __JIM__H |
| 144 | 167 | #define __JIM__H |
| @@ -199,44 +222,34 @@ | ||
| 199 | 222 | #define JIM_EVAL 7 |
| 200 | 223 | |
| 201 | 224 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 202 | 225 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 203 | 226 | |
| 204 | -#define JIM_NONE 0 | |
| 205 | -#define JIM_ERRMSG 1 | |
| 206 | - | |
| 207 | -#define JIM_UNSHARED 4 | |
| 208 | -#define JIM_MUSTEXIST 8 | |
| 209 | - | |
| 210 | - | |
| 211 | -#define JIM_GLOBAL_ONLY 0x100 | |
| 227 | + | |
| 228 | +#define JIM_PRIV_FLAG_SHIFT 20 | |
| 229 | + | |
| 230 | +#define JIM_NONE 0 | |
| 231 | +#define JIM_ERRMSG 1 | |
| 232 | +#define JIM_ENUM_ABBREV 2 | |
| 233 | +#define JIM_UNSHARED 4 | |
| 234 | +#define JIM_MUSTEXIST 8 | |
| 212 | 235 | |
| 213 | 236 | |
| 214 | 237 | #define JIM_SUBST_NOVAR 1 |
| 215 | 238 | #define JIM_SUBST_NOCMD 2 |
| 216 | 239 | #define JIM_SUBST_NOESC 4 |
| 217 | 240 | #define JIM_SUBST_FLAG 128 |
| 218 | 241 | |
| 219 | - | |
| 220 | -#define JIM_NOTUSED(V) ((void) V) | |
| 221 | - | |
| 222 | - | |
| 223 | -#define JIM_ENUM_ABBREV 2 | |
| 224 | - | |
| 225 | 242 | |
| 226 | 243 | #define JIM_CASESENS 0 |
| 227 | 244 | #define JIM_NOCASE 1 |
| 228 | 245 | |
| 229 | 246 | |
| 230 | 247 | #define JIM_PATH_LEN 1024 |
| 231 | 248 | |
| 232 | 249 | |
| 233 | -#ifdef JIM_CRLF | |
| 234 | -#define JIM_NL "\r\n" | |
| 235 | -#else | |
| 236 | -#define JIM_NL "\n" | |
| 237 | -#endif | |
| 250 | +#define JIM_NOTUSED(V) ((void) V) | |
| 238 | 251 | |
| 239 | 252 | #define JIM_LIBPATH "auto_path" |
| 240 | 253 | #define JIM_INTERACTIVE "tcl_interactive" |
| 241 | 254 | |
| 242 | 255 | |
| @@ -266,21 +279,22 @@ | ||
| 266 | 279 | } Jim_HashTableType; |
| 267 | 280 | |
| 268 | 281 | typedef struct Jim_HashTable { |
| 269 | 282 | Jim_HashEntry **table; |
| 270 | 283 | const Jim_HashTableType *type; |
| 284 | + void *privdata; | |
| 271 | 285 | unsigned int size; |
| 272 | 286 | unsigned int sizemask; |
| 273 | 287 | unsigned int used; |
| 274 | 288 | unsigned int collisions; |
| 275 | - void *privdata; | |
| 289 | + unsigned int uniq; | |
| 276 | 290 | } Jim_HashTable; |
| 277 | 291 | |
| 278 | 292 | typedef struct Jim_HashTableIterator { |
| 279 | 293 | Jim_HashTable *ht; |
| 280 | - int index; | |
| 281 | 294 | Jim_HashEntry *entry, *nextEntry; |
| 295 | + int index; | |
| 282 | 296 | } Jim_HashTableIterator; |
| 283 | 297 | |
| 284 | 298 | |
| 285 | 299 | #define JIM_HT_INITIAL_SIZE 16 |
| 286 | 300 | |
| @@ -289,35 +303,35 @@ | ||
| 289 | 303 | if ((ht)->type->valDestructor) \ |
| 290 | 304 | (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) |
| 291 | 305 | |
| 292 | 306 | #define Jim_SetHashVal(ht, entry, _val_) do { \ |
| 293 | 307 | if ((ht)->type->valDup) \ |
| 294 | - entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ | |
| 308 | + (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ | |
| 295 | 309 | else \ |
| 296 | - entry->u.val = (_val_); \ | |
| 310 | + (entry)->u.val = (_val_); \ | |
| 297 | 311 | } while(0) |
| 298 | 312 | |
| 299 | 313 | #define Jim_FreeEntryKey(ht, entry) \ |
| 300 | 314 | if ((ht)->type->keyDestructor) \ |
| 301 | 315 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) |
| 302 | 316 | |
| 303 | 317 | #define Jim_SetHashKey(ht, entry, _key_) do { \ |
| 304 | 318 | if ((ht)->type->keyDup) \ |
| 305 | - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ | |
| 319 | + (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \ | |
| 306 | 320 | else \ |
| 307 | - entry->key = (void *)(_key_); \ | |
| 321 | + (entry)->key = (void *)(_key_); \ | |
| 308 | 322 | } while(0) |
| 309 | 323 | |
| 310 | 324 | #define Jim_CompareHashKeys(ht, key1, key2) \ |
| 311 | 325 | (((ht)->type->keyCompare) ? \ |
| 312 | - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ | |
| 326 | + (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \ | |
| 313 | 327 | (key1) == (key2)) |
| 314 | 328 | |
| 315 | -#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) | |
| 329 | +#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) | |
| 316 | 330 | |
| 317 | 331 | #define Jim_GetHashEntryKey(he) ((he)->key) |
| 318 | -#define Jim_GetHashEntryVal(he) ((he)->val) | |
| 332 | +#define Jim_GetHashEntryVal(he) ((he)->u.val) | |
| 319 | 333 | #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) |
| 320 | 334 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 321 | 335 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 322 | 336 | |
| 323 | 337 | |
| @@ -341,19 +355,19 @@ | ||
| 341 | 355 | void *ptr1; |
| 342 | 356 | void *ptr2; |
| 343 | 357 | } twoPtrValue; |
| 344 | 358 | |
| 345 | 359 | struct { |
| 346 | - unsigned long callFrameId; | |
| 347 | 360 | struct Jim_Var *varPtr; |
| 361 | + unsigned long callFrameId; | |
| 348 | 362 | int global; |
| 349 | 363 | } varValue; |
| 350 | 364 | |
| 351 | 365 | struct { |
| 352 | - unsigned long procEpoch; | |
| 353 | 366 | struct Jim_Obj *nsObj; |
| 354 | 367 | struct Jim_Cmd *cmdPtr; |
| 368 | + unsigned long procEpoch; | |
| 355 | 369 | } cmdValue; |
| 356 | 370 | |
| 357 | 371 | struct { |
| 358 | 372 | struct Jim_Obj **ele; |
| 359 | 373 | int len; |
| @@ -379,12 +393,12 @@ | ||
| 379 | 393 | struct Jim_Obj *varNameObjPtr; |
| 380 | 394 | struct Jim_Obj *indexObjPtr; |
| 381 | 395 | } dictSubstValue; |
| 382 | 396 | |
| 383 | 397 | struct { |
| 384 | - unsigned flags; | |
| 385 | 398 | void *compre; |
| 399 | + unsigned flags; | |
| 386 | 400 | } regexpValue; |
| 387 | 401 | struct { |
| 388 | 402 | int line; |
| 389 | 403 | int argc; |
| 390 | 404 | } scriptLineValue; |
| @@ -453,21 +467,24 @@ | ||
| 453 | 467 | struct Jim_CallFrame *next; |
| 454 | 468 | Jim_Obj *nsObj; |
| 455 | 469 | Jim_Obj *fileNameObj; |
| 456 | 470 | int line; |
| 457 | 471 | Jim_Stack *localCommands; |
| 472 | + int tailcall; | |
| 473 | + struct Jim_Obj *tailcallObj; | |
| 474 | + struct Jim_Cmd *tailcallCmd; | |
| 458 | 475 | } Jim_CallFrame; |
| 459 | 476 | |
| 460 | 477 | typedef struct Jim_Var { |
| 461 | 478 | Jim_Obj *objPtr; |
| 462 | 479 | struct Jim_CallFrame *linkFramePtr; |
| 463 | 480 | } Jim_Var; |
| 464 | 481 | |
| 465 | 482 | |
| 466 | -typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, | |
| 483 | +typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, | |
| 467 | 484 | Jim_Obj *const *argv); |
| 468 | -typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); | |
| 485 | +typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); | |
| 469 | 486 | |
| 470 | 487 | |
| 471 | 488 | |
| 472 | 489 | typedef struct Jim_Cmd { |
| 473 | 490 | int inUse; |
| @@ -474,12 +491,12 @@ | ||
| 474 | 491 | int isproc; |
| 475 | 492 | struct Jim_Cmd *prevCmd; |
| 476 | 493 | union { |
| 477 | 494 | struct { |
| 478 | 495 | |
| 479 | - Jim_CmdProc cmdProc; | |
| 480 | - Jim_DelCmdProc delProc; | |
| 496 | + Jim_CmdProc *cmdProc; | |
| 497 | + Jim_DelCmdProc *delProc; | |
| 481 | 498 | void *privData; |
| 482 | 499 | } native; |
| 483 | 500 | struct { |
| 484 | 501 | |
| 485 | 502 | Jim_Obj *argListObjPtr; |
| @@ -589,15 +606,11 @@ | ||
| 589 | 606 | Jim_Obj *finalizerCmdNamePtr; |
| 590 | 607 | char tag[JIM_REFERENCE_TAGLEN+1]; |
| 591 | 608 | } Jim_Reference; |
| 592 | 609 | |
| 593 | 610 | |
| 594 | - | |
| 595 | 611 | #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) |
| 596 | - | |
| 597 | - | |
| 598 | - | |
| 599 | 612 | #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) |
| 600 | 613 | |
| 601 | 614 | #define JIM_EXPORT |
| 602 | 615 | |
| 603 | 616 | |
| @@ -608,10 +621,11 @@ | ||
| 608 | 621 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 609 | 622 | |
| 610 | 623 | |
| 611 | 624 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 612 | 625 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 626 | +JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); | |
| 613 | 627 | |
| 614 | 628 | |
| 615 | 629 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 616 | 630 | |
| 617 | 631 | |
| @@ -739,13 +753,12 @@ | ||
| 739 | 753 | JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, |
| 740 | 754 | const char *name, const char *val); |
| 741 | 755 | JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, |
| 742 | 756 | Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, |
| 743 | 757 | Jim_CallFrame *targetCallFrame); |
| 744 | -JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp, | |
| 745 | - Jim_Obj *varNameObj, Jim_Obj *targetNameObj); | |
| 746 | -JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp); | |
| 758 | +JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp, | |
| 759 | + Jim_Obj *nameObjPtr); | |
| 747 | 760 | JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, |
| 748 | 761 | Jim_Obj *nameObjPtr, int flags); |
| 749 | 762 | JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, |
| 750 | 763 | Jim_Obj *nameObjPtr, int flags); |
| 751 | 764 | JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, |
| @@ -804,10 +817,11 @@ | ||
| 804 | 817 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 805 | 818 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 806 | 819 | JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); |
| 807 | 820 | JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); |
| 808 | 821 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 822 | +JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); | |
| 809 | 823 | |
| 810 | 824 | |
| 811 | 825 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 812 | 826 | int *intPtr); |
| 813 | 827 | |
| @@ -869,19 +883,19 @@ | ||
| 869 | 883 | |
| 870 | 884 | |
| 871 | 885 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| 872 | 886 | JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); |
| 873 | 887 | JIM_EXPORT int Jim_IsBigEndian(void); |
| 888 | + | |
| 874 | 889 | #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) |
| 875 | 890 | |
| 876 | 891 | |
| 877 | 892 | JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); |
| 878 | 893 | JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); |
| 879 | 894 | |
| 880 | 895 | |
| 881 | 896 | JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 882 | - | |
| 883 | 897 | |
| 884 | 898 | |
| 885 | 899 | JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); |
| 886 | 900 | JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); |
| 887 | 901 | |
| @@ -903,16 +917,16 @@ | ||
| 903 | 917 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 904 | 918 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 905 | 919 | |
| 906 | 920 | |
| 907 | 921 | |
| 908 | -typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |
| 922 | +typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |
| 909 | 923 | |
| 910 | 924 | typedef struct { |
| 911 | 925 | const char *cmd; |
| 912 | 926 | const char *args; |
| 913 | - tclmod_cmd_function *function; | |
| 927 | + jim_subcmd_function *function; | |
| 914 | 928 | short minargs; |
| 915 | 929 | short maxargs; |
| 916 | 930 | unsigned short flags; |
| 917 | 931 | } jim_subcmd_type; |
| 918 | 932 | |
| @@ -929,22 +943,16 @@ | ||
| 929 | 943 | |
| 930 | 944 | #endif |
| 931 | 945 | #ifndef JIMREGEXP_H |
| 932 | 946 | #define JIMREGEXP_H |
| 933 | 947 | |
| 934 | -#ifndef _JIMAUTOCONF_H | |
| 935 | -#error Need jimautoconf.h | |
| 948 | + | |
| 949 | +#ifdef __cplusplus | |
| 950 | +extern "C" { | |
| 936 | 951 | #endif |
| 937 | 952 | |
| 938 | -#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP) | |
| 939 | - | |
| 940 | -#include <regex.h> | |
| 941 | - | |
| 942 | -#else | |
| 943 | - | |
| 944 | 953 | #include <stdlib.h> |
| 945 | - | |
| 946 | 954 | |
| 947 | 955 | typedef struct { |
| 948 | 956 | int rm_so; |
| 949 | 957 | int rm_eo; |
| 950 | 958 | } regmatch_t; |
| @@ -1013,10 +1021,12 @@ | ||
| 1013 | 1021 | int regcomp(regex_t *preg, const char *regex, int cflags); |
| 1014 | 1022 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1015 | 1023 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1016 | 1024 | void regfree(regex_t *preg); |
| 1017 | 1025 | |
| 1026 | +#ifdef __cplusplus | |
| 1027 | +} | |
| 1018 | 1028 | #endif |
| 1019 | 1029 | |
| 1020 | 1030 | #endif |
| 1021 | 1031 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1022 | 1032 | { |
| @@ -1079,10 +1089,15 @@ | ||
| 1079 | 1089 | "\n" |
| 1080 | 1090 | "package require readdir\n" |
| 1081 | 1091 | "\n" |
| 1082 | 1092 | "\n" |
| 1083 | 1093 | "proc glob.globdir {dir pattern} {\n" |
| 1094 | +" if {[file exists $dir/$pattern]} {\n" | |
| 1095 | +"\n" | |
| 1096 | +" return $pattern\n" | |
| 1097 | +" }\n" | |
| 1098 | +"\n" | |
| 1084 | 1099 | " set result {}\n" |
| 1085 | 1100 | " set files [readdir $dir]\n" |
| 1086 | 1101 | " lappend files . ..\n" |
| 1087 | 1102 | "\n" |
| 1088 | 1103 | " foreach name $files {\n" |
| @@ -1261,10 +1276,12 @@ | ||
| 1261 | 1276 | { |
| 1262 | 1277 | if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) |
| 1263 | 1278 | return JIM_ERR; |
| 1264 | 1279 | |
| 1265 | 1280 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1281 | +"\n" | |
| 1282 | +"\n" | |
| 1266 | 1283 | "\n" |
| 1267 | 1284 | "proc lambda {arglist args} {\n" |
| 1268 | 1285 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1269 | 1286 | "}\n" |
| 1270 | 1287 | "\n" |
| @@ -1290,46 +1307,48 @@ | ||
| 1290 | 1307 | "}\n" |
| 1291 | 1308 | "\n" |
| 1292 | 1309 | "\n" |
| 1293 | 1310 | "\n" |
| 1294 | 1311 | "\n" |
| 1295 | -"proc stacktrace {} {\n" | |
| 1312 | +"proc stacktrace {{skip 0}} {\n" | |
| 1296 | 1313 | " set trace {}\n" |
| 1297 | -" foreach level [range 1 [info level]] {\n" | |
| 1298 | -" lassign [info frame -$level] p f l\n" | |
| 1299 | -" lappend trace $p $f $l\n" | |
| 1314 | +" incr skip\n" | |
| 1315 | +" foreach level [range $skip [info level]] {\n" | |
| 1316 | +" lappend trace {*}[info frame -$level]\n" | |
| 1300 | 1317 | " }\n" |
| 1301 | 1318 | " return $trace\n" |
| 1302 | 1319 | "}\n" |
| 1303 | 1320 | "\n" |
| 1304 | 1321 | "\n" |
| 1305 | 1322 | "proc stackdump {stacktrace} {\n" |
| 1306 | -" set result {}\n" | |
| 1307 | -" set count 0\n" | |
| 1323 | +" set lines {}\n" | |
| 1308 | 1324 | " foreach {l f p} [lreverse $stacktrace] {\n" |
| 1309 | -" if {$count} {\n" | |
| 1310 | -" append result \\n\n" | |
| 1311 | -" }\n" | |
| 1312 | -" incr count\n" | |
| 1325 | +" set line {}\n" | |
| 1313 | 1326 | " if {$p ne \"\"} {\n" |
| 1314 | -" append result \"in procedure '$p' \"\n" | |
| 1327 | +" append line \"in procedure '$p' \"\n" | |
| 1315 | 1328 | " if {$f ne \"\"} {\n" |
| 1316 | -" append result \"called \"\n" | |
| 1329 | +" append line \"called \"\n" | |
| 1317 | 1330 | " }\n" |
| 1318 | 1331 | " }\n" |
| 1319 | 1332 | " if {$f ne \"\"} {\n" |
| 1320 | -" append result \"at file \\\"$f\\\", line $l\"\n" | |
| 1333 | +" append line \"at file \\\"$f\\\", line $l\"\n" | |
| 1334 | +" }\n" | |
| 1335 | +" if {$line ne \"\"} {\n" | |
| 1336 | +" lappend lines $line\n" | |
| 1321 | 1337 | " }\n" |
| 1322 | 1338 | " }\n" |
| 1323 | -" return $result\n" | |
| 1339 | +" join $lines \\n\n" | |
| 1324 | 1340 | "}\n" |
| 1325 | 1341 | "\n" |
| 1326 | 1342 | "\n" |
| 1327 | 1343 | "\n" |
| 1328 | 1344 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1329 | 1345 | " if {$stacktrace eq \"\"} {\n" |
| 1346 | +"\n" | |
| 1330 | 1347 | " set stacktrace [info stacktrace]\n" |
| 1348 | +"\n" | |
| 1349 | +" lappend stacktrace {*}[stacktrace 1]\n" | |
| 1331 | 1350 | " }\n" |
| 1332 | 1351 | " lassign $stacktrace p f l\n" |
| 1333 | 1352 | " if {$f ne \"\"} {\n" |
| 1334 | 1353 | " set result \"Runtime Error: $f:$l: \"\n" |
| 1335 | 1354 | " }\n" |
| @@ -1356,25 +1375,46 @@ | ||
| 1356 | 1375 | " }\n" |
| 1357 | 1376 | " return \"\"\n" |
| 1358 | 1377 | "}\n" |
| 1359 | 1378 | "\n" |
| 1360 | 1379 | "\n" |
| 1361 | -"proc {dict with} {dictVar args script} {\n" | |
| 1362 | -" upvar $dictVar dict\n" | |
| 1380 | +"proc {dict with} {&dictVar {args key} script} {\n" | |
| 1363 | 1381 | " set keys {}\n" |
| 1364 | -" foreach {n v} [dict get $dict {*}$args] {\n" | |
| 1382 | +" foreach {n v} [dict get $dictVar {*}$key] {\n" | |
| 1365 | 1383 | " upvar $n var_$n\n" |
| 1366 | 1384 | " set var_$n $v\n" |
| 1367 | 1385 | " lappend keys $n\n" |
| 1368 | 1386 | " }\n" |
| 1369 | 1387 | " catch {uplevel 1 $script} msg opts\n" |
| 1370 | -" if {[info exists dict] && [dict exists $dict {*}$args]} {\n" | |
| 1388 | +" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" | |
| 1371 | 1389 | " foreach n $keys {\n" |
| 1372 | 1390 | " if {[info exists var_$n]} {\n" |
| 1373 | -" dict set dict {*}$args $n [set var_$n]\n" | |
| 1391 | +" dict set dictVar {*}$key $n [set var_$n]\n" | |
| 1392 | +" } else {\n" | |
| 1393 | +" dict unset dictVar {*}$key $n\n" | |
| 1394 | +" }\n" | |
| 1395 | +" }\n" | |
| 1396 | +" }\n" | |
| 1397 | +" return {*}$opts $msg\n" | |
| 1398 | +"}\n" | |
| 1399 | +"\n" | |
| 1400 | +"\n" | |
| 1401 | +"proc {dict update} {&varName args script} {\n" | |
| 1402 | +" set keys {}\n" | |
| 1403 | +" foreach {n v} $args {\n" | |
| 1404 | +" upvar $v var_$v\n" | |
| 1405 | +" if {[dict exists $varName $n]} {\n" | |
| 1406 | +" set var_$v [dict get $varName $n]\n" | |
| 1407 | +" }\n" | |
| 1408 | +" }\n" | |
| 1409 | +" catch {uplevel 1 $script} msg opts\n" | |
| 1410 | +" if {[info exists varName]} {\n" | |
| 1411 | +" foreach {n v} $args {\n" | |
| 1412 | +" if {[info exists var_$v]} {\n" | |
| 1413 | +" dict set varName $n [set var_$v]\n" | |
| 1374 | 1414 | " } else {\n" |
| 1375 | -" dict unset dict {*}$args $n\n" | |
| 1415 | +" dict unset varName $n\n" | |
| 1376 | 1416 | " }\n" |
| 1377 | 1417 | " }\n" |
| 1378 | 1418 | " }\n" |
| 1379 | 1419 | " return {*}$opts $msg\n" |
| 1380 | 1420 | "}\n" |
| @@ -1389,10 +1429,69 @@ | ||
| 1389 | 1429 | " dict set dict $k $v\n" |
| 1390 | 1430 | " }\n" |
| 1391 | 1431 | " }\n" |
| 1392 | 1432 | " return $dict\n" |
| 1393 | 1433 | "}\n" |
| 1434 | +"\n" | |
| 1435 | +"proc {dict replace} {dictionary {args {key value}}} {\n" | |
| 1436 | +" if {[llength ${key value}] % 2} {\n" | |
| 1437 | +" tailcall {dict replace}\n" | |
| 1438 | +" }\n" | |
| 1439 | +" tailcall dict merge $dictionary ${key value}\n" | |
| 1440 | +"}\n" | |
| 1441 | +"\n" | |
| 1442 | +"\n" | |
| 1443 | +"proc {dict lappend} {varName key {args value}} {\n" | |
| 1444 | +" upvar $varName dict\n" | |
| 1445 | +" if {[exists dict] && [dict exists $dict $key]} {\n" | |
| 1446 | +" set list [dict get $dict $key]\n" | |
| 1447 | +" }\n" | |
| 1448 | +" lappend list {*}$value\n" | |
| 1449 | +" dict set dict $key $list\n" | |
| 1450 | +"}\n" | |
| 1451 | +"\n" | |
| 1452 | +"\n" | |
| 1453 | +"proc {dict append} {varName key {args value}} {\n" | |
| 1454 | +" upvar $varName dict\n" | |
| 1455 | +" if {[exists dict] && [dict exists $dict $key]} {\n" | |
| 1456 | +" set str [dict get $dict $key]\n" | |
| 1457 | +" }\n" | |
| 1458 | +" append str {*}$value\n" | |
| 1459 | +" dict set dict $key $str\n" | |
| 1460 | +"}\n" | |
| 1461 | +"\n" | |
| 1462 | +"\n" | |
| 1463 | +"proc {dict incr} {varName key {increment 1}} {\n" | |
| 1464 | +" upvar $varName dict\n" | |
| 1465 | +" if {[exists dict] && [dict exists $dict $key]} {\n" | |
| 1466 | +" set value [dict get $dict $key]\n" | |
| 1467 | +" }\n" | |
| 1468 | +" incr value $increment\n" | |
| 1469 | +" dict set dict $key $value\n" | |
| 1470 | +"}\n" | |
| 1471 | +"\n" | |
| 1472 | +"\n" | |
| 1473 | +"proc {dict remove} {dictionary {args key}} {\n" | |
| 1474 | +" foreach k $key {\n" | |
| 1475 | +" dict unset dictionary $k\n" | |
| 1476 | +" }\n" | |
| 1477 | +" return $dictionary\n" | |
| 1478 | +"}\n" | |
| 1479 | +"\n" | |
| 1480 | +"\n" | |
| 1481 | +"proc {dict values} {dictionary {pattern *}} {\n" | |
| 1482 | +" dict keys [lreverse $dictionary] $pattern\n" | |
| 1483 | +"}\n" | |
| 1484 | +"\n" | |
| 1485 | +"\n" | |
| 1486 | +"proc {dict for} {vars dictionary script} {\n" | |
| 1487 | +" if {[llength $vars] != 2} {\n" | |
| 1488 | +" return -code error \"must have exactly two variable names\"\n" | |
| 1489 | +" }\n" | |
| 1490 | +" dict size $dictionary\n" | |
| 1491 | +" tailcall foreach $vars $dictionary $script\n" | |
| 1492 | +"}\n" | |
| 1394 | 1493 | ); |
| 1395 | 1494 | } |
| 1396 | 1495 | int Jim_tclcompatInit(Jim_Interp *interp) |
| 1397 | 1496 | { |
| 1398 | 1497 | if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG)) |
| @@ -1403,12 +1502,14 @@ | ||
| 1403 | 1502 | "\n" |
| 1404 | 1503 | "\n" |
| 1405 | 1504 | "\n" |
| 1406 | 1505 | "\n" |
| 1407 | 1506 | "\n" |
| 1507 | +"\n" | |
| 1408 | 1508 | "\n" |
| 1409 | 1509 | "set env [env]\n" |
| 1510 | +"\n" | |
| 1410 | 1511 | "\n" |
| 1411 | 1512 | "if {[info commands stdout] ne \"\"} {\n" |
| 1412 | 1513 | "\n" |
| 1413 | 1514 | " foreach p {gets flush close eof seek tell} {\n" |
| 1414 | 1515 | " proc $p {chan args} {p} {\n" |
| @@ -1455,51 +1556,10 @@ | ||
| 1455 | 1556 | " }\n" |
| 1456 | 1557 | " }\n" |
| 1457 | 1558 | " }\n" |
| 1458 | 1559 | "}\n" |
| 1459 | 1560 | "\n" |
| 1460 | -"\n" | |
| 1461 | -"proc case {var args} {\n" | |
| 1462 | -"\n" | |
| 1463 | -" if {[lindex $args 0] eq \"in\"} {\n" | |
| 1464 | -" set args [lrange $args 1 end]\n" | |
| 1465 | -" }\n" | |
| 1466 | -"\n" | |
| 1467 | -"\n" | |
| 1468 | -" if {[llength $args] == 1} {\n" | |
| 1469 | -" set args [lindex $args 0]\n" | |
| 1470 | -" }\n" | |
| 1471 | -"\n" | |
| 1472 | -"\n" | |
| 1473 | -" if {[llength $args] % 2 != 0} {\n" | |
| 1474 | -" return -code error \"extra case pattern with no body\"\n" | |
| 1475 | -" }\n" | |
| 1476 | -"\n" | |
| 1477 | -"\n" | |
| 1478 | -" local proc case.checker {value pattern} {\n" | |
| 1479 | -" string match $pattern $value\n" | |
| 1480 | -" }\n" | |
| 1481 | -"\n" | |
| 1482 | -" foreach {value action} $args {\n" | |
| 1483 | -" if {$value eq \"default\"} {\n" | |
| 1484 | -" set do_action $action\n" | |
| 1485 | -" continue\n" | |
| 1486 | -" } elseif {[lsearch -bool -command case.checker $value $var]} {\n" | |
| 1487 | -" set do_action $action\n" | |
| 1488 | -" break\n" | |
| 1489 | -" }\n" | |
| 1490 | -" }\n" | |
| 1491 | -"\n" | |
| 1492 | -" if {[info exists do_action]} {\n" | |
| 1493 | -" set rc [catch [list uplevel 1 $do_action] result opts]\n" | |
| 1494 | -" if {$rc} {\n" | |
| 1495 | -" incr opts(-level)\n" | |
| 1496 | -" }\n" | |
| 1497 | -" return {*}$opts $result\n" | |
| 1498 | -" }\n" | |
| 1499 | -"}\n" | |
| 1500 | -"\n" | |
| 1501 | 1561 | "\n" |
| 1502 | 1562 | "proc fileevent {args} {\n" |
| 1503 | 1563 | " tailcall {*}$args\n" |
| 1504 | 1564 | "}\n" |
| 1505 | 1565 | "\n" |
| @@ -1529,13 +1589,25 @@ | ||
| 1529 | 1589 | " error \"bad option \\\"$force\\\": should be -force\"\n" |
| 1530 | 1590 | " }\n" |
| 1531 | 1591 | "\n" |
| 1532 | 1592 | " set in [open $source]\n" |
| 1533 | 1593 | "\n" |
| 1534 | -" if {$force eq \"\" && [file exists $target]} {\n" | |
| 1535 | -" $in close\n" | |
| 1536 | -" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" | |
| 1594 | +" if {[file exists $target]} {\n" | |
| 1595 | +" if {$force eq \"\"} {\n" | |
| 1596 | +" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" | |
| 1597 | +" }\n" | |
| 1598 | +"\n" | |
| 1599 | +" if {$source eq $target} {\n" | |
| 1600 | +" return\n" | |
| 1601 | +" }\n" | |
| 1602 | +"\n" | |
| 1603 | +"\n" | |
| 1604 | +" file stat $source ss\n" | |
| 1605 | +" file stat $target ts\n" | |
| 1606 | +" if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n" | |
| 1607 | +" return\n" | |
| 1608 | +" }\n" | |
| 1537 | 1609 | " }\n" |
| 1538 | 1610 | " set out [open $target w]\n" |
| 1539 | 1611 | " $in copyto $out\n" |
| 1540 | 1612 | " $out close\n" |
| 1541 | 1613 | " } on error {msg opts} {\n" |
| @@ -1580,18 +1652,18 @@ | ||
| 1580 | 1652 | " error $error\n" |
| 1581 | 1653 | " }\n" |
| 1582 | 1654 | "}\n" |
| 1583 | 1655 | "\n" |
| 1584 | 1656 | "\n" |
| 1585 | -"local proc pid {{chan {}}} {\n" | |
| 1586 | -" if {$chan eq \"\"} {\n" | |
| 1657 | +"local proc pid {{channelId {}}} {\n" | |
| 1658 | +" if {$channelId eq \"\"} {\n" | |
| 1587 | 1659 | " tailcall upcall pid\n" |
| 1588 | 1660 | " }\n" |
| 1589 | -" if {[catch {$chan tell}]} {\n" | |
| 1590 | -" return -code error \"can not find channel named \\\"$chan\\\"\"\n" | |
| 1661 | +" if {[catch {$channelId tell}]} {\n" | |
| 1662 | +" return -code error \"can not find channel named \\\"$channelId\\\"\"\n" | |
| 1591 | 1663 | " }\n" |
| 1592 | -" if {[catch {$chan pid} pids]} {\n" | |
| 1664 | +" if {[catch {$channelId pid} pids]} {\n" | |
| 1593 | 1665 | " return \"\"\n" |
| 1594 | 1666 | " }\n" |
| 1595 | 1667 | " return $pids\n" |
| 1596 | 1668 | "}\n" |
| 1597 | 1669 | "\n" |
| @@ -1680,23 +1752,25 @@ | ||
| 1680 | 1752 | "}\n" |
| 1681 | 1753 | ); |
| 1682 | 1754 | } |
| 1683 | 1755 | |
| 1684 | 1756 | |
| 1685 | - | |
| 1686 | 1757 | #include <stdio.h> |
| 1687 | 1758 | #include <string.h> |
| 1688 | 1759 | #include <errno.h> |
| 1689 | 1760 | #include <fcntl.h> |
| 1761 | +#ifdef HAVE_UNISTD_H | |
| 1762 | +#include <unistd.h> | |
| 1763 | +#include <sys/stat.h> | |
| 1764 | +#endif | |
| 1690 | 1765 | |
| 1691 | 1766 | |
| 1692 | 1767 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1693 | 1768 | #include <sys/socket.h> |
| 1694 | 1769 | #include <netinet/in.h> |
| 1695 | 1770 | #include <arpa/inet.h> |
| 1696 | 1771 | #include <netdb.h> |
| 1697 | -#include <unistd.h> | |
| 1698 | 1772 | #ifdef HAVE_SYS_UN_H |
| 1699 | 1773 | #include <sys/un.h> |
| 1700 | 1774 | #endif |
| 1701 | 1775 | #else |
| 1702 | 1776 | #define JIM_ANSIC |
| @@ -1728,15 +1802,12 @@ | ||
| 1728 | 1802 | typedef struct AioFile |
| 1729 | 1803 | { |
| 1730 | 1804 | FILE *fp; |
| 1731 | 1805 | Jim_Obj *filename; |
| 1732 | 1806 | int type; |
| 1733 | - int OpenFlags; | |
| 1807 | + int openFlags; | |
| 1734 | 1808 | int fd; |
| 1735 | -#ifdef O_NDELAY | |
| 1736 | - int flags; | |
| 1737 | -#endif | |
| 1738 | 1809 | Jim_Obj *rEvent; |
| 1739 | 1810 | Jim_Obj *wEvent; |
| 1740 | 1811 | Jim_Obj *eEvent; |
| 1741 | 1812 | int addr_family; |
| 1742 | 1813 | } AioFile; |
| @@ -1760,20 +1831,21 @@ | ||
| 1760 | 1831 | { |
| 1761 | 1832 | AioFile *af = privData; |
| 1762 | 1833 | |
| 1763 | 1834 | JIM_NOTUSED(interp); |
| 1764 | 1835 | |
| 1765 | - if (!(af->OpenFlags & AIO_KEEPOPEN)) { | |
| 1766 | - fclose(af->fp); | |
| 1767 | - } | |
| 1768 | - | |
| 1769 | 1836 | Jim_DecrRefCount(interp, af->filename); |
| 1770 | 1837 | |
| 1771 | 1838 | #ifdef jim_ext_eventloop |
| 1772 | 1839 | |
| 1773 | 1840 | Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 1774 | 1841 | #endif |
| 1842 | + | |
| 1843 | + if (!(af->openFlags & AIO_KEEPOPEN)) { | |
| 1844 | + fclose(af->fp); | |
| 1845 | + } | |
| 1846 | + | |
| 1775 | 1847 | Jim_Free(af); |
| 1776 | 1848 | } |
| 1777 | 1849 | |
| 1778 | 1850 | static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) |
| 1779 | 1851 | { |
| @@ -2020,12 +2092,31 @@ | ||
| 2020 | 2092 | return JIM_OK; |
| 2021 | 2093 | } |
| 2022 | 2094 | |
| 2023 | 2095 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2024 | 2096 | { |
| 2025 | - Jim_DeleteCommand(interp, Jim_String(argv[0])); | |
| 2026 | - return JIM_OK; | |
| 2097 | + if (argc == 3) { | |
| 2098 | +#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) | |
| 2099 | + static const char * const options[] = { "r", "w", NULL }; | |
| 2100 | + enum { OPT_R, OPT_W, }; | |
| 2101 | + int option; | |
| 2102 | + AioFile *af = Jim_CmdPrivData(interp); | |
| 2103 | + | |
| 2104 | + if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { | |
| 2105 | + return JIM_ERR; | |
| 2106 | + } | |
| 2107 | + if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { | |
| 2108 | + return JIM_OK; | |
| 2109 | + } | |
| 2110 | + JimAioSetError(interp, NULL); | |
| 2111 | +#else | |
| 2112 | + Jim_SetResultString(interp, "async close not supported", -1); | |
| 2113 | +#endif | |
| 2114 | + return JIM_ERR; | |
| 2115 | + } | |
| 2116 | + | |
| 2117 | + return Jim_DeleteCommand(interp, Jim_String(argv[0])); | |
| 2027 | 2118 | } |
| 2028 | 2119 | |
| 2029 | 2120 | static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2030 | 2121 | { |
| 2031 | 2122 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2072,11 +2163,11 @@ | ||
| 2072 | 2163 | #ifdef O_NDELAY |
| 2073 | 2164 | static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2074 | 2165 | { |
| 2075 | 2166 | AioFile *af = Jim_CmdPrivData(interp); |
| 2076 | 2167 | |
| 2077 | - int fmode = af->flags; | |
| 2168 | + int fmode = fcntl(af->fd, F_GETFL); | |
| 2078 | 2169 | |
| 2079 | 2170 | if (argc) { |
| 2080 | 2171 | long nb; |
| 2081 | 2172 | |
| 2082 | 2173 | if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { |
| @@ -2086,12 +2177,11 @@ | ||
| 2086 | 2177 | fmode |= O_NDELAY; |
| 2087 | 2178 | } |
| 2088 | 2179 | else { |
| 2089 | 2180 | fmode &= ~O_NDELAY; |
| 2090 | 2181 | } |
| 2091 | - fcntl(af->fd, F_SETFL, fmode); | |
| 2092 | - af->flags = fmode; | |
| 2182 | + (void)fcntl(af->fd, F_SETFL, fmode); | |
| 2093 | 2183 | } |
| 2094 | 2184 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2095 | 2185 | return JIM_OK; |
| 2096 | 2186 | } |
| 2097 | 2187 | #endif |
| @@ -2195,11 +2285,11 @@ | ||
| 2195 | 2285 | |
| 2196 | 2286 | static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2197 | 2287 | { |
| 2198 | 2288 | AioFile *af = Jim_CmdPrivData(interp); |
| 2199 | 2289 | |
| 2200 | - return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv); | |
| 2290 | + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); | |
| 2201 | 2291 | } |
| 2202 | 2292 | #endif |
| 2203 | 2293 | |
| 2204 | 2294 | static const jim_subcmd_type aio_command_table[] = { |
| 2205 | 2295 | { "read", |
| @@ -2250,14 +2340,14 @@ | ||
| 2250 | 2340 | 0, |
| 2251 | 2341 | 0, |
| 2252 | 2342 | |
| 2253 | 2343 | }, |
| 2254 | 2344 | { "close", |
| 2255 | - NULL, | |
| 2345 | + "?r(ead)|w(rite)?", | |
| 2256 | 2346 | aio_cmd_close, |
| 2257 | 2347 | 0, |
| 2258 | - 0, | |
| 2348 | + 1, | |
| 2259 | 2349 | JIM_MODFLAG_FULLARGV, |
| 2260 | 2350 | |
| 2261 | 2351 | }, |
| 2262 | 2352 | { "seek", |
| 2263 | 2353 | "offset ?start|current|end", |
| @@ -2329,30 +2419,32 @@ | ||
| 2329 | 2419 | |
| 2330 | 2420 | static int JimAioOpenCommand(Jim_Interp *interp, int argc, |
| 2331 | 2421 | Jim_Obj *const *argv) |
| 2332 | 2422 | { |
| 2333 | 2423 | const char *mode; |
| 2334 | - const char *filename; | |
| 2335 | 2424 | |
| 2336 | 2425 | if (argc != 2 && argc != 3) { |
| 2337 | 2426 | Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); |
| 2338 | 2427 | return JIM_ERR; |
| 2339 | 2428 | } |
| 2340 | 2429 | |
| 2341 | 2430 | mode = (argc == 3) ? Jim_String(argv[2]) : "r"; |
| 2342 | - filename = Jim_String(argv[1]); | |
| 2343 | 2431 | |
| 2344 | 2432 | #ifdef jim_ext_tclcompat |
| 2345 | - | |
| 2346 | - if (*filename == '|') { | |
| 2347 | - Jim_Obj *evalObj[3]; | |
| 2348 | - | |
| 2349 | - evalObj[0] = Jim_NewStringObj(interp, "popen", -1); | |
| 2350 | - evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); | |
| 2351 | - evalObj[2] = Jim_NewStringObj(interp, mode, -1); | |
| 2352 | - | |
| 2353 | - return Jim_EvalObjVector(interp, 3, evalObj); | |
| 2433 | + { | |
| 2434 | + const char *filename = Jim_String(argv[1]); | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + if (*filename == '|') { | |
| 2438 | + Jim_Obj *evalObj[3]; | |
| 2439 | + | |
| 2440 | + evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); | |
| 2441 | + evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); | |
| 2442 | + evalObj[2] = Jim_NewStringObj(interp, mode, -1); | |
| 2443 | + | |
| 2444 | + return Jim_EvalObjVector(interp, 3, evalObj); | |
| 2445 | + } | |
| 2354 | 2446 | } |
| 2355 | 2447 | #endif |
| 2356 | 2448 | return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode); |
| 2357 | 2449 | } |
| 2358 | 2450 | |
| @@ -2359,70 +2451,129 @@ | ||
| 2359 | 2451 | static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2360 | 2452 | const char *hdlfmt, int family, const char *mode) |
| 2361 | 2453 | { |
| 2362 | 2454 | AioFile *af; |
| 2363 | 2455 | char buf[AIO_CMD_LEN]; |
| 2364 | - int OpenFlags = 0; | |
| 2456 | + int openFlags = 0; | |
| 2365 | 2457 | |
| 2366 | - if (filename == NULL) { | |
| 2458 | + if (fh) { | |
| 2367 | 2459 | filename = Jim_NewStringObj(interp, hdlfmt, -1); |
| 2460 | + openFlags = AIO_KEEPOPEN; | |
| 2368 | 2461 | } |
| 2369 | 2462 | |
| 2370 | 2463 | Jim_IncrRefCount(filename); |
| 2371 | 2464 | |
| 2372 | 2465 | if (fh == NULL) { |
| 2373 | - if (fd < 0) { | |
| 2374 | - fh = fopen(Jim_String(filename), mode); | |
| 2375 | - } | |
| 2376 | - else { | |
| 2466 | +#if !defined(JIM_ANSIC) | |
| 2467 | + if (fd >= 0) { | |
| 2377 | 2468 | fh = fdopen(fd, mode); |
| 2378 | 2469 | } |
| 2379 | - } | |
| 2380 | - else { | |
| 2381 | - OpenFlags = AIO_KEEPOPEN; | |
| 2382 | - } | |
| 2470 | + else | |
| 2471 | +#endif | |
| 2472 | + fh = fopen(Jim_String(filename), mode); | |
| 2383 | 2473 | |
| 2384 | - if (fh == NULL) { | |
| 2385 | - JimAioSetError(interp, filename); | |
| 2474 | + if (fh == NULL) { | |
| 2475 | + JimAioSetError(interp, filename); | |
| 2386 | 2476 | #if !defined(JIM_ANSIC) |
| 2387 | - if (fd >= 0) { | |
| 2388 | - close(fd); | |
| 2477 | + if (fd >= 0) { | |
| 2478 | + close(fd); | |
| 2479 | + } | |
| 2480 | +#endif | |
| 2481 | + Jim_DecrRefCount(interp, filename); | |
| 2482 | + return JIM_ERR; | |
| 2389 | 2483 | } |
| 2390 | -#endif | |
| 2391 | - Jim_DecrRefCount(interp, filename); | |
| 2392 | - return JIM_ERR; | |
| 2393 | 2484 | } |
| 2394 | 2485 | |
| 2395 | 2486 | |
| 2396 | 2487 | af = Jim_Alloc(sizeof(*af)); |
| 2397 | 2488 | memset(af, 0, sizeof(*af)); |
| 2398 | 2489 | af->fp = fh; |
| 2399 | 2490 | af->fd = fileno(fh); |
| 2400 | 2491 | af->filename = filename; |
| 2401 | 2492 | #ifdef FD_CLOEXEC |
| 2402 | - if ((OpenFlags & AIO_KEEPOPEN) == 0) { | |
| 2403 | - fcntl(af->fd, F_SETFD, FD_CLOEXEC); | |
| 2493 | + if ((openFlags & AIO_KEEPOPEN) == 0) { | |
| 2494 | + (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); | |
| 2404 | 2495 | } |
| 2405 | 2496 | #endif |
| 2406 | - af->OpenFlags = OpenFlags; | |
| 2407 | -#ifdef O_NDELAY | |
| 2408 | - af->flags = fcntl(af->fd, F_GETFL); | |
| 2409 | -#endif | |
| 2497 | + af->openFlags = openFlags; | |
| 2410 | 2498 | af->addr_family = family; |
| 2411 | 2499 | snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2412 | 2500 | Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); |
| 2413 | 2501 | |
| 2414 | - Jim_SetResultString(interp, buf, -1); | |
| 2502 | + Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); | |
| 2415 | 2503 | |
| 2416 | 2504 | return JIM_OK; |
| 2417 | 2505 | } |
| 2418 | 2506 | |
| 2507 | +static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename, | |
| 2508 | + const char *hdlfmt, int family, const char *mode[2]) | |
| 2509 | +{ | |
| 2510 | + if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) { | |
| 2511 | + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); | |
| 2512 | + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); | |
| 2513 | + | |
| 2514 | + if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) { | |
| 2515 | + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); | |
| 2516 | + Jim_SetResult(interp, objPtr); | |
| 2517 | + return JIM_OK; | |
| 2518 | + } | |
| 2519 | + } | |
| 2520 | + | |
| 2521 | + | |
| 2522 | + close(p[0]); | |
| 2523 | + close(p[1]); | |
| 2524 | + JimAioSetError(interp, NULL); | |
| 2525 | + return JIM_ERR; | |
| 2526 | +} | |
| 2527 | + | |
| 2528 | + | |
| 2529 | +int Jim_MakeTempFile(Jim_Interp *interp, const char *template) | |
| 2530 | +{ | |
| 2531 | +#ifdef HAVE_MKSTEMP | |
| 2532 | + int fd; | |
| 2533 | + mode_t mask; | |
| 2534 | + Jim_Obj *filenameObj; | |
| 2535 | + | |
| 2536 | + if (template == NULL) { | |
| 2537 | + const char *tmpdir = getenv("TMPDIR"); | |
| 2538 | + if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { | |
| 2539 | + tmpdir = "/tmp/"; | |
| 2540 | + } | |
| 2541 | + filenameObj = Jim_NewStringObj(interp, tmpdir, -1); | |
| 2542 | + if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { | |
| 2543 | + Jim_AppendString(interp, filenameObj, "/", 1); | |
| 2544 | + } | |
| 2545 | + Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); | |
| 2546 | + } | |
| 2547 | + else { | |
| 2548 | + filenameObj = Jim_NewStringObj(interp, template, -1); | |
| 2549 | + } | |
| 2550 | + | |
| 2551 | + mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); | |
| 2552 | + | |
| 2553 | + | |
| 2554 | + fd = mkstemp(filenameObj->bytes); | |
| 2555 | + umask(mask); | |
| 2556 | + if (fd < 0) { | |
| 2557 | + Jim_SetResultString(interp, "Failed to create tempfile", -1); | |
| 2558 | + Jim_FreeNewObj(interp, filenameObj); | |
| 2559 | + return -1; | |
| 2560 | + } | |
| 2561 | + | |
| 2562 | + Jim_SetResult(interp, filenameObj); | |
| 2563 | + return fd; | |
| 2564 | +#else | |
| 2565 | + Jim_SetResultString(interp, "tempfile not supported", -1); | |
| 2566 | + return -1; | |
| 2567 | +#endif | |
| 2568 | +} | |
| 2419 | 2569 | |
| 2420 | 2570 | FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2421 | 2571 | { |
| 2422 | 2572 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2423 | 2573 | |
| 2574 | + | |
| 2424 | 2575 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2425 | 2576 | return ((AioFile *) cmdPtr->u.native.privData)->fp; |
| 2426 | 2577 | } |
| 2427 | 2578 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2428 | 2579 | return NULL; |
| @@ -2443,11 +2594,10 @@ | ||
| 2443 | 2594 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2444 | 2595 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2445 | 2596 | |
| 2446 | 2597 | return JIM_OK; |
| 2447 | 2598 | } |
| 2448 | - | |
| 2449 | 2599 | |
| 2450 | 2600 | #include <errno.h> |
| 2451 | 2601 | #include <stdio.h> |
| 2452 | 2602 | #include <string.h> |
| 2453 | 2603 | |
| @@ -2479,28 +2629,29 @@ | ||
| 2479 | 2629 | return JIM_OK; |
| 2480 | 2630 | } |
| 2481 | 2631 | Jim_SetResultString(interp, strerror(errno), -1); |
| 2482 | 2632 | return JIM_ERR; |
| 2483 | 2633 | } |
| 2484 | - Jim_SetResultString(interp, strerror(errno), -1); | |
| 2485 | - | |
| 2486 | - Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); | |
| 2487 | - | |
| 2488 | - while ((entryPtr = readdir(dirPtr)) != NULL) { | |
| 2489 | - if (entryPtr->d_name[0] == '.') { | |
| 2490 | - if (entryPtr->d_name[1] == '\0') { | |
| 2491 | - continue; | |
| 2492 | - } | |
| 2493 | - if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) | |
| 2494 | - continue; | |
| 2495 | - } | |
| 2496 | - Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, | |
| 2497 | - entryPtr->d_name, -1)); | |
| 2498 | - } | |
| 2499 | - closedir(dirPtr); | |
| 2500 | - | |
| 2501 | - return JIM_OK; | |
| 2634 | + else { | |
| 2635 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); | |
| 2636 | + | |
| 2637 | + while ((entryPtr = readdir(dirPtr)) != NULL) { | |
| 2638 | + if (entryPtr->d_name[0] == '.') { | |
| 2639 | + if (entryPtr->d_name[1] == '\0') { | |
| 2640 | + continue; | |
| 2641 | + } | |
| 2642 | + if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) | |
| 2643 | + continue; | |
| 2644 | + } | |
| 2645 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); | |
| 2646 | + } | |
| 2647 | + closedir(dirPtr); | |
| 2648 | + | |
| 2649 | + Jim_SetResult(interp, listObj); | |
| 2650 | + | |
| 2651 | + return JIM_OK; | |
| 2652 | + } | |
| 2502 | 2653 | } |
| 2503 | 2654 | |
| 2504 | 2655 | int Jim_readdirInit(Jim_Interp *interp) |
| 2505 | 2656 | { |
| 2506 | 2657 | if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) |
| @@ -2511,10 +2662,14 @@ | ||
| 2511 | 2662 | } |
| 2512 | 2663 | |
| 2513 | 2664 | #include <stdlib.h> |
| 2514 | 2665 | #include <string.h> |
| 2515 | 2666 | |
| 2667 | +#if defined(JIM_REGEXP) | |
| 2668 | +#else | |
| 2669 | + #include <regex.h> | |
| 2670 | +#endif | |
| 2516 | 2671 | |
| 2517 | 2672 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2518 | 2673 | { |
| 2519 | 2674 | regfree(objPtr->internalRep.regexpValue.compre); |
| 2520 | 2675 | Jim_Free(objPtr->internalRep.regexpValue.compre); |
| @@ -3058,58 +3213,61 @@ | ||
| 3058 | 3213 | } |
| 3059 | 3214 | #endif |
| 3060 | 3215 | return "unknown"; |
| 3061 | 3216 | } |
| 3062 | 3217 | |
| 3063 | - | |
| 3064 | -static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, | |
| 3065 | - jim_wide value) | |
| 3066 | -{ | |
| 3067 | - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); | |
| 3068 | - Jim_Obj *valobj = Jim_NewWideObj(interp, value); | |
| 3069 | - | |
| 3070 | - if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { | |
| 3071 | - Jim_FreeObj(interp, nameobj); | |
| 3072 | - Jim_FreeObj(interp, valobj); | |
| 3073 | - return JIM_ERR; | |
| 3074 | - } | |
| 3075 | - return JIM_OK; | |
| 3076 | -} | |
| 3077 | - | |
| 3078 | -static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, | |
| 3079 | - const char *value) | |
| 3080 | -{ | |
| 3081 | - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); | |
| 3082 | - Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); | |
| 3083 | - | |
| 3084 | - if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { | |
| 3085 | - Jim_FreeObj(interp, nameobj); | |
| 3086 | - Jim_FreeObj(interp, valobj); | |
| 3087 | - return JIM_ERR; | |
| 3088 | - } | |
| 3089 | - return JIM_OK; | |
| 3218 | +static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value) | |
| 3219 | +{ | |
| 3220 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); | |
| 3221 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); | |
| 3090 | 3222 | } |
| 3091 | 3223 | |
| 3092 | 3224 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3093 | 3225 | { |
| 3094 | - if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { | |
| 3095 | - Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); | |
| 3096 | - return JIM_ERR; | |
| 3097 | - } | |
| 3098 | - set_array_int_value(interp, varName, "ino", sb->st_ino); | |
| 3099 | - set_array_int_value(interp, varName, "mode", sb->st_mode); | |
| 3100 | - set_array_int_value(interp, varName, "nlink", sb->st_nlink); | |
| 3101 | - set_array_int_value(interp, varName, "uid", sb->st_uid); | |
| 3102 | - set_array_int_value(interp, varName, "gid", sb->st_gid); | |
| 3103 | - set_array_int_value(interp, varName, "size", sb->st_size); | |
| 3104 | - set_array_int_value(interp, varName, "atime", sb->st_atime); | |
| 3105 | - set_array_int_value(interp, varName, "mtime", sb->st_mtime); | |
| 3106 | - set_array_int_value(interp, varName, "ctime", sb->st_ctime); | |
| 3107 | - set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); | |
| 3108 | - | |
| 3109 | - | |
| 3110 | - Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); | |
| 3226 | + | |
| 3227 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); | |
| 3228 | + | |
| 3229 | + AppendStatElement(interp, listObj, "dev", sb->st_dev); | |
| 3230 | + AppendStatElement(interp, listObj, "ino", sb->st_ino); | |
| 3231 | + AppendStatElement(interp, listObj, "mode", sb->st_mode); | |
| 3232 | + AppendStatElement(interp, listObj, "nlink", sb->st_nlink); | |
| 3233 | + AppendStatElement(interp, listObj, "uid", sb->st_uid); | |
| 3234 | + AppendStatElement(interp, listObj, "gid", sb->st_gid); | |
| 3235 | + AppendStatElement(interp, listObj, "size", sb->st_size); | |
| 3236 | + AppendStatElement(interp, listObj, "atime", sb->st_atime); | |
| 3237 | + AppendStatElement(interp, listObj, "mtime", sb->st_mtime); | |
| 3238 | + AppendStatElement(interp, listObj, "ctime", sb->st_ctime); | |
| 3239 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); | |
| 3240 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); | |
| 3241 | + | |
| 3242 | + | |
| 3243 | + if (varName) { | |
| 3244 | + Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); | |
| 3245 | + if (objPtr) { | |
| 3246 | + if (Jim_DictSize(interp, objPtr) < 0) { | |
| 3247 | + | |
| 3248 | + Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); | |
| 3249 | + Jim_FreeNewObj(interp, listObj); | |
| 3250 | + return JIM_ERR; | |
| 3251 | + } | |
| 3252 | + | |
| 3253 | + if (Jim_IsShared(objPtr)) | |
| 3254 | + objPtr = Jim_DuplicateObj(interp, objPtr); | |
| 3255 | + | |
| 3256 | + | |
| 3257 | + Jim_ListAppendList(interp, objPtr, listObj); | |
| 3258 | + Jim_DictSize(interp, objPtr); | |
| 3259 | + Jim_InvalidateStringRep(objPtr); | |
| 3260 | + | |
| 3261 | + Jim_FreeNewObj(interp, listObj); | |
| 3262 | + listObj = objPtr; | |
| 3263 | + } | |
| 3264 | + Jim_SetVariable(interp, varName, listObj); | |
| 3265 | + } | |
| 3266 | + | |
| 3267 | + | |
| 3268 | + Jim_SetResult(interp, listObj); | |
| 3111 | 3269 | |
| 3112 | 3270 | return JIM_OK; |
| 3113 | 3271 | } |
| 3114 | 3272 | |
| 3115 | 3273 | static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3264,14 +3422,11 @@ | ||
| 3264 | 3422 | return JIM_OK; |
| 3265 | 3423 | } |
| 3266 | 3424 | |
| 3267 | 3425 | static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) |
| 3268 | 3426 | { |
| 3269 | - const char *path = Jim_String(filename); | |
| 3270 | - int rc = access(path, mode); | |
| 3271 | - | |
| 3272 | - Jim_SetResultBool(interp, rc != -1); | |
| 3427 | + Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1); | |
| 3273 | 3428 | |
| 3274 | 3429 | return JIM_OK; |
| 3275 | 3430 | } |
| 3276 | 3431 | |
| 3277 | 3432 | static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3287,10 +3442,11 @@ | ||
| 3287 | 3442 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3288 | 3443 | { |
| 3289 | 3444 | #ifdef X_OK |
| 3290 | 3445 | return file_access(interp, argv[0], X_OK); |
| 3291 | 3446 | #else |
| 3447 | + | |
| 3292 | 3448 | Jim_SetResultBool(interp, 1); |
| 3293 | 3449 | return JIM_OK; |
| 3294 | 3450 | #endif |
| 3295 | 3451 | } |
| 3296 | 3452 | |
| @@ -3391,33 +3547,21 @@ | ||
| 3391 | 3547 | argv++; |
| 3392 | 3548 | } |
| 3393 | 3549 | return JIM_OK; |
| 3394 | 3550 | } |
| 3395 | 3551 | |
| 3396 | -#ifdef HAVE_MKSTEMP | |
| 3397 | 3552 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3398 | 3553 | { |
| 3399 | - int fd; | |
| 3400 | - char *filename; | |
| 3401 | - const char *template = "/tmp/tcl.tmp.XXXXXX"; | |
| 3402 | - | |
| 3403 | - if (argc >= 1) { | |
| 3404 | - template = Jim_String(argv[0]); | |
| 3405 | - } | |
| 3406 | - filename = Jim_StrDup(template); | |
| 3407 | - | |
| 3408 | - fd = mkstemp(filename); | |
| 3409 | - if (fd < 0) { | |
| 3410 | - Jim_SetResultString(interp, "Failed to create tempfile", -1); | |
| 3554 | + int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); | |
| 3555 | + | |
| 3556 | + if (fd < 0) { | |
| 3411 | 3557 | return JIM_ERR; |
| 3412 | 3558 | } |
| 3413 | 3559 | close(fd); |
| 3414 | 3560 | |
| 3415 | - Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1)); | |
| 3416 | 3561 | return JIM_OK; |
| 3417 | 3562 | } |
| 3418 | -#endif | |
| 3419 | 3563 | |
| 3420 | 3564 | static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3421 | 3565 | { |
| 3422 | 3566 | const char *source; |
| 3423 | 3567 | const char *dest; |
| @@ -3459,14 +3603,11 @@ | ||
| 3459 | 3603 | return JIM_ERR; |
| 3460 | 3604 | } |
| 3461 | 3605 | return JIM_OK; |
| 3462 | 3606 | } |
| 3463 | 3607 | |
| 3464 | -#ifndef HAVE_LSTAT | |
| 3465 | -#define lstat stat | |
| 3466 | -#endif | |
| 3467 | - | |
| 3608 | +#ifdef HAVE_LSTAT | |
| 3468 | 3609 | static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 3469 | 3610 | { |
| 3470 | 3611 | const char *path = Jim_String(filename); |
| 3471 | 3612 | |
| 3472 | 3613 | if (lstat(path, sb) == -1) { |
| @@ -3473,10 +3614,13 @@ | ||
| 3473 | 3614 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3474 | 3615 | return JIM_ERR; |
| 3475 | 3616 | } |
| 3476 | 3617 | return JIM_OK; |
| 3477 | 3618 | } |
| 3619 | +#else | |
| 3620 | +#define file_lstat file_stat | |
| 3621 | +#endif | |
| 3478 | 3622 | |
| 3479 | 3623 | static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3480 | 3624 | { |
| 3481 | 3625 | struct stat sb; |
| 3482 | 3626 | |
| @@ -3601,28 +3745,32 @@ | ||
| 3601 | 3745 | } |
| 3602 | 3746 | Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); |
| 3603 | 3747 | return JIM_OK; |
| 3604 | 3748 | } |
| 3605 | 3749 | |
| 3750 | +#ifdef HAVE_LSTAT | |
| 3606 | 3751 | static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3607 | 3752 | { |
| 3608 | 3753 | struct stat sb; |
| 3609 | 3754 | |
| 3610 | 3755 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 3611 | 3756 | return JIM_ERR; |
| 3612 | 3757 | } |
| 3613 | - return StoreStatData(interp, argv[1], &sb); | |
| 3758 | + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); | |
| 3614 | 3759 | } |
| 3760 | +#else | |
| 3761 | +#define file_cmd_lstat file_cmd_stat | |
| 3762 | +#endif | |
| 3615 | 3763 | |
| 3616 | 3764 | static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3617 | 3765 | { |
| 3618 | 3766 | struct stat sb; |
| 3619 | 3767 | |
| 3620 | 3768 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 3621 | 3769 | return JIM_ERR; |
| 3622 | 3770 | } |
| 3623 | - return StoreStatData(interp, argv[1], &sb); | |
| 3771 | + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); | |
| 3624 | 3772 | } |
| 3625 | 3773 | |
| 3626 | 3774 | static const jim_subcmd_type file_command_table[] = { |
| 3627 | 3775 | { "atime", |
| 3628 | 3776 | "name", |
| @@ -3727,19 +3875,17 @@ | ||
| 3727 | 3875 | file_cmd_mkdir, |
| 3728 | 3876 | 1, |
| 3729 | 3877 | -1, |
| 3730 | 3878 | |
| 3731 | 3879 | }, |
| 3732 | -#ifdef HAVE_MKSTEMP | |
| 3733 | 3880 | { "tempfile", |
| 3734 | 3881 | "?template?", |
| 3735 | 3882 | file_cmd_tempfile, |
| 3736 | 3883 | 0, |
| 3737 | 3884 | 1, |
| 3738 | 3885 | |
| 3739 | 3886 | }, |
| 3740 | -#endif | |
| 3741 | 3887 | { "rename", |
| 3742 | 3888 | "?-force? source dest", |
| 3743 | 3889 | file_cmd_rename, |
| 3744 | 3890 | 2, |
| 3745 | 3891 | 3, |
| @@ -3760,20 +3906,20 @@ | ||
| 3760 | 3906 | 1, |
| 3761 | 3907 | 1, |
| 3762 | 3908 | |
| 3763 | 3909 | }, |
| 3764 | 3910 | { "stat", |
| 3765 | - "name var", | |
| 3911 | + "name ?var?", | |
| 3766 | 3912 | file_cmd_stat, |
| 3767 | - 2, | |
| 3913 | + 1, | |
| 3768 | 3914 | 2, |
| 3769 | 3915 | |
| 3770 | 3916 | }, |
| 3771 | 3917 | { "lstat", |
| 3772 | - "name var", | |
| 3918 | + "name ?var?", | |
| 3773 | 3919 | file_cmd_lstat, |
| 3774 | - 2, | |
| 3920 | + 1, | |
| 3775 | 3921 | 2, |
| 3776 | 3922 | |
| 3777 | 3923 | }, |
| 3778 | 3924 | { "type", |
| 3779 | 3925 | "name", |
| @@ -3829,15 +3975,15 @@ | ||
| 3829 | 3975 | return JIM_OK; |
| 3830 | 3976 | } |
| 3831 | 3977 | |
| 3832 | 3978 | static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3833 | 3979 | { |
| 3834 | - const int cwd_len = 2048; | |
| 3835 | - char *cwd = malloc(cwd_len); | |
| 3980 | + char *cwd = Jim_Alloc(MAXPATHLEN); | |
| 3836 | 3981 | |
| 3837 | - if (getcwd(cwd, cwd_len) == NULL) { | |
| 3982 | + if (getcwd(cwd, MAXPATHLEN) == NULL) { | |
| 3838 | 3983 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 3984 | + Jim_Free(cwd); | |
| 3839 | 3985 | return JIM_ERR; |
| 3840 | 3986 | } |
| 3841 | 3987 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 3842 | 3988 | { |
| 3843 | 3989 | |
| @@ -3848,11 +3994,11 @@ | ||
| 3848 | 3994 | } |
| 3849 | 3995 | #endif |
| 3850 | 3996 | |
| 3851 | 3997 | Jim_SetResultString(interp, cwd, -1); |
| 3852 | 3998 | |
| 3853 | - free(cwd); | |
| 3999 | + Jim_Free(cwd); | |
| 3854 | 4000 | return JIM_OK; |
| 3855 | 4001 | } |
| 3856 | 4002 | |
| 3857 | 4003 | int Jim_fileInit(Jim_Interp *interp) |
| 3858 | 4004 | { |
| @@ -3917,10 +4063,11 @@ | ||
| 3917 | 4063 | |
| 3918 | 4064 | int Jim_execInit(Jim_Interp *interp) |
| 3919 | 4065 | { |
| 3920 | 4066 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 3921 | 4067 | return JIM_ERR; |
| 4068 | + | |
| 3922 | 4069 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); |
| 3923 | 4070 | return JIM_OK; |
| 3924 | 4071 | } |
| 3925 | 4072 | #else |
| 3926 | 4073 | |
| @@ -3960,10 +4107,11 @@ | ||
| 3960 | 4107 | static int JimErrno(void); |
| 3961 | 4108 | #else |
| 3962 | 4109 | #include <unistd.h> |
| 3963 | 4110 | #include <fcntl.h> |
| 3964 | 4111 | #include <sys/wait.h> |
| 4112 | + #include <sys/stat.h> | |
| 3965 | 4113 | |
| 3966 | 4114 | typedef int fdtype; |
| 3967 | 4115 | typedef int pidtype; |
| 3968 | 4116 | #define JimPipe pipe |
| 3969 | 4117 | #define JimErrno() errno |
| @@ -4034,23 +4182,12 @@ | ||
| 4034 | 4182 | Jim_RemoveTrailingNewline(strObj); |
| 4035 | 4183 | fclose(fh); |
| 4036 | 4184 | return JIM_OK; |
| 4037 | 4185 | } |
| 4038 | 4186 | |
| 4039 | -static void JimTrimTrailingNewline(Jim_Interp *interp) | |
| 4040 | -{ | |
| 4041 | - int len; | |
| 4042 | - const char *p = Jim_GetString(Jim_GetResult(interp), &len); | |
| 4043 | - | |
| 4044 | - if (len > 0 && p[len - 1] == '\n') { | |
| 4045 | - Jim_SetResultString(interp, p, len - 1); | |
| 4046 | - } | |
| 4047 | -} | |
| 4048 | - | |
| 4049 | 4187 | static char **JimBuildEnv(Jim_Interp *interp) |
| 4050 | 4188 | { |
| 4051 | -#if defined(jim_ext_tclcompat) | |
| 4052 | 4189 | int i; |
| 4053 | 4190 | int size; |
| 4054 | 4191 | int num; |
| 4055 | 4192 | int n; |
| 4056 | 4193 | char **envptr; |
| @@ -4064,10 +4201,11 @@ | ||
| 4064 | 4201 | |
| 4065 | 4202 | |
| 4066 | 4203 | |
| 4067 | 4204 | num = Jim_ListLength(interp, objPtr); |
| 4068 | 4205 | if (num % 2) { |
| 4206 | + | |
| 4069 | 4207 | num--; |
| 4070 | 4208 | } |
| 4071 | 4209 | size = Jim_Length(objPtr) + 2; |
| 4072 | 4210 | |
| 4073 | 4211 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4090,22 +4228,17 @@ | ||
| 4090 | 4228 | } |
| 4091 | 4229 | envptr[n] = NULL; |
| 4092 | 4230 | *envdata = 0; |
| 4093 | 4231 | |
| 4094 | 4232 | return envptr; |
| 4095 | -#else | |
| 4096 | - return Jim_GetEnviron(); | |
| 4097 | -#endif | |
| 4098 | 4233 | } |
| 4099 | 4234 | |
| 4100 | 4235 | static void JimFreeEnv(char **env, char **original_environ) |
| 4101 | 4236 | { |
| 4102 | -#ifdef jim_ext_tclcompat | |
| 4103 | 4237 | if (env != original_environ) { |
| 4104 | 4238 | Jim_Free(env); |
| 4105 | 4239 | } |
| 4106 | -#endif | |
| 4107 | 4240 | } |
| 4108 | 4241 | |
| 4109 | 4242 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) |
| 4110 | 4243 | { |
| 4111 | 4244 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| @@ -4154,19 +4287,19 @@ | ||
| 4154 | 4287 | } |
| 4155 | 4288 | |
| 4156 | 4289 | |
| 4157 | 4290 | struct WaitInfo |
| 4158 | 4291 | { |
| 4159 | - pidtype pid; | |
| 4292 | + pidtype pid; | |
| 4160 | 4293 | int status; |
| 4161 | 4294 | int flags; |
| 4162 | 4295 | }; |
| 4163 | 4296 | |
| 4164 | 4297 | struct WaitInfoTable { |
| 4165 | - struct WaitInfo *info; | |
| 4166 | - int size; | |
| 4167 | - int used; | |
| 4298 | + struct WaitInfo *info; | |
| 4299 | + int size; | |
| 4300 | + int used; | |
| 4168 | 4301 | }; |
| 4169 | 4302 | |
| 4170 | 4303 | |
| 4171 | 4304 | #define WI_DETACHED 2 |
| 4172 | 4305 | |
| @@ -4189,14 +4322,12 @@ | ||
| 4189 | 4322 | return table; |
| 4190 | 4323 | } |
| 4191 | 4324 | |
| 4192 | 4325 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4193 | 4326 | { |
| 4194 | - fdtype outputId; /* File id for output pipe. -1 | |
| 4195 | - * means command overrode. */ | |
| 4196 | - fdtype errorId; /* File id for temporary file | |
| 4197 | - * containing error output. */ | |
| 4327 | + fdtype outputId; | |
| 4328 | + fdtype errorId; | |
| 4198 | 4329 | pidtype *pidPtr; |
| 4199 | 4330 | int numPids, result; |
| 4200 | 4331 | |
| 4201 | 4332 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4202 | 4333 | Jim_Obj *listObj; |
| @@ -4243,26 +4374,32 @@ | ||
| 4243 | 4374 | |
| 4244 | 4375 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4245 | 4376 | { |
| 4246 | 4377 | struct WaitInfo *waitPtr; |
| 4247 | 4378 | int count; |
| 4379 | + int dest; | |
| 4248 | 4380 | |
| 4249 | 4381 | if (!table) { |
| 4250 | 4382 | return; |
| 4251 | 4383 | } |
| 4252 | 4384 | |
| 4253 | - for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) { | |
| 4385 | + waitPtr = table->info; | |
| 4386 | + dest = 0; | |
| 4387 | + for (count = table->used; count > 0; waitPtr++, count--) { | |
| 4254 | 4388 | if (waitPtr->flags & WI_DETACHED) { |
| 4255 | 4389 | int status; |
| 4256 | 4390 | pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); |
| 4257 | - if (pid != JIM_BAD_PID) { | |
| 4258 | - if (waitPtr != &table->info[table->used - 1]) { | |
| 4259 | - *waitPtr = table->info[table->used - 1]; | |
| 4260 | - } | |
| 4391 | + if (pid == waitPtr->pid) { | |
| 4392 | + | |
| 4261 | 4393 | table->used--; |
| 4394 | + continue; | |
| 4262 | 4395 | } |
| 4263 | 4396 | } |
| 4397 | + if (waitPtr != &table->info[dest]) { | |
| 4398 | + table->info[dest] = *waitPtr; | |
| 4399 | + } | |
| 4400 | + dest++; | |
| 4264 | 4401 | } |
| 4265 | 4402 | } |
| 4266 | 4403 | |
| 4267 | 4404 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4268 | 4405 | { |
| @@ -4284,11 +4421,10 @@ | ||
| 4284 | 4421 | } |
| 4285 | 4422 | |
| 4286 | 4423 | |
| 4287 | 4424 | return JIM_BAD_PID; |
| 4288 | 4425 | } |
| 4289 | - | |
| 4290 | 4426 | |
| 4291 | 4427 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) |
| 4292 | 4428 | { |
| 4293 | 4429 | int j; |
| 4294 | 4430 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| @@ -4609,27 +4745,23 @@ | ||
| 4609 | 4745 | } |
| 4610 | 4746 | outputId = pipeIds[1]; |
| 4611 | 4747 | } |
| 4612 | 4748 | |
| 4613 | 4749 | |
| 4750 | + if (pipe_dup_err) { | |
| 4751 | + errorId = outputId; | |
| 4752 | + } | |
| 4753 | + | |
| 4754 | + | |
| 4614 | 4755 | |
| 4615 | 4756 | #ifdef __MINGW32__ |
| 4616 | 4757 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); |
| 4617 | 4758 | if (pid == JIM_BAD_PID) { |
| 4618 | 4759 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4619 | 4760 | goto error; |
| 4620 | 4761 | } |
| 4621 | 4762 | #else |
| 4622 | - if (table->info == NULL) { | |
| 4623 | - (void)signal(SIGPIPE, SIG_IGN); | |
| 4624 | - } | |
| 4625 | - | |
| 4626 | - | |
| 4627 | - if (pipe_dup_err) { | |
| 4628 | - errorId = outputId; | |
| 4629 | - } | |
| 4630 | - | |
| 4631 | 4763 | pid = vfork(); |
| 4632 | 4764 | if (pid < 0) { |
| 4633 | 4765 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 4634 | 4766 | goto error; |
| 4635 | 4767 | } |
| @@ -4642,14 +4774,17 @@ | ||
| 4642 | 4774 | |
| 4643 | 4775 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 4644 | 4776 | close(i); |
| 4645 | 4777 | } |
| 4646 | 4778 | |
| 4779 | + | |
| 4780 | + (void)signal(SIGPIPE, SIG_DFL); | |
| 4781 | + | |
| 4647 | 4782 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 4648 | 4783 | |
| 4649 | 4784 | |
| 4650 | - fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]); | |
| 4785 | + fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); | |
| 4651 | 4786 | _exit(127); |
| 4652 | 4787 | } |
| 4653 | 4788 | #endif |
| 4654 | 4789 | |
| 4655 | 4790 | |
| @@ -4751,19 +4886,24 @@ | ||
| 4751 | 4886 | if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { |
| 4752 | 4887 | result = JIM_ERR; |
| 4753 | 4888 | } |
| 4754 | 4889 | } |
| 4755 | 4890 | |
| 4756 | - JimTrimTrailingNewline(interp); | |
| 4891 | + Jim_RemoveTrailingNewline(Jim_GetResult(interp)); | |
| 4757 | 4892 | |
| 4758 | 4893 | return result; |
| 4759 | 4894 | } |
| 4760 | 4895 | |
| 4761 | 4896 | int Jim_execInit(Jim_Interp *interp) |
| 4762 | 4897 | { |
| 4763 | 4898 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4764 | 4899 | return JIM_ERR; |
| 4900 | + | |
| 4901 | +#ifdef SIGPIPE | |
| 4902 | + (void)signal(SIGPIPE, SIG_IGN); | |
| 4903 | +#endif | |
| 4904 | + | |
| 4765 | 4905 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); |
| 4766 | 4906 | return JIM_OK; |
| 4767 | 4907 | } |
| 4768 | 4908 | |
| 4769 | 4909 | #if defined(__MINGW32__) |
| @@ -5088,28 +5228,26 @@ | ||
| 5088 | 5228 | { |
| 5089 | 5229 | STARTUPINFO startInfo; |
| 5090 | 5230 | PROCESS_INFORMATION procInfo; |
| 5091 | 5231 | HANDLE hProcess, h; |
| 5092 | 5232 | char execPath[MAX_PATH]; |
| 5093 | - char *originalName; | |
| 5094 | 5233 | pidtype pid = JIM_BAD_PID; |
| 5095 | 5234 | Jim_Obj *cmdLineObj; |
| 5096 | 5235 | |
| 5097 | 5236 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5098 | 5237 | return JIM_BAD_PID; |
| 5099 | 5238 | } |
| 5100 | - originalName = argv[0]; | |
| 5101 | 5239 | argv[0] = execPath; |
| 5102 | 5240 | |
| 5103 | 5241 | hProcess = GetCurrentProcess(); |
| 5104 | 5242 | cmdLineObj = JimWinBuildCommandLine(interp, argv); |
| 5105 | 5243 | |
| 5106 | 5244 | |
| 5107 | 5245 | ZeroMemory(&startInfo, sizeof(startInfo)); |
| 5108 | 5246 | startInfo.cb = sizeof(startInfo); |
| 5109 | 5247 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5110 | - startInfo.hStdInput = INVALID_HANDLE_VALUE; | |
| 5248 | + startInfo.hStdInput = INVALID_HANDLE_VALUE; | |
| 5111 | 5249 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5112 | 5250 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5113 | 5251 | |
| 5114 | 5252 | if (inputId == JIM_BAD_FD) { |
| 5115 | 5253 | if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { |
| @@ -5182,18 +5320,17 @@ | ||
| 5182 | 5320 | return lseek(fd, 0L, SEEK_SET); |
| 5183 | 5321 | } |
| 5184 | 5322 | |
| 5185 | 5323 | static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5186 | 5324 | { |
| 5187 | - char inName[] = "/tmp/tcl.tmp.XXXXXX"; | |
| 5325 | + int fd = Jim_MakeTempFile(interp, NULL); | |
| 5188 | 5326 | |
| 5189 | - int fd = mkstemp(inName); | |
| 5190 | 5327 | if (fd == JIM_BAD_FD) { |
| 5191 | 5328 | Jim_SetResultErrno(interp, "couldn't create temp file"); |
| 5192 | 5329 | return -1; |
| 5193 | 5330 | } |
| 5194 | - unlink(inName); | |
| 5331 | + unlink(Jim_String(Jim_GetResult(interp))); | |
| 5195 | 5332 | if (contents) { |
| 5196 | 5333 | if (write(fd, contents, len) != len) { |
| 5197 | 5334 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5198 | 5335 | close(fd); |
| 5199 | 5336 | return -1; |
| @@ -5217,11 +5354,10 @@ | ||
| 5217 | 5354 | } |
| 5218 | 5355 | #endif |
| 5219 | 5356 | #endif |
| 5220 | 5357 | |
| 5221 | 5358 | |
| 5222 | - | |
| 5223 | 5359 | #ifndef _XOPEN_SOURCE |
| 5224 | 5360 | #define _XOPEN_SOURCE 500 |
| 5225 | 5361 | #endif |
| 5226 | 5362 | |
| 5227 | 5363 | #include <stdlib.h> |
| @@ -5239,11 +5375,11 @@ | ||
| 5239 | 5375 | |
| 5240 | 5376 | char buf[100]; |
| 5241 | 5377 | time_t t; |
| 5242 | 5378 | long seconds; |
| 5243 | 5379 | |
| 5244 | - const char *format = "%a %b %d %H:%M:%S %Z %Y"; | |
| 5380 | + const char *format = "%a %b %d %H:%M:%S %Z %Y"; | |
| 5245 | 5381 | |
| 5246 | 5382 | if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { |
| 5247 | 5383 | return -1; |
| 5248 | 5384 | } |
| 5249 | 5385 | |
| @@ -5254,11 +5390,14 @@ | ||
| 5254 | 5390 | if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { |
| 5255 | 5391 | return JIM_ERR; |
| 5256 | 5392 | } |
| 5257 | 5393 | t = seconds; |
| 5258 | 5394 | |
| 5259 | - strftime(buf, sizeof(buf), format, localtime(&t)); | |
| 5395 | + if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { | |
| 5396 | + Jim_SetResultString(interp, "format string too long", -1); | |
| 5397 | + return JIM_ERR; | |
| 5398 | + } | |
| 5260 | 5399 | |
| 5261 | 5400 | Jim_SetResultString(interp, buf, -1); |
| 5262 | 5401 | |
| 5263 | 5402 | return JIM_OK; |
| 5264 | 5403 | } |
| @@ -5374,11 +5513,10 @@ | ||
| 5374 | 5513 | |
| 5375 | 5514 | Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); |
| 5376 | 5515 | return JIM_OK; |
| 5377 | 5516 | } |
| 5378 | 5517 | |
| 5379 | - | |
| 5380 | 5518 | #include <limits.h> |
| 5381 | 5519 | #include <stdlib.h> |
| 5382 | 5520 | #include <string.h> |
| 5383 | 5521 | #include <stdio.h> |
| 5384 | 5522 | #include <errno.h> |
| @@ -5392,33 +5530,29 @@ | ||
| 5392 | 5530 | } |
| 5393 | 5531 | |
| 5394 | 5532 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5395 | 5533 | { |
| 5396 | 5534 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5535 | + Jim_Obj *patternObj; | |
| 5397 | 5536 | |
| 5398 | 5537 | if (!objPtr) { |
| 5399 | 5538 | return JIM_OK; |
| 5400 | 5539 | } |
| 5401 | 5540 | |
| 5402 | - if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { | |
| 5403 | - | |
| 5404 | - if (Jim_IsList(objPtr)) { | |
| 5405 | - if (Jim_ListLength(interp, objPtr) % 2 != 0) { | |
| 5406 | - | |
| 5407 | - return JIM_ERR; | |
| 5408 | - } | |
| 5409 | - } | |
| 5410 | - else if (Jim_DictSize(interp, objPtr) < 0) { | |
| 5411 | - | |
| 5412 | - return JIM_ERR; | |
| 5413 | - } | |
| 5414 | - Jim_SetResult(interp, objPtr); | |
| 5415 | - return JIM_OK; | |
| 5541 | + patternObj = (argc == 1) ? NULL : argv[1]; | |
| 5542 | + | |
| 5543 | + | |
| 5544 | + if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { | |
| 5545 | + if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { | |
| 5546 | + | |
| 5547 | + Jim_SetResult(interp, objPtr); | |
| 5548 | + return JIM_OK; | |
| 5549 | + } | |
| 5416 | 5550 | } |
| 5417 | 5551 | |
| 5418 | 5552 | |
| 5419 | - return Jim_DictValues(interp, objPtr, argv[1]); | |
| 5553 | + return Jim_DictValues(interp, objPtr, patternObj); | |
| 5420 | 5554 | } |
| 5421 | 5555 | |
| 5422 | 5556 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5423 | 5557 | { |
| 5424 | 5558 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5443,10 +5577,15 @@ | ||
| 5443 | 5577 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5444 | 5578 | return JIM_OK; |
| 5445 | 5579 | } |
| 5446 | 5580 | |
| 5447 | 5581 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5582 | + | |
| 5583 | + if (objPtr == NULL) { | |
| 5584 | + | |
| 5585 | + return JIM_OK; | |
| 5586 | + } | |
| 5448 | 5587 | |
| 5449 | 5588 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5450 | 5589 | return JIM_ERR; |
| 5451 | 5590 | } |
| 5452 | 5591 | |
| @@ -5480,10 +5619,20 @@ | ||
| 5480 | 5619 | |
| 5481 | 5620 | Jim_SetResultInt(interp, len); |
| 5482 | 5621 | |
| 5483 | 5622 | return JIM_OK; |
| 5484 | 5623 | } |
| 5624 | + | |
| 5625 | +static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 5626 | +{ | |
| 5627 | + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); | |
| 5628 | + if (objPtr) { | |
| 5629 | + return Jim_DictInfo(interp, objPtr); | |
| 5630 | + } | |
| 5631 | + Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL); | |
| 5632 | + return JIM_ERR; | |
| 5633 | +} | |
| 5485 | 5634 | |
| 5486 | 5635 | static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5487 | 5636 | { |
| 5488 | 5637 | int i; |
| 5489 | 5638 | int len; |
| @@ -5498,10 +5647,13 @@ | ||
| 5498 | 5647 | |
| 5499 | 5648 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5500 | 5649 | if (!dictObj) { |
| 5501 | 5650 | |
| 5502 | 5651 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5652 | + } | |
| 5653 | + else if (Jim_DictSize(interp, dictObj) < 0) { | |
| 5654 | + return JIM_ERR; | |
| 5503 | 5655 | } |
| 5504 | 5656 | |
| 5505 | 5657 | if (Jim_IsShared(dictObj)) { |
| 5506 | 5658 | dictObj = Jim_DuplicateObj(interp, dictObj); |
| 5507 | 5659 | } |
| @@ -5551,10 +5703,17 @@ | ||
| 5551 | 5703 | "arrayName", |
| 5552 | 5704 | array_cmd_size, |
| 5553 | 5705 | 1, |
| 5554 | 5706 | 1, |
| 5555 | 5707 | |
| 5708 | + }, | |
| 5709 | + { "stat", | |
| 5710 | + "arrayName", | |
| 5711 | + array_cmd_stat, | |
| 5712 | + 1, | |
| 5713 | + 1, | |
| 5714 | + | |
| 5556 | 5715 | }, |
| 5557 | 5716 | { "unset", |
| 5558 | 5717 | "arrayName ?pattern?", |
| 5559 | 5718 | array_cmd_unset, |
| 5560 | 5719 | 1, |
| @@ -5597,11 +5756,10 @@ | ||
| 5597 | 5756 | Jim_arrayInit(interp); |
| 5598 | 5757 | Jim_stdlibInit(interp); |
| 5599 | 5758 | Jim_tclcompatInit(interp); |
| 5600 | 5759 | return JIM_OK; |
| 5601 | 5760 | } |
| 5602 | - | |
| 5603 | 5761 | #define JIM_OPTIMIZATION |
| 5604 | 5762 | |
| 5605 | 5763 | #include <stdio.h> |
| 5606 | 5764 | #include <stdlib.h> |
| 5607 | 5765 | |
| @@ -5661,21 +5819,20 @@ | ||
| 5661 | 5819 | #define JIM_INTEGER_SPACE 24 |
| 5662 | 5820 | |
| 5663 | 5821 | const char *jim_tt_name(int type); |
| 5664 | 5822 | |
| 5665 | 5823 | #ifdef JIM_DEBUG_PANIC |
| 5666 | -static void JimPanicDump(int panic_condition, const char *fmt, ...); | |
| 5824 | +static void JimPanicDump(int fail_condition, const char *fmt, ...); | |
| 5667 | 5825 | #define JimPanic(X) JimPanicDump X |
| 5668 | 5826 | #else |
| 5669 | 5827 | #define JimPanic(X) |
| 5670 | 5828 | #endif |
| 5671 | 5829 | |
| 5672 | 5830 | |
| 5673 | 5831 | static char JimEmptyStringRep[] = ""; |
| 5674 | 5832 | |
| 5675 | -static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); | |
| 5676 | -static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); | |
| 5833 | +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); | |
| 5677 | 5834 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| 5678 | 5835 | int flags); |
| 5679 | 5836 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); |
| 5680 | 5837 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); |
| 5681 | 5838 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -5922,44 +6079,10 @@ | ||
| 5922 | 6079 | } |
| 5923 | 6080 | return n; |
| 5924 | 6081 | } |
| 5925 | 6082 | #endif |
| 5926 | 6083 | |
| 5927 | -static int JimWideToString(char *buf, jim_wide wideValue) | |
| 5928 | -{ | |
| 5929 | - int pos = 0; | |
| 5930 | - | |
| 5931 | - if (wideValue == 0) { | |
| 5932 | - buf[pos++] = '0'; | |
| 5933 | - } | |
| 5934 | - else { | |
| 5935 | - char tmp[JIM_INTEGER_SPACE]; | |
| 5936 | - int num = 0; | |
| 5937 | - int i; | |
| 5938 | - | |
| 5939 | - if (wideValue < 0) { | |
| 5940 | - buf[pos++] = '-'; | |
| 5941 | - | |
| 5942 | - i = wideValue % 10; | |
| 5943 | - tmp[num++] = (i > 0) ? (10 - i) : -i; | |
| 5944 | - wideValue /= -10; | |
| 5945 | - } | |
| 5946 | - | |
| 5947 | - while (wideValue) { | |
| 5948 | - tmp[num++] = wideValue % 10; | |
| 5949 | - wideValue /= 10; | |
| 5950 | - } | |
| 5951 | - | |
| 5952 | - for (i = 0; i < num; i++) { | |
| 5953 | - buf[pos++] = '0' + tmp[num - i - 1]; | |
| 5954 | - } | |
| 5955 | - } | |
| 5956 | - buf[pos] = 0; | |
| 5957 | - | |
| 5958 | - return pos; | |
| 5959 | -} | |
| 5960 | - | |
| 5961 | 6084 | static int JimCheckConversion(const char *str, const char *endptr) |
| 5962 | 6085 | { |
| 5963 | 6086 | if (str[0] == '\0' || str == endptr) { |
| 5964 | 6087 | return JIM_ERR; |
| 5965 | 6088 | } |
| @@ -6070,48 +6193,10 @@ | ||
| 6070 | 6193 | } |
| 6071 | 6194 | |
| 6072 | 6195 | return JimCheckConversion(str, endptr); |
| 6073 | 6196 | } |
| 6074 | 6197 | |
| 6075 | -int Jim_DoubleToString(char *buf, double doubleValue) | |
| 6076 | -{ | |
| 6077 | - int len; | |
| 6078 | - int i; | |
| 6079 | - | |
| 6080 | - len = sprintf(buf, "%.12g", doubleValue); | |
| 6081 | - | |
| 6082 | - | |
| 6083 | - for (i = 0; i < len; i++) { | |
| 6084 | - if (buf[i] == '.' || buf[i] == 'e') { | |
| 6085 | -#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) | |
| 6086 | - char *e = strchr(buf, 'e'); | |
| 6087 | - if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { | |
| 6088 | - | |
| 6089 | - e += 2; | |
| 6090 | - memmove(e, e + 1, len - (e - buf)); | |
| 6091 | - return len - 1; | |
| 6092 | - } | |
| 6093 | -#endif | |
| 6094 | - return len; | |
| 6095 | - } | |
| 6096 | - | |
| 6097 | - if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') { | |
| 6098 | - buf[i] = toupper(UCHAR(buf[i])); | |
| 6099 | - if (buf[i] == 'n' || buf[i] == 'N') | |
| 6100 | - buf[i+2] = toupper(UCHAR(buf[i+2])); | |
| 6101 | - buf[i + 3] = 0; | |
| 6102 | - return i + 3; | |
| 6103 | - } | |
| 6104 | - } | |
| 6105 | - | |
| 6106 | - buf[i++] = '.'; | |
| 6107 | - buf[i++] = '0'; | |
| 6108 | - buf[i] = '\0'; | |
| 6109 | - | |
| 6110 | - return i; | |
| 6111 | -} | |
| 6112 | - | |
| 6113 | 6198 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6114 | 6199 | { |
| 6115 | 6200 | char *endptr; |
| 6116 | 6201 | |
| 6117 | 6202 | |
| @@ -6133,23 +6218,23 @@ | ||
| 6133 | 6218 | } |
| 6134 | 6219 | return res; |
| 6135 | 6220 | } |
| 6136 | 6221 | |
| 6137 | 6222 | #ifdef JIM_DEBUG_PANIC |
| 6138 | -void JimPanicDump(int condition, const char *fmt, ...) | |
| 6223 | +static void JimPanicDump(int condition, const char *fmt, ...) | |
| 6139 | 6224 | { |
| 6140 | 6225 | va_list ap; |
| 6141 | 6226 | |
| 6142 | 6227 | if (!condition) { |
| 6143 | 6228 | return; |
| 6144 | 6229 | } |
| 6145 | 6230 | |
| 6146 | 6231 | va_start(ap, fmt); |
| 6147 | 6232 | |
| 6148 | - fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); | |
| 6233 | + fprintf(stderr, "\nJIM INTERPRETER PANIC: "); | |
| 6149 | 6234 | vfprintf(stderr, fmt, ap); |
| 6150 | - fprintf(stderr, JIM_NL JIM_NL); | |
| 6235 | + fprintf(stderr, "\n\n"); | |
| 6151 | 6236 | va_end(ap); |
| 6152 | 6237 | |
| 6153 | 6238 | #ifdef HAVE_BACKTRACE |
| 6154 | 6239 | { |
| 6155 | 6240 | void *array[40]; |
| @@ -6157,13 +6242,13 @@ | ||
| 6157 | 6242 | char **strings; |
| 6158 | 6243 | |
| 6159 | 6244 | size = backtrace(array, 40); |
| 6160 | 6245 | strings = backtrace_symbols(array, size); |
| 6161 | 6246 | for (i = 0; i < size; i++) |
| 6162 | - fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]); | |
| 6163 | - fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL); | |
| 6164 | - fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL); | |
| 6247 | + fprintf(stderr, "[backtrace] %s\n", strings[i]); | |
| 6248 | + fprintf(stderr, "[backtrace] Include the above lines and the output\n"); | |
| 6249 | + fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n"); | |
| 6165 | 6250 | } |
| 6166 | 6251 | #endif |
| 6167 | 6252 | |
| 6168 | 6253 | exit(1); |
| 6169 | 6254 | } |
| @@ -6237,18 +6322,24 @@ | ||
| 6237 | 6322 | h += (h << 3) + *buf++; |
| 6238 | 6323 | return h; |
| 6239 | 6324 | } |
| 6240 | 6325 | |
| 6241 | 6326 | |
| 6327 | + | |
| 6242 | 6328 | |
| 6243 | 6329 | static void JimResetHashTable(Jim_HashTable *ht) |
| 6244 | 6330 | { |
| 6245 | 6331 | ht->table = NULL; |
| 6246 | 6332 | ht->size = 0; |
| 6247 | 6333 | ht->sizemask = 0; |
| 6248 | 6334 | ht->used = 0; |
| 6249 | 6335 | ht->collisions = 0; |
| 6336 | +#ifdef JIM_RANDOMISE_HASH | |
| 6337 | + ht->uniq = (rand() ^ time(NULL) ^ clock()); | |
| 6338 | +#else | |
| 6339 | + ht->uniq = 0; | |
| 6340 | +#endif | |
| 6250 | 6341 | } |
| 6251 | 6342 | |
| 6252 | 6343 | static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) |
| 6253 | 6344 | { |
| 6254 | 6345 | iter->ht = ht; |
| @@ -6286,10 +6377,12 @@ | ||
| 6286 | 6377 | |
| 6287 | 6378 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6288 | 6379 | n.size = realsize; |
| 6289 | 6380 | n.sizemask = realsize - 1; |
| 6290 | 6381 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6382 | + | |
| 6383 | + n.uniq = ht->uniq; | |
| 6291 | 6384 | |
| 6292 | 6385 | |
| 6293 | 6386 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6294 | 6387 | |
| 6295 | 6388 | n.used = ht->used; |
| @@ -6342,20 +6435,27 @@ | ||
| 6342 | 6435 | int existed; |
| 6343 | 6436 | Jim_HashEntry *entry; |
| 6344 | 6437 | |
| 6345 | 6438 | entry = JimInsertHashEntry(ht, key, 1); |
| 6346 | 6439 | if (entry->key) { |
| 6347 | - | |
| 6348 | - Jim_FreeEntryVal(ht, entry); | |
| 6440 | + if (ht->type->valDestructor && ht->type->valDup) { | |
| 6441 | + void *newval = ht->type->valDup(ht->privdata, val); | |
| 6442 | + ht->type->valDestructor(ht->privdata, entry->u.val); | |
| 6443 | + entry->u.val = newval; | |
| 6444 | + } | |
| 6445 | + else { | |
| 6446 | + Jim_FreeEntryVal(ht, entry); | |
| 6447 | + Jim_SetHashVal(ht, entry, val); | |
| 6448 | + } | |
| 6349 | 6449 | existed = 1; |
| 6350 | 6450 | } |
| 6351 | 6451 | else { |
| 6352 | 6452 | |
| 6353 | 6453 | Jim_SetHashKey(ht, entry, key); |
| 6454 | + Jim_SetHashVal(ht, entry, val); | |
| 6354 | 6455 | existed = 0; |
| 6355 | 6456 | } |
| 6356 | - Jim_SetHashVal(ht, entry, val); | |
| 6357 | 6457 | |
| 6358 | 6458 | return existed; |
| 6359 | 6459 | } |
| 6360 | 6460 | |
| 6361 | 6461 | |
| @@ -6520,11 +6620,11 @@ | ||
| 6520 | 6620 | return Jim_GenHashFunction(key, strlen(key)); |
| 6521 | 6621 | } |
| 6522 | 6622 | |
| 6523 | 6623 | static void *JimStringCopyHTDup(void *privdata, const void *key) |
| 6524 | 6624 | { |
| 6525 | - return strdup(key); | |
| 6625 | + return Jim_StrDup(key); | |
| 6526 | 6626 | } |
| 6527 | 6627 | |
| 6528 | 6628 | static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 6529 | 6629 | { |
| 6530 | 6630 | return strcmp(key1, key2) == 0; |
| @@ -6620,11 +6720,11 @@ | ||
| 6620 | 6720 | freeFunc(stack->vector[i]); |
| 6621 | 6721 | } |
| 6622 | 6722 | |
| 6623 | 6723 | |
| 6624 | 6724 | |
| 6625 | -#define JIM_TT_NONE 0 | |
| 6725 | +#define JIM_TT_NONE 0 | |
| 6626 | 6726 | #define JIM_TT_STR 1 |
| 6627 | 6727 | #define JIM_TT_ESC 2 |
| 6628 | 6728 | #define JIM_TT_VAR 3 |
| 6629 | 6729 | #define JIM_TT_DICTSUGAR 4 |
| 6630 | 6730 | #define JIM_TT_CMD 5 |
| @@ -6652,10 +6752,15 @@ | ||
| 6652 | 6752 | |
| 6653 | 6753 | |
| 6654 | 6754 | #define JIM_PS_DEF 0 |
| 6655 | 6755 | #define JIM_PS_QUOTE 1 |
| 6656 | 6756 | #define JIM_PS_DICTSUGAR 2 |
| 6757 | + | |
| 6758 | +struct JimParseMissing { | |
| 6759 | + int ch; | |
| 6760 | + int line; | |
| 6761 | +}; | |
| 6657 | 6762 | |
| 6658 | 6763 | struct JimParserCtx |
| 6659 | 6764 | { |
| 6660 | 6765 | const char *p; |
| 6661 | 6766 | int len; |
| @@ -6665,17 +6770,11 @@ | ||
| 6665 | 6770 | int tline; |
| 6666 | 6771 | int tt; |
| 6667 | 6772 | int eof; |
| 6668 | 6773 | int state; |
| 6669 | 6774 | int comment; |
| 6670 | - char missing; | |
| 6671 | - int missingline; | |
| 6672 | -}; | |
| 6673 | - | |
| 6674 | -struct JimParseResult { | |
| 6675 | - char missing; | |
| 6676 | - int line; | |
| 6775 | + struct JimParseMissing missing; | |
| 6677 | 6776 | }; |
| 6678 | 6777 | |
| 6679 | 6778 | static int JimParseScript(struct JimParserCtx *pc); |
| 6680 | 6779 | static int JimParseSep(struct JimParserCtx *pc); |
| 6681 | 6780 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -6685,11 +6784,10 @@ | ||
| 6685 | 6784 | static int JimParseBrace(struct JimParserCtx *pc); |
| 6686 | 6785 | static int JimParseStr(struct JimParserCtx *pc); |
| 6687 | 6786 | static int JimParseComment(struct JimParserCtx *pc); |
| 6688 | 6787 | static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6689 | 6788 | static int JimParseSubQuote(struct JimParserCtx *pc); |
| 6690 | -static void JimParseSubCmd(struct JimParserCtx *pc); | |
| 6691 | 6789 | static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); |
| 6692 | 6790 | |
| 6693 | 6791 | static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) |
| 6694 | 6792 | { |
| 6695 | 6793 | pc->p = prg; |
| @@ -6700,12 +6798,12 @@ | ||
| 6700 | 6798 | pc->tt = JIM_TT_NONE; |
| 6701 | 6799 | pc->eof = 0; |
| 6702 | 6800 | pc->state = JIM_PS_DEF; |
| 6703 | 6801 | pc->linenr = linenr; |
| 6704 | 6802 | pc->comment = 1; |
| 6705 | - pc->missing = ' '; | |
| 6706 | - pc->missingline = linenr; | |
| 6803 | + pc->missing.ch = ' '; | |
| 6804 | + pc->missing.line = linenr; | |
| 6707 | 6805 | } |
| 6708 | 6806 | |
| 6709 | 6807 | static int JimParseScript(struct JimParserCtx *pc) |
| 6710 | 6808 | { |
| 6711 | 6809 | while (1) { |
| @@ -6837,12 +6935,12 @@ | ||
| 6837 | 6935 | break; |
| 6838 | 6936 | } |
| 6839 | 6937 | pc->p++; |
| 6840 | 6938 | pc->len--; |
| 6841 | 6939 | } |
| 6842 | - pc->missing = '{'; | |
| 6843 | - pc->missingline = pc->tline; | |
| 6940 | + pc->missing.ch = '{'; | |
| 6941 | + pc->missing.line = pc->tline; | |
| 6844 | 6942 | pc->tend = pc->p - 1; |
| 6845 | 6943 | } |
| 6846 | 6944 | |
| 6847 | 6945 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 6848 | 6946 | { |
| @@ -6884,12 +6982,12 @@ | ||
| 6884 | 6982 | break; |
| 6885 | 6983 | } |
| 6886 | 6984 | pc->p++; |
| 6887 | 6985 | pc->len--; |
| 6888 | 6986 | } |
| 6889 | - pc->missing = '"'; | |
| 6890 | - pc->missingline = line; | |
| 6987 | + pc->missing.ch = '"'; | |
| 6988 | + pc->missing.line = line; | |
| 6891 | 6989 | pc->tend = pc->p - 1; |
| 6892 | 6990 | return tt; |
| 6893 | 6991 | } |
| 6894 | 6992 | |
| 6895 | 6993 | static void JimParseSubCmd(struct JimParserCtx *pc) |
| @@ -6943,12 +7041,12 @@ | ||
| 6943 | 7041 | } |
| 6944 | 7042 | startofword = isspace(UCHAR(*pc->p)); |
| 6945 | 7043 | pc->p++; |
| 6946 | 7044 | pc->len--; |
| 6947 | 7045 | } |
| 6948 | - pc->missing = '['; | |
| 6949 | - pc->missingline = line; | |
| 7046 | + pc->missing.ch = '['; | |
| 7047 | + pc->missing.line = line; | |
| 6950 | 7048 | pc->tend = pc->p - 1; |
| 6951 | 7049 | } |
| 6952 | 7050 | |
| 6953 | 7051 | static int JimParseBrace(struct JimParserCtx *pc) |
| 6954 | 7052 | { |
| @@ -7088,19 +7186,19 @@ | ||
| 7088 | 7186 | if (*pc->p == '"') { |
| 7089 | 7187 | pc->state = JIM_PS_QUOTE; |
| 7090 | 7188 | pc->p++; |
| 7091 | 7189 | pc->len--; |
| 7092 | 7190 | |
| 7093 | - pc->missingline = pc->tline; | |
| 7191 | + pc->missing.line = pc->tline; | |
| 7094 | 7192 | } |
| 7095 | 7193 | } |
| 7096 | 7194 | pc->tstart = pc->p; |
| 7097 | 7195 | pc->tline = pc->linenr; |
| 7098 | 7196 | while (1) { |
| 7099 | 7197 | if (pc->len == 0) { |
| 7100 | 7198 | if (pc->state == JIM_PS_QUOTE) { |
| 7101 | - pc->missing = '"'; | |
| 7199 | + pc->missing.ch = '"'; | |
| 7102 | 7200 | } |
| 7103 | 7201 | pc->tend = pc->p - 1; |
| 7104 | 7202 | pc->tt = JIM_TT_ESC; |
| 7105 | 7203 | return JIM_OK; |
| 7106 | 7204 | } |
| @@ -7116,10 +7214,14 @@ | ||
| 7116 | 7214 | pc->linenr++; |
| 7117 | 7215 | } |
| 7118 | 7216 | pc->p++; |
| 7119 | 7217 | pc->len--; |
| 7120 | 7218 | } |
| 7219 | + else if (pc->len == 1) { | |
| 7220 | + | |
| 7221 | + pc->missing.ch = '\\'; | |
| 7222 | + } | |
| 7121 | 7223 | break; |
| 7122 | 7224 | case '(': |
| 7123 | 7225 | |
| 7124 | 7226 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7125 | 7227 | break; |
| @@ -7176,17 +7278,26 @@ | ||
| 7176 | 7278 | } |
| 7177 | 7279 | |
| 7178 | 7280 | static int JimParseComment(struct JimParserCtx *pc) |
| 7179 | 7281 | { |
| 7180 | 7282 | while (*pc->p) { |
| 7181 | - if (*pc->p == '\n') { | |
| 7283 | + if (*pc->p == '\\') { | |
| 7284 | + pc->p++; | |
| 7285 | + pc->len--; | |
| 7286 | + if (pc->len == 0) { | |
| 7287 | + pc->missing.ch = '\\'; | |
| 7288 | + return JIM_OK; | |
| 7289 | + } | |
| 7290 | + if (*pc->p == '\n') { | |
| 7291 | + pc->linenr++; | |
| 7292 | + } | |
| 7293 | + } | |
| 7294 | + else if (*pc->p == '\n') { | |
| 7295 | + pc->p++; | |
| 7296 | + pc->len--; | |
| 7182 | 7297 | pc->linenr++; |
| 7183 | - if (*(pc->p - 1) != '\\') { | |
| 7184 | - pc->p++; | |
| 7185 | - pc->len--; | |
| 7186 | - return JIM_OK; | |
| 7187 | - } | |
| 7298 | + break; | |
| 7188 | 7299 | } |
| 7189 | 7300 | pc->p++; |
| 7190 | 7301 | pc->len--; |
| 7191 | 7302 | } |
| 7192 | 7303 | return JIM_OK; |
| @@ -7404,13 +7515,13 @@ | ||
| 7404 | 7515 | JimParserInit(&parser, s, len, 1); |
| 7405 | 7516 | while (!parser.eof) { |
| 7406 | 7517 | JimParseScript(&parser); |
| 7407 | 7518 | } |
| 7408 | 7519 | if (stateCharPtr) { |
| 7409 | - *stateCharPtr = parser.missing; | |
| 7520 | + *stateCharPtr = parser.missing.ch; | |
| 7410 | 7521 | } |
| 7411 | - return parser.missing == ' '; | |
| 7522 | + return parser.missing.ch == ' '; | |
| 7412 | 7523 | } |
| 7413 | 7524 | |
| 7414 | 7525 | static int JimParseListSep(struct JimParserCtx *pc); |
| 7415 | 7526 | static int JimParseListStr(struct JimParserCtx *pc); |
| 7416 | 7527 | static int JimParseListQuote(struct JimParserCtx *pc); |
| @@ -7662,10 +7773,16 @@ | ||
| 7662 | 7773 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7663 | 7774 | objPtr->typePtr->updateStringProc(objPtr); |
| 7664 | 7775 | } |
| 7665 | 7776 | return objPtr->bytes; |
| 7666 | 7777 | } |
| 7778 | + | |
| 7779 | +static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) | |
| 7780 | +{ | |
| 7781 | + objPtr->bytes = Jim_StrDup(str); | |
| 7782 | + objPtr->length = strlen(str); | |
| 7783 | +} | |
| 7667 | 7784 | |
| 7668 | 7785 | static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 7669 | 7786 | static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 7670 | 7787 | |
| 7671 | 7788 | static const Jim_ObjType dictSubstObjType = { |
| @@ -7703,11 +7820,10 @@ | ||
| 7703 | 7820 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 7704 | 7821 | { |
| 7705 | 7822 | JIM_NOTUSED(interp); |
| 7706 | 7823 | |
| 7707 | 7824 | dupPtr->internalRep.strValue.maxLength = srcPtr->length; |
| 7708 | - | |
| 7709 | 7825 | dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; |
| 7710 | 7826 | } |
| 7711 | 7827 | |
| 7712 | 7828 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7713 | 7829 | { |
| @@ -7752,18 +7868,17 @@ | ||
| 7752 | 7868 | if (len == -1) |
| 7753 | 7869 | len = strlen(s); |
| 7754 | 7870 | |
| 7755 | 7871 | if (len == 0) { |
| 7756 | 7872 | objPtr->bytes = JimEmptyStringRep; |
| 7757 | - objPtr->length = 0; | |
| 7758 | 7873 | } |
| 7759 | 7874 | else { |
| 7760 | 7875 | objPtr->bytes = Jim_Alloc(len + 1); |
| 7761 | - objPtr->length = len; | |
| 7762 | 7876 | memcpy(objPtr->bytes, s, len); |
| 7763 | 7877 | objPtr->bytes[len] = '\0'; |
| 7764 | 7878 | } |
| 7879 | + objPtr->length = len; | |
| 7765 | 7880 | |
| 7766 | 7881 | |
| 7767 | 7882 | objPtr->typePtr = NULL; |
| 7768 | 7883 | return objPtr; |
| 7769 | 7884 | } |
| @@ -7791,11 +7906,11 @@ | ||
| 7791 | 7906 | Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) |
| 7792 | 7907 | { |
| 7793 | 7908 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 7794 | 7909 | |
| 7795 | 7910 | objPtr->bytes = s; |
| 7796 | - objPtr->length = len == -1 ? strlen(s) : len; | |
| 7911 | + objPtr->length = (len == -1) ? strlen(s) : len; | |
| 7797 | 7912 | objPtr->typePtr = NULL; |
| 7798 | 7913 | return objPtr; |
| 7799 | 7914 | } |
| 7800 | 7915 | |
| 7801 | 7916 | static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) |
| @@ -7820,17 +7935,17 @@ | ||
| 7820 | 7935 | } |
| 7821 | 7936 | objPtr->internalRep.strValue.maxLength = needlen; |
| 7822 | 7937 | } |
| 7823 | 7938 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 7824 | 7939 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 7940 | + | |
| 7825 | 7941 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 7826 | 7942 | |
| 7827 | 7943 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 7828 | 7944 | } |
| 7829 | 7945 | objPtr->length += len; |
| 7830 | 7946 | } |
| 7831 | - | |
| 7832 | 7947 | |
| 7833 | 7948 | void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) |
| 7834 | 7949 | { |
| 7835 | 7950 | JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); |
| 7836 | 7951 | SetStringFromAny(interp, objPtr); |
| @@ -7838,13 +7953,11 @@ | ||
| 7838 | 7953 | } |
| 7839 | 7954 | |
| 7840 | 7955 | void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) |
| 7841 | 7956 | { |
| 7842 | 7957 | int len; |
| 7843 | - const char *str; | |
| 7844 | - | |
| 7845 | - str = Jim_GetString(appendObjPtr, &len); | |
| 7958 | + const char *str = Jim_GetString(appendObjPtr, &len); | |
| 7846 | 7959 | Jim_AppendString(interp, objPtr, str, len); |
| 7847 | 7960 | } |
| 7848 | 7961 | |
| 7849 | 7962 | void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) |
| 7850 | 7963 | { |
| @@ -7851,11 +7964,11 @@ | ||
| 7851 | 7964 | va_list ap; |
| 7852 | 7965 | |
| 7853 | 7966 | SetStringFromAny(interp, objPtr); |
| 7854 | 7967 | va_start(ap, objPtr); |
| 7855 | 7968 | while (1) { |
| 7856 | - char *s = va_arg(ap, char *); | |
| 7969 | + const char *s = va_arg(ap, const char *); | |
| 7857 | 7970 | |
| 7858 | 7971 | if (s == NULL) |
| 7859 | 7972 | break; |
| 7860 | 7973 | Jim_AppendString(interp, objPtr, s, -1); |
| 7861 | 7974 | } |
| @@ -7862,20 +7975,20 @@ | ||
| 7862 | 7975 | va_end(ap); |
| 7863 | 7976 | } |
| 7864 | 7977 | |
| 7865 | 7978 | int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) |
| 7866 | 7979 | { |
| 7867 | - const char *aStr, *bStr; | |
| 7868 | - int aLen, bLen; | |
| 7869 | - | |
| 7870 | - if (aObjPtr == bObjPtr) | |
| 7980 | + if (aObjPtr == bObjPtr) { | |
| 7871 | 7981 | return 1; |
| 7872 | - aStr = Jim_GetString(aObjPtr, &aLen); | |
| 7873 | - bStr = Jim_GetString(bObjPtr, &bLen); | |
| 7874 | - if (aLen != bLen) | |
| 7875 | - return 0; | |
| 7876 | - return JimStringCompare(aStr, aLen, bStr, bLen) == 0; | |
| 7982 | + } | |
| 7983 | + else { | |
| 7984 | + int Alen, Blen; | |
| 7985 | + const char *sA = Jim_GetString(aObjPtr, &Alen); | |
| 7986 | + const char *sB = Jim_GetString(bObjPtr, &Blen); | |
| 7987 | + | |
| 7988 | + return Alen == Blen && memcmp(sA, sB, Alen) == 0; | |
| 7989 | + } | |
| 7877 | 7990 | } |
| 7878 | 7991 | |
| 7879 | 7992 | int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) |
| 7880 | 7993 | { |
| 7881 | 7994 | return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); |
| @@ -8036,11 +8149,11 @@ | ||
| 8036 | 8149 | static void JimStrCopyUpperLower(char *dest, const char *str, int uc) |
| 8037 | 8150 | { |
| 8038 | 8151 | while (*str) { |
| 8039 | 8152 | int c; |
| 8040 | 8153 | str += utf8_tounicode(str, &c); |
| 8041 | - dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c)); | |
| 8154 | + dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c)); | |
| 8042 | 8155 | } |
| 8043 | 8156 | *dest = 0; |
| 8044 | 8157 | } |
| 8045 | 8158 | |
| 8046 | 8159 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) |
| @@ -8096,11 +8209,11 @@ | ||
| 8096 | 8209 | len *= 2; |
| 8097 | 8210 | #endif |
| 8098 | 8211 | buf = p = Jim_Alloc(len + 1); |
| 8099 | 8212 | |
| 8100 | 8213 | str += utf8_tounicode(str, &c); |
| 8101 | - p += utf8_fromunicode(p, utf8_title(c)); | |
| 8214 | + p += utf8_getchars(p, utf8_title(c)); | |
| 8102 | 8215 | |
| 8103 | 8216 | JimStrCopyUpperLower(p, str, 0); |
| 8104 | 8217 | |
| 8105 | 8218 | return Jim_NewStringObjNoAlloc(interp, buf, -1); |
| 8106 | 8219 | } |
| @@ -8203,10 +8316,11 @@ | ||
| 8203 | 8316 | if (nontrim == NULL) { |
| 8204 | 8317 | |
| 8205 | 8318 | return Jim_NewEmptyStringObj(interp); |
| 8206 | 8319 | } |
| 8207 | 8320 | if (nontrim == strObjPtr->bytes + len) { |
| 8321 | + | |
| 8208 | 8322 | return strObjPtr; |
| 8209 | 8323 | } |
| 8210 | 8324 | |
| 8211 | 8325 | if (Jim_IsShared(strObjPtr)) { |
| 8212 | 8326 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| @@ -8226,14 +8340,14 @@ | ||
| 8226 | 8340 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8227 | 8341 | |
| 8228 | 8342 | |
| 8229 | 8343 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8230 | 8344 | |
| 8231 | - if (objPtr != strObjPtr) { | |
| 8345 | + | |
| 8346 | + if (objPtr != strObjPtr && objPtr->refCount == 0) { | |
| 8232 | 8347 | |
| 8233 | - Jim_IncrRefCount(objPtr); | |
| 8234 | - Jim_DecrRefCount(interp, objPtr); | |
| 8348 | + Jim_FreeNewObj(interp, objPtr); | |
| 8235 | 8349 | } |
| 8236 | 8350 | |
| 8237 | 8351 | return strObjPtr; |
| 8238 | 8352 | } |
| 8239 | 8353 | |
| @@ -8270,26 +8384,26 @@ | ||
| 8270 | 8384 | return JIM_ERR; |
| 8271 | 8385 | } |
| 8272 | 8386 | |
| 8273 | 8387 | str = Jim_GetString(strObjPtr, &len); |
| 8274 | 8388 | if (len == 0) { |
| 8275 | - Jim_SetResultInt(interp, !strict); | |
| 8389 | + Jim_SetResultBool(interp, !strict); | |
| 8276 | 8390 | return JIM_OK; |
| 8277 | 8391 | } |
| 8278 | 8392 | |
| 8279 | 8393 | switch (strclass) { |
| 8280 | 8394 | case STR_IS_INTEGER: |
| 8281 | 8395 | { |
| 8282 | 8396 | jim_wide w; |
| 8283 | - Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); | |
| 8397 | + Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); | |
| 8284 | 8398 | return JIM_OK; |
| 8285 | 8399 | } |
| 8286 | 8400 | |
| 8287 | 8401 | case STR_IS_DOUBLE: |
| 8288 | 8402 | { |
| 8289 | 8403 | double d; |
| 8290 | - Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); | |
| 8404 | + Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); | |
| 8291 | 8405 | return JIM_OK; |
| 8292 | 8406 | } |
| 8293 | 8407 | |
| 8294 | 8408 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8295 | 8409 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| @@ -8307,15 +8421,15 @@ | ||
| 8307 | 8421 | return JIM_ERR; |
| 8308 | 8422 | } |
| 8309 | 8423 | |
| 8310 | 8424 | for (i = 0; i < len; i++) { |
| 8311 | 8425 | if (!isclassfunc(str[i])) { |
| 8312 | - Jim_SetResultInt(interp, 0); | |
| 8426 | + Jim_SetResultBool(interp, 0); | |
| 8313 | 8427 | return JIM_OK; |
| 8314 | 8428 | } |
| 8315 | 8429 | } |
| 8316 | - Jim_SetResultInt(interp, 1); | |
| 8430 | + Jim_SetResultBool(interp, 1); | |
| 8317 | 8431 | return JIM_OK; |
| 8318 | 8432 | } |
| 8319 | 8433 | |
| 8320 | 8434 | |
| 8321 | 8435 | |
| @@ -8327,17 +8441,19 @@ | ||
| 8327 | 8441 | JIM_TYPE_REFERENCES, |
| 8328 | 8442 | }; |
| 8329 | 8443 | |
| 8330 | 8444 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) |
| 8331 | 8445 | { |
| 8332 | - if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) | |
| 8446 | + if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { | |
| 8333 | 8447 | return 1; |
| 8448 | + } | |
| 8334 | 8449 | else { |
| 8335 | 8450 | const char *objStr = Jim_String(objPtr); |
| 8336 | 8451 | |
| 8337 | 8452 | if (strcmp(str, objStr) != 0) |
| 8338 | 8453 | return 0; |
| 8454 | + | |
| 8339 | 8455 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8340 | 8456 | Jim_FreeIntRep(interp, objPtr); |
| 8341 | 8457 | objPtr->typePtr = &comparedStringObjType; |
| 8342 | 8458 | } |
| 8343 | 8459 | objPtr->internalRep.ptr = (char *)str; |
| @@ -8379,24 +8495,23 @@ | ||
| 8379 | 8495 | |
| 8380 | 8496 | static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, |
| 8381 | 8497 | Jim_Obj *fileNameObj, int lineNumber) |
| 8382 | 8498 | { |
| 8383 | 8499 | JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); |
| 8384 | - JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object")); | |
| 8500 | + JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); | |
| 8385 | 8501 | Jim_IncrRefCount(fileNameObj); |
| 8386 | 8502 | objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; |
| 8387 | 8503 | objPtr->internalRep.sourceValue.lineNumber = lineNumber; |
| 8388 | 8504 | objPtr->typePtr = &sourceObjType; |
| 8389 | 8505 | } |
| 8390 | 8506 | |
| 8391 | - | |
| 8392 | 8507 | static const Jim_ObjType scriptLineObjType = { |
| 8393 | 8508 | "scriptline", |
| 8394 | 8509 | NULL, |
| 8395 | 8510 | NULL, |
| 8396 | 8511 | NULL, |
| 8397 | - 0, | |
| 8512 | + JIM_NONE, | |
| 8398 | 8513 | }; |
| 8399 | 8514 | |
| 8400 | 8515 | static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) |
| 8401 | 8516 | { |
| 8402 | 8517 | Jim_Obj *objPtr; |
| @@ -8413,15 +8528,14 @@ | ||
| 8413 | 8528 | objPtr->internalRep.scriptLineValue.line = line; |
| 8414 | 8529 | |
| 8415 | 8530 | return objPtr; |
| 8416 | 8531 | } |
| 8417 | 8532 | |
| 8418 | -#define JIM_CMDSTRUCT_EXPAND -1 | |
| 8419 | - | |
| 8420 | 8533 | static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 8421 | 8534 | static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8422 | -static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result); | |
| 8535 | +static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); | |
| 8536 | +static int JimParseCheckMissing(Jim_Interp *interp, int ch); | |
| 8423 | 8537 | |
| 8424 | 8538 | static const Jim_ObjType scriptObjType = { |
| 8425 | 8539 | "script", |
| 8426 | 8540 | FreeScriptInternalRep, |
| 8427 | 8541 | DupScriptInternalRep, |
| @@ -8429,34 +8543,33 @@ | ||
| 8429 | 8543 | JIM_TYPE_REFERENCES, |
| 8430 | 8544 | }; |
| 8431 | 8545 | |
| 8432 | 8546 | typedef struct ScriptToken |
| 8433 | 8547 | { |
| 8434 | - int type; | |
| 8435 | 8548 | Jim_Obj *objPtr; |
| 8549 | + int type; | |
| 8436 | 8550 | } ScriptToken; |
| 8437 | 8551 | |
| 8438 | 8552 | typedef struct ScriptObj |
| 8439 | 8553 | { |
| 8440 | - int len; | |
| 8441 | 8554 | ScriptToken *token; |
| 8555 | + Jim_Obj *fileNameObj; | |
| 8556 | + int len; | |
| 8442 | 8557 | int substFlags; |
| 8443 | 8558 | int inUse; /* Used to share a ScriptObj. Currently |
| 8444 | 8559 | only used by Jim_EvalObj() as protection against |
| 8445 | 8560 | shimmering of the currently evaluated object. */ |
| 8446 | - Jim_Obj *fileNameObj; | |
| 8447 | 8561 | int firstline; |
| 8448 | 8562 | int linenr; |
| 8449 | 8563 | } ScriptObj; |
| 8450 | 8564 | |
| 8451 | 8565 | void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8452 | 8566 | { |
| 8453 | 8567 | int i; |
| 8454 | 8568 | struct ScriptObj *script = (void *)objPtr->internalRep.ptr; |
| 8455 | 8569 | |
| 8456 | - script->inUse--; | |
| 8457 | - if (script->inUse != 0) | |
| 8570 | + if (--script->inUse != 0) | |
| 8458 | 8571 | return; |
| 8459 | 8572 | for (i = 0; i < script->len; i++) { |
| 8460 | 8573 | Jim_DecrRefCount(interp, script->token[i].objPtr); |
| 8461 | 8574 | } |
| 8462 | 8575 | Jim_Free(script->token); |
| @@ -8467,11 +8580,10 @@ | ||
| 8467 | 8580 | void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 8468 | 8581 | { |
| 8469 | 8582 | JIM_NOTUSED(interp); |
| 8470 | 8583 | JIM_NOTUSED(srcPtr); |
| 8471 | 8584 | |
| 8472 | - | |
| 8473 | 8585 | dupPtr->typePtr = NULL; |
| 8474 | 8586 | } |
| 8475 | 8587 | |
| 8476 | 8588 | typedef struct |
| 8477 | 8589 | { |
| @@ -8666,11 +8778,11 @@ | ||
| 8666 | 8778 | token--; |
| 8667 | 8779 | } |
| 8668 | 8780 | |
| 8669 | 8781 | script->len = token - script->token; |
| 8670 | 8782 | |
| 8671 | - assert(script->len < count); | |
| 8783 | + JimPanic((script->len >= count, "allocated script array is too short")); | |
| 8672 | 8784 | |
| 8673 | 8785 | #ifdef DEBUG_SHOW_SCRIPT |
| 8674 | 8786 | printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); |
| 8675 | 8787 | for (i = 0; i < script->len; i++) { |
| 8676 | 8788 | const ScriptToken *t = &script->token[i]; |
| @@ -8677,10 +8789,35 @@ | ||
| 8677 | 8789 | printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); |
| 8678 | 8790 | } |
| 8679 | 8791 | #endif |
| 8680 | 8792 | |
| 8681 | 8793 | } |
| 8794 | + | |
| 8795 | +static int JimParseCheckMissing(Jim_Interp *interp, int ch) | |
| 8796 | +{ | |
| 8797 | + const char *msg; | |
| 8798 | + | |
| 8799 | + switch (ch) { | |
| 8800 | + case '\\': | |
| 8801 | + case ' ': | |
| 8802 | + return JIM_OK; | |
| 8803 | + | |
| 8804 | + case '[': | |
| 8805 | + msg = "unmatched \"[\""; | |
| 8806 | + break; | |
| 8807 | + case '{': | |
| 8808 | + msg = "missing close-brace"; | |
| 8809 | + break; | |
| 8810 | + case '"': | |
| 8811 | + default: | |
| 8812 | + msg = "missing quote"; | |
| 8813 | + break; | |
| 8814 | + } | |
| 8815 | + | |
| 8816 | + Jim_SetResultString(interp, msg, -1); | |
| 8817 | + return JIM_ERR; | |
| 8818 | +} | |
| 8682 | 8819 | |
| 8683 | 8820 | static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8684 | 8821 | ParseTokenList *tokenlist) |
| 8685 | 8822 | { |
| 8686 | 8823 | int i; |
| @@ -8699,18 +8836,19 @@ | ||
| 8699 | 8836 | } |
| 8700 | 8837 | |
| 8701 | 8838 | script->len = i; |
| 8702 | 8839 | } |
| 8703 | 8840 | |
| 8704 | -static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result) | |
| 8841 | +static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) | |
| 8705 | 8842 | { |
| 8706 | 8843 | int scriptTextLen; |
| 8707 | 8844 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 8708 | 8845 | struct JimParserCtx parser; |
| 8709 | 8846 | struct ScriptObj *script; |
| 8710 | 8847 | ParseTokenList tokenlist; |
| 8711 | 8848 | int line = 1; |
| 8849 | + int retcode = JIM_OK; | |
| 8712 | 8850 | |
| 8713 | 8851 | |
| 8714 | 8852 | if (objPtr->typePtr == &sourceObjType) { |
| 8715 | 8853 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 8716 | 8854 | } |
| @@ -8722,16 +8860,12 @@ | ||
| 8722 | 8860 | while (!parser.eof) { |
| 8723 | 8861 | JimParseScript(&parser); |
| 8724 | 8862 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 8725 | 8863 | parser.tline); |
| 8726 | 8864 | } |
| 8727 | - if (result && parser.missing != ' ') { | |
| 8728 | - ScriptTokenListFree(&tokenlist); | |
| 8729 | - result->missing = parser.missing; | |
| 8730 | - result->line = parser.missingline; | |
| 8731 | - return JIM_ERR; | |
| 8732 | - } | |
| 8865 | + | |
| 8866 | + retcode = JimParseCheckMissing(interp, parser.missing.ch); | |
| 8733 | 8867 | |
| 8734 | 8868 | |
| 8735 | 8869 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 8736 | 8870 | |
| 8737 | 8871 | |
| @@ -8742,10 +8876,11 @@ | ||
| 8742 | 8876 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 8743 | 8877 | } |
| 8744 | 8878 | else { |
| 8745 | 8879 | script->fileNameObj = interp->emptyObj; |
| 8746 | 8880 | } |
| 8881 | + script->linenr = parser.missing.line; | |
| 8747 | 8882 | Jim_IncrRefCount(script->fileNameObj); |
| 8748 | 8883 | |
| 8749 | 8884 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 8750 | 8885 | |
| 8751 | 8886 | |
| @@ -8754,11 +8889,11 @@ | ||
| 8754 | 8889 | |
| 8755 | 8890 | Jim_FreeIntRep(interp, objPtr); |
| 8756 | 8891 | Jim_SetIntRepPtr(objPtr, script); |
| 8757 | 8892 | objPtr->typePtr = &scriptObjType; |
| 8758 | 8893 | |
| 8759 | - return JIM_OK; | |
| 8894 | + return retcode; | |
| 8760 | 8895 | } |
| 8761 | 8896 | |
| 8762 | 8897 | ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8763 | 8898 | { |
| 8764 | 8899 | if (objPtr == interp->emptyObj) { |
| @@ -8765,11 +8900,13 @@ | ||
| 8765 | 8900 | |
| 8766 | 8901 | objPtr = interp->nullScriptObj; |
| 8767 | 8902 | } |
| 8768 | 8903 | |
| 8769 | 8904 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 8770 | - SetScriptFromAny(interp, objPtr, NULL); | |
| 8905 | + if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) { | |
| 8906 | + return NULL; | |
| 8907 | + } | |
| 8771 | 8908 | } |
| 8772 | 8909 | return (ScriptObj *) Jim_GetIntRepPtr(objPtr); |
| 8773 | 8910 | } |
| 8774 | 8911 | |
| 8775 | 8912 | static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) |
| @@ -8850,10 +8987,26 @@ | ||
| 8850 | 8987 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 8851 | 8988 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 8852 | 8989 | } |
| 8853 | 8990 | return nsObj; |
| 8854 | 8991 | } |
| 8992 | + | |
| 8993 | +Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) | |
| 8994 | +{ | |
| 8995 | + Jim_Obj *resultObj; | |
| 8996 | + | |
| 8997 | + const char *name = Jim_String(nameObjPtr); | |
| 8998 | + if (name[0] == ':' && name[1] == ':') { | |
| 8999 | + return nameObjPtr; | |
| 9000 | + } | |
| 9001 | + Jim_IncrRefCount(nameObjPtr); | |
| 9002 | + resultObj = Jim_NewStringObj(interp, "::", -1); | |
| 9003 | + Jim_AppendObj(interp, resultObj, nameObjPtr); | |
| 9004 | + Jim_DecrRefCount(interp, nameObjPtr); | |
| 9005 | + | |
| 9006 | + return resultObj; | |
| 9007 | +} | |
| 8855 | 9008 | |
| 8856 | 9009 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 8857 | 9010 | { |
| 8858 | 9011 | Jim_Obj *objPtr = interp->emptyObj; |
| 8859 | 9012 | |
| @@ -8877,10 +9030,15 @@ | ||
| 8877 | 9030 | |
| 8878 | 9031 | #else |
| 8879 | 9032 | |
| 8880 | 9033 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 8881 | 9034 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9035 | + | |
| 9036 | +Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) | |
| 9037 | +{ | |
| 9038 | + return nameObjPtr; | |
| 9039 | +} | |
| 8882 | 9040 | #endif |
| 8883 | 9041 | |
| 8884 | 9042 | static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) |
| 8885 | 9043 | { |
| 8886 | 9044 | Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); |
| @@ -8889,12 +9047,12 @@ | ||
| 8889 | 9047 | Jim_InterpIncrProcEpoch(interp); |
| 8890 | 9048 | } |
| 8891 | 9049 | |
| 8892 | 9050 | if (he && interp->local) { |
| 8893 | 9051 | |
| 8894 | - cmd->prevCmd = he->u.val; | |
| 8895 | - he->u.val = cmd; | |
| 9052 | + cmd->prevCmd = Jim_GetHashEntryVal(he); | |
| 9053 | + Jim_SetHashVal(&interp->commands, he, cmd); | |
| 8896 | 9054 | } |
| 8897 | 9055 | else { |
| 8898 | 9056 | if (he) { |
| 8899 | 9057 | |
| 8900 | 9058 | Jim_DeleteHashEntry(&interp->commands, name); |
| @@ -8933,19 +9091,19 @@ | ||
| 8933 | 9091 | } |
| 8934 | 9092 | |
| 8935 | 9093 | cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); |
| 8936 | 9094 | Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); |
| 8937 | 9095 | for (i = 0; i < len; i++) { |
| 8938 | - Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL; | |
| 9096 | + Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; | |
| 8939 | 9097 | Jim_Var *varPtr; |
| 8940 | 9098 | int subLen; |
| 8941 | 9099 | |
| 8942 | - Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE); | |
| 9100 | + objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); | |
| 8943 | 9101 | |
| 8944 | 9102 | subLen = Jim_ListLength(interp, objPtr); |
| 8945 | 9103 | if (subLen == 1 || subLen == 2) { |
| 8946 | - Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE); | |
| 9104 | + nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); | |
| 8947 | 9105 | if (subLen == 1) { |
| 8948 | 9106 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 8949 | 9107 | if (initObjPtr == NULL) { |
| 8950 | 9108 | Jim_SetResultFormatted(interp, |
| 8951 | 9109 | "variable for initialization of static \"%#s\" not found in the local context", |
| @@ -8952,11 +9110,11 @@ | ||
| 8952 | 9110 | nameObjPtr); |
| 8953 | 9111 | return JIM_ERR; |
| 8954 | 9112 | } |
| 8955 | 9113 | } |
| 8956 | 9114 | else { |
| 8957 | - Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE); | |
| 9115 | + initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); | |
| 8958 | 9116 | } |
| 8959 | 9117 | if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { |
| 8960 | 9118 | return JIM_ERR; |
| 8961 | 9119 | } |
| 8962 | 9120 | |
| @@ -9038,11 +9196,11 @@ | ||
| 9038 | 9196 | Jim_Obj *nameObjPtr; |
| 9039 | 9197 | Jim_Obj *defaultObjPtr; |
| 9040 | 9198 | int len; |
| 9041 | 9199 | |
| 9042 | 9200 | |
| 9043 | - Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE); | |
| 9201 | + argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); | |
| 9044 | 9202 | len = Jim_ListLength(interp, argPtr); |
| 9045 | 9203 | if (len == 0) { |
| 9046 | 9204 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9047 | 9205 | err: |
| 9048 | 9206 | JimDecrCmdRefCount(interp, cmdPtr); |
| @@ -9053,12 +9211,12 @@ | ||
| 9053 | 9211 | goto err; |
| 9054 | 9212 | } |
| 9055 | 9213 | |
| 9056 | 9214 | if (len == 2) { |
| 9057 | 9215 | |
| 9058 | - Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE); | |
| 9059 | - Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE); | |
| 9216 | + nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); | |
| 9217 | + defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); | |
| 9060 | 9218 | } |
| 9061 | 9219 | else { |
| 9062 | 9220 | |
| 9063 | 9221 | nameObjPtr = argPtr; |
| 9064 | 9222 | defaultObjPtr = NULL; |
| @@ -9132,11 +9290,11 @@ | ||
| 9132 | 9290 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9133 | 9291 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9134 | 9292 | } |
| 9135 | 9293 | else { |
| 9136 | 9294 | |
| 9137 | - cmdPtr = he->u.val; | |
| 9295 | + cmdPtr = Jim_GetHashEntryVal(he); | |
| 9138 | 9296 | JimIncrCmdRefCount(cmdPtr); |
| 9139 | 9297 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9140 | 9298 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9141 | 9299 | |
| 9142 | 9300 | |
| @@ -9217,11 +9375,11 @@ | ||
| 9217 | 9375 | return NULL; |
| 9218 | 9376 | } |
| 9219 | 9377 | #ifdef jim_ext_namespace |
| 9220 | 9378 | found: |
| 9221 | 9379 | #endif |
| 9222 | - cmd = (Jim_Cmd *)he->u.val; | |
| 9380 | + cmd = Jim_GetHashEntryVal(he); | |
| 9223 | 9381 | |
| 9224 | 9382 | |
| 9225 | 9383 | Jim_FreeIntRep(interp, objPtr); |
| 9226 | 9384 | objPtr->typePtr = &commandObjType; |
| 9227 | 9385 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| @@ -9323,11 +9481,11 @@ | ||
| 9323 | 9481 | |
| 9324 | 9482 | |
| 9325 | 9483 | Jim_FreeIntRep(interp, objPtr); |
| 9326 | 9484 | objPtr->typePtr = &variableObjType; |
| 9327 | 9485 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9328 | - objPtr->internalRep.varValue.varPtr = he->u.val; | |
| 9486 | + objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); | |
| 9329 | 9487 | objPtr->internalRep.varValue.global = global; |
| 9330 | 9488 | return JIM_OK; |
| 9331 | 9489 | } |
| 9332 | 9490 | |
| 9333 | 9491 | |
| @@ -9641,11 +9799,11 @@ | ||
| 9641 | 9799 | } |
| 9642 | 9800 | |
| 9643 | 9801 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 9644 | 9802 | if (retval == JIM_OK) { |
| 9645 | 9803 | |
| 9646 | - JimChangeCallFrameId(interp, framePtr); | |
| 9804 | + framePtr->id = interp->callFrameEpoch++; | |
| 9647 | 9805 | } |
| 9648 | 9806 | } |
| 9649 | 9807 | } |
| 9650 | 9808 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| 9651 | 9809 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); |
| @@ -9725,28 +9883,17 @@ | ||
| 9725 | 9883 | return NULL; |
| 9726 | 9884 | } |
| 9727 | 9885 | |
| 9728 | 9886 | ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9729 | 9887 | if (ret != JIM_OK) { |
| 9730 | - resObjPtr = NULL; | |
| 9731 | - if (ret < 0) { | |
| 9732 | - Jim_SetResultFormatted(interp, | |
| 9733 | - "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr); | |
| 9734 | - } | |
| 9735 | - else { | |
| 9736 | - Jim_SetResultFormatted(interp, | |
| 9737 | - "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr); | |
| 9738 | - } | |
| 9888 | + Jim_SetResultFormatted(interp, | |
| 9889 | + "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, | |
| 9890 | + ret < 0 ? "variable isn't" : "no such element in"); | |
| 9739 | 9891 | } |
| 9740 | 9892 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 9741 | - dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr); | |
| 9742 | - if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) { | |
| 9743 | - | |
| 9744 | - JimPanic((1, "SetVariable failed for JIM_UNSHARED")); | |
| 9745 | - } | |
| 9746 | 9893 | |
| 9747 | - Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); | |
| 9894 | + Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); | |
| 9748 | 9895 | } |
| 9749 | 9896 | |
| 9750 | 9897 | return resObjPtr; |
| 9751 | 9898 | } |
| 9752 | 9899 | |
| @@ -9843,68 +9990,67 @@ | ||
| 9843 | 9990 | Jim_CallFrame *cf; |
| 9844 | 9991 | |
| 9845 | 9992 | if (interp->freeFramesList) { |
| 9846 | 9993 | cf = interp->freeFramesList; |
| 9847 | 9994 | interp->freeFramesList = cf->next; |
| 9995 | + | |
| 9996 | + cf->argv = NULL; | |
| 9997 | + cf->argc = 0; | |
| 9998 | + cf->procArgsObjPtr = NULL; | |
| 9999 | + cf->procBodyObjPtr = NULL; | |
| 10000 | + cf->next = NULL; | |
| 10001 | + cf->staticVars = NULL; | |
| 10002 | + cf->localCommands = NULL; | |
| 10003 | + cf->tailcall = 0; | |
| 10004 | + cf->tailcallObj = NULL; | |
| 10005 | + cf->tailcallCmd = NULL; | |
| 9848 | 10006 | } |
| 9849 | 10007 | else { |
| 9850 | 10008 | cf = Jim_Alloc(sizeof(*cf)); |
| 9851 | - cf->vars.table = NULL; | |
| 10009 | + memset(cf, 0, sizeof(*cf)); | |
| 10010 | + | |
| 10011 | + Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); | |
| 9852 | 10012 | } |
| 9853 | 10013 | |
| 9854 | 10014 | cf->id = interp->callFrameEpoch++; |
| 9855 | 10015 | cf->parent = parent; |
| 9856 | 10016 | cf->level = parent ? parent->level + 1 : 0; |
| 9857 | - cf->argv = NULL; | |
| 9858 | - cf->argc = 0; | |
| 9859 | - cf->procArgsObjPtr = NULL; | |
| 9860 | - cf->procBodyObjPtr = NULL; | |
| 9861 | - cf->next = NULL; | |
| 9862 | - cf->staticVars = NULL; | |
| 9863 | - cf->localCommands = NULL; | |
| 9864 | - | |
| 9865 | 10017 | cf->nsObj = nsObj; |
| 9866 | 10018 | Jim_IncrRefCount(nsObj); |
| 9867 | - if (cf->vars.table == NULL) | |
| 9868 | - Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); | |
| 10019 | + | |
| 9869 | 10020 | return cf; |
| 9870 | 10021 | } |
| 9871 | 10022 | |
| 9872 | - | |
| 9873 | -static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf) | |
| 9874 | -{ | |
| 9875 | - cf->id = interp->callFrameEpoch++; | |
| 9876 | -} | |
| 9877 | - | |
| 9878 | 10023 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 9879 | 10024 | { |
| 9880 | 10025 | |
| 9881 | 10026 | if (localCommands) { |
| 9882 | 10027 | Jim_Obj *cmdNameObj; |
| 9883 | 10028 | |
| 9884 | 10029 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 9885 | 10030 | Jim_HashEntry *he; |
| 9886 | 10031 | Jim_Obj *fqObjName; |
| 10032 | + Jim_HashTable *ht = &interp->commands; | |
| 9887 | 10033 | |
| 9888 | 10034 | const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); |
| 9889 | 10035 | |
| 9890 | - he = Jim_FindHashEntry(&interp->commands, fqname); | |
| 10036 | + he = Jim_FindHashEntry(ht, fqname); | |
| 9891 | 10037 | |
| 9892 | 10038 | if (he) { |
| 9893 | - Jim_Cmd *cmd = he->u.val; | |
| 10039 | + Jim_Cmd *cmd = Jim_GetHashEntryVal(he); | |
| 9894 | 10040 | if (cmd->prevCmd) { |
| 9895 | 10041 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 9896 | 10042 | cmd->prevCmd = NULL; |
| 9897 | 10043 | |
| 9898 | 10044 | |
| 9899 | 10045 | JimDecrCmdRefCount(interp, cmd); |
| 9900 | 10046 | |
| 9901 | 10047 | |
| 9902 | - he->u.val = prevCmd; | |
| 10048 | + Jim_SetHashVal(ht, he, prevCmd); | |
| 9903 | 10049 | } |
| 9904 | 10050 | else { |
| 9905 | - Jim_DeleteHashEntry(&interp->commands, fqname); | |
| 10051 | + Jim_DeleteHashEntry(ht, fqname); | |
| 9906 | 10052 | Jim_InterpIncrProcEpoch(interp); |
| 9907 | 10053 | } |
| 9908 | 10054 | } |
| 9909 | 10055 | Jim_DecrRefCount(interp, cmdNameObj); |
| 9910 | 10056 | JimFreeQualifiedName(interp, fqObjName); |
| @@ -9914,47 +10060,45 @@ | ||
| 9914 | 10060 | } |
| 9915 | 10061 | return JIM_OK; |
| 9916 | 10062 | } |
| 9917 | 10063 | |
| 9918 | 10064 | |
| 9919 | -#define JIM_FCF_NONE 0 | |
| 9920 | -#define JIM_FCF_NOHT 1 | |
| 9921 | -static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags) | |
| 9922 | -{ | |
| 10065 | +#define JIM_FCF_FULL 0 | |
| 10066 | +#define JIM_FCF_REUSE 1 | |
| 10067 | +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) | |
| 10068 | + { | |
| 10069 | + JimDeleteLocalProcs(interp, cf->localCommands); | |
| 10070 | + | |
| 9923 | 10071 | if (cf->procArgsObjPtr) |
| 9924 | 10072 | Jim_DecrRefCount(interp, cf->procArgsObjPtr); |
| 9925 | 10073 | if (cf->procBodyObjPtr) |
| 9926 | 10074 | Jim_DecrRefCount(interp, cf->procBodyObjPtr); |
| 9927 | 10075 | Jim_DecrRefCount(interp, cf->nsObj); |
| 9928 | - if (!(flags & JIM_FCF_NOHT)) | |
| 10076 | + if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) | |
| 9929 | 10077 | Jim_FreeHashTable(&cf->vars); |
| 9930 | 10078 | else { |
| 9931 | 10079 | int i; |
| 9932 | 10080 | Jim_HashEntry **table = cf->vars.table, *he; |
| 9933 | 10081 | |
| 9934 | 10082 | for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { |
| 9935 | 10083 | he = table[i]; |
| 9936 | 10084 | while (he != NULL) { |
| 9937 | 10085 | Jim_HashEntry *nextEntry = he->next; |
| 9938 | - Jim_Var *varPtr = (void *)he->u.val; | |
| 10086 | + Jim_Var *varPtr = Jim_GetHashEntryVal(he); | |
| 9939 | 10087 | |
| 9940 | 10088 | Jim_DecrRefCount(interp, varPtr->objPtr); |
| 9941 | - Jim_Free(he->u.val); | |
| 9942 | - Jim_Free((void *)he->key); | |
| 10089 | + Jim_Free(Jim_GetHashEntryKey(he)); | |
| 10090 | + Jim_Free(varPtr); | |
| 9943 | 10091 | Jim_Free(he); |
| 9944 | 10092 | table[i] = NULL; |
| 9945 | 10093 | he = nextEntry; |
| 9946 | 10094 | } |
| 9947 | 10095 | } |
| 9948 | 10096 | cf->vars.used = 0; |
| 9949 | 10097 | } |
| 9950 | - | |
| 9951 | - JimDeleteLocalProcs(interp, cf->localCommands); | |
| 9952 | - | |
| 9953 | 10098 | cf->next = interp->freeFramesList; |
| 9954 | 10099 | interp->freeFramesList = cf; |
| 9955 | - | |
| 9956 | 10100 | } |
| 9957 | 10101 | |
| 9958 | 10102 | |
| 9959 | 10103 | #ifdef JIM_REFERENCES |
| 9960 | 10104 | |
| @@ -10031,21 +10175,16 @@ | ||
| 10031 | 10175 | NULL, |
| 10032 | 10176 | UpdateStringOfReference, |
| 10033 | 10177 | JIM_TYPE_REFERENCES, |
| 10034 | 10178 | }; |
| 10035 | 10179 | |
| 10036 | -void UpdateStringOfReference(struct Jim_Obj *objPtr) | |
| 10180 | +static void UpdateStringOfReference(struct Jim_Obj *objPtr) | |
| 10037 | 10181 | { |
| 10038 | - int len; | |
| 10039 | 10182 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 10040 | - Jim_Reference *refPtr; | |
| 10041 | 10183 | |
| 10042 | - refPtr = objPtr->internalRep.refValue.refPtr; | |
| 10043 | - len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id); | |
| 10044 | - objPtr->bytes = Jim_Alloc(len + 1); | |
| 10045 | - memcpy(objPtr->bytes, buf, len + 1); | |
| 10046 | - objPtr->length = len; | |
| 10184 | + JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); | |
| 10185 | + JimSetStringBytes(objPtr, buf); | |
| 10047 | 10186 | } |
| 10048 | 10187 | |
| 10049 | 10188 | static int isrefchar(int c) |
| 10050 | 10189 | { |
| 10051 | 10190 | return (c == '_' || isalnum(c)); |
| @@ -10096,11 +10235,11 @@ | ||
| 10096 | 10235 | he = Jim_FindHashEntry(&interp->references, &value); |
| 10097 | 10236 | if (he == NULL) { |
| 10098 | 10237 | Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); |
| 10099 | 10238 | return JIM_ERR; |
| 10100 | 10239 | } |
| 10101 | - refPtr = he->u.val; | |
| 10240 | + refPtr = Jim_GetHashEntryVal(he); | |
| 10102 | 10241 | |
| 10103 | 10242 | Jim_FreeIntRep(interp, objPtr); |
| 10104 | 10243 | objPtr->typePtr = &referenceObjType; |
| 10105 | 10244 | objPtr->internalRep.refValue.id = value; |
| 10106 | 10245 | objPtr->internalRep.refValue.refPtr = refPtr; |
| @@ -10279,13 +10418,20 @@ | ||
| 10279 | 10418 | return i; |
| 10280 | 10419 | } |
| 10281 | 10420 | |
| 10282 | 10421 | void Jim_FreeInterp(Jim_Interp *i) |
| 10283 | 10422 | { |
| 10284 | - Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf; | |
| 10423 | + Jim_CallFrame *cf, *cfx; | |
| 10424 | + | |
| 10285 | 10425 | Jim_Obj *objPtr, *nextObjPtr; |
| 10286 | 10426 | |
| 10427 | + | |
| 10428 | + for (cf = i->framePtr; cf; cf = cfx) { | |
| 10429 | + cfx = cf->parent; | |
| 10430 | + JimFreeCallFrame(i, cf, JIM_FCF_FULL); | |
| 10431 | + } | |
| 10432 | + | |
| 10287 | 10433 | Jim_DecrRefCount(i, i->emptyObj); |
| 10288 | 10434 | Jim_DecrRefCount(i, i->trueObj); |
| 10289 | 10435 | Jim_DecrRefCount(i, i->falseObj); |
| 10290 | 10436 | Jim_DecrRefCount(i, i->result); |
| 10291 | 10437 | Jim_DecrRefCount(i, i->stackTrace); |
| @@ -10300,61 +10446,54 @@ | ||
| 10300 | 10446 | #endif |
| 10301 | 10447 | Jim_FreeHashTable(&i->packages); |
| 10302 | 10448 | Jim_Free(i->prngState); |
| 10303 | 10449 | Jim_FreeHashTable(&i->assocData); |
| 10304 | 10450 | |
| 10305 | - | |
| 10306 | - while (cf) { | |
| 10307 | - prevcf = cf->parent; | |
| 10308 | - JimFreeCallFrame(i, cf, JIM_FCF_NONE); | |
| 10309 | - cf = prevcf; | |
| 10310 | - } | |
| 10451 | +#ifdef JIM_MAINTAINER | |
| 10311 | 10452 | if (i->liveList != NULL) { |
| 10312 | 10453 | objPtr = i->liveList; |
| 10313 | 10454 | |
| 10314 | - printf(JIM_NL "-------------------------------------" JIM_NL); | |
| 10315 | - printf("Objects still in the free list:" JIM_NL); | |
| 10455 | + printf("\n-------------------------------------\n"); | |
| 10456 | + printf("Objects still in the free list:\n"); | |
| 10316 | 10457 | while (objPtr) { |
| 10317 | 10458 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10318 | 10459 | |
| 10319 | 10460 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10320 | - printf("%p (%d) %-10s: '%.20s...'" JIM_NL, | |
| 10461 | + printf("%p (%d) %-10s: '%.20s...'\n", | |
| 10321 | 10462 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10322 | 10463 | } |
| 10323 | 10464 | else { |
| 10324 | - printf("%p (%d) %-10s: '%s'" JIM_NL, | |
| 10465 | + printf("%p (%d) %-10s: '%s'\n", | |
| 10325 | 10466 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); |
| 10326 | 10467 | } |
| 10327 | 10468 | if (objPtr->typePtr == &sourceObjType) { |
| 10328 | - printf("FILE %s LINE %d" JIM_NL, | |
| 10469 | + printf("FILE %s LINE %d\n", | |
| 10329 | 10470 | Jim_String(objPtr->internalRep.sourceValue.fileNameObj), |
| 10330 | 10471 | objPtr->internalRep.sourceValue.lineNumber); |
| 10331 | 10472 | } |
| 10332 | 10473 | objPtr = objPtr->nextObjPtr; |
| 10333 | 10474 | } |
| 10334 | - printf("-------------------------------------" JIM_NL JIM_NL); | |
| 10475 | + printf("-------------------------------------\n\n"); | |
| 10335 | 10476 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10336 | 10477 | } |
| 10478 | +#endif | |
| 10479 | + | |
| 10337 | 10480 | |
| 10338 | 10481 | objPtr = i->freeList; |
| 10339 | 10482 | while (objPtr) { |
| 10340 | 10483 | nextObjPtr = objPtr->nextObjPtr; |
| 10341 | 10484 | Jim_Free(objPtr); |
| 10342 | 10485 | objPtr = nextObjPtr; |
| 10343 | 10486 | } |
| 10487 | + | |
| 10344 | 10488 | |
| 10345 | - cf = i->freeFramesList; | |
| 10346 | - while (cf) { | |
| 10347 | - nextcf = cf->next; | |
| 10348 | - if (cf->vars.table != NULL) | |
| 10349 | - Jim_Free(cf->vars.table); | |
| 10489 | + for (cf = i->freeFramesList; cf; cf = cfx) { | |
| 10490 | + cfx = cf->next; | |
| 10491 | + if (cf->vars.table) | |
| 10492 | + Jim_FreeHashTable(&cf->vars); | |
| 10350 | 10493 | Jim_Free(cf); |
| 10351 | - cf = nextcf; | |
| 10352 | 10494 | } |
| 10353 | -#ifdef jim_ext_load | |
| 10354 | - Jim_FreeLoadHandles(i); | |
| 10355 | -#endif | |
| 10356 | 10495 | |
| 10357 | 10496 | |
| 10358 | 10497 | Jim_Free(i); |
| 10359 | 10498 | } |
| 10360 | 10499 | |
| @@ -10455,11 +10594,10 @@ | ||
| 10455 | 10594 | interp->addStackTrace = 1; |
| 10456 | 10595 | } |
| 10457 | 10596 | } |
| 10458 | 10597 | } |
| 10459 | 10598 | |
| 10460 | - | |
| 10461 | 10599 | static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, |
| 10462 | 10600 | Jim_Obj *fileNameObj, int linenr) |
| 10463 | 10601 | { |
| 10464 | 10602 | if (strcmp(procname, "unknown") == 0) { |
| 10465 | 10603 | procname = ""; |
| @@ -10513,12 +10651,11 @@ | ||
| 10513 | 10651 | void *Jim_GetAssocData(Jim_Interp *interp, const char *key) |
| 10514 | 10652 | { |
| 10515 | 10653 | Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); |
| 10516 | 10654 | |
| 10517 | 10655 | if (entryPtr != NULL) { |
| 10518 | - AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val; | |
| 10519 | - | |
| 10656 | + AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr); | |
| 10520 | 10657 | return assocEntryPtr->data; |
| 10521 | 10658 | } |
| 10522 | 10659 | return NULL; |
| 10523 | 10660 | } |
| 10524 | 10661 | |
| @@ -10552,20 +10689,44 @@ | ||
| 10552 | 10689 | }; |
| 10553 | 10690 | |
| 10554 | 10691 | |
| 10555 | 10692 | static void UpdateStringOfInt(struct Jim_Obj *objPtr) |
| 10556 | 10693 | { |
| 10557 | - int len; | |
| 10558 | 10694 | char buf[JIM_INTEGER_SPACE + 1]; |
| 10695 | + jim_wide wideValue = JimWideValue(objPtr); | |
| 10696 | + int pos = 0; | |
| 10559 | 10697 | |
| 10560 | - len = JimWideToString(buf, JimWideValue(objPtr)); | |
| 10561 | - objPtr->bytes = Jim_Alloc(len + 1); | |
| 10562 | - memcpy(objPtr->bytes, buf, len + 1); | |
| 10563 | - objPtr->length = len; | |
| 10698 | + if (wideValue == 0) { | |
| 10699 | + buf[pos++] = '0'; | |
| 10700 | + } | |
| 10701 | + else { | |
| 10702 | + char tmp[JIM_INTEGER_SPACE]; | |
| 10703 | + int num = 0; | |
| 10704 | + int i; | |
| 10705 | + | |
| 10706 | + if (wideValue < 0) { | |
| 10707 | + buf[pos++] = '-'; | |
| 10708 | + i = wideValue % 10; | |
| 10709 | + tmp[num++] = (i > 0) ? (10 - i) : -i; | |
| 10710 | + wideValue /= -10; | |
| 10711 | + } | |
| 10712 | + | |
| 10713 | + while (wideValue) { | |
| 10714 | + tmp[num++] = wideValue % 10; | |
| 10715 | + wideValue /= 10; | |
| 10716 | + } | |
| 10717 | + | |
| 10718 | + for (i = 0; i < num; i++) { | |
| 10719 | + buf[pos++] = '0' + tmp[num - i - 1]; | |
| 10720 | + } | |
| 10721 | + } | |
| 10722 | + buf[pos] = 0; | |
| 10723 | + | |
| 10724 | + JimSetStringBytes(objPtr, buf); | |
| 10564 | 10725 | } |
| 10565 | 10726 | |
| 10566 | -int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) | |
| 10727 | +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) | |
| 10567 | 10728 | { |
| 10568 | 10729 | jim_wide wideValue; |
| 10569 | 10730 | const char *str; |
| 10570 | 10731 | |
| 10571 | 10732 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| @@ -10653,22 +10814,65 @@ | ||
| 10653 | 10814 | NULL, |
| 10654 | 10815 | UpdateStringOfDouble, |
| 10655 | 10816 | JIM_TYPE_NONE, |
| 10656 | 10817 | }; |
| 10657 | 10818 | |
| 10658 | -void UpdateStringOfDouble(struct Jim_Obj *objPtr) | |
| 10659 | -{ | |
| 10660 | - int len; | |
| 10661 | - char buf[JIM_DOUBLE_SPACE + 1]; | |
| 10662 | - | |
| 10663 | - len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); | |
| 10664 | - objPtr->bytes = Jim_Alloc(len + 1); | |
| 10665 | - memcpy(objPtr->bytes, buf, len + 1); | |
| 10666 | - objPtr->length = len; | |
| 10819 | +#ifndef HAVE_ISNAN | |
| 10820 | +#undef isnan | |
| 10821 | +#define isnan(X) ((X) != (X)) | |
| 10822 | +#endif | |
| 10823 | +#ifndef HAVE_ISINF | |
| 10824 | +#undef isinf | |
| 10825 | +#define isinf(X) (1.0 / (X) == 0.0) | |
| 10826 | +#endif | |
| 10827 | + | |
| 10828 | +static void UpdateStringOfDouble(struct Jim_Obj *objPtr) | |
| 10829 | +{ | |
| 10830 | + double value = objPtr->internalRep.doubleValue; | |
| 10831 | + | |
| 10832 | + if (isnan(value)) { | |
| 10833 | + JimSetStringBytes(objPtr, "NaN"); | |
| 10834 | + return; | |
| 10835 | + } | |
| 10836 | + if (isinf(value)) { | |
| 10837 | + if (value < 0) { | |
| 10838 | + JimSetStringBytes(objPtr, "-Inf"); | |
| 10839 | + } | |
| 10840 | + else { | |
| 10841 | + JimSetStringBytes(objPtr, "Inf"); | |
| 10842 | + } | |
| 10843 | + return; | |
| 10844 | + } | |
| 10845 | + { | |
| 10846 | + char buf[JIM_DOUBLE_SPACE + 1]; | |
| 10847 | + int i; | |
| 10848 | + int len = sprintf(buf, "%.12g", value); | |
| 10849 | + | |
| 10850 | + | |
| 10851 | + for (i = 0; i < len; i++) { | |
| 10852 | + if (buf[i] == '.' || buf[i] == 'e') { | |
| 10853 | +#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) | |
| 10854 | + char *e = strchr(buf, 'e'); | |
| 10855 | + if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { | |
| 10856 | + | |
| 10857 | + e += 2; | |
| 10858 | + memmove(e, e + 1, len - (e - buf)); | |
| 10859 | + } | |
| 10860 | +#endif | |
| 10861 | + break; | |
| 10862 | + } | |
| 10863 | + } | |
| 10864 | + if (buf[i] == '\0') { | |
| 10865 | + buf[i++] = '.'; | |
| 10866 | + buf[i++] = '0'; | |
| 10867 | + buf[i] = '\0'; | |
| 10868 | + } | |
| 10869 | + JimSetStringBytes(objPtr, buf); | |
| 10870 | + } | |
| 10667 | 10871 | } |
| 10668 | 10872 | |
| 10669 | -int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 10873 | +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 10670 | 10874 | { |
| 10671 | 10875 | double doubleValue; |
| 10672 | 10876 | jim_wide wideValue; |
| 10673 | 10877 | const char *str; |
| 10674 | 10878 | |
| @@ -10876,15 +11080,15 @@ | ||
| 10876 | 11080 | return JIM_ELESTR_SIMPLE; |
| 10877 | 11081 | } |
| 10878 | 11082 | return JIM_ELESTR_QUOTE; |
| 10879 | 11083 | } |
| 10880 | 11084 | |
| 10881 | -static int BackslashQuoteString(const char *s, char *q) | |
| 11085 | +static int BackslashQuoteString(const char *s, int len, char *q) | |
| 10882 | 11086 | { |
| 10883 | 11087 | char *p = q; |
| 10884 | 11088 | |
| 10885 | - while (*s) { | |
| 11089 | + while (len--) { | |
| 10886 | 11090 | switch (*s) { |
| 10887 | 11091 | case ' ': |
| 10888 | 11092 | case '$': |
| 10889 | 11093 | case '"': |
| 10890 | 11094 | case '[': |
| @@ -10996,11 +11200,11 @@ | ||
| 10996 | 11200 | case JIM_ELESTR_QUOTE: |
| 10997 | 11201 | if (i == 0 && strRep[0] == '#') { |
| 10998 | 11202 | *p++ = '\\'; |
| 10999 | 11203 | realLength++; |
| 11000 | 11204 | } |
| 11001 | - qlen = BackslashQuoteString(strRep, p); | |
| 11205 | + qlen = BackslashQuoteString(strRep, len, p); | |
| 11002 | 11206 | p += qlen; |
| 11003 | 11207 | realLength += qlen; |
| 11004 | 11208 | break; |
| 11005 | 11209 | } |
| 11006 | 11210 | |
| @@ -11032,11 +11236,11 @@ | ||
| 11032 | 11236 | |
| 11033 | 11237 | if (objPtr->typePtr == &listObjType) { |
| 11034 | 11238 | return JIM_OK; |
| 11035 | 11239 | } |
| 11036 | 11240 | |
| 11037 | - if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) { | |
| 11241 | + if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { | |
| 11038 | 11242 | Jim_Obj **listObjPtrPtr; |
| 11039 | 11243 | int len; |
| 11040 | 11244 | int i; |
| 11041 | 11245 | |
| 11042 | 11246 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| @@ -11136,15 +11340,17 @@ | ||
| 11136 | 11340 | Jim_Interp *interp; |
| 11137 | 11341 | enum { |
| 11138 | 11342 | JIM_LSORT_ASCII, |
| 11139 | 11343 | JIM_LSORT_NOCASE, |
| 11140 | 11344 | JIM_LSORT_INTEGER, |
| 11345 | + JIM_LSORT_REAL, | |
| 11141 | 11346 | JIM_LSORT_COMMAND |
| 11142 | 11347 | } type; |
| 11143 | 11348 | int order; |
| 11144 | 11349 | int index; |
| 11145 | 11350 | int indexed; |
| 11351 | + int unique; | |
| 11146 | 11352 | int (*subfn)(Jim_Obj **, Jim_Obj **); |
| 11147 | 11353 | }; |
| 11148 | 11354 | |
| 11149 | 11355 | static struct lsort_info *sort_info; |
| 11150 | 11356 | |
| @@ -11179,10 +11385,27 @@ | ||
| 11179 | 11385 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11180 | 11386 | } |
| 11181 | 11387 | |
| 11182 | 11388 | return JimSign(lhs - rhs) * sort_info->order; |
| 11183 | 11389 | } |
| 11390 | + | |
| 11391 | +static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj) | |
| 11392 | +{ | |
| 11393 | + double lhs = 0, rhs = 0; | |
| 11394 | + | |
| 11395 | + if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK || | |
| 11396 | + Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { | |
| 11397 | + longjmp(sort_info->jmpbuf, JIM_ERR); | |
| 11398 | + } | |
| 11399 | + if (lhs == rhs) { | |
| 11400 | + return 0; | |
| 11401 | + } | |
| 11402 | + if (lhs > rhs) { | |
| 11403 | + return sort_info->order; | |
| 11404 | + } | |
| 11405 | + return -sort_info->order; | |
| 11406 | +} | |
| 11184 | 11407 | |
| 11185 | 11408 | static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11186 | 11409 | { |
| 11187 | 11410 | Jim_Obj *compare_script; |
| 11188 | 11411 | int rc; |
| @@ -11201,10 +11424,34 @@ | ||
| 11201 | 11424 | } |
| 11202 | 11425 | |
| 11203 | 11426 | return JimSign(ret) * sort_info->order; |
| 11204 | 11427 | } |
| 11205 | 11428 | |
| 11429 | +static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs)) | |
| 11430 | +{ | |
| 11431 | + int src; | |
| 11432 | + int dst = 0; | |
| 11433 | + Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; | |
| 11434 | + | |
| 11435 | + for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { | |
| 11436 | + if (comp(&ele[dst], &ele[src]) == 0) { | |
| 11437 | + | |
| 11438 | + Jim_DecrRefCount(sort_info->interp, ele[dst]); | |
| 11439 | + } | |
| 11440 | + else { | |
| 11441 | + | |
| 11442 | + dst++; | |
| 11443 | + } | |
| 11444 | + ele[dst] = ele[src]; | |
| 11445 | + } | |
| 11446 | + | |
| 11447 | + ele[++dst] = ele[src]; | |
| 11448 | + | |
| 11449 | + | |
| 11450 | + listObjPtr->internalRep.listValue.len = dst; | |
| 11451 | +} | |
| 11452 | + | |
| 11206 | 11453 | |
| 11207 | 11454 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| 11208 | 11455 | { |
| 11209 | 11456 | struct lsort_info *prev_info; |
| 11210 | 11457 | |
| @@ -11212,11 +11459,11 @@ | ||
| 11212 | 11459 | int (*fn) (Jim_Obj **, Jim_Obj **); |
| 11213 | 11460 | Jim_Obj **vector; |
| 11214 | 11461 | int len; |
| 11215 | 11462 | int rc; |
| 11216 | 11463 | |
| 11217 | - JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object")); | |
| 11464 | + JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); | |
| 11218 | 11465 | SetListFromAny(interp, listObjPtr); |
| 11219 | 11466 | |
| 11220 | 11467 | |
| 11221 | 11468 | prev_info = sort_info; |
| 11222 | 11469 | sort_info = info; |
| @@ -11231,10 +11478,13 @@ | ||
| 11231 | 11478 | fn = ListSortStringNoCase; |
| 11232 | 11479 | break; |
| 11233 | 11480 | case JIM_LSORT_INTEGER: |
| 11234 | 11481 | fn = ListSortInteger; |
| 11235 | 11482 | break; |
| 11483 | + case JIM_LSORT_REAL: | |
| 11484 | + fn = ListSortReal; | |
| 11485 | + break; | |
| 11236 | 11486 | case JIM_LSORT_COMMAND: |
| 11237 | 11487 | fn = ListSortCommand; |
| 11238 | 11488 | break; |
| 11239 | 11489 | default: |
| 11240 | 11490 | fn = NULL; |
| @@ -11247,12 +11497,17 @@ | ||
| 11247 | 11497 | fn = ListSortIndexHelper; |
| 11248 | 11498 | } |
| 11249 | 11499 | |
| 11250 | 11500 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| 11251 | 11501 | qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); |
| 11502 | + | |
| 11503 | + if (info->unique && len > 1) { | |
| 11504 | + ListRemoveDuplicates(listObjPtr, fn); | |
| 11505 | + } | |
| 11506 | + | |
| 11507 | + Jim_InvalidateStringRep(listObjPtr); | |
| 11252 | 11508 | } |
| 11253 | - Jim_InvalidateStringRep(listObjPtr); | |
| 11254 | 11509 | sort_info = prev_info; |
| 11255 | 11510 | |
| 11256 | 11511 | return rc; |
| 11257 | 11512 | } |
| 11258 | 11513 | |
| @@ -11377,11 +11632,11 @@ | ||
| 11377 | 11632 | listPtr->internalRep.listValue.ele[idx] = newObjPtr; |
| 11378 | 11633 | Jim_IncrRefCount(newObjPtr); |
| 11379 | 11634 | return JIM_OK; |
| 11380 | 11635 | } |
| 11381 | 11636 | |
| 11382 | -int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, | |
| 11637 | +int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, | |
| 11383 | 11638 | Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) |
| 11384 | 11639 | { |
| 11385 | 11640 | Jim_Obj *varObjPtr, *objPtr, *listObjPtr; |
| 11386 | 11641 | int shared, i, idx; |
| 11387 | 11642 | |
| @@ -11425,14 +11680,11 @@ | ||
| 11425 | 11680 | int i; |
| 11426 | 11681 | int listLen = Jim_ListLength(interp, listObjPtr); |
| 11427 | 11682 | Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); |
| 11428 | 11683 | |
| 11429 | 11684 | for (i = 0; i < listLen; ) { |
| 11430 | - Jim_Obj *objPtr; | |
| 11431 | - | |
| 11432 | - Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); | |
| 11433 | - Jim_AppendObj(interp, resObjPtr, objPtr); | |
| 11685 | + Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i)); | |
| 11434 | 11686 | if (++i != listLen) { |
| 11435 | 11687 | Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); |
| 11436 | 11688 | } |
| 11437 | 11689 | } |
| 11438 | 11690 | return resObjPtr; |
| @@ -11458,43 +11710,42 @@ | ||
| 11458 | 11710 | int len = 0, objLen; |
| 11459 | 11711 | char *bytes, *p; |
| 11460 | 11712 | |
| 11461 | 11713 | |
| 11462 | 11714 | for (i = 0; i < objc; i++) { |
| 11463 | - Jim_GetString(objv[i], &objLen); | |
| 11464 | - len += objLen; | |
| 11715 | + len += Jim_Length(objv[i]); | |
| 11465 | 11716 | } |
| 11466 | 11717 | if (objc) |
| 11467 | 11718 | len += objc - 1; |
| 11468 | 11719 | |
| 11469 | 11720 | p = bytes = Jim_Alloc(len + 1); |
| 11470 | 11721 | for (i = 0; i < objc; i++) { |
| 11471 | 11722 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11472 | 11723 | |
| 11473 | 11724 | |
| 11474 | - while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) { | |
| 11725 | + while (objLen && isspace(UCHAR(*s))) { | |
| 11475 | 11726 | s++; |
| 11476 | 11727 | objLen--; |
| 11477 | 11728 | len--; |
| 11478 | 11729 | } |
| 11479 | 11730 | |
| 11480 | - while (objLen && (s[objLen - 1] == ' ' || | |
| 11481 | - s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) { | |
| 11731 | + while (objLen && isspace(UCHAR(s[objLen - 1]))) { | |
| 11482 | 11732 | |
| 11483 | 11733 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11484 | 11734 | break; |
| 11485 | 11735 | } |
| 11486 | 11736 | objLen--; |
| 11487 | 11737 | len--; |
| 11488 | 11738 | } |
| 11489 | 11739 | memcpy(p, s, objLen); |
| 11490 | 11740 | p += objLen; |
| 11491 | - if (objLen && i + 1 != objc) { | |
| 11492 | - *p++ = ' '; | |
| 11493 | - } | |
| 11494 | - else if (i + 1 != objc) { | |
| 11495 | - len--; | |
| 11741 | + if (i + 1 != objc) { | |
| 11742 | + if (objLen) | |
| 11743 | + *p++ = ' '; | |
| 11744 | + else { | |
| 11745 | + len--; | |
| 11746 | + } | |
| 11496 | 11747 | } |
| 11497 | 11748 | } |
| 11498 | 11749 | *p = '\0'; |
| 11499 | 11750 | return Jim_NewStringObjNoAlloc(interp, bytes, len); |
| 11500 | 11751 | } |
| @@ -11534,20 +11785,26 @@ | ||
| 11534 | 11785 | |
| 11535 | 11786 | static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 11536 | 11787 | { |
| 11537 | 11788 | return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 11538 | 11789 | } |
| 11790 | + | |
| 11791 | +static void *JimObjectHTKeyValDup(void *privdata, const void *val) | |
| 11792 | +{ | |
| 11793 | + Jim_IncrRefCount((Jim_Obj *)val); | |
| 11794 | + return (void *)val; | |
| 11795 | +} | |
| 11539 | 11796 | |
| 11540 | 11797 | static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 11541 | 11798 | { |
| 11542 | 11799 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11543 | 11800 | } |
| 11544 | 11801 | |
| 11545 | 11802 | static const Jim_HashTableType JimDictHashTableType = { |
| 11546 | 11803 | JimObjectHTHashFunction, |
| 11547 | - NULL, | |
| 11548 | - NULL, | |
| 11804 | + JimObjectHTKeyValDup, | |
| 11805 | + JimObjectHTKeyValDup, | |
| 11549 | 11806 | JimObjectHTKeyCompare, |
| 11550 | 11807 | JimObjectHTKeyValDestructor, |
| 11551 | 11808 | JimObjectHTKeyValDestructor |
| 11552 | 11809 | }; |
| 11553 | 11810 | |
| @@ -11580,16 +11837,11 @@ | ||
| 11580 | 11837 | if (ht->size != 0) |
| 11581 | 11838 | Jim_ExpandHashTable(dupHt, ht->size); |
| 11582 | 11839 | |
| 11583 | 11840 | JimInitHashTableIterator(ht, &htiter); |
| 11584 | 11841 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11585 | - const Jim_Obj *keyObjPtr = he->key; | |
| 11586 | - Jim_Obj *valObjPtr = he->u.val; | |
| 11587 | - | |
| 11588 | - Jim_IncrRefCount((Jim_Obj *)keyObjPtr); | |
| 11589 | - Jim_IncrRefCount(valObjPtr); | |
| 11590 | - Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); | |
| 11842 | + Jim_AddHashEntry(dupHt, he->key, he->u.val); | |
| 11591 | 11843 | } |
| 11592 | 11844 | |
| 11593 | 11845 | dupPtr->internalRep.ptr = dupHt; |
| 11594 | 11846 | dupPtr->typePtr = &dictObjType; |
| 11595 | 11847 | } |
| @@ -11607,12 +11859,12 @@ | ||
| 11607 | 11859 | |
| 11608 | 11860 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 11609 | 11861 | JimInitHashTableIterator(ht, &htiter); |
| 11610 | 11862 | i = 0; |
| 11611 | 11863 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11612 | - objv[i++] = (Jim_Obj *)he->key; | |
| 11613 | - objv[i++] = he->u.val; | |
| 11864 | + objv[i++] = Jim_GetHashEntryKey(he); | |
| 11865 | + objv[i++] = Jim_GetHashEntryVal(he); | |
| 11614 | 11866 | } |
| 11615 | 11867 | *len = i; |
| 11616 | 11868 | return objv; |
| 11617 | 11869 | } |
| 11618 | 11870 | |
| @@ -11620,10 +11872,11 @@ | ||
| 11620 | 11872 | { |
| 11621 | 11873 | |
| 11622 | 11874 | int len; |
| 11623 | 11875 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 11624 | 11876 | |
| 11877 | + | |
| 11625 | 11878 | JimMakeListStringRep(objPtr, objv, len); |
| 11626 | 11879 | |
| 11627 | 11880 | Jim_Free(objv); |
| 11628 | 11881 | } |
| 11629 | 11882 | |
| @@ -11633,11 +11886,13 @@ | ||
| 11633 | 11886 | |
| 11634 | 11887 | if (objPtr->typePtr == &dictObjType) { |
| 11635 | 11888 | return JIM_OK; |
| 11636 | 11889 | } |
| 11637 | 11890 | |
| 11638 | - Jim_String(objPtr); | |
| 11891 | + if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { | |
| 11892 | + Jim_String(objPtr); | |
| 11893 | + } | |
| 11639 | 11894 | |
| 11640 | 11895 | |
| 11641 | 11896 | listlen = Jim_ListLength(interp, objPtr); |
| 11642 | 11897 | if (listlen % 2) { |
| 11643 | 11898 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| @@ -11650,28 +11905,14 @@ | ||
| 11650 | 11905 | |
| 11651 | 11906 | ht = Jim_Alloc(sizeof(*ht)); |
| 11652 | 11907 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| 11653 | 11908 | |
| 11654 | 11909 | for (i = 0; i < listlen; i += 2) { |
| 11655 | - Jim_Obj *keyObjPtr; | |
| 11656 | - Jim_Obj *valObjPtr; | |
| 11657 | - | |
| 11658 | - Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE); | |
| 11659 | - Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE); | |
| 11660 | - | |
| 11661 | - Jim_IncrRefCount(keyObjPtr); | |
| 11662 | - Jim_IncrRefCount(valObjPtr); | |
| 11663 | - | |
| 11664 | - if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) { | |
| 11665 | - Jim_HashEntry *he; | |
| 11666 | - | |
| 11667 | - he = Jim_FindHashEntry(ht, keyObjPtr); | |
| 11668 | - Jim_DecrRefCount(interp, keyObjPtr); | |
| 11669 | - | |
| 11670 | - Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); | |
| 11671 | - he->u.val = valObjPtr; | |
| 11672 | - } | |
| 11910 | + Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); | |
| 11911 | + Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); | |
| 11912 | + | |
| 11913 | + Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); | |
| 11673 | 11914 | } |
| 11674 | 11915 | |
| 11675 | 11916 | Jim_FreeIntRep(interp, objPtr); |
| 11676 | 11917 | objPtr->typePtr = &dictObjType; |
| 11677 | 11918 | objPtr->internalRep.ptr = ht; |
| @@ -11688,31 +11929,23 @@ | ||
| 11688 | 11929 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 11689 | 11930 | |
| 11690 | 11931 | if (valueObjPtr == NULL) { |
| 11691 | 11932 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 11692 | 11933 | } |
| 11693 | - Jim_IncrRefCount(keyObjPtr); | |
| 11694 | - Jim_IncrRefCount(valueObjPtr); | |
| 11695 | - if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) { | |
| 11696 | - | |
| 11697 | - Jim_DecrRefCount(interp, keyObjPtr); | |
| 11698 | - } | |
| 11934 | + Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); | |
| 11699 | 11935 | return JIM_OK; |
| 11700 | 11936 | } |
| 11701 | 11937 | |
| 11702 | 11938 | int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 11703 | 11939 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 11704 | 11940 | { |
| 11705 | - int retcode; | |
| 11706 | - | |
| 11707 | 11941 | JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); |
| 11708 | 11942 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 11709 | 11943 | return JIM_ERR; |
| 11710 | 11944 | } |
| 11711 | - retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); | |
| 11712 | 11945 | Jim_InvalidateStringRep(objPtr); |
| 11713 | - return retcode; | |
| 11946 | + return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); | |
| 11714 | 11947 | } |
| 11715 | 11948 | |
| 11716 | 11949 | Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) |
| 11717 | 11950 | { |
| 11718 | 11951 | Jim_Obj *objPtr; |
| @@ -11839,10 +12072,11 @@ | ||
| 11839 | 12072 | } |
| 11840 | 12073 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 11841 | 12074 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 11842 | 12075 | } |
| 11843 | 12076 | } |
| 12077 | + | |
| 11844 | 12078 | Jim_InvalidateStringRep(objPtr); |
| 11845 | 12079 | Jim_InvalidateStringRep(varObjPtr); |
| 11846 | 12080 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 11847 | 12081 | goto err; |
| 11848 | 12082 | } |
| @@ -11864,28 +12098,29 @@ | ||
| 11864 | 12098 | NULL, |
| 11865 | 12099 | UpdateStringOfIndex, |
| 11866 | 12100 | JIM_TYPE_NONE, |
| 11867 | 12101 | }; |
| 11868 | 12102 | |
| 11869 | -void UpdateStringOfIndex(struct Jim_Obj *objPtr) | |
| 11870 | -{ | |
| 11871 | - int len; | |
| 11872 | - char buf[JIM_INTEGER_SPACE + 1]; | |
| 11873 | - | |
| 11874 | - if (objPtr->internalRep.intValue >= 0) | |
| 11875 | - len = sprintf(buf, "%d", objPtr->internalRep.intValue); | |
| 11876 | - else if (objPtr->internalRep.intValue == -1) | |
| 11877 | - len = sprintf(buf, "end"); | |
| 12103 | +static void UpdateStringOfIndex(struct Jim_Obj *objPtr) | |
| 12104 | +{ | |
| 12105 | + if (objPtr->internalRep.intValue == -1) { | |
| 12106 | + JimSetStringBytes(objPtr, "end"); | |
| 12107 | + } | |
| 11878 | 12108 | else { |
| 11879 | - len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); | |
| 12109 | + char buf[JIM_INTEGER_SPACE + 1]; | |
| 12110 | + if (objPtr->internalRep.intValue >= 0) { | |
| 12111 | + sprintf(buf, "%d", objPtr->internalRep.intValue); | |
| 12112 | + } | |
| 12113 | + else { | |
| 12114 | + | |
| 12115 | + sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); | |
| 12116 | + } | |
| 12117 | + JimSetStringBytes(objPtr, buf); | |
| 11880 | 12118 | } |
| 11881 | - objPtr->bytes = Jim_Alloc(len + 1); | |
| 11882 | - memcpy(objPtr->bytes, buf, len + 1); | |
| 11883 | - objPtr->length = len; | |
| 11884 | 12119 | } |
| 11885 | 12120 | |
| 11886 | -int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 12121 | +static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 11887 | 12122 | { |
| 11888 | 12123 | int idx, end = 0; |
| 11889 | 12124 | const char *str; |
| 11890 | 12125 | char *endptr; |
| 11891 | 12126 | |
| @@ -11953,14 +12188,17 @@ | ||
| 11953 | 12188 | { |
| 11954 | 12189 | |
| 11955 | 12190 | if (objPtr->typePtr == &intObjType) { |
| 11956 | 12191 | jim_wide val = JimWideValue(objPtr); |
| 11957 | 12192 | |
| 11958 | - if (!(val < LONG_MIN) && !(val > LONG_MAX)) { | |
| 11959 | - *indexPtr = (val < 0) ? -INT_MAX : (long)val;; | |
| 11960 | - return JIM_OK; | |
| 11961 | - } | |
| 12193 | + if (val < 0) | |
| 12194 | + *indexPtr = -INT_MAX; | |
| 12195 | + else if (val > INT_MAX) | |
| 12196 | + *indexPtr = INT_MAX; | |
| 12197 | + else | |
| 12198 | + *indexPtr = (int)val; | |
| 12199 | + return JIM_OK; | |
| 11962 | 12200 | } |
| 11963 | 12201 | if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) |
| 11964 | 12202 | return JIM_ERR; |
| 11965 | 12203 | *indexPtr = objPtr->internalRep.intValue; |
| 11966 | 12204 | return JIM_OK; |
| @@ -11980,12 +12218,10 @@ | ||
| 11980 | 12218 | NULL |
| 11981 | 12219 | }; |
| 11982 | 12220 | |
| 11983 | 12221 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) |
| 11984 | 12222 | |
| 11985 | -static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr); | |
| 11986 | - | |
| 11987 | 12223 | static const Jim_ObjType returnCodeObjType = { |
| 11988 | 12224 | "return-code", |
| 11989 | 12225 | NULL, |
| 11990 | 12226 | NULL, |
| 11991 | 12227 | NULL, |
| @@ -12000,11 +12236,11 @@ | ||
| 12000 | 12236 | else { |
| 12001 | 12237 | return jimReturnCodes[code]; |
| 12002 | 12238 | } |
| 12003 | 12239 | } |
| 12004 | 12240 | |
| 12005 | -int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 12241 | +static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 12006 | 12242 | { |
| 12007 | 12243 | int returnCode; |
| 12008 | 12244 | jim_wide wideValue; |
| 12009 | 12245 | |
| 12010 | 12246 | |
| @@ -12152,24 +12388,21 @@ | ||
| 12152 | 12388 | return e->stack[--e->stacklen]; |
| 12153 | 12389 | } |
| 12154 | 12390 | |
| 12155 | 12391 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12156 | 12392 | { |
| 12157 | - int intresult = 0; | |
| 12393 | + int intresult = 1; | |
| 12158 | 12394 | int rc = JIM_OK; |
| 12159 | 12395 | Jim_Obj *A = ExprPop(e); |
| 12160 | 12396 | double dA, dC = 0; |
| 12161 | 12397 | jim_wide wA, wC = 0; |
| 12162 | 12398 | |
| 12163 | 12399 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12164 | - intresult = 1; | |
| 12165 | - | |
| 12166 | 12400 | switch (e->opcode) { |
| 12167 | 12401 | case JIM_EXPROP_FUNC_INT: |
| 12168 | - wC = wA; | |
| 12169 | - break; | |
| 12170 | 12402 | case JIM_EXPROP_FUNC_ROUND: |
| 12403 | + case JIM_EXPROP_UNARYPLUS: | |
| 12171 | 12404 | wC = wA; |
| 12172 | 12405 | break; |
| 12173 | 12406 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12174 | 12407 | dC = wA; |
| 12175 | 12408 | intresult = 0; |
| @@ -12178,13 +12411,10 @@ | ||
| 12178 | 12411 | wC = wA >= 0 ? wA : -wA; |
| 12179 | 12412 | break; |
| 12180 | 12413 | case JIM_EXPROP_UNARYMINUS: |
| 12181 | 12414 | wC = -wA; |
| 12182 | 12415 | break; |
| 12183 | - case JIM_EXPROP_UNARYPLUS: | |
| 12184 | - wC = wA; | |
| 12185 | - break; | |
| 12186 | 12416 | case JIM_EXPROP_NOT: |
| 12187 | 12417 | wC = !wA; |
| 12188 | 12418 | break; |
| 12189 | 12419 | default: |
| 12190 | 12420 | abort(); |
| @@ -12192,31 +12422,29 @@ | ||
| 12192 | 12422 | } |
| 12193 | 12423 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12194 | 12424 | switch (e->opcode) { |
| 12195 | 12425 | case JIM_EXPROP_FUNC_INT: |
| 12196 | 12426 | wC = dA; |
| 12197 | - intresult = 1; | |
| 12198 | 12427 | break; |
| 12199 | 12428 | case JIM_EXPROP_FUNC_ROUND: |
| 12200 | 12429 | wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); |
| 12201 | - intresult = 1; | |
| 12202 | 12430 | break; |
| 12203 | 12431 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12432 | + case JIM_EXPROP_UNARYPLUS: | |
| 12204 | 12433 | dC = dA; |
| 12434 | + intresult = 0; | |
| 12205 | 12435 | break; |
| 12206 | 12436 | case JIM_EXPROP_FUNC_ABS: |
| 12207 | 12437 | dC = dA >= 0 ? dA : -dA; |
| 12438 | + intresult = 0; | |
| 12208 | 12439 | break; |
| 12209 | 12440 | case JIM_EXPROP_UNARYMINUS: |
| 12210 | 12441 | dC = -dA; |
| 12211 | - break; | |
| 12212 | - case JIM_EXPROP_UNARYPLUS: | |
| 12213 | - dC = dA; | |
| 12442 | + intresult = 0; | |
| 12214 | 12443 | break; |
| 12215 | 12444 | case JIM_EXPROP_NOT: |
| 12216 | 12445 | wC = !dA; |
| 12217 | - intresult = 1; | |
| 12218 | 12446 | break; |
| 12219 | 12447 | default: |
| 12220 | 12448 | abort(); |
| 12221 | 12449 | } |
| 12222 | 12450 | } |
| @@ -12427,11 +12655,11 @@ | ||
| 12427 | 12655 | |
| 12428 | 12656 | |
| 12429 | 12657 | |
| 12430 | 12658 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) |
| 12431 | 12659 | { |
| 12432 | - int intresult = 0; | |
| 12660 | + int intresult = 1; | |
| 12433 | 12661 | int rc = JIM_OK; |
| 12434 | 12662 | double dA, dB, dC = 0; |
| 12435 | 12663 | jim_wide wA, wB, wC = 0; |
| 12436 | 12664 | |
| 12437 | 12665 | Jim_Obj *B = ExprPop(e); |
| @@ -12441,12 +12669,10 @@ | ||
| 12441 | 12669 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12442 | 12670 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12443 | 12671 | |
| 12444 | 12672 | |
| 12445 | 12673 | |
| 12446 | - intresult = 1; | |
| 12447 | - | |
| 12448 | 12674 | switch (e->opcode) { |
| 12449 | 12675 | case JIM_EXPROP_POW: |
| 12450 | 12676 | case JIM_EXPROP_FUNC_POW: |
| 12451 | 12677 | wC = JimPowWide(wA, wB); |
| 12452 | 12678 | break; |
| @@ -12496,10 +12722,11 @@ | ||
| 12496 | 12722 | default: |
| 12497 | 12723 | abort(); |
| 12498 | 12724 | } |
| 12499 | 12725 | } |
| 12500 | 12726 | else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12727 | + intresult = 0; | |
| 12501 | 12728 | switch (e->opcode) { |
| 12502 | 12729 | case JIM_EXPROP_POW: |
| 12503 | 12730 | case JIM_EXPROP_FUNC_POW: |
| 12504 | 12731 | #ifdef JIM_MATH_FUNCTIONS |
| 12505 | 12732 | dC = pow(dA, dB); |
| @@ -12561,12 +12788,10 @@ | ||
| 12561 | 12788 | |
| 12562 | 12789 | |
| 12563 | 12790 | |
| 12564 | 12791 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 12565 | 12792 | |
| 12566 | - intresult = 1; | |
| 12567 | - | |
| 12568 | 12793 | switch (e->opcode) { |
| 12569 | 12794 | case JIM_EXPROP_LT: |
| 12570 | 12795 | wC = i < 0; |
| 12571 | 12796 | break; |
| 12572 | 12797 | case JIM_EXPROP_GT: |
| @@ -12610,15 +12835,11 @@ | ||
| 12610 | 12835 | int listlen; |
| 12611 | 12836 | int i; |
| 12612 | 12837 | |
| 12613 | 12838 | listlen = Jim_ListLength(interp, listObjPtr); |
| 12614 | 12839 | for (i = 0; i < listlen; i++) { |
| 12615 | - Jim_Obj *objPtr; | |
| 12616 | - | |
| 12617 | - Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); | |
| 12618 | - | |
| 12619 | - if (Jim_StringEqObj(objPtr, valObj)) { | |
| 12840 | + if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { | |
| 12620 | 12841 | return 1; |
| 12621 | 12842 | } |
| 12622 | 12843 | } |
| 12623 | 12844 | return 0; |
| 12624 | 12845 | } |
| @@ -12630,23 +12851,16 @@ | ||
| 12630 | 12851 | |
| 12631 | 12852 | jim_wide wC; |
| 12632 | 12853 | |
| 12633 | 12854 | switch (e->opcode) { |
| 12634 | 12855 | case JIM_EXPROP_STREQ: |
| 12635 | - case JIM_EXPROP_STRNE: { | |
| 12636 | - int Alen, Blen; | |
| 12637 | - const char *sA = Jim_GetString(A, &Alen); | |
| 12638 | - const char *sB = Jim_GetString(B, &Blen); | |
| 12639 | - | |
| 12640 | - if (e->opcode == JIM_EXPROP_STREQ) { | |
| 12641 | - wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0); | |
| 12642 | - } | |
| 12643 | - else { | |
| 12644 | - wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0); | |
| 12856 | + case JIM_EXPROP_STRNE: | |
| 12857 | + wC = Jim_StringEqObj(A, B); | |
| 12858 | + if (e->opcode == JIM_EXPROP_STRNE) { | |
| 12859 | + wC = !wC; | |
| 12645 | 12860 | } |
| 12646 | 12861 | break; |
| 12647 | - } | |
| 12648 | 12862 | case JIM_EXPROP_STRIN: |
| 12649 | 12863 | wC = JimSearchList(interp, B, A); |
| 12650 | 12864 | break; |
| 12651 | 12865 | case JIM_EXPROP_STRNI: |
| 12652 | 12866 | wC = !JimSearchList(interp, B, A); |
| @@ -12818,96 +13032,98 @@ | ||
| 12818 | 13032 | LAZY_OP, |
| 12819 | 13033 | LAZY_LEFT, |
| 12820 | 13034 | LAZY_RIGHT |
| 12821 | 13035 | }; |
| 12822 | 13036 | |
| 12823 | -#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} | |
| 13037 | +#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} | |
| 13038 | +#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} | |
| 12824 | 13039 | |
| 12825 | 13040 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 12826 | - OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE), | |
| 12827 | - OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE), | |
| 12828 | - OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12829 | - | |
| 12830 | - OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE), | |
| 12831 | - OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE), | |
| 12832 | - | |
| 12833 | - OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12834 | - OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12835 | - | |
| 12836 | - OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12837 | - OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12838 | - | |
| 12839 | - OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE), | |
| 12840 | - OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE), | |
| 12841 | - OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE), | |
| 12842 | - OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE), | |
| 12843 | - | |
| 12844 | - OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE), | |
| 12845 | - OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE), | |
| 12846 | - | |
| 12847 | - OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12848 | - OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12849 | - OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE), | |
| 12850 | - | |
| 12851 | - OPRINIT("&&", 10, 2, NULL, LAZY_OP), | |
| 12852 | - OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), | |
| 12853 | - OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 12854 | - | |
| 12855 | - OPRINIT("||", 9, 2, NULL, LAZY_OP), | |
| 12856 | - OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), | |
| 12857 | - OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 12858 | - | |
| 12859 | - OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP), | |
| 12860 | - OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), | |
| 12861 | - OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 12862 | - | |
| 12863 | - OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP), | |
| 12864 | - OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), | |
| 12865 | - OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 12866 | - | |
| 12867 | - OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE), | |
| 12868 | - | |
| 12869 | - OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE), | |
| 12870 | - OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE), | |
| 12871 | - | |
| 12872 | - OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE), | |
| 12873 | - OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE), | |
| 12874 | - | |
| 12875 | - OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12876 | - OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE), | |
| 12877 | - OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12878 | - OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12879 | - | |
| 12880 | - | |
| 12881 | - | |
| 12882 | - OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12883 | - OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12884 | - OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12885 | - OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE), | |
| 12886 | - OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE), | |
| 12887 | - OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE), | |
| 13041 | + OPRINIT("*", 110, 2, JimExprOpBin), | |
| 13042 | + OPRINIT("/", 110, 2, JimExprOpBin), | |
| 13043 | + OPRINIT("%", 110, 2, JimExprOpIntBin), | |
| 13044 | + | |
| 13045 | + OPRINIT("-", 100, 2, JimExprOpBin), | |
| 13046 | + OPRINIT("+", 100, 2, JimExprOpBin), | |
| 13047 | + | |
| 13048 | + OPRINIT("<<", 90, 2, JimExprOpIntBin), | |
| 13049 | + OPRINIT(">>", 90, 2, JimExprOpIntBin), | |
| 13050 | + | |
| 13051 | + OPRINIT("<<<", 90, 2, JimExprOpIntBin), | |
| 13052 | + OPRINIT(">>>", 90, 2, JimExprOpIntBin), | |
| 13053 | + | |
| 13054 | + OPRINIT("<", 80, 2, JimExprOpBin), | |
| 13055 | + OPRINIT(">", 80, 2, JimExprOpBin), | |
| 13056 | + OPRINIT("<=", 80, 2, JimExprOpBin), | |
| 13057 | + OPRINIT(">=", 80, 2, JimExprOpBin), | |
| 13058 | + | |
| 13059 | + OPRINIT("==", 70, 2, JimExprOpBin), | |
| 13060 | + OPRINIT("!=", 70, 2, JimExprOpBin), | |
| 13061 | + | |
| 13062 | + OPRINIT("&", 50, 2, JimExprOpIntBin), | |
| 13063 | + OPRINIT("^", 49, 2, JimExprOpIntBin), | |
| 13064 | + OPRINIT("|", 48, 2, JimExprOpIntBin), | |
| 13065 | + | |
| 13066 | + OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), | |
| 13067 | + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), | |
| 13068 | + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 13069 | + | |
| 13070 | + OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), | |
| 13071 | + OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), | |
| 13072 | + OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 13073 | + | |
| 13074 | + OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), | |
| 13075 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), | |
| 13076 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 13077 | + | |
| 13078 | + OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), | |
| 13079 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), | |
| 13080 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 13081 | + | |
| 13082 | + OPRINIT("**", 250, 2, JimExprOpBin), | |
| 13083 | + | |
| 13084 | + OPRINIT("eq", 60, 2, JimExprOpStrBin), | |
| 13085 | + OPRINIT("ne", 60, 2, JimExprOpStrBin), | |
| 13086 | + | |
| 13087 | + OPRINIT("in", 55, 2, JimExprOpStrBin), | |
| 13088 | + OPRINIT("ni", 55, 2, JimExprOpStrBin), | |
| 13089 | + | |
| 13090 | + OPRINIT("!", 150, 1, JimExprOpNumUnary), | |
| 13091 | + OPRINIT("~", 150, 1, JimExprOpIntUnary), | |
| 13092 | + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), | |
| 13093 | + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), | |
| 13094 | + | |
| 13095 | + | |
| 13096 | + | |
| 13097 | + OPRINIT("int", 200, 1, JimExprOpNumUnary), | |
| 13098 | + OPRINIT("abs", 200, 1, JimExprOpNumUnary), | |
| 13099 | + OPRINIT("double", 200, 1, JimExprOpNumUnary), | |
| 13100 | + OPRINIT("round", 200, 1, JimExprOpNumUnary), | |
| 13101 | + OPRINIT("rand", 200, 0, JimExprOpNone), | |
| 13102 | + OPRINIT("srand", 200, 1, JimExprOpIntUnary), | |
| 12888 | 13103 | |
| 12889 | 13104 | #ifdef JIM_MATH_FUNCTIONS |
| 12890 | - OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12891 | - OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12892 | - OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12893 | - OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12894 | - OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12895 | - OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12896 | - OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12897 | - OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12898 | - OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12899 | - OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12900 | - OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12901 | - OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12902 | - OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12903 | - OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12904 | - OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), | |
| 12905 | - OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE), | |
| 13105 | + OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), | |
| 13106 | + OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), | |
| 13107 | + OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), | |
| 13108 | + OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), | |
| 13109 | + OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), | |
| 13110 | + OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), | |
| 13111 | + OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), | |
| 13112 | + OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), | |
| 13113 | + OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), | |
| 13114 | + OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), | |
| 13115 | + OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), | |
| 13116 | + OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), | |
| 13117 | + OPRINIT("log", 200, 1, JimExprOpDoubleUnary), | |
| 13118 | + OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), | |
| 13119 | + OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), | |
| 13120 | + OPRINIT("pow", 200, 2, JimExprOpBin), | |
| 12906 | 13121 | #endif |
| 12907 | 13122 | }; |
| 12908 | 13123 | #undef OPRINIT |
| 13124 | +#undef OPRINIT_LAZY | |
| 12909 | 13125 | |
| 12910 | 13126 | #define JIM_EXPR_OPERATORS_NUM \ |
| 12911 | 13127 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 12912 | 13128 | |
| 12913 | 13129 | static int JimParseExpression(struct JimParserCtx *pc) |
| @@ -12919,13 +13135,16 @@ | ||
| 12919 | 13135 | } |
| 12920 | 13136 | pc->p++; |
| 12921 | 13137 | pc->len--; |
| 12922 | 13138 | } |
| 12923 | 13139 | |
| 13140 | + | |
| 13141 | + pc->tline = pc->linenr; | |
| 13142 | + pc->tstart = pc->p; | |
| 13143 | + | |
| 12924 | 13144 | if (pc->len == 0) { |
| 12925 | - pc->tstart = pc->tend = pc->p; | |
| 12926 | - pc->tline = pc->linenr; | |
| 13145 | + pc->tend = pc->p; | |
| 12927 | 13146 | pc->tt = JIM_TT_EOL; |
| 12928 | 13147 | pc->eof = 1; |
| 12929 | 13148 | return JIM_OK; |
| 12930 | 13149 | } |
| 12931 | 13150 | switch (*(pc->p)) { |
| @@ -12936,12 +13155,11 @@ | ||
| 12936 | 13155 | pc->tt = JIM_TT_SUBEXPR_END; |
| 12937 | 13156 | goto singlechar; |
| 12938 | 13157 | case ',': |
| 12939 | 13158 | pc->tt = JIM_TT_SUBEXPR_COMMA; |
| 12940 | 13159 | singlechar: |
| 12941 | - pc->tstart = pc->tend = pc->p; | |
| 12942 | - pc->tline = pc->linenr; | |
| 13160 | + pc->tend = pc->p; | |
| 12943 | 13161 | pc->p++; |
| 12944 | 13162 | pc->len--; |
| 12945 | 13163 | break; |
| 12946 | 13164 | case '[': |
| 12947 | 13165 | return JimParseCmd(pc); |
| @@ -12987,82 +13205,44 @@ | ||
| 12987 | 13205 | return JIM_OK; |
| 12988 | 13206 | } |
| 12989 | 13207 | |
| 12990 | 13208 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 12991 | 13209 | { |
| 12992 | - int allowdot = 1; | |
| 12993 | - int base = 10; | |
| 13210 | + char *end; | |
| 12994 | 13211 | |
| 12995 | 13212 | |
| 12996 | 13213 | pc->tt = JIM_TT_EXPR_INT; |
| 12997 | - pc->tstart = pc->p; | |
| 12998 | - pc->tline = pc->linenr; | |
| 12999 | - | |
| 13000 | - | |
| 13001 | - if (pc->p[0] == '0') { | |
| 13002 | - switch (pc->p[1]) { | |
| 13003 | - case 'x': | |
| 13004 | - case 'X': | |
| 13005 | - base = 16; | |
| 13006 | - allowdot = 0; | |
| 13007 | - pc->p += 2; | |
| 13008 | - pc->len -= 2; | |
| 13009 | - break; | |
| 13010 | - case 'o': | |
| 13011 | - case 'O': | |
| 13012 | - base = 8; | |
| 13013 | - allowdot = 0; | |
| 13014 | - pc->p += 2; | |
| 13015 | - pc->len -= 2; | |
| 13016 | - break; | |
| 13017 | - case 'b': | |
| 13018 | - case 'B': | |
| 13019 | - base = 2; | |
| 13020 | - allowdot = 0; | |
| 13021 | - pc->p += 2; | |
| 13022 | - pc->len -= 2; | |
| 13023 | - break; | |
| 13024 | - } | |
| 13025 | - } | |
| 13026 | - | |
| 13027 | - while (isdigit(UCHAR(*pc->p)) | |
| 13028 | - || (base == 16 && isxdigit(UCHAR(*pc->p))) | |
| 13029 | - || (base == 8 && *pc->p >= '0' && *pc->p <= '7') | |
| 13030 | - || (base == 2 && (*pc->p == '0' || *pc->p == '1')) | |
| 13031 | - || (allowdot && *pc->p == '.') | |
| 13032 | - ) { | |
| 13033 | - if (*pc->p == '.') { | |
| 13034 | - allowdot = 0; | |
| 13035 | - pc->tt = JIM_TT_EXPR_DOUBLE; | |
| 13036 | - } | |
| 13037 | - pc->p++; | |
| 13038 | - pc->len--; | |
| 13039 | - if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+' | |
| 13040 | - || isdigit(UCHAR(pc->p[1])))) { | |
| 13041 | - pc->p += 2; | |
| 13042 | - pc->len -= 2; | |
| 13043 | - pc->tt = JIM_TT_EXPR_DOUBLE; | |
| 13214 | + | |
| 13215 | + jim_strtoull(pc->p, (char **)&pc->p); | |
| 13216 | + | |
| 13217 | + if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { | |
| 13218 | + if (strtod(pc->tstart, &end)) { } | |
| 13219 | + if (end == pc->tstart) | |
| 13220 | + return JIM_ERR; | |
| 13221 | + if (end > pc->p) { | |
| 13222 | + | |
| 13223 | + pc->tt = JIM_TT_EXPR_DOUBLE; | |
| 13224 | + pc->p = end; | |
| 13044 | 13225 | } |
| 13045 | 13226 | } |
| 13046 | 13227 | pc->tend = pc->p - 1; |
| 13228 | + pc->len -= (pc->p - pc->tstart); | |
| 13047 | 13229 | return JIM_OK; |
| 13048 | 13230 | } |
| 13049 | 13231 | |
| 13050 | 13232 | static int JimParseExprIrrational(struct JimParserCtx *pc) |
| 13051 | 13233 | { |
| 13052 | - const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; | |
| 13053 | - const char **token; | |
| 13054 | - | |
| 13055 | - for (token = Tokens; *token != NULL; token++) { | |
| 13056 | - int len = strlen(*token); | |
| 13057 | - | |
| 13058 | - if (strncmp(*token, pc->p, len) == 0) { | |
| 13059 | - pc->tstart = pc->p; | |
| 13060 | - pc->tend = pc->p + len - 1; | |
| 13061 | - pc->p += len; | |
| 13062 | - pc->len -= len; | |
| 13063 | - pc->tline = pc->linenr; | |
| 13234 | + const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; | |
| 13235 | + int i; | |
| 13236 | + | |
| 13237 | + for (i = 0; irrationals[i]; i++) { | |
| 13238 | + const char *irr = irrationals[i]; | |
| 13239 | + | |
| 13240 | + if (strncmp(irr, pc->p, 3) == 0) { | |
| 13241 | + pc->p += 3; | |
| 13242 | + pc->len -= 3; | |
| 13243 | + pc->tend = pc->p - 1; | |
| 13064 | 13244 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13065 | 13245 | return JIM_OK; |
| 13066 | 13246 | } |
| 13067 | 13247 | } |
| 13068 | 13248 | return JIM_ERR; |
| @@ -13102,15 +13282,13 @@ | ||
| 13102 | 13282 | } |
| 13103 | 13283 | if (*p != '(') { |
| 13104 | 13284 | return JIM_ERR; |
| 13105 | 13285 | } |
| 13106 | 13286 | } |
| 13107 | - pc->tstart = pc->p; | |
| 13108 | 13287 | pc->tend = pc->p + bestLen - 1; |
| 13109 | 13288 | pc->p += bestLen; |
| 13110 | 13289 | pc->len -= bestLen; |
| 13111 | - pc->tline = pc->linenr; | |
| 13112 | 13290 | |
| 13113 | 13291 | pc->tt = bestIdx; |
| 13114 | 13292 | return JIM_OK; |
| 13115 | 13293 | } |
| 13116 | 13294 | |
| @@ -13608,17 +13786,23 @@ | ||
| 13608 | 13786 | } |
| 13609 | 13787 | |
| 13610 | 13788 | #ifdef DEBUG_SHOW_EXPR_TOKENS |
| 13611 | 13789 | { |
| 13612 | 13790 | int i; |
| 13613 | - printf("==== Expr Tokens ====\n"); | |
| 13791 | + printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj)); | |
| 13614 | 13792 | for (i = 0; i < tokenlist.count; i++) { |
| 13615 | 13793 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), |
| 13616 | 13794 | tokenlist.list[i].len, tokenlist.list[i].token); |
| 13617 | 13795 | } |
| 13618 | 13796 | } |
| 13619 | 13797 | #endif |
| 13798 | + | |
| 13799 | + if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { | |
| 13800 | + ScriptTokenListFree(&tokenlist); | |
| 13801 | + Jim_DecrRefCount(interp, fileNameObj); | |
| 13802 | + return JIM_ERR; | |
| 13803 | + } | |
| 13620 | 13804 | |
| 13621 | 13805 | |
| 13622 | 13806 | expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); |
| 13623 | 13807 | |
| 13624 | 13808 | |
| @@ -13665,10 +13849,24 @@ | ||
| 13665 | 13849 | return NULL; |
| 13666 | 13850 | } |
| 13667 | 13851 | } |
| 13668 | 13852 | return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); |
| 13669 | 13853 | } |
| 13854 | + | |
| 13855 | +#ifdef JIM_OPTIMIZATION | |
| 13856 | +static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) | |
| 13857 | +{ | |
| 13858 | + if (token->type == JIM_TT_EXPR_INT) | |
| 13859 | + return token->objPtr; | |
| 13860 | + else if (token->type == JIM_TT_VAR) | |
| 13861 | + return Jim_GetVariable(interp, token->objPtr, JIM_NONE); | |
| 13862 | + else if (token->type == JIM_TT_DICTSUGAR) | |
| 13863 | + return JimExpandDictSugar(interp, token->objPtr); | |
| 13864 | + else | |
| 13865 | + return NULL; | |
| 13866 | +} | |
| 13867 | +#endif | |
| 13670 | 13868 | |
| 13671 | 13869 | #define JIM_EE_STATICSTACK_LEN 10 |
| 13672 | 13870 | |
| 13673 | 13871 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) |
| 13674 | 13872 | { |
| @@ -13688,102 +13886,69 @@ | ||
| 13688 | 13886 | Jim_Obj *objPtr; |
| 13689 | 13887 | |
| 13690 | 13888 | |
| 13691 | 13889 | switch (expr->len) { |
| 13692 | 13890 | case 1: |
| 13693 | - if (expr->token[0].type == JIM_TT_EXPR_INT) { | |
| 13694 | - *exprResultPtrPtr = expr->token[0].objPtr; | |
| 13695 | - Jim_IncrRefCount(*exprResultPtrPtr); | |
| 13696 | - return JIM_OK; | |
| 13697 | - } | |
| 13698 | - if (expr->token[0].type == JIM_TT_VAR) { | |
| 13699 | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG); | |
| 13700 | - if (objPtr) { | |
| 13701 | - *exprResultPtrPtr = objPtr; | |
| 13702 | - Jim_IncrRefCount(*exprResultPtrPtr); | |
| 13703 | - return JIM_OK; | |
| 13704 | - } | |
| 13891 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 13892 | + if (objPtr) { | |
| 13893 | + Jim_IncrRefCount(objPtr); | |
| 13894 | + *exprResultPtrPtr = objPtr; | |
| 13895 | + return JIM_OK; | |
| 13705 | 13896 | } |
| 13706 | 13897 | break; |
| 13707 | 13898 | |
| 13708 | 13899 | case 2: |
| 13709 | - if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) { | |
| 13710 | - jim_wide wideValue; | |
| 13900 | + if (expr->token[1].type == JIM_EXPROP_NOT) { | |
| 13901 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 13711 | 13902 | |
| 13712 | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); | |
| 13713 | - if (objPtr && JimIsWide(objPtr) | |
| 13714 | - && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) { | |
| 13715 | - *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj; | |
| 13903 | + if (objPtr && JimIsWide(objPtr)) { | |
| 13904 | + *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; | |
| 13716 | 13905 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13717 | 13906 | return JIM_OK; |
| 13718 | 13907 | } |
| 13719 | 13908 | } |
| 13720 | 13909 | break; |
| 13721 | 13910 | |
| 13722 | 13911 | case 3: |
| 13723 | - if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT | |
| 13724 | - || expr->token[1].type == JIM_TT_VAR)) { | |
| 13725 | - switch (expr->token[2].type) { | |
| 13726 | - case JIM_EXPROP_LT: | |
| 13727 | - case JIM_EXPROP_LTE: | |
| 13728 | - case JIM_EXPROP_GT: | |
| 13729 | - case JIM_EXPROP_GTE: | |
| 13730 | - case JIM_EXPROP_NUMEQ: | |
| 13731 | - case JIM_EXPROP_NUMNE:{ | |
| 13732 | - | |
| 13733 | - jim_wide wideValueA; | |
| 13734 | - jim_wide wideValueB; | |
| 13735 | - | |
| 13736 | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); | |
| 13737 | - if (objPtr && JimIsWide(objPtr) | |
| 13738 | - && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) { | |
| 13739 | - if (expr->token[1].type == JIM_TT_VAR) { | |
| 13740 | - objPtr = | |
| 13741 | - Jim_GetVariable(interp, expr->token[1].objPtr, | |
| 13742 | - JIM_NONE); | |
| 13743 | - } | |
| 13744 | - else { | |
| 13745 | - objPtr = expr->token[1].objPtr; | |
| 13746 | - } | |
| 13747 | - if (objPtr && JimIsWide(objPtr) | |
| 13748 | - && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) { | |
| 13749 | - int cmpRes; | |
| 13750 | - | |
| 13751 | - switch (expr->token[2].type) { | |
| 13752 | - case JIM_EXPROP_LT: | |
| 13753 | - cmpRes = wideValueA < wideValueB; | |
| 13754 | - break; | |
| 13755 | - case JIM_EXPROP_LTE: | |
| 13756 | - cmpRes = wideValueA <= wideValueB; | |
| 13757 | - break; | |
| 13758 | - case JIM_EXPROP_GT: | |
| 13759 | - cmpRes = wideValueA > wideValueB; | |
| 13760 | - break; | |
| 13761 | - case JIM_EXPROP_GTE: | |
| 13762 | - cmpRes = wideValueA >= wideValueB; | |
| 13763 | - break; | |
| 13764 | - case JIM_EXPROP_NUMEQ: | |
| 13765 | - cmpRes = wideValueA == wideValueB; | |
| 13766 | - break; | |
| 13767 | - case JIM_EXPROP_NUMNE: | |
| 13768 | - cmpRes = wideValueA != wideValueB; | |
| 13769 | - break; | |
| 13770 | - default: | |
| 13771 | - cmpRes = 0; | |
| 13772 | - } | |
| 13773 | - *exprResultPtrPtr = | |
| 13774 | - cmpRes ? interp->trueObj : interp->falseObj; | |
| 13775 | - Jim_IncrRefCount(*exprResultPtrPtr); | |
| 13776 | - return JIM_OK; | |
| 13777 | - } | |
| 13778 | - } | |
| 13779 | - } | |
| 13780 | - } | |
| 13781 | - } | |
| 13782 | - break; | |
| 13783 | - } | |
| 13784 | - } | |
| 13912 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 13913 | + if (objPtr && JimIsWide(objPtr)) { | |
| 13914 | + Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); | |
| 13915 | + if (objPtr2 && JimIsWide(objPtr2)) { | |
| 13916 | + jim_wide wideValueA = JimWideValue(objPtr); | |
| 13917 | + jim_wide wideValueB = JimWideValue(objPtr2); | |
| 13918 | + int cmpRes; | |
| 13919 | + switch (expr->token[2].type) { | |
| 13920 | + case JIM_EXPROP_LT: | |
| 13921 | + cmpRes = wideValueA < wideValueB; | |
| 13922 | + break; | |
| 13923 | + case JIM_EXPROP_LTE: | |
| 13924 | + cmpRes = wideValueA <= wideValueB; | |
| 13925 | + break; | |
| 13926 | + case JIM_EXPROP_GT: | |
| 13927 | + cmpRes = wideValueA > wideValueB; | |
| 13928 | + break; | |
| 13929 | + case JIM_EXPROP_GTE: | |
| 13930 | + cmpRes = wideValueA >= wideValueB; | |
| 13931 | + break; | |
| 13932 | + case JIM_EXPROP_NUMEQ: | |
| 13933 | + cmpRes = wideValueA == wideValueB; | |
| 13934 | + break; | |
| 13935 | + case JIM_EXPROP_NUMNE: | |
| 13936 | + cmpRes = wideValueA != wideValueB; | |
| 13937 | + break; | |
| 13938 | + default: | |
| 13939 | + goto noopt; | |
| 13940 | + } | |
| 13941 | + *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; | |
| 13942 | + Jim_IncrRefCount(*exprResultPtrPtr); | |
| 13943 | + return JIM_OK; | |
| 13944 | + } | |
| 13945 | + } | |
| 13946 | + break; | |
| 13947 | + } | |
| 13948 | + } | |
| 13949 | +noopt: | |
| 13785 | 13950 | #endif |
| 13786 | 13951 | |
| 13787 | 13952 | expr->inUse++; |
| 13788 | 13953 | |
| 13789 | 13954 | |
| @@ -13952,16 +14117,13 @@ | ||
| 13952 | 14117 | memcpy(newVec, srcPtr->internalRep.ptr, size); |
| 13953 | 14118 | dupPtr->internalRep.ptr = newVec; |
| 13954 | 14119 | dupPtr->typePtr = &scanFmtStringObjType; |
| 13955 | 14120 | } |
| 13956 | 14121 | |
| 13957 | -void UpdateStringOfScanFmt(Jim_Obj *objPtr) | |
| 14122 | +static void UpdateStringOfScanFmt(Jim_Obj *objPtr) | |
| 13958 | 14123 | { |
| 13959 | - char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep; | |
| 13960 | - | |
| 13961 | - objPtr->bytes = Jim_StrDup(bytes); | |
| 13962 | - objPtr->length = strlen(bytes); | |
| 14124 | + JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep); | |
| 13963 | 14125 | } |
| 13964 | 14126 | |
| 13965 | 14127 | |
| 13966 | 14128 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13967 | 14129 | { |
| @@ -14171,11 +14333,10 @@ | ||
| 14171 | 14333 | Jim_Obj *tmpObj = NULL; |
| 14172 | 14334 | |
| 14173 | 14335 | |
| 14174 | 14336 | *valObjPtr = 0; |
| 14175 | 14337 | if (descr->prefix) { |
| 14176 | - | |
| 14177 | 14338 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14178 | 14339 | |
| 14179 | 14340 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14180 | 14341 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14181 | 14342 | ++pos; |
| @@ -14512,34 +14673,55 @@ | ||
| 14512 | 14673 | } |
| 14513 | 14674 | |
| 14514 | 14675 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14515 | 14676 | { |
| 14516 | 14677 | int retcode; |
| 14517 | - Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); | |
| 14678 | + Jim_Cmd *cmdPtr; | |
| 14518 | 14679 | |
| 14519 | - if (cmdPtr == NULL) { | |
| 14520 | - return JimUnknown(interp, objc, objv); | |
| 14680 | +#if 0 | |
| 14681 | + printf("invoke"); | |
| 14682 | + int j; | |
| 14683 | + for (j = 0; j < objc; j++) { | |
| 14684 | + printf(" '%s'", Jim_String(objv[j])); | |
| 14521 | 14685 | } |
| 14686 | + printf("\n"); | |
| 14687 | +#endif | |
| 14688 | + | |
| 14689 | + if (interp->framePtr->tailcallCmd) { | |
| 14690 | + | |
| 14691 | + cmdPtr = interp->framePtr->tailcallCmd; | |
| 14692 | + interp->framePtr->tailcallCmd = NULL; | |
| 14693 | + } | |
| 14694 | + else { | |
| 14695 | + cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); | |
| 14696 | + if (cmdPtr == NULL) { | |
| 14697 | + return JimUnknown(interp, objc, objv); | |
| 14698 | + } | |
| 14699 | + JimIncrCmdRefCount(cmdPtr); | |
| 14700 | + } | |
| 14701 | + | |
| 14522 | 14702 | if (interp->evalDepth == interp->maxEvalDepth) { |
| 14523 | 14703 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14524 | - return JIM_ERR; | |
| 14704 | + retcode = JIM_ERR; | |
| 14705 | + goto out; | |
| 14525 | 14706 | } |
| 14526 | 14707 | interp->evalDepth++; |
| 14527 | 14708 | |
| 14528 | 14709 | |
| 14529 | - JimIncrCmdRefCount(cmdPtr); | |
| 14530 | 14710 | Jim_SetEmptyResult(interp); |
| 14531 | 14711 | if (cmdPtr->isproc) { |
| 14532 | 14712 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14533 | 14713 | } |
| 14534 | 14714 | else { |
| 14535 | 14715 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14536 | 14716 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14537 | 14717 | } |
| 14538 | - JimDecrCmdRefCount(interp, cmdPtr); | |
| 14539 | 14718 | interp->evalDepth--; |
| 14540 | 14719 | |
| 14720 | +out: | |
| 14721 | + JimDecrCmdRefCount(interp, cmdPtr); | |
| 14722 | + | |
| 14541 | 14723 | return retcode; |
| 14542 | 14724 | } |
| 14543 | 14725 | |
| 14544 | 14726 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14545 | 14727 | { |
| @@ -14717,10 +14899,15 @@ | ||
| 14717 | 14899 | objPtr->typePtr = &interpolatedObjType; |
| 14718 | 14900 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 14719 | 14901 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 14720 | 14902 | Jim_IncrRefCount(intv[2]); |
| 14721 | 14903 | } |
| 14904 | + else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { | |
| 14905 | + | |
| 14906 | + JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); | |
| 14907 | + } | |
| 14908 | + | |
| 14722 | 14909 | |
| 14723 | 14910 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| 14724 | 14911 | objPtr->length = totlen; |
| 14725 | 14912 | for (i = 0; i < tokens; i++) { |
| 14726 | 14913 | if (intv[i]) { |
| @@ -14772,10 +14959,14 @@ | ||
| 14772 | 14959 | return JimEvalObjList(interp, scriptObjPtr); |
| 14773 | 14960 | } |
| 14774 | 14961 | |
| 14775 | 14962 | Jim_IncrRefCount(scriptObjPtr); |
| 14776 | 14963 | script = Jim_GetScript(interp, scriptObjPtr); |
| 14964 | + if (script == NULL) { | |
| 14965 | + Jim_DecrRefCount(interp, scriptObjPtr); | |
| 14966 | + return JIM_ERR; | |
| 14967 | + } | |
| 14777 | 14968 | |
| 14778 | 14969 | Jim_SetEmptyResult(interp); |
| 14779 | 14970 | |
| 14780 | 14971 | token = script->token; |
| 14781 | 14972 | |
| @@ -15046,26 +15237,20 @@ | ||
| 15046 | 15237 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15047 | 15238 | } |
| 15048 | 15239 | |
| 15049 | 15240 | |
| 15050 | 15241 | interp->framePtr = interp->framePtr->parent; |
| 15051 | - if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { | |
| 15052 | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); | |
| 15053 | - } | |
| 15054 | - else { | |
| 15055 | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); | |
| 15056 | - } | |
| 15242 | + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); | |
| 15057 | 15243 | |
| 15058 | 15244 | return retcode; |
| 15059 | 15245 | } |
| 15060 | 15246 | #endif |
| 15061 | 15247 | |
| 15062 | 15248 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) |
| 15063 | 15249 | { |
| 15064 | 15250 | Jim_CallFrame *callFramePtr; |
| 15065 | 15251 | int i, d, retcode, optargs; |
| 15066 | - Jim_Stack *localCommands; | |
| 15067 | 15252 | ScriptObj *script; |
| 15068 | 15253 | |
| 15069 | 15254 | |
| 15070 | 15255 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15071 | 15256 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| @@ -15145,37 +15330,42 @@ | ||
| 15145 | 15330 | |
| 15146 | 15331 | |
| 15147 | 15332 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15148 | 15333 | |
| 15149 | 15334 | badargset: |
| 15335 | + | |
| 15150 | 15336 | |
| 15151 | - | |
| 15152 | - localCommands = callFramePtr->localCommands; | |
| 15153 | - callFramePtr->localCommands = NULL; | |
| 15154 | - | |
| 15155 | 15337 | interp->framePtr = interp->framePtr->parent; |
| 15156 | - if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { | |
| 15157 | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); | |
| 15158 | - } | |
| 15159 | - else { | |
| 15160 | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); | |
| 15161 | - } | |
| 15162 | - | |
| 15163 | - | |
| 15164 | - while (retcode == JIM_EVAL) { | |
| 15165 | - Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); | |
| 15166 | - | |
| 15167 | - Jim_IncrRefCount(resultScriptObjPtr); | |
| 15168 | - | |
| 15169 | - JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list")); | |
| 15170 | - | |
| 15171 | - retcode = JimEvalObjList(interp, resultScriptObjPtr); | |
| 15172 | - if (retcode == JIM_RETURN) { | |
| 15173 | - interp->returnLevel++; | |
| 15174 | - } | |
| 15175 | - Jim_DecrRefCount(interp, resultScriptObjPtr); | |
| 15176 | - } | |
| 15338 | + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); | |
| 15339 | + | |
| 15340 | + if (interp->framePtr->tailcallObj) { | |
| 15341 | + | |
| 15342 | + if (interp->framePtr->tailcall++ == 0) { | |
| 15343 | + | |
| 15344 | + do { | |
| 15345 | + Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; | |
| 15346 | + | |
| 15347 | + interp->framePtr->tailcallObj = NULL; | |
| 15348 | + | |
| 15349 | + if (retcode == JIM_EVAL) { | |
| 15350 | + retcode = Jim_EvalObjList(interp, tailcallObj); | |
| 15351 | + if (retcode == JIM_RETURN) { | |
| 15352 | + interp->returnLevel++; | |
| 15353 | + } | |
| 15354 | + } | |
| 15355 | + Jim_DecrRefCount(interp, tailcallObj); | |
| 15356 | + } while (interp->framePtr->tailcallObj); | |
| 15357 | + | |
| 15358 | + | |
| 15359 | + if (interp->framePtr->tailcallCmd) { | |
| 15360 | + JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); | |
| 15361 | + interp->framePtr->tailcallCmd = NULL; | |
| 15362 | + } | |
| 15363 | + } | |
| 15364 | + interp->framePtr->tailcall--; | |
| 15365 | + } | |
| 15366 | + | |
| 15177 | 15367 | |
| 15178 | 15368 | if (retcode == JIM_RETURN) { |
| 15179 | 15369 | if (--interp->returnLevel <= 0) { |
| 15180 | 15370 | retcode = interp->returnCode; |
| 15181 | 15371 | interp->returnCode = JIM_OK; |
| @@ -15187,13 +15377,10 @@ | ||
| 15187 | 15377 | Jim_DecrRefCount(interp, interp->errorProc); |
| 15188 | 15378 | interp->errorProc = argv[0]; |
| 15189 | 15379 | Jim_IncrRefCount(interp->errorProc); |
| 15190 | 15380 | } |
| 15191 | 15381 | |
| 15192 | - | |
| 15193 | - JimDeleteLocalProcs(interp, localCommands); | |
| 15194 | - | |
| 15195 | 15382 | return retcode; |
| 15196 | 15383 | } |
| 15197 | 15384 | |
| 15198 | 15385 | int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) |
| 15199 | 15386 | { |
| @@ -15261,11 +15448,10 @@ | ||
| 15261 | 15448 | Jim_Obj *scriptObjPtr; |
| 15262 | 15449 | Jim_Obj *prevScriptObj; |
| 15263 | 15450 | struct stat sb; |
| 15264 | 15451 | int retcode; |
| 15265 | 15452 | int readlen; |
| 15266 | - struct JimParseResult result; | |
| 15267 | 15453 | |
| 15268 | 15454 | if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { |
| 15269 | 15455 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); |
| 15270 | 15456 | return JIM_ERR; |
| 15271 | 15457 | } |
| @@ -15288,31 +15474,13 @@ | ||
| 15288 | 15474 | scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 15289 | 15475 | JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); |
| 15290 | 15476 | Jim_IncrRefCount(scriptObjPtr); |
| 15291 | 15477 | |
| 15292 | 15478 | |
| 15293 | - if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) { | |
| 15294 | - const char *msg; | |
| 15295 | - char linebuf[20]; | |
| 15296 | - | |
| 15297 | - switch (result.missing) { | |
| 15298 | - case '[': | |
| 15299 | - msg = "unmatched \"[\""; | |
| 15300 | - break; | |
| 15301 | - case '{': | |
| 15302 | - msg = "missing close-brace"; | |
| 15303 | - break; | |
| 15304 | - case '"': | |
| 15305 | - default: | |
| 15306 | - msg = "missing quote"; | |
| 15307 | - break; | |
| 15308 | - } | |
| 15309 | - | |
| 15310 | - snprintf(linebuf, sizeof(linebuf), "%d", result.line); | |
| 15311 | - | |
| 15312 | - Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s", | |
| 15313 | - msg, filename, linebuf); | |
| 15479 | + if (Jim_GetScript(interp, scriptObjPtr) == NULL) { | |
| 15480 | + | |
| 15481 | + JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr)); | |
| 15314 | 15482 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15315 | 15483 | return JIM_ERR; |
| 15316 | 15484 | } |
| 15317 | 15485 | |
| 15318 | 15486 | prevScriptObj = interp->currentScriptObj; |
| @@ -15475,11 +15643,11 @@ | ||
| 15475 | 15643 | } |
| 15476 | 15644 | |
| 15477 | 15645 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15478 | 15646 | Jim_HashEntry *he, int type); |
| 15479 | 15647 | |
| 15480 | -#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) | |
| 15648 | +#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) | |
| 15481 | 15649 | |
| 15482 | 15650 | static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 15483 | 15651 | JimHashtableIteratorCallbackType *callback, int type) |
| 15484 | 15652 | { |
| 15485 | 15653 | Jim_HashEntry *he; |
| @@ -15510,11 +15678,11 @@ | ||
| 15510 | 15678 | #define JIM_CMDLIST_CHANNELS 2 |
| 15511 | 15679 | |
| 15512 | 15680 | static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15513 | 15681 | Jim_HashEntry *he, int type) |
| 15514 | 15682 | { |
| 15515 | - Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val; | |
| 15683 | + Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); | |
| 15516 | 15684 | Jim_Obj *objPtr; |
| 15517 | 15685 | |
| 15518 | 15686 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15519 | 15687 | |
| 15520 | 15688 | return; |
| @@ -15543,11 +15711,11 @@ | ||
| 15543 | 15711 | #define JIM_VARLIST_VALUES 0x1000 |
| 15544 | 15712 | |
| 15545 | 15713 | static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15546 | 15714 | Jim_HashEntry *he, int type) |
| 15547 | 15715 | { |
| 15548 | - Jim_Var *varPtr = (Jim_Var *)he->u.val; | |
| 15716 | + Jim_Var *varPtr = Jim_GetHashEntryVal(he); | |
| 15549 | 15717 | |
| 15550 | 15718 | if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { |
| 15551 | 15719 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); |
| 15552 | 15720 | if (type & JIM_VARLIST_VALUES) { |
| 15553 | 15721 | Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); |
| @@ -15865,11 +16033,11 @@ | ||
| 15865 | 16033 | |
| 15866 | 16034 | expr = JimGetExpression(interp, argv[2]); |
| 15867 | 16035 | incrScript = Jim_GetScript(interp, argv[3]); |
| 15868 | 16036 | |
| 15869 | 16037 | |
| 15870 | - if (incrScript->len != 3 || !expr || expr->len != 3) { | |
| 16038 | + if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { | |
| 15871 | 16039 | goto evalstart; |
| 15872 | 16040 | } |
| 15873 | 16041 | |
| 15874 | 16042 | if (incrScript->token[1].type != JIM_TT_ESC || |
| 15875 | 16043 | expr->token[0].type != JIM_TT_VAR || |
| @@ -16088,11 +16256,11 @@ | ||
| 16088 | 16256 | } |
| 16089 | 16257 | |
| 16090 | 16258 | |
| 16091 | 16259 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16092 | 16260 | { |
| 16093 | - int result = JIM_ERR; | |
| 16261 | + int result = JIM_OK; | |
| 16094 | 16262 | int i, numargs; |
| 16095 | 16263 | Jim_ListIter twoiters[2]; |
| 16096 | 16264 | Jim_ListIter *iters; |
| 16097 | 16265 | Jim_Obj *script; |
| 16098 | 16266 | Jim_Obj *resultObj; |
| @@ -16111,13 +16279,16 @@ | ||
| 16111 | 16279 | iters = Jim_Alloc(numargs * sizeof(*iters)); |
| 16112 | 16280 | } |
| 16113 | 16281 | for (i = 0; i < numargs; i++) { |
| 16114 | 16282 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16115 | 16283 | if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { |
| 16116 | - Jim_SetResultString(interp, "foreach varlist is empty", -1); | |
| 16117 | - return JIM_ERR; | |
| 16284 | + result = JIM_ERR; | |
| 16118 | 16285 | } |
| 16286 | + } | |
| 16287 | + if (result != JIM_OK) { | |
| 16288 | + Jim_SetResultString(interp, "foreach varlist is empty", -1); | |
| 16289 | + return result; | |
| 16119 | 16290 | } |
| 16120 | 16291 | |
| 16121 | 16292 | if (doMap) { |
| 16122 | 16293 | resultObj = Jim_NewListObj(interp, NULL, 0); |
| 16123 | 16294 | } |
| @@ -16430,12 +16601,12 @@ | ||
| 16430 | 16601 | { |
| 16431 | 16602 | Jim_Obj *objPtr, *listObjPtr; |
| 16432 | 16603 | int i; |
| 16433 | 16604 | int idx; |
| 16434 | 16605 | |
| 16435 | - if (argc < 3) { | |
| 16436 | - Jim_WrongNumArgs(interp, 1, argv, "list index ?...?"); | |
| 16606 | + if (argc < 2) { | |
| 16607 | + Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); | |
| 16437 | 16608 | return JIM_ERR; |
| 16438 | 16609 | } |
| 16439 | 16610 | objPtr = argv[1]; |
| 16440 | 16611 | Jim_IncrRefCount(objPtr); |
| 16441 | 16612 | for (i = 2; i < argc; i++) { |
| @@ -16547,14 +16718,13 @@ | ||
| 16547 | 16718 | Jim_IncrRefCount(commandObj); |
| 16548 | 16719 | } |
| 16549 | 16720 | |
| 16550 | 16721 | listlen = Jim_ListLength(interp, argv[0]); |
| 16551 | 16722 | for (i = 0; i < listlen; i++) { |
| 16552 | - Jim_Obj *objPtr; | |
| 16553 | 16723 | int eq = 0; |
| 16724 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); | |
| 16554 | 16725 | |
| 16555 | - Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE); | |
| 16556 | 16726 | switch (opt_match) { |
| 16557 | 16727 | case OPT_EXACT: |
| 16558 | 16728 | eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; |
| 16559 | 16729 | break; |
| 16560 | 16730 | |
| @@ -16744,29 +16914,27 @@ | ||
| 16744 | 16914 | if (argc < 3) { |
| 16745 | 16915 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 16746 | 16916 | return JIM_ERR; |
| 16747 | 16917 | } |
| 16748 | 16918 | else if (argc == 3) { |
| 16919 | + | |
| 16749 | 16920 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16750 | 16921 | return JIM_ERR; |
| 16751 | 16922 | Jim_SetResult(interp, argv[2]); |
| 16752 | 16923 | return JIM_OK; |
| 16753 | 16924 | } |
| 16754 | - if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]) | |
| 16755 | - == JIM_ERR) | |
| 16756 | - return JIM_ERR; | |
| 16757 | - return JIM_OK; | |
| 16925 | + return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]); | |
| 16758 | 16926 | } |
| 16759 | 16927 | |
| 16760 | 16928 | |
| 16761 | 16929 | static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) |
| 16762 | 16930 | { |
| 16763 | 16931 | static const char * const options[] = { |
| 16764 | - "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL | |
| 16932 | + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL | |
| 16765 | 16933 | }; |
| 16766 | 16934 | enum |
| 16767 | - { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX }; | |
| 16935 | + { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; | |
| 16768 | 16936 | Jim_Obj *resObj; |
| 16769 | 16937 | int i; |
| 16770 | 16938 | int retCode; |
| 16771 | 16939 | |
| 16772 | 16940 | struct lsort_info info; |
| @@ -16777,17 +16945,18 @@ | ||
| 16777 | 16945 | } |
| 16778 | 16946 | |
| 16779 | 16947 | info.type = JIM_LSORT_ASCII; |
| 16780 | 16948 | info.order = 1; |
| 16781 | 16949 | info.indexed = 0; |
| 16950 | + info.unique = 0; | |
| 16782 | 16951 | info.command = NULL; |
| 16783 | 16952 | info.interp = interp; |
| 16784 | 16953 | |
| 16785 | 16954 | for (i = 1; i < (argc - 1); i++) { |
| 16786 | 16955 | int option; |
| 16787 | 16956 | |
| 16788 | - if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) | |
| 16957 | + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) | |
| 16789 | 16958 | != JIM_OK) |
| 16790 | 16959 | return JIM_ERR; |
| 16791 | 16960 | switch (option) { |
| 16792 | 16961 | case OPT_ASCII: |
| 16793 | 16962 | info.type = JIM_LSORT_ASCII; |
| @@ -16796,16 +16965,22 @@ | ||
| 16796 | 16965 | info.type = JIM_LSORT_NOCASE; |
| 16797 | 16966 | break; |
| 16798 | 16967 | case OPT_INTEGER: |
| 16799 | 16968 | info.type = JIM_LSORT_INTEGER; |
| 16800 | 16969 | break; |
| 16970 | + case OPT_REAL: | |
| 16971 | + info.type = JIM_LSORT_REAL; | |
| 16972 | + break; | |
| 16801 | 16973 | case OPT_INCREASING: |
| 16802 | 16974 | info.order = 1; |
| 16803 | 16975 | break; |
| 16804 | 16976 | case OPT_DECREASING: |
| 16805 | 16977 | info.order = -1; |
| 16806 | 16978 | break; |
| 16979 | + case OPT_UNIQUE: | |
| 16980 | + info.unique = 1; | |
| 16981 | + break; | |
| 16807 | 16982 | case OPT_COMMAND: |
| 16808 | 16983 | if (i >= (argc - 2)) { |
| 16809 | 16984 | Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); |
| 16810 | 16985 | return JIM_ERR; |
| 16811 | 16986 | } |
| @@ -16915,20 +17090,20 @@ | ||
| 16915 | 17090 | static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16916 | 17091 | { |
| 16917 | 17092 | if (argc >= 2) { |
| 16918 | 17093 | int retcode; |
| 16919 | 17094 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 16920 | - Jim_Obj *objPtr; | |
| 17095 | + int savedTailcall; | |
| 16921 | 17096 | const char *str; |
| 16922 | 17097 | |
| 16923 | 17098 | |
| 16924 | 17099 | savedCallFrame = interp->framePtr; |
| 16925 | 17100 | |
| 16926 | 17101 | |
| 16927 | 17102 | str = Jim_String(argv[1]); |
| 16928 | 17103 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 16929 | - targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]); | |
| 17104 | + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); | |
| 16930 | 17105 | argc--; |
| 16931 | 17106 | argv++; |
| 16932 | 17107 | } |
| 16933 | 17108 | else { |
| 16934 | 17109 | targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); |
| @@ -16935,25 +17110,25 @@ | ||
| 16935 | 17110 | } |
| 16936 | 17111 | if (targetCallFrame == NULL) { |
| 16937 | 17112 | return JIM_ERR; |
| 16938 | 17113 | } |
| 16939 | 17114 | if (argc < 2) { |
| 16940 | - argv--; | |
| 16941 | - Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); | |
| 17115 | + Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); | |
| 16942 | 17116 | return JIM_ERR; |
| 16943 | 17117 | } |
| 16944 | 17118 | |
| 16945 | 17119 | interp->framePtr = targetCallFrame; |
| 17120 | + | |
| 17121 | + savedTailcall = interp->framePtr->tailcall; | |
| 17122 | + interp->framePtr->tailcall = 0; | |
| 16946 | 17123 | if (argc == 2) { |
| 16947 | 17124 | retcode = Jim_EvalObj(interp, argv[1]); |
| 16948 | 17125 | } |
| 16949 | 17126 | else { |
| 16950 | - objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); | |
| 16951 | - Jim_IncrRefCount(objPtr); | |
| 16952 | - retcode = Jim_EvalObj(interp, objPtr); | |
| 16953 | - Jim_DecrRefCount(interp, objPtr); | |
| 17127 | + retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); | |
| 16954 | 17128 | } |
| 17129 | + interp->framePtr->tailcall = savedTailcall; | |
| 16955 | 17130 | interp->framePtr = savedCallFrame; |
| 16956 | 17131 | return retcode; |
| 16957 | 17132 | } |
| 16958 | 17133 | else { |
| 16959 | 17134 | Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| @@ -17064,12 +17239,39 @@ | ||
| 17064 | 17239 | } |
| 17065 | 17240 | |
| 17066 | 17241 | |
| 17067 | 17242 | static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17068 | 17243 | { |
| 17069 | - Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1)); | |
| 17070 | - return JIM_EVAL; | |
| 17244 | + if (interp->framePtr->level == 0) { | |
| 17245 | + Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); | |
| 17246 | + return JIM_ERR; | |
| 17247 | + } | |
| 17248 | + else if (argc >= 2) { | |
| 17249 | + | |
| 17250 | + Jim_CallFrame *cf = interp->framePtr->parent; | |
| 17251 | + | |
| 17252 | + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); | |
| 17253 | + if (cmdPtr == NULL) { | |
| 17254 | + return JIM_ERR; | |
| 17255 | + } | |
| 17256 | + | |
| 17257 | + JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); | |
| 17258 | + | |
| 17259 | + | |
| 17260 | + JimIncrCmdRefCount(cmdPtr); | |
| 17261 | + cf->tailcallCmd = cmdPtr; | |
| 17262 | + | |
| 17263 | + | |
| 17264 | + JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); | |
| 17265 | + | |
| 17266 | + cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); | |
| 17267 | + Jim_IncrRefCount(cf->tailcallObj); | |
| 17268 | + | |
| 17269 | + | |
| 17270 | + return JIM_EVAL; | |
| 17271 | + } | |
| 17272 | + return JIM_OK; | |
| 17071 | 17273 | } |
| 17072 | 17274 | |
| 17073 | 17275 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17074 | 17276 | { |
| 17075 | 17277 | Jim_Obj *cmdList; |
| @@ -17354,11 +17556,11 @@ | ||
| 17354 | 17556 | for (i = 0; i < numMaps; i += 2) { |
| 17355 | 17557 | Jim_Obj *objPtr; |
| 17356 | 17558 | const char *k; |
| 17357 | 17559 | int kl; |
| 17358 | 17560 | |
| 17359 | - Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE); | |
| 17561 | + objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); | |
| 17360 | 17562 | k = Jim_String(objPtr); |
| 17361 | 17563 | kl = Jim_Utf8Length(interp, objPtr); |
| 17362 | 17564 | |
| 17363 | 17565 | if (strLen >= kl && kl) { |
| 17364 | 17566 | int rc; |
| @@ -17366,12 +17568,11 @@ | ||
| 17366 | 17568 | if (rc == 0) { |
| 17367 | 17569 | if (noMatchStart) { |
| 17368 | 17570 | Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); |
| 17369 | 17571 | noMatchStart = NULL; |
| 17370 | 17572 | } |
| 17371 | - Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE); | |
| 17372 | - Jim_AppendObj(interp, resultObjPtr, objPtr); | |
| 17573 | + Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1)); | |
| 17373 | 17574 | str += utf8_index(str, kl); |
| 17374 | 17575 | strLen -= kl; |
| 17375 | 17576 | break; |
| 17376 | 17577 | } |
| 17377 | 17578 | } |
| @@ -17851,15 +18052,17 @@ | ||
| 17851 | 18052 | |
| 17852 | 18053 | exitCode = JIM_SIGNAL; |
| 17853 | 18054 | } |
| 17854 | 18055 | else { |
| 17855 | 18056 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18057 | + | |
| 18058 | + interp->errorFlag = 0; | |
| 17856 | 18059 | } |
| 17857 | 18060 | interp->signal_level -= sig; |
| 17858 | 18061 | |
| 17859 | 18062 | |
| 17860 | - if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) { | |
| 18063 | + if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { | |
| 17861 | 18064 | |
| 17862 | 18065 | return exitCode; |
| 17863 | 18066 | } |
| 17864 | 18067 | |
| 17865 | 18068 | if (sig && exitCode == JIM_SIGNAL) { |
| @@ -18009,11 +18212,11 @@ | ||
| 18009 | 18212 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18010 | 18213 | |
| 18011 | 18214 | JimInitHashTableIterator(&interp->references, &htiter); |
| 18012 | 18215 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18013 | 18216 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 18014 | - Jim_Reference *refPtr = he->u.val; | |
| 18217 | + Jim_Reference *refPtr = Jim_GetHashEntryVal(he); | |
| 18015 | 18218 | const unsigned long *refId = he->key; |
| 18016 | 18219 | |
| 18017 | 18220 | JimFormatReference(buf, refPtr, *refId); |
| 18018 | 18221 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); |
| 18019 | 18222 | } |
| @@ -18043,11 +18246,11 @@ | ||
| 18043 | 18246 | |
| 18044 | 18247 | static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) |
| 18045 | 18248 | { |
| 18046 | 18249 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 18047 | 18250 | if (type & JIM_DICTMATCH_VALUES) { |
| 18048 | - Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val); | |
| 18251 | + Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); | |
| 18049 | 18252 | } |
| 18050 | 18253 | } |
| 18051 | 18254 | |
| 18052 | 18255 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 18053 | 18256 | JimDictMatchCallbackType *callback, int type) |
| @@ -18092,21 +18295,65 @@ | ||
| 18092 | 18295 | return -1; |
| 18093 | 18296 | } |
| 18094 | 18297 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18095 | 18298 | } |
| 18096 | 18299 | |
| 18300 | +int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 18301 | +{ | |
| 18302 | + Jim_HashTable *ht; | |
| 18303 | + unsigned int i; | |
| 18304 | + | |
| 18305 | + if (SetDictFromAny(interp, objPtr) != JIM_OK) { | |
| 18306 | + return JIM_ERR; | |
| 18307 | + } | |
| 18308 | + | |
| 18309 | + ht = (Jim_HashTable *)objPtr->internalRep.ptr; | |
| 18310 | + | |
| 18311 | + | |
| 18312 | + printf("%d entries in table, %d buckets\n", ht->used, ht->size); | |
| 18313 | + | |
| 18314 | + for (i = 0; i < ht->size; i++) { | |
| 18315 | + Jim_HashEntry *he = ht->table[i]; | |
| 18316 | + | |
| 18317 | + if (he) { | |
| 18318 | + printf("%d: ", i); | |
| 18319 | + | |
| 18320 | + while (he) { | |
| 18321 | + printf(" %s", Jim_String(he->key)); | |
| 18322 | + he = he->next; | |
| 18323 | + } | |
| 18324 | + printf("\n"); | |
| 18325 | + } | |
| 18326 | + } | |
| 18327 | + return JIM_OK; | |
| 18328 | +} | |
| 18329 | + | |
| 18330 | +static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) | |
| 18331 | +{ | |
| 18332 | + Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1); | |
| 18333 | + | |
| 18334 | + Jim_AppendString(interp, prefixObj, " ", 1); | |
| 18335 | + Jim_AppendString(interp, prefixObj, subcmd, -1); | |
| 18336 | + | |
| 18337 | + return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); | |
| 18338 | +} | |
| 18339 | + | |
| 18097 | 18340 | |
| 18098 | 18341 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18099 | 18342 | { |
| 18100 | 18343 | Jim_Obj *objPtr; |
| 18101 | 18344 | int option; |
| 18102 | 18345 | static const char * const options[] = { |
| 18103 | - "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL | |
| 18346 | + "create", "get", "set", "unset", "exists", "keys", "size", "info", | |
| 18347 | + "merge", "with", "append", "lappend", "incr", "remove", "values", "for", | |
| 18348 | + "replace", "update", NULL | |
| 18104 | 18349 | }; |
| 18105 | 18350 | enum |
| 18106 | 18351 | { |
| 18107 | - OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH, | |
| 18352 | + OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, | |
| 18353 | + OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, | |
| 18354 | + OPT_REPLACE, OPT_UPDATE, | |
| 18108 | 18355 | }; |
| 18109 | 18356 | |
| 18110 | 18357 | if (argc < 2) { |
| 18111 | 18358 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18112 | 18359 | return JIM_ERR; |
| @@ -18117,11 +18364,11 @@ | ||
| 18117 | 18364 | } |
| 18118 | 18365 | |
| 18119 | 18366 | switch (option) { |
| 18120 | 18367 | case OPT_GET: |
| 18121 | 18368 | if (argc < 3) { |
| 18122 | - Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); | |
| 18369 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); | |
| 18123 | 18370 | return JIM_ERR; |
| 18124 | 18371 | } |
| 18125 | 18372 | if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, |
| 18126 | 18373 | JIM_ERRMSG) != JIM_OK) { |
| 18127 | 18374 | return JIM_ERR; |
| @@ -18134,82 +18381,87 @@ | ||
| 18134 | 18381 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); |
| 18135 | 18382 | return JIM_ERR; |
| 18136 | 18383 | } |
| 18137 | 18384 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); |
| 18138 | 18385 | |
| 18139 | - case OPT_EXIST: | |
| 18140 | - if (argc < 3) { | |
| 18141 | - Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); | |
| 18386 | + case OPT_EXISTS: | |
| 18387 | + if (argc < 4) { | |
| 18388 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); | |
| 18142 | 18389 | return JIM_ERR; |
| 18143 | 18390 | } |
| 18144 | - Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, | |
| 18145 | - &objPtr, JIM_ERRMSG) == JIM_OK); | |
| 18146 | - return JIM_OK; | |
| 18391 | + else { | |
| 18392 | + int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); | |
| 18393 | + if (rc < 0) { | |
| 18394 | + return JIM_ERR; | |
| 18395 | + } | |
| 18396 | + Jim_SetResultBool(interp, rc == JIM_OK); | |
| 18397 | + return JIM_OK; | |
| 18398 | + } | |
| 18147 | 18399 | |
| 18148 | 18400 | case OPT_UNSET: |
| 18149 | 18401 | if (argc < 4) { |
| 18150 | 18402 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); |
| 18151 | 18403 | return JIM_ERR; |
| 18152 | 18404 | } |
| 18153 | - return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE); | |
| 18405 | + if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { | |
| 18406 | + return JIM_ERR; | |
| 18407 | + } | |
| 18408 | + return JIM_OK; | |
| 18154 | 18409 | |
| 18155 | 18410 | case OPT_KEYS: |
| 18156 | 18411 | if (argc != 3 && argc != 4) { |
| 18157 | - Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?"); | |
| 18412 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); | |
| 18158 | 18413 | return JIM_ERR; |
| 18159 | 18414 | } |
| 18160 | 18415 | return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); |
| 18161 | 18416 | |
| 18162 | - case OPT_SIZE: { | |
| 18163 | - int size; | |
| 18164 | - | |
| 18417 | + case OPT_SIZE: | |
| 18165 | 18418 | if (argc != 3) { |
| 18166 | - Jim_WrongNumArgs(interp, 2, argv, "dictVar"); | |
| 18419 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary"); | |
| 18167 | 18420 | return JIM_ERR; |
| 18168 | 18421 | } |
| 18169 | - | |
| 18170 | - size = Jim_DictSize(interp, argv[2]); | |
| 18171 | - if (size < 0) { | |
| 18422 | + else if (Jim_DictSize(interp, argv[2]) < 0) { | |
| 18172 | 18423 | return JIM_ERR; |
| 18173 | 18424 | } |
| 18174 | - Jim_SetResultInt(interp, size); | |
| 18425 | + Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); | |
| 18175 | 18426 | return JIM_OK; |
| 18176 | - } | |
| 18177 | 18427 | |
| 18178 | 18428 | case OPT_MERGE: |
| 18179 | 18429 | if (argc == 2) { |
| 18180 | 18430 | return JIM_OK; |
| 18181 | 18431 | } |
| 18182 | - else if (SetDictFromAny(interp, argv[2]) != JIM_OK) { | |
| 18183 | - return JIM_ERR; | |
| 18184 | - } | |
| 18185 | - else { | |
| 18186 | - return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2); | |
| 18187 | - } | |
| 18188 | - | |
| 18189 | - case OPT_WITH: | |
| 18190 | - if (argc < 4) { | |
| 18191 | - Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); | |
| 18192 | - return JIM_ERR; | |
| 18193 | - } | |
| 18194 | - else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) { | |
| 18195 | - return JIM_ERR; | |
| 18196 | - } | |
| 18197 | - else { | |
| 18198 | - return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2); | |
| 18199 | - } | |
| 18432 | + if (Jim_DictSize(interp, argv[2]) < 0) { | |
| 18433 | + return JIM_ERR; | |
| 18434 | + } | |
| 18435 | + | |
| 18436 | + break; | |
| 18437 | + | |
| 18438 | + case OPT_UPDATE: | |
| 18439 | + if (argc < 6 || argc % 2) { | |
| 18440 | + | |
| 18441 | + argc = 2; | |
| 18442 | + } | |
| 18443 | + break; | |
| 18200 | 18444 | |
| 18201 | 18445 | case OPT_CREATE: |
| 18202 | 18446 | if (argc % 2) { |
| 18203 | 18447 | Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); |
| 18204 | 18448 | return JIM_ERR; |
| 18205 | 18449 | } |
| 18206 | 18450 | objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); |
| 18207 | 18451 | Jim_SetResult(interp, objPtr); |
| 18208 | 18452 | return JIM_OK; |
| 18453 | + | |
| 18454 | + case OPT_INFO: | |
| 18455 | + if (argc != 3) { | |
| 18456 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary"); | |
| 18457 | + return JIM_ERR; | |
| 18458 | + } | |
| 18459 | + return Jim_DictInfo(interp, argv[2]); | |
| 18209 | 18460 | } |
| 18210 | - return JIM_ERR; | |
| 18461 | + | |
| 18462 | + return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); | |
| 18211 | 18463 | } |
| 18212 | 18464 | |
| 18213 | 18465 | |
| 18214 | 18466 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18215 | 18467 | { |
| @@ -18267,11 +18519,11 @@ | ||
| 18267 | 18519 | }; |
| 18268 | 18520 | enum |
| 18269 | 18521 | { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, |
| 18270 | 18522 | INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, |
| 18271 | 18523 | INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, |
| 18272 | - INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS | |
| 18524 | + INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, | |
| 18273 | 18525 | }; |
| 18274 | 18526 | |
| 18275 | 18527 | #ifdef jim_ext_namespace |
| 18276 | 18528 | int nons = 0; |
| 18277 | 18529 | |
| @@ -19047,11 +19299,11 @@ | ||
| 19047 | 19299 | } |
| 19048 | 19300 | } |
| 19049 | 19301 | |
| 19050 | 19302 | static const struct { |
| 19051 | 19303 | const char *name; |
| 19052 | - Jim_CmdProc cmdProc; | |
| 19304 | + Jim_CmdProc *cmdProc; | |
| 19053 | 19305 | } Jim_CoreCommandsTable[] = { |
| 19054 | 19306 | {"alias", Jim_AliasCoreCommand}, |
| 19055 | 19307 | {"set", Jim_SetCoreCommand}, |
| 19056 | 19308 | {"unset", Jim_UnsetCoreCommand}, |
| 19057 | 19309 | {"puts", Jim_PutsCoreCommand}, |
| @@ -19279,10 +19531,12 @@ | ||
| 19279 | 19531 | } |
| 19280 | 19532 | |
| 19281 | 19533 | len += extra; |
| 19282 | 19534 | buf = Jim_Alloc(len + 1); |
| 19283 | 19535 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19536 | + | |
| 19537 | + va_end(args); | |
| 19284 | 19538 | |
| 19285 | 19539 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19286 | 19540 | } |
| 19287 | 19541 | |
| 19288 | 19542 | |
| @@ -19530,23 +19784,22 @@ | ||
| 19530 | 19784 | |
| 19531 | 19785 | #include <ctype.h> |
| 19532 | 19786 | #include <string.h> |
| 19533 | 19787 | |
| 19534 | 19788 | |
| 19535 | -#define JIM_UTF_MAX 3 | |
| 19536 | 19789 | #define JIM_INTEGER_SPACE 24 |
| 19537 | 19790 | #define MAX_FLOAT_WIDTH 320 |
| 19538 | 19791 | |
| 19539 | 19792 | Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) |
| 19540 | 19793 | { |
| 19541 | 19794 | const char *span, *format, *formatEnd, *msg; |
| 19542 | 19795 | int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; |
| 19543 | 19796 | static const char * const mixedXPG = |
| 19544 | - "cannot mix \"%\" and \"%n$\" conversion specifiers"; | |
| 19797 | + "cannot mix \"%\" and \"%n$\" conversion specifiers"; | |
| 19545 | 19798 | static const char * const badIndex[2] = { |
| 19546 | - "not enough arguments for all format specifiers", | |
| 19547 | - "\"%n$\" argument index out of range" | |
| 19799 | + "not enough arguments for all format specifiers", | |
| 19800 | + "\"%n$\" argument index out of range" | |
| 19548 | 19801 | }; |
| 19549 | 19802 | int formatLen; |
| 19550 | 19803 | Jim_Obj *resultPtr; |
| 19551 | 19804 | |
| 19552 | 19805 | char *num_buffer = NULL; |
| @@ -19555,319 +19808,349 @@ | ||
| 19555 | 19808 | span = format = Jim_GetString(fmtObjPtr, &formatLen); |
| 19556 | 19809 | formatEnd = format + formatLen; |
| 19557 | 19810 | resultPtr = Jim_NewEmptyStringObj(interp); |
| 19558 | 19811 | |
| 19559 | 19812 | while (format != formatEnd) { |
| 19560 | - char *end; | |
| 19561 | - int gotMinus, sawFlag; | |
| 19562 | - int gotPrecision, useShort; | |
| 19563 | - long width, precision; | |
| 19564 | - int newXpg; | |
| 19565 | - int ch; | |
| 19566 | - int step; | |
| 19567 | - int doubleType; | |
| 19568 | - char pad = ' '; | |
| 19569 | - char spec[2*JIM_INTEGER_SPACE + 12]; | |
| 19570 | - char *p; | |
| 19571 | - | |
| 19572 | - int formatted_chars; | |
| 19573 | - int formatted_bytes; | |
| 19574 | - const char *formatted_buf; | |
| 19575 | - | |
| 19576 | - step = utf8_tounicode(format, &ch); | |
| 19577 | - format += step; | |
| 19578 | - if (ch != '%') { | |
| 19579 | - numBytes += step; | |
| 19580 | - continue; | |
| 19581 | - } | |
| 19582 | - if (numBytes) { | |
| 19583 | - Jim_AppendString(interp, resultPtr, span, numBytes); | |
| 19584 | - numBytes = 0; | |
| 19585 | - } | |
| 19586 | - | |
| 19587 | - | |
| 19588 | - step = utf8_tounicode(format, &ch); | |
| 19589 | - if (ch == '%') { | |
| 19590 | - span = format; | |
| 19591 | - numBytes = step; | |
| 19592 | - format += step; | |
| 19593 | - continue; | |
| 19594 | - } | |
| 19595 | - | |
| 19596 | - | |
| 19597 | - newXpg = 0; | |
| 19598 | - if (isdigit(ch)) { | |
| 19599 | - int position = strtoul(format, &end, 10); | |
| 19600 | - if (*end == '$') { | |
| 19601 | - newXpg = 1; | |
| 19602 | - objIndex = position - 1; | |
| 19603 | - format = end + 1; | |
| 19604 | - step = utf8_tounicode(format, &ch); | |
| 19605 | - } | |
| 19606 | - } | |
| 19607 | - if (newXpg) { | |
| 19608 | - if (gotSequential) { | |
| 19609 | - msg = mixedXPG; | |
| 19610 | - goto errorMsg; | |
| 19611 | - } | |
| 19612 | - gotXpg = 1; | |
| 19613 | - } else { | |
| 19614 | - if (gotXpg) { | |
| 19615 | - msg = mixedXPG; | |
| 19616 | - goto errorMsg; | |
| 19617 | - } | |
| 19618 | - gotSequential = 1; | |
| 19619 | - } | |
| 19620 | - if ((objIndex < 0) || (objIndex >= objc)) { | |
| 19621 | - msg = badIndex[gotXpg]; | |
| 19622 | - goto errorMsg; | |
| 19623 | - } | |
| 19624 | - | |
| 19625 | - p = spec; | |
| 19626 | - *p++ = '%'; | |
| 19627 | - | |
| 19628 | - gotMinus = 0; | |
| 19629 | - sawFlag = 1; | |
| 19630 | - do { | |
| 19631 | - switch (ch) { | |
| 19632 | - case '-': | |
| 19633 | - gotMinus = 1; | |
| 19634 | - break; | |
| 19635 | - case '0': | |
| 19636 | - pad = ch; | |
| 19637 | - break; | |
| 19638 | - case ' ': | |
| 19639 | - case '+': | |
| 19640 | - case '#': | |
| 19641 | - break; | |
| 19642 | - default: | |
| 19643 | - sawFlag = 0; | |
| 19644 | - continue; | |
| 19645 | - } | |
| 19646 | - *p++ = ch; | |
| 19647 | - format += step; | |
| 19648 | - step = utf8_tounicode(format, &ch); | |
| 19649 | - } while (sawFlag); | |
| 19650 | - | |
| 19651 | - | |
| 19652 | - width = 0; | |
| 19653 | - if (isdigit(ch)) { | |
| 19654 | - width = strtoul(format, &end, 10); | |
| 19655 | - format = end; | |
| 19656 | - step = utf8_tounicode(format, &ch); | |
| 19657 | - } else if (ch == '*') { | |
| 19658 | - if (objIndex >= objc - 1) { | |
| 19659 | - msg = badIndex[gotXpg]; | |
| 19660 | - goto errorMsg; | |
| 19661 | - } | |
| 19662 | - if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { | |
| 19663 | - goto error; | |
| 19664 | - } | |
| 19665 | - if (width < 0) { | |
| 19666 | - width = -width; | |
| 19667 | - if (!gotMinus) { | |
| 19668 | - *p++ = '-'; | |
| 19669 | - gotMinus = 1; | |
| 19670 | - } | |
| 19671 | - } | |
| 19672 | - objIndex++; | |
| 19673 | - format += step; | |
| 19674 | - step = utf8_tounicode(format, &ch); | |
| 19675 | - } | |
| 19676 | - | |
| 19677 | - | |
| 19678 | - gotPrecision = precision = 0; | |
| 19679 | - if (ch == '.') { | |
| 19680 | - gotPrecision = 1; | |
| 19681 | - format += step; | |
| 19682 | - step = utf8_tounicode(format, &ch); | |
| 19683 | - } | |
| 19684 | - if (isdigit(ch)) { | |
| 19685 | - precision = strtoul(format, &end, 10); | |
| 19686 | - format = end; | |
| 19687 | - step = utf8_tounicode(format, &ch); | |
| 19688 | - } else if (ch == '*') { | |
| 19689 | - if (objIndex >= objc - 1) { | |
| 19690 | - msg = badIndex[gotXpg]; | |
| 19691 | - goto errorMsg; | |
| 19692 | - } | |
| 19693 | - if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { | |
| 19694 | - goto error; | |
| 19695 | - } | |
| 19696 | - | |
| 19697 | - | |
| 19698 | - if (precision < 0) { | |
| 19699 | - precision = 0; | |
| 19700 | - } | |
| 19701 | - objIndex++; | |
| 19702 | - format += step; | |
| 19703 | - step = utf8_tounicode(format, &ch); | |
| 19704 | - } | |
| 19705 | - | |
| 19706 | - | |
| 19707 | - useShort = 0; | |
| 19708 | - if (ch == 'h') { | |
| 19709 | - useShort = 1; | |
| 19710 | - format += step; | |
| 19711 | - step = utf8_tounicode(format, &ch); | |
| 19712 | - } else if (ch == 'l') { | |
| 19713 | - | |
| 19714 | - format += step; | |
| 19715 | - step = utf8_tounicode(format, &ch); | |
| 19716 | - if (ch == 'l') { | |
| 19717 | - format += step; | |
| 19718 | - step = utf8_tounicode(format, &ch); | |
| 19719 | - } | |
| 19720 | - } | |
| 19721 | - | |
| 19722 | - format += step; | |
| 19723 | - span = format; | |
| 19724 | - | |
| 19725 | - | |
| 19726 | - if (ch == 'i') { | |
| 19727 | - ch = 'd'; | |
| 19728 | - } | |
| 19729 | - | |
| 19730 | - doubleType = 0; | |
| 19731 | - | |
| 19732 | - switch (ch) { | |
| 19733 | - case '\0': | |
| 19734 | - msg = "format string ended in middle of field specifier"; | |
| 19735 | - goto errorMsg; | |
| 19736 | - case 's': { | |
| 19737 | - formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); | |
| 19738 | - formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); | |
| 19739 | - if (gotPrecision && (precision < formatted_chars)) { | |
| 19740 | - | |
| 19741 | - formatted_chars = precision; | |
| 19742 | - formatted_bytes = utf8_index(formatted_buf, precision); | |
| 19743 | - } | |
| 19744 | - break; | |
| 19745 | - } | |
| 19746 | - case 'c': { | |
| 19747 | - jim_wide code; | |
| 19748 | - | |
| 19749 | - if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { | |
| 19750 | - goto error; | |
| 19751 | - } | |
| 19752 | - | |
| 19753 | - formatted_bytes = utf8_fromunicode(spec, code); | |
| 19754 | - formatted_buf = spec; | |
| 19755 | - formatted_chars = 1; | |
| 19756 | - break; | |
| 19757 | - } | |
| 19758 | - | |
| 19759 | - case 'e': | |
| 19760 | - case 'E': | |
| 19761 | - case 'f': | |
| 19762 | - case 'g': | |
| 19763 | - case 'G': | |
| 19764 | - doubleType = 1; | |
| 19765 | - | |
| 19766 | - case 'd': | |
| 19767 | - case 'u': | |
| 19768 | - case 'o': | |
| 19769 | - case 'x': | |
| 19770 | - case 'X': { | |
| 19771 | - jim_wide w; | |
| 19772 | - double d; | |
| 19773 | - int length; | |
| 19774 | - | |
| 19775 | - | |
| 19776 | - if (width) { | |
| 19777 | - p += sprintf(p, "%ld", width); | |
| 19778 | - } | |
| 19779 | - if (gotPrecision) { | |
| 19780 | - p += sprintf(p, ".%ld", precision); | |
| 19781 | - } | |
| 19782 | - | |
| 19783 | - | |
| 19784 | - if (doubleType) { | |
| 19785 | - if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { | |
| 19786 | - goto error; | |
| 19787 | - } | |
| 19788 | - length = MAX_FLOAT_WIDTH; | |
| 19789 | - } | |
| 19790 | - else { | |
| 19791 | - if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { | |
| 19792 | - goto error; | |
| 19793 | - } | |
| 19794 | - length = JIM_INTEGER_SPACE; | |
| 19795 | - if (useShort) { | |
| 19796 | - *p++ = 'h'; | |
| 19797 | - if (ch == 'd') { | |
| 19798 | - w = (short)w; | |
| 19799 | - } | |
| 19800 | - else { | |
| 19801 | - w = (unsigned short)w; | |
| 19802 | - } | |
| 19803 | - } | |
| 19804 | - else { | |
| 19805 | - *p++ = 'l'; | |
| 19806 | -#ifdef HAVE_LONG_LONG | |
| 19807 | - if (sizeof(long long) == sizeof(jim_wide)) { | |
| 19808 | - *p++ = 'l'; | |
| 19809 | - } | |
| 19810 | -#endif | |
| 19811 | - } | |
| 19812 | - } | |
| 19813 | - | |
| 19814 | - *p++ = (char) ch; | |
| 19815 | - *p = '\0'; | |
| 19816 | - | |
| 19817 | - | |
| 19818 | - if (width > length) { | |
| 19819 | - length = width; | |
| 19820 | - } | |
| 19821 | - if (gotPrecision) { | |
| 19822 | - length += precision; | |
| 19823 | - } | |
| 19824 | - | |
| 19825 | - | |
| 19826 | - if (num_buffer_size < length + 1) { | |
| 19827 | - num_buffer_size = length + 1; | |
| 19828 | - num_buffer = Jim_Realloc(num_buffer, num_buffer_size); | |
| 19829 | - } | |
| 19830 | - | |
| 19831 | - if (doubleType) { | |
| 19832 | - snprintf(num_buffer, length + 1, spec, d); | |
| 19833 | - } | |
| 19834 | - else { | |
| 19835 | - formatted_bytes = snprintf(num_buffer, length + 1, spec, w); | |
| 19836 | - } | |
| 19837 | - formatted_chars = formatted_bytes = strlen(num_buffer); | |
| 19838 | - formatted_buf = num_buffer; | |
| 19839 | - break; | |
| 19840 | - } | |
| 19841 | - | |
| 19842 | - default: { | |
| 19843 | - | |
| 19844 | - spec[0] = ch; | |
| 19845 | - spec[1] = '\0'; | |
| 19846 | - Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); | |
| 19847 | - goto error; | |
| 19848 | - } | |
| 19849 | - } | |
| 19850 | - | |
| 19851 | - if (!gotMinus) { | |
| 19852 | - while (formatted_chars < width) { | |
| 19853 | - Jim_AppendString(interp, resultPtr, &pad, 1); | |
| 19854 | - formatted_chars++; | |
| 19855 | - } | |
| 19856 | - } | |
| 19857 | - | |
| 19858 | - Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); | |
| 19859 | - | |
| 19860 | - while (formatted_chars < width) { | |
| 19861 | - Jim_AppendString(interp, resultPtr, &pad, 1); | |
| 19862 | - formatted_chars++; | |
| 19863 | - } | |
| 19864 | - | |
| 19865 | - objIndex += gotSequential; | |
| 19866 | - } | |
| 19867 | - if (numBytes) { | |
| 19868 | - Jim_AppendString(interp, resultPtr, span, numBytes); | |
| 19813 | + char *end; | |
| 19814 | + int gotMinus, sawFlag; | |
| 19815 | + int gotPrecision, useShort; | |
| 19816 | + long width, precision; | |
| 19817 | + int newXpg; | |
| 19818 | + int ch; | |
| 19819 | + int step; | |
| 19820 | + int doubleType; | |
| 19821 | + char pad = ' '; | |
| 19822 | + char spec[2*JIM_INTEGER_SPACE + 12]; | |
| 19823 | + char *p; | |
| 19824 | + | |
| 19825 | + int formatted_chars; | |
| 19826 | + int formatted_bytes; | |
| 19827 | + const char *formatted_buf; | |
| 19828 | + | |
| 19829 | + step = utf8_tounicode(format, &ch); | |
| 19830 | + format += step; | |
| 19831 | + if (ch != '%') { | |
| 19832 | + numBytes += step; | |
| 19833 | + continue; | |
| 19834 | + } | |
| 19835 | + if (numBytes) { | |
| 19836 | + Jim_AppendString(interp, resultPtr, span, numBytes); | |
| 19837 | + numBytes = 0; | |
| 19838 | + } | |
| 19839 | + | |
| 19840 | + | |
| 19841 | + step = utf8_tounicode(format, &ch); | |
| 19842 | + if (ch == '%') { | |
| 19843 | + span = format; | |
| 19844 | + numBytes = step; | |
| 19845 | + format += step; | |
| 19846 | + continue; | |
| 19847 | + } | |
| 19848 | + | |
| 19849 | + | |
| 19850 | + newXpg = 0; | |
| 19851 | + if (isdigit(ch)) { | |
| 19852 | + int position = strtoul(format, &end, 10); | |
| 19853 | + if (*end == '$') { | |
| 19854 | + newXpg = 1; | |
| 19855 | + objIndex = position - 1; | |
| 19856 | + format = end + 1; | |
| 19857 | + step = utf8_tounicode(format, &ch); | |
| 19858 | + } | |
| 19859 | + } | |
| 19860 | + if (newXpg) { | |
| 19861 | + if (gotSequential) { | |
| 19862 | + msg = mixedXPG; | |
| 19863 | + goto errorMsg; | |
| 19864 | + } | |
| 19865 | + gotXpg = 1; | |
| 19866 | + } else { | |
| 19867 | + if (gotXpg) { | |
| 19868 | + msg = mixedXPG; | |
| 19869 | + goto errorMsg; | |
| 19870 | + } | |
| 19871 | + gotSequential = 1; | |
| 19872 | + } | |
| 19873 | + if ((objIndex < 0) || (objIndex >= objc)) { | |
| 19874 | + msg = badIndex[gotXpg]; | |
| 19875 | + goto errorMsg; | |
| 19876 | + } | |
| 19877 | + | |
| 19878 | + p = spec; | |
| 19879 | + *p++ = '%'; | |
| 19880 | + | |
| 19881 | + gotMinus = 0; | |
| 19882 | + sawFlag = 1; | |
| 19883 | + do { | |
| 19884 | + switch (ch) { | |
| 19885 | + case '-': | |
| 19886 | + gotMinus = 1; | |
| 19887 | + break; | |
| 19888 | + case '0': | |
| 19889 | + pad = ch; | |
| 19890 | + break; | |
| 19891 | + case ' ': | |
| 19892 | + case '+': | |
| 19893 | + case '#': | |
| 19894 | + break; | |
| 19895 | + default: | |
| 19896 | + sawFlag = 0; | |
| 19897 | + continue; | |
| 19898 | + } | |
| 19899 | + *p++ = ch; | |
| 19900 | + format += step; | |
| 19901 | + step = utf8_tounicode(format, &ch); | |
| 19902 | + } while (sawFlag); | |
| 19903 | + | |
| 19904 | + | |
| 19905 | + width = 0; | |
| 19906 | + if (isdigit(ch)) { | |
| 19907 | + width = strtoul(format, &end, 10); | |
| 19908 | + format = end; | |
| 19909 | + step = utf8_tounicode(format, &ch); | |
| 19910 | + } else if (ch == '*') { | |
| 19911 | + if (objIndex >= objc - 1) { | |
| 19912 | + msg = badIndex[gotXpg]; | |
| 19913 | + goto errorMsg; | |
| 19914 | + } | |
| 19915 | + if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { | |
| 19916 | + goto error; | |
| 19917 | + } | |
| 19918 | + if (width < 0) { | |
| 19919 | + width = -width; | |
| 19920 | + if (!gotMinus) { | |
| 19921 | + *p++ = '-'; | |
| 19922 | + gotMinus = 1; | |
| 19923 | + } | |
| 19924 | + } | |
| 19925 | + objIndex++; | |
| 19926 | + format += step; | |
| 19927 | + step = utf8_tounicode(format, &ch); | |
| 19928 | + } | |
| 19929 | + | |
| 19930 | + | |
| 19931 | + gotPrecision = precision = 0; | |
| 19932 | + if (ch == '.') { | |
| 19933 | + gotPrecision = 1; | |
| 19934 | + format += step; | |
| 19935 | + step = utf8_tounicode(format, &ch); | |
| 19936 | + } | |
| 19937 | + if (isdigit(ch)) { | |
| 19938 | + precision = strtoul(format, &end, 10); | |
| 19939 | + format = end; | |
| 19940 | + step = utf8_tounicode(format, &ch); | |
| 19941 | + } else if (ch == '*') { | |
| 19942 | + if (objIndex >= objc - 1) { | |
| 19943 | + msg = badIndex[gotXpg]; | |
| 19944 | + goto errorMsg; | |
| 19945 | + } | |
| 19946 | + if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { | |
| 19947 | + goto error; | |
| 19948 | + } | |
| 19949 | + | |
| 19950 | + | |
| 19951 | + if (precision < 0) { | |
| 19952 | + precision = 0; | |
| 19953 | + } | |
| 19954 | + objIndex++; | |
| 19955 | + format += step; | |
| 19956 | + step = utf8_tounicode(format, &ch); | |
| 19957 | + } | |
| 19958 | + | |
| 19959 | + | |
| 19960 | + useShort = 0; | |
| 19961 | + if (ch == 'h') { | |
| 19962 | + useShort = 1; | |
| 19963 | + format += step; | |
| 19964 | + step = utf8_tounicode(format, &ch); | |
| 19965 | + } else if (ch == 'l') { | |
| 19966 | + | |
| 19967 | + format += step; | |
| 19968 | + step = utf8_tounicode(format, &ch); | |
| 19969 | + if (ch == 'l') { | |
| 19970 | + format += step; | |
| 19971 | + step = utf8_tounicode(format, &ch); | |
| 19972 | + } | |
| 19973 | + } | |
| 19974 | + | |
| 19975 | + format += step; | |
| 19976 | + span = format; | |
| 19977 | + | |
| 19978 | + | |
| 19979 | + if (ch == 'i') { | |
| 19980 | + ch = 'd'; | |
| 19981 | + } | |
| 19982 | + | |
| 19983 | + doubleType = 0; | |
| 19984 | + | |
| 19985 | + switch (ch) { | |
| 19986 | + case '\0': | |
| 19987 | + msg = "format string ended in middle of field specifier"; | |
| 19988 | + goto errorMsg; | |
| 19989 | + case 's': { | |
| 19990 | + formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); | |
| 19991 | + formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); | |
| 19992 | + if (gotPrecision && (precision < formatted_chars)) { | |
| 19993 | + | |
| 19994 | + formatted_chars = precision; | |
| 19995 | + formatted_bytes = utf8_index(formatted_buf, precision); | |
| 19996 | + } | |
| 19997 | + break; | |
| 19998 | + } | |
| 19999 | + case 'c': { | |
| 20000 | + jim_wide code; | |
| 20001 | + | |
| 20002 | + if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { | |
| 20003 | + goto error; | |
| 20004 | + } | |
| 20005 | + | |
| 20006 | + formatted_bytes = utf8_getchars(spec, code); | |
| 20007 | + formatted_buf = spec; | |
| 20008 | + formatted_chars = 1; | |
| 20009 | + break; | |
| 20010 | + } | |
| 20011 | + case 'b': { | |
| 20012 | + unsigned jim_wide w; | |
| 20013 | + int length; | |
| 20014 | + int i; | |
| 20015 | + int j; | |
| 20016 | + | |
| 20017 | + if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) { | |
| 20018 | + goto error; | |
| 20019 | + } | |
| 20020 | + length = sizeof(w) * 8; | |
| 20021 | + | |
| 20022 | + | |
| 20023 | + | |
| 20024 | + if (num_buffer_size < length + 1) { | |
| 20025 | + num_buffer_size = length + 1; | |
| 20026 | + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); | |
| 20027 | + } | |
| 20028 | + | |
| 20029 | + j = 0; | |
| 20030 | + for (i = length; i > 0; ) { | |
| 20031 | + i--; | |
| 20032 | + if (w & ((unsigned jim_wide)1 << i)) { | |
| 20033 | + num_buffer[j++] = '1'; | |
| 20034 | + } | |
| 20035 | + else if (j || i == 0) { | |
| 20036 | + num_buffer[j++] = '0'; | |
| 20037 | + } | |
| 20038 | + } | |
| 20039 | + num_buffer[j] = 0; | |
| 20040 | + formatted_chars = formatted_bytes = j; | |
| 20041 | + formatted_buf = num_buffer; | |
| 20042 | + break; | |
| 20043 | + } | |
| 20044 | + | |
| 20045 | + case 'e': | |
| 20046 | + case 'E': | |
| 20047 | + case 'f': | |
| 20048 | + case 'g': | |
| 20049 | + case 'G': | |
| 20050 | + doubleType = 1; | |
| 20051 | + | |
| 20052 | + case 'd': | |
| 20053 | + case 'u': | |
| 20054 | + case 'o': | |
| 20055 | + case 'x': | |
| 20056 | + case 'X': { | |
| 20057 | + jim_wide w; | |
| 20058 | + double d; | |
| 20059 | + int length; | |
| 20060 | + | |
| 20061 | + | |
| 20062 | + if (width) { | |
| 20063 | + p += sprintf(p, "%ld", width); | |
| 20064 | + } | |
| 20065 | + if (gotPrecision) { | |
| 20066 | + p += sprintf(p, ".%ld", precision); | |
| 20067 | + } | |
| 20068 | + | |
| 20069 | + | |
| 20070 | + if (doubleType) { | |
| 20071 | + if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { | |
| 20072 | + goto error; | |
| 20073 | + } | |
| 20074 | + length = MAX_FLOAT_WIDTH; | |
| 20075 | + } | |
| 20076 | + else { | |
| 20077 | + if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { | |
| 20078 | + goto error; | |
| 20079 | + } | |
| 20080 | + length = JIM_INTEGER_SPACE; | |
| 20081 | + if (useShort) { | |
| 20082 | + if (ch == 'd') { | |
| 20083 | + w = (short)w; | |
| 20084 | + } | |
| 20085 | + else { | |
| 20086 | + w = (unsigned short)w; | |
| 20087 | + } | |
| 20088 | + } | |
| 20089 | + *p++ = 'l'; | |
| 20090 | +#ifdef HAVE_LONG_LONG | |
| 20091 | + if (sizeof(long long) == sizeof(jim_wide)) { | |
| 20092 | + *p++ = 'l'; | |
| 20093 | + } | |
| 20094 | +#endif | |
| 20095 | + } | |
| 20096 | + | |
| 20097 | + *p++ = (char) ch; | |
| 20098 | + *p = '\0'; | |
| 20099 | + | |
| 20100 | + | |
| 20101 | + if (width > length) { | |
| 20102 | + length = width; | |
| 20103 | + } | |
| 20104 | + if (gotPrecision) { | |
| 20105 | + length += precision; | |
| 20106 | + } | |
| 20107 | + | |
| 20108 | + | |
| 20109 | + if (num_buffer_size < length + 1) { | |
| 20110 | + num_buffer_size = length + 1; | |
| 20111 | + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); | |
| 20112 | + } | |
| 20113 | + | |
| 20114 | + if (doubleType) { | |
| 20115 | + snprintf(num_buffer, length + 1, spec, d); | |
| 20116 | + } | |
| 20117 | + else { | |
| 20118 | + formatted_bytes = snprintf(num_buffer, length + 1, spec, w); | |
| 20119 | + } | |
| 20120 | + formatted_chars = formatted_bytes = strlen(num_buffer); | |
| 20121 | + formatted_buf = num_buffer; | |
| 20122 | + break; | |
| 20123 | + } | |
| 20124 | + | |
| 20125 | + default: { | |
| 20126 | + | |
| 20127 | + spec[0] = ch; | |
| 20128 | + spec[1] = '\0'; | |
| 20129 | + Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); | |
| 20130 | + goto error; | |
| 20131 | + } | |
| 20132 | + } | |
| 20133 | + | |
| 20134 | + if (!gotMinus) { | |
| 20135 | + while (formatted_chars < width) { | |
| 20136 | + Jim_AppendString(interp, resultPtr, &pad, 1); | |
| 20137 | + formatted_chars++; | |
| 20138 | + } | |
| 20139 | + } | |
| 20140 | + | |
| 20141 | + Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); | |
| 20142 | + | |
| 20143 | + while (formatted_chars < width) { | |
| 20144 | + Jim_AppendString(interp, resultPtr, &pad, 1); | |
| 20145 | + formatted_chars++; | |
| 20146 | + } | |
| 20147 | + | |
| 20148 | + objIndex += gotSequential; | |
| 20149 | + } | |
| 20150 | + if (numBytes) { | |
| 20151 | + Jim_AppendString(interp, resultPtr, span, numBytes); | |
| 19869 | 20152 | } |
| 19870 | 20153 | |
| 19871 | 20154 | Jim_Free(num_buffer); |
| 19872 | 20155 | return resultPtr; |
| 19873 | 20156 | |
| @@ -19876,21 +20159,22 @@ | ||
| 19876 | 20159 | error: |
| 19877 | 20160 | Jim_FreeNewObj(interp, resultPtr); |
| 19878 | 20161 | Jim_Free(num_buffer); |
| 19879 | 20162 | return NULL; |
| 19880 | 20163 | } |
| 20164 | + | |
| 20165 | + | |
| 20166 | +#if defined(JIM_REGEXP) | |
| 19881 | 20167 | #include <stdio.h> |
| 19882 | 20168 | #include <ctype.h> |
| 19883 | 20169 | #include <stdlib.h> |
| 19884 | 20170 | #include <string.h> |
| 19885 | 20171 | |
| 19886 | - | |
| 19887 | -#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP) | |
| 19888 | - | |
| 19889 | 20172 | |
| 19890 | 20173 | |
| 19891 | 20174 | #define REG_MAX_PAREN 100 |
| 20175 | + | |
| 19892 | 20176 | |
| 19893 | 20177 | |
| 19894 | 20178 | #define END 0 |
| 19895 | 20179 | #define BOL 1 |
| 19896 | 20180 | #define EOL 2 |
| @@ -19899,23 +20183,27 @@ | ||
| 19899 | 20183 | #define ANYBUT 5 |
| 19900 | 20184 | #define BRANCH 6 |
| 19901 | 20185 | #define BACK 7 |
| 19902 | 20186 | #define EXACTLY 8 |
| 19903 | 20187 | #define NOTHING 9 |
| 19904 | -#define REP 10 | |
| 20188 | +#define REP 10 | |
| 19905 | 20189 | #define REPMIN 11 |
| 19906 | 20190 | #define REPX 12 |
| 19907 | 20191 | #define REPXMIN 13 |
| 19908 | 20192 | |
| 19909 | 20193 | #define WORDA 15 |
| 19910 | 20194 | #define WORDZ 16 |
| 19911 | -#define OPENNC 19 | |
| 19912 | -#define OPEN 20 | |
| 20195 | + | |
| 20196 | +#define OPENNC 1000 | |
| 20197 | +#define OPEN 1001 | |
| 19913 | 20198 | |
| 19914 | -#define CLOSE (OPEN+REG_MAX_PAREN+1) | |
| 20199 | + | |
| 20200 | + | |
| 20201 | + | |
| 20202 | +#define CLOSENC 2000 | |
| 20203 | +#define CLOSE 2001 | |
| 19915 | 20204 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 19916 | -#define CLOSENC (CLOSE-1) | |
| 19917 | 20205 | |
| 19918 | 20206 | #define REG_MAGIC 0xFADED00D |
| 19919 | 20207 | |
| 19920 | 20208 | |
| 19921 | 20209 | #define OP(preg, p) (preg->program[p]) |
| @@ -19925,15 +20213,15 @@ | ||
| 19925 | 20213 | |
| 19926 | 20214 | |
| 19927 | 20215 | |
| 19928 | 20216 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 19929 | 20217 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 19930 | -#define META "^$.[()|?{+*" | |
| 20218 | +#define META "^$.[()|?{+*" | |
| 19931 | 20219 | |
| 19932 | -#define HASWIDTH 01 | |
| 19933 | -#define SIMPLE 02 | |
| 19934 | -#define SPSTART 04 | |
| 20220 | +#define HASWIDTH 1 | |
| 20221 | +#define SIMPLE 2 | |
| 20222 | +#define SPSTART 4 | |
| 19935 | 20223 | #define WORST 0 |
| 19936 | 20224 | |
| 19937 | 20225 | #define MAX_REP_COUNT 1000000 |
| 19938 | 20226 | |
| 19939 | 20227 | static int reg(regex_t *preg, int paren , int *flagp ); |
| @@ -19942,13 +20230,13 @@ | ||
| 19942 | 20230 | static int regatom(regex_t *preg, int *flagp ); |
| 19943 | 20231 | static int regnode(regex_t *preg, int op ); |
| 19944 | 20232 | static int regnext(regex_t *preg, int p ); |
| 19945 | 20233 | static void regc(regex_t *preg, int b ); |
| 19946 | 20234 | static int reginsert(regex_t *preg, int op, int size, int opnd ); |
| 19947 | -static void regtail_(regex_t *preg, int p, int val, int line ); | |
| 20235 | +static void regtail(regex_t *preg, int p, int val); | |
| 19948 | 20236 | static void regoptail(regex_t *preg, int p, int val ); |
| 19949 | -#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__) | |
| 20237 | +static int regopsize(regex_t *preg, int p ); | |
| 19950 | 20238 | |
| 19951 | 20239 | static int reg_range_find(const int *string, int c); |
| 19952 | 20240 | static const char *str_find(const char *string, int c, int nocase); |
| 19953 | 20241 | static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); |
| 19954 | 20242 | |
| @@ -19985,13 +20273,10 @@ | ||
| 19985 | 20273 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 19986 | 20274 | |
| 19987 | 20275 | |
| 19988 | 20276 | preg->cflags = cflags; |
| 19989 | 20277 | preg->regparse = exp; |
| 19990 | - | |
| 19991 | - preg->program = NULL; | |
| 19992 | - preg->proglen = 0; | |
| 19993 | 20278 | |
| 19994 | 20279 | |
| 19995 | 20280 | preg->proglen = (strlen(exp) + 1) * 5; |
| 19996 | 20281 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 19997 | 20282 | if (preg->program == NULL) |
| @@ -20152,11 +20437,10 @@ | ||
| 20152 | 20437 | { |
| 20153 | 20438 | int ret; |
| 20154 | 20439 | char op; |
| 20155 | 20440 | int next; |
| 20156 | 20441 | int flags; |
| 20157 | - int chain = 0; | |
| 20158 | 20442 | int min; |
| 20159 | 20443 | int max; |
| 20160 | 20444 | |
| 20161 | 20445 | ret = regatom(preg, &flags); |
| 20162 | 20446 | if (ret == 0) |
| @@ -20235,11 +20519,11 @@ | ||
| 20235 | 20519 | if (ISMULT(*preg->regparse)) { |
| 20236 | 20520 | preg->err = REG_ERR_NESTED_COUNT; |
| 20237 | 20521 | return 0; |
| 20238 | 20522 | } |
| 20239 | 20523 | |
| 20240 | - return chain ? chain : ret; | |
| 20524 | + return ret; | |
| 20241 | 20525 | } |
| 20242 | 20526 | |
| 20243 | 20527 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20244 | 20528 | { |
| 20245 | 20529 | if (lower > upper) { |
| @@ -20329,10 +20613,11 @@ | ||
| 20329 | 20613 | break; |
| 20330 | 20614 | case 'U': |
| 20331 | 20615 | if ((n = parse_hex(s, 8, ch)) > 0) { |
| 20332 | 20616 | s += n; |
| 20333 | 20617 | } |
| 20618 | + break; | |
| 20334 | 20619 | case 'x': |
| 20335 | 20620 | if ((n = parse_hex(s, 2, ch)) > 0) { |
| 20336 | 20621 | s += n; |
| 20337 | 20622 | } |
| 20338 | 20623 | break; |
| @@ -20577,10 +20862,11 @@ | ||
| 20577 | 20862 | |
| 20578 | 20863 | static int regnode(regex_t *preg, int op) |
| 20579 | 20864 | { |
| 20580 | 20865 | reg_grow(preg, 2); |
| 20581 | 20866 | |
| 20867 | + | |
| 20582 | 20868 | preg->program[preg->p++] = op; |
| 20583 | 20869 | preg->program[preg->p++] = 0; |
| 20584 | 20870 | |
| 20585 | 20871 | |
| 20586 | 20872 | return preg->p - 2; |
| @@ -20606,11 +20892,11 @@ | ||
| 20606 | 20892 | preg->p += size; |
| 20607 | 20893 | |
| 20608 | 20894 | return opnd + size; |
| 20609 | 20895 | } |
| 20610 | 20896 | |
| 20611 | -static void regtail_(regex_t *preg, int p, int val, int line ) | |
| 20897 | +static void regtail(regex_t *preg, int p, int val) | |
| 20612 | 20898 | { |
| 20613 | 20899 | int scan; |
| 20614 | 20900 | int temp; |
| 20615 | 20901 | int offset; |
| 20616 | 20902 | |
| @@ -20669,36 +20955,16 @@ | ||
| 20669 | 20955 | preg->pmatch = pmatch; |
| 20670 | 20956 | preg->nmatch = nmatch; |
| 20671 | 20957 | preg->start = string; |
| 20672 | 20958 | |
| 20673 | 20959 | |
| 20674 | - for (scan = OPERAND(1); scan != 0; ) { | |
| 20675 | - switch (OP(preg, scan)) { | |
| 20676 | - case REP: | |
| 20677 | - case REPMIN: | |
| 20678 | - case REPX: | |
| 20679 | - case REPXMIN: | |
| 20680 | - preg->program[scan + 4] = 0; | |
| 20681 | - scan += 5; | |
| 20682 | - break; | |
| 20683 | - | |
| 20684 | - case ANYOF: | |
| 20685 | - case ANYBUT: | |
| 20686 | - case EXACTLY: | |
| 20687 | - scan += 2; | |
| 20688 | - while (preg->program[scan++]) { | |
| 20689 | - } | |
| 20690 | - break; | |
| 20691 | - | |
| 20692 | - case END: | |
| 20693 | - scan = 0; | |
| 20694 | - break; | |
| 20695 | - | |
| 20696 | - default: | |
| 20697 | - scan += 2; | |
| 20698 | - break; | |
| 20699 | - } | |
| 20960 | + for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { | |
| 20961 | + int op = OP(preg, scan); | |
| 20962 | + if (op == END) | |
| 20963 | + break; | |
| 20964 | + if (op == REPX || op == REPXMIN) | |
| 20965 | + preg->program[scan + 4] = 0; | |
| 20700 | 20966 | } |
| 20701 | 20967 | |
| 20702 | 20968 | |
| 20703 | 20969 | if (preg->regmust != 0) { |
| 20704 | 20970 | s = string; |
| @@ -20950,10 +21216,11 @@ | ||
| 20950 | 21216 | |
| 20951 | 21217 | static int regmatch(regex_t *preg, int prog) |
| 20952 | 21218 | { |
| 20953 | 21219 | int scan; |
| 20954 | 21220 | int next; |
| 21221 | + const char *save; | |
| 20955 | 21222 | |
| 20956 | 21223 | scan = prog; |
| 20957 | 21224 | |
| 20958 | 21225 | #ifdef DEBUG |
| 20959 | 21226 | if (scan != 0 && regnarrate) |
| @@ -21038,27 +21305,24 @@ | ||
| 21038 | 21305 | break; |
| 21039 | 21306 | case NOTHING: |
| 21040 | 21307 | break; |
| 21041 | 21308 | case BACK: |
| 21042 | 21309 | break; |
| 21043 | - case BRANCH: { | |
| 21044 | - const char *save; | |
| 21045 | - | |
| 21046 | - if (OP(preg, next) != BRANCH) | |
| 21047 | - next = OPERAND(scan); | |
| 21048 | - else { | |
| 21049 | - do { | |
| 21050 | - save = preg->reginput; | |
| 21051 | - if (regmatch(preg, OPERAND(scan))) { | |
| 21052 | - return(1); | |
| 21053 | - } | |
| 21054 | - preg->reginput = save; | |
| 21055 | - scan = regnext(preg, scan); | |
| 21056 | - } while (scan != 0 && OP(preg, scan) == BRANCH); | |
| 21057 | - return(0); | |
| 21058 | - | |
| 21059 | - } | |
| 21310 | + case BRANCH: | |
| 21311 | + if (OP(preg, next) != BRANCH) | |
| 21312 | + next = OPERAND(scan); | |
| 21313 | + else { | |
| 21314 | + do { | |
| 21315 | + save = preg->reginput; | |
| 21316 | + if (regmatch(preg, OPERAND(scan))) { | |
| 21317 | + return(1); | |
| 21318 | + } | |
| 21319 | + preg->reginput = save; | |
| 21320 | + scan = regnext(preg, scan); | |
| 21321 | + } while (scan != 0 && OP(preg, scan) == BRANCH); | |
| 21322 | + return(0); | |
| 21323 | + | |
| 21060 | 21324 | } |
| 21061 | 21325 | break; |
| 21062 | 21326 | case REP: |
| 21063 | 21327 | case REPMIN: |
| 21064 | 21328 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21066,43 +21330,35 @@ | ||
| 21066 | 21330 | case REPX: |
| 21067 | 21331 | case REPXMIN: |
| 21068 | 21332 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21069 | 21333 | |
| 21070 | 21334 | case END: |
| 21071 | - return(1); | |
| 21072 | - break; | |
| 21335 | + return 1; | |
| 21073 | 21336 | |
| 21074 | 21337 | case OPENNC: |
| 21075 | 21338 | case CLOSENC: |
| 21076 | - if (regmatch(preg, next)) { | |
| 21077 | - return 1; | |
| 21078 | - } | |
| 21079 | - return 0; | |
| 21339 | + return regmatch(preg, next); | |
| 21080 | 21340 | |
| 21081 | 21341 | default: |
| 21082 | 21342 | if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { |
| 21083 | - const char *save; | |
| 21084 | - | |
| 21085 | 21343 | save = preg->reginput; |
| 21086 | - | |
| 21087 | 21344 | if (regmatch(preg, next)) { |
| 21088 | - int no; | |
| 21089 | 21345 | if (OP(preg, scan) < CLOSE) { |
| 21090 | - no = OP(preg, scan) - OPEN; | |
| 21346 | + int no = OP(preg, scan) - OPEN; | |
| 21091 | 21347 | if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { |
| 21092 | 21348 | preg->pmatch[no].rm_so = save - preg->start; |
| 21093 | 21349 | } |
| 21094 | 21350 | } |
| 21095 | 21351 | else { |
| 21096 | - no = OP(preg, scan) - CLOSE; | |
| 21352 | + int no = OP(preg, scan) - CLOSE; | |
| 21097 | 21353 | if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { |
| 21098 | 21354 | preg->pmatch[no].rm_eo = save - preg->start; |
| 21099 | 21355 | } |
| 21100 | 21356 | } |
| 21101 | 21357 | return(1); |
| 21102 | - } else | |
| 21103 | - return(0); | |
| 21358 | + } | |
| 21359 | + return(0); | |
| 21104 | 21360 | } |
| 21105 | 21361 | return REG_ERR_INTERNAL; |
| 21106 | 21362 | } |
| 21107 | 21363 | |
| 21108 | 21364 | scan = next; |
| @@ -21181,10 +21437,32 @@ | ||
| 21181 | 21437 | if (OP(preg, p) == BACK) |
| 21182 | 21438 | return(p-offset); |
| 21183 | 21439 | else |
| 21184 | 21440 | return(p+offset); |
| 21185 | 21441 | } |
| 21442 | + | |
| 21443 | +static int regopsize(regex_t *preg, int p ) | |
| 21444 | +{ | |
| 21445 | + | |
| 21446 | + switch (OP(preg, p)) { | |
| 21447 | + case REP: | |
| 21448 | + case REPMIN: | |
| 21449 | + case REPX: | |
| 21450 | + case REPXMIN: | |
| 21451 | + return 5; | |
| 21452 | + | |
| 21453 | + case ANYOF: | |
| 21454 | + case ANYBUT: | |
| 21455 | + case EXACTLY: { | |
| 21456 | + int s = p + 2; | |
| 21457 | + while (preg->program[s++]) { | |
| 21458 | + } | |
| 21459 | + return s - p; | |
| 21460 | + } | |
| 21461 | + } | |
| 21462 | + return 2; | |
| 21463 | +} | |
| 21186 | 21464 | |
| 21187 | 21465 | |
| 21188 | 21466 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 21189 | 21467 | { |
| 21190 | 21468 | static const char *error_strings[] = { |
| @@ -21359,19 +21637,24 @@ | ||
| 21359 | 21637 | char *Jim_HistoryGetline(const char *prompt) |
| 21360 | 21638 | { |
| 21361 | 21639 | #ifdef USE_LINENOISE |
| 21362 | 21640 | return linenoise(prompt); |
| 21363 | 21641 | #else |
| 21642 | + int len; | |
| 21364 | 21643 | char *line = malloc(MAX_LINE_LEN); |
| 21365 | 21644 | |
| 21366 | 21645 | fputs(prompt, stdout); |
| 21367 | 21646 | fflush(stdout); |
| 21368 | 21647 | |
| 21369 | 21648 | if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { |
| 21370 | 21649 | free(line); |
| 21371 | 21650 | return NULL; |
| 21372 | 21651 | } |
| 21652 | + len = strlen(line); | |
| 21653 | + if (len && line[len - 1] == '\n') { | |
| 21654 | + line[len - 1] = '\0'; | |
| 21655 | + } | |
| 21373 | 21656 | return line; |
| 21374 | 21657 | #endif |
| 21375 | 21658 | } |
| 21376 | 21659 | |
| 21377 | 21660 | void Jim_HistoryLoad(const char *filename) |
| @@ -21422,11 +21705,11 @@ | ||
| 21422 | 21705 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 21423 | 21706 | Jim_HistoryLoad(history_file); |
| 21424 | 21707 | } |
| 21425 | 21708 | #endif |
| 21426 | 21709 | |
| 21427 | - printf("Welcome to Jim version %d.%d" JIM_NL, | |
| 21710 | + printf("Welcome to Jim version %d.%d\n", | |
| 21428 | 21711 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 21429 | 21712 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| 21430 | 21713 | |
| 21431 | 21714 | while (1) { |
| 21432 | 21715 | Jim_Obj *scriptObjPtr; |
| @@ -21534,10 +21817,16 @@ | ||
| 21534 | 21817 | } |
| 21535 | 21818 | |
| 21536 | 21819 | Jim_SetVariableStr(interp, "argv", listObj); |
| 21537 | 21820 | Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); |
| 21538 | 21821 | } |
| 21822 | + | |
| 21823 | +static void JimPrintErrorMessage(Jim_Interp *interp) | |
| 21824 | +{ | |
| 21825 | + Jim_MakeErrorMessage(interp); | |
| 21826 | + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); | |
| 21827 | +} | |
| 21539 | 21828 | |
| 21540 | 21829 | int main(int argc, char *const argv[]) |
| 21541 | 21830 | { |
| 21542 | 21831 | int retcode; |
| 21543 | 21832 | Jim_Interp *interp; |
| @@ -21551,22 +21840,20 @@ | ||
| 21551 | 21840 | interp = Jim_CreateInterp(); |
| 21552 | 21841 | Jim_RegisterCoreCommands(interp); |
| 21553 | 21842 | |
| 21554 | 21843 | |
| 21555 | 21844 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 21556 | - Jim_MakeErrorMessage(interp); | |
| 21557 | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); | |
| 21845 | + JimPrintErrorMessage(interp); | |
| 21558 | 21846 | } |
| 21559 | 21847 | |
| 21560 | 21848 | Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); |
| 21561 | 21849 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 21562 | 21850 | retcode = Jim_initjimshInit(interp); |
| 21563 | 21851 | |
| 21564 | 21852 | if (argc == 1) { |
| 21565 | 21853 | if (retcode == JIM_ERR) { |
| 21566 | - Jim_MakeErrorMessage(interp); | |
| 21567 | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); | |
| 21854 | + JimPrintErrorMessage(interp); | |
| 21568 | 21855 | } |
| 21569 | 21856 | if (retcode != JIM_EXIT) { |
| 21570 | 21857 | JimSetArgv(interp, 0, NULL); |
| 21571 | 21858 | retcode = Jim_InteractivePrompt(interp); |
| 21572 | 21859 | } |
| @@ -21583,12 +21870,11 @@ | ||
| 21583 | 21870 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 21584 | 21871 | JimSetArgv(interp, argc - 2, argv + 2); |
| 21585 | 21872 | retcode = Jim_EvalFile(interp, argv[1]); |
| 21586 | 21873 | } |
| 21587 | 21874 | if (retcode == JIM_ERR) { |
| 21588 | - Jim_MakeErrorMessage(interp); | |
| 21589 | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); | |
| 21875 | + JimPrintErrorMessage(interp); | |
| 21590 | 21876 | } |
| 21591 | 21877 | } |
| 21592 | 21878 | if (retcode == JIM_EXIT) { |
| 21593 | 21879 | retcode = Jim_GetExitCode(interp); |
| 21594 | 21880 | } |
| 21595 | 21881 |
| --- autosetup/jimsh0.c | |
| +++ autosetup/jimsh0.c | |
| @@ -1,6 +1,6 @@ | |
| 1 | /* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */ |
| 2 | #define _GNU_SOURCE |
| 3 | #define JIM_TCL_COMPAT |
| 4 | #define JIM_REFERENCES |
| 5 | #define JIM_ANSIC |
| 6 | #define JIM_REGEXP |
| @@ -47,10 +47,14 @@ | |
| 47 | #define JIM_VERSION 75 |
| 48 | #ifndef JIM_WIN32COMPAT_H |
| 49 | #define JIM_WIN32COMPAT_H |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | #if defined(_WIN32) || defined(WIN32) |
| 55 | |
| 56 | #define HAVE_DLOPEN |
| @@ -106,17 +110,31 @@ | |
| 106 | } DIR; |
| 107 | |
| 108 | DIR *opendir(const char *name); |
| 109 | int closedir(DIR *dir); |
| 110 | struct dirent *readdir(DIR *dir); |
| 111 | #endif |
| 112 | |
| 113 | #endif |
| 114 | |
| 115 | #endif |
| 116 | #ifndef UTF8_UTIL_H |
| 117 | #define UTF8_UTIL_H |
| 118 | |
| 119 | |
| 120 | #define MAX_UTF8_LEN 4 |
| 121 | |
| 122 | int utf8_fromunicode(char *p, unsigned uc); |
| @@ -125,10 +143,11 @@ | |
| 125 | #include <ctype.h> |
| 126 | |
| 127 | |
| 128 | #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) |
| 129 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 130 | #define utf8_upper(C) toupper(C) |
| 131 | #define utf8_title(C) toupper(C) |
| 132 | #define utf8_lower(C) tolower(C) |
| 133 | #define utf8_index(C, I) (I) |
| 134 | #define utf8_charlen(C) 1 |
| @@ -135,10 +154,14 @@ | |
| 135 | #define utf8_prev_len(S, L) 1 |
| 136 | |
| 137 | #else |
| 138 | |
| 139 | #endif |
| 140 | |
| 141 | #endif |
| 142 | |
| 143 | #ifndef __JIM__H |
| 144 | #define __JIM__H |
| @@ -199,44 +222,34 @@ | |
| 199 | #define JIM_EVAL 7 |
| 200 | |
| 201 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 202 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 203 | |
| 204 | #define JIM_NONE 0 |
| 205 | #define JIM_ERRMSG 1 |
| 206 | |
| 207 | #define JIM_UNSHARED 4 |
| 208 | #define JIM_MUSTEXIST 8 |
| 209 | |
| 210 | |
| 211 | #define JIM_GLOBAL_ONLY 0x100 |
| 212 | |
| 213 | |
| 214 | #define JIM_SUBST_NOVAR 1 |
| 215 | #define JIM_SUBST_NOCMD 2 |
| 216 | #define JIM_SUBST_NOESC 4 |
| 217 | #define JIM_SUBST_FLAG 128 |
| 218 | |
| 219 | |
| 220 | #define JIM_NOTUSED(V) ((void) V) |
| 221 | |
| 222 | |
| 223 | #define JIM_ENUM_ABBREV 2 |
| 224 | |
| 225 | |
| 226 | #define JIM_CASESENS 0 |
| 227 | #define JIM_NOCASE 1 |
| 228 | |
| 229 | |
| 230 | #define JIM_PATH_LEN 1024 |
| 231 | |
| 232 | |
| 233 | #ifdef JIM_CRLF |
| 234 | #define JIM_NL "\r\n" |
| 235 | #else |
| 236 | #define JIM_NL "\n" |
| 237 | #endif |
| 238 | |
| 239 | #define JIM_LIBPATH "auto_path" |
| 240 | #define JIM_INTERACTIVE "tcl_interactive" |
| 241 | |
| 242 | |
| @@ -266,21 +279,22 @@ | |
| 266 | } Jim_HashTableType; |
| 267 | |
| 268 | typedef struct Jim_HashTable { |
| 269 | Jim_HashEntry **table; |
| 270 | const Jim_HashTableType *type; |
| 271 | unsigned int size; |
| 272 | unsigned int sizemask; |
| 273 | unsigned int used; |
| 274 | unsigned int collisions; |
| 275 | void *privdata; |
| 276 | } Jim_HashTable; |
| 277 | |
| 278 | typedef struct Jim_HashTableIterator { |
| 279 | Jim_HashTable *ht; |
| 280 | int index; |
| 281 | Jim_HashEntry *entry, *nextEntry; |
| 282 | } Jim_HashTableIterator; |
| 283 | |
| 284 | |
| 285 | #define JIM_HT_INITIAL_SIZE 16 |
| 286 | |
| @@ -289,35 +303,35 @@ | |
| 289 | if ((ht)->type->valDestructor) \ |
| 290 | (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) |
| 291 | |
| 292 | #define Jim_SetHashVal(ht, entry, _val_) do { \ |
| 293 | if ((ht)->type->valDup) \ |
| 294 | entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ |
| 295 | else \ |
| 296 | entry->u.val = (_val_); \ |
| 297 | } while(0) |
| 298 | |
| 299 | #define Jim_FreeEntryKey(ht, entry) \ |
| 300 | if ((ht)->type->keyDestructor) \ |
| 301 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) |
| 302 | |
| 303 | #define Jim_SetHashKey(ht, entry, _key_) do { \ |
| 304 | if ((ht)->type->keyDup) \ |
| 305 | entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ |
| 306 | else \ |
| 307 | entry->key = (void *)(_key_); \ |
| 308 | } while(0) |
| 309 | |
| 310 | #define Jim_CompareHashKeys(ht, key1, key2) \ |
| 311 | (((ht)->type->keyCompare) ? \ |
| 312 | (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ |
| 313 | (key1) == (key2)) |
| 314 | |
| 315 | #define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) |
| 316 | |
| 317 | #define Jim_GetHashEntryKey(he) ((he)->key) |
| 318 | #define Jim_GetHashEntryVal(he) ((he)->val) |
| 319 | #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) |
| 320 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 321 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 322 | |
| 323 | |
| @@ -341,19 +355,19 @@ | |
| 341 | void *ptr1; |
| 342 | void *ptr2; |
| 343 | } twoPtrValue; |
| 344 | |
| 345 | struct { |
| 346 | unsigned long callFrameId; |
| 347 | struct Jim_Var *varPtr; |
| 348 | int global; |
| 349 | } varValue; |
| 350 | |
| 351 | struct { |
| 352 | unsigned long procEpoch; |
| 353 | struct Jim_Obj *nsObj; |
| 354 | struct Jim_Cmd *cmdPtr; |
| 355 | } cmdValue; |
| 356 | |
| 357 | struct { |
| 358 | struct Jim_Obj **ele; |
| 359 | int len; |
| @@ -379,12 +393,12 @@ | |
| 379 | struct Jim_Obj *varNameObjPtr; |
| 380 | struct Jim_Obj *indexObjPtr; |
| 381 | } dictSubstValue; |
| 382 | |
| 383 | struct { |
| 384 | unsigned flags; |
| 385 | void *compre; |
| 386 | } regexpValue; |
| 387 | struct { |
| 388 | int line; |
| 389 | int argc; |
| 390 | } scriptLineValue; |
| @@ -453,21 +467,24 @@ | |
| 453 | struct Jim_CallFrame *next; |
| 454 | Jim_Obj *nsObj; |
| 455 | Jim_Obj *fileNameObj; |
| 456 | int line; |
| 457 | Jim_Stack *localCommands; |
| 458 | } Jim_CallFrame; |
| 459 | |
| 460 | typedef struct Jim_Var { |
| 461 | Jim_Obj *objPtr; |
| 462 | struct Jim_CallFrame *linkFramePtr; |
| 463 | } Jim_Var; |
| 464 | |
| 465 | |
| 466 | typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, |
| 467 | Jim_Obj *const *argv); |
| 468 | typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); |
| 469 | |
| 470 | |
| 471 | |
| 472 | typedef struct Jim_Cmd { |
| 473 | int inUse; |
| @@ -474,12 +491,12 @@ | |
| 474 | int isproc; |
| 475 | struct Jim_Cmd *prevCmd; |
| 476 | union { |
| 477 | struct { |
| 478 | |
| 479 | Jim_CmdProc cmdProc; |
| 480 | Jim_DelCmdProc delProc; |
| 481 | void *privData; |
| 482 | } native; |
| 483 | struct { |
| 484 | |
| 485 | Jim_Obj *argListObjPtr; |
| @@ -589,15 +606,11 @@ | |
| 589 | Jim_Obj *finalizerCmdNamePtr; |
| 590 | char tag[JIM_REFERENCE_TAGLEN+1]; |
| 591 | } Jim_Reference; |
| 592 | |
| 593 | |
| 594 | |
| 595 | #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) |
| 596 | |
| 597 | |
| 598 | |
| 599 | #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) |
| 600 | |
| 601 | #define JIM_EXPORT |
| 602 | |
| 603 | |
| @@ -608,10 +621,11 @@ | |
| 608 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 609 | |
| 610 | |
| 611 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 612 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 613 | |
| 614 | |
| 615 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 616 | |
| 617 | |
| @@ -739,13 +753,12 @@ | |
| 739 | JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, |
| 740 | const char *name, const char *val); |
| 741 | JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, |
| 742 | Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, |
| 743 | Jim_CallFrame *targetCallFrame); |
| 744 | JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp, |
| 745 | Jim_Obj *varNameObj, Jim_Obj *targetNameObj); |
| 746 | JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp); |
| 747 | JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, |
| 748 | Jim_Obj *nameObjPtr, int flags); |
| 749 | JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, |
| 750 | Jim_Obj *nameObjPtr, int flags); |
| 751 | JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, |
| @@ -804,10 +817,11 @@ | |
| 804 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 805 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 806 | JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); |
| 807 | JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); |
| 808 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 809 | |
| 810 | |
| 811 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 812 | int *intPtr); |
| 813 | |
| @@ -869,19 +883,19 @@ | |
| 869 | |
| 870 | |
| 871 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| 872 | JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); |
| 873 | JIM_EXPORT int Jim_IsBigEndian(void); |
| 874 | #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) |
| 875 | |
| 876 | |
| 877 | JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); |
| 878 | JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); |
| 879 | |
| 880 | |
| 881 | JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 882 | |
| 883 | |
| 884 | |
| 885 | JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); |
| 886 | JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); |
| 887 | |
| @@ -903,16 +917,16 @@ | |
| 903 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 904 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 905 | |
| 906 | |
| 907 | |
| 908 | typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 909 | |
| 910 | typedef struct { |
| 911 | const char *cmd; |
| 912 | const char *args; |
| 913 | tclmod_cmd_function *function; |
| 914 | short minargs; |
| 915 | short maxargs; |
| 916 | unsigned short flags; |
| 917 | } jim_subcmd_type; |
| 918 | |
| @@ -929,22 +943,16 @@ | |
| 929 | |
| 930 | #endif |
| 931 | #ifndef JIMREGEXP_H |
| 932 | #define JIMREGEXP_H |
| 933 | |
| 934 | #ifndef _JIMAUTOCONF_H |
| 935 | #error Need jimautoconf.h |
| 936 | #endif |
| 937 | |
| 938 | #if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP) |
| 939 | |
| 940 | #include <regex.h> |
| 941 | |
| 942 | #else |
| 943 | |
| 944 | #include <stdlib.h> |
| 945 | |
| 946 | |
| 947 | typedef struct { |
| 948 | int rm_so; |
| 949 | int rm_eo; |
| 950 | } regmatch_t; |
| @@ -1013,10 +1021,12 @@ | |
| 1013 | int regcomp(regex_t *preg, const char *regex, int cflags); |
| 1014 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1015 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1016 | void regfree(regex_t *preg); |
| 1017 | |
| 1018 | #endif |
| 1019 | |
| 1020 | #endif |
| 1021 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1022 | { |
| @@ -1079,10 +1089,15 @@ | |
| 1079 | "\n" |
| 1080 | "package require readdir\n" |
| 1081 | "\n" |
| 1082 | "\n" |
| 1083 | "proc glob.globdir {dir pattern} {\n" |
| 1084 | " set result {}\n" |
| 1085 | " set files [readdir $dir]\n" |
| 1086 | " lappend files . ..\n" |
| 1087 | "\n" |
| 1088 | " foreach name $files {\n" |
| @@ -1261,10 +1276,12 @@ | |
| 1261 | { |
| 1262 | if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) |
| 1263 | return JIM_ERR; |
| 1264 | |
| 1265 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1266 | "\n" |
| 1267 | "proc lambda {arglist args} {\n" |
| 1268 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1269 | "}\n" |
| 1270 | "\n" |
| @@ -1290,46 +1307,48 @@ | |
| 1290 | "}\n" |
| 1291 | "\n" |
| 1292 | "\n" |
| 1293 | "\n" |
| 1294 | "\n" |
| 1295 | "proc stacktrace {} {\n" |
| 1296 | " set trace {}\n" |
| 1297 | " foreach level [range 1 [info level]] {\n" |
| 1298 | " lassign [info frame -$level] p f l\n" |
| 1299 | " lappend trace $p $f $l\n" |
| 1300 | " }\n" |
| 1301 | " return $trace\n" |
| 1302 | "}\n" |
| 1303 | "\n" |
| 1304 | "\n" |
| 1305 | "proc stackdump {stacktrace} {\n" |
| 1306 | " set result {}\n" |
| 1307 | " set count 0\n" |
| 1308 | " foreach {l f p} [lreverse $stacktrace] {\n" |
| 1309 | " if {$count} {\n" |
| 1310 | " append result \\n\n" |
| 1311 | " }\n" |
| 1312 | " incr count\n" |
| 1313 | " if {$p ne \"\"} {\n" |
| 1314 | " append result \"in procedure '$p' \"\n" |
| 1315 | " if {$f ne \"\"} {\n" |
| 1316 | " append result \"called \"\n" |
| 1317 | " }\n" |
| 1318 | " }\n" |
| 1319 | " if {$f ne \"\"} {\n" |
| 1320 | " append result \"at file \\\"$f\\\", line $l\"\n" |
| 1321 | " }\n" |
| 1322 | " }\n" |
| 1323 | " return $result\n" |
| 1324 | "}\n" |
| 1325 | "\n" |
| 1326 | "\n" |
| 1327 | "\n" |
| 1328 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1329 | " if {$stacktrace eq \"\"} {\n" |
| 1330 | " set stacktrace [info stacktrace]\n" |
| 1331 | " }\n" |
| 1332 | " lassign $stacktrace p f l\n" |
| 1333 | " if {$f ne \"\"} {\n" |
| 1334 | " set result \"Runtime Error: $f:$l: \"\n" |
| 1335 | " }\n" |
| @@ -1356,25 +1375,46 @@ | |
| 1356 | " }\n" |
| 1357 | " return \"\"\n" |
| 1358 | "}\n" |
| 1359 | "\n" |
| 1360 | "\n" |
| 1361 | "proc {dict with} {dictVar args script} {\n" |
| 1362 | " upvar $dictVar dict\n" |
| 1363 | " set keys {}\n" |
| 1364 | " foreach {n v} [dict get $dict {*}$args] {\n" |
| 1365 | " upvar $n var_$n\n" |
| 1366 | " set var_$n $v\n" |
| 1367 | " lappend keys $n\n" |
| 1368 | " }\n" |
| 1369 | " catch {uplevel 1 $script} msg opts\n" |
| 1370 | " if {[info exists dict] && [dict exists $dict {*}$args]} {\n" |
| 1371 | " foreach n $keys {\n" |
| 1372 | " if {[info exists var_$n]} {\n" |
| 1373 | " dict set dict {*}$args $n [set var_$n]\n" |
| 1374 | " } else {\n" |
| 1375 | " dict unset dict {*}$args $n\n" |
| 1376 | " }\n" |
| 1377 | " }\n" |
| 1378 | " }\n" |
| 1379 | " return {*}$opts $msg\n" |
| 1380 | "}\n" |
| @@ -1389,10 +1429,69 @@ | |
| 1389 | " dict set dict $k $v\n" |
| 1390 | " }\n" |
| 1391 | " }\n" |
| 1392 | " return $dict\n" |
| 1393 | "}\n" |
| 1394 | ); |
| 1395 | } |
| 1396 | int Jim_tclcompatInit(Jim_Interp *interp) |
| 1397 | { |
| 1398 | if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG)) |
| @@ -1403,12 +1502,14 @@ | |
| 1403 | "\n" |
| 1404 | "\n" |
| 1405 | "\n" |
| 1406 | "\n" |
| 1407 | "\n" |
| 1408 | "\n" |
| 1409 | "set env [env]\n" |
| 1410 | "\n" |
| 1411 | "if {[info commands stdout] ne \"\"} {\n" |
| 1412 | "\n" |
| 1413 | " foreach p {gets flush close eof seek tell} {\n" |
| 1414 | " proc $p {chan args} {p} {\n" |
| @@ -1455,51 +1556,10 @@ | |
| 1455 | " }\n" |
| 1456 | " }\n" |
| 1457 | " }\n" |
| 1458 | "}\n" |
| 1459 | "\n" |
| 1460 | "\n" |
| 1461 | "proc case {var args} {\n" |
| 1462 | "\n" |
| 1463 | " if {[lindex $args 0] eq \"in\"} {\n" |
| 1464 | " set args [lrange $args 1 end]\n" |
| 1465 | " }\n" |
| 1466 | "\n" |
| 1467 | "\n" |
| 1468 | " if {[llength $args] == 1} {\n" |
| 1469 | " set args [lindex $args 0]\n" |
| 1470 | " }\n" |
| 1471 | "\n" |
| 1472 | "\n" |
| 1473 | " if {[llength $args] % 2 != 0} {\n" |
| 1474 | " return -code error \"extra case pattern with no body\"\n" |
| 1475 | " }\n" |
| 1476 | "\n" |
| 1477 | "\n" |
| 1478 | " local proc case.checker {value pattern} {\n" |
| 1479 | " string match $pattern $value\n" |
| 1480 | " }\n" |
| 1481 | "\n" |
| 1482 | " foreach {value action} $args {\n" |
| 1483 | " if {$value eq \"default\"} {\n" |
| 1484 | " set do_action $action\n" |
| 1485 | " continue\n" |
| 1486 | " } elseif {[lsearch -bool -command case.checker $value $var]} {\n" |
| 1487 | " set do_action $action\n" |
| 1488 | " break\n" |
| 1489 | " }\n" |
| 1490 | " }\n" |
| 1491 | "\n" |
| 1492 | " if {[info exists do_action]} {\n" |
| 1493 | " set rc [catch [list uplevel 1 $do_action] result opts]\n" |
| 1494 | " if {$rc} {\n" |
| 1495 | " incr opts(-level)\n" |
| 1496 | " }\n" |
| 1497 | " return {*}$opts $result\n" |
| 1498 | " }\n" |
| 1499 | "}\n" |
| 1500 | "\n" |
| 1501 | "\n" |
| 1502 | "proc fileevent {args} {\n" |
| 1503 | " tailcall {*}$args\n" |
| 1504 | "}\n" |
| 1505 | "\n" |
| @@ -1529,13 +1589,25 @@ | |
| 1529 | " error \"bad option \\\"$force\\\": should be -force\"\n" |
| 1530 | " }\n" |
| 1531 | "\n" |
| 1532 | " set in [open $source]\n" |
| 1533 | "\n" |
| 1534 | " if {$force eq \"\" && [file exists $target]} {\n" |
| 1535 | " $in close\n" |
| 1536 | " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" |
| 1537 | " }\n" |
| 1538 | " set out [open $target w]\n" |
| 1539 | " $in copyto $out\n" |
| 1540 | " $out close\n" |
| 1541 | " } on error {msg opts} {\n" |
| @@ -1580,18 +1652,18 @@ | |
| 1580 | " error $error\n" |
| 1581 | " }\n" |
| 1582 | "}\n" |
| 1583 | "\n" |
| 1584 | "\n" |
| 1585 | "local proc pid {{chan {}}} {\n" |
| 1586 | " if {$chan eq \"\"} {\n" |
| 1587 | " tailcall upcall pid\n" |
| 1588 | " }\n" |
| 1589 | " if {[catch {$chan tell}]} {\n" |
| 1590 | " return -code error \"can not find channel named \\\"$chan\\\"\"\n" |
| 1591 | " }\n" |
| 1592 | " if {[catch {$chan pid} pids]} {\n" |
| 1593 | " return \"\"\n" |
| 1594 | " }\n" |
| 1595 | " return $pids\n" |
| 1596 | "}\n" |
| 1597 | "\n" |
| @@ -1680,23 +1752,25 @@ | |
| 1680 | "}\n" |
| 1681 | ); |
| 1682 | } |
| 1683 | |
| 1684 | |
| 1685 | |
| 1686 | #include <stdio.h> |
| 1687 | #include <string.h> |
| 1688 | #include <errno.h> |
| 1689 | #include <fcntl.h> |
| 1690 | |
| 1691 | |
| 1692 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1693 | #include <sys/socket.h> |
| 1694 | #include <netinet/in.h> |
| 1695 | #include <arpa/inet.h> |
| 1696 | #include <netdb.h> |
| 1697 | #include <unistd.h> |
| 1698 | #ifdef HAVE_SYS_UN_H |
| 1699 | #include <sys/un.h> |
| 1700 | #endif |
| 1701 | #else |
| 1702 | #define JIM_ANSIC |
| @@ -1728,15 +1802,12 @@ | |
| 1728 | typedef struct AioFile |
| 1729 | { |
| 1730 | FILE *fp; |
| 1731 | Jim_Obj *filename; |
| 1732 | int type; |
| 1733 | int OpenFlags; |
| 1734 | int fd; |
| 1735 | #ifdef O_NDELAY |
| 1736 | int flags; |
| 1737 | #endif |
| 1738 | Jim_Obj *rEvent; |
| 1739 | Jim_Obj *wEvent; |
| 1740 | Jim_Obj *eEvent; |
| 1741 | int addr_family; |
| 1742 | } AioFile; |
| @@ -1760,20 +1831,21 @@ | |
| 1760 | { |
| 1761 | AioFile *af = privData; |
| 1762 | |
| 1763 | JIM_NOTUSED(interp); |
| 1764 | |
| 1765 | if (!(af->OpenFlags & AIO_KEEPOPEN)) { |
| 1766 | fclose(af->fp); |
| 1767 | } |
| 1768 | |
| 1769 | Jim_DecrRefCount(interp, af->filename); |
| 1770 | |
| 1771 | #ifdef jim_ext_eventloop |
| 1772 | |
| 1773 | Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 1774 | #endif |
| 1775 | Jim_Free(af); |
| 1776 | } |
| 1777 | |
| 1778 | static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) |
| 1779 | { |
| @@ -2020,12 +2092,31 @@ | |
| 2020 | return JIM_OK; |
| 2021 | } |
| 2022 | |
| 2023 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2024 | { |
| 2025 | Jim_DeleteCommand(interp, Jim_String(argv[0])); |
| 2026 | return JIM_OK; |
| 2027 | } |
| 2028 | |
| 2029 | static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2030 | { |
| 2031 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2072,11 +2163,11 @@ | |
| 2072 | #ifdef O_NDELAY |
| 2073 | static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2074 | { |
| 2075 | AioFile *af = Jim_CmdPrivData(interp); |
| 2076 | |
| 2077 | int fmode = af->flags; |
| 2078 | |
| 2079 | if (argc) { |
| 2080 | long nb; |
| 2081 | |
| 2082 | if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { |
| @@ -2086,12 +2177,11 @@ | |
| 2086 | fmode |= O_NDELAY; |
| 2087 | } |
| 2088 | else { |
| 2089 | fmode &= ~O_NDELAY; |
| 2090 | } |
| 2091 | fcntl(af->fd, F_SETFL, fmode); |
| 2092 | af->flags = fmode; |
| 2093 | } |
| 2094 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2095 | return JIM_OK; |
| 2096 | } |
| 2097 | #endif |
| @@ -2195,11 +2285,11 @@ | |
| 2195 | |
| 2196 | static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2197 | { |
| 2198 | AioFile *af = Jim_CmdPrivData(interp); |
| 2199 | |
| 2200 | return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv); |
| 2201 | } |
| 2202 | #endif |
| 2203 | |
| 2204 | static const jim_subcmd_type aio_command_table[] = { |
| 2205 | { "read", |
| @@ -2250,14 +2340,14 @@ | |
| 2250 | 0, |
| 2251 | 0, |
| 2252 | |
| 2253 | }, |
| 2254 | { "close", |
| 2255 | NULL, |
| 2256 | aio_cmd_close, |
| 2257 | 0, |
| 2258 | 0, |
| 2259 | JIM_MODFLAG_FULLARGV, |
| 2260 | |
| 2261 | }, |
| 2262 | { "seek", |
| 2263 | "offset ?start|current|end", |
| @@ -2329,30 +2419,32 @@ | |
| 2329 | |
| 2330 | static int JimAioOpenCommand(Jim_Interp *interp, int argc, |
| 2331 | Jim_Obj *const *argv) |
| 2332 | { |
| 2333 | const char *mode; |
| 2334 | const char *filename; |
| 2335 | |
| 2336 | if (argc != 2 && argc != 3) { |
| 2337 | Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); |
| 2338 | return JIM_ERR; |
| 2339 | } |
| 2340 | |
| 2341 | mode = (argc == 3) ? Jim_String(argv[2]) : "r"; |
| 2342 | filename = Jim_String(argv[1]); |
| 2343 | |
| 2344 | #ifdef jim_ext_tclcompat |
| 2345 | |
| 2346 | if (*filename == '|') { |
| 2347 | Jim_Obj *evalObj[3]; |
| 2348 | |
| 2349 | evalObj[0] = Jim_NewStringObj(interp, "popen", -1); |
| 2350 | evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| 2351 | evalObj[2] = Jim_NewStringObj(interp, mode, -1); |
| 2352 | |
| 2353 | return Jim_EvalObjVector(interp, 3, evalObj); |
| 2354 | } |
| 2355 | #endif |
| 2356 | return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode); |
| 2357 | } |
| 2358 | |
| @@ -2359,70 +2451,129 @@ | |
| 2359 | static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2360 | const char *hdlfmt, int family, const char *mode) |
| 2361 | { |
| 2362 | AioFile *af; |
| 2363 | char buf[AIO_CMD_LEN]; |
| 2364 | int OpenFlags = 0; |
| 2365 | |
| 2366 | if (filename == NULL) { |
| 2367 | filename = Jim_NewStringObj(interp, hdlfmt, -1); |
| 2368 | } |
| 2369 | |
| 2370 | Jim_IncrRefCount(filename); |
| 2371 | |
| 2372 | if (fh == NULL) { |
| 2373 | if (fd < 0) { |
| 2374 | fh = fopen(Jim_String(filename), mode); |
| 2375 | } |
| 2376 | else { |
| 2377 | fh = fdopen(fd, mode); |
| 2378 | } |
| 2379 | } |
| 2380 | else { |
| 2381 | OpenFlags = AIO_KEEPOPEN; |
| 2382 | } |
| 2383 | |
| 2384 | if (fh == NULL) { |
| 2385 | JimAioSetError(interp, filename); |
| 2386 | #if !defined(JIM_ANSIC) |
| 2387 | if (fd >= 0) { |
| 2388 | close(fd); |
| 2389 | } |
| 2390 | #endif |
| 2391 | Jim_DecrRefCount(interp, filename); |
| 2392 | return JIM_ERR; |
| 2393 | } |
| 2394 | |
| 2395 | |
| 2396 | af = Jim_Alloc(sizeof(*af)); |
| 2397 | memset(af, 0, sizeof(*af)); |
| 2398 | af->fp = fh; |
| 2399 | af->fd = fileno(fh); |
| 2400 | af->filename = filename; |
| 2401 | #ifdef FD_CLOEXEC |
| 2402 | if ((OpenFlags & AIO_KEEPOPEN) == 0) { |
| 2403 | fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2404 | } |
| 2405 | #endif |
| 2406 | af->OpenFlags = OpenFlags; |
| 2407 | #ifdef O_NDELAY |
| 2408 | af->flags = fcntl(af->fd, F_GETFL); |
| 2409 | #endif |
| 2410 | af->addr_family = family; |
| 2411 | snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2412 | Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); |
| 2413 | |
| 2414 | Jim_SetResultString(interp, buf, -1); |
| 2415 | |
| 2416 | return JIM_OK; |
| 2417 | } |
| 2418 | |
| 2419 | |
| 2420 | FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2421 | { |
| 2422 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2423 | |
| 2424 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2425 | return ((AioFile *) cmdPtr->u.native.privData)->fp; |
| 2426 | } |
| 2427 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2428 | return NULL; |
| @@ -2443,11 +2594,10 @@ | |
| 2443 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2444 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2445 | |
| 2446 | return JIM_OK; |
| 2447 | } |
| 2448 | |
| 2449 | |
| 2450 | #include <errno.h> |
| 2451 | #include <stdio.h> |
| 2452 | #include <string.h> |
| 2453 | |
| @@ -2479,28 +2629,29 @@ | |
| 2479 | return JIM_OK; |
| 2480 | } |
| 2481 | Jim_SetResultString(interp, strerror(errno), -1); |
| 2482 | return JIM_ERR; |
| 2483 | } |
| 2484 | Jim_SetResultString(interp, strerror(errno), -1); |
| 2485 | |
| 2486 | Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); |
| 2487 | |
| 2488 | while ((entryPtr = readdir(dirPtr)) != NULL) { |
| 2489 | if (entryPtr->d_name[0] == '.') { |
| 2490 | if (entryPtr->d_name[1] == '\0') { |
| 2491 | continue; |
| 2492 | } |
| 2493 | if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) |
| 2494 | continue; |
| 2495 | } |
| 2496 | Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, |
| 2497 | entryPtr->d_name, -1)); |
| 2498 | } |
| 2499 | closedir(dirPtr); |
| 2500 | |
| 2501 | return JIM_OK; |
| 2502 | } |
| 2503 | |
| 2504 | int Jim_readdirInit(Jim_Interp *interp) |
| 2505 | { |
| 2506 | if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) |
| @@ -2511,10 +2662,14 @@ | |
| 2511 | } |
| 2512 | |
| 2513 | #include <stdlib.h> |
| 2514 | #include <string.h> |
| 2515 | |
| 2516 | |
| 2517 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2518 | { |
| 2519 | regfree(objPtr->internalRep.regexpValue.compre); |
| 2520 | Jim_Free(objPtr->internalRep.regexpValue.compre); |
| @@ -3058,58 +3213,61 @@ | |
| 3058 | } |
| 3059 | #endif |
| 3060 | return "unknown"; |
| 3061 | } |
| 3062 | |
| 3063 | |
| 3064 | static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, |
| 3065 | jim_wide value) |
| 3066 | { |
| 3067 | Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); |
| 3068 | Jim_Obj *valobj = Jim_NewWideObj(interp, value); |
| 3069 | |
| 3070 | if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { |
| 3071 | Jim_FreeObj(interp, nameobj); |
| 3072 | Jim_FreeObj(interp, valobj); |
| 3073 | return JIM_ERR; |
| 3074 | } |
| 3075 | return JIM_OK; |
| 3076 | } |
| 3077 | |
| 3078 | static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, |
| 3079 | const char *value) |
| 3080 | { |
| 3081 | Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); |
| 3082 | Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); |
| 3083 | |
| 3084 | if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { |
| 3085 | Jim_FreeObj(interp, nameobj); |
| 3086 | Jim_FreeObj(interp, valobj); |
| 3087 | return JIM_ERR; |
| 3088 | } |
| 3089 | return JIM_OK; |
| 3090 | } |
| 3091 | |
| 3092 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3093 | { |
| 3094 | if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { |
| 3095 | Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3096 | return JIM_ERR; |
| 3097 | } |
| 3098 | set_array_int_value(interp, varName, "ino", sb->st_ino); |
| 3099 | set_array_int_value(interp, varName, "mode", sb->st_mode); |
| 3100 | set_array_int_value(interp, varName, "nlink", sb->st_nlink); |
| 3101 | set_array_int_value(interp, varName, "uid", sb->st_uid); |
| 3102 | set_array_int_value(interp, varName, "gid", sb->st_gid); |
| 3103 | set_array_int_value(interp, varName, "size", sb->st_size); |
| 3104 | set_array_int_value(interp, varName, "atime", sb->st_atime); |
| 3105 | set_array_int_value(interp, varName, "mtime", sb->st_mtime); |
| 3106 | set_array_int_value(interp, varName, "ctime", sb->st_ctime); |
| 3107 | set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); |
| 3108 | |
| 3109 | |
| 3110 | Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); |
| 3111 | |
| 3112 | return JIM_OK; |
| 3113 | } |
| 3114 | |
| 3115 | static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3264,14 +3422,11 @@ | |
| 3264 | return JIM_OK; |
| 3265 | } |
| 3266 | |
| 3267 | static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) |
| 3268 | { |
| 3269 | const char *path = Jim_String(filename); |
| 3270 | int rc = access(path, mode); |
| 3271 | |
| 3272 | Jim_SetResultBool(interp, rc != -1); |
| 3273 | |
| 3274 | return JIM_OK; |
| 3275 | } |
| 3276 | |
| 3277 | static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3287,10 +3442,11 @@ | |
| 3287 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3288 | { |
| 3289 | #ifdef X_OK |
| 3290 | return file_access(interp, argv[0], X_OK); |
| 3291 | #else |
| 3292 | Jim_SetResultBool(interp, 1); |
| 3293 | return JIM_OK; |
| 3294 | #endif |
| 3295 | } |
| 3296 | |
| @@ -3391,33 +3547,21 @@ | |
| 3391 | argv++; |
| 3392 | } |
| 3393 | return JIM_OK; |
| 3394 | } |
| 3395 | |
| 3396 | #ifdef HAVE_MKSTEMP |
| 3397 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3398 | { |
| 3399 | int fd; |
| 3400 | char *filename; |
| 3401 | const char *template = "/tmp/tcl.tmp.XXXXXX"; |
| 3402 | |
| 3403 | if (argc >= 1) { |
| 3404 | template = Jim_String(argv[0]); |
| 3405 | } |
| 3406 | filename = Jim_StrDup(template); |
| 3407 | |
| 3408 | fd = mkstemp(filename); |
| 3409 | if (fd < 0) { |
| 3410 | Jim_SetResultString(interp, "Failed to create tempfile", -1); |
| 3411 | return JIM_ERR; |
| 3412 | } |
| 3413 | close(fd); |
| 3414 | |
| 3415 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1)); |
| 3416 | return JIM_OK; |
| 3417 | } |
| 3418 | #endif |
| 3419 | |
| 3420 | static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3421 | { |
| 3422 | const char *source; |
| 3423 | const char *dest; |
| @@ -3459,14 +3603,11 @@ | |
| 3459 | return JIM_ERR; |
| 3460 | } |
| 3461 | return JIM_OK; |
| 3462 | } |
| 3463 | |
| 3464 | #ifndef HAVE_LSTAT |
| 3465 | #define lstat stat |
| 3466 | #endif |
| 3467 | |
| 3468 | static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 3469 | { |
| 3470 | const char *path = Jim_String(filename); |
| 3471 | |
| 3472 | if (lstat(path, sb) == -1) { |
| @@ -3473,10 +3614,13 @@ | |
| 3473 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3474 | return JIM_ERR; |
| 3475 | } |
| 3476 | return JIM_OK; |
| 3477 | } |
| 3478 | |
| 3479 | static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3480 | { |
| 3481 | struct stat sb; |
| 3482 | |
| @@ -3601,28 +3745,32 @@ | |
| 3601 | } |
| 3602 | Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); |
| 3603 | return JIM_OK; |
| 3604 | } |
| 3605 | |
| 3606 | static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3607 | { |
| 3608 | struct stat sb; |
| 3609 | |
| 3610 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 3611 | return JIM_ERR; |
| 3612 | } |
| 3613 | return StoreStatData(interp, argv[1], &sb); |
| 3614 | } |
| 3615 | |
| 3616 | static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3617 | { |
| 3618 | struct stat sb; |
| 3619 | |
| 3620 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 3621 | return JIM_ERR; |
| 3622 | } |
| 3623 | return StoreStatData(interp, argv[1], &sb); |
| 3624 | } |
| 3625 | |
| 3626 | static const jim_subcmd_type file_command_table[] = { |
| 3627 | { "atime", |
| 3628 | "name", |
| @@ -3727,19 +3875,17 @@ | |
| 3727 | file_cmd_mkdir, |
| 3728 | 1, |
| 3729 | -1, |
| 3730 | |
| 3731 | }, |
| 3732 | #ifdef HAVE_MKSTEMP |
| 3733 | { "tempfile", |
| 3734 | "?template?", |
| 3735 | file_cmd_tempfile, |
| 3736 | 0, |
| 3737 | 1, |
| 3738 | |
| 3739 | }, |
| 3740 | #endif |
| 3741 | { "rename", |
| 3742 | "?-force? source dest", |
| 3743 | file_cmd_rename, |
| 3744 | 2, |
| 3745 | 3, |
| @@ -3760,20 +3906,20 @@ | |
| 3760 | 1, |
| 3761 | 1, |
| 3762 | |
| 3763 | }, |
| 3764 | { "stat", |
| 3765 | "name var", |
| 3766 | file_cmd_stat, |
| 3767 | 2, |
| 3768 | 2, |
| 3769 | |
| 3770 | }, |
| 3771 | { "lstat", |
| 3772 | "name var", |
| 3773 | file_cmd_lstat, |
| 3774 | 2, |
| 3775 | 2, |
| 3776 | |
| 3777 | }, |
| 3778 | { "type", |
| 3779 | "name", |
| @@ -3829,15 +3975,15 @@ | |
| 3829 | return JIM_OK; |
| 3830 | } |
| 3831 | |
| 3832 | static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3833 | { |
| 3834 | const int cwd_len = 2048; |
| 3835 | char *cwd = malloc(cwd_len); |
| 3836 | |
| 3837 | if (getcwd(cwd, cwd_len) == NULL) { |
| 3838 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 3839 | return JIM_ERR; |
| 3840 | } |
| 3841 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 3842 | { |
| 3843 | |
| @@ -3848,11 +3994,11 @@ | |
| 3848 | } |
| 3849 | #endif |
| 3850 | |
| 3851 | Jim_SetResultString(interp, cwd, -1); |
| 3852 | |
| 3853 | free(cwd); |
| 3854 | return JIM_OK; |
| 3855 | } |
| 3856 | |
| 3857 | int Jim_fileInit(Jim_Interp *interp) |
| 3858 | { |
| @@ -3917,10 +4063,11 @@ | |
| 3917 | |
| 3918 | int Jim_execInit(Jim_Interp *interp) |
| 3919 | { |
| 3920 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 3921 | return JIM_ERR; |
| 3922 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); |
| 3923 | return JIM_OK; |
| 3924 | } |
| 3925 | #else |
| 3926 | |
| @@ -3960,10 +4107,11 @@ | |
| 3960 | static int JimErrno(void); |
| 3961 | #else |
| 3962 | #include <unistd.h> |
| 3963 | #include <fcntl.h> |
| 3964 | #include <sys/wait.h> |
| 3965 | |
| 3966 | typedef int fdtype; |
| 3967 | typedef int pidtype; |
| 3968 | #define JimPipe pipe |
| 3969 | #define JimErrno() errno |
| @@ -4034,23 +4182,12 @@ | |
| 4034 | Jim_RemoveTrailingNewline(strObj); |
| 4035 | fclose(fh); |
| 4036 | return JIM_OK; |
| 4037 | } |
| 4038 | |
| 4039 | static void JimTrimTrailingNewline(Jim_Interp *interp) |
| 4040 | { |
| 4041 | int len; |
| 4042 | const char *p = Jim_GetString(Jim_GetResult(interp), &len); |
| 4043 | |
| 4044 | if (len > 0 && p[len - 1] == '\n') { |
| 4045 | Jim_SetResultString(interp, p, len - 1); |
| 4046 | } |
| 4047 | } |
| 4048 | |
| 4049 | static char **JimBuildEnv(Jim_Interp *interp) |
| 4050 | { |
| 4051 | #if defined(jim_ext_tclcompat) |
| 4052 | int i; |
| 4053 | int size; |
| 4054 | int num; |
| 4055 | int n; |
| 4056 | char **envptr; |
| @@ -4064,10 +4201,11 @@ | |
| 4064 | |
| 4065 | |
| 4066 | |
| 4067 | num = Jim_ListLength(interp, objPtr); |
| 4068 | if (num % 2) { |
| 4069 | num--; |
| 4070 | } |
| 4071 | size = Jim_Length(objPtr) + 2; |
| 4072 | |
| 4073 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4090,22 +4228,17 @@ | |
| 4090 | } |
| 4091 | envptr[n] = NULL; |
| 4092 | *envdata = 0; |
| 4093 | |
| 4094 | return envptr; |
| 4095 | #else |
| 4096 | return Jim_GetEnviron(); |
| 4097 | #endif |
| 4098 | } |
| 4099 | |
| 4100 | static void JimFreeEnv(char **env, char **original_environ) |
| 4101 | { |
| 4102 | #ifdef jim_ext_tclcompat |
| 4103 | if (env != original_environ) { |
| 4104 | Jim_Free(env); |
| 4105 | } |
| 4106 | #endif |
| 4107 | } |
| 4108 | |
| 4109 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) |
| 4110 | { |
| 4111 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| @@ -4154,19 +4287,19 @@ | |
| 4154 | } |
| 4155 | |
| 4156 | |
| 4157 | struct WaitInfo |
| 4158 | { |
| 4159 | pidtype pid; |
| 4160 | int status; |
| 4161 | int flags; |
| 4162 | }; |
| 4163 | |
| 4164 | struct WaitInfoTable { |
| 4165 | struct WaitInfo *info; |
| 4166 | int size; |
| 4167 | int used; |
| 4168 | }; |
| 4169 | |
| 4170 | |
| 4171 | #define WI_DETACHED 2 |
| 4172 | |
| @@ -4189,14 +4322,12 @@ | |
| 4189 | return table; |
| 4190 | } |
| 4191 | |
| 4192 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4193 | { |
| 4194 | fdtype outputId; /* File id for output pipe. -1 |
| 4195 | * means command overrode. */ |
| 4196 | fdtype errorId; /* File id for temporary file |
| 4197 | * containing error output. */ |
| 4198 | pidtype *pidPtr; |
| 4199 | int numPids, result; |
| 4200 | |
| 4201 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4202 | Jim_Obj *listObj; |
| @@ -4243,26 +4374,32 @@ | |
| 4243 | |
| 4244 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4245 | { |
| 4246 | struct WaitInfo *waitPtr; |
| 4247 | int count; |
| 4248 | |
| 4249 | if (!table) { |
| 4250 | return; |
| 4251 | } |
| 4252 | |
| 4253 | for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) { |
| 4254 | if (waitPtr->flags & WI_DETACHED) { |
| 4255 | int status; |
| 4256 | pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); |
| 4257 | if (pid != JIM_BAD_PID) { |
| 4258 | if (waitPtr != &table->info[table->used - 1]) { |
| 4259 | *waitPtr = table->info[table->used - 1]; |
| 4260 | } |
| 4261 | table->used--; |
| 4262 | } |
| 4263 | } |
| 4264 | } |
| 4265 | } |
| 4266 | |
| 4267 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4268 | { |
| @@ -4284,11 +4421,10 @@ | |
| 4284 | } |
| 4285 | |
| 4286 | |
| 4287 | return JIM_BAD_PID; |
| 4288 | } |
| 4289 | |
| 4290 | |
| 4291 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) |
| 4292 | { |
| 4293 | int j; |
| 4294 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| @@ -4609,27 +4745,23 @@ | |
| 4609 | } |
| 4610 | outputId = pipeIds[1]; |
| 4611 | } |
| 4612 | |
| 4613 | |
| 4614 | |
| 4615 | #ifdef __MINGW32__ |
| 4616 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); |
| 4617 | if (pid == JIM_BAD_PID) { |
| 4618 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4619 | goto error; |
| 4620 | } |
| 4621 | #else |
| 4622 | if (table->info == NULL) { |
| 4623 | (void)signal(SIGPIPE, SIG_IGN); |
| 4624 | } |
| 4625 | |
| 4626 | |
| 4627 | if (pipe_dup_err) { |
| 4628 | errorId = outputId; |
| 4629 | } |
| 4630 | |
| 4631 | pid = vfork(); |
| 4632 | if (pid < 0) { |
| 4633 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 4634 | goto error; |
| 4635 | } |
| @@ -4642,14 +4774,17 @@ | |
| 4642 | |
| 4643 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 4644 | close(i); |
| 4645 | } |
| 4646 | |
| 4647 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 4648 | |
| 4649 | |
| 4650 | fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4651 | _exit(127); |
| 4652 | } |
| 4653 | #endif |
| 4654 | |
| 4655 | |
| @@ -4751,19 +4886,24 @@ | |
| 4751 | if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { |
| 4752 | result = JIM_ERR; |
| 4753 | } |
| 4754 | } |
| 4755 | |
| 4756 | JimTrimTrailingNewline(interp); |
| 4757 | |
| 4758 | return result; |
| 4759 | } |
| 4760 | |
| 4761 | int Jim_execInit(Jim_Interp *interp) |
| 4762 | { |
| 4763 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4764 | return JIM_ERR; |
| 4765 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); |
| 4766 | return JIM_OK; |
| 4767 | } |
| 4768 | |
| 4769 | #if defined(__MINGW32__) |
| @@ -5088,28 +5228,26 @@ | |
| 5088 | { |
| 5089 | STARTUPINFO startInfo; |
| 5090 | PROCESS_INFORMATION procInfo; |
| 5091 | HANDLE hProcess, h; |
| 5092 | char execPath[MAX_PATH]; |
| 5093 | char *originalName; |
| 5094 | pidtype pid = JIM_BAD_PID; |
| 5095 | Jim_Obj *cmdLineObj; |
| 5096 | |
| 5097 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5098 | return JIM_BAD_PID; |
| 5099 | } |
| 5100 | originalName = argv[0]; |
| 5101 | argv[0] = execPath; |
| 5102 | |
| 5103 | hProcess = GetCurrentProcess(); |
| 5104 | cmdLineObj = JimWinBuildCommandLine(interp, argv); |
| 5105 | |
| 5106 | |
| 5107 | ZeroMemory(&startInfo, sizeof(startInfo)); |
| 5108 | startInfo.cb = sizeof(startInfo); |
| 5109 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5110 | startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5111 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5112 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5113 | |
| 5114 | if (inputId == JIM_BAD_FD) { |
| 5115 | if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { |
| @@ -5182,18 +5320,17 @@ | |
| 5182 | return lseek(fd, 0L, SEEK_SET); |
| 5183 | } |
| 5184 | |
| 5185 | static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5186 | { |
| 5187 | char inName[] = "/tmp/tcl.tmp.XXXXXX"; |
| 5188 | |
| 5189 | int fd = mkstemp(inName); |
| 5190 | if (fd == JIM_BAD_FD) { |
| 5191 | Jim_SetResultErrno(interp, "couldn't create temp file"); |
| 5192 | return -1; |
| 5193 | } |
| 5194 | unlink(inName); |
| 5195 | if (contents) { |
| 5196 | if (write(fd, contents, len) != len) { |
| 5197 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5198 | close(fd); |
| 5199 | return -1; |
| @@ -5217,11 +5354,10 @@ | |
| 5217 | } |
| 5218 | #endif |
| 5219 | #endif |
| 5220 | |
| 5221 | |
| 5222 | |
| 5223 | #ifndef _XOPEN_SOURCE |
| 5224 | #define _XOPEN_SOURCE 500 |
| 5225 | #endif |
| 5226 | |
| 5227 | #include <stdlib.h> |
| @@ -5239,11 +5375,11 @@ | |
| 5239 | |
| 5240 | char buf[100]; |
| 5241 | time_t t; |
| 5242 | long seconds; |
| 5243 | |
| 5244 | const char *format = "%a %b %d %H:%M:%S %Z %Y"; |
| 5245 | |
| 5246 | if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { |
| 5247 | return -1; |
| 5248 | } |
| 5249 | |
| @@ -5254,11 +5390,14 @@ | |
| 5254 | if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { |
| 5255 | return JIM_ERR; |
| 5256 | } |
| 5257 | t = seconds; |
| 5258 | |
| 5259 | strftime(buf, sizeof(buf), format, localtime(&t)); |
| 5260 | |
| 5261 | Jim_SetResultString(interp, buf, -1); |
| 5262 | |
| 5263 | return JIM_OK; |
| 5264 | } |
| @@ -5374,11 +5513,10 @@ | |
| 5374 | |
| 5375 | Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); |
| 5376 | return JIM_OK; |
| 5377 | } |
| 5378 | |
| 5379 | |
| 5380 | #include <limits.h> |
| 5381 | #include <stdlib.h> |
| 5382 | #include <string.h> |
| 5383 | #include <stdio.h> |
| 5384 | #include <errno.h> |
| @@ -5392,33 +5530,29 @@ | |
| 5392 | } |
| 5393 | |
| 5394 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5395 | { |
| 5396 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5397 | |
| 5398 | if (!objPtr) { |
| 5399 | return JIM_OK; |
| 5400 | } |
| 5401 | |
| 5402 | if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { |
| 5403 | |
| 5404 | if (Jim_IsList(objPtr)) { |
| 5405 | if (Jim_ListLength(interp, objPtr) % 2 != 0) { |
| 5406 | |
| 5407 | return JIM_ERR; |
| 5408 | } |
| 5409 | } |
| 5410 | else if (Jim_DictSize(interp, objPtr) < 0) { |
| 5411 | |
| 5412 | return JIM_ERR; |
| 5413 | } |
| 5414 | Jim_SetResult(interp, objPtr); |
| 5415 | return JIM_OK; |
| 5416 | } |
| 5417 | |
| 5418 | |
| 5419 | return Jim_DictValues(interp, objPtr, argv[1]); |
| 5420 | } |
| 5421 | |
| 5422 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5423 | { |
| 5424 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5443,10 +5577,15 @@ | |
| 5443 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5444 | return JIM_OK; |
| 5445 | } |
| 5446 | |
| 5447 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5448 | |
| 5449 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5450 | return JIM_ERR; |
| 5451 | } |
| 5452 | |
| @@ -5480,10 +5619,20 @@ | |
| 5480 | |
| 5481 | Jim_SetResultInt(interp, len); |
| 5482 | |
| 5483 | return JIM_OK; |
| 5484 | } |
| 5485 | |
| 5486 | static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5487 | { |
| 5488 | int i; |
| 5489 | int len; |
| @@ -5498,10 +5647,13 @@ | |
| 5498 | |
| 5499 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5500 | if (!dictObj) { |
| 5501 | |
| 5502 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5503 | } |
| 5504 | |
| 5505 | if (Jim_IsShared(dictObj)) { |
| 5506 | dictObj = Jim_DuplicateObj(interp, dictObj); |
| 5507 | } |
| @@ -5551,10 +5703,17 @@ | |
| 5551 | "arrayName", |
| 5552 | array_cmd_size, |
| 5553 | 1, |
| 5554 | 1, |
| 5555 | |
| 5556 | }, |
| 5557 | { "unset", |
| 5558 | "arrayName ?pattern?", |
| 5559 | array_cmd_unset, |
| 5560 | 1, |
| @@ -5597,11 +5756,10 @@ | |
| 5597 | Jim_arrayInit(interp); |
| 5598 | Jim_stdlibInit(interp); |
| 5599 | Jim_tclcompatInit(interp); |
| 5600 | return JIM_OK; |
| 5601 | } |
| 5602 | |
| 5603 | #define JIM_OPTIMIZATION |
| 5604 | |
| 5605 | #include <stdio.h> |
| 5606 | #include <stdlib.h> |
| 5607 | |
| @@ -5661,21 +5819,20 @@ | |
| 5661 | #define JIM_INTEGER_SPACE 24 |
| 5662 | |
| 5663 | const char *jim_tt_name(int type); |
| 5664 | |
| 5665 | #ifdef JIM_DEBUG_PANIC |
| 5666 | static void JimPanicDump(int panic_condition, const char *fmt, ...); |
| 5667 | #define JimPanic(X) JimPanicDump X |
| 5668 | #else |
| 5669 | #define JimPanic(X) |
| 5670 | #endif |
| 5671 | |
| 5672 | |
| 5673 | static char JimEmptyStringRep[] = ""; |
| 5674 | |
| 5675 | static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); |
| 5676 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); |
| 5677 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| 5678 | int flags); |
| 5679 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); |
| 5680 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); |
| 5681 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -5922,44 +6079,10 @@ | |
| 5922 | } |
| 5923 | return n; |
| 5924 | } |
| 5925 | #endif |
| 5926 | |
| 5927 | static int JimWideToString(char *buf, jim_wide wideValue) |
| 5928 | { |
| 5929 | int pos = 0; |
| 5930 | |
| 5931 | if (wideValue == 0) { |
| 5932 | buf[pos++] = '0'; |
| 5933 | } |
| 5934 | else { |
| 5935 | char tmp[JIM_INTEGER_SPACE]; |
| 5936 | int num = 0; |
| 5937 | int i; |
| 5938 | |
| 5939 | if (wideValue < 0) { |
| 5940 | buf[pos++] = '-'; |
| 5941 | |
| 5942 | i = wideValue % 10; |
| 5943 | tmp[num++] = (i > 0) ? (10 - i) : -i; |
| 5944 | wideValue /= -10; |
| 5945 | } |
| 5946 | |
| 5947 | while (wideValue) { |
| 5948 | tmp[num++] = wideValue % 10; |
| 5949 | wideValue /= 10; |
| 5950 | } |
| 5951 | |
| 5952 | for (i = 0; i < num; i++) { |
| 5953 | buf[pos++] = '0' + tmp[num - i - 1]; |
| 5954 | } |
| 5955 | } |
| 5956 | buf[pos] = 0; |
| 5957 | |
| 5958 | return pos; |
| 5959 | } |
| 5960 | |
| 5961 | static int JimCheckConversion(const char *str, const char *endptr) |
| 5962 | { |
| 5963 | if (str[0] == '\0' || str == endptr) { |
| 5964 | return JIM_ERR; |
| 5965 | } |
| @@ -6070,48 +6193,10 @@ | |
| 6070 | } |
| 6071 | |
| 6072 | return JimCheckConversion(str, endptr); |
| 6073 | } |
| 6074 | |
| 6075 | int Jim_DoubleToString(char *buf, double doubleValue) |
| 6076 | { |
| 6077 | int len; |
| 6078 | int i; |
| 6079 | |
| 6080 | len = sprintf(buf, "%.12g", doubleValue); |
| 6081 | |
| 6082 | |
| 6083 | for (i = 0; i < len; i++) { |
| 6084 | if (buf[i] == '.' || buf[i] == 'e') { |
| 6085 | #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 6086 | char *e = strchr(buf, 'e'); |
| 6087 | if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 6088 | |
| 6089 | e += 2; |
| 6090 | memmove(e, e + 1, len - (e - buf)); |
| 6091 | return len - 1; |
| 6092 | } |
| 6093 | #endif |
| 6094 | return len; |
| 6095 | } |
| 6096 | |
| 6097 | if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') { |
| 6098 | buf[i] = toupper(UCHAR(buf[i])); |
| 6099 | if (buf[i] == 'n' || buf[i] == 'N') |
| 6100 | buf[i+2] = toupper(UCHAR(buf[i+2])); |
| 6101 | buf[i + 3] = 0; |
| 6102 | return i + 3; |
| 6103 | } |
| 6104 | } |
| 6105 | |
| 6106 | buf[i++] = '.'; |
| 6107 | buf[i++] = '0'; |
| 6108 | buf[i] = '\0'; |
| 6109 | |
| 6110 | return i; |
| 6111 | } |
| 6112 | |
| 6113 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6114 | { |
| 6115 | char *endptr; |
| 6116 | |
| 6117 | |
| @@ -6133,23 +6218,23 @@ | |
| 6133 | } |
| 6134 | return res; |
| 6135 | } |
| 6136 | |
| 6137 | #ifdef JIM_DEBUG_PANIC |
| 6138 | void JimPanicDump(int condition, const char *fmt, ...) |
| 6139 | { |
| 6140 | va_list ap; |
| 6141 | |
| 6142 | if (!condition) { |
| 6143 | return; |
| 6144 | } |
| 6145 | |
| 6146 | va_start(ap, fmt); |
| 6147 | |
| 6148 | fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); |
| 6149 | vfprintf(stderr, fmt, ap); |
| 6150 | fprintf(stderr, JIM_NL JIM_NL); |
| 6151 | va_end(ap); |
| 6152 | |
| 6153 | #ifdef HAVE_BACKTRACE |
| 6154 | { |
| 6155 | void *array[40]; |
| @@ -6157,13 +6242,13 @@ | |
| 6157 | char **strings; |
| 6158 | |
| 6159 | size = backtrace(array, 40); |
| 6160 | strings = backtrace_symbols(array, size); |
| 6161 | for (i = 0; i < size; i++) |
| 6162 | fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]); |
| 6163 | fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL); |
| 6164 | fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL); |
| 6165 | } |
| 6166 | #endif |
| 6167 | |
| 6168 | exit(1); |
| 6169 | } |
| @@ -6237,18 +6322,24 @@ | |
| 6237 | h += (h << 3) + *buf++; |
| 6238 | return h; |
| 6239 | } |
| 6240 | |
| 6241 | |
| 6242 | |
| 6243 | static void JimResetHashTable(Jim_HashTable *ht) |
| 6244 | { |
| 6245 | ht->table = NULL; |
| 6246 | ht->size = 0; |
| 6247 | ht->sizemask = 0; |
| 6248 | ht->used = 0; |
| 6249 | ht->collisions = 0; |
| 6250 | } |
| 6251 | |
| 6252 | static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) |
| 6253 | { |
| 6254 | iter->ht = ht; |
| @@ -6286,10 +6377,12 @@ | |
| 6286 | |
| 6287 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6288 | n.size = realsize; |
| 6289 | n.sizemask = realsize - 1; |
| 6290 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6291 | |
| 6292 | |
| 6293 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6294 | |
| 6295 | n.used = ht->used; |
| @@ -6342,20 +6435,27 @@ | |
| 6342 | int existed; |
| 6343 | Jim_HashEntry *entry; |
| 6344 | |
| 6345 | entry = JimInsertHashEntry(ht, key, 1); |
| 6346 | if (entry->key) { |
| 6347 | |
| 6348 | Jim_FreeEntryVal(ht, entry); |
| 6349 | existed = 1; |
| 6350 | } |
| 6351 | else { |
| 6352 | |
| 6353 | Jim_SetHashKey(ht, entry, key); |
| 6354 | existed = 0; |
| 6355 | } |
| 6356 | Jim_SetHashVal(ht, entry, val); |
| 6357 | |
| 6358 | return existed; |
| 6359 | } |
| 6360 | |
| 6361 | |
| @@ -6520,11 +6620,11 @@ | |
| 6520 | return Jim_GenHashFunction(key, strlen(key)); |
| 6521 | } |
| 6522 | |
| 6523 | static void *JimStringCopyHTDup(void *privdata, const void *key) |
| 6524 | { |
| 6525 | return strdup(key); |
| 6526 | } |
| 6527 | |
| 6528 | static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 6529 | { |
| 6530 | return strcmp(key1, key2) == 0; |
| @@ -6620,11 +6720,11 @@ | |
| 6620 | freeFunc(stack->vector[i]); |
| 6621 | } |
| 6622 | |
| 6623 | |
| 6624 | |
| 6625 | #define JIM_TT_NONE 0 |
| 6626 | #define JIM_TT_STR 1 |
| 6627 | #define JIM_TT_ESC 2 |
| 6628 | #define JIM_TT_VAR 3 |
| 6629 | #define JIM_TT_DICTSUGAR 4 |
| 6630 | #define JIM_TT_CMD 5 |
| @@ -6652,10 +6752,15 @@ | |
| 6652 | |
| 6653 | |
| 6654 | #define JIM_PS_DEF 0 |
| 6655 | #define JIM_PS_QUOTE 1 |
| 6656 | #define JIM_PS_DICTSUGAR 2 |
| 6657 | |
| 6658 | struct JimParserCtx |
| 6659 | { |
| 6660 | const char *p; |
| 6661 | int len; |
| @@ -6665,17 +6770,11 @@ | |
| 6665 | int tline; |
| 6666 | int tt; |
| 6667 | int eof; |
| 6668 | int state; |
| 6669 | int comment; |
| 6670 | char missing; |
| 6671 | int missingline; |
| 6672 | }; |
| 6673 | |
| 6674 | struct JimParseResult { |
| 6675 | char missing; |
| 6676 | int line; |
| 6677 | }; |
| 6678 | |
| 6679 | static int JimParseScript(struct JimParserCtx *pc); |
| 6680 | static int JimParseSep(struct JimParserCtx *pc); |
| 6681 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -6685,11 +6784,10 @@ | |
| 6685 | static int JimParseBrace(struct JimParserCtx *pc); |
| 6686 | static int JimParseStr(struct JimParserCtx *pc); |
| 6687 | static int JimParseComment(struct JimParserCtx *pc); |
| 6688 | static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6689 | static int JimParseSubQuote(struct JimParserCtx *pc); |
| 6690 | static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6691 | static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); |
| 6692 | |
| 6693 | static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) |
| 6694 | { |
| 6695 | pc->p = prg; |
| @@ -6700,12 +6798,12 @@ | |
| 6700 | pc->tt = JIM_TT_NONE; |
| 6701 | pc->eof = 0; |
| 6702 | pc->state = JIM_PS_DEF; |
| 6703 | pc->linenr = linenr; |
| 6704 | pc->comment = 1; |
| 6705 | pc->missing = ' '; |
| 6706 | pc->missingline = linenr; |
| 6707 | } |
| 6708 | |
| 6709 | static int JimParseScript(struct JimParserCtx *pc) |
| 6710 | { |
| 6711 | while (1) { |
| @@ -6837,12 +6935,12 @@ | |
| 6837 | break; |
| 6838 | } |
| 6839 | pc->p++; |
| 6840 | pc->len--; |
| 6841 | } |
| 6842 | pc->missing = '{'; |
| 6843 | pc->missingline = pc->tline; |
| 6844 | pc->tend = pc->p - 1; |
| 6845 | } |
| 6846 | |
| 6847 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 6848 | { |
| @@ -6884,12 +6982,12 @@ | |
| 6884 | break; |
| 6885 | } |
| 6886 | pc->p++; |
| 6887 | pc->len--; |
| 6888 | } |
| 6889 | pc->missing = '"'; |
| 6890 | pc->missingline = line; |
| 6891 | pc->tend = pc->p - 1; |
| 6892 | return tt; |
| 6893 | } |
| 6894 | |
| 6895 | static void JimParseSubCmd(struct JimParserCtx *pc) |
| @@ -6943,12 +7041,12 @@ | |
| 6943 | } |
| 6944 | startofword = isspace(UCHAR(*pc->p)); |
| 6945 | pc->p++; |
| 6946 | pc->len--; |
| 6947 | } |
| 6948 | pc->missing = '['; |
| 6949 | pc->missingline = line; |
| 6950 | pc->tend = pc->p - 1; |
| 6951 | } |
| 6952 | |
| 6953 | static int JimParseBrace(struct JimParserCtx *pc) |
| 6954 | { |
| @@ -7088,19 +7186,19 @@ | |
| 7088 | if (*pc->p == '"') { |
| 7089 | pc->state = JIM_PS_QUOTE; |
| 7090 | pc->p++; |
| 7091 | pc->len--; |
| 7092 | |
| 7093 | pc->missingline = pc->tline; |
| 7094 | } |
| 7095 | } |
| 7096 | pc->tstart = pc->p; |
| 7097 | pc->tline = pc->linenr; |
| 7098 | while (1) { |
| 7099 | if (pc->len == 0) { |
| 7100 | if (pc->state == JIM_PS_QUOTE) { |
| 7101 | pc->missing = '"'; |
| 7102 | } |
| 7103 | pc->tend = pc->p - 1; |
| 7104 | pc->tt = JIM_TT_ESC; |
| 7105 | return JIM_OK; |
| 7106 | } |
| @@ -7116,10 +7214,14 @@ | |
| 7116 | pc->linenr++; |
| 7117 | } |
| 7118 | pc->p++; |
| 7119 | pc->len--; |
| 7120 | } |
| 7121 | break; |
| 7122 | case '(': |
| 7123 | |
| 7124 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7125 | break; |
| @@ -7176,17 +7278,26 @@ | |
| 7176 | } |
| 7177 | |
| 7178 | static int JimParseComment(struct JimParserCtx *pc) |
| 7179 | { |
| 7180 | while (*pc->p) { |
| 7181 | if (*pc->p == '\n') { |
| 7182 | pc->linenr++; |
| 7183 | if (*(pc->p - 1) != '\\') { |
| 7184 | pc->p++; |
| 7185 | pc->len--; |
| 7186 | return JIM_OK; |
| 7187 | } |
| 7188 | } |
| 7189 | pc->p++; |
| 7190 | pc->len--; |
| 7191 | } |
| 7192 | return JIM_OK; |
| @@ -7404,13 +7515,13 @@ | |
| 7404 | JimParserInit(&parser, s, len, 1); |
| 7405 | while (!parser.eof) { |
| 7406 | JimParseScript(&parser); |
| 7407 | } |
| 7408 | if (stateCharPtr) { |
| 7409 | *stateCharPtr = parser.missing; |
| 7410 | } |
| 7411 | return parser.missing == ' '; |
| 7412 | } |
| 7413 | |
| 7414 | static int JimParseListSep(struct JimParserCtx *pc); |
| 7415 | static int JimParseListStr(struct JimParserCtx *pc); |
| 7416 | static int JimParseListQuote(struct JimParserCtx *pc); |
| @@ -7662,10 +7773,16 @@ | |
| 7662 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7663 | objPtr->typePtr->updateStringProc(objPtr); |
| 7664 | } |
| 7665 | return objPtr->bytes; |
| 7666 | } |
| 7667 | |
| 7668 | static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 7669 | static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 7670 | |
| 7671 | static const Jim_ObjType dictSubstObjType = { |
| @@ -7703,11 +7820,10 @@ | |
| 7703 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 7704 | { |
| 7705 | JIM_NOTUSED(interp); |
| 7706 | |
| 7707 | dupPtr->internalRep.strValue.maxLength = srcPtr->length; |
| 7708 | |
| 7709 | dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; |
| 7710 | } |
| 7711 | |
| 7712 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7713 | { |
| @@ -7752,18 +7868,17 @@ | |
| 7752 | if (len == -1) |
| 7753 | len = strlen(s); |
| 7754 | |
| 7755 | if (len == 0) { |
| 7756 | objPtr->bytes = JimEmptyStringRep; |
| 7757 | objPtr->length = 0; |
| 7758 | } |
| 7759 | else { |
| 7760 | objPtr->bytes = Jim_Alloc(len + 1); |
| 7761 | objPtr->length = len; |
| 7762 | memcpy(objPtr->bytes, s, len); |
| 7763 | objPtr->bytes[len] = '\0'; |
| 7764 | } |
| 7765 | |
| 7766 | |
| 7767 | objPtr->typePtr = NULL; |
| 7768 | return objPtr; |
| 7769 | } |
| @@ -7791,11 +7906,11 @@ | |
| 7791 | Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) |
| 7792 | { |
| 7793 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 7794 | |
| 7795 | objPtr->bytes = s; |
| 7796 | objPtr->length = len == -1 ? strlen(s) : len; |
| 7797 | objPtr->typePtr = NULL; |
| 7798 | return objPtr; |
| 7799 | } |
| 7800 | |
| 7801 | static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) |
| @@ -7820,17 +7935,17 @@ | |
| 7820 | } |
| 7821 | objPtr->internalRep.strValue.maxLength = needlen; |
| 7822 | } |
| 7823 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 7824 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 7825 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 7826 | |
| 7827 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 7828 | } |
| 7829 | objPtr->length += len; |
| 7830 | } |
| 7831 | |
| 7832 | |
| 7833 | void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) |
| 7834 | { |
| 7835 | JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); |
| 7836 | SetStringFromAny(interp, objPtr); |
| @@ -7838,13 +7953,11 @@ | |
| 7838 | } |
| 7839 | |
| 7840 | void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) |
| 7841 | { |
| 7842 | int len; |
| 7843 | const char *str; |
| 7844 | |
| 7845 | str = Jim_GetString(appendObjPtr, &len); |
| 7846 | Jim_AppendString(interp, objPtr, str, len); |
| 7847 | } |
| 7848 | |
| 7849 | void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) |
| 7850 | { |
| @@ -7851,11 +7964,11 @@ | |
| 7851 | va_list ap; |
| 7852 | |
| 7853 | SetStringFromAny(interp, objPtr); |
| 7854 | va_start(ap, objPtr); |
| 7855 | while (1) { |
| 7856 | char *s = va_arg(ap, char *); |
| 7857 | |
| 7858 | if (s == NULL) |
| 7859 | break; |
| 7860 | Jim_AppendString(interp, objPtr, s, -1); |
| 7861 | } |
| @@ -7862,20 +7975,20 @@ | |
| 7862 | va_end(ap); |
| 7863 | } |
| 7864 | |
| 7865 | int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) |
| 7866 | { |
| 7867 | const char *aStr, *bStr; |
| 7868 | int aLen, bLen; |
| 7869 | |
| 7870 | if (aObjPtr == bObjPtr) |
| 7871 | return 1; |
| 7872 | aStr = Jim_GetString(aObjPtr, &aLen); |
| 7873 | bStr = Jim_GetString(bObjPtr, &bLen); |
| 7874 | if (aLen != bLen) |
| 7875 | return 0; |
| 7876 | return JimStringCompare(aStr, aLen, bStr, bLen) == 0; |
| 7877 | } |
| 7878 | |
| 7879 | int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) |
| 7880 | { |
| 7881 | return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); |
| @@ -8036,11 +8149,11 @@ | |
| 8036 | static void JimStrCopyUpperLower(char *dest, const char *str, int uc) |
| 8037 | { |
| 8038 | while (*str) { |
| 8039 | int c; |
| 8040 | str += utf8_tounicode(str, &c); |
| 8041 | dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c)); |
| 8042 | } |
| 8043 | *dest = 0; |
| 8044 | } |
| 8045 | |
| 8046 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) |
| @@ -8096,11 +8209,11 @@ | |
| 8096 | len *= 2; |
| 8097 | #endif |
| 8098 | buf = p = Jim_Alloc(len + 1); |
| 8099 | |
| 8100 | str += utf8_tounicode(str, &c); |
| 8101 | p += utf8_fromunicode(p, utf8_title(c)); |
| 8102 | |
| 8103 | JimStrCopyUpperLower(p, str, 0); |
| 8104 | |
| 8105 | return Jim_NewStringObjNoAlloc(interp, buf, -1); |
| 8106 | } |
| @@ -8203,10 +8316,11 @@ | |
| 8203 | if (nontrim == NULL) { |
| 8204 | |
| 8205 | return Jim_NewEmptyStringObj(interp); |
| 8206 | } |
| 8207 | if (nontrim == strObjPtr->bytes + len) { |
| 8208 | return strObjPtr; |
| 8209 | } |
| 8210 | |
| 8211 | if (Jim_IsShared(strObjPtr)) { |
| 8212 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| @@ -8226,14 +8340,14 @@ | |
| 8226 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8227 | |
| 8228 | |
| 8229 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8230 | |
| 8231 | if (objPtr != strObjPtr) { |
| 8232 | |
| 8233 | Jim_IncrRefCount(objPtr); |
| 8234 | Jim_DecrRefCount(interp, objPtr); |
| 8235 | } |
| 8236 | |
| 8237 | return strObjPtr; |
| 8238 | } |
| 8239 | |
| @@ -8270,26 +8384,26 @@ | |
| 8270 | return JIM_ERR; |
| 8271 | } |
| 8272 | |
| 8273 | str = Jim_GetString(strObjPtr, &len); |
| 8274 | if (len == 0) { |
| 8275 | Jim_SetResultInt(interp, !strict); |
| 8276 | return JIM_OK; |
| 8277 | } |
| 8278 | |
| 8279 | switch (strclass) { |
| 8280 | case STR_IS_INTEGER: |
| 8281 | { |
| 8282 | jim_wide w; |
| 8283 | Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); |
| 8284 | return JIM_OK; |
| 8285 | } |
| 8286 | |
| 8287 | case STR_IS_DOUBLE: |
| 8288 | { |
| 8289 | double d; |
| 8290 | Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8291 | return JIM_OK; |
| 8292 | } |
| 8293 | |
| 8294 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8295 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| @@ -8307,15 +8421,15 @@ | |
| 8307 | return JIM_ERR; |
| 8308 | } |
| 8309 | |
| 8310 | for (i = 0; i < len; i++) { |
| 8311 | if (!isclassfunc(str[i])) { |
| 8312 | Jim_SetResultInt(interp, 0); |
| 8313 | return JIM_OK; |
| 8314 | } |
| 8315 | } |
| 8316 | Jim_SetResultInt(interp, 1); |
| 8317 | return JIM_OK; |
| 8318 | } |
| 8319 | |
| 8320 | |
| 8321 | |
| @@ -8327,17 +8441,19 @@ | |
| 8327 | JIM_TYPE_REFERENCES, |
| 8328 | }; |
| 8329 | |
| 8330 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) |
| 8331 | { |
| 8332 | if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) |
| 8333 | return 1; |
| 8334 | else { |
| 8335 | const char *objStr = Jim_String(objPtr); |
| 8336 | |
| 8337 | if (strcmp(str, objStr) != 0) |
| 8338 | return 0; |
| 8339 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8340 | Jim_FreeIntRep(interp, objPtr); |
| 8341 | objPtr->typePtr = &comparedStringObjType; |
| 8342 | } |
| 8343 | objPtr->internalRep.ptr = (char *)str; |
| @@ -8379,24 +8495,23 @@ | |
| 8379 | |
| 8380 | static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, |
| 8381 | Jim_Obj *fileNameObj, int lineNumber) |
| 8382 | { |
| 8383 | JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); |
| 8384 | JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object")); |
| 8385 | Jim_IncrRefCount(fileNameObj); |
| 8386 | objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; |
| 8387 | objPtr->internalRep.sourceValue.lineNumber = lineNumber; |
| 8388 | objPtr->typePtr = &sourceObjType; |
| 8389 | } |
| 8390 | |
| 8391 | |
| 8392 | static const Jim_ObjType scriptLineObjType = { |
| 8393 | "scriptline", |
| 8394 | NULL, |
| 8395 | NULL, |
| 8396 | NULL, |
| 8397 | 0, |
| 8398 | }; |
| 8399 | |
| 8400 | static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) |
| 8401 | { |
| 8402 | Jim_Obj *objPtr; |
| @@ -8413,15 +8528,14 @@ | |
| 8413 | objPtr->internalRep.scriptLineValue.line = line; |
| 8414 | |
| 8415 | return objPtr; |
| 8416 | } |
| 8417 | |
| 8418 | #define JIM_CMDSTRUCT_EXPAND -1 |
| 8419 | |
| 8420 | static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 8421 | static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8422 | static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result); |
| 8423 | |
| 8424 | static const Jim_ObjType scriptObjType = { |
| 8425 | "script", |
| 8426 | FreeScriptInternalRep, |
| 8427 | DupScriptInternalRep, |
| @@ -8429,34 +8543,33 @@ | |
| 8429 | JIM_TYPE_REFERENCES, |
| 8430 | }; |
| 8431 | |
| 8432 | typedef struct ScriptToken |
| 8433 | { |
| 8434 | int type; |
| 8435 | Jim_Obj *objPtr; |
| 8436 | } ScriptToken; |
| 8437 | |
| 8438 | typedef struct ScriptObj |
| 8439 | { |
| 8440 | int len; |
| 8441 | ScriptToken *token; |
| 8442 | int substFlags; |
| 8443 | int inUse; /* Used to share a ScriptObj. Currently |
| 8444 | only used by Jim_EvalObj() as protection against |
| 8445 | shimmering of the currently evaluated object. */ |
| 8446 | Jim_Obj *fileNameObj; |
| 8447 | int firstline; |
| 8448 | int linenr; |
| 8449 | } ScriptObj; |
| 8450 | |
| 8451 | void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8452 | { |
| 8453 | int i; |
| 8454 | struct ScriptObj *script = (void *)objPtr->internalRep.ptr; |
| 8455 | |
| 8456 | script->inUse--; |
| 8457 | if (script->inUse != 0) |
| 8458 | return; |
| 8459 | for (i = 0; i < script->len; i++) { |
| 8460 | Jim_DecrRefCount(interp, script->token[i].objPtr); |
| 8461 | } |
| 8462 | Jim_Free(script->token); |
| @@ -8467,11 +8580,10 @@ | |
| 8467 | void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 8468 | { |
| 8469 | JIM_NOTUSED(interp); |
| 8470 | JIM_NOTUSED(srcPtr); |
| 8471 | |
| 8472 | |
| 8473 | dupPtr->typePtr = NULL; |
| 8474 | } |
| 8475 | |
| 8476 | typedef struct |
| 8477 | { |
| @@ -8666,11 +8778,11 @@ | |
| 8666 | token--; |
| 8667 | } |
| 8668 | |
| 8669 | script->len = token - script->token; |
| 8670 | |
| 8671 | assert(script->len < count); |
| 8672 | |
| 8673 | #ifdef DEBUG_SHOW_SCRIPT |
| 8674 | printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); |
| 8675 | for (i = 0; i < script->len; i++) { |
| 8676 | const ScriptToken *t = &script->token[i]; |
| @@ -8677,10 +8789,35 @@ | |
| 8677 | printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); |
| 8678 | } |
| 8679 | #endif |
| 8680 | |
| 8681 | } |
| 8682 | |
| 8683 | static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8684 | ParseTokenList *tokenlist) |
| 8685 | { |
| 8686 | int i; |
| @@ -8699,18 +8836,19 @@ | |
| 8699 | } |
| 8700 | |
| 8701 | script->len = i; |
| 8702 | } |
| 8703 | |
| 8704 | static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result) |
| 8705 | { |
| 8706 | int scriptTextLen; |
| 8707 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 8708 | struct JimParserCtx parser; |
| 8709 | struct ScriptObj *script; |
| 8710 | ParseTokenList tokenlist; |
| 8711 | int line = 1; |
| 8712 | |
| 8713 | |
| 8714 | if (objPtr->typePtr == &sourceObjType) { |
| 8715 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 8716 | } |
| @@ -8722,16 +8860,12 @@ | |
| 8722 | while (!parser.eof) { |
| 8723 | JimParseScript(&parser); |
| 8724 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 8725 | parser.tline); |
| 8726 | } |
| 8727 | if (result && parser.missing != ' ') { |
| 8728 | ScriptTokenListFree(&tokenlist); |
| 8729 | result->missing = parser.missing; |
| 8730 | result->line = parser.missingline; |
| 8731 | return JIM_ERR; |
| 8732 | } |
| 8733 | |
| 8734 | |
| 8735 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 8736 | |
| 8737 | |
| @@ -8742,10 +8876,11 @@ | |
| 8742 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 8743 | } |
| 8744 | else { |
| 8745 | script->fileNameObj = interp->emptyObj; |
| 8746 | } |
| 8747 | Jim_IncrRefCount(script->fileNameObj); |
| 8748 | |
| 8749 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 8750 | |
| 8751 | |
| @@ -8754,11 +8889,11 @@ | |
| 8754 | |
| 8755 | Jim_FreeIntRep(interp, objPtr); |
| 8756 | Jim_SetIntRepPtr(objPtr, script); |
| 8757 | objPtr->typePtr = &scriptObjType; |
| 8758 | |
| 8759 | return JIM_OK; |
| 8760 | } |
| 8761 | |
| 8762 | ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8763 | { |
| 8764 | if (objPtr == interp->emptyObj) { |
| @@ -8765,11 +8900,13 @@ | |
| 8765 | |
| 8766 | objPtr = interp->nullScriptObj; |
| 8767 | } |
| 8768 | |
| 8769 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 8770 | SetScriptFromAny(interp, objPtr, NULL); |
| 8771 | } |
| 8772 | return (ScriptObj *) Jim_GetIntRepPtr(objPtr); |
| 8773 | } |
| 8774 | |
| 8775 | static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) |
| @@ -8850,10 +8987,26 @@ | |
| 8850 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 8851 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 8852 | } |
| 8853 | return nsObj; |
| 8854 | } |
| 8855 | |
| 8856 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 8857 | { |
| 8858 | Jim_Obj *objPtr = interp->emptyObj; |
| 8859 | |
| @@ -8877,10 +9030,15 @@ | |
| 8877 | |
| 8878 | #else |
| 8879 | |
| 8880 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 8881 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 8882 | #endif |
| 8883 | |
| 8884 | static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) |
| 8885 | { |
| 8886 | Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); |
| @@ -8889,12 +9047,12 @@ | |
| 8889 | Jim_InterpIncrProcEpoch(interp); |
| 8890 | } |
| 8891 | |
| 8892 | if (he && interp->local) { |
| 8893 | |
| 8894 | cmd->prevCmd = he->u.val; |
| 8895 | he->u.val = cmd; |
| 8896 | } |
| 8897 | else { |
| 8898 | if (he) { |
| 8899 | |
| 8900 | Jim_DeleteHashEntry(&interp->commands, name); |
| @@ -8933,19 +9091,19 @@ | |
| 8933 | } |
| 8934 | |
| 8935 | cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); |
| 8936 | Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); |
| 8937 | for (i = 0; i < len; i++) { |
| 8938 | Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL; |
| 8939 | Jim_Var *varPtr; |
| 8940 | int subLen; |
| 8941 | |
| 8942 | Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE); |
| 8943 | |
| 8944 | subLen = Jim_ListLength(interp, objPtr); |
| 8945 | if (subLen == 1 || subLen == 2) { |
| 8946 | Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE); |
| 8947 | if (subLen == 1) { |
| 8948 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 8949 | if (initObjPtr == NULL) { |
| 8950 | Jim_SetResultFormatted(interp, |
| 8951 | "variable for initialization of static \"%#s\" not found in the local context", |
| @@ -8952,11 +9110,11 @@ | |
| 8952 | nameObjPtr); |
| 8953 | return JIM_ERR; |
| 8954 | } |
| 8955 | } |
| 8956 | else { |
| 8957 | Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE); |
| 8958 | } |
| 8959 | if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { |
| 8960 | return JIM_ERR; |
| 8961 | } |
| 8962 | |
| @@ -9038,11 +9196,11 @@ | |
| 9038 | Jim_Obj *nameObjPtr; |
| 9039 | Jim_Obj *defaultObjPtr; |
| 9040 | int len; |
| 9041 | |
| 9042 | |
| 9043 | Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE); |
| 9044 | len = Jim_ListLength(interp, argPtr); |
| 9045 | if (len == 0) { |
| 9046 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9047 | err: |
| 9048 | JimDecrCmdRefCount(interp, cmdPtr); |
| @@ -9053,12 +9211,12 @@ | |
| 9053 | goto err; |
| 9054 | } |
| 9055 | |
| 9056 | if (len == 2) { |
| 9057 | |
| 9058 | Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE); |
| 9059 | Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE); |
| 9060 | } |
| 9061 | else { |
| 9062 | |
| 9063 | nameObjPtr = argPtr; |
| 9064 | defaultObjPtr = NULL; |
| @@ -9132,11 +9290,11 @@ | |
| 9132 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9133 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9134 | } |
| 9135 | else { |
| 9136 | |
| 9137 | cmdPtr = he->u.val; |
| 9138 | JimIncrCmdRefCount(cmdPtr); |
| 9139 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9140 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9141 | |
| 9142 | |
| @@ -9217,11 +9375,11 @@ | |
| 9217 | return NULL; |
| 9218 | } |
| 9219 | #ifdef jim_ext_namespace |
| 9220 | found: |
| 9221 | #endif |
| 9222 | cmd = (Jim_Cmd *)he->u.val; |
| 9223 | |
| 9224 | |
| 9225 | Jim_FreeIntRep(interp, objPtr); |
| 9226 | objPtr->typePtr = &commandObjType; |
| 9227 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| @@ -9323,11 +9481,11 @@ | |
| 9323 | |
| 9324 | |
| 9325 | Jim_FreeIntRep(interp, objPtr); |
| 9326 | objPtr->typePtr = &variableObjType; |
| 9327 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9328 | objPtr->internalRep.varValue.varPtr = he->u.val; |
| 9329 | objPtr->internalRep.varValue.global = global; |
| 9330 | return JIM_OK; |
| 9331 | } |
| 9332 | |
| 9333 | |
| @@ -9641,11 +9799,11 @@ | |
| 9641 | } |
| 9642 | |
| 9643 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 9644 | if (retval == JIM_OK) { |
| 9645 | |
| 9646 | JimChangeCallFrameId(interp, framePtr); |
| 9647 | } |
| 9648 | } |
| 9649 | } |
| 9650 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| 9651 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); |
| @@ -9725,28 +9883,17 @@ | |
| 9725 | return NULL; |
| 9726 | } |
| 9727 | |
| 9728 | ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9729 | if (ret != JIM_OK) { |
| 9730 | resObjPtr = NULL; |
| 9731 | if (ret < 0) { |
| 9732 | Jim_SetResultFormatted(interp, |
| 9733 | "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr); |
| 9734 | } |
| 9735 | else { |
| 9736 | Jim_SetResultFormatted(interp, |
| 9737 | "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr); |
| 9738 | } |
| 9739 | } |
| 9740 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 9741 | dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr); |
| 9742 | if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) { |
| 9743 | |
| 9744 | JimPanic((1, "SetVariable failed for JIM_UNSHARED")); |
| 9745 | } |
| 9746 | |
| 9747 | Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9748 | } |
| 9749 | |
| 9750 | return resObjPtr; |
| 9751 | } |
| 9752 | |
| @@ -9843,68 +9990,67 @@ | |
| 9843 | Jim_CallFrame *cf; |
| 9844 | |
| 9845 | if (interp->freeFramesList) { |
| 9846 | cf = interp->freeFramesList; |
| 9847 | interp->freeFramesList = cf->next; |
| 9848 | } |
| 9849 | else { |
| 9850 | cf = Jim_Alloc(sizeof(*cf)); |
| 9851 | cf->vars.table = NULL; |
| 9852 | } |
| 9853 | |
| 9854 | cf->id = interp->callFrameEpoch++; |
| 9855 | cf->parent = parent; |
| 9856 | cf->level = parent ? parent->level + 1 : 0; |
| 9857 | cf->argv = NULL; |
| 9858 | cf->argc = 0; |
| 9859 | cf->procArgsObjPtr = NULL; |
| 9860 | cf->procBodyObjPtr = NULL; |
| 9861 | cf->next = NULL; |
| 9862 | cf->staticVars = NULL; |
| 9863 | cf->localCommands = NULL; |
| 9864 | |
| 9865 | cf->nsObj = nsObj; |
| 9866 | Jim_IncrRefCount(nsObj); |
| 9867 | if (cf->vars.table == NULL) |
| 9868 | Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); |
| 9869 | return cf; |
| 9870 | } |
| 9871 | |
| 9872 | |
| 9873 | static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf) |
| 9874 | { |
| 9875 | cf->id = interp->callFrameEpoch++; |
| 9876 | } |
| 9877 | |
| 9878 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 9879 | { |
| 9880 | |
| 9881 | if (localCommands) { |
| 9882 | Jim_Obj *cmdNameObj; |
| 9883 | |
| 9884 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 9885 | Jim_HashEntry *he; |
| 9886 | Jim_Obj *fqObjName; |
| 9887 | |
| 9888 | const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); |
| 9889 | |
| 9890 | he = Jim_FindHashEntry(&interp->commands, fqname); |
| 9891 | |
| 9892 | if (he) { |
| 9893 | Jim_Cmd *cmd = he->u.val; |
| 9894 | if (cmd->prevCmd) { |
| 9895 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 9896 | cmd->prevCmd = NULL; |
| 9897 | |
| 9898 | |
| 9899 | JimDecrCmdRefCount(interp, cmd); |
| 9900 | |
| 9901 | |
| 9902 | he->u.val = prevCmd; |
| 9903 | } |
| 9904 | else { |
| 9905 | Jim_DeleteHashEntry(&interp->commands, fqname); |
| 9906 | Jim_InterpIncrProcEpoch(interp); |
| 9907 | } |
| 9908 | } |
| 9909 | Jim_DecrRefCount(interp, cmdNameObj); |
| 9910 | JimFreeQualifiedName(interp, fqObjName); |
| @@ -9914,47 +10060,45 @@ | |
| 9914 | } |
| 9915 | return JIM_OK; |
| 9916 | } |
| 9917 | |
| 9918 | |
| 9919 | #define JIM_FCF_NONE 0 |
| 9920 | #define JIM_FCF_NOHT 1 |
| 9921 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags) |
| 9922 | { |
| 9923 | if (cf->procArgsObjPtr) |
| 9924 | Jim_DecrRefCount(interp, cf->procArgsObjPtr); |
| 9925 | if (cf->procBodyObjPtr) |
| 9926 | Jim_DecrRefCount(interp, cf->procBodyObjPtr); |
| 9927 | Jim_DecrRefCount(interp, cf->nsObj); |
| 9928 | if (!(flags & JIM_FCF_NOHT)) |
| 9929 | Jim_FreeHashTable(&cf->vars); |
| 9930 | else { |
| 9931 | int i; |
| 9932 | Jim_HashEntry **table = cf->vars.table, *he; |
| 9933 | |
| 9934 | for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { |
| 9935 | he = table[i]; |
| 9936 | while (he != NULL) { |
| 9937 | Jim_HashEntry *nextEntry = he->next; |
| 9938 | Jim_Var *varPtr = (void *)he->u.val; |
| 9939 | |
| 9940 | Jim_DecrRefCount(interp, varPtr->objPtr); |
| 9941 | Jim_Free(he->u.val); |
| 9942 | Jim_Free((void *)he->key); |
| 9943 | Jim_Free(he); |
| 9944 | table[i] = NULL; |
| 9945 | he = nextEntry; |
| 9946 | } |
| 9947 | } |
| 9948 | cf->vars.used = 0; |
| 9949 | } |
| 9950 | |
| 9951 | JimDeleteLocalProcs(interp, cf->localCommands); |
| 9952 | |
| 9953 | cf->next = interp->freeFramesList; |
| 9954 | interp->freeFramesList = cf; |
| 9955 | |
| 9956 | } |
| 9957 | |
| 9958 | |
| 9959 | #ifdef JIM_REFERENCES |
| 9960 | |
| @@ -10031,21 +10175,16 @@ | |
| 10031 | NULL, |
| 10032 | UpdateStringOfReference, |
| 10033 | JIM_TYPE_REFERENCES, |
| 10034 | }; |
| 10035 | |
| 10036 | void UpdateStringOfReference(struct Jim_Obj *objPtr) |
| 10037 | { |
| 10038 | int len; |
| 10039 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 10040 | Jim_Reference *refPtr; |
| 10041 | |
| 10042 | refPtr = objPtr->internalRep.refValue.refPtr; |
| 10043 | len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id); |
| 10044 | objPtr->bytes = Jim_Alloc(len + 1); |
| 10045 | memcpy(objPtr->bytes, buf, len + 1); |
| 10046 | objPtr->length = len; |
| 10047 | } |
| 10048 | |
| 10049 | static int isrefchar(int c) |
| 10050 | { |
| 10051 | return (c == '_' || isalnum(c)); |
| @@ -10096,11 +10235,11 @@ | |
| 10096 | he = Jim_FindHashEntry(&interp->references, &value); |
| 10097 | if (he == NULL) { |
| 10098 | Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); |
| 10099 | return JIM_ERR; |
| 10100 | } |
| 10101 | refPtr = he->u.val; |
| 10102 | |
| 10103 | Jim_FreeIntRep(interp, objPtr); |
| 10104 | objPtr->typePtr = &referenceObjType; |
| 10105 | objPtr->internalRep.refValue.id = value; |
| 10106 | objPtr->internalRep.refValue.refPtr = refPtr; |
| @@ -10279,13 +10418,20 @@ | |
| 10279 | return i; |
| 10280 | } |
| 10281 | |
| 10282 | void Jim_FreeInterp(Jim_Interp *i) |
| 10283 | { |
| 10284 | Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf; |
| 10285 | Jim_Obj *objPtr, *nextObjPtr; |
| 10286 | |
| 10287 | Jim_DecrRefCount(i, i->emptyObj); |
| 10288 | Jim_DecrRefCount(i, i->trueObj); |
| 10289 | Jim_DecrRefCount(i, i->falseObj); |
| 10290 | Jim_DecrRefCount(i, i->result); |
| 10291 | Jim_DecrRefCount(i, i->stackTrace); |
| @@ -10300,61 +10446,54 @@ | |
| 10300 | #endif |
| 10301 | Jim_FreeHashTable(&i->packages); |
| 10302 | Jim_Free(i->prngState); |
| 10303 | Jim_FreeHashTable(&i->assocData); |
| 10304 | |
| 10305 | |
| 10306 | while (cf) { |
| 10307 | prevcf = cf->parent; |
| 10308 | JimFreeCallFrame(i, cf, JIM_FCF_NONE); |
| 10309 | cf = prevcf; |
| 10310 | } |
| 10311 | if (i->liveList != NULL) { |
| 10312 | objPtr = i->liveList; |
| 10313 | |
| 10314 | printf(JIM_NL "-------------------------------------" JIM_NL); |
| 10315 | printf("Objects still in the free list:" JIM_NL); |
| 10316 | while (objPtr) { |
| 10317 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10318 | |
| 10319 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10320 | printf("%p (%d) %-10s: '%.20s...'" JIM_NL, |
| 10321 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10322 | } |
| 10323 | else { |
| 10324 | printf("%p (%d) %-10s: '%s'" JIM_NL, |
| 10325 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); |
| 10326 | } |
| 10327 | if (objPtr->typePtr == &sourceObjType) { |
| 10328 | printf("FILE %s LINE %d" JIM_NL, |
| 10329 | Jim_String(objPtr->internalRep.sourceValue.fileNameObj), |
| 10330 | objPtr->internalRep.sourceValue.lineNumber); |
| 10331 | } |
| 10332 | objPtr = objPtr->nextObjPtr; |
| 10333 | } |
| 10334 | printf("-------------------------------------" JIM_NL JIM_NL); |
| 10335 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10336 | } |
| 10337 | |
| 10338 | objPtr = i->freeList; |
| 10339 | while (objPtr) { |
| 10340 | nextObjPtr = objPtr->nextObjPtr; |
| 10341 | Jim_Free(objPtr); |
| 10342 | objPtr = nextObjPtr; |
| 10343 | } |
| 10344 | |
| 10345 | cf = i->freeFramesList; |
| 10346 | while (cf) { |
| 10347 | nextcf = cf->next; |
| 10348 | if (cf->vars.table != NULL) |
| 10349 | Jim_Free(cf->vars.table); |
| 10350 | Jim_Free(cf); |
| 10351 | cf = nextcf; |
| 10352 | } |
| 10353 | #ifdef jim_ext_load |
| 10354 | Jim_FreeLoadHandles(i); |
| 10355 | #endif |
| 10356 | |
| 10357 | |
| 10358 | Jim_Free(i); |
| 10359 | } |
| 10360 | |
| @@ -10455,11 +10594,10 @@ | |
| 10455 | interp->addStackTrace = 1; |
| 10456 | } |
| 10457 | } |
| 10458 | } |
| 10459 | |
| 10460 | |
| 10461 | static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, |
| 10462 | Jim_Obj *fileNameObj, int linenr) |
| 10463 | { |
| 10464 | if (strcmp(procname, "unknown") == 0) { |
| 10465 | procname = ""; |
| @@ -10513,12 +10651,11 @@ | |
| 10513 | void *Jim_GetAssocData(Jim_Interp *interp, const char *key) |
| 10514 | { |
| 10515 | Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); |
| 10516 | |
| 10517 | if (entryPtr != NULL) { |
| 10518 | AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val; |
| 10519 | |
| 10520 | return assocEntryPtr->data; |
| 10521 | } |
| 10522 | return NULL; |
| 10523 | } |
| 10524 | |
| @@ -10552,20 +10689,44 @@ | |
| 10552 | }; |
| 10553 | |
| 10554 | |
| 10555 | static void UpdateStringOfInt(struct Jim_Obj *objPtr) |
| 10556 | { |
| 10557 | int len; |
| 10558 | char buf[JIM_INTEGER_SPACE + 1]; |
| 10559 | |
| 10560 | len = JimWideToString(buf, JimWideValue(objPtr)); |
| 10561 | objPtr->bytes = Jim_Alloc(len + 1); |
| 10562 | memcpy(objPtr->bytes, buf, len + 1); |
| 10563 | objPtr->length = len; |
| 10564 | } |
| 10565 | |
| 10566 | int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 10567 | { |
| 10568 | jim_wide wideValue; |
| 10569 | const char *str; |
| 10570 | |
| 10571 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| @@ -10653,22 +10814,65 @@ | |
| 10653 | NULL, |
| 10654 | UpdateStringOfDouble, |
| 10655 | JIM_TYPE_NONE, |
| 10656 | }; |
| 10657 | |
| 10658 | void UpdateStringOfDouble(struct Jim_Obj *objPtr) |
| 10659 | { |
| 10660 | int len; |
| 10661 | char buf[JIM_DOUBLE_SPACE + 1]; |
| 10662 | |
| 10663 | len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); |
| 10664 | objPtr->bytes = Jim_Alloc(len + 1); |
| 10665 | memcpy(objPtr->bytes, buf, len + 1); |
| 10666 | objPtr->length = len; |
| 10667 | } |
| 10668 | |
| 10669 | int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10670 | { |
| 10671 | double doubleValue; |
| 10672 | jim_wide wideValue; |
| 10673 | const char *str; |
| 10674 | |
| @@ -10876,15 +11080,15 @@ | |
| 10876 | return JIM_ELESTR_SIMPLE; |
| 10877 | } |
| 10878 | return JIM_ELESTR_QUOTE; |
| 10879 | } |
| 10880 | |
| 10881 | static int BackslashQuoteString(const char *s, char *q) |
| 10882 | { |
| 10883 | char *p = q; |
| 10884 | |
| 10885 | while (*s) { |
| 10886 | switch (*s) { |
| 10887 | case ' ': |
| 10888 | case '$': |
| 10889 | case '"': |
| 10890 | case '[': |
| @@ -10996,11 +11200,11 @@ | |
| 10996 | case JIM_ELESTR_QUOTE: |
| 10997 | if (i == 0 && strRep[0] == '#') { |
| 10998 | *p++ = '\\'; |
| 10999 | realLength++; |
| 11000 | } |
| 11001 | qlen = BackslashQuoteString(strRep, p); |
| 11002 | p += qlen; |
| 11003 | realLength += qlen; |
| 11004 | break; |
| 11005 | } |
| 11006 | |
| @@ -11032,11 +11236,11 @@ | |
| 11032 | |
| 11033 | if (objPtr->typePtr == &listObjType) { |
| 11034 | return JIM_OK; |
| 11035 | } |
| 11036 | |
| 11037 | if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) { |
| 11038 | Jim_Obj **listObjPtrPtr; |
| 11039 | int len; |
| 11040 | int i; |
| 11041 | |
| 11042 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| @@ -11136,15 +11340,17 @@ | |
| 11136 | Jim_Interp *interp; |
| 11137 | enum { |
| 11138 | JIM_LSORT_ASCII, |
| 11139 | JIM_LSORT_NOCASE, |
| 11140 | JIM_LSORT_INTEGER, |
| 11141 | JIM_LSORT_COMMAND |
| 11142 | } type; |
| 11143 | int order; |
| 11144 | int index; |
| 11145 | int indexed; |
| 11146 | int (*subfn)(Jim_Obj **, Jim_Obj **); |
| 11147 | }; |
| 11148 | |
| 11149 | static struct lsort_info *sort_info; |
| 11150 | |
| @@ -11179,10 +11385,27 @@ | |
| 11179 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11180 | } |
| 11181 | |
| 11182 | return JimSign(lhs - rhs) * sort_info->order; |
| 11183 | } |
| 11184 | |
| 11185 | static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11186 | { |
| 11187 | Jim_Obj *compare_script; |
| 11188 | int rc; |
| @@ -11201,10 +11424,34 @@ | |
| 11201 | } |
| 11202 | |
| 11203 | return JimSign(ret) * sort_info->order; |
| 11204 | } |
| 11205 | |
| 11206 | |
| 11207 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| 11208 | { |
| 11209 | struct lsort_info *prev_info; |
| 11210 | |
| @@ -11212,11 +11459,11 @@ | |
| 11212 | int (*fn) (Jim_Obj **, Jim_Obj **); |
| 11213 | Jim_Obj **vector; |
| 11214 | int len; |
| 11215 | int rc; |
| 11216 | |
| 11217 | JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object")); |
| 11218 | SetListFromAny(interp, listObjPtr); |
| 11219 | |
| 11220 | |
| 11221 | prev_info = sort_info; |
| 11222 | sort_info = info; |
| @@ -11231,10 +11478,13 @@ | |
| 11231 | fn = ListSortStringNoCase; |
| 11232 | break; |
| 11233 | case JIM_LSORT_INTEGER: |
| 11234 | fn = ListSortInteger; |
| 11235 | break; |
| 11236 | case JIM_LSORT_COMMAND: |
| 11237 | fn = ListSortCommand; |
| 11238 | break; |
| 11239 | default: |
| 11240 | fn = NULL; |
| @@ -11247,12 +11497,17 @@ | |
| 11247 | fn = ListSortIndexHelper; |
| 11248 | } |
| 11249 | |
| 11250 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| 11251 | qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); |
| 11252 | } |
| 11253 | Jim_InvalidateStringRep(listObjPtr); |
| 11254 | sort_info = prev_info; |
| 11255 | |
| 11256 | return rc; |
| 11257 | } |
| 11258 | |
| @@ -11377,11 +11632,11 @@ | |
| 11377 | listPtr->internalRep.listValue.ele[idx] = newObjPtr; |
| 11378 | Jim_IncrRefCount(newObjPtr); |
| 11379 | return JIM_OK; |
| 11380 | } |
| 11381 | |
| 11382 | int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, |
| 11383 | Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) |
| 11384 | { |
| 11385 | Jim_Obj *varObjPtr, *objPtr, *listObjPtr; |
| 11386 | int shared, i, idx; |
| 11387 | |
| @@ -11425,14 +11680,11 @@ | |
| 11425 | int i; |
| 11426 | int listLen = Jim_ListLength(interp, listObjPtr); |
| 11427 | Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); |
| 11428 | |
| 11429 | for (i = 0; i < listLen; ) { |
| 11430 | Jim_Obj *objPtr; |
| 11431 | |
| 11432 | Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); |
| 11433 | Jim_AppendObj(interp, resObjPtr, objPtr); |
| 11434 | if (++i != listLen) { |
| 11435 | Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); |
| 11436 | } |
| 11437 | } |
| 11438 | return resObjPtr; |
| @@ -11458,43 +11710,42 @@ | |
| 11458 | int len = 0, objLen; |
| 11459 | char *bytes, *p; |
| 11460 | |
| 11461 | |
| 11462 | for (i = 0; i < objc; i++) { |
| 11463 | Jim_GetString(objv[i], &objLen); |
| 11464 | len += objLen; |
| 11465 | } |
| 11466 | if (objc) |
| 11467 | len += objc - 1; |
| 11468 | |
| 11469 | p = bytes = Jim_Alloc(len + 1); |
| 11470 | for (i = 0; i < objc; i++) { |
| 11471 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11472 | |
| 11473 | |
| 11474 | while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) { |
| 11475 | s++; |
| 11476 | objLen--; |
| 11477 | len--; |
| 11478 | } |
| 11479 | |
| 11480 | while (objLen && (s[objLen - 1] == ' ' || |
| 11481 | s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) { |
| 11482 | |
| 11483 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11484 | break; |
| 11485 | } |
| 11486 | objLen--; |
| 11487 | len--; |
| 11488 | } |
| 11489 | memcpy(p, s, objLen); |
| 11490 | p += objLen; |
| 11491 | if (objLen && i + 1 != objc) { |
| 11492 | *p++ = ' '; |
| 11493 | } |
| 11494 | else if (i + 1 != objc) { |
| 11495 | len--; |
| 11496 | } |
| 11497 | } |
| 11498 | *p = '\0'; |
| 11499 | return Jim_NewStringObjNoAlloc(interp, bytes, len); |
| 11500 | } |
| @@ -11534,20 +11785,26 @@ | |
| 11534 | |
| 11535 | static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 11536 | { |
| 11537 | return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 11538 | } |
| 11539 | |
| 11540 | static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 11541 | { |
| 11542 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11543 | } |
| 11544 | |
| 11545 | static const Jim_HashTableType JimDictHashTableType = { |
| 11546 | JimObjectHTHashFunction, |
| 11547 | NULL, |
| 11548 | NULL, |
| 11549 | JimObjectHTKeyCompare, |
| 11550 | JimObjectHTKeyValDestructor, |
| 11551 | JimObjectHTKeyValDestructor |
| 11552 | }; |
| 11553 | |
| @@ -11580,16 +11837,11 @@ | |
| 11580 | if (ht->size != 0) |
| 11581 | Jim_ExpandHashTable(dupHt, ht->size); |
| 11582 | |
| 11583 | JimInitHashTableIterator(ht, &htiter); |
| 11584 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11585 | const Jim_Obj *keyObjPtr = he->key; |
| 11586 | Jim_Obj *valObjPtr = he->u.val; |
| 11587 | |
| 11588 | Jim_IncrRefCount((Jim_Obj *)keyObjPtr); |
| 11589 | Jim_IncrRefCount(valObjPtr); |
| 11590 | Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); |
| 11591 | } |
| 11592 | |
| 11593 | dupPtr->internalRep.ptr = dupHt; |
| 11594 | dupPtr->typePtr = &dictObjType; |
| 11595 | } |
| @@ -11607,12 +11859,12 @@ | |
| 11607 | |
| 11608 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 11609 | JimInitHashTableIterator(ht, &htiter); |
| 11610 | i = 0; |
| 11611 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11612 | objv[i++] = (Jim_Obj *)he->key; |
| 11613 | objv[i++] = he->u.val; |
| 11614 | } |
| 11615 | *len = i; |
| 11616 | return objv; |
| 11617 | } |
| 11618 | |
| @@ -11620,10 +11872,11 @@ | |
| 11620 | { |
| 11621 | |
| 11622 | int len; |
| 11623 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 11624 | |
| 11625 | JimMakeListStringRep(objPtr, objv, len); |
| 11626 | |
| 11627 | Jim_Free(objv); |
| 11628 | } |
| 11629 | |
| @@ -11633,11 +11886,13 @@ | |
| 11633 | |
| 11634 | if (objPtr->typePtr == &dictObjType) { |
| 11635 | return JIM_OK; |
| 11636 | } |
| 11637 | |
| 11638 | Jim_String(objPtr); |
| 11639 | |
| 11640 | |
| 11641 | listlen = Jim_ListLength(interp, objPtr); |
| 11642 | if (listlen % 2) { |
| 11643 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| @@ -11650,28 +11905,14 @@ | |
| 11650 | |
| 11651 | ht = Jim_Alloc(sizeof(*ht)); |
| 11652 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| 11653 | |
| 11654 | for (i = 0; i < listlen; i += 2) { |
| 11655 | Jim_Obj *keyObjPtr; |
| 11656 | Jim_Obj *valObjPtr; |
| 11657 | |
| 11658 | Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE); |
| 11659 | Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE); |
| 11660 | |
| 11661 | Jim_IncrRefCount(keyObjPtr); |
| 11662 | Jim_IncrRefCount(valObjPtr); |
| 11663 | |
| 11664 | if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) { |
| 11665 | Jim_HashEntry *he; |
| 11666 | |
| 11667 | he = Jim_FindHashEntry(ht, keyObjPtr); |
| 11668 | Jim_DecrRefCount(interp, keyObjPtr); |
| 11669 | |
| 11670 | Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); |
| 11671 | he->u.val = valObjPtr; |
| 11672 | } |
| 11673 | } |
| 11674 | |
| 11675 | Jim_FreeIntRep(interp, objPtr); |
| 11676 | objPtr->typePtr = &dictObjType; |
| 11677 | objPtr->internalRep.ptr = ht; |
| @@ -11688,31 +11929,23 @@ | |
| 11688 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 11689 | |
| 11690 | if (valueObjPtr == NULL) { |
| 11691 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 11692 | } |
| 11693 | Jim_IncrRefCount(keyObjPtr); |
| 11694 | Jim_IncrRefCount(valueObjPtr); |
| 11695 | if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) { |
| 11696 | |
| 11697 | Jim_DecrRefCount(interp, keyObjPtr); |
| 11698 | } |
| 11699 | return JIM_OK; |
| 11700 | } |
| 11701 | |
| 11702 | int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 11703 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 11704 | { |
| 11705 | int retcode; |
| 11706 | |
| 11707 | JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); |
| 11708 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 11709 | return JIM_ERR; |
| 11710 | } |
| 11711 | retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); |
| 11712 | Jim_InvalidateStringRep(objPtr); |
| 11713 | return retcode; |
| 11714 | } |
| 11715 | |
| 11716 | Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) |
| 11717 | { |
| 11718 | Jim_Obj *objPtr; |
| @@ -11839,10 +12072,11 @@ | |
| 11839 | } |
| 11840 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 11841 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 11842 | } |
| 11843 | } |
| 11844 | Jim_InvalidateStringRep(objPtr); |
| 11845 | Jim_InvalidateStringRep(varObjPtr); |
| 11846 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 11847 | goto err; |
| 11848 | } |
| @@ -11864,28 +12098,29 @@ | |
| 11864 | NULL, |
| 11865 | UpdateStringOfIndex, |
| 11866 | JIM_TYPE_NONE, |
| 11867 | }; |
| 11868 | |
| 11869 | void UpdateStringOfIndex(struct Jim_Obj *objPtr) |
| 11870 | { |
| 11871 | int len; |
| 11872 | char buf[JIM_INTEGER_SPACE + 1]; |
| 11873 | |
| 11874 | if (objPtr->internalRep.intValue >= 0) |
| 11875 | len = sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 11876 | else if (objPtr->internalRep.intValue == -1) |
| 11877 | len = sprintf(buf, "end"); |
| 11878 | else { |
| 11879 | len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 11880 | } |
| 11881 | objPtr->bytes = Jim_Alloc(len + 1); |
| 11882 | memcpy(objPtr->bytes, buf, len + 1); |
| 11883 | objPtr->length = len; |
| 11884 | } |
| 11885 | |
| 11886 | int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 11887 | { |
| 11888 | int idx, end = 0; |
| 11889 | const char *str; |
| 11890 | char *endptr; |
| 11891 | |
| @@ -11953,14 +12188,17 @@ | |
| 11953 | { |
| 11954 | |
| 11955 | if (objPtr->typePtr == &intObjType) { |
| 11956 | jim_wide val = JimWideValue(objPtr); |
| 11957 | |
| 11958 | if (!(val < LONG_MIN) && !(val > LONG_MAX)) { |
| 11959 | *indexPtr = (val < 0) ? -INT_MAX : (long)val;; |
| 11960 | return JIM_OK; |
| 11961 | } |
| 11962 | } |
| 11963 | if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) |
| 11964 | return JIM_ERR; |
| 11965 | *indexPtr = objPtr->internalRep.intValue; |
| 11966 | return JIM_OK; |
| @@ -11980,12 +12218,10 @@ | |
| 11980 | NULL |
| 11981 | }; |
| 11982 | |
| 11983 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) |
| 11984 | |
| 11985 | static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| 11986 | |
| 11987 | static const Jim_ObjType returnCodeObjType = { |
| 11988 | "return-code", |
| 11989 | NULL, |
| 11990 | NULL, |
| 11991 | NULL, |
| @@ -12000,11 +12236,11 @@ | |
| 12000 | else { |
| 12001 | return jimReturnCodes[code]; |
| 12002 | } |
| 12003 | } |
| 12004 | |
| 12005 | int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12006 | { |
| 12007 | int returnCode; |
| 12008 | jim_wide wideValue; |
| 12009 | |
| 12010 | |
| @@ -12152,24 +12388,21 @@ | |
| 12152 | return e->stack[--e->stacklen]; |
| 12153 | } |
| 12154 | |
| 12155 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12156 | { |
| 12157 | int intresult = 0; |
| 12158 | int rc = JIM_OK; |
| 12159 | Jim_Obj *A = ExprPop(e); |
| 12160 | double dA, dC = 0; |
| 12161 | jim_wide wA, wC = 0; |
| 12162 | |
| 12163 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12164 | intresult = 1; |
| 12165 | |
| 12166 | switch (e->opcode) { |
| 12167 | case JIM_EXPROP_FUNC_INT: |
| 12168 | wC = wA; |
| 12169 | break; |
| 12170 | case JIM_EXPROP_FUNC_ROUND: |
| 12171 | wC = wA; |
| 12172 | break; |
| 12173 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12174 | dC = wA; |
| 12175 | intresult = 0; |
| @@ -12178,13 +12411,10 @@ | |
| 12178 | wC = wA >= 0 ? wA : -wA; |
| 12179 | break; |
| 12180 | case JIM_EXPROP_UNARYMINUS: |
| 12181 | wC = -wA; |
| 12182 | break; |
| 12183 | case JIM_EXPROP_UNARYPLUS: |
| 12184 | wC = wA; |
| 12185 | break; |
| 12186 | case JIM_EXPROP_NOT: |
| 12187 | wC = !wA; |
| 12188 | break; |
| 12189 | default: |
| 12190 | abort(); |
| @@ -12192,31 +12422,29 @@ | |
| 12192 | } |
| 12193 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12194 | switch (e->opcode) { |
| 12195 | case JIM_EXPROP_FUNC_INT: |
| 12196 | wC = dA; |
| 12197 | intresult = 1; |
| 12198 | break; |
| 12199 | case JIM_EXPROP_FUNC_ROUND: |
| 12200 | wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); |
| 12201 | intresult = 1; |
| 12202 | break; |
| 12203 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12204 | dC = dA; |
| 12205 | break; |
| 12206 | case JIM_EXPROP_FUNC_ABS: |
| 12207 | dC = dA >= 0 ? dA : -dA; |
| 12208 | break; |
| 12209 | case JIM_EXPROP_UNARYMINUS: |
| 12210 | dC = -dA; |
| 12211 | break; |
| 12212 | case JIM_EXPROP_UNARYPLUS: |
| 12213 | dC = dA; |
| 12214 | break; |
| 12215 | case JIM_EXPROP_NOT: |
| 12216 | wC = !dA; |
| 12217 | intresult = 1; |
| 12218 | break; |
| 12219 | default: |
| 12220 | abort(); |
| 12221 | } |
| 12222 | } |
| @@ -12427,11 +12655,11 @@ | |
| 12427 | |
| 12428 | |
| 12429 | |
| 12430 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) |
| 12431 | { |
| 12432 | int intresult = 0; |
| 12433 | int rc = JIM_OK; |
| 12434 | double dA, dB, dC = 0; |
| 12435 | jim_wide wA, wB, wC = 0; |
| 12436 | |
| 12437 | Jim_Obj *B = ExprPop(e); |
| @@ -12441,12 +12669,10 @@ | |
| 12441 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12442 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12443 | |
| 12444 | |
| 12445 | |
| 12446 | intresult = 1; |
| 12447 | |
| 12448 | switch (e->opcode) { |
| 12449 | case JIM_EXPROP_POW: |
| 12450 | case JIM_EXPROP_FUNC_POW: |
| 12451 | wC = JimPowWide(wA, wB); |
| 12452 | break; |
| @@ -12496,10 +12722,11 @@ | |
| 12496 | default: |
| 12497 | abort(); |
| 12498 | } |
| 12499 | } |
| 12500 | else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12501 | switch (e->opcode) { |
| 12502 | case JIM_EXPROP_POW: |
| 12503 | case JIM_EXPROP_FUNC_POW: |
| 12504 | #ifdef JIM_MATH_FUNCTIONS |
| 12505 | dC = pow(dA, dB); |
| @@ -12561,12 +12788,10 @@ | |
| 12561 | |
| 12562 | |
| 12563 | |
| 12564 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 12565 | |
| 12566 | intresult = 1; |
| 12567 | |
| 12568 | switch (e->opcode) { |
| 12569 | case JIM_EXPROP_LT: |
| 12570 | wC = i < 0; |
| 12571 | break; |
| 12572 | case JIM_EXPROP_GT: |
| @@ -12610,15 +12835,11 @@ | |
| 12610 | int listlen; |
| 12611 | int i; |
| 12612 | |
| 12613 | listlen = Jim_ListLength(interp, listObjPtr); |
| 12614 | for (i = 0; i < listlen; i++) { |
| 12615 | Jim_Obj *objPtr; |
| 12616 | |
| 12617 | Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); |
| 12618 | |
| 12619 | if (Jim_StringEqObj(objPtr, valObj)) { |
| 12620 | return 1; |
| 12621 | } |
| 12622 | } |
| 12623 | return 0; |
| 12624 | } |
| @@ -12630,23 +12851,16 @@ | |
| 12630 | |
| 12631 | jim_wide wC; |
| 12632 | |
| 12633 | switch (e->opcode) { |
| 12634 | case JIM_EXPROP_STREQ: |
| 12635 | case JIM_EXPROP_STRNE: { |
| 12636 | int Alen, Blen; |
| 12637 | const char *sA = Jim_GetString(A, &Alen); |
| 12638 | const char *sB = Jim_GetString(B, &Blen); |
| 12639 | |
| 12640 | if (e->opcode == JIM_EXPROP_STREQ) { |
| 12641 | wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0); |
| 12642 | } |
| 12643 | else { |
| 12644 | wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0); |
| 12645 | } |
| 12646 | break; |
| 12647 | } |
| 12648 | case JIM_EXPROP_STRIN: |
| 12649 | wC = JimSearchList(interp, B, A); |
| 12650 | break; |
| 12651 | case JIM_EXPROP_STRNI: |
| 12652 | wC = !JimSearchList(interp, B, A); |
| @@ -12818,96 +13032,98 @@ | |
| 12818 | LAZY_OP, |
| 12819 | LAZY_LEFT, |
| 12820 | LAZY_RIGHT |
| 12821 | }; |
| 12822 | |
| 12823 | #define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} |
| 12824 | |
| 12825 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 12826 | OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE), |
| 12827 | OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE), |
| 12828 | OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE), |
| 12829 | |
| 12830 | OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE), |
| 12831 | OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE), |
| 12832 | |
| 12833 | OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE), |
| 12834 | OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE), |
| 12835 | |
| 12836 | OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE), |
| 12837 | OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE), |
| 12838 | |
| 12839 | OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE), |
| 12840 | OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE), |
| 12841 | OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE), |
| 12842 | OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE), |
| 12843 | |
| 12844 | OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE), |
| 12845 | OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE), |
| 12846 | |
| 12847 | OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE), |
| 12848 | OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE), |
| 12849 | OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE), |
| 12850 | |
| 12851 | OPRINIT("&&", 10, 2, NULL, LAZY_OP), |
| 12852 | OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), |
| 12853 | OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 12854 | |
| 12855 | OPRINIT("||", 9, 2, NULL, LAZY_OP), |
| 12856 | OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), |
| 12857 | OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 12858 | |
| 12859 | OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP), |
| 12860 | OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), |
| 12861 | OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 12862 | |
| 12863 | OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP), |
| 12864 | OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), |
| 12865 | OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 12866 | |
| 12867 | OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE), |
| 12868 | |
| 12869 | OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE), |
| 12870 | OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE), |
| 12871 | |
| 12872 | OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE), |
| 12873 | OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE), |
| 12874 | |
| 12875 | OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12876 | OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE), |
| 12877 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12878 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12879 | |
| 12880 | |
| 12881 | |
| 12882 | OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12883 | OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12884 | OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12885 | OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE), |
| 12886 | OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE), |
| 12887 | OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE), |
| 12888 | |
| 12889 | #ifdef JIM_MATH_FUNCTIONS |
| 12890 | OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12891 | OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12892 | OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12893 | OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12894 | OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12895 | OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12896 | OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12897 | OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12898 | OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12899 | OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12900 | OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12901 | OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12902 | OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12903 | OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12904 | OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), |
| 12905 | OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE), |
| 12906 | #endif |
| 12907 | }; |
| 12908 | #undef OPRINIT |
| 12909 | |
| 12910 | #define JIM_EXPR_OPERATORS_NUM \ |
| 12911 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 12912 | |
| 12913 | static int JimParseExpression(struct JimParserCtx *pc) |
| @@ -12919,13 +13135,16 @@ | |
| 12919 | } |
| 12920 | pc->p++; |
| 12921 | pc->len--; |
| 12922 | } |
| 12923 | |
| 12924 | if (pc->len == 0) { |
| 12925 | pc->tstart = pc->tend = pc->p; |
| 12926 | pc->tline = pc->linenr; |
| 12927 | pc->tt = JIM_TT_EOL; |
| 12928 | pc->eof = 1; |
| 12929 | return JIM_OK; |
| 12930 | } |
| 12931 | switch (*(pc->p)) { |
| @@ -12936,12 +13155,11 @@ | |
| 12936 | pc->tt = JIM_TT_SUBEXPR_END; |
| 12937 | goto singlechar; |
| 12938 | case ',': |
| 12939 | pc->tt = JIM_TT_SUBEXPR_COMMA; |
| 12940 | singlechar: |
| 12941 | pc->tstart = pc->tend = pc->p; |
| 12942 | pc->tline = pc->linenr; |
| 12943 | pc->p++; |
| 12944 | pc->len--; |
| 12945 | break; |
| 12946 | case '[': |
| 12947 | return JimParseCmd(pc); |
| @@ -12987,82 +13205,44 @@ | |
| 12987 | return JIM_OK; |
| 12988 | } |
| 12989 | |
| 12990 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 12991 | { |
| 12992 | int allowdot = 1; |
| 12993 | int base = 10; |
| 12994 | |
| 12995 | |
| 12996 | pc->tt = JIM_TT_EXPR_INT; |
| 12997 | pc->tstart = pc->p; |
| 12998 | pc->tline = pc->linenr; |
| 12999 | |
| 13000 | |
| 13001 | if (pc->p[0] == '0') { |
| 13002 | switch (pc->p[1]) { |
| 13003 | case 'x': |
| 13004 | case 'X': |
| 13005 | base = 16; |
| 13006 | allowdot = 0; |
| 13007 | pc->p += 2; |
| 13008 | pc->len -= 2; |
| 13009 | break; |
| 13010 | case 'o': |
| 13011 | case 'O': |
| 13012 | base = 8; |
| 13013 | allowdot = 0; |
| 13014 | pc->p += 2; |
| 13015 | pc->len -= 2; |
| 13016 | break; |
| 13017 | case 'b': |
| 13018 | case 'B': |
| 13019 | base = 2; |
| 13020 | allowdot = 0; |
| 13021 | pc->p += 2; |
| 13022 | pc->len -= 2; |
| 13023 | break; |
| 13024 | } |
| 13025 | } |
| 13026 | |
| 13027 | while (isdigit(UCHAR(*pc->p)) |
| 13028 | || (base == 16 && isxdigit(UCHAR(*pc->p))) |
| 13029 | || (base == 8 && *pc->p >= '0' && *pc->p <= '7') |
| 13030 | || (base == 2 && (*pc->p == '0' || *pc->p == '1')) |
| 13031 | || (allowdot && *pc->p == '.') |
| 13032 | ) { |
| 13033 | if (*pc->p == '.') { |
| 13034 | allowdot = 0; |
| 13035 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13036 | } |
| 13037 | pc->p++; |
| 13038 | pc->len--; |
| 13039 | if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+' |
| 13040 | || isdigit(UCHAR(pc->p[1])))) { |
| 13041 | pc->p += 2; |
| 13042 | pc->len -= 2; |
| 13043 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13044 | } |
| 13045 | } |
| 13046 | pc->tend = pc->p - 1; |
| 13047 | return JIM_OK; |
| 13048 | } |
| 13049 | |
| 13050 | static int JimParseExprIrrational(struct JimParserCtx *pc) |
| 13051 | { |
| 13052 | const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; |
| 13053 | const char **token; |
| 13054 | |
| 13055 | for (token = Tokens; *token != NULL; token++) { |
| 13056 | int len = strlen(*token); |
| 13057 | |
| 13058 | if (strncmp(*token, pc->p, len) == 0) { |
| 13059 | pc->tstart = pc->p; |
| 13060 | pc->tend = pc->p + len - 1; |
| 13061 | pc->p += len; |
| 13062 | pc->len -= len; |
| 13063 | pc->tline = pc->linenr; |
| 13064 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13065 | return JIM_OK; |
| 13066 | } |
| 13067 | } |
| 13068 | return JIM_ERR; |
| @@ -13102,15 +13282,13 @@ | |
| 13102 | } |
| 13103 | if (*p != '(') { |
| 13104 | return JIM_ERR; |
| 13105 | } |
| 13106 | } |
| 13107 | pc->tstart = pc->p; |
| 13108 | pc->tend = pc->p + bestLen - 1; |
| 13109 | pc->p += bestLen; |
| 13110 | pc->len -= bestLen; |
| 13111 | pc->tline = pc->linenr; |
| 13112 | |
| 13113 | pc->tt = bestIdx; |
| 13114 | return JIM_OK; |
| 13115 | } |
| 13116 | |
| @@ -13608,17 +13786,23 @@ | |
| 13608 | } |
| 13609 | |
| 13610 | #ifdef DEBUG_SHOW_EXPR_TOKENS |
| 13611 | { |
| 13612 | int i; |
| 13613 | printf("==== Expr Tokens ====\n"); |
| 13614 | for (i = 0; i < tokenlist.count; i++) { |
| 13615 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), |
| 13616 | tokenlist.list[i].len, tokenlist.list[i].token); |
| 13617 | } |
| 13618 | } |
| 13619 | #endif |
| 13620 | |
| 13621 | |
| 13622 | expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); |
| 13623 | |
| 13624 | |
| @@ -13665,10 +13849,24 @@ | |
| 13665 | return NULL; |
| 13666 | } |
| 13667 | } |
| 13668 | return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); |
| 13669 | } |
| 13670 | |
| 13671 | #define JIM_EE_STATICSTACK_LEN 10 |
| 13672 | |
| 13673 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) |
| 13674 | { |
| @@ -13688,102 +13886,69 @@ | |
| 13688 | Jim_Obj *objPtr; |
| 13689 | |
| 13690 | |
| 13691 | switch (expr->len) { |
| 13692 | case 1: |
| 13693 | if (expr->token[0].type == JIM_TT_EXPR_INT) { |
| 13694 | *exprResultPtrPtr = expr->token[0].objPtr; |
| 13695 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13696 | return JIM_OK; |
| 13697 | } |
| 13698 | if (expr->token[0].type == JIM_TT_VAR) { |
| 13699 | objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG); |
| 13700 | if (objPtr) { |
| 13701 | *exprResultPtrPtr = objPtr; |
| 13702 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13703 | return JIM_OK; |
| 13704 | } |
| 13705 | } |
| 13706 | break; |
| 13707 | |
| 13708 | case 2: |
| 13709 | if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) { |
| 13710 | jim_wide wideValue; |
| 13711 | |
| 13712 | objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); |
| 13713 | if (objPtr && JimIsWide(objPtr) |
| 13714 | && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) { |
| 13715 | *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj; |
| 13716 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13717 | return JIM_OK; |
| 13718 | } |
| 13719 | } |
| 13720 | break; |
| 13721 | |
| 13722 | case 3: |
| 13723 | if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT |
| 13724 | || expr->token[1].type == JIM_TT_VAR)) { |
| 13725 | switch (expr->token[2].type) { |
| 13726 | case JIM_EXPROP_LT: |
| 13727 | case JIM_EXPROP_LTE: |
| 13728 | case JIM_EXPROP_GT: |
| 13729 | case JIM_EXPROP_GTE: |
| 13730 | case JIM_EXPROP_NUMEQ: |
| 13731 | case JIM_EXPROP_NUMNE:{ |
| 13732 | |
| 13733 | jim_wide wideValueA; |
| 13734 | jim_wide wideValueB; |
| 13735 | |
| 13736 | objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); |
| 13737 | if (objPtr && JimIsWide(objPtr) |
| 13738 | && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) { |
| 13739 | if (expr->token[1].type == JIM_TT_VAR) { |
| 13740 | objPtr = |
| 13741 | Jim_GetVariable(interp, expr->token[1].objPtr, |
| 13742 | JIM_NONE); |
| 13743 | } |
| 13744 | else { |
| 13745 | objPtr = expr->token[1].objPtr; |
| 13746 | } |
| 13747 | if (objPtr && JimIsWide(objPtr) |
| 13748 | && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) { |
| 13749 | int cmpRes; |
| 13750 | |
| 13751 | switch (expr->token[2].type) { |
| 13752 | case JIM_EXPROP_LT: |
| 13753 | cmpRes = wideValueA < wideValueB; |
| 13754 | break; |
| 13755 | case JIM_EXPROP_LTE: |
| 13756 | cmpRes = wideValueA <= wideValueB; |
| 13757 | break; |
| 13758 | case JIM_EXPROP_GT: |
| 13759 | cmpRes = wideValueA > wideValueB; |
| 13760 | break; |
| 13761 | case JIM_EXPROP_GTE: |
| 13762 | cmpRes = wideValueA >= wideValueB; |
| 13763 | break; |
| 13764 | case JIM_EXPROP_NUMEQ: |
| 13765 | cmpRes = wideValueA == wideValueB; |
| 13766 | break; |
| 13767 | case JIM_EXPROP_NUMNE: |
| 13768 | cmpRes = wideValueA != wideValueB; |
| 13769 | break; |
| 13770 | default: |
| 13771 | cmpRes = 0; |
| 13772 | } |
| 13773 | *exprResultPtrPtr = |
| 13774 | cmpRes ? interp->trueObj : interp->falseObj; |
| 13775 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13776 | return JIM_OK; |
| 13777 | } |
| 13778 | } |
| 13779 | } |
| 13780 | } |
| 13781 | } |
| 13782 | break; |
| 13783 | } |
| 13784 | } |
| 13785 | #endif |
| 13786 | |
| 13787 | expr->inUse++; |
| 13788 | |
| 13789 | |
| @@ -13952,16 +14117,13 @@ | |
| 13952 | memcpy(newVec, srcPtr->internalRep.ptr, size); |
| 13953 | dupPtr->internalRep.ptr = newVec; |
| 13954 | dupPtr->typePtr = &scanFmtStringObjType; |
| 13955 | } |
| 13956 | |
| 13957 | void UpdateStringOfScanFmt(Jim_Obj *objPtr) |
| 13958 | { |
| 13959 | char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep; |
| 13960 | |
| 13961 | objPtr->bytes = Jim_StrDup(bytes); |
| 13962 | objPtr->length = strlen(bytes); |
| 13963 | } |
| 13964 | |
| 13965 | |
| 13966 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13967 | { |
| @@ -14171,11 +14333,10 @@ | |
| 14171 | Jim_Obj *tmpObj = NULL; |
| 14172 | |
| 14173 | |
| 14174 | *valObjPtr = 0; |
| 14175 | if (descr->prefix) { |
| 14176 | |
| 14177 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14178 | |
| 14179 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14180 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14181 | ++pos; |
| @@ -14512,34 +14673,55 @@ | |
| 14512 | } |
| 14513 | |
| 14514 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14515 | { |
| 14516 | int retcode; |
| 14517 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| 14518 | |
| 14519 | if (cmdPtr == NULL) { |
| 14520 | return JimUnknown(interp, objc, objv); |
| 14521 | } |
| 14522 | if (interp->evalDepth == interp->maxEvalDepth) { |
| 14523 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14524 | return JIM_ERR; |
| 14525 | } |
| 14526 | interp->evalDepth++; |
| 14527 | |
| 14528 | |
| 14529 | JimIncrCmdRefCount(cmdPtr); |
| 14530 | Jim_SetEmptyResult(interp); |
| 14531 | if (cmdPtr->isproc) { |
| 14532 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14533 | } |
| 14534 | else { |
| 14535 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14536 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14537 | } |
| 14538 | JimDecrCmdRefCount(interp, cmdPtr); |
| 14539 | interp->evalDepth--; |
| 14540 | |
| 14541 | return retcode; |
| 14542 | } |
| 14543 | |
| 14544 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14545 | { |
| @@ -14717,10 +14899,15 @@ | |
| 14717 | objPtr->typePtr = &interpolatedObjType; |
| 14718 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 14719 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 14720 | Jim_IncrRefCount(intv[2]); |
| 14721 | } |
| 14722 | |
| 14723 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| 14724 | objPtr->length = totlen; |
| 14725 | for (i = 0; i < tokens; i++) { |
| 14726 | if (intv[i]) { |
| @@ -14772,10 +14959,14 @@ | |
| 14772 | return JimEvalObjList(interp, scriptObjPtr); |
| 14773 | } |
| 14774 | |
| 14775 | Jim_IncrRefCount(scriptObjPtr); |
| 14776 | script = Jim_GetScript(interp, scriptObjPtr); |
| 14777 | |
| 14778 | Jim_SetEmptyResult(interp); |
| 14779 | |
| 14780 | token = script->token; |
| 14781 | |
| @@ -15046,26 +15237,20 @@ | |
| 15046 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15047 | } |
| 15048 | |
| 15049 | |
| 15050 | interp->framePtr = interp->framePtr->parent; |
| 15051 | if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { |
| 15052 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); |
| 15053 | } |
| 15054 | else { |
| 15055 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); |
| 15056 | } |
| 15057 | |
| 15058 | return retcode; |
| 15059 | } |
| 15060 | #endif |
| 15061 | |
| 15062 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) |
| 15063 | { |
| 15064 | Jim_CallFrame *callFramePtr; |
| 15065 | int i, d, retcode, optargs; |
| 15066 | Jim_Stack *localCommands; |
| 15067 | ScriptObj *script; |
| 15068 | |
| 15069 | |
| 15070 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15071 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| @@ -15145,37 +15330,42 @@ | |
| 15145 | |
| 15146 | |
| 15147 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15148 | |
| 15149 | badargset: |
| 15150 | |
| 15151 | |
| 15152 | localCommands = callFramePtr->localCommands; |
| 15153 | callFramePtr->localCommands = NULL; |
| 15154 | |
| 15155 | interp->framePtr = interp->framePtr->parent; |
| 15156 | if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { |
| 15157 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); |
| 15158 | } |
| 15159 | else { |
| 15160 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); |
| 15161 | } |
| 15162 | |
| 15163 | |
| 15164 | while (retcode == JIM_EVAL) { |
| 15165 | Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); |
| 15166 | |
| 15167 | Jim_IncrRefCount(resultScriptObjPtr); |
| 15168 | |
| 15169 | JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list")); |
| 15170 | |
| 15171 | retcode = JimEvalObjList(interp, resultScriptObjPtr); |
| 15172 | if (retcode == JIM_RETURN) { |
| 15173 | interp->returnLevel++; |
| 15174 | } |
| 15175 | Jim_DecrRefCount(interp, resultScriptObjPtr); |
| 15176 | } |
| 15177 | |
| 15178 | if (retcode == JIM_RETURN) { |
| 15179 | if (--interp->returnLevel <= 0) { |
| 15180 | retcode = interp->returnCode; |
| 15181 | interp->returnCode = JIM_OK; |
| @@ -15187,13 +15377,10 @@ | |
| 15187 | Jim_DecrRefCount(interp, interp->errorProc); |
| 15188 | interp->errorProc = argv[0]; |
| 15189 | Jim_IncrRefCount(interp->errorProc); |
| 15190 | } |
| 15191 | |
| 15192 | |
| 15193 | JimDeleteLocalProcs(interp, localCommands); |
| 15194 | |
| 15195 | return retcode; |
| 15196 | } |
| 15197 | |
| 15198 | int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) |
| 15199 | { |
| @@ -15261,11 +15448,10 @@ | |
| 15261 | Jim_Obj *scriptObjPtr; |
| 15262 | Jim_Obj *prevScriptObj; |
| 15263 | struct stat sb; |
| 15264 | int retcode; |
| 15265 | int readlen; |
| 15266 | struct JimParseResult result; |
| 15267 | |
| 15268 | if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { |
| 15269 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); |
| 15270 | return JIM_ERR; |
| 15271 | } |
| @@ -15288,31 +15474,13 @@ | |
| 15288 | scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 15289 | JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); |
| 15290 | Jim_IncrRefCount(scriptObjPtr); |
| 15291 | |
| 15292 | |
| 15293 | if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) { |
| 15294 | const char *msg; |
| 15295 | char linebuf[20]; |
| 15296 | |
| 15297 | switch (result.missing) { |
| 15298 | case '[': |
| 15299 | msg = "unmatched \"[\""; |
| 15300 | break; |
| 15301 | case '{': |
| 15302 | msg = "missing close-brace"; |
| 15303 | break; |
| 15304 | case '"': |
| 15305 | default: |
| 15306 | msg = "missing quote"; |
| 15307 | break; |
| 15308 | } |
| 15309 | |
| 15310 | snprintf(linebuf, sizeof(linebuf), "%d", result.line); |
| 15311 | |
| 15312 | Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s", |
| 15313 | msg, filename, linebuf); |
| 15314 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15315 | return JIM_ERR; |
| 15316 | } |
| 15317 | |
| 15318 | prevScriptObj = interp->currentScriptObj; |
| @@ -15475,11 +15643,11 @@ | |
| 15475 | } |
| 15476 | |
| 15477 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15478 | Jim_HashEntry *he, int type); |
| 15479 | |
| 15480 | #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) |
| 15481 | |
| 15482 | static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 15483 | JimHashtableIteratorCallbackType *callback, int type) |
| 15484 | { |
| 15485 | Jim_HashEntry *he; |
| @@ -15510,11 +15678,11 @@ | |
| 15510 | #define JIM_CMDLIST_CHANNELS 2 |
| 15511 | |
| 15512 | static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15513 | Jim_HashEntry *he, int type) |
| 15514 | { |
| 15515 | Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val; |
| 15516 | Jim_Obj *objPtr; |
| 15517 | |
| 15518 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15519 | |
| 15520 | return; |
| @@ -15543,11 +15711,11 @@ | |
| 15543 | #define JIM_VARLIST_VALUES 0x1000 |
| 15544 | |
| 15545 | static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15546 | Jim_HashEntry *he, int type) |
| 15547 | { |
| 15548 | Jim_Var *varPtr = (Jim_Var *)he->u.val; |
| 15549 | |
| 15550 | if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { |
| 15551 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); |
| 15552 | if (type & JIM_VARLIST_VALUES) { |
| 15553 | Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); |
| @@ -15865,11 +16033,11 @@ | |
| 15865 | |
| 15866 | expr = JimGetExpression(interp, argv[2]); |
| 15867 | incrScript = Jim_GetScript(interp, argv[3]); |
| 15868 | |
| 15869 | |
| 15870 | if (incrScript->len != 3 || !expr || expr->len != 3) { |
| 15871 | goto evalstart; |
| 15872 | } |
| 15873 | |
| 15874 | if (incrScript->token[1].type != JIM_TT_ESC || |
| 15875 | expr->token[0].type != JIM_TT_VAR || |
| @@ -16088,11 +16256,11 @@ | |
| 16088 | } |
| 16089 | |
| 16090 | |
| 16091 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16092 | { |
| 16093 | int result = JIM_ERR; |
| 16094 | int i, numargs; |
| 16095 | Jim_ListIter twoiters[2]; |
| 16096 | Jim_ListIter *iters; |
| 16097 | Jim_Obj *script; |
| 16098 | Jim_Obj *resultObj; |
| @@ -16111,13 +16279,16 @@ | |
| 16111 | iters = Jim_Alloc(numargs * sizeof(*iters)); |
| 16112 | } |
| 16113 | for (i = 0; i < numargs; i++) { |
| 16114 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16115 | if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { |
| 16116 | Jim_SetResultString(interp, "foreach varlist is empty", -1); |
| 16117 | return JIM_ERR; |
| 16118 | } |
| 16119 | } |
| 16120 | |
| 16121 | if (doMap) { |
| 16122 | resultObj = Jim_NewListObj(interp, NULL, 0); |
| 16123 | } |
| @@ -16430,12 +16601,12 @@ | |
| 16430 | { |
| 16431 | Jim_Obj *objPtr, *listObjPtr; |
| 16432 | int i; |
| 16433 | int idx; |
| 16434 | |
| 16435 | if (argc < 3) { |
| 16436 | Jim_WrongNumArgs(interp, 1, argv, "list index ?...?"); |
| 16437 | return JIM_ERR; |
| 16438 | } |
| 16439 | objPtr = argv[1]; |
| 16440 | Jim_IncrRefCount(objPtr); |
| 16441 | for (i = 2; i < argc; i++) { |
| @@ -16547,14 +16718,13 @@ | |
| 16547 | Jim_IncrRefCount(commandObj); |
| 16548 | } |
| 16549 | |
| 16550 | listlen = Jim_ListLength(interp, argv[0]); |
| 16551 | for (i = 0; i < listlen; i++) { |
| 16552 | Jim_Obj *objPtr; |
| 16553 | int eq = 0; |
| 16554 | |
| 16555 | Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE); |
| 16556 | switch (opt_match) { |
| 16557 | case OPT_EXACT: |
| 16558 | eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; |
| 16559 | break; |
| 16560 | |
| @@ -16744,29 +16914,27 @@ | |
| 16744 | if (argc < 3) { |
| 16745 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 16746 | return JIM_ERR; |
| 16747 | } |
| 16748 | else if (argc == 3) { |
| 16749 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16750 | return JIM_ERR; |
| 16751 | Jim_SetResult(interp, argv[2]); |
| 16752 | return JIM_OK; |
| 16753 | } |
| 16754 | if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]) |
| 16755 | == JIM_ERR) |
| 16756 | return JIM_ERR; |
| 16757 | return JIM_OK; |
| 16758 | } |
| 16759 | |
| 16760 | |
| 16761 | static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) |
| 16762 | { |
| 16763 | static const char * const options[] = { |
| 16764 | "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL |
| 16765 | }; |
| 16766 | enum |
| 16767 | { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX }; |
| 16768 | Jim_Obj *resObj; |
| 16769 | int i; |
| 16770 | int retCode; |
| 16771 | |
| 16772 | struct lsort_info info; |
| @@ -16777,17 +16945,18 @@ | |
| 16777 | } |
| 16778 | |
| 16779 | info.type = JIM_LSORT_ASCII; |
| 16780 | info.order = 1; |
| 16781 | info.indexed = 0; |
| 16782 | info.command = NULL; |
| 16783 | info.interp = interp; |
| 16784 | |
| 16785 | for (i = 1; i < (argc - 1); i++) { |
| 16786 | int option; |
| 16787 | |
| 16788 | if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) |
| 16789 | != JIM_OK) |
| 16790 | return JIM_ERR; |
| 16791 | switch (option) { |
| 16792 | case OPT_ASCII: |
| 16793 | info.type = JIM_LSORT_ASCII; |
| @@ -16796,16 +16965,22 @@ | |
| 16796 | info.type = JIM_LSORT_NOCASE; |
| 16797 | break; |
| 16798 | case OPT_INTEGER: |
| 16799 | info.type = JIM_LSORT_INTEGER; |
| 16800 | break; |
| 16801 | case OPT_INCREASING: |
| 16802 | info.order = 1; |
| 16803 | break; |
| 16804 | case OPT_DECREASING: |
| 16805 | info.order = -1; |
| 16806 | break; |
| 16807 | case OPT_COMMAND: |
| 16808 | if (i >= (argc - 2)) { |
| 16809 | Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); |
| 16810 | return JIM_ERR; |
| 16811 | } |
| @@ -16915,20 +17090,20 @@ | |
| 16915 | static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16916 | { |
| 16917 | if (argc >= 2) { |
| 16918 | int retcode; |
| 16919 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 16920 | Jim_Obj *objPtr; |
| 16921 | const char *str; |
| 16922 | |
| 16923 | |
| 16924 | savedCallFrame = interp->framePtr; |
| 16925 | |
| 16926 | |
| 16927 | str = Jim_String(argv[1]); |
| 16928 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 16929 | targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]); |
| 16930 | argc--; |
| 16931 | argv++; |
| 16932 | } |
| 16933 | else { |
| 16934 | targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); |
| @@ -16935,25 +17110,25 @@ | |
| 16935 | } |
| 16936 | if (targetCallFrame == NULL) { |
| 16937 | return JIM_ERR; |
| 16938 | } |
| 16939 | if (argc < 2) { |
| 16940 | argv--; |
| 16941 | Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| 16942 | return JIM_ERR; |
| 16943 | } |
| 16944 | |
| 16945 | interp->framePtr = targetCallFrame; |
| 16946 | if (argc == 2) { |
| 16947 | retcode = Jim_EvalObj(interp, argv[1]); |
| 16948 | } |
| 16949 | else { |
| 16950 | objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 16951 | Jim_IncrRefCount(objPtr); |
| 16952 | retcode = Jim_EvalObj(interp, objPtr); |
| 16953 | Jim_DecrRefCount(interp, objPtr); |
| 16954 | } |
| 16955 | interp->framePtr = savedCallFrame; |
| 16956 | return retcode; |
| 16957 | } |
| 16958 | else { |
| 16959 | Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| @@ -17064,12 +17239,39 @@ | |
| 17064 | } |
| 17065 | |
| 17066 | |
| 17067 | static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17068 | { |
| 17069 | Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1)); |
| 17070 | return JIM_EVAL; |
| 17071 | } |
| 17072 | |
| 17073 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17074 | { |
| 17075 | Jim_Obj *cmdList; |
| @@ -17354,11 +17556,11 @@ | |
| 17354 | for (i = 0; i < numMaps; i += 2) { |
| 17355 | Jim_Obj *objPtr; |
| 17356 | const char *k; |
| 17357 | int kl; |
| 17358 | |
| 17359 | Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE); |
| 17360 | k = Jim_String(objPtr); |
| 17361 | kl = Jim_Utf8Length(interp, objPtr); |
| 17362 | |
| 17363 | if (strLen >= kl && kl) { |
| 17364 | int rc; |
| @@ -17366,12 +17568,11 @@ | |
| 17366 | if (rc == 0) { |
| 17367 | if (noMatchStart) { |
| 17368 | Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); |
| 17369 | noMatchStart = NULL; |
| 17370 | } |
| 17371 | Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE); |
| 17372 | Jim_AppendObj(interp, resultObjPtr, objPtr); |
| 17373 | str += utf8_index(str, kl); |
| 17374 | strLen -= kl; |
| 17375 | break; |
| 17376 | } |
| 17377 | } |
| @@ -17851,15 +18052,17 @@ | |
| 17851 | |
| 17852 | exitCode = JIM_SIGNAL; |
| 17853 | } |
| 17854 | else { |
| 17855 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 17856 | } |
| 17857 | interp->signal_level -= sig; |
| 17858 | |
| 17859 | |
| 17860 | if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) { |
| 17861 | |
| 17862 | return exitCode; |
| 17863 | } |
| 17864 | |
| 17865 | if (sig && exitCode == JIM_SIGNAL) { |
| @@ -18009,11 +18212,11 @@ | |
| 18009 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18010 | |
| 18011 | JimInitHashTableIterator(&interp->references, &htiter); |
| 18012 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18013 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 18014 | Jim_Reference *refPtr = he->u.val; |
| 18015 | const unsigned long *refId = he->key; |
| 18016 | |
| 18017 | JimFormatReference(buf, refPtr, *refId); |
| 18018 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); |
| 18019 | } |
| @@ -18043,11 +18246,11 @@ | |
| 18043 | |
| 18044 | static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) |
| 18045 | { |
| 18046 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 18047 | if (type & JIM_DICTMATCH_VALUES) { |
| 18048 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val); |
| 18049 | } |
| 18050 | } |
| 18051 | |
| 18052 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 18053 | JimDictMatchCallbackType *callback, int type) |
| @@ -18092,21 +18295,65 @@ | |
| 18092 | return -1; |
| 18093 | } |
| 18094 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18095 | } |
| 18096 | |
| 18097 | |
| 18098 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18099 | { |
| 18100 | Jim_Obj *objPtr; |
| 18101 | int option; |
| 18102 | static const char * const options[] = { |
| 18103 | "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL |
| 18104 | }; |
| 18105 | enum |
| 18106 | { |
| 18107 | OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH, |
| 18108 | }; |
| 18109 | |
| 18110 | if (argc < 2) { |
| 18111 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18112 | return JIM_ERR; |
| @@ -18117,11 +18364,11 @@ | |
| 18117 | } |
| 18118 | |
| 18119 | switch (option) { |
| 18120 | case OPT_GET: |
| 18121 | if (argc < 3) { |
| 18122 | Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); |
| 18123 | return JIM_ERR; |
| 18124 | } |
| 18125 | if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, |
| 18126 | JIM_ERRMSG) != JIM_OK) { |
| 18127 | return JIM_ERR; |
| @@ -18134,82 +18381,87 @@ | |
| 18134 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); |
| 18135 | return JIM_ERR; |
| 18136 | } |
| 18137 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); |
| 18138 | |
| 18139 | case OPT_EXIST: |
| 18140 | if (argc < 3) { |
| 18141 | Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); |
| 18142 | return JIM_ERR; |
| 18143 | } |
| 18144 | Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, |
| 18145 | &objPtr, JIM_ERRMSG) == JIM_OK); |
| 18146 | return JIM_OK; |
| 18147 | |
| 18148 | case OPT_UNSET: |
| 18149 | if (argc < 4) { |
| 18150 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); |
| 18151 | return JIM_ERR; |
| 18152 | } |
| 18153 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE); |
| 18154 | |
| 18155 | case OPT_KEYS: |
| 18156 | if (argc != 3 && argc != 4) { |
| 18157 | Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?"); |
| 18158 | return JIM_ERR; |
| 18159 | } |
| 18160 | return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); |
| 18161 | |
| 18162 | case OPT_SIZE: { |
| 18163 | int size; |
| 18164 | |
| 18165 | if (argc != 3) { |
| 18166 | Jim_WrongNumArgs(interp, 2, argv, "dictVar"); |
| 18167 | return JIM_ERR; |
| 18168 | } |
| 18169 | |
| 18170 | size = Jim_DictSize(interp, argv[2]); |
| 18171 | if (size < 0) { |
| 18172 | return JIM_ERR; |
| 18173 | } |
| 18174 | Jim_SetResultInt(interp, size); |
| 18175 | return JIM_OK; |
| 18176 | } |
| 18177 | |
| 18178 | case OPT_MERGE: |
| 18179 | if (argc == 2) { |
| 18180 | return JIM_OK; |
| 18181 | } |
| 18182 | else if (SetDictFromAny(interp, argv[2]) != JIM_OK) { |
| 18183 | return JIM_ERR; |
| 18184 | } |
| 18185 | else { |
| 18186 | return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2); |
| 18187 | } |
| 18188 | |
| 18189 | case OPT_WITH: |
| 18190 | if (argc < 4) { |
| 18191 | Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); |
| 18192 | return JIM_ERR; |
| 18193 | } |
| 18194 | else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) { |
| 18195 | return JIM_ERR; |
| 18196 | } |
| 18197 | else { |
| 18198 | return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2); |
| 18199 | } |
| 18200 | |
| 18201 | case OPT_CREATE: |
| 18202 | if (argc % 2) { |
| 18203 | Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); |
| 18204 | return JIM_ERR; |
| 18205 | } |
| 18206 | objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); |
| 18207 | Jim_SetResult(interp, objPtr); |
| 18208 | return JIM_OK; |
| 18209 | } |
| 18210 | return JIM_ERR; |
| 18211 | } |
| 18212 | |
| 18213 | |
| 18214 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18215 | { |
| @@ -18267,11 +18519,11 @@ | |
| 18267 | }; |
| 18268 | enum |
| 18269 | { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, |
| 18270 | INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, |
| 18271 | INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, |
| 18272 | INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS |
| 18273 | }; |
| 18274 | |
| 18275 | #ifdef jim_ext_namespace |
| 18276 | int nons = 0; |
| 18277 | |
| @@ -19047,11 +19299,11 @@ | |
| 19047 | } |
| 19048 | } |
| 19049 | |
| 19050 | static const struct { |
| 19051 | const char *name; |
| 19052 | Jim_CmdProc cmdProc; |
| 19053 | } Jim_CoreCommandsTable[] = { |
| 19054 | {"alias", Jim_AliasCoreCommand}, |
| 19055 | {"set", Jim_SetCoreCommand}, |
| 19056 | {"unset", Jim_UnsetCoreCommand}, |
| 19057 | {"puts", Jim_PutsCoreCommand}, |
| @@ -19279,10 +19531,12 @@ | |
| 19279 | } |
| 19280 | |
| 19281 | len += extra; |
| 19282 | buf = Jim_Alloc(len + 1); |
| 19283 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19284 | |
| 19285 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19286 | } |
| 19287 | |
| 19288 | |
| @@ -19530,23 +19784,22 @@ | |
| 19530 | |
| 19531 | #include <ctype.h> |
| 19532 | #include <string.h> |
| 19533 | |
| 19534 | |
| 19535 | #define JIM_UTF_MAX 3 |
| 19536 | #define JIM_INTEGER_SPACE 24 |
| 19537 | #define MAX_FLOAT_WIDTH 320 |
| 19538 | |
| 19539 | Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) |
| 19540 | { |
| 19541 | const char *span, *format, *formatEnd, *msg; |
| 19542 | int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; |
| 19543 | static const char * const mixedXPG = |
| 19544 | "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 19545 | static const char * const badIndex[2] = { |
| 19546 | "not enough arguments for all format specifiers", |
| 19547 | "\"%n$\" argument index out of range" |
| 19548 | }; |
| 19549 | int formatLen; |
| 19550 | Jim_Obj *resultPtr; |
| 19551 | |
| 19552 | char *num_buffer = NULL; |
| @@ -19555,319 +19808,349 @@ | |
| 19555 | span = format = Jim_GetString(fmtObjPtr, &formatLen); |
| 19556 | formatEnd = format + formatLen; |
| 19557 | resultPtr = Jim_NewEmptyStringObj(interp); |
| 19558 | |
| 19559 | while (format != formatEnd) { |
| 19560 | char *end; |
| 19561 | int gotMinus, sawFlag; |
| 19562 | int gotPrecision, useShort; |
| 19563 | long width, precision; |
| 19564 | int newXpg; |
| 19565 | int ch; |
| 19566 | int step; |
| 19567 | int doubleType; |
| 19568 | char pad = ' '; |
| 19569 | char spec[2*JIM_INTEGER_SPACE + 12]; |
| 19570 | char *p; |
| 19571 | |
| 19572 | int formatted_chars; |
| 19573 | int formatted_bytes; |
| 19574 | const char *formatted_buf; |
| 19575 | |
| 19576 | step = utf8_tounicode(format, &ch); |
| 19577 | format += step; |
| 19578 | if (ch != '%') { |
| 19579 | numBytes += step; |
| 19580 | continue; |
| 19581 | } |
| 19582 | if (numBytes) { |
| 19583 | Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19584 | numBytes = 0; |
| 19585 | } |
| 19586 | |
| 19587 | |
| 19588 | step = utf8_tounicode(format, &ch); |
| 19589 | if (ch == '%') { |
| 19590 | span = format; |
| 19591 | numBytes = step; |
| 19592 | format += step; |
| 19593 | continue; |
| 19594 | } |
| 19595 | |
| 19596 | |
| 19597 | newXpg = 0; |
| 19598 | if (isdigit(ch)) { |
| 19599 | int position = strtoul(format, &end, 10); |
| 19600 | if (*end == '$') { |
| 19601 | newXpg = 1; |
| 19602 | objIndex = position - 1; |
| 19603 | format = end + 1; |
| 19604 | step = utf8_tounicode(format, &ch); |
| 19605 | } |
| 19606 | } |
| 19607 | if (newXpg) { |
| 19608 | if (gotSequential) { |
| 19609 | msg = mixedXPG; |
| 19610 | goto errorMsg; |
| 19611 | } |
| 19612 | gotXpg = 1; |
| 19613 | } else { |
| 19614 | if (gotXpg) { |
| 19615 | msg = mixedXPG; |
| 19616 | goto errorMsg; |
| 19617 | } |
| 19618 | gotSequential = 1; |
| 19619 | } |
| 19620 | if ((objIndex < 0) || (objIndex >= objc)) { |
| 19621 | msg = badIndex[gotXpg]; |
| 19622 | goto errorMsg; |
| 19623 | } |
| 19624 | |
| 19625 | p = spec; |
| 19626 | *p++ = '%'; |
| 19627 | |
| 19628 | gotMinus = 0; |
| 19629 | sawFlag = 1; |
| 19630 | do { |
| 19631 | switch (ch) { |
| 19632 | case '-': |
| 19633 | gotMinus = 1; |
| 19634 | break; |
| 19635 | case '0': |
| 19636 | pad = ch; |
| 19637 | break; |
| 19638 | case ' ': |
| 19639 | case '+': |
| 19640 | case '#': |
| 19641 | break; |
| 19642 | default: |
| 19643 | sawFlag = 0; |
| 19644 | continue; |
| 19645 | } |
| 19646 | *p++ = ch; |
| 19647 | format += step; |
| 19648 | step = utf8_tounicode(format, &ch); |
| 19649 | } while (sawFlag); |
| 19650 | |
| 19651 | |
| 19652 | width = 0; |
| 19653 | if (isdigit(ch)) { |
| 19654 | width = strtoul(format, &end, 10); |
| 19655 | format = end; |
| 19656 | step = utf8_tounicode(format, &ch); |
| 19657 | } else if (ch == '*') { |
| 19658 | if (objIndex >= objc - 1) { |
| 19659 | msg = badIndex[gotXpg]; |
| 19660 | goto errorMsg; |
| 19661 | } |
| 19662 | if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { |
| 19663 | goto error; |
| 19664 | } |
| 19665 | if (width < 0) { |
| 19666 | width = -width; |
| 19667 | if (!gotMinus) { |
| 19668 | *p++ = '-'; |
| 19669 | gotMinus = 1; |
| 19670 | } |
| 19671 | } |
| 19672 | objIndex++; |
| 19673 | format += step; |
| 19674 | step = utf8_tounicode(format, &ch); |
| 19675 | } |
| 19676 | |
| 19677 | |
| 19678 | gotPrecision = precision = 0; |
| 19679 | if (ch == '.') { |
| 19680 | gotPrecision = 1; |
| 19681 | format += step; |
| 19682 | step = utf8_tounicode(format, &ch); |
| 19683 | } |
| 19684 | if (isdigit(ch)) { |
| 19685 | precision = strtoul(format, &end, 10); |
| 19686 | format = end; |
| 19687 | step = utf8_tounicode(format, &ch); |
| 19688 | } else if (ch == '*') { |
| 19689 | if (objIndex >= objc - 1) { |
| 19690 | msg = badIndex[gotXpg]; |
| 19691 | goto errorMsg; |
| 19692 | } |
| 19693 | if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { |
| 19694 | goto error; |
| 19695 | } |
| 19696 | |
| 19697 | |
| 19698 | if (precision < 0) { |
| 19699 | precision = 0; |
| 19700 | } |
| 19701 | objIndex++; |
| 19702 | format += step; |
| 19703 | step = utf8_tounicode(format, &ch); |
| 19704 | } |
| 19705 | |
| 19706 | |
| 19707 | useShort = 0; |
| 19708 | if (ch == 'h') { |
| 19709 | useShort = 1; |
| 19710 | format += step; |
| 19711 | step = utf8_tounicode(format, &ch); |
| 19712 | } else if (ch == 'l') { |
| 19713 | |
| 19714 | format += step; |
| 19715 | step = utf8_tounicode(format, &ch); |
| 19716 | if (ch == 'l') { |
| 19717 | format += step; |
| 19718 | step = utf8_tounicode(format, &ch); |
| 19719 | } |
| 19720 | } |
| 19721 | |
| 19722 | format += step; |
| 19723 | span = format; |
| 19724 | |
| 19725 | |
| 19726 | if (ch == 'i') { |
| 19727 | ch = 'd'; |
| 19728 | } |
| 19729 | |
| 19730 | doubleType = 0; |
| 19731 | |
| 19732 | switch (ch) { |
| 19733 | case '\0': |
| 19734 | msg = "format string ended in middle of field specifier"; |
| 19735 | goto errorMsg; |
| 19736 | case 's': { |
| 19737 | formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 19738 | formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 19739 | if (gotPrecision && (precision < formatted_chars)) { |
| 19740 | |
| 19741 | formatted_chars = precision; |
| 19742 | formatted_bytes = utf8_index(formatted_buf, precision); |
| 19743 | } |
| 19744 | break; |
| 19745 | } |
| 19746 | case 'c': { |
| 19747 | jim_wide code; |
| 19748 | |
| 19749 | if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 19750 | goto error; |
| 19751 | } |
| 19752 | |
| 19753 | formatted_bytes = utf8_fromunicode(spec, code); |
| 19754 | formatted_buf = spec; |
| 19755 | formatted_chars = 1; |
| 19756 | break; |
| 19757 | } |
| 19758 | |
| 19759 | case 'e': |
| 19760 | case 'E': |
| 19761 | case 'f': |
| 19762 | case 'g': |
| 19763 | case 'G': |
| 19764 | doubleType = 1; |
| 19765 | |
| 19766 | case 'd': |
| 19767 | case 'u': |
| 19768 | case 'o': |
| 19769 | case 'x': |
| 19770 | case 'X': { |
| 19771 | jim_wide w; |
| 19772 | double d; |
| 19773 | int length; |
| 19774 | |
| 19775 | |
| 19776 | if (width) { |
| 19777 | p += sprintf(p, "%ld", width); |
| 19778 | } |
| 19779 | if (gotPrecision) { |
| 19780 | p += sprintf(p, ".%ld", precision); |
| 19781 | } |
| 19782 | |
| 19783 | |
| 19784 | if (doubleType) { |
| 19785 | if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 19786 | goto error; |
| 19787 | } |
| 19788 | length = MAX_FLOAT_WIDTH; |
| 19789 | } |
| 19790 | else { |
| 19791 | if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { |
| 19792 | goto error; |
| 19793 | } |
| 19794 | length = JIM_INTEGER_SPACE; |
| 19795 | if (useShort) { |
| 19796 | *p++ = 'h'; |
| 19797 | if (ch == 'd') { |
| 19798 | w = (short)w; |
| 19799 | } |
| 19800 | else { |
| 19801 | w = (unsigned short)w; |
| 19802 | } |
| 19803 | } |
| 19804 | else { |
| 19805 | *p++ = 'l'; |
| 19806 | #ifdef HAVE_LONG_LONG |
| 19807 | if (sizeof(long long) == sizeof(jim_wide)) { |
| 19808 | *p++ = 'l'; |
| 19809 | } |
| 19810 | #endif |
| 19811 | } |
| 19812 | } |
| 19813 | |
| 19814 | *p++ = (char) ch; |
| 19815 | *p = '\0'; |
| 19816 | |
| 19817 | |
| 19818 | if (width > length) { |
| 19819 | length = width; |
| 19820 | } |
| 19821 | if (gotPrecision) { |
| 19822 | length += precision; |
| 19823 | } |
| 19824 | |
| 19825 | |
| 19826 | if (num_buffer_size < length + 1) { |
| 19827 | num_buffer_size = length + 1; |
| 19828 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 19829 | } |
| 19830 | |
| 19831 | if (doubleType) { |
| 19832 | snprintf(num_buffer, length + 1, spec, d); |
| 19833 | } |
| 19834 | else { |
| 19835 | formatted_bytes = snprintf(num_buffer, length + 1, spec, w); |
| 19836 | } |
| 19837 | formatted_chars = formatted_bytes = strlen(num_buffer); |
| 19838 | formatted_buf = num_buffer; |
| 19839 | break; |
| 19840 | } |
| 19841 | |
| 19842 | default: { |
| 19843 | |
| 19844 | spec[0] = ch; |
| 19845 | spec[1] = '\0'; |
| 19846 | Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 19847 | goto error; |
| 19848 | } |
| 19849 | } |
| 19850 | |
| 19851 | if (!gotMinus) { |
| 19852 | while (formatted_chars < width) { |
| 19853 | Jim_AppendString(interp, resultPtr, &pad, 1); |
| 19854 | formatted_chars++; |
| 19855 | } |
| 19856 | } |
| 19857 | |
| 19858 | Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); |
| 19859 | |
| 19860 | while (formatted_chars < width) { |
| 19861 | Jim_AppendString(interp, resultPtr, &pad, 1); |
| 19862 | formatted_chars++; |
| 19863 | } |
| 19864 | |
| 19865 | objIndex += gotSequential; |
| 19866 | } |
| 19867 | if (numBytes) { |
| 19868 | Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19869 | } |
| 19870 | |
| 19871 | Jim_Free(num_buffer); |
| 19872 | return resultPtr; |
| 19873 | |
| @@ -19876,21 +20159,22 @@ | |
| 19876 | error: |
| 19877 | Jim_FreeNewObj(interp, resultPtr); |
| 19878 | Jim_Free(num_buffer); |
| 19879 | return NULL; |
| 19880 | } |
| 19881 | #include <stdio.h> |
| 19882 | #include <ctype.h> |
| 19883 | #include <stdlib.h> |
| 19884 | #include <string.h> |
| 19885 | |
| 19886 | |
| 19887 | #if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP) |
| 19888 | |
| 19889 | |
| 19890 | |
| 19891 | #define REG_MAX_PAREN 100 |
| 19892 | |
| 19893 | |
| 19894 | #define END 0 |
| 19895 | #define BOL 1 |
| 19896 | #define EOL 2 |
| @@ -19899,23 +20183,27 @@ | |
| 19899 | #define ANYBUT 5 |
| 19900 | #define BRANCH 6 |
| 19901 | #define BACK 7 |
| 19902 | #define EXACTLY 8 |
| 19903 | #define NOTHING 9 |
| 19904 | #define REP 10 |
| 19905 | #define REPMIN 11 |
| 19906 | #define REPX 12 |
| 19907 | #define REPXMIN 13 |
| 19908 | |
| 19909 | #define WORDA 15 |
| 19910 | #define WORDZ 16 |
| 19911 | #define OPENNC 19 |
| 19912 | #define OPEN 20 |
| 19913 | |
| 19914 | #define CLOSE (OPEN+REG_MAX_PAREN+1) |
| 19915 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 19916 | #define CLOSENC (CLOSE-1) |
| 19917 | |
| 19918 | #define REG_MAGIC 0xFADED00D |
| 19919 | |
| 19920 | |
| 19921 | #define OP(preg, p) (preg->program[p]) |
| @@ -19925,15 +20213,15 @@ | |
| 19925 | |
| 19926 | |
| 19927 | |
| 19928 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 19929 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 19930 | #define META "^$.[()|?{+*" |
| 19931 | |
| 19932 | #define HASWIDTH 01 |
| 19933 | #define SIMPLE 02 |
| 19934 | #define SPSTART 04 |
| 19935 | #define WORST 0 |
| 19936 | |
| 19937 | #define MAX_REP_COUNT 1000000 |
| 19938 | |
| 19939 | static int reg(regex_t *preg, int paren , int *flagp ); |
| @@ -19942,13 +20230,13 @@ | |
| 19942 | static int regatom(regex_t *preg, int *flagp ); |
| 19943 | static int regnode(regex_t *preg, int op ); |
| 19944 | static int regnext(regex_t *preg, int p ); |
| 19945 | static void regc(regex_t *preg, int b ); |
| 19946 | static int reginsert(regex_t *preg, int op, int size, int opnd ); |
| 19947 | static void regtail_(regex_t *preg, int p, int val, int line ); |
| 19948 | static void regoptail(regex_t *preg, int p, int val ); |
| 19949 | #define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__) |
| 19950 | |
| 19951 | static int reg_range_find(const int *string, int c); |
| 19952 | static const char *str_find(const char *string, int c, int nocase); |
| 19953 | static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); |
| 19954 | |
| @@ -19985,13 +20273,10 @@ | |
| 19985 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 19986 | |
| 19987 | |
| 19988 | preg->cflags = cflags; |
| 19989 | preg->regparse = exp; |
| 19990 | |
| 19991 | preg->program = NULL; |
| 19992 | preg->proglen = 0; |
| 19993 | |
| 19994 | |
| 19995 | preg->proglen = (strlen(exp) + 1) * 5; |
| 19996 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 19997 | if (preg->program == NULL) |
| @@ -20152,11 +20437,10 @@ | |
| 20152 | { |
| 20153 | int ret; |
| 20154 | char op; |
| 20155 | int next; |
| 20156 | int flags; |
| 20157 | int chain = 0; |
| 20158 | int min; |
| 20159 | int max; |
| 20160 | |
| 20161 | ret = regatom(preg, &flags); |
| 20162 | if (ret == 0) |
| @@ -20235,11 +20519,11 @@ | |
| 20235 | if (ISMULT(*preg->regparse)) { |
| 20236 | preg->err = REG_ERR_NESTED_COUNT; |
| 20237 | return 0; |
| 20238 | } |
| 20239 | |
| 20240 | return chain ? chain : ret; |
| 20241 | } |
| 20242 | |
| 20243 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20244 | { |
| 20245 | if (lower > upper) { |
| @@ -20329,10 +20613,11 @@ | |
| 20329 | break; |
| 20330 | case 'U': |
| 20331 | if ((n = parse_hex(s, 8, ch)) > 0) { |
| 20332 | s += n; |
| 20333 | } |
| 20334 | case 'x': |
| 20335 | if ((n = parse_hex(s, 2, ch)) > 0) { |
| 20336 | s += n; |
| 20337 | } |
| 20338 | break; |
| @@ -20577,10 +20862,11 @@ | |
| 20577 | |
| 20578 | static int regnode(regex_t *preg, int op) |
| 20579 | { |
| 20580 | reg_grow(preg, 2); |
| 20581 | |
| 20582 | preg->program[preg->p++] = op; |
| 20583 | preg->program[preg->p++] = 0; |
| 20584 | |
| 20585 | |
| 20586 | return preg->p - 2; |
| @@ -20606,11 +20892,11 @@ | |
| 20606 | preg->p += size; |
| 20607 | |
| 20608 | return opnd + size; |
| 20609 | } |
| 20610 | |
| 20611 | static void regtail_(regex_t *preg, int p, int val, int line ) |
| 20612 | { |
| 20613 | int scan; |
| 20614 | int temp; |
| 20615 | int offset; |
| 20616 | |
| @@ -20669,36 +20955,16 @@ | |
| 20669 | preg->pmatch = pmatch; |
| 20670 | preg->nmatch = nmatch; |
| 20671 | preg->start = string; |
| 20672 | |
| 20673 | |
| 20674 | for (scan = OPERAND(1); scan != 0; ) { |
| 20675 | switch (OP(preg, scan)) { |
| 20676 | case REP: |
| 20677 | case REPMIN: |
| 20678 | case REPX: |
| 20679 | case REPXMIN: |
| 20680 | preg->program[scan + 4] = 0; |
| 20681 | scan += 5; |
| 20682 | break; |
| 20683 | |
| 20684 | case ANYOF: |
| 20685 | case ANYBUT: |
| 20686 | case EXACTLY: |
| 20687 | scan += 2; |
| 20688 | while (preg->program[scan++]) { |
| 20689 | } |
| 20690 | break; |
| 20691 | |
| 20692 | case END: |
| 20693 | scan = 0; |
| 20694 | break; |
| 20695 | |
| 20696 | default: |
| 20697 | scan += 2; |
| 20698 | break; |
| 20699 | } |
| 20700 | } |
| 20701 | |
| 20702 | |
| 20703 | if (preg->regmust != 0) { |
| 20704 | s = string; |
| @@ -20950,10 +21216,11 @@ | |
| 20950 | |
| 20951 | static int regmatch(regex_t *preg, int prog) |
| 20952 | { |
| 20953 | int scan; |
| 20954 | int next; |
| 20955 | |
| 20956 | scan = prog; |
| 20957 | |
| 20958 | #ifdef DEBUG |
| 20959 | if (scan != 0 && regnarrate) |
| @@ -21038,27 +21305,24 @@ | |
| 21038 | break; |
| 21039 | case NOTHING: |
| 21040 | break; |
| 21041 | case BACK: |
| 21042 | break; |
| 21043 | case BRANCH: { |
| 21044 | const char *save; |
| 21045 | |
| 21046 | if (OP(preg, next) != BRANCH) |
| 21047 | next = OPERAND(scan); |
| 21048 | else { |
| 21049 | do { |
| 21050 | save = preg->reginput; |
| 21051 | if (regmatch(preg, OPERAND(scan))) { |
| 21052 | return(1); |
| 21053 | } |
| 21054 | preg->reginput = save; |
| 21055 | scan = regnext(preg, scan); |
| 21056 | } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21057 | return(0); |
| 21058 | |
| 21059 | } |
| 21060 | } |
| 21061 | break; |
| 21062 | case REP: |
| 21063 | case REPMIN: |
| 21064 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21066,43 +21330,35 @@ | |
| 21066 | case REPX: |
| 21067 | case REPXMIN: |
| 21068 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21069 | |
| 21070 | case END: |
| 21071 | return(1); |
| 21072 | break; |
| 21073 | |
| 21074 | case OPENNC: |
| 21075 | case CLOSENC: |
| 21076 | if (regmatch(preg, next)) { |
| 21077 | return 1; |
| 21078 | } |
| 21079 | return 0; |
| 21080 | |
| 21081 | default: |
| 21082 | if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { |
| 21083 | const char *save; |
| 21084 | |
| 21085 | save = preg->reginput; |
| 21086 | |
| 21087 | if (regmatch(preg, next)) { |
| 21088 | int no; |
| 21089 | if (OP(preg, scan) < CLOSE) { |
| 21090 | no = OP(preg, scan) - OPEN; |
| 21091 | if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { |
| 21092 | preg->pmatch[no].rm_so = save - preg->start; |
| 21093 | } |
| 21094 | } |
| 21095 | else { |
| 21096 | no = OP(preg, scan) - CLOSE; |
| 21097 | if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { |
| 21098 | preg->pmatch[no].rm_eo = save - preg->start; |
| 21099 | } |
| 21100 | } |
| 21101 | return(1); |
| 21102 | } else |
| 21103 | return(0); |
| 21104 | } |
| 21105 | return REG_ERR_INTERNAL; |
| 21106 | } |
| 21107 | |
| 21108 | scan = next; |
| @@ -21181,10 +21437,32 @@ | |
| 21181 | if (OP(preg, p) == BACK) |
| 21182 | return(p-offset); |
| 21183 | else |
| 21184 | return(p+offset); |
| 21185 | } |
| 21186 | |
| 21187 | |
| 21188 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 21189 | { |
| 21190 | static const char *error_strings[] = { |
| @@ -21359,19 +21637,24 @@ | |
| 21359 | char *Jim_HistoryGetline(const char *prompt) |
| 21360 | { |
| 21361 | #ifdef USE_LINENOISE |
| 21362 | return linenoise(prompt); |
| 21363 | #else |
| 21364 | char *line = malloc(MAX_LINE_LEN); |
| 21365 | |
| 21366 | fputs(prompt, stdout); |
| 21367 | fflush(stdout); |
| 21368 | |
| 21369 | if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { |
| 21370 | free(line); |
| 21371 | return NULL; |
| 21372 | } |
| 21373 | return line; |
| 21374 | #endif |
| 21375 | } |
| 21376 | |
| 21377 | void Jim_HistoryLoad(const char *filename) |
| @@ -21422,11 +21705,11 @@ | |
| 21422 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 21423 | Jim_HistoryLoad(history_file); |
| 21424 | } |
| 21425 | #endif |
| 21426 | |
| 21427 | printf("Welcome to Jim version %d.%d" JIM_NL, |
| 21428 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 21429 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| 21430 | |
| 21431 | while (1) { |
| 21432 | Jim_Obj *scriptObjPtr; |
| @@ -21534,10 +21817,16 @@ | |
| 21534 | } |
| 21535 | |
| 21536 | Jim_SetVariableStr(interp, "argv", listObj); |
| 21537 | Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); |
| 21538 | } |
| 21539 | |
| 21540 | int main(int argc, char *const argv[]) |
| 21541 | { |
| 21542 | int retcode; |
| 21543 | Jim_Interp *interp; |
| @@ -21551,22 +21840,20 @@ | |
| 21551 | interp = Jim_CreateInterp(); |
| 21552 | Jim_RegisterCoreCommands(interp); |
| 21553 | |
| 21554 | |
| 21555 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 21556 | Jim_MakeErrorMessage(interp); |
| 21557 | fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21558 | } |
| 21559 | |
| 21560 | Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); |
| 21561 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 21562 | retcode = Jim_initjimshInit(interp); |
| 21563 | |
| 21564 | if (argc == 1) { |
| 21565 | if (retcode == JIM_ERR) { |
| 21566 | Jim_MakeErrorMessage(interp); |
| 21567 | fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21568 | } |
| 21569 | if (retcode != JIM_EXIT) { |
| 21570 | JimSetArgv(interp, 0, NULL); |
| 21571 | retcode = Jim_InteractivePrompt(interp); |
| 21572 | } |
| @@ -21583,12 +21870,11 @@ | |
| 21583 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 21584 | JimSetArgv(interp, argc - 2, argv + 2); |
| 21585 | retcode = Jim_EvalFile(interp, argv[1]); |
| 21586 | } |
| 21587 | if (retcode == JIM_ERR) { |
| 21588 | Jim_MakeErrorMessage(interp); |
| 21589 | fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21590 | } |
| 21591 | } |
| 21592 | if (retcode == JIM_EXIT) { |
| 21593 | retcode = Jim_GetExitCode(interp); |
| 21594 | } |
| 21595 |
| --- autosetup/jimsh0.c | |
| +++ autosetup/jimsh0.c | |
| @@ -1,6 +1,6 @@ | |
| 1 | /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ |
| 2 | #define _GNU_SOURCE |
| 3 | #define JIM_TCL_COMPAT |
| 4 | #define JIM_REFERENCES |
| 5 | #define JIM_ANSIC |
| 6 | #define JIM_REGEXP |
| @@ -47,10 +47,14 @@ | |
| 47 | #define JIM_VERSION 75 |
| 48 | #ifndef JIM_WIN32COMPAT_H |
| 49 | #define JIM_WIN32COMPAT_H |
| 50 | |
| 51 | |
| 52 | |
| 53 | #ifdef __cplusplus |
| 54 | extern "C" { |
| 55 | #endif |
| 56 | |
| 57 | |
| 58 | #if defined(_WIN32) || defined(WIN32) |
| 59 | |
| 60 | #define HAVE_DLOPEN |
| @@ -106,17 +110,31 @@ | |
| 110 | } DIR; |
| 111 | |
| 112 | DIR *opendir(const char *name); |
| 113 | int closedir(DIR *dir); |
| 114 | struct dirent *readdir(DIR *dir); |
| 115 | |
| 116 | #elif defined(__MINGW32__) |
| 117 | |
| 118 | #define strtod __strtod |
| 119 | |
| 120 | #endif |
| 121 | |
| 122 | #endif |
| 123 | |
| 124 | #ifdef __cplusplus |
| 125 | } |
| 126 | #endif |
| 127 | |
| 128 | #endif |
| 129 | #ifndef UTF8_UTIL_H |
| 130 | #define UTF8_UTIL_H |
| 131 | |
| 132 | #ifdef __cplusplus |
| 133 | extern "C" { |
| 134 | #endif |
| 135 | |
| 136 | |
| 137 | |
| 138 | #define MAX_UTF8_LEN 4 |
| 139 | |
| 140 | int utf8_fromunicode(char *p, unsigned uc); |
| @@ -125,10 +143,11 @@ | |
| 143 | #include <ctype.h> |
| 144 | |
| 145 | |
| 146 | #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) |
| 147 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 148 | #define utf8_getchars(CP, C) (*(CP) = (C), 1) |
| 149 | #define utf8_upper(C) toupper(C) |
| 150 | #define utf8_title(C) toupper(C) |
| 151 | #define utf8_lower(C) tolower(C) |
| 152 | #define utf8_index(C, I) (I) |
| 153 | #define utf8_charlen(C) 1 |
| @@ -135,10 +154,14 @@ | |
| 154 | #define utf8_prev_len(S, L) 1 |
| 155 | |
| 156 | #else |
| 157 | |
| 158 | #endif |
| 159 | |
| 160 | #ifdef __cplusplus |
| 161 | } |
| 162 | #endif |
| 163 | |
| 164 | #endif |
| 165 | |
| 166 | #ifndef __JIM__H |
| 167 | #define __JIM__H |
| @@ -199,44 +222,34 @@ | |
| 222 | #define JIM_EVAL 7 |
| 223 | |
| 224 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 225 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 226 | |
| 227 | |
| 228 | #define JIM_PRIV_FLAG_SHIFT 20 |
| 229 | |
| 230 | #define JIM_NONE 0 |
| 231 | #define JIM_ERRMSG 1 |
| 232 | #define JIM_ENUM_ABBREV 2 |
| 233 | #define JIM_UNSHARED 4 |
| 234 | #define JIM_MUSTEXIST 8 |
| 235 | |
| 236 | |
| 237 | #define JIM_SUBST_NOVAR 1 |
| 238 | #define JIM_SUBST_NOCMD 2 |
| 239 | #define JIM_SUBST_NOESC 4 |
| 240 | #define JIM_SUBST_FLAG 128 |
| 241 | |
| 242 | |
| 243 | #define JIM_CASESENS 0 |
| 244 | #define JIM_NOCASE 1 |
| 245 | |
| 246 | |
| 247 | #define JIM_PATH_LEN 1024 |
| 248 | |
| 249 | |
| 250 | #define JIM_NOTUSED(V) ((void) V) |
| 251 | |
| 252 | #define JIM_LIBPATH "auto_path" |
| 253 | #define JIM_INTERACTIVE "tcl_interactive" |
| 254 | |
| 255 | |
| @@ -266,21 +279,22 @@ | |
| 279 | } Jim_HashTableType; |
| 280 | |
| 281 | typedef struct Jim_HashTable { |
| 282 | Jim_HashEntry **table; |
| 283 | const Jim_HashTableType *type; |
| 284 | void *privdata; |
| 285 | unsigned int size; |
| 286 | unsigned int sizemask; |
| 287 | unsigned int used; |
| 288 | unsigned int collisions; |
| 289 | unsigned int uniq; |
| 290 | } Jim_HashTable; |
| 291 | |
| 292 | typedef struct Jim_HashTableIterator { |
| 293 | Jim_HashTable *ht; |
| 294 | Jim_HashEntry *entry, *nextEntry; |
| 295 | int index; |
| 296 | } Jim_HashTableIterator; |
| 297 | |
| 298 | |
| 299 | #define JIM_HT_INITIAL_SIZE 16 |
| 300 | |
| @@ -289,35 +303,35 @@ | |
| 303 | if ((ht)->type->valDestructor) \ |
| 304 | (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) |
| 305 | |
| 306 | #define Jim_SetHashVal(ht, entry, _val_) do { \ |
| 307 | if ((ht)->type->valDup) \ |
| 308 | (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ |
| 309 | else \ |
| 310 | (entry)->u.val = (_val_); \ |
| 311 | } while(0) |
| 312 | |
| 313 | #define Jim_FreeEntryKey(ht, entry) \ |
| 314 | if ((ht)->type->keyDestructor) \ |
| 315 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) |
| 316 | |
| 317 | #define Jim_SetHashKey(ht, entry, _key_) do { \ |
| 318 | if ((ht)->type->keyDup) \ |
| 319 | (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \ |
| 320 | else \ |
| 321 | (entry)->key = (void *)(_key_); \ |
| 322 | } while(0) |
| 323 | |
| 324 | #define Jim_CompareHashKeys(ht, key1, key2) \ |
| 325 | (((ht)->type->keyCompare) ? \ |
| 326 | (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \ |
| 327 | (key1) == (key2)) |
| 328 | |
| 329 | #define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) |
| 330 | |
| 331 | #define Jim_GetHashEntryKey(he) ((he)->key) |
| 332 | #define Jim_GetHashEntryVal(he) ((he)->u.val) |
| 333 | #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) |
| 334 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 335 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 336 | |
| 337 | |
| @@ -341,19 +355,19 @@ | |
| 355 | void *ptr1; |
| 356 | void *ptr2; |
| 357 | } twoPtrValue; |
| 358 | |
| 359 | struct { |
| 360 | struct Jim_Var *varPtr; |
| 361 | unsigned long callFrameId; |
| 362 | int global; |
| 363 | } varValue; |
| 364 | |
| 365 | struct { |
| 366 | struct Jim_Obj *nsObj; |
| 367 | struct Jim_Cmd *cmdPtr; |
| 368 | unsigned long procEpoch; |
| 369 | } cmdValue; |
| 370 | |
| 371 | struct { |
| 372 | struct Jim_Obj **ele; |
| 373 | int len; |
| @@ -379,12 +393,12 @@ | |
| 393 | struct Jim_Obj *varNameObjPtr; |
| 394 | struct Jim_Obj *indexObjPtr; |
| 395 | } dictSubstValue; |
| 396 | |
| 397 | struct { |
| 398 | void *compre; |
| 399 | unsigned flags; |
| 400 | } regexpValue; |
| 401 | struct { |
| 402 | int line; |
| 403 | int argc; |
| 404 | } scriptLineValue; |
| @@ -453,21 +467,24 @@ | |
| 467 | struct Jim_CallFrame *next; |
| 468 | Jim_Obj *nsObj; |
| 469 | Jim_Obj *fileNameObj; |
| 470 | int line; |
| 471 | Jim_Stack *localCommands; |
| 472 | int tailcall; |
| 473 | struct Jim_Obj *tailcallObj; |
| 474 | struct Jim_Cmd *tailcallCmd; |
| 475 | } Jim_CallFrame; |
| 476 | |
| 477 | typedef struct Jim_Var { |
| 478 | Jim_Obj *objPtr; |
| 479 | struct Jim_CallFrame *linkFramePtr; |
| 480 | } Jim_Var; |
| 481 | |
| 482 | |
| 483 | typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, |
| 484 | Jim_Obj *const *argv); |
| 485 | typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 486 | |
| 487 | |
| 488 | |
| 489 | typedef struct Jim_Cmd { |
| 490 | int inUse; |
| @@ -474,12 +491,12 @@ | |
| 491 | int isproc; |
| 492 | struct Jim_Cmd *prevCmd; |
| 493 | union { |
| 494 | struct { |
| 495 | |
| 496 | Jim_CmdProc *cmdProc; |
| 497 | Jim_DelCmdProc *delProc; |
| 498 | void *privData; |
| 499 | } native; |
| 500 | struct { |
| 501 | |
| 502 | Jim_Obj *argListObjPtr; |
| @@ -589,15 +606,11 @@ | |
| 606 | Jim_Obj *finalizerCmdNamePtr; |
| 607 | char tag[JIM_REFERENCE_TAGLEN+1]; |
| 608 | } Jim_Reference; |
| 609 | |
| 610 | |
| 611 | #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) |
| 612 | #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) |
| 613 | |
| 614 | #define JIM_EXPORT |
| 615 | |
| 616 | |
| @@ -608,10 +621,11 @@ | |
| 621 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 622 | |
| 623 | |
| 624 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 625 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 626 | JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); |
| 627 | |
| 628 | |
| 629 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 630 | |
| 631 | |
| @@ -739,13 +753,12 @@ | |
| 753 | JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, |
| 754 | const char *name, const char *val); |
| 755 | JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, |
| 756 | Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, |
| 757 | Jim_CallFrame *targetCallFrame); |
| 758 | JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp, |
| 759 | Jim_Obj *nameObjPtr); |
| 760 | JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, |
| 761 | Jim_Obj *nameObjPtr, int flags); |
| 762 | JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, |
| 763 | Jim_Obj *nameObjPtr, int flags); |
| 764 | JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, |
| @@ -804,10 +817,11 @@ | |
| 817 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 818 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 819 | JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); |
| 820 | JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); |
| 821 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 822 | JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); |
| 823 | |
| 824 | |
| 825 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 826 | int *intPtr); |
| 827 | |
| @@ -869,19 +883,19 @@ | |
| 883 | |
| 884 | |
| 885 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| 886 | JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); |
| 887 | JIM_EXPORT int Jim_IsBigEndian(void); |
| 888 | |
| 889 | #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) |
| 890 | |
| 891 | |
| 892 | JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); |
| 893 | JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); |
| 894 | |
| 895 | |
| 896 | JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 897 | |
| 898 | |
| 899 | JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); |
| 900 | JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); |
| 901 | |
| @@ -903,16 +917,16 @@ | |
| 917 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 918 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 919 | |
| 920 | |
| 921 | |
| 922 | typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 923 | |
| 924 | typedef struct { |
| 925 | const char *cmd; |
| 926 | const char *args; |
| 927 | jim_subcmd_function *function; |
| 928 | short minargs; |
| 929 | short maxargs; |
| 930 | unsigned short flags; |
| 931 | } jim_subcmd_type; |
| 932 | |
| @@ -929,22 +943,16 @@ | |
| 943 | |
| 944 | #endif |
| 945 | #ifndef JIMREGEXP_H |
| 946 | #define JIMREGEXP_H |
| 947 | |
| 948 | |
| 949 | #ifdef __cplusplus |
| 950 | extern "C" { |
| 951 | #endif |
| 952 | |
| 953 | #include <stdlib.h> |
| 954 | |
| 955 | typedef struct { |
| 956 | int rm_so; |
| 957 | int rm_eo; |
| 958 | } regmatch_t; |
| @@ -1013,10 +1021,12 @@ | |
| 1021 | int regcomp(regex_t *preg, const char *regex, int cflags); |
| 1022 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1023 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1024 | void regfree(regex_t *preg); |
| 1025 | |
| 1026 | #ifdef __cplusplus |
| 1027 | } |
| 1028 | #endif |
| 1029 | |
| 1030 | #endif |
| 1031 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1032 | { |
| @@ -1079,10 +1089,15 @@ | |
| 1089 | "\n" |
| 1090 | "package require readdir\n" |
| 1091 | "\n" |
| 1092 | "\n" |
| 1093 | "proc glob.globdir {dir pattern} {\n" |
| 1094 | " if {[file exists $dir/$pattern]} {\n" |
| 1095 | "\n" |
| 1096 | " return $pattern\n" |
| 1097 | " }\n" |
| 1098 | "\n" |
| 1099 | " set result {}\n" |
| 1100 | " set files [readdir $dir]\n" |
| 1101 | " lappend files . ..\n" |
| 1102 | "\n" |
| 1103 | " foreach name $files {\n" |
| @@ -1261,10 +1276,12 @@ | |
| 1276 | { |
| 1277 | if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) |
| 1278 | return JIM_ERR; |
| 1279 | |
| 1280 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1281 | "\n" |
| 1282 | "\n" |
| 1283 | "\n" |
| 1284 | "proc lambda {arglist args} {\n" |
| 1285 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1286 | "}\n" |
| 1287 | "\n" |
| @@ -1290,46 +1307,48 @@ | |
| 1307 | "}\n" |
| 1308 | "\n" |
| 1309 | "\n" |
| 1310 | "\n" |
| 1311 | "\n" |
| 1312 | "proc stacktrace {{skip 0}} {\n" |
| 1313 | " set trace {}\n" |
| 1314 | " incr skip\n" |
| 1315 | " foreach level [range $skip [info level]] {\n" |
| 1316 | " lappend trace {*}[info frame -$level]\n" |
| 1317 | " }\n" |
| 1318 | " return $trace\n" |
| 1319 | "}\n" |
| 1320 | "\n" |
| 1321 | "\n" |
| 1322 | "proc stackdump {stacktrace} {\n" |
| 1323 | " set lines {}\n" |
| 1324 | " foreach {l f p} [lreverse $stacktrace] {\n" |
| 1325 | " set line {}\n" |
| 1326 | " if {$p ne \"\"} {\n" |
| 1327 | " append line \"in procedure '$p' \"\n" |
| 1328 | " if {$f ne \"\"} {\n" |
| 1329 | " append line \"called \"\n" |
| 1330 | " }\n" |
| 1331 | " }\n" |
| 1332 | " if {$f ne \"\"} {\n" |
| 1333 | " append line \"at file \\\"$f\\\", line $l\"\n" |
| 1334 | " }\n" |
| 1335 | " if {$line ne \"\"} {\n" |
| 1336 | " lappend lines $line\n" |
| 1337 | " }\n" |
| 1338 | " }\n" |
| 1339 | " join $lines \\n\n" |
| 1340 | "}\n" |
| 1341 | "\n" |
| 1342 | "\n" |
| 1343 | "\n" |
| 1344 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1345 | " if {$stacktrace eq \"\"} {\n" |
| 1346 | "\n" |
| 1347 | " set stacktrace [info stacktrace]\n" |
| 1348 | "\n" |
| 1349 | " lappend stacktrace {*}[stacktrace 1]\n" |
| 1350 | " }\n" |
| 1351 | " lassign $stacktrace p f l\n" |
| 1352 | " if {$f ne \"\"} {\n" |
| 1353 | " set result \"Runtime Error: $f:$l: \"\n" |
| 1354 | " }\n" |
| @@ -1356,25 +1375,46 @@ | |
| 1375 | " }\n" |
| 1376 | " return \"\"\n" |
| 1377 | "}\n" |
| 1378 | "\n" |
| 1379 | "\n" |
| 1380 | "proc {dict with} {&dictVar {args key} script} {\n" |
| 1381 | " set keys {}\n" |
| 1382 | " foreach {n v} [dict get $dictVar {*}$key] {\n" |
| 1383 | " upvar $n var_$n\n" |
| 1384 | " set var_$n $v\n" |
| 1385 | " lappend keys $n\n" |
| 1386 | " }\n" |
| 1387 | " catch {uplevel 1 $script} msg opts\n" |
| 1388 | " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" |
| 1389 | " foreach n $keys {\n" |
| 1390 | " if {[info exists var_$n]} {\n" |
| 1391 | " dict set dictVar {*}$key $n [set var_$n]\n" |
| 1392 | " } else {\n" |
| 1393 | " dict unset dictVar {*}$key $n\n" |
| 1394 | " }\n" |
| 1395 | " }\n" |
| 1396 | " }\n" |
| 1397 | " return {*}$opts $msg\n" |
| 1398 | "}\n" |
| 1399 | "\n" |
| 1400 | "\n" |
| 1401 | "proc {dict update} {&varName args script} {\n" |
| 1402 | " set keys {}\n" |
| 1403 | " foreach {n v} $args {\n" |
| 1404 | " upvar $v var_$v\n" |
| 1405 | " if {[dict exists $varName $n]} {\n" |
| 1406 | " set var_$v [dict get $varName $n]\n" |
| 1407 | " }\n" |
| 1408 | " }\n" |
| 1409 | " catch {uplevel 1 $script} msg opts\n" |
| 1410 | " if {[info exists varName]} {\n" |
| 1411 | " foreach {n v} $args {\n" |
| 1412 | " if {[info exists var_$v]} {\n" |
| 1413 | " dict set varName $n [set var_$v]\n" |
| 1414 | " } else {\n" |
| 1415 | " dict unset varName $n\n" |
| 1416 | " }\n" |
| 1417 | " }\n" |
| 1418 | " }\n" |
| 1419 | " return {*}$opts $msg\n" |
| 1420 | "}\n" |
| @@ -1389,10 +1429,69 @@ | |
| 1429 | " dict set dict $k $v\n" |
| 1430 | " }\n" |
| 1431 | " }\n" |
| 1432 | " return $dict\n" |
| 1433 | "}\n" |
| 1434 | "\n" |
| 1435 | "proc {dict replace} {dictionary {args {key value}}} {\n" |
| 1436 | " if {[llength ${key value}] % 2} {\n" |
| 1437 | " tailcall {dict replace}\n" |
| 1438 | " }\n" |
| 1439 | " tailcall dict merge $dictionary ${key value}\n" |
| 1440 | "}\n" |
| 1441 | "\n" |
| 1442 | "\n" |
| 1443 | "proc {dict lappend} {varName key {args value}} {\n" |
| 1444 | " upvar $varName dict\n" |
| 1445 | " if {[exists dict] && [dict exists $dict $key]} {\n" |
| 1446 | " set list [dict get $dict $key]\n" |
| 1447 | " }\n" |
| 1448 | " lappend list {*}$value\n" |
| 1449 | " dict set dict $key $list\n" |
| 1450 | "}\n" |
| 1451 | "\n" |
| 1452 | "\n" |
| 1453 | "proc {dict append} {varName key {args value}} {\n" |
| 1454 | " upvar $varName dict\n" |
| 1455 | " if {[exists dict] && [dict exists $dict $key]} {\n" |
| 1456 | " set str [dict get $dict $key]\n" |
| 1457 | " }\n" |
| 1458 | " append str {*}$value\n" |
| 1459 | " dict set dict $key $str\n" |
| 1460 | "}\n" |
| 1461 | "\n" |
| 1462 | "\n" |
| 1463 | "proc {dict incr} {varName key {increment 1}} {\n" |
| 1464 | " upvar $varName dict\n" |
| 1465 | " if {[exists dict] && [dict exists $dict $key]} {\n" |
| 1466 | " set value [dict get $dict $key]\n" |
| 1467 | " }\n" |
| 1468 | " incr value $increment\n" |
| 1469 | " dict set dict $key $value\n" |
| 1470 | "}\n" |
| 1471 | "\n" |
| 1472 | "\n" |
| 1473 | "proc {dict remove} {dictionary {args key}} {\n" |
| 1474 | " foreach k $key {\n" |
| 1475 | " dict unset dictionary $k\n" |
| 1476 | " }\n" |
| 1477 | " return $dictionary\n" |
| 1478 | "}\n" |
| 1479 | "\n" |
| 1480 | "\n" |
| 1481 | "proc {dict values} {dictionary {pattern *}} {\n" |
| 1482 | " dict keys [lreverse $dictionary] $pattern\n" |
| 1483 | "}\n" |
| 1484 | "\n" |
| 1485 | "\n" |
| 1486 | "proc {dict for} {vars dictionary script} {\n" |
| 1487 | " if {[llength $vars] != 2} {\n" |
| 1488 | " return -code error \"must have exactly two variable names\"\n" |
| 1489 | " }\n" |
| 1490 | " dict size $dictionary\n" |
| 1491 | " tailcall foreach $vars $dictionary $script\n" |
| 1492 | "}\n" |
| 1493 | ); |
| 1494 | } |
| 1495 | int Jim_tclcompatInit(Jim_Interp *interp) |
| 1496 | { |
| 1497 | if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG)) |
| @@ -1403,12 +1502,14 @@ | |
| 1502 | "\n" |
| 1503 | "\n" |
| 1504 | "\n" |
| 1505 | "\n" |
| 1506 | "\n" |
| 1507 | "\n" |
| 1508 | "\n" |
| 1509 | "set env [env]\n" |
| 1510 | "\n" |
| 1511 | "\n" |
| 1512 | "if {[info commands stdout] ne \"\"} {\n" |
| 1513 | "\n" |
| 1514 | " foreach p {gets flush close eof seek tell} {\n" |
| 1515 | " proc $p {chan args} {p} {\n" |
| @@ -1455,51 +1556,10 @@ | |
| 1556 | " }\n" |
| 1557 | " }\n" |
| 1558 | " }\n" |
| 1559 | "}\n" |
| 1560 | "\n" |
| 1561 | "\n" |
| 1562 | "proc fileevent {args} {\n" |
| 1563 | " tailcall {*}$args\n" |
| 1564 | "}\n" |
| 1565 | "\n" |
| @@ -1529,13 +1589,25 @@ | |
| 1589 | " error \"bad option \\\"$force\\\": should be -force\"\n" |
| 1590 | " }\n" |
| 1591 | "\n" |
| 1592 | " set in [open $source]\n" |
| 1593 | "\n" |
| 1594 | " if {[file exists $target]} {\n" |
| 1595 | " if {$force eq \"\"} {\n" |
| 1596 | " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" |
| 1597 | " }\n" |
| 1598 | "\n" |
| 1599 | " if {$source eq $target} {\n" |
| 1600 | " return\n" |
| 1601 | " }\n" |
| 1602 | "\n" |
| 1603 | "\n" |
| 1604 | " file stat $source ss\n" |
| 1605 | " file stat $target ts\n" |
| 1606 | " if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n" |
| 1607 | " return\n" |
| 1608 | " }\n" |
| 1609 | " }\n" |
| 1610 | " set out [open $target w]\n" |
| 1611 | " $in copyto $out\n" |
| 1612 | " $out close\n" |
| 1613 | " } on error {msg opts} {\n" |
| @@ -1580,18 +1652,18 @@ | |
| 1652 | " error $error\n" |
| 1653 | " }\n" |
| 1654 | "}\n" |
| 1655 | "\n" |
| 1656 | "\n" |
| 1657 | "local proc pid {{channelId {}}} {\n" |
| 1658 | " if {$channelId eq \"\"} {\n" |
| 1659 | " tailcall upcall pid\n" |
| 1660 | " }\n" |
| 1661 | " if {[catch {$channelId tell}]} {\n" |
| 1662 | " return -code error \"can not find channel named \\\"$channelId\\\"\"\n" |
| 1663 | " }\n" |
| 1664 | " if {[catch {$channelId pid} pids]} {\n" |
| 1665 | " return \"\"\n" |
| 1666 | " }\n" |
| 1667 | " return $pids\n" |
| 1668 | "}\n" |
| 1669 | "\n" |
| @@ -1680,23 +1752,25 @@ | |
| 1752 | "}\n" |
| 1753 | ); |
| 1754 | } |
| 1755 | |
| 1756 | |
| 1757 | #include <stdio.h> |
| 1758 | #include <string.h> |
| 1759 | #include <errno.h> |
| 1760 | #include <fcntl.h> |
| 1761 | #ifdef HAVE_UNISTD_H |
| 1762 | #include <unistd.h> |
| 1763 | #include <sys/stat.h> |
| 1764 | #endif |
| 1765 | |
| 1766 | |
| 1767 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1768 | #include <sys/socket.h> |
| 1769 | #include <netinet/in.h> |
| 1770 | #include <arpa/inet.h> |
| 1771 | #include <netdb.h> |
| 1772 | #ifdef HAVE_SYS_UN_H |
| 1773 | #include <sys/un.h> |
| 1774 | #endif |
| 1775 | #else |
| 1776 | #define JIM_ANSIC |
| @@ -1728,15 +1802,12 @@ | |
| 1802 | typedef struct AioFile |
| 1803 | { |
| 1804 | FILE *fp; |
| 1805 | Jim_Obj *filename; |
| 1806 | int type; |
| 1807 | int openFlags; |
| 1808 | int fd; |
| 1809 | Jim_Obj *rEvent; |
| 1810 | Jim_Obj *wEvent; |
| 1811 | Jim_Obj *eEvent; |
| 1812 | int addr_family; |
| 1813 | } AioFile; |
| @@ -1760,20 +1831,21 @@ | |
| 1831 | { |
| 1832 | AioFile *af = privData; |
| 1833 | |
| 1834 | JIM_NOTUSED(interp); |
| 1835 | |
| 1836 | Jim_DecrRefCount(interp, af->filename); |
| 1837 | |
| 1838 | #ifdef jim_ext_eventloop |
| 1839 | |
| 1840 | Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 1841 | #endif |
| 1842 | |
| 1843 | if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 1844 | fclose(af->fp); |
| 1845 | } |
| 1846 | |
| 1847 | Jim_Free(af); |
| 1848 | } |
| 1849 | |
| 1850 | static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) |
| 1851 | { |
| @@ -2020,12 +2092,31 @@ | |
| 2092 | return JIM_OK; |
| 2093 | } |
| 2094 | |
| 2095 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2096 | { |
| 2097 | if (argc == 3) { |
| 2098 | #if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) |
| 2099 | static const char * const options[] = { "r", "w", NULL }; |
| 2100 | enum { OPT_R, OPT_W, }; |
| 2101 | int option; |
| 2102 | AioFile *af = Jim_CmdPrivData(interp); |
| 2103 | |
| 2104 | if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2105 | return JIM_ERR; |
| 2106 | } |
| 2107 | if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { |
| 2108 | return JIM_OK; |
| 2109 | } |
| 2110 | JimAioSetError(interp, NULL); |
| 2111 | #else |
| 2112 | Jim_SetResultString(interp, "async close not supported", -1); |
| 2113 | #endif |
| 2114 | return JIM_ERR; |
| 2115 | } |
| 2116 | |
| 2117 | return Jim_DeleteCommand(interp, Jim_String(argv[0])); |
| 2118 | } |
| 2119 | |
| 2120 | static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2121 | { |
| 2122 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2072,11 +2163,11 @@ | |
| 2163 | #ifdef O_NDELAY |
| 2164 | static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2165 | { |
| 2166 | AioFile *af = Jim_CmdPrivData(interp); |
| 2167 | |
| 2168 | int fmode = fcntl(af->fd, F_GETFL); |
| 2169 | |
| 2170 | if (argc) { |
| 2171 | long nb; |
| 2172 | |
| 2173 | if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { |
| @@ -2086,12 +2177,11 @@ | |
| 2177 | fmode |= O_NDELAY; |
| 2178 | } |
| 2179 | else { |
| 2180 | fmode &= ~O_NDELAY; |
| 2181 | } |
| 2182 | (void)fcntl(af->fd, F_SETFL, fmode); |
| 2183 | } |
| 2184 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2185 | return JIM_OK; |
| 2186 | } |
| 2187 | #endif |
| @@ -2195,11 +2285,11 @@ | |
| 2285 | |
| 2286 | static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2287 | { |
| 2288 | AioFile *af = Jim_CmdPrivData(interp); |
| 2289 | |
| 2290 | return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2291 | } |
| 2292 | #endif |
| 2293 | |
| 2294 | static const jim_subcmd_type aio_command_table[] = { |
| 2295 | { "read", |
| @@ -2250,14 +2340,14 @@ | |
| 2340 | 0, |
| 2341 | 0, |
| 2342 | |
| 2343 | }, |
| 2344 | { "close", |
| 2345 | "?r(ead)|w(rite)?", |
| 2346 | aio_cmd_close, |
| 2347 | 0, |
| 2348 | 1, |
| 2349 | JIM_MODFLAG_FULLARGV, |
| 2350 | |
| 2351 | }, |
| 2352 | { "seek", |
| 2353 | "offset ?start|current|end", |
| @@ -2329,30 +2419,32 @@ | |
| 2419 | |
| 2420 | static int JimAioOpenCommand(Jim_Interp *interp, int argc, |
| 2421 | Jim_Obj *const *argv) |
| 2422 | { |
| 2423 | const char *mode; |
| 2424 | |
| 2425 | if (argc != 2 && argc != 3) { |
| 2426 | Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); |
| 2427 | return JIM_ERR; |
| 2428 | } |
| 2429 | |
| 2430 | mode = (argc == 3) ? Jim_String(argv[2]) : "r"; |
| 2431 | |
| 2432 | #ifdef jim_ext_tclcompat |
| 2433 | { |
| 2434 | const char *filename = Jim_String(argv[1]); |
| 2435 | |
| 2436 | |
| 2437 | if (*filename == '|') { |
| 2438 | Jim_Obj *evalObj[3]; |
| 2439 | |
| 2440 | evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2441 | evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| 2442 | evalObj[2] = Jim_NewStringObj(interp, mode, -1); |
| 2443 | |
| 2444 | return Jim_EvalObjVector(interp, 3, evalObj); |
| 2445 | } |
| 2446 | } |
| 2447 | #endif |
| 2448 | return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode); |
| 2449 | } |
| 2450 | |
| @@ -2359,70 +2451,129 @@ | |
| 2451 | static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2452 | const char *hdlfmt, int family, const char *mode) |
| 2453 | { |
| 2454 | AioFile *af; |
| 2455 | char buf[AIO_CMD_LEN]; |
| 2456 | int openFlags = 0; |
| 2457 | |
| 2458 | if (fh) { |
| 2459 | filename = Jim_NewStringObj(interp, hdlfmt, -1); |
| 2460 | openFlags = AIO_KEEPOPEN; |
| 2461 | } |
| 2462 | |
| 2463 | Jim_IncrRefCount(filename); |
| 2464 | |
| 2465 | if (fh == NULL) { |
| 2466 | #if !defined(JIM_ANSIC) |
| 2467 | if (fd >= 0) { |
| 2468 | fh = fdopen(fd, mode); |
| 2469 | } |
| 2470 | else |
| 2471 | #endif |
| 2472 | fh = fopen(Jim_String(filename), mode); |
| 2473 | |
| 2474 | if (fh == NULL) { |
| 2475 | JimAioSetError(interp, filename); |
| 2476 | #if !defined(JIM_ANSIC) |
| 2477 | if (fd >= 0) { |
| 2478 | close(fd); |
| 2479 | } |
| 2480 | #endif |
| 2481 | Jim_DecrRefCount(interp, filename); |
| 2482 | return JIM_ERR; |
| 2483 | } |
| 2484 | } |
| 2485 | |
| 2486 | |
| 2487 | af = Jim_Alloc(sizeof(*af)); |
| 2488 | memset(af, 0, sizeof(*af)); |
| 2489 | af->fp = fh; |
| 2490 | af->fd = fileno(fh); |
| 2491 | af->filename = filename; |
| 2492 | #ifdef FD_CLOEXEC |
| 2493 | if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 2494 | (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2495 | } |
| 2496 | #endif |
| 2497 | af->openFlags = openFlags; |
| 2498 | af->addr_family = family; |
| 2499 | snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2500 | Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); |
| 2501 | |
| 2502 | Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); |
| 2503 | |
| 2504 | return JIM_OK; |
| 2505 | } |
| 2506 | |
| 2507 | static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename, |
| 2508 | const char *hdlfmt, int family, const char *mode[2]) |
| 2509 | { |
| 2510 | if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) { |
| 2511 | Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); |
| 2512 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2513 | |
| 2514 | if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) { |
| 2515 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2516 | Jim_SetResult(interp, objPtr); |
| 2517 | return JIM_OK; |
| 2518 | } |
| 2519 | } |
| 2520 | |
| 2521 | |
| 2522 | close(p[0]); |
| 2523 | close(p[1]); |
| 2524 | JimAioSetError(interp, NULL); |
| 2525 | return JIM_ERR; |
| 2526 | } |
| 2527 | |
| 2528 | |
| 2529 | int Jim_MakeTempFile(Jim_Interp *interp, const char *template) |
| 2530 | { |
| 2531 | #ifdef HAVE_MKSTEMP |
| 2532 | int fd; |
| 2533 | mode_t mask; |
| 2534 | Jim_Obj *filenameObj; |
| 2535 | |
| 2536 | if (template == NULL) { |
| 2537 | const char *tmpdir = getenv("TMPDIR"); |
| 2538 | if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { |
| 2539 | tmpdir = "/tmp/"; |
| 2540 | } |
| 2541 | filenameObj = Jim_NewStringObj(interp, tmpdir, -1); |
| 2542 | if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { |
| 2543 | Jim_AppendString(interp, filenameObj, "/", 1); |
| 2544 | } |
| 2545 | Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); |
| 2546 | } |
| 2547 | else { |
| 2548 | filenameObj = Jim_NewStringObj(interp, template, -1); |
| 2549 | } |
| 2550 | |
| 2551 | mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); |
| 2552 | |
| 2553 | |
| 2554 | fd = mkstemp(filenameObj->bytes); |
| 2555 | umask(mask); |
| 2556 | if (fd < 0) { |
| 2557 | Jim_SetResultString(interp, "Failed to create tempfile", -1); |
| 2558 | Jim_FreeNewObj(interp, filenameObj); |
| 2559 | return -1; |
| 2560 | } |
| 2561 | |
| 2562 | Jim_SetResult(interp, filenameObj); |
| 2563 | return fd; |
| 2564 | #else |
| 2565 | Jim_SetResultString(interp, "tempfile not supported", -1); |
| 2566 | return -1; |
| 2567 | #endif |
| 2568 | } |
| 2569 | |
| 2570 | FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2571 | { |
| 2572 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2573 | |
| 2574 | |
| 2575 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2576 | return ((AioFile *) cmdPtr->u.native.privData)->fp; |
| 2577 | } |
| 2578 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2579 | return NULL; |
| @@ -2443,11 +2594,10 @@ | |
| 2594 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2595 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2596 | |
| 2597 | return JIM_OK; |
| 2598 | } |
| 2599 | |
| 2600 | #include <errno.h> |
| 2601 | #include <stdio.h> |
| 2602 | #include <string.h> |
| 2603 | |
| @@ -2479,28 +2629,29 @@ | |
| 2629 | return JIM_OK; |
| 2630 | } |
| 2631 | Jim_SetResultString(interp, strerror(errno), -1); |
| 2632 | return JIM_ERR; |
| 2633 | } |
| 2634 | else { |
| 2635 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 2636 | |
| 2637 | while ((entryPtr = readdir(dirPtr)) != NULL) { |
| 2638 | if (entryPtr->d_name[0] == '.') { |
| 2639 | if (entryPtr->d_name[1] == '\0') { |
| 2640 | continue; |
| 2641 | } |
| 2642 | if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) |
| 2643 | continue; |
| 2644 | } |
| 2645 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); |
| 2646 | } |
| 2647 | closedir(dirPtr); |
| 2648 | |
| 2649 | Jim_SetResult(interp, listObj); |
| 2650 | |
| 2651 | return JIM_OK; |
| 2652 | } |
| 2653 | } |
| 2654 | |
| 2655 | int Jim_readdirInit(Jim_Interp *interp) |
| 2656 | { |
| 2657 | if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) |
| @@ -2511,10 +2662,14 @@ | |
| 2662 | } |
| 2663 | |
| 2664 | #include <stdlib.h> |
| 2665 | #include <string.h> |
| 2666 | |
| 2667 | #if defined(JIM_REGEXP) |
| 2668 | #else |
| 2669 | #include <regex.h> |
| 2670 | #endif |
| 2671 | |
| 2672 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2673 | { |
| 2674 | regfree(objPtr->internalRep.regexpValue.compre); |
| 2675 | Jim_Free(objPtr->internalRep.regexpValue.compre); |
| @@ -3058,58 +3213,61 @@ | |
| 3213 | } |
| 3214 | #endif |
| 3215 | return "unknown"; |
| 3216 | } |
| 3217 | |
| 3218 | static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value) |
| 3219 | { |
| 3220 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); |
| 3221 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3222 | } |
| 3223 | |
| 3224 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3225 | { |
| 3226 | |
| 3227 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3228 | |
| 3229 | AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| 3230 | AppendStatElement(interp, listObj, "ino", sb->st_ino); |
| 3231 | AppendStatElement(interp, listObj, "mode", sb->st_mode); |
| 3232 | AppendStatElement(interp, listObj, "nlink", sb->st_nlink); |
| 3233 | AppendStatElement(interp, listObj, "uid", sb->st_uid); |
| 3234 | AppendStatElement(interp, listObj, "gid", sb->st_gid); |
| 3235 | AppendStatElement(interp, listObj, "size", sb->st_size); |
| 3236 | AppendStatElement(interp, listObj, "atime", sb->st_atime); |
| 3237 | AppendStatElement(interp, listObj, "mtime", sb->st_mtime); |
| 3238 | AppendStatElement(interp, listObj, "ctime", sb->st_ctime); |
| 3239 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 3240 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); |
| 3241 | |
| 3242 | |
| 3243 | if (varName) { |
| 3244 | Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); |
| 3245 | if (objPtr) { |
| 3246 | if (Jim_DictSize(interp, objPtr) < 0) { |
| 3247 | |
| 3248 | Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3249 | Jim_FreeNewObj(interp, listObj); |
| 3250 | return JIM_ERR; |
| 3251 | } |
| 3252 | |
| 3253 | if (Jim_IsShared(objPtr)) |
| 3254 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| 3255 | |
| 3256 | |
| 3257 | Jim_ListAppendList(interp, objPtr, listObj); |
| 3258 | Jim_DictSize(interp, objPtr); |
| 3259 | Jim_InvalidateStringRep(objPtr); |
| 3260 | |
| 3261 | Jim_FreeNewObj(interp, listObj); |
| 3262 | listObj = objPtr; |
| 3263 | } |
| 3264 | Jim_SetVariable(interp, varName, listObj); |
| 3265 | } |
| 3266 | |
| 3267 | |
| 3268 | Jim_SetResult(interp, listObj); |
| 3269 | |
| 3270 | return JIM_OK; |
| 3271 | } |
| 3272 | |
| 3273 | static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3264,14 +3422,11 @@ | |
| 3422 | return JIM_OK; |
| 3423 | } |
| 3424 | |
| 3425 | static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) |
| 3426 | { |
| 3427 | Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1); |
| 3428 | |
| 3429 | return JIM_OK; |
| 3430 | } |
| 3431 | |
| 3432 | static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3287,10 +3442,11 @@ | |
| 3442 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3443 | { |
| 3444 | #ifdef X_OK |
| 3445 | return file_access(interp, argv[0], X_OK); |
| 3446 | #else |
| 3447 | |
| 3448 | Jim_SetResultBool(interp, 1); |
| 3449 | return JIM_OK; |
| 3450 | #endif |
| 3451 | } |
| 3452 | |
| @@ -3391,33 +3547,21 @@ | |
| 3547 | argv++; |
| 3548 | } |
| 3549 | return JIM_OK; |
| 3550 | } |
| 3551 | |
| 3552 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3553 | { |
| 3554 | int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); |
| 3555 | |
| 3556 | if (fd < 0) { |
| 3557 | return JIM_ERR; |
| 3558 | } |
| 3559 | close(fd); |
| 3560 | |
| 3561 | return JIM_OK; |
| 3562 | } |
| 3563 | |
| 3564 | static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3565 | { |
| 3566 | const char *source; |
| 3567 | const char *dest; |
| @@ -3459,14 +3603,11 @@ | |
| 3603 | return JIM_ERR; |
| 3604 | } |
| 3605 | return JIM_OK; |
| 3606 | } |
| 3607 | |
| 3608 | #ifdef HAVE_LSTAT |
| 3609 | static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 3610 | { |
| 3611 | const char *path = Jim_String(filename); |
| 3612 | |
| 3613 | if (lstat(path, sb) == -1) { |
| @@ -3473,10 +3614,13 @@ | |
| 3614 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3615 | return JIM_ERR; |
| 3616 | } |
| 3617 | return JIM_OK; |
| 3618 | } |
| 3619 | #else |
| 3620 | #define file_lstat file_stat |
| 3621 | #endif |
| 3622 | |
| 3623 | static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3624 | { |
| 3625 | struct stat sb; |
| 3626 | |
| @@ -3601,28 +3745,32 @@ | |
| 3745 | } |
| 3746 | Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); |
| 3747 | return JIM_OK; |
| 3748 | } |
| 3749 | |
| 3750 | #ifdef HAVE_LSTAT |
| 3751 | static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3752 | { |
| 3753 | struct stat sb; |
| 3754 | |
| 3755 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 3756 | return JIM_ERR; |
| 3757 | } |
| 3758 | return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 3759 | } |
| 3760 | #else |
| 3761 | #define file_cmd_lstat file_cmd_stat |
| 3762 | #endif |
| 3763 | |
| 3764 | static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3765 | { |
| 3766 | struct stat sb; |
| 3767 | |
| 3768 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 3769 | return JIM_ERR; |
| 3770 | } |
| 3771 | return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 3772 | } |
| 3773 | |
| 3774 | static const jim_subcmd_type file_command_table[] = { |
| 3775 | { "atime", |
| 3776 | "name", |
| @@ -3727,19 +3875,17 @@ | |
| 3875 | file_cmd_mkdir, |
| 3876 | 1, |
| 3877 | -1, |
| 3878 | |
| 3879 | }, |
| 3880 | { "tempfile", |
| 3881 | "?template?", |
| 3882 | file_cmd_tempfile, |
| 3883 | 0, |
| 3884 | 1, |
| 3885 | |
| 3886 | }, |
| 3887 | { "rename", |
| 3888 | "?-force? source dest", |
| 3889 | file_cmd_rename, |
| 3890 | 2, |
| 3891 | 3, |
| @@ -3760,20 +3906,20 @@ | |
| 3906 | 1, |
| 3907 | 1, |
| 3908 | |
| 3909 | }, |
| 3910 | { "stat", |
| 3911 | "name ?var?", |
| 3912 | file_cmd_stat, |
| 3913 | 1, |
| 3914 | 2, |
| 3915 | |
| 3916 | }, |
| 3917 | { "lstat", |
| 3918 | "name ?var?", |
| 3919 | file_cmd_lstat, |
| 3920 | 1, |
| 3921 | 2, |
| 3922 | |
| 3923 | }, |
| 3924 | { "type", |
| 3925 | "name", |
| @@ -3829,15 +3975,15 @@ | |
| 3975 | return JIM_OK; |
| 3976 | } |
| 3977 | |
| 3978 | static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3979 | { |
| 3980 | char *cwd = Jim_Alloc(MAXPATHLEN); |
| 3981 | |
| 3982 | if (getcwd(cwd, MAXPATHLEN) == NULL) { |
| 3983 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 3984 | Jim_Free(cwd); |
| 3985 | return JIM_ERR; |
| 3986 | } |
| 3987 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 3988 | { |
| 3989 | |
| @@ -3848,11 +3994,11 @@ | |
| 3994 | } |
| 3995 | #endif |
| 3996 | |
| 3997 | Jim_SetResultString(interp, cwd, -1); |
| 3998 | |
| 3999 | Jim_Free(cwd); |
| 4000 | return JIM_OK; |
| 4001 | } |
| 4002 | |
| 4003 | int Jim_fileInit(Jim_Interp *interp) |
| 4004 | { |
| @@ -3917,10 +4063,11 @@ | |
| 4063 | |
| 4064 | int Jim_execInit(Jim_Interp *interp) |
| 4065 | { |
| 4066 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4067 | return JIM_ERR; |
| 4068 | |
| 4069 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); |
| 4070 | return JIM_OK; |
| 4071 | } |
| 4072 | #else |
| 4073 | |
| @@ -3960,10 +4107,11 @@ | |
| 4107 | static int JimErrno(void); |
| 4108 | #else |
| 4109 | #include <unistd.h> |
| 4110 | #include <fcntl.h> |
| 4111 | #include <sys/wait.h> |
| 4112 | #include <sys/stat.h> |
| 4113 | |
| 4114 | typedef int fdtype; |
| 4115 | typedef int pidtype; |
| 4116 | #define JimPipe pipe |
| 4117 | #define JimErrno() errno |
| @@ -4034,23 +4182,12 @@ | |
| 4182 | Jim_RemoveTrailingNewline(strObj); |
| 4183 | fclose(fh); |
| 4184 | return JIM_OK; |
| 4185 | } |
| 4186 | |
| 4187 | static char **JimBuildEnv(Jim_Interp *interp) |
| 4188 | { |
| 4189 | int i; |
| 4190 | int size; |
| 4191 | int num; |
| 4192 | int n; |
| 4193 | char **envptr; |
| @@ -4064,10 +4201,11 @@ | |
| 4201 | |
| 4202 | |
| 4203 | |
| 4204 | num = Jim_ListLength(interp, objPtr); |
| 4205 | if (num % 2) { |
| 4206 | |
| 4207 | num--; |
| 4208 | } |
| 4209 | size = Jim_Length(objPtr) + 2; |
| 4210 | |
| 4211 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4090,22 +4228,17 @@ | |
| 4228 | } |
| 4229 | envptr[n] = NULL; |
| 4230 | *envdata = 0; |
| 4231 | |
| 4232 | return envptr; |
| 4233 | } |
| 4234 | |
| 4235 | static void JimFreeEnv(char **env, char **original_environ) |
| 4236 | { |
| 4237 | if (env != original_environ) { |
| 4238 | Jim_Free(env); |
| 4239 | } |
| 4240 | } |
| 4241 | |
| 4242 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) |
| 4243 | { |
| 4244 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| @@ -4154,19 +4287,19 @@ | |
| 4287 | } |
| 4288 | |
| 4289 | |
| 4290 | struct WaitInfo |
| 4291 | { |
| 4292 | pidtype pid; |
| 4293 | int status; |
| 4294 | int flags; |
| 4295 | }; |
| 4296 | |
| 4297 | struct WaitInfoTable { |
| 4298 | struct WaitInfo *info; |
| 4299 | int size; |
| 4300 | int used; |
| 4301 | }; |
| 4302 | |
| 4303 | |
| 4304 | #define WI_DETACHED 2 |
| 4305 | |
| @@ -4189,14 +4322,12 @@ | |
| 4322 | return table; |
| 4323 | } |
| 4324 | |
| 4325 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4326 | { |
| 4327 | fdtype outputId; |
| 4328 | fdtype errorId; |
| 4329 | pidtype *pidPtr; |
| 4330 | int numPids, result; |
| 4331 | |
| 4332 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4333 | Jim_Obj *listObj; |
| @@ -4243,26 +4374,32 @@ | |
| 4374 | |
| 4375 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4376 | { |
| 4377 | struct WaitInfo *waitPtr; |
| 4378 | int count; |
| 4379 | int dest; |
| 4380 | |
| 4381 | if (!table) { |
| 4382 | return; |
| 4383 | } |
| 4384 | |
| 4385 | waitPtr = table->info; |
| 4386 | dest = 0; |
| 4387 | for (count = table->used; count > 0; waitPtr++, count--) { |
| 4388 | if (waitPtr->flags & WI_DETACHED) { |
| 4389 | int status; |
| 4390 | pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); |
| 4391 | if (pid == waitPtr->pid) { |
| 4392 | |
| 4393 | table->used--; |
| 4394 | continue; |
| 4395 | } |
| 4396 | } |
| 4397 | if (waitPtr != &table->info[dest]) { |
| 4398 | table->info[dest] = *waitPtr; |
| 4399 | } |
| 4400 | dest++; |
| 4401 | } |
| 4402 | } |
| 4403 | |
| 4404 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4405 | { |
| @@ -4284,11 +4421,10 @@ | |
| 4421 | } |
| 4422 | |
| 4423 | |
| 4424 | return JIM_BAD_PID; |
| 4425 | } |
| 4426 | |
| 4427 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) |
| 4428 | { |
| 4429 | int j; |
| 4430 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| @@ -4609,27 +4745,23 @@ | |
| 4745 | } |
| 4746 | outputId = pipeIds[1]; |
| 4747 | } |
| 4748 | |
| 4749 | |
| 4750 | if (pipe_dup_err) { |
| 4751 | errorId = outputId; |
| 4752 | } |
| 4753 | |
| 4754 | |
| 4755 | |
| 4756 | #ifdef __MINGW32__ |
| 4757 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); |
| 4758 | if (pid == JIM_BAD_PID) { |
| 4759 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4760 | goto error; |
| 4761 | } |
| 4762 | #else |
| 4763 | pid = vfork(); |
| 4764 | if (pid < 0) { |
| 4765 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 4766 | goto error; |
| 4767 | } |
| @@ -4642,14 +4774,17 @@ | |
| 4774 | |
| 4775 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 4776 | close(i); |
| 4777 | } |
| 4778 | |
| 4779 | |
| 4780 | (void)signal(SIGPIPE, SIG_DFL); |
| 4781 | |
| 4782 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 4783 | |
| 4784 | |
| 4785 | fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); |
| 4786 | _exit(127); |
| 4787 | } |
| 4788 | #endif |
| 4789 | |
| 4790 | |
| @@ -4751,19 +4886,24 @@ | |
| 4886 | if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { |
| 4887 | result = JIM_ERR; |
| 4888 | } |
| 4889 | } |
| 4890 | |
| 4891 | Jim_RemoveTrailingNewline(Jim_GetResult(interp)); |
| 4892 | |
| 4893 | return result; |
| 4894 | } |
| 4895 | |
| 4896 | int Jim_execInit(Jim_Interp *interp) |
| 4897 | { |
| 4898 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4899 | return JIM_ERR; |
| 4900 | |
| 4901 | #ifdef SIGPIPE |
| 4902 | (void)signal(SIGPIPE, SIG_IGN); |
| 4903 | #endif |
| 4904 | |
| 4905 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); |
| 4906 | return JIM_OK; |
| 4907 | } |
| 4908 | |
| 4909 | #if defined(__MINGW32__) |
| @@ -5088,28 +5228,26 @@ | |
| 5228 | { |
| 5229 | STARTUPINFO startInfo; |
| 5230 | PROCESS_INFORMATION procInfo; |
| 5231 | HANDLE hProcess, h; |
| 5232 | char execPath[MAX_PATH]; |
| 5233 | pidtype pid = JIM_BAD_PID; |
| 5234 | Jim_Obj *cmdLineObj; |
| 5235 | |
| 5236 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5237 | return JIM_BAD_PID; |
| 5238 | } |
| 5239 | argv[0] = execPath; |
| 5240 | |
| 5241 | hProcess = GetCurrentProcess(); |
| 5242 | cmdLineObj = JimWinBuildCommandLine(interp, argv); |
| 5243 | |
| 5244 | |
| 5245 | ZeroMemory(&startInfo, sizeof(startInfo)); |
| 5246 | startInfo.cb = sizeof(startInfo); |
| 5247 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5248 | startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5249 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5250 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5251 | |
| 5252 | if (inputId == JIM_BAD_FD) { |
| 5253 | if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { |
| @@ -5182,18 +5320,17 @@ | |
| 5320 | return lseek(fd, 0L, SEEK_SET); |
| 5321 | } |
| 5322 | |
| 5323 | static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5324 | { |
| 5325 | int fd = Jim_MakeTempFile(interp, NULL); |
| 5326 | |
| 5327 | if (fd == JIM_BAD_FD) { |
| 5328 | Jim_SetResultErrno(interp, "couldn't create temp file"); |
| 5329 | return -1; |
| 5330 | } |
| 5331 | unlink(Jim_String(Jim_GetResult(interp))); |
| 5332 | if (contents) { |
| 5333 | if (write(fd, contents, len) != len) { |
| 5334 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5335 | close(fd); |
| 5336 | return -1; |
| @@ -5217,11 +5354,10 @@ | |
| 5354 | } |
| 5355 | #endif |
| 5356 | #endif |
| 5357 | |
| 5358 | |
| 5359 | #ifndef _XOPEN_SOURCE |
| 5360 | #define _XOPEN_SOURCE 500 |
| 5361 | #endif |
| 5362 | |
| 5363 | #include <stdlib.h> |
| @@ -5239,11 +5375,11 @@ | |
| 5375 | |
| 5376 | char buf[100]; |
| 5377 | time_t t; |
| 5378 | long seconds; |
| 5379 | |
| 5380 | const char *format = "%a %b %d %H:%M:%S %Z %Y"; |
| 5381 | |
| 5382 | if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { |
| 5383 | return -1; |
| 5384 | } |
| 5385 | |
| @@ -5254,11 +5390,14 @@ | |
| 5390 | if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { |
| 5391 | return JIM_ERR; |
| 5392 | } |
| 5393 | t = seconds; |
| 5394 | |
| 5395 | if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { |
| 5396 | Jim_SetResultString(interp, "format string too long", -1); |
| 5397 | return JIM_ERR; |
| 5398 | } |
| 5399 | |
| 5400 | Jim_SetResultString(interp, buf, -1); |
| 5401 | |
| 5402 | return JIM_OK; |
| 5403 | } |
| @@ -5374,11 +5513,10 @@ | |
| 5513 | |
| 5514 | Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); |
| 5515 | return JIM_OK; |
| 5516 | } |
| 5517 | |
| 5518 | #include <limits.h> |
| 5519 | #include <stdlib.h> |
| 5520 | #include <string.h> |
| 5521 | #include <stdio.h> |
| 5522 | #include <errno.h> |
| @@ -5392,33 +5530,29 @@ | |
| 5530 | } |
| 5531 | |
| 5532 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5533 | { |
| 5534 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5535 | Jim_Obj *patternObj; |
| 5536 | |
| 5537 | if (!objPtr) { |
| 5538 | return JIM_OK; |
| 5539 | } |
| 5540 | |
| 5541 | patternObj = (argc == 1) ? NULL : argv[1]; |
| 5542 | |
| 5543 | |
| 5544 | if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { |
| 5545 | if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { |
| 5546 | |
| 5547 | Jim_SetResult(interp, objPtr); |
| 5548 | return JIM_OK; |
| 5549 | } |
| 5550 | } |
| 5551 | |
| 5552 | |
| 5553 | return Jim_DictValues(interp, objPtr, patternObj); |
| 5554 | } |
| 5555 | |
| 5556 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5557 | { |
| 5558 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5443,10 +5577,15 @@ | |
| 5577 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5578 | return JIM_OK; |
| 5579 | } |
| 5580 | |
| 5581 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5582 | |
| 5583 | if (objPtr == NULL) { |
| 5584 | |
| 5585 | return JIM_OK; |
| 5586 | } |
| 5587 | |
| 5588 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5589 | return JIM_ERR; |
| 5590 | } |
| 5591 | |
| @@ -5480,10 +5619,20 @@ | |
| 5619 | |
| 5620 | Jim_SetResultInt(interp, len); |
| 5621 | |
| 5622 | return JIM_OK; |
| 5623 | } |
| 5624 | |
| 5625 | static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5626 | { |
| 5627 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5628 | if (objPtr) { |
| 5629 | return Jim_DictInfo(interp, objPtr); |
| 5630 | } |
| 5631 | Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL); |
| 5632 | return JIM_ERR; |
| 5633 | } |
| 5634 | |
| 5635 | static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5636 | { |
| 5637 | int i; |
| 5638 | int len; |
| @@ -5498,10 +5647,13 @@ | |
| 5647 | |
| 5648 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5649 | if (!dictObj) { |
| 5650 | |
| 5651 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5652 | } |
| 5653 | else if (Jim_DictSize(interp, dictObj) < 0) { |
| 5654 | return JIM_ERR; |
| 5655 | } |
| 5656 | |
| 5657 | if (Jim_IsShared(dictObj)) { |
| 5658 | dictObj = Jim_DuplicateObj(interp, dictObj); |
| 5659 | } |
| @@ -5551,10 +5703,17 @@ | |
| 5703 | "arrayName", |
| 5704 | array_cmd_size, |
| 5705 | 1, |
| 5706 | 1, |
| 5707 | |
| 5708 | }, |
| 5709 | { "stat", |
| 5710 | "arrayName", |
| 5711 | array_cmd_stat, |
| 5712 | 1, |
| 5713 | 1, |
| 5714 | |
| 5715 | }, |
| 5716 | { "unset", |
| 5717 | "arrayName ?pattern?", |
| 5718 | array_cmd_unset, |
| 5719 | 1, |
| @@ -5597,11 +5756,10 @@ | |
| 5756 | Jim_arrayInit(interp); |
| 5757 | Jim_stdlibInit(interp); |
| 5758 | Jim_tclcompatInit(interp); |
| 5759 | return JIM_OK; |
| 5760 | } |
| 5761 | #define JIM_OPTIMIZATION |
| 5762 | |
| 5763 | #include <stdio.h> |
| 5764 | #include <stdlib.h> |
| 5765 | |
| @@ -5661,21 +5819,20 @@ | |
| 5819 | #define JIM_INTEGER_SPACE 24 |
| 5820 | |
| 5821 | const char *jim_tt_name(int type); |
| 5822 | |
| 5823 | #ifdef JIM_DEBUG_PANIC |
| 5824 | static void JimPanicDump(int fail_condition, const char *fmt, ...); |
| 5825 | #define JimPanic(X) JimPanicDump X |
| 5826 | #else |
| 5827 | #define JimPanic(X) |
| 5828 | #endif |
| 5829 | |
| 5830 | |
| 5831 | static char JimEmptyStringRep[] = ""; |
| 5832 | |
| 5833 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 5834 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| 5835 | int flags); |
| 5836 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); |
| 5837 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); |
| 5838 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -5922,44 +6079,10 @@ | |
| 6079 | } |
| 6080 | return n; |
| 6081 | } |
| 6082 | #endif |
| 6083 | |
| 6084 | static int JimCheckConversion(const char *str, const char *endptr) |
| 6085 | { |
| 6086 | if (str[0] == '\0' || str == endptr) { |
| 6087 | return JIM_ERR; |
| 6088 | } |
| @@ -6070,48 +6193,10 @@ | |
| 6193 | } |
| 6194 | |
| 6195 | return JimCheckConversion(str, endptr); |
| 6196 | } |
| 6197 | |
| 6198 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6199 | { |
| 6200 | char *endptr; |
| 6201 | |
| 6202 | |
| @@ -6133,23 +6218,23 @@ | |
| 6218 | } |
| 6219 | return res; |
| 6220 | } |
| 6221 | |
| 6222 | #ifdef JIM_DEBUG_PANIC |
| 6223 | static void JimPanicDump(int condition, const char *fmt, ...) |
| 6224 | { |
| 6225 | va_list ap; |
| 6226 | |
| 6227 | if (!condition) { |
| 6228 | return; |
| 6229 | } |
| 6230 | |
| 6231 | va_start(ap, fmt); |
| 6232 | |
| 6233 | fprintf(stderr, "\nJIM INTERPRETER PANIC: "); |
| 6234 | vfprintf(stderr, fmt, ap); |
| 6235 | fprintf(stderr, "\n\n"); |
| 6236 | va_end(ap); |
| 6237 | |
| 6238 | #ifdef HAVE_BACKTRACE |
| 6239 | { |
| 6240 | void *array[40]; |
| @@ -6157,13 +6242,13 @@ | |
| 6242 | char **strings; |
| 6243 | |
| 6244 | size = backtrace(array, 40); |
| 6245 | strings = backtrace_symbols(array, size); |
| 6246 | for (i = 0; i < size; i++) |
| 6247 | fprintf(stderr, "[backtrace] %s\n", strings[i]); |
| 6248 | fprintf(stderr, "[backtrace] Include the above lines and the output\n"); |
| 6249 | fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n"); |
| 6250 | } |
| 6251 | #endif |
| 6252 | |
| 6253 | exit(1); |
| 6254 | } |
| @@ -6237,18 +6322,24 @@ | |
| 6322 | h += (h << 3) + *buf++; |
| 6323 | return h; |
| 6324 | } |
| 6325 | |
| 6326 | |
| 6327 | |
| 6328 | |
| 6329 | static void JimResetHashTable(Jim_HashTable *ht) |
| 6330 | { |
| 6331 | ht->table = NULL; |
| 6332 | ht->size = 0; |
| 6333 | ht->sizemask = 0; |
| 6334 | ht->used = 0; |
| 6335 | ht->collisions = 0; |
| 6336 | #ifdef JIM_RANDOMISE_HASH |
| 6337 | ht->uniq = (rand() ^ time(NULL) ^ clock()); |
| 6338 | #else |
| 6339 | ht->uniq = 0; |
| 6340 | #endif |
| 6341 | } |
| 6342 | |
| 6343 | static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) |
| 6344 | { |
| 6345 | iter->ht = ht; |
| @@ -6286,10 +6377,12 @@ | |
| 6377 | |
| 6378 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6379 | n.size = realsize; |
| 6380 | n.sizemask = realsize - 1; |
| 6381 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6382 | |
| 6383 | n.uniq = ht->uniq; |
| 6384 | |
| 6385 | |
| 6386 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6387 | |
| 6388 | n.used = ht->used; |
| @@ -6342,20 +6435,27 @@ | |
| 6435 | int existed; |
| 6436 | Jim_HashEntry *entry; |
| 6437 | |
| 6438 | entry = JimInsertHashEntry(ht, key, 1); |
| 6439 | if (entry->key) { |
| 6440 | if (ht->type->valDestructor && ht->type->valDup) { |
| 6441 | void *newval = ht->type->valDup(ht->privdata, val); |
| 6442 | ht->type->valDestructor(ht->privdata, entry->u.val); |
| 6443 | entry->u.val = newval; |
| 6444 | } |
| 6445 | else { |
| 6446 | Jim_FreeEntryVal(ht, entry); |
| 6447 | Jim_SetHashVal(ht, entry, val); |
| 6448 | } |
| 6449 | existed = 1; |
| 6450 | } |
| 6451 | else { |
| 6452 | |
| 6453 | Jim_SetHashKey(ht, entry, key); |
| 6454 | Jim_SetHashVal(ht, entry, val); |
| 6455 | existed = 0; |
| 6456 | } |
| 6457 | |
| 6458 | return existed; |
| 6459 | } |
| 6460 | |
| 6461 | |
| @@ -6520,11 +6620,11 @@ | |
| 6620 | return Jim_GenHashFunction(key, strlen(key)); |
| 6621 | } |
| 6622 | |
| 6623 | static void *JimStringCopyHTDup(void *privdata, const void *key) |
| 6624 | { |
| 6625 | return Jim_StrDup(key); |
| 6626 | } |
| 6627 | |
| 6628 | static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 6629 | { |
| 6630 | return strcmp(key1, key2) == 0; |
| @@ -6620,11 +6720,11 @@ | |
| 6720 | freeFunc(stack->vector[i]); |
| 6721 | } |
| 6722 | |
| 6723 | |
| 6724 | |
| 6725 | #define JIM_TT_NONE 0 |
| 6726 | #define JIM_TT_STR 1 |
| 6727 | #define JIM_TT_ESC 2 |
| 6728 | #define JIM_TT_VAR 3 |
| 6729 | #define JIM_TT_DICTSUGAR 4 |
| 6730 | #define JIM_TT_CMD 5 |
| @@ -6652,10 +6752,15 @@ | |
| 6752 | |
| 6753 | |
| 6754 | #define JIM_PS_DEF 0 |
| 6755 | #define JIM_PS_QUOTE 1 |
| 6756 | #define JIM_PS_DICTSUGAR 2 |
| 6757 | |
| 6758 | struct JimParseMissing { |
| 6759 | int ch; |
| 6760 | int line; |
| 6761 | }; |
| 6762 | |
| 6763 | struct JimParserCtx |
| 6764 | { |
| 6765 | const char *p; |
| 6766 | int len; |
| @@ -6665,17 +6770,11 @@ | |
| 6770 | int tline; |
| 6771 | int tt; |
| 6772 | int eof; |
| 6773 | int state; |
| 6774 | int comment; |
| 6775 | struct JimParseMissing missing; |
| 6776 | }; |
| 6777 | |
| 6778 | static int JimParseScript(struct JimParserCtx *pc); |
| 6779 | static int JimParseSep(struct JimParserCtx *pc); |
| 6780 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -6685,11 +6784,10 @@ | |
| 6784 | static int JimParseBrace(struct JimParserCtx *pc); |
| 6785 | static int JimParseStr(struct JimParserCtx *pc); |
| 6786 | static int JimParseComment(struct JimParserCtx *pc); |
| 6787 | static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6788 | static int JimParseSubQuote(struct JimParserCtx *pc); |
| 6789 | static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); |
| 6790 | |
| 6791 | static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) |
| 6792 | { |
| 6793 | pc->p = prg; |
| @@ -6700,12 +6798,12 @@ | |
| 6798 | pc->tt = JIM_TT_NONE; |
| 6799 | pc->eof = 0; |
| 6800 | pc->state = JIM_PS_DEF; |
| 6801 | pc->linenr = linenr; |
| 6802 | pc->comment = 1; |
| 6803 | pc->missing.ch = ' '; |
| 6804 | pc->missing.line = linenr; |
| 6805 | } |
| 6806 | |
| 6807 | static int JimParseScript(struct JimParserCtx *pc) |
| 6808 | { |
| 6809 | while (1) { |
| @@ -6837,12 +6935,12 @@ | |
| 6935 | break; |
| 6936 | } |
| 6937 | pc->p++; |
| 6938 | pc->len--; |
| 6939 | } |
| 6940 | pc->missing.ch = '{'; |
| 6941 | pc->missing.line = pc->tline; |
| 6942 | pc->tend = pc->p - 1; |
| 6943 | } |
| 6944 | |
| 6945 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 6946 | { |
| @@ -6884,12 +6982,12 @@ | |
| 6982 | break; |
| 6983 | } |
| 6984 | pc->p++; |
| 6985 | pc->len--; |
| 6986 | } |
| 6987 | pc->missing.ch = '"'; |
| 6988 | pc->missing.line = line; |
| 6989 | pc->tend = pc->p - 1; |
| 6990 | return tt; |
| 6991 | } |
| 6992 | |
| 6993 | static void JimParseSubCmd(struct JimParserCtx *pc) |
| @@ -6943,12 +7041,12 @@ | |
| 7041 | } |
| 7042 | startofword = isspace(UCHAR(*pc->p)); |
| 7043 | pc->p++; |
| 7044 | pc->len--; |
| 7045 | } |
| 7046 | pc->missing.ch = '['; |
| 7047 | pc->missing.line = line; |
| 7048 | pc->tend = pc->p - 1; |
| 7049 | } |
| 7050 | |
| 7051 | static int JimParseBrace(struct JimParserCtx *pc) |
| 7052 | { |
| @@ -7088,19 +7186,19 @@ | |
| 7186 | if (*pc->p == '"') { |
| 7187 | pc->state = JIM_PS_QUOTE; |
| 7188 | pc->p++; |
| 7189 | pc->len--; |
| 7190 | |
| 7191 | pc->missing.line = pc->tline; |
| 7192 | } |
| 7193 | } |
| 7194 | pc->tstart = pc->p; |
| 7195 | pc->tline = pc->linenr; |
| 7196 | while (1) { |
| 7197 | if (pc->len == 0) { |
| 7198 | if (pc->state == JIM_PS_QUOTE) { |
| 7199 | pc->missing.ch = '"'; |
| 7200 | } |
| 7201 | pc->tend = pc->p - 1; |
| 7202 | pc->tt = JIM_TT_ESC; |
| 7203 | return JIM_OK; |
| 7204 | } |
| @@ -7116,10 +7214,14 @@ | |
| 7214 | pc->linenr++; |
| 7215 | } |
| 7216 | pc->p++; |
| 7217 | pc->len--; |
| 7218 | } |
| 7219 | else if (pc->len == 1) { |
| 7220 | |
| 7221 | pc->missing.ch = '\\'; |
| 7222 | } |
| 7223 | break; |
| 7224 | case '(': |
| 7225 | |
| 7226 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7227 | break; |
| @@ -7176,17 +7278,26 @@ | |
| 7278 | } |
| 7279 | |
| 7280 | static int JimParseComment(struct JimParserCtx *pc) |
| 7281 | { |
| 7282 | while (*pc->p) { |
| 7283 | if (*pc->p == '\\') { |
| 7284 | pc->p++; |
| 7285 | pc->len--; |
| 7286 | if (pc->len == 0) { |
| 7287 | pc->missing.ch = '\\'; |
| 7288 | return JIM_OK; |
| 7289 | } |
| 7290 | if (*pc->p == '\n') { |
| 7291 | pc->linenr++; |
| 7292 | } |
| 7293 | } |
| 7294 | else if (*pc->p == '\n') { |
| 7295 | pc->p++; |
| 7296 | pc->len--; |
| 7297 | pc->linenr++; |
| 7298 | break; |
| 7299 | } |
| 7300 | pc->p++; |
| 7301 | pc->len--; |
| 7302 | } |
| 7303 | return JIM_OK; |
| @@ -7404,13 +7515,13 @@ | |
| 7515 | JimParserInit(&parser, s, len, 1); |
| 7516 | while (!parser.eof) { |
| 7517 | JimParseScript(&parser); |
| 7518 | } |
| 7519 | if (stateCharPtr) { |
| 7520 | *stateCharPtr = parser.missing.ch; |
| 7521 | } |
| 7522 | return parser.missing.ch == ' '; |
| 7523 | } |
| 7524 | |
| 7525 | static int JimParseListSep(struct JimParserCtx *pc); |
| 7526 | static int JimParseListStr(struct JimParserCtx *pc); |
| 7527 | static int JimParseListQuote(struct JimParserCtx *pc); |
| @@ -7662,10 +7773,16 @@ | |
| 7773 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7774 | objPtr->typePtr->updateStringProc(objPtr); |
| 7775 | } |
| 7776 | return objPtr->bytes; |
| 7777 | } |
| 7778 | |
| 7779 | static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) |
| 7780 | { |
| 7781 | objPtr->bytes = Jim_StrDup(str); |
| 7782 | objPtr->length = strlen(str); |
| 7783 | } |
| 7784 | |
| 7785 | static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 7786 | static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 7787 | |
| 7788 | static const Jim_ObjType dictSubstObjType = { |
| @@ -7703,11 +7820,10 @@ | |
| 7820 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 7821 | { |
| 7822 | JIM_NOTUSED(interp); |
| 7823 | |
| 7824 | dupPtr->internalRep.strValue.maxLength = srcPtr->length; |
| 7825 | dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; |
| 7826 | } |
| 7827 | |
| 7828 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7829 | { |
| @@ -7752,18 +7868,17 @@ | |
| 7868 | if (len == -1) |
| 7869 | len = strlen(s); |
| 7870 | |
| 7871 | if (len == 0) { |
| 7872 | objPtr->bytes = JimEmptyStringRep; |
| 7873 | } |
| 7874 | else { |
| 7875 | objPtr->bytes = Jim_Alloc(len + 1); |
| 7876 | memcpy(objPtr->bytes, s, len); |
| 7877 | objPtr->bytes[len] = '\0'; |
| 7878 | } |
| 7879 | objPtr->length = len; |
| 7880 | |
| 7881 | |
| 7882 | objPtr->typePtr = NULL; |
| 7883 | return objPtr; |
| 7884 | } |
| @@ -7791,11 +7906,11 @@ | |
| 7906 | Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) |
| 7907 | { |
| 7908 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 7909 | |
| 7910 | objPtr->bytes = s; |
| 7911 | objPtr->length = (len == -1) ? strlen(s) : len; |
| 7912 | objPtr->typePtr = NULL; |
| 7913 | return objPtr; |
| 7914 | } |
| 7915 | |
| 7916 | static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) |
| @@ -7820,17 +7935,17 @@ | |
| 7935 | } |
| 7936 | objPtr->internalRep.strValue.maxLength = needlen; |
| 7937 | } |
| 7938 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 7939 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 7940 | |
| 7941 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 7942 | |
| 7943 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 7944 | } |
| 7945 | objPtr->length += len; |
| 7946 | } |
| 7947 | |
| 7948 | void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) |
| 7949 | { |
| 7950 | JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); |
| 7951 | SetStringFromAny(interp, objPtr); |
| @@ -7838,13 +7953,11 @@ | |
| 7953 | } |
| 7954 | |
| 7955 | void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) |
| 7956 | { |
| 7957 | int len; |
| 7958 | const char *str = Jim_GetString(appendObjPtr, &len); |
| 7959 | Jim_AppendString(interp, objPtr, str, len); |
| 7960 | } |
| 7961 | |
| 7962 | void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) |
| 7963 | { |
| @@ -7851,11 +7964,11 @@ | |
| 7964 | va_list ap; |
| 7965 | |
| 7966 | SetStringFromAny(interp, objPtr); |
| 7967 | va_start(ap, objPtr); |
| 7968 | while (1) { |
| 7969 | const char *s = va_arg(ap, const char *); |
| 7970 | |
| 7971 | if (s == NULL) |
| 7972 | break; |
| 7973 | Jim_AppendString(interp, objPtr, s, -1); |
| 7974 | } |
| @@ -7862,20 +7975,20 @@ | |
| 7975 | va_end(ap); |
| 7976 | } |
| 7977 | |
| 7978 | int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) |
| 7979 | { |
| 7980 | if (aObjPtr == bObjPtr) { |
| 7981 | return 1; |
| 7982 | } |
| 7983 | else { |
| 7984 | int Alen, Blen; |
| 7985 | const char *sA = Jim_GetString(aObjPtr, &Alen); |
| 7986 | const char *sB = Jim_GetString(bObjPtr, &Blen); |
| 7987 | |
| 7988 | return Alen == Blen && memcmp(sA, sB, Alen) == 0; |
| 7989 | } |
| 7990 | } |
| 7991 | |
| 7992 | int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) |
| 7993 | { |
| 7994 | return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); |
| @@ -8036,11 +8149,11 @@ | |
| 8149 | static void JimStrCopyUpperLower(char *dest, const char *str, int uc) |
| 8150 | { |
| 8151 | while (*str) { |
| 8152 | int c; |
| 8153 | str += utf8_tounicode(str, &c); |
| 8154 | dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c)); |
| 8155 | } |
| 8156 | *dest = 0; |
| 8157 | } |
| 8158 | |
| 8159 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) |
| @@ -8096,11 +8209,11 @@ | |
| 8209 | len *= 2; |
| 8210 | #endif |
| 8211 | buf = p = Jim_Alloc(len + 1); |
| 8212 | |
| 8213 | str += utf8_tounicode(str, &c); |
| 8214 | p += utf8_getchars(p, utf8_title(c)); |
| 8215 | |
| 8216 | JimStrCopyUpperLower(p, str, 0); |
| 8217 | |
| 8218 | return Jim_NewStringObjNoAlloc(interp, buf, -1); |
| 8219 | } |
| @@ -8203,10 +8316,11 @@ | |
| 8316 | if (nontrim == NULL) { |
| 8317 | |
| 8318 | return Jim_NewEmptyStringObj(interp); |
| 8319 | } |
| 8320 | if (nontrim == strObjPtr->bytes + len) { |
| 8321 | |
| 8322 | return strObjPtr; |
| 8323 | } |
| 8324 | |
| 8325 | if (Jim_IsShared(strObjPtr)) { |
| 8326 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| @@ -8226,14 +8340,14 @@ | |
| 8340 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8341 | |
| 8342 | |
| 8343 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8344 | |
| 8345 | |
| 8346 | if (objPtr != strObjPtr && objPtr->refCount == 0) { |
| 8347 | |
| 8348 | Jim_FreeNewObj(interp, objPtr); |
| 8349 | } |
| 8350 | |
| 8351 | return strObjPtr; |
| 8352 | } |
| 8353 | |
| @@ -8270,26 +8384,26 @@ | |
| 8384 | return JIM_ERR; |
| 8385 | } |
| 8386 | |
| 8387 | str = Jim_GetString(strObjPtr, &len); |
| 8388 | if (len == 0) { |
| 8389 | Jim_SetResultBool(interp, !strict); |
| 8390 | return JIM_OK; |
| 8391 | } |
| 8392 | |
| 8393 | switch (strclass) { |
| 8394 | case STR_IS_INTEGER: |
| 8395 | { |
| 8396 | jim_wide w; |
| 8397 | Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); |
| 8398 | return JIM_OK; |
| 8399 | } |
| 8400 | |
| 8401 | case STR_IS_DOUBLE: |
| 8402 | { |
| 8403 | double d; |
| 8404 | Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8405 | return JIM_OK; |
| 8406 | } |
| 8407 | |
| 8408 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8409 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| @@ -8307,15 +8421,15 @@ | |
| 8421 | return JIM_ERR; |
| 8422 | } |
| 8423 | |
| 8424 | for (i = 0; i < len; i++) { |
| 8425 | if (!isclassfunc(str[i])) { |
| 8426 | Jim_SetResultBool(interp, 0); |
| 8427 | return JIM_OK; |
| 8428 | } |
| 8429 | } |
| 8430 | Jim_SetResultBool(interp, 1); |
| 8431 | return JIM_OK; |
| 8432 | } |
| 8433 | |
| 8434 | |
| 8435 | |
| @@ -8327,17 +8441,19 @@ | |
| 8441 | JIM_TYPE_REFERENCES, |
| 8442 | }; |
| 8443 | |
| 8444 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) |
| 8445 | { |
| 8446 | if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { |
| 8447 | return 1; |
| 8448 | } |
| 8449 | else { |
| 8450 | const char *objStr = Jim_String(objPtr); |
| 8451 | |
| 8452 | if (strcmp(str, objStr) != 0) |
| 8453 | return 0; |
| 8454 | |
| 8455 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8456 | Jim_FreeIntRep(interp, objPtr); |
| 8457 | objPtr->typePtr = &comparedStringObjType; |
| 8458 | } |
| 8459 | objPtr->internalRep.ptr = (char *)str; |
| @@ -8379,24 +8495,23 @@ | |
| 8495 | |
| 8496 | static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, |
| 8497 | Jim_Obj *fileNameObj, int lineNumber) |
| 8498 | { |
| 8499 | JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); |
| 8500 | JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); |
| 8501 | Jim_IncrRefCount(fileNameObj); |
| 8502 | objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; |
| 8503 | objPtr->internalRep.sourceValue.lineNumber = lineNumber; |
| 8504 | objPtr->typePtr = &sourceObjType; |
| 8505 | } |
| 8506 | |
| 8507 | static const Jim_ObjType scriptLineObjType = { |
| 8508 | "scriptline", |
| 8509 | NULL, |
| 8510 | NULL, |
| 8511 | NULL, |
| 8512 | JIM_NONE, |
| 8513 | }; |
| 8514 | |
| 8515 | static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) |
| 8516 | { |
| 8517 | Jim_Obj *objPtr; |
| @@ -8413,15 +8528,14 @@ | |
| 8528 | objPtr->internalRep.scriptLineValue.line = line; |
| 8529 | |
| 8530 | return objPtr; |
| 8531 | } |
| 8532 | |
| 8533 | static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 8534 | static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8535 | static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8536 | static int JimParseCheckMissing(Jim_Interp *interp, int ch); |
| 8537 | |
| 8538 | static const Jim_ObjType scriptObjType = { |
| 8539 | "script", |
| 8540 | FreeScriptInternalRep, |
| 8541 | DupScriptInternalRep, |
| @@ -8429,34 +8543,33 @@ | |
| 8543 | JIM_TYPE_REFERENCES, |
| 8544 | }; |
| 8545 | |
| 8546 | typedef struct ScriptToken |
| 8547 | { |
| 8548 | Jim_Obj *objPtr; |
| 8549 | int type; |
| 8550 | } ScriptToken; |
| 8551 | |
| 8552 | typedef struct ScriptObj |
| 8553 | { |
| 8554 | ScriptToken *token; |
| 8555 | Jim_Obj *fileNameObj; |
| 8556 | int len; |
| 8557 | int substFlags; |
| 8558 | int inUse; /* Used to share a ScriptObj. Currently |
| 8559 | only used by Jim_EvalObj() as protection against |
| 8560 | shimmering of the currently evaluated object. */ |
| 8561 | int firstline; |
| 8562 | int linenr; |
| 8563 | } ScriptObj; |
| 8564 | |
| 8565 | void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8566 | { |
| 8567 | int i; |
| 8568 | struct ScriptObj *script = (void *)objPtr->internalRep.ptr; |
| 8569 | |
| 8570 | if (--script->inUse != 0) |
| 8571 | return; |
| 8572 | for (i = 0; i < script->len; i++) { |
| 8573 | Jim_DecrRefCount(interp, script->token[i].objPtr); |
| 8574 | } |
| 8575 | Jim_Free(script->token); |
| @@ -8467,11 +8580,10 @@ | |
| 8580 | void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 8581 | { |
| 8582 | JIM_NOTUSED(interp); |
| 8583 | JIM_NOTUSED(srcPtr); |
| 8584 | |
| 8585 | dupPtr->typePtr = NULL; |
| 8586 | } |
| 8587 | |
| 8588 | typedef struct |
| 8589 | { |
| @@ -8666,11 +8778,11 @@ | |
| 8778 | token--; |
| 8779 | } |
| 8780 | |
| 8781 | script->len = token - script->token; |
| 8782 | |
| 8783 | JimPanic((script->len >= count, "allocated script array is too short")); |
| 8784 | |
| 8785 | #ifdef DEBUG_SHOW_SCRIPT |
| 8786 | printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); |
| 8787 | for (i = 0; i < script->len; i++) { |
| 8788 | const ScriptToken *t = &script->token[i]; |
| @@ -8677,10 +8789,35 @@ | |
| 8789 | printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); |
| 8790 | } |
| 8791 | #endif |
| 8792 | |
| 8793 | } |
| 8794 | |
| 8795 | static int JimParseCheckMissing(Jim_Interp *interp, int ch) |
| 8796 | { |
| 8797 | const char *msg; |
| 8798 | |
| 8799 | switch (ch) { |
| 8800 | case '\\': |
| 8801 | case ' ': |
| 8802 | return JIM_OK; |
| 8803 | |
| 8804 | case '[': |
| 8805 | msg = "unmatched \"[\""; |
| 8806 | break; |
| 8807 | case '{': |
| 8808 | msg = "missing close-brace"; |
| 8809 | break; |
| 8810 | case '"': |
| 8811 | default: |
| 8812 | msg = "missing quote"; |
| 8813 | break; |
| 8814 | } |
| 8815 | |
| 8816 | Jim_SetResultString(interp, msg, -1); |
| 8817 | return JIM_ERR; |
| 8818 | } |
| 8819 | |
| 8820 | static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8821 | ParseTokenList *tokenlist) |
| 8822 | { |
| 8823 | int i; |
| @@ -8699,18 +8836,19 @@ | |
| 8836 | } |
| 8837 | |
| 8838 | script->len = i; |
| 8839 | } |
| 8840 | |
| 8841 | static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 8842 | { |
| 8843 | int scriptTextLen; |
| 8844 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 8845 | struct JimParserCtx parser; |
| 8846 | struct ScriptObj *script; |
| 8847 | ParseTokenList tokenlist; |
| 8848 | int line = 1; |
| 8849 | int retcode = JIM_OK; |
| 8850 | |
| 8851 | |
| 8852 | if (objPtr->typePtr == &sourceObjType) { |
| 8853 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 8854 | } |
| @@ -8722,16 +8860,12 @@ | |
| 8860 | while (!parser.eof) { |
| 8861 | JimParseScript(&parser); |
| 8862 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 8863 | parser.tline); |
| 8864 | } |
| 8865 | |
| 8866 | retcode = JimParseCheckMissing(interp, parser.missing.ch); |
| 8867 | |
| 8868 | |
| 8869 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 8870 | |
| 8871 | |
| @@ -8742,10 +8876,11 @@ | |
| 8876 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 8877 | } |
| 8878 | else { |
| 8879 | script->fileNameObj = interp->emptyObj; |
| 8880 | } |
| 8881 | script->linenr = parser.missing.line; |
| 8882 | Jim_IncrRefCount(script->fileNameObj); |
| 8883 | |
| 8884 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 8885 | |
| 8886 | |
| @@ -8754,11 +8889,11 @@ | |
| 8889 | |
| 8890 | Jim_FreeIntRep(interp, objPtr); |
| 8891 | Jim_SetIntRepPtr(objPtr, script); |
| 8892 | objPtr->typePtr = &scriptObjType; |
| 8893 | |
| 8894 | return retcode; |
| 8895 | } |
| 8896 | |
| 8897 | ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8898 | { |
| 8899 | if (objPtr == interp->emptyObj) { |
| @@ -8765,11 +8900,13 @@ | |
| 8900 | |
| 8901 | objPtr = interp->nullScriptObj; |
| 8902 | } |
| 8903 | |
| 8904 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 8905 | if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) { |
| 8906 | return NULL; |
| 8907 | } |
| 8908 | } |
| 8909 | return (ScriptObj *) Jim_GetIntRepPtr(objPtr); |
| 8910 | } |
| 8911 | |
| 8912 | static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) |
| @@ -8850,10 +8987,26 @@ | |
| 8987 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 8988 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 8989 | } |
| 8990 | return nsObj; |
| 8991 | } |
| 8992 | |
| 8993 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 8994 | { |
| 8995 | Jim_Obj *resultObj; |
| 8996 | |
| 8997 | const char *name = Jim_String(nameObjPtr); |
| 8998 | if (name[0] == ':' && name[1] == ':') { |
| 8999 | return nameObjPtr; |
| 9000 | } |
| 9001 | Jim_IncrRefCount(nameObjPtr); |
| 9002 | resultObj = Jim_NewStringObj(interp, "::", -1); |
| 9003 | Jim_AppendObj(interp, resultObj, nameObjPtr); |
| 9004 | Jim_DecrRefCount(interp, nameObjPtr); |
| 9005 | |
| 9006 | return resultObj; |
| 9007 | } |
| 9008 | |
| 9009 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 9010 | { |
| 9011 | Jim_Obj *objPtr = interp->emptyObj; |
| 9012 | |
| @@ -8877,10 +9030,15 @@ | |
| 9030 | |
| 9031 | #else |
| 9032 | |
| 9033 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 9034 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9035 | |
| 9036 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9037 | { |
| 9038 | return nameObjPtr; |
| 9039 | } |
| 9040 | #endif |
| 9041 | |
| 9042 | static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) |
| 9043 | { |
| 9044 | Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); |
| @@ -8889,12 +9047,12 @@ | |
| 9047 | Jim_InterpIncrProcEpoch(interp); |
| 9048 | } |
| 9049 | |
| 9050 | if (he && interp->local) { |
| 9051 | |
| 9052 | cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9053 | Jim_SetHashVal(&interp->commands, he, cmd); |
| 9054 | } |
| 9055 | else { |
| 9056 | if (he) { |
| 9057 | |
| 9058 | Jim_DeleteHashEntry(&interp->commands, name); |
| @@ -8933,19 +9091,19 @@ | |
| 9091 | } |
| 9092 | |
| 9093 | cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); |
| 9094 | Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); |
| 9095 | for (i = 0; i < len; i++) { |
| 9096 | Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 9097 | Jim_Var *varPtr; |
| 9098 | int subLen; |
| 9099 | |
| 9100 | objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 9101 | |
| 9102 | subLen = Jim_ListLength(interp, objPtr); |
| 9103 | if (subLen == 1 || subLen == 2) { |
| 9104 | nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 9105 | if (subLen == 1) { |
| 9106 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 9107 | if (initObjPtr == NULL) { |
| 9108 | Jim_SetResultFormatted(interp, |
| 9109 | "variable for initialization of static \"%#s\" not found in the local context", |
| @@ -8952,11 +9110,11 @@ | |
| 9110 | nameObjPtr); |
| 9111 | return JIM_ERR; |
| 9112 | } |
| 9113 | } |
| 9114 | else { |
| 9115 | initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); |
| 9116 | } |
| 9117 | if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { |
| 9118 | return JIM_ERR; |
| 9119 | } |
| 9120 | |
| @@ -9038,11 +9196,11 @@ | |
| 9196 | Jim_Obj *nameObjPtr; |
| 9197 | Jim_Obj *defaultObjPtr; |
| 9198 | int len; |
| 9199 | |
| 9200 | |
| 9201 | argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); |
| 9202 | len = Jim_ListLength(interp, argPtr); |
| 9203 | if (len == 0) { |
| 9204 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9205 | err: |
| 9206 | JimDecrCmdRefCount(interp, cmdPtr); |
| @@ -9053,12 +9211,12 @@ | |
| 9211 | goto err; |
| 9212 | } |
| 9213 | |
| 9214 | if (len == 2) { |
| 9215 | |
| 9216 | nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); |
| 9217 | defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); |
| 9218 | } |
| 9219 | else { |
| 9220 | |
| 9221 | nameObjPtr = argPtr; |
| 9222 | defaultObjPtr = NULL; |
| @@ -9132,11 +9290,11 @@ | |
| 9290 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9291 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9292 | } |
| 9293 | else { |
| 9294 | |
| 9295 | cmdPtr = Jim_GetHashEntryVal(he); |
| 9296 | JimIncrCmdRefCount(cmdPtr); |
| 9297 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9298 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9299 | |
| 9300 | |
| @@ -9217,11 +9375,11 @@ | |
| 9375 | return NULL; |
| 9376 | } |
| 9377 | #ifdef jim_ext_namespace |
| 9378 | found: |
| 9379 | #endif |
| 9380 | cmd = Jim_GetHashEntryVal(he); |
| 9381 | |
| 9382 | |
| 9383 | Jim_FreeIntRep(interp, objPtr); |
| 9384 | objPtr->typePtr = &commandObjType; |
| 9385 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| @@ -9323,11 +9481,11 @@ | |
| 9481 | |
| 9482 | |
| 9483 | Jim_FreeIntRep(interp, objPtr); |
| 9484 | objPtr->typePtr = &variableObjType; |
| 9485 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9486 | objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 9487 | objPtr->internalRep.varValue.global = global; |
| 9488 | return JIM_OK; |
| 9489 | } |
| 9490 | |
| 9491 | |
| @@ -9641,11 +9799,11 @@ | |
| 9799 | } |
| 9800 | |
| 9801 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 9802 | if (retval == JIM_OK) { |
| 9803 | |
| 9804 | framePtr->id = interp->callFrameEpoch++; |
| 9805 | } |
| 9806 | } |
| 9807 | } |
| 9808 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| 9809 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); |
| @@ -9725,28 +9883,17 @@ | |
| 9883 | return NULL; |
| 9884 | } |
| 9885 | |
| 9886 | ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9887 | if (ret != JIM_OK) { |
| 9888 | Jim_SetResultFormatted(interp, |
| 9889 | "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, |
| 9890 | ret < 0 ? "variable isn't" : "no such element in"); |
| 9891 | } |
| 9892 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 9893 | |
| 9894 | Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); |
| 9895 | } |
| 9896 | |
| 9897 | return resObjPtr; |
| 9898 | } |
| 9899 | |
| @@ -9843,68 +9990,67 @@ | |
| 9990 | Jim_CallFrame *cf; |
| 9991 | |
| 9992 | if (interp->freeFramesList) { |
| 9993 | cf = interp->freeFramesList; |
| 9994 | interp->freeFramesList = cf->next; |
| 9995 | |
| 9996 | cf->argv = NULL; |
| 9997 | cf->argc = 0; |
| 9998 | cf->procArgsObjPtr = NULL; |
| 9999 | cf->procBodyObjPtr = NULL; |
| 10000 | cf->next = NULL; |
| 10001 | cf->staticVars = NULL; |
| 10002 | cf->localCommands = NULL; |
| 10003 | cf->tailcall = 0; |
| 10004 | cf->tailcallObj = NULL; |
| 10005 | cf->tailcallCmd = NULL; |
| 10006 | } |
| 10007 | else { |
| 10008 | cf = Jim_Alloc(sizeof(*cf)); |
| 10009 | memset(cf, 0, sizeof(*cf)); |
| 10010 | |
| 10011 | Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); |
| 10012 | } |
| 10013 | |
| 10014 | cf->id = interp->callFrameEpoch++; |
| 10015 | cf->parent = parent; |
| 10016 | cf->level = parent ? parent->level + 1 : 0; |
| 10017 | cf->nsObj = nsObj; |
| 10018 | Jim_IncrRefCount(nsObj); |
| 10019 | |
| 10020 | return cf; |
| 10021 | } |
| 10022 | |
| 10023 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 10024 | { |
| 10025 | |
| 10026 | if (localCommands) { |
| 10027 | Jim_Obj *cmdNameObj; |
| 10028 | |
| 10029 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 10030 | Jim_HashEntry *he; |
| 10031 | Jim_Obj *fqObjName; |
| 10032 | Jim_HashTable *ht = &interp->commands; |
| 10033 | |
| 10034 | const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); |
| 10035 | |
| 10036 | he = Jim_FindHashEntry(ht, fqname); |
| 10037 | |
| 10038 | if (he) { |
| 10039 | Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 10040 | if (cmd->prevCmd) { |
| 10041 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 10042 | cmd->prevCmd = NULL; |
| 10043 | |
| 10044 | |
| 10045 | JimDecrCmdRefCount(interp, cmd); |
| 10046 | |
| 10047 | |
| 10048 | Jim_SetHashVal(ht, he, prevCmd); |
| 10049 | } |
| 10050 | else { |
| 10051 | Jim_DeleteHashEntry(ht, fqname); |
| 10052 | Jim_InterpIncrProcEpoch(interp); |
| 10053 | } |
| 10054 | } |
| 10055 | Jim_DecrRefCount(interp, cmdNameObj); |
| 10056 | JimFreeQualifiedName(interp, fqObjName); |
| @@ -9914,47 +10060,45 @@ | |
| 10060 | } |
| 10061 | return JIM_OK; |
| 10062 | } |
| 10063 | |
| 10064 | |
| 10065 | #define JIM_FCF_FULL 0 |
| 10066 | #define JIM_FCF_REUSE 1 |
| 10067 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) |
| 10068 | { |
| 10069 | JimDeleteLocalProcs(interp, cf->localCommands); |
| 10070 | |
| 10071 | if (cf->procArgsObjPtr) |
| 10072 | Jim_DecrRefCount(interp, cf->procArgsObjPtr); |
| 10073 | if (cf->procBodyObjPtr) |
| 10074 | Jim_DecrRefCount(interp, cf->procBodyObjPtr); |
| 10075 | Jim_DecrRefCount(interp, cf->nsObj); |
| 10076 | if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) |
| 10077 | Jim_FreeHashTable(&cf->vars); |
| 10078 | else { |
| 10079 | int i; |
| 10080 | Jim_HashEntry **table = cf->vars.table, *he; |
| 10081 | |
| 10082 | for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { |
| 10083 | he = table[i]; |
| 10084 | while (he != NULL) { |
| 10085 | Jim_HashEntry *nextEntry = he->next; |
| 10086 | Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 10087 | |
| 10088 | Jim_DecrRefCount(interp, varPtr->objPtr); |
| 10089 | Jim_Free(Jim_GetHashEntryKey(he)); |
| 10090 | Jim_Free(varPtr); |
| 10091 | Jim_Free(he); |
| 10092 | table[i] = NULL; |
| 10093 | he = nextEntry; |
| 10094 | } |
| 10095 | } |
| 10096 | cf->vars.used = 0; |
| 10097 | } |
| 10098 | cf->next = interp->freeFramesList; |
| 10099 | interp->freeFramesList = cf; |
| 10100 | } |
| 10101 | |
| 10102 | |
| 10103 | #ifdef JIM_REFERENCES |
| 10104 | |
| @@ -10031,21 +10175,16 @@ | |
| 10175 | NULL, |
| 10176 | UpdateStringOfReference, |
| 10177 | JIM_TYPE_REFERENCES, |
| 10178 | }; |
| 10179 | |
| 10180 | static void UpdateStringOfReference(struct Jim_Obj *objPtr) |
| 10181 | { |
| 10182 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 10183 | |
| 10184 | JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); |
| 10185 | JimSetStringBytes(objPtr, buf); |
| 10186 | } |
| 10187 | |
| 10188 | static int isrefchar(int c) |
| 10189 | { |
| 10190 | return (c == '_' || isalnum(c)); |
| @@ -10096,11 +10235,11 @@ | |
| 10235 | he = Jim_FindHashEntry(&interp->references, &value); |
| 10236 | if (he == NULL) { |
| 10237 | Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); |
| 10238 | return JIM_ERR; |
| 10239 | } |
| 10240 | refPtr = Jim_GetHashEntryVal(he); |
| 10241 | |
| 10242 | Jim_FreeIntRep(interp, objPtr); |
| 10243 | objPtr->typePtr = &referenceObjType; |
| 10244 | objPtr->internalRep.refValue.id = value; |
| 10245 | objPtr->internalRep.refValue.refPtr = refPtr; |
| @@ -10279,13 +10418,20 @@ | |
| 10418 | return i; |
| 10419 | } |
| 10420 | |
| 10421 | void Jim_FreeInterp(Jim_Interp *i) |
| 10422 | { |
| 10423 | Jim_CallFrame *cf, *cfx; |
| 10424 | |
| 10425 | Jim_Obj *objPtr, *nextObjPtr; |
| 10426 | |
| 10427 | |
| 10428 | for (cf = i->framePtr; cf; cf = cfx) { |
| 10429 | cfx = cf->parent; |
| 10430 | JimFreeCallFrame(i, cf, JIM_FCF_FULL); |
| 10431 | } |
| 10432 | |
| 10433 | Jim_DecrRefCount(i, i->emptyObj); |
| 10434 | Jim_DecrRefCount(i, i->trueObj); |
| 10435 | Jim_DecrRefCount(i, i->falseObj); |
| 10436 | Jim_DecrRefCount(i, i->result); |
| 10437 | Jim_DecrRefCount(i, i->stackTrace); |
| @@ -10300,61 +10446,54 @@ | |
| 10446 | #endif |
| 10447 | Jim_FreeHashTable(&i->packages); |
| 10448 | Jim_Free(i->prngState); |
| 10449 | Jim_FreeHashTable(&i->assocData); |
| 10450 | |
| 10451 | #ifdef JIM_MAINTAINER |
| 10452 | if (i->liveList != NULL) { |
| 10453 | objPtr = i->liveList; |
| 10454 | |
| 10455 | printf("\n-------------------------------------\n"); |
| 10456 | printf("Objects still in the free list:\n"); |
| 10457 | while (objPtr) { |
| 10458 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10459 | |
| 10460 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10461 | printf("%p (%d) %-10s: '%.20s...'\n", |
| 10462 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10463 | } |
| 10464 | else { |
| 10465 | printf("%p (%d) %-10s: '%s'\n", |
| 10466 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); |
| 10467 | } |
| 10468 | if (objPtr->typePtr == &sourceObjType) { |
| 10469 | printf("FILE %s LINE %d\n", |
| 10470 | Jim_String(objPtr->internalRep.sourceValue.fileNameObj), |
| 10471 | objPtr->internalRep.sourceValue.lineNumber); |
| 10472 | } |
| 10473 | objPtr = objPtr->nextObjPtr; |
| 10474 | } |
| 10475 | printf("-------------------------------------\n\n"); |
| 10476 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10477 | } |
| 10478 | #endif |
| 10479 | |
| 10480 | |
| 10481 | objPtr = i->freeList; |
| 10482 | while (objPtr) { |
| 10483 | nextObjPtr = objPtr->nextObjPtr; |
| 10484 | Jim_Free(objPtr); |
| 10485 | objPtr = nextObjPtr; |
| 10486 | } |
| 10487 | |
| 10488 | |
| 10489 | for (cf = i->freeFramesList; cf; cf = cfx) { |
| 10490 | cfx = cf->next; |
| 10491 | if (cf->vars.table) |
| 10492 | Jim_FreeHashTable(&cf->vars); |
| 10493 | Jim_Free(cf); |
| 10494 | } |
| 10495 | |
| 10496 | |
| 10497 | Jim_Free(i); |
| 10498 | } |
| 10499 | |
| @@ -10455,11 +10594,10 @@ | |
| 10594 | interp->addStackTrace = 1; |
| 10595 | } |
| 10596 | } |
| 10597 | } |
| 10598 | |
| 10599 | static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, |
| 10600 | Jim_Obj *fileNameObj, int linenr) |
| 10601 | { |
| 10602 | if (strcmp(procname, "unknown") == 0) { |
| 10603 | procname = ""; |
| @@ -10513,12 +10651,11 @@ | |
| 10651 | void *Jim_GetAssocData(Jim_Interp *interp, const char *key) |
| 10652 | { |
| 10653 | Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); |
| 10654 | |
| 10655 | if (entryPtr != NULL) { |
| 10656 | AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr); |
| 10657 | return assocEntryPtr->data; |
| 10658 | } |
| 10659 | return NULL; |
| 10660 | } |
| 10661 | |
| @@ -10552,20 +10689,44 @@ | |
| 10689 | }; |
| 10690 | |
| 10691 | |
| 10692 | static void UpdateStringOfInt(struct Jim_Obj *objPtr) |
| 10693 | { |
| 10694 | char buf[JIM_INTEGER_SPACE + 1]; |
| 10695 | jim_wide wideValue = JimWideValue(objPtr); |
| 10696 | int pos = 0; |
| 10697 | |
| 10698 | if (wideValue == 0) { |
| 10699 | buf[pos++] = '0'; |
| 10700 | } |
| 10701 | else { |
| 10702 | char tmp[JIM_INTEGER_SPACE]; |
| 10703 | int num = 0; |
| 10704 | int i; |
| 10705 | |
| 10706 | if (wideValue < 0) { |
| 10707 | buf[pos++] = '-'; |
| 10708 | i = wideValue % 10; |
| 10709 | tmp[num++] = (i > 0) ? (10 - i) : -i; |
| 10710 | wideValue /= -10; |
| 10711 | } |
| 10712 | |
| 10713 | while (wideValue) { |
| 10714 | tmp[num++] = wideValue % 10; |
| 10715 | wideValue /= 10; |
| 10716 | } |
| 10717 | |
| 10718 | for (i = 0; i < num; i++) { |
| 10719 | buf[pos++] = '0' + tmp[num - i - 1]; |
| 10720 | } |
| 10721 | } |
| 10722 | buf[pos] = 0; |
| 10723 | |
| 10724 | JimSetStringBytes(objPtr, buf); |
| 10725 | } |
| 10726 | |
| 10727 | static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 10728 | { |
| 10729 | jim_wide wideValue; |
| 10730 | const char *str; |
| 10731 | |
| 10732 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| @@ -10653,22 +10814,65 @@ | |
| 10814 | NULL, |
| 10815 | UpdateStringOfDouble, |
| 10816 | JIM_TYPE_NONE, |
| 10817 | }; |
| 10818 | |
| 10819 | #ifndef HAVE_ISNAN |
| 10820 | #undef isnan |
| 10821 | #define isnan(X) ((X) != (X)) |
| 10822 | #endif |
| 10823 | #ifndef HAVE_ISINF |
| 10824 | #undef isinf |
| 10825 | #define isinf(X) (1.0 / (X) == 0.0) |
| 10826 | #endif |
| 10827 | |
| 10828 | static void UpdateStringOfDouble(struct Jim_Obj *objPtr) |
| 10829 | { |
| 10830 | double value = objPtr->internalRep.doubleValue; |
| 10831 | |
| 10832 | if (isnan(value)) { |
| 10833 | JimSetStringBytes(objPtr, "NaN"); |
| 10834 | return; |
| 10835 | } |
| 10836 | if (isinf(value)) { |
| 10837 | if (value < 0) { |
| 10838 | JimSetStringBytes(objPtr, "-Inf"); |
| 10839 | } |
| 10840 | else { |
| 10841 | JimSetStringBytes(objPtr, "Inf"); |
| 10842 | } |
| 10843 | return; |
| 10844 | } |
| 10845 | { |
| 10846 | char buf[JIM_DOUBLE_SPACE + 1]; |
| 10847 | int i; |
| 10848 | int len = sprintf(buf, "%.12g", value); |
| 10849 | |
| 10850 | |
| 10851 | for (i = 0; i < len; i++) { |
| 10852 | if (buf[i] == '.' || buf[i] == 'e') { |
| 10853 | #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 10854 | char *e = strchr(buf, 'e'); |
| 10855 | if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 10856 | |
| 10857 | e += 2; |
| 10858 | memmove(e, e + 1, len - (e - buf)); |
| 10859 | } |
| 10860 | #endif |
| 10861 | break; |
| 10862 | } |
| 10863 | } |
| 10864 | if (buf[i] == '\0') { |
| 10865 | buf[i++] = '.'; |
| 10866 | buf[i++] = '0'; |
| 10867 | buf[i] = '\0'; |
| 10868 | } |
| 10869 | JimSetStringBytes(objPtr, buf); |
| 10870 | } |
| 10871 | } |
| 10872 | |
| 10873 | static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10874 | { |
| 10875 | double doubleValue; |
| 10876 | jim_wide wideValue; |
| 10877 | const char *str; |
| 10878 | |
| @@ -10876,15 +11080,15 @@ | |
| 11080 | return JIM_ELESTR_SIMPLE; |
| 11081 | } |
| 11082 | return JIM_ELESTR_QUOTE; |
| 11083 | } |
| 11084 | |
| 11085 | static int BackslashQuoteString(const char *s, int len, char *q) |
| 11086 | { |
| 11087 | char *p = q; |
| 11088 | |
| 11089 | while (len--) { |
| 11090 | switch (*s) { |
| 11091 | case ' ': |
| 11092 | case '$': |
| 11093 | case '"': |
| 11094 | case '[': |
| @@ -10996,11 +11200,11 @@ | |
| 11200 | case JIM_ELESTR_QUOTE: |
| 11201 | if (i == 0 && strRep[0] == '#') { |
| 11202 | *p++ = '\\'; |
| 11203 | realLength++; |
| 11204 | } |
| 11205 | qlen = BackslashQuoteString(strRep, len, p); |
| 11206 | p += qlen; |
| 11207 | realLength += qlen; |
| 11208 | break; |
| 11209 | } |
| 11210 | |
| @@ -11032,11 +11236,11 @@ | |
| 11236 | |
| 11237 | if (objPtr->typePtr == &listObjType) { |
| 11238 | return JIM_OK; |
| 11239 | } |
| 11240 | |
| 11241 | if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { |
| 11242 | Jim_Obj **listObjPtrPtr; |
| 11243 | int len; |
| 11244 | int i; |
| 11245 | |
| 11246 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| @@ -11136,15 +11340,17 @@ | |
| 11340 | Jim_Interp *interp; |
| 11341 | enum { |
| 11342 | JIM_LSORT_ASCII, |
| 11343 | JIM_LSORT_NOCASE, |
| 11344 | JIM_LSORT_INTEGER, |
| 11345 | JIM_LSORT_REAL, |
| 11346 | JIM_LSORT_COMMAND |
| 11347 | } type; |
| 11348 | int order; |
| 11349 | int index; |
| 11350 | int indexed; |
| 11351 | int unique; |
| 11352 | int (*subfn)(Jim_Obj **, Jim_Obj **); |
| 11353 | }; |
| 11354 | |
| 11355 | static struct lsort_info *sort_info; |
| 11356 | |
| @@ -11179,10 +11385,27 @@ | |
| 11385 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11386 | } |
| 11387 | |
| 11388 | return JimSign(lhs - rhs) * sort_info->order; |
| 11389 | } |
| 11390 | |
| 11391 | static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11392 | { |
| 11393 | double lhs = 0, rhs = 0; |
| 11394 | |
| 11395 | if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK || |
| 11396 | Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { |
| 11397 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11398 | } |
| 11399 | if (lhs == rhs) { |
| 11400 | return 0; |
| 11401 | } |
| 11402 | if (lhs > rhs) { |
| 11403 | return sort_info->order; |
| 11404 | } |
| 11405 | return -sort_info->order; |
| 11406 | } |
| 11407 | |
| 11408 | static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11409 | { |
| 11410 | Jim_Obj *compare_script; |
| 11411 | int rc; |
| @@ -11201,10 +11424,34 @@ | |
| 11424 | } |
| 11425 | |
| 11426 | return JimSign(ret) * sort_info->order; |
| 11427 | } |
| 11428 | |
| 11429 | static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs)) |
| 11430 | { |
| 11431 | int src; |
| 11432 | int dst = 0; |
| 11433 | Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; |
| 11434 | |
| 11435 | for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { |
| 11436 | if (comp(&ele[dst], &ele[src]) == 0) { |
| 11437 | |
| 11438 | Jim_DecrRefCount(sort_info->interp, ele[dst]); |
| 11439 | } |
| 11440 | else { |
| 11441 | |
| 11442 | dst++; |
| 11443 | } |
| 11444 | ele[dst] = ele[src]; |
| 11445 | } |
| 11446 | |
| 11447 | ele[++dst] = ele[src]; |
| 11448 | |
| 11449 | |
| 11450 | listObjPtr->internalRep.listValue.len = dst; |
| 11451 | } |
| 11452 | |
| 11453 | |
| 11454 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| 11455 | { |
| 11456 | struct lsort_info *prev_info; |
| 11457 | |
| @@ -11212,11 +11459,11 @@ | |
| 11459 | int (*fn) (Jim_Obj **, Jim_Obj **); |
| 11460 | Jim_Obj **vector; |
| 11461 | int len; |
| 11462 | int rc; |
| 11463 | |
| 11464 | JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); |
| 11465 | SetListFromAny(interp, listObjPtr); |
| 11466 | |
| 11467 | |
| 11468 | prev_info = sort_info; |
| 11469 | sort_info = info; |
| @@ -11231,10 +11478,13 @@ | |
| 11478 | fn = ListSortStringNoCase; |
| 11479 | break; |
| 11480 | case JIM_LSORT_INTEGER: |
| 11481 | fn = ListSortInteger; |
| 11482 | break; |
| 11483 | case JIM_LSORT_REAL: |
| 11484 | fn = ListSortReal; |
| 11485 | break; |
| 11486 | case JIM_LSORT_COMMAND: |
| 11487 | fn = ListSortCommand; |
| 11488 | break; |
| 11489 | default: |
| 11490 | fn = NULL; |
| @@ -11247,12 +11497,17 @@ | |
| 11497 | fn = ListSortIndexHelper; |
| 11498 | } |
| 11499 | |
| 11500 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| 11501 | qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); |
| 11502 | |
| 11503 | if (info->unique && len > 1) { |
| 11504 | ListRemoveDuplicates(listObjPtr, fn); |
| 11505 | } |
| 11506 | |
| 11507 | Jim_InvalidateStringRep(listObjPtr); |
| 11508 | } |
| 11509 | sort_info = prev_info; |
| 11510 | |
| 11511 | return rc; |
| 11512 | } |
| 11513 | |
| @@ -11377,11 +11632,11 @@ | |
| 11632 | listPtr->internalRep.listValue.ele[idx] = newObjPtr; |
| 11633 | Jim_IncrRefCount(newObjPtr); |
| 11634 | return JIM_OK; |
| 11635 | } |
| 11636 | |
| 11637 | int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, |
| 11638 | Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) |
| 11639 | { |
| 11640 | Jim_Obj *varObjPtr, *objPtr, *listObjPtr; |
| 11641 | int shared, i, idx; |
| 11642 | |
| @@ -11425,14 +11680,11 @@ | |
| 11680 | int i; |
| 11681 | int listLen = Jim_ListLength(interp, listObjPtr); |
| 11682 | Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); |
| 11683 | |
| 11684 | for (i = 0; i < listLen; ) { |
| 11685 | Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i)); |
| 11686 | if (++i != listLen) { |
| 11687 | Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); |
| 11688 | } |
| 11689 | } |
| 11690 | return resObjPtr; |
| @@ -11458,43 +11710,42 @@ | |
| 11710 | int len = 0, objLen; |
| 11711 | char *bytes, *p; |
| 11712 | |
| 11713 | |
| 11714 | for (i = 0; i < objc; i++) { |
| 11715 | len += Jim_Length(objv[i]); |
| 11716 | } |
| 11717 | if (objc) |
| 11718 | len += objc - 1; |
| 11719 | |
| 11720 | p = bytes = Jim_Alloc(len + 1); |
| 11721 | for (i = 0; i < objc; i++) { |
| 11722 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11723 | |
| 11724 | |
| 11725 | while (objLen && isspace(UCHAR(*s))) { |
| 11726 | s++; |
| 11727 | objLen--; |
| 11728 | len--; |
| 11729 | } |
| 11730 | |
| 11731 | while (objLen && isspace(UCHAR(s[objLen - 1]))) { |
| 11732 | |
| 11733 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11734 | break; |
| 11735 | } |
| 11736 | objLen--; |
| 11737 | len--; |
| 11738 | } |
| 11739 | memcpy(p, s, objLen); |
| 11740 | p += objLen; |
| 11741 | if (i + 1 != objc) { |
| 11742 | if (objLen) |
| 11743 | *p++ = ' '; |
| 11744 | else { |
| 11745 | len--; |
| 11746 | } |
| 11747 | } |
| 11748 | } |
| 11749 | *p = '\0'; |
| 11750 | return Jim_NewStringObjNoAlloc(interp, bytes, len); |
| 11751 | } |
| @@ -11534,20 +11785,26 @@ | |
| 11785 | |
| 11786 | static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 11787 | { |
| 11788 | return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 11789 | } |
| 11790 | |
| 11791 | static void *JimObjectHTKeyValDup(void *privdata, const void *val) |
| 11792 | { |
| 11793 | Jim_IncrRefCount((Jim_Obj *)val); |
| 11794 | return (void *)val; |
| 11795 | } |
| 11796 | |
| 11797 | static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 11798 | { |
| 11799 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11800 | } |
| 11801 | |
| 11802 | static const Jim_HashTableType JimDictHashTableType = { |
| 11803 | JimObjectHTHashFunction, |
| 11804 | JimObjectHTKeyValDup, |
| 11805 | JimObjectHTKeyValDup, |
| 11806 | JimObjectHTKeyCompare, |
| 11807 | JimObjectHTKeyValDestructor, |
| 11808 | JimObjectHTKeyValDestructor |
| 11809 | }; |
| 11810 | |
| @@ -11580,16 +11837,11 @@ | |
| 11837 | if (ht->size != 0) |
| 11838 | Jim_ExpandHashTable(dupHt, ht->size); |
| 11839 | |
| 11840 | JimInitHashTableIterator(ht, &htiter); |
| 11841 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11842 | Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 11843 | } |
| 11844 | |
| 11845 | dupPtr->internalRep.ptr = dupHt; |
| 11846 | dupPtr->typePtr = &dictObjType; |
| 11847 | } |
| @@ -11607,12 +11859,12 @@ | |
| 11859 | |
| 11860 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 11861 | JimInitHashTableIterator(ht, &htiter); |
| 11862 | i = 0; |
| 11863 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11864 | objv[i++] = Jim_GetHashEntryKey(he); |
| 11865 | objv[i++] = Jim_GetHashEntryVal(he); |
| 11866 | } |
| 11867 | *len = i; |
| 11868 | return objv; |
| 11869 | } |
| 11870 | |
| @@ -11620,10 +11872,11 @@ | |
| 11872 | { |
| 11873 | |
| 11874 | int len; |
| 11875 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 11876 | |
| 11877 | |
| 11878 | JimMakeListStringRep(objPtr, objv, len); |
| 11879 | |
| 11880 | Jim_Free(objv); |
| 11881 | } |
| 11882 | |
| @@ -11633,11 +11886,13 @@ | |
| 11886 | |
| 11887 | if (objPtr->typePtr == &dictObjType) { |
| 11888 | return JIM_OK; |
| 11889 | } |
| 11890 | |
| 11891 | if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 11892 | Jim_String(objPtr); |
| 11893 | } |
| 11894 | |
| 11895 | |
| 11896 | listlen = Jim_ListLength(interp, objPtr); |
| 11897 | if (listlen % 2) { |
| 11898 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| @@ -11650,28 +11905,14 @@ | |
| 11905 | |
| 11906 | ht = Jim_Alloc(sizeof(*ht)); |
| 11907 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| 11908 | |
| 11909 | for (i = 0; i < listlen; i += 2) { |
| 11910 | Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); |
| 11911 | Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); |
| 11912 | |
| 11913 | Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); |
| 11914 | } |
| 11915 | |
| 11916 | Jim_FreeIntRep(interp, objPtr); |
| 11917 | objPtr->typePtr = &dictObjType; |
| 11918 | objPtr->internalRep.ptr = ht; |
| @@ -11688,31 +11929,23 @@ | |
| 11929 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 11930 | |
| 11931 | if (valueObjPtr == NULL) { |
| 11932 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 11933 | } |
| 11934 | Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 11935 | return JIM_OK; |
| 11936 | } |
| 11937 | |
| 11938 | int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 11939 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 11940 | { |
| 11941 | JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); |
| 11942 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 11943 | return JIM_ERR; |
| 11944 | } |
| 11945 | Jim_InvalidateStringRep(objPtr); |
| 11946 | return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); |
| 11947 | } |
| 11948 | |
| 11949 | Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) |
| 11950 | { |
| 11951 | Jim_Obj *objPtr; |
| @@ -11839,10 +12072,11 @@ | |
| 12072 | } |
| 12073 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12074 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 12075 | } |
| 12076 | } |
| 12077 | |
| 12078 | Jim_InvalidateStringRep(objPtr); |
| 12079 | Jim_InvalidateStringRep(varObjPtr); |
| 12080 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 12081 | goto err; |
| 12082 | } |
| @@ -11864,28 +12098,29 @@ | |
| 12098 | NULL, |
| 12099 | UpdateStringOfIndex, |
| 12100 | JIM_TYPE_NONE, |
| 12101 | }; |
| 12102 | |
| 12103 | static void UpdateStringOfIndex(struct Jim_Obj *objPtr) |
| 12104 | { |
| 12105 | if (objPtr->internalRep.intValue == -1) { |
| 12106 | JimSetStringBytes(objPtr, "end"); |
| 12107 | } |
| 12108 | else { |
| 12109 | char buf[JIM_INTEGER_SPACE + 1]; |
| 12110 | if (objPtr->internalRep.intValue >= 0) { |
| 12111 | sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12112 | } |
| 12113 | else { |
| 12114 | |
| 12115 | sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12116 | } |
| 12117 | JimSetStringBytes(objPtr, buf); |
| 12118 | } |
| 12119 | } |
| 12120 | |
| 12121 | static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12122 | { |
| 12123 | int idx, end = 0; |
| 12124 | const char *str; |
| 12125 | char *endptr; |
| 12126 | |
| @@ -11953,14 +12188,17 @@ | |
| 12188 | { |
| 12189 | |
| 12190 | if (objPtr->typePtr == &intObjType) { |
| 12191 | jim_wide val = JimWideValue(objPtr); |
| 12192 | |
| 12193 | if (val < 0) |
| 12194 | *indexPtr = -INT_MAX; |
| 12195 | else if (val > INT_MAX) |
| 12196 | *indexPtr = INT_MAX; |
| 12197 | else |
| 12198 | *indexPtr = (int)val; |
| 12199 | return JIM_OK; |
| 12200 | } |
| 12201 | if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) |
| 12202 | return JIM_ERR; |
| 12203 | *indexPtr = objPtr->internalRep.intValue; |
| 12204 | return JIM_OK; |
| @@ -11980,12 +12218,10 @@ | |
| 12218 | NULL |
| 12219 | }; |
| 12220 | |
| 12221 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) |
| 12222 | |
| 12223 | static const Jim_ObjType returnCodeObjType = { |
| 12224 | "return-code", |
| 12225 | NULL, |
| 12226 | NULL, |
| 12227 | NULL, |
| @@ -12000,11 +12236,11 @@ | |
| 12236 | else { |
| 12237 | return jimReturnCodes[code]; |
| 12238 | } |
| 12239 | } |
| 12240 | |
| 12241 | static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12242 | { |
| 12243 | int returnCode; |
| 12244 | jim_wide wideValue; |
| 12245 | |
| 12246 | |
| @@ -12152,24 +12388,21 @@ | |
| 12388 | return e->stack[--e->stacklen]; |
| 12389 | } |
| 12390 | |
| 12391 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12392 | { |
| 12393 | int intresult = 1; |
| 12394 | int rc = JIM_OK; |
| 12395 | Jim_Obj *A = ExprPop(e); |
| 12396 | double dA, dC = 0; |
| 12397 | jim_wide wA, wC = 0; |
| 12398 | |
| 12399 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12400 | switch (e->opcode) { |
| 12401 | case JIM_EXPROP_FUNC_INT: |
| 12402 | case JIM_EXPROP_FUNC_ROUND: |
| 12403 | case JIM_EXPROP_UNARYPLUS: |
| 12404 | wC = wA; |
| 12405 | break; |
| 12406 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12407 | dC = wA; |
| 12408 | intresult = 0; |
| @@ -12178,13 +12411,10 @@ | |
| 12411 | wC = wA >= 0 ? wA : -wA; |
| 12412 | break; |
| 12413 | case JIM_EXPROP_UNARYMINUS: |
| 12414 | wC = -wA; |
| 12415 | break; |
| 12416 | case JIM_EXPROP_NOT: |
| 12417 | wC = !wA; |
| 12418 | break; |
| 12419 | default: |
| 12420 | abort(); |
| @@ -12192,31 +12422,29 @@ | |
| 12422 | } |
| 12423 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12424 | switch (e->opcode) { |
| 12425 | case JIM_EXPROP_FUNC_INT: |
| 12426 | wC = dA; |
| 12427 | break; |
| 12428 | case JIM_EXPROP_FUNC_ROUND: |
| 12429 | wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); |
| 12430 | break; |
| 12431 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12432 | case JIM_EXPROP_UNARYPLUS: |
| 12433 | dC = dA; |
| 12434 | intresult = 0; |
| 12435 | break; |
| 12436 | case JIM_EXPROP_FUNC_ABS: |
| 12437 | dC = dA >= 0 ? dA : -dA; |
| 12438 | intresult = 0; |
| 12439 | break; |
| 12440 | case JIM_EXPROP_UNARYMINUS: |
| 12441 | dC = -dA; |
| 12442 | intresult = 0; |
| 12443 | break; |
| 12444 | case JIM_EXPROP_NOT: |
| 12445 | wC = !dA; |
| 12446 | break; |
| 12447 | default: |
| 12448 | abort(); |
| 12449 | } |
| 12450 | } |
| @@ -12427,11 +12655,11 @@ | |
| 12655 | |
| 12656 | |
| 12657 | |
| 12658 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) |
| 12659 | { |
| 12660 | int intresult = 1; |
| 12661 | int rc = JIM_OK; |
| 12662 | double dA, dB, dC = 0; |
| 12663 | jim_wide wA, wB, wC = 0; |
| 12664 | |
| 12665 | Jim_Obj *B = ExprPop(e); |
| @@ -12441,12 +12669,10 @@ | |
| 12669 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12670 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12671 | |
| 12672 | |
| 12673 | |
| 12674 | switch (e->opcode) { |
| 12675 | case JIM_EXPROP_POW: |
| 12676 | case JIM_EXPROP_FUNC_POW: |
| 12677 | wC = JimPowWide(wA, wB); |
| 12678 | break; |
| @@ -12496,10 +12722,11 @@ | |
| 12722 | default: |
| 12723 | abort(); |
| 12724 | } |
| 12725 | } |
| 12726 | else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12727 | intresult = 0; |
| 12728 | switch (e->opcode) { |
| 12729 | case JIM_EXPROP_POW: |
| 12730 | case JIM_EXPROP_FUNC_POW: |
| 12731 | #ifdef JIM_MATH_FUNCTIONS |
| 12732 | dC = pow(dA, dB); |
| @@ -12561,12 +12788,10 @@ | |
| 12788 | |
| 12789 | |
| 12790 | |
| 12791 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 12792 | |
| 12793 | switch (e->opcode) { |
| 12794 | case JIM_EXPROP_LT: |
| 12795 | wC = i < 0; |
| 12796 | break; |
| 12797 | case JIM_EXPROP_GT: |
| @@ -12610,15 +12835,11 @@ | |
| 12835 | int listlen; |
| 12836 | int i; |
| 12837 | |
| 12838 | listlen = Jim_ListLength(interp, listObjPtr); |
| 12839 | for (i = 0; i < listlen; i++) { |
| 12840 | if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { |
| 12841 | return 1; |
| 12842 | } |
| 12843 | } |
| 12844 | return 0; |
| 12845 | } |
| @@ -12630,23 +12851,16 @@ | |
| 12851 | |
| 12852 | jim_wide wC; |
| 12853 | |
| 12854 | switch (e->opcode) { |
| 12855 | case JIM_EXPROP_STREQ: |
| 12856 | case JIM_EXPROP_STRNE: |
| 12857 | wC = Jim_StringEqObj(A, B); |
| 12858 | if (e->opcode == JIM_EXPROP_STRNE) { |
| 12859 | wC = !wC; |
| 12860 | } |
| 12861 | break; |
| 12862 | case JIM_EXPROP_STRIN: |
| 12863 | wC = JimSearchList(interp, B, A); |
| 12864 | break; |
| 12865 | case JIM_EXPROP_STRNI: |
| 12866 | wC = !JimSearchList(interp, B, A); |
| @@ -12818,96 +13032,98 @@ | |
| 13032 | LAZY_OP, |
| 13033 | LAZY_LEFT, |
| 13034 | LAZY_RIGHT |
| 13035 | }; |
| 13036 | |
| 13037 | #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} |
| 13038 | #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} |
| 13039 | |
| 13040 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 13041 | OPRINIT("*", 110, 2, JimExprOpBin), |
| 13042 | OPRINIT("/", 110, 2, JimExprOpBin), |
| 13043 | OPRINIT("%", 110, 2, JimExprOpIntBin), |
| 13044 | |
| 13045 | OPRINIT("-", 100, 2, JimExprOpBin), |
| 13046 | OPRINIT("+", 100, 2, JimExprOpBin), |
| 13047 | |
| 13048 | OPRINIT("<<", 90, 2, JimExprOpIntBin), |
| 13049 | OPRINIT(">>", 90, 2, JimExprOpIntBin), |
| 13050 | |
| 13051 | OPRINIT("<<<", 90, 2, JimExprOpIntBin), |
| 13052 | OPRINIT(">>>", 90, 2, JimExprOpIntBin), |
| 13053 | |
| 13054 | OPRINIT("<", 80, 2, JimExprOpBin), |
| 13055 | OPRINIT(">", 80, 2, JimExprOpBin), |
| 13056 | OPRINIT("<=", 80, 2, JimExprOpBin), |
| 13057 | OPRINIT(">=", 80, 2, JimExprOpBin), |
| 13058 | |
| 13059 | OPRINIT("==", 70, 2, JimExprOpBin), |
| 13060 | OPRINIT("!=", 70, 2, JimExprOpBin), |
| 13061 | |
| 13062 | OPRINIT("&", 50, 2, JimExprOpIntBin), |
| 13063 | OPRINIT("^", 49, 2, JimExprOpIntBin), |
| 13064 | OPRINIT("|", 48, 2, JimExprOpIntBin), |
| 13065 | |
| 13066 | OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), |
| 13067 | OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), |
| 13068 | OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13069 | |
| 13070 | OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), |
| 13071 | OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), |
| 13072 | OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13073 | |
| 13074 | OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), |
| 13075 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), |
| 13076 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13077 | |
| 13078 | OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), |
| 13079 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), |
| 13080 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13081 | |
| 13082 | OPRINIT("**", 250, 2, JimExprOpBin), |
| 13083 | |
| 13084 | OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13085 | OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13086 | |
| 13087 | OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13088 | OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 13089 | |
| 13090 | OPRINIT("!", 150, 1, JimExprOpNumUnary), |
| 13091 | OPRINIT("~", 150, 1, JimExprOpIntUnary), |
| 13092 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13093 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13094 | |
| 13095 | |
| 13096 | |
| 13097 | OPRINIT("int", 200, 1, JimExprOpNumUnary), |
| 13098 | OPRINIT("abs", 200, 1, JimExprOpNumUnary), |
| 13099 | OPRINIT("double", 200, 1, JimExprOpNumUnary), |
| 13100 | OPRINIT("round", 200, 1, JimExprOpNumUnary), |
| 13101 | OPRINIT("rand", 200, 0, JimExprOpNone), |
| 13102 | OPRINIT("srand", 200, 1, JimExprOpIntUnary), |
| 13103 | |
| 13104 | #ifdef JIM_MATH_FUNCTIONS |
| 13105 | OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), |
| 13106 | OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), |
| 13107 | OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), |
| 13108 | OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), |
| 13109 | OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), |
| 13110 | OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), |
| 13111 | OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), |
| 13112 | OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), |
| 13113 | OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), |
| 13114 | OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), |
| 13115 | OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), |
| 13116 | OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), |
| 13117 | OPRINIT("log", 200, 1, JimExprOpDoubleUnary), |
| 13118 | OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), |
| 13119 | OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), |
| 13120 | OPRINIT("pow", 200, 2, JimExprOpBin), |
| 13121 | #endif |
| 13122 | }; |
| 13123 | #undef OPRINIT |
| 13124 | #undef OPRINIT_LAZY |
| 13125 | |
| 13126 | #define JIM_EXPR_OPERATORS_NUM \ |
| 13127 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 13128 | |
| 13129 | static int JimParseExpression(struct JimParserCtx *pc) |
| @@ -12919,13 +13135,16 @@ | |
| 13135 | } |
| 13136 | pc->p++; |
| 13137 | pc->len--; |
| 13138 | } |
| 13139 | |
| 13140 | |
| 13141 | pc->tline = pc->linenr; |
| 13142 | pc->tstart = pc->p; |
| 13143 | |
| 13144 | if (pc->len == 0) { |
| 13145 | pc->tend = pc->p; |
| 13146 | pc->tt = JIM_TT_EOL; |
| 13147 | pc->eof = 1; |
| 13148 | return JIM_OK; |
| 13149 | } |
| 13150 | switch (*(pc->p)) { |
| @@ -12936,12 +13155,11 @@ | |
| 13155 | pc->tt = JIM_TT_SUBEXPR_END; |
| 13156 | goto singlechar; |
| 13157 | case ',': |
| 13158 | pc->tt = JIM_TT_SUBEXPR_COMMA; |
| 13159 | singlechar: |
| 13160 | pc->tend = pc->p; |
| 13161 | pc->p++; |
| 13162 | pc->len--; |
| 13163 | break; |
| 13164 | case '[': |
| 13165 | return JimParseCmd(pc); |
| @@ -12987,82 +13205,44 @@ | |
| 13205 | return JIM_OK; |
| 13206 | } |
| 13207 | |
| 13208 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 13209 | { |
| 13210 | char *end; |
| 13211 | |
| 13212 | |
| 13213 | pc->tt = JIM_TT_EXPR_INT; |
| 13214 | |
| 13215 | jim_strtoull(pc->p, (char **)&pc->p); |
| 13216 | |
| 13217 | if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { |
| 13218 | if (strtod(pc->tstart, &end)) { } |
| 13219 | if (end == pc->tstart) |
| 13220 | return JIM_ERR; |
| 13221 | if (end > pc->p) { |
| 13222 | |
| 13223 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13224 | pc->p = end; |
| 13225 | } |
| 13226 | } |
| 13227 | pc->tend = pc->p - 1; |
| 13228 | pc->len -= (pc->p - pc->tstart); |
| 13229 | return JIM_OK; |
| 13230 | } |
| 13231 | |
| 13232 | static int JimParseExprIrrational(struct JimParserCtx *pc) |
| 13233 | { |
| 13234 | const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; |
| 13235 | int i; |
| 13236 | |
| 13237 | for (i = 0; irrationals[i]; i++) { |
| 13238 | const char *irr = irrationals[i]; |
| 13239 | |
| 13240 | if (strncmp(irr, pc->p, 3) == 0) { |
| 13241 | pc->p += 3; |
| 13242 | pc->len -= 3; |
| 13243 | pc->tend = pc->p - 1; |
| 13244 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13245 | return JIM_OK; |
| 13246 | } |
| 13247 | } |
| 13248 | return JIM_ERR; |
| @@ -13102,15 +13282,13 @@ | |
| 13282 | } |
| 13283 | if (*p != '(') { |
| 13284 | return JIM_ERR; |
| 13285 | } |
| 13286 | } |
| 13287 | pc->tend = pc->p + bestLen - 1; |
| 13288 | pc->p += bestLen; |
| 13289 | pc->len -= bestLen; |
| 13290 | |
| 13291 | pc->tt = bestIdx; |
| 13292 | return JIM_OK; |
| 13293 | } |
| 13294 | |
| @@ -13608,17 +13786,23 @@ | |
| 13786 | } |
| 13787 | |
| 13788 | #ifdef DEBUG_SHOW_EXPR_TOKENS |
| 13789 | { |
| 13790 | int i; |
| 13791 | printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj)); |
| 13792 | for (i = 0; i < tokenlist.count; i++) { |
| 13793 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), |
| 13794 | tokenlist.list[i].len, tokenlist.list[i].token); |
| 13795 | } |
| 13796 | } |
| 13797 | #endif |
| 13798 | |
| 13799 | if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { |
| 13800 | ScriptTokenListFree(&tokenlist); |
| 13801 | Jim_DecrRefCount(interp, fileNameObj); |
| 13802 | return JIM_ERR; |
| 13803 | } |
| 13804 | |
| 13805 | |
| 13806 | expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); |
| 13807 | |
| 13808 | |
| @@ -13665,10 +13849,24 @@ | |
| 13849 | return NULL; |
| 13850 | } |
| 13851 | } |
| 13852 | return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); |
| 13853 | } |
| 13854 | |
| 13855 | #ifdef JIM_OPTIMIZATION |
| 13856 | static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) |
| 13857 | { |
| 13858 | if (token->type == JIM_TT_EXPR_INT) |
| 13859 | return token->objPtr; |
| 13860 | else if (token->type == JIM_TT_VAR) |
| 13861 | return Jim_GetVariable(interp, token->objPtr, JIM_NONE); |
| 13862 | else if (token->type == JIM_TT_DICTSUGAR) |
| 13863 | return JimExpandDictSugar(interp, token->objPtr); |
| 13864 | else |
| 13865 | return NULL; |
| 13866 | } |
| 13867 | #endif |
| 13868 | |
| 13869 | #define JIM_EE_STATICSTACK_LEN 10 |
| 13870 | |
| 13871 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) |
| 13872 | { |
| @@ -13688,102 +13886,69 @@ | |
| 13886 | Jim_Obj *objPtr; |
| 13887 | |
| 13888 | |
| 13889 | switch (expr->len) { |
| 13890 | case 1: |
| 13891 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13892 | if (objPtr) { |
| 13893 | Jim_IncrRefCount(objPtr); |
| 13894 | *exprResultPtrPtr = objPtr; |
| 13895 | return JIM_OK; |
| 13896 | } |
| 13897 | break; |
| 13898 | |
| 13899 | case 2: |
| 13900 | if (expr->token[1].type == JIM_EXPROP_NOT) { |
| 13901 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13902 | |
| 13903 | if (objPtr && JimIsWide(objPtr)) { |
| 13904 | *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; |
| 13905 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13906 | return JIM_OK; |
| 13907 | } |
| 13908 | } |
| 13909 | break; |
| 13910 | |
| 13911 | case 3: |
| 13912 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13913 | if (objPtr && JimIsWide(objPtr)) { |
| 13914 | Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); |
| 13915 | if (objPtr2 && JimIsWide(objPtr2)) { |
| 13916 | jim_wide wideValueA = JimWideValue(objPtr); |
| 13917 | jim_wide wideValueB = JimWideValue(objPtr2); |
| 13918 | int cmpRes; |
| 13919 | switch (expr->token[2].type) { |
| 13920 | case JIM_EXPROP_LT: |
| 13921 | cmpRes = wideValueA < wideValueB; |
| 13922 | break; |
| 13923 | case JIM_EXPROP_LTE: |
| 13924 | cmpRes = wideValueA <= wideValueB; |
| 13925 | break; |
| 13926 | case JIM_EXPROP_GT: |
| 13927 | cmpRes = wideValueA > wideValueB; |
| 13928 | break; |
| 13929 | case JIM_EXPROP_GTE: |
| 13930 | cmpRes = wideValueA >= wideValueB; |
| 13931 | break; |
| 13932 | case JIM_EXPROP_NUMEQ: |
| 13933 | cmpRes = wideValueA == wideValueB; |
| 13934 | break; |
| 13935 | case JIM_EXPROP_NUMNE: |
| 13936 | cmpRes = wideValueA != wideValueB; |
| 13937 | break; |
| 13938 | default: |
| 13939 | goto noopt; |
| 13940 | } |
| 13941 | *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; |
| 13942 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13943 | return JIM_OK; |
| 13944 | } |
| 13945 | } |
| 13946 | break; |
| 13947 | } |
| 13948 | } |
| 13949 | noopt: |
| 13950 | #endif |
| 13951 | |
| 13952 | expr->inUse++; |
| 13953 | |
| 13954 | |
| @@ -13952,16 +14117,13 @@ | |
| 14117 | memcpy(newVec, srcPtr->internalRep.ptr, size); |
| 14118 | dupPtr->internalRep.ptr = newVec; |
| 14119 | dupPtr->typePtr = &scanFmtStringObjType; |
| 14120 | } |
| 14121 | |
| 14122 | static void UpdateStringOfScanFmt(Jim_Obj *objPtr) |
| 14123 | { |
| 14124 | JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep); |
| 14125 | } |
| 14126 | |
| 14127 | |
| 14128 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 14129 | { |
| @@ -14171,11 +14333,10 @@ | |
| 14333 | Jim_Obj *tmpObj = NULL; |
| 14334 | |
| 14335 | |
| 14336 | *valObjPtr = 0; |
| 14337 | if (descr->prefix) { |
| 14338 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14339 | |
| 14340 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14341 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14342 | ++pos; |
| @@ -14512,34 +14673,55 @@ | |
| 14673 | } |
| 14674 | |
| 14675 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14676 | { |
| 14677 | int retcode; |
| 14678 | Jim_Cmd *cmdPtr; |
| 14679 | |
| 14680 | #if 0 |
| 14681 | printf("invoke"); |
| 14682 | int j; |
| 14683 | for (j = 0; j < objc; j++) { |
| 14684 | printf(" '%s'", Jim_String(objv[j])); |
| 14685 | } |
| 14686 | printf("\n"); |
| 14687 | #endif |
| 14688 | |
| 14689 | if (interp->framePtr->tailcallCmd) { |
| 14690 | |
| 14691 | cmdPtr = interp->framePtr->tailcallCmd; |
| 14692 | interp->framePtr->tailcallCmd = NULL; |
| 14693 | } |
| 14694 | else { |
| 14695 | cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| 14696 | if (cmdPtr == NULL) { |
| 14697 | return JimUnknown(interp, objc, objv); |
| 14698 | } |
| 14699 | JimIncrCmdRefCount(cmdPtr); |
| 14700 | } |
| 14701 | |
| 14702 | if (interp->evalDepth == interp->maxEvalDepth) { |
| 14703 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14704 | retcode = JIM_ERR; |
| 14705 | goto out; |
| 14706 | } |
| 14707 | interp->evalDepth++; |
| 14708 | |
| 14709 | |
| 14710 | Jim_SetEmptyResult(interp); |
| 14711 | if (cmdPtr->isproc) { |
| 14712 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14713 | } |
| 14714 | else { |
| 14715 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14716 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14717 | } |
| 14718 | interp->evalDepth--; |
| 14719 | |
| 14720 | out: |
| 14721 | JimDecrCmdRefCount(interp, cmdPtr); |
| 14722 | |
| 14723 | return retcode; |
| 14724 | } |
| 14725 | |
| 14726 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14727 | { |
| @@ -14717,10 +14899,15 @@ | |
| 14899 | objPtr->typePtr = &interpolatedObjType; |
| 14900 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 14901 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 14902 | Jim_IncrRefCount(intv[2]); |
| 14903 | } |
| 14904 | else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { |
| 14905 | |
| 14906 | JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); |
| 14907 | } |
| 14908 | |
| 14909 | |
| 14910 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| 14911 | objPtr->length = totlen; |
| 14912 | for (i = 0; i < tokens; i++) { |
| 14913 | if (intv[i]) { |
| @@ -14772,10 +14959,14 @@ | |
| 14959 | return JimEvalObjList(interp, scriptObjPtr); |
| 14960 | } |
| 14961 | |
| 14962 | Jim_IncrRefCount(scriptObjPtr); |
| 14963 | script = Jim_GetScript(interp, scriptObjPtr); |
| 14964 | if (script == NULL) { |
| 14965 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 14966 | return JIM_ERR; |
| 14967 | } |
| 14968 | |
| 14969 | Jim_SetEmptyResult(interp); |
| 14970 | |
| 14971 | token = script->token; |
| 14972 | |
| @@ -15046,26 +15237,20 @@ | |
| 15237 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15238 | } |
| 15239 | |
| 15240 | |
| 15241 | interp->framePtr = interp->framePtr->parent; |
| 15242 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15243 | |
| 15244 | return retcode; |
| 15245 | } |
| 15246 | #endif |
| 15247 | |
| 15248 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) |
| 15249 | { |
| 15250 | Jim_CallFrame *callFramePtr; |
| 15251 | int i, d, retcode, optargs; |
| 15252 | ScriptObj *script; |
| 15253 | |
| 15254 | |
| 15255 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15256 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| @@ -15145,37 +15330,42 @@ | |
| 15330 | |
| 15331 | |
| 15332 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15333 | |
| 15334 | badargset: |
| 15335 | |
| 15336 | |
| 15337 | interp->framePtr = interp->framePtr->parent; |
| 15338 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15339 | |
| 15340 | if (interp->framePtr->tailcallObj) { |
| 15341 | |
| 15342 | if (interp->framePtr->tailcall++ == 0) { |
| 15343 | |
| 15344 | do { |
| 15345 | Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15346 | |
| 15347 | interp->framePtr->tailcallObj = NULL; |
| 15348 | |
| 15349 | if (retcode == JIM_EVAL) { |
| 15350 | retcode = Jim_EvalObjList(interp, tailcallObj); |
| 15351 | if (retcode == JIM_RETURN) { |
| 15352 | interp->returnLevel++; |
| 15353 | } |
| 15354 | } |
| 15355 | Jim_DecrRefCount(interp, tailcallObj); |
| 15356 | } while (interp->framePtr->tailcallObj); |
| 15357 | |
| 15358 | |
| 15359 | if (interp->framePtr->tailcallCmd) { |
| 15360 | JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15361 | interp->framePtr->tailcallCmd = NULL; |
| 15362 | } |
| 15363 | } |
| 15364 | interp->framePtr->tailcall--; |
| 15365 | } |
| 15366 | |
| 15367 | |
| 15368 | if (retcode == JIM_RETURN) { |
| 15369 | if (--interp->returnLevel <= 0) { |
| 15370 | retcode = interp->returnCode; |
| 15371 | interp->returnCode = JIM_OK; |
| @@ -15187,13 +15377,10 @@ | |
| 15377 | Jim_DecrRefCount(interp, interp->errorProc); |
| 15378 | interp->errorProc = argv[0]; |
| 15379 | Jim_IncrRefCount(interp->errorProc); |
| 15380 | } |
| 15381 | |
| 15382 | return retcode; |
| 15383 | } |
| 15384 | |
| 15385 | int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) |
| 15386 | { |
| @@ -15261,11 +15448,10 @@ | |
| 15448 | Jim_Obj *scriptObjPtr; |
| 15449 | Jim_Obj *prevScriptObj; |
| 15450 | struct stat sb; |
| 15451 | int retcode; |
| 15452 | int readlen; |
| 15453 | |
| 15454 | if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { |
| 15455 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); |
| 15456 | return JIM_ERR; |
| 15457 | } |
| @@ -15288,31 +15474,13 @@ | |
| 15474 | scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 15475 | JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); |
| 15476 | Jim_IncrRefCount(scriptObjPtr); |
| 15477 | |
| 15478 | |
| 15479 | if (Jim_GetScript(interp, scriptObjPtr) == NULL) { |
| 15480 | |
| 15481 | JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr)); |
| 15482 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15483 | return JIM_ERR; |
| 15484 | } |
| 15485 | |
| 15486 | prevScriptObj = interp->currentScriptObj; |
| @@ -15475,11 +15643,11 @@ | |
| 15643 | } |
| 15644 | |
| 15645 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15646 | Jim_HashEntry *he, int type); |
| 15647 | |
| 15648 | #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) |
| 15649 | |
| 15650 | static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 15651 | JimHashtableIteratorCallbackType *callback, int type) |
| 15652 | { |
| 15653 | Jim_HashEntry *he; |
| @@ -15510,11 +15678,11 @@ | |
| 15678 | #define JIM_CMDLIST_CHANNELS 2 |
| 15679 | |
| 15680 | static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15681 | Jim_HashEntry *he, int type) |
| 15682 | { |
| 15683 | Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15684 | Jim_Obj *objPtr; |
| 15685 | |
| 15686 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15687 | |
| 15688 | return; |
| @@ -15543,11 +15711,11 @@ | |
| 15711 | #define JIM_VARLIST_VALUES 0x1000 |
| 15712 | |
| 15713 | static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15714 | Jim_HashEntry *he, int type) |
| 15715 | { |
| 15716 | Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 15717 | |
| 15718 | if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { |
| 15719 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); |
| 15720 | if (type & JIM_VARLIST_VALUES) { |
| 15721 | Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); |
| @@ -15865,11 +16033,11 @@ | |
| 16033 | |
| 16034 | expr = JimGetExpression(interp, argv[2]); |
| 16035 | incrScript = Jim_GetScript(interp, argv[3]); |
| 16036 | |
| 16037 | |
| 16038 | if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { |
| 16039 | goto evalstart; |
| 16040 | } |
| 16041 | |
| 16042 | if (incrScript->token[1].type != JIM_TT_ESC || |
| 16043 | expr->token[0].type != JIM_TT_VAR || |
| @@ -16088,11 +16256,11 @@ | |
| 16256 | } |
| 16257 | |
| 16258 | |
| 16259 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16260 | { |
| 16261 | int result = JIM_OK; |
| 16262 | int i, numargs; |
| 16263 | Jim_ListIter twoiters[2]; |
| 16264 | Jim_ListIter *iters; |
| 16265 | Jim_Obj *script; |
| 16266 | Jim_Obj *resultObj; |
| @@ -16111,13 +16279,16 @@ | |
| 16279 | iters = Jim_Alloc(numargs * sizeof(*iters)); |
| 16280 | } |
| 16281 | for (i = 0; i < numargs; i++) { |
| 16282 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16283 | if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { |
| 16284 | result = JIM_ERR; |
| 16285 | } |
| 16286 | } |
| 16287 | if (result != JIM_OK) { |
| 16288 | Jim_SetResultString(interp, "foreach varlist is empty", -1); |
| 16289 | return result; |
| 16290 | } |
| 16291 | |
| 16292 | if (doMap) { |
| 16293 | resultObj = Jim_NewListObj(interp, NULL, 0); |
| 16294 | } |
| @@ -16430,12 +16601,12 @@ | |
| 16601 | { |
| 16602 | Jim_Obj *objPtr, *listObjPtr; |
| 16603 | int i; |
| 16604 | int idx; |
| 16605 | |
| 16606 | if (argc < 2) { |
| 16607 | Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); |
| 16608 | return JIM_ERR; |
| 16609 | } |
| 16610 | objPtr = argv[1]; |
| 16611 | Jim_IncrRefCount(objPtr); |
| 16612 | for (i = 2; i < argc; i++) { |
| @@ -16547,14 +16718,13 @@ | |
| 16718 | Jim_IncrRefCount(commandObj); |
| 16719 | } |
| 16720 | |
| 16721 | listlen = Jim_ListLength(interp, argv[0]); |
| 16722 | for (i = 0; i < listlen; i++) { |
| 16723 | int eq = 0; |
| 16724 | Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); |
| 16725 | |
| 16726 | switch (opt_match) { |
| 16727 | case OPT_EXACT: |
| 16728 | eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; |
| 16729 | break; |
| 16730 | |
| @@ -16744,29 +16914,27 @@ | |
| 16914 | if (argc < 3) { |
| 16915 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 16916 | return JIM_ERR; |
| 16917 | } |
| 16918 | else if (argc == 3) { |
| 16919 | |
| 16920 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16921 | return JIM_ERR; |
| 16922 | Jim_SetResult(interp, argv[2]); |
| 16923 | return JIM_OK; |
| 16924 | } |
| 16925 | return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]); |
| 16926 | } |
| 16927 | |
| 16928 | |
| 16929 | static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) |
| 16930 | { |
| 16931 | static const char * const options[] = { |
| 16932 | "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL |
| 16933 | }; |
| 16934 | enum |
| 16935 | { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 16936 | Jim_Obj *resObj; |
| 16937 | int i; |
| 16938 | int retCode; |
| 16939 | |
| 16940 | struct lsort_info info; |
| @@ -16777,17 +16945,18 @@ | |
| 16945 | } |
| 16946 | |
| 16947 | info.type = JIM_LSORT_ASCII; |
| 16948 | info.order = 1; |
| 16949 | info.indexed = 0; |
| 16950 | info.unique = 0; |
| 16951 | info.command = NULL; |
| 16952 | info.interp = interp; |
| 16953 | |
| 16954 | for (i = 1; i < (argc - 1); i++) { |
| 16955 | int option; |
| 16956 | |
| 16957 | if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) |
| 16958 | != JIM_OK) |
| 16959 | return JIM_ERR; |
| 16960 | switch (option) { |
| 16961 | case OPT_ASCII: |
| 16962 | info.type = JIM_LSORT_ASCII; |
| @@ -16796,16 +16965,22 @@ | |
| 16965 | info.type = JIM_LSORT_NOCASE; |
| 16966 | break; |
| 16967 | case OPT_INTEGER: |
| 16968 | info.type = JIM_LSORT_INTEGER; |
| 16969 | break; |
| 16970 | case OPT_REAL: |
| 16971 | info.type = JIM_LSORT_REAL; |
| 16972 | break; |
| 16973 | case OPT_INCREASING: |
| 16974 | info.order = 1; |
| 16975 | break; |
| 16976 | case OPT_DECREASING: |
| 16977 | info.order = -1; |
| 16978 | break; |
| 16979 | case OPT_UNIQUE: |
| 16980 | info.unique = 1; |
| 16981 | break; |
| 16982 | case OPT_COMMAND: |
| 16983 | if (i >= (argc - 2)) { |
| 16984 | Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); |
| 16985 | return JIM_ERR; |
| 16986 | } |
| @@ -16915,20 +17090,20 @@ | |
| 17090 | static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17091 | { |
| 17092 | if (argc >= 2) { |
| 17093 | int retcode; |
| 17094 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 17095 | int savedTailcall; |
| 17096 | const char *str; |
| 17097 | |
| 17098 | |
| 17099 | savedCallFrame = interp->framePtr; |
| 17100 | |
| 17101 | |
| 17102 | str = Jim_String(argv[1]); |
| 17103 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 17104 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17105 | argc--; |
| 17106 | argv++; |
| 17107 | } |
| 17108 | else { |
| 17109 | targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); |
| @@ -16935,25 +17110,25 @@ | |
| 17110 | } |
| 17111 | if (targetCallFrame == NULL) { |
| 17112 | return JIM_ERR; |
| 17113 | } |
| 17114 | if (argc < 2) { |
| 17115 | Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); |
| 17116 | return JIM_ERR; |
| 17117 | } |
| 17118 | |
| 17119 | interp->framePtr = targetCallFrame; |
| 17120 | |
| 17121 | savedTailcall = interp->framePtr->tailcall; |
| 17122 | interp->framePtr->tailcall = 0; |
| 17123 | if (argc == 2) { |
| 17124 | retcode = Jim_EvalObj(interp, argv[1]); |
| 17125 | } |
| 17126 | else { |
| 17127 | retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 17128 | } |
| 17129 | interp->framePtr->tailcall = savedTailcall; |
| 17130 | interp->framePtr = savedCallFrame; |
| 17131 | return retcode; |
| 17132 | } |
| 17133 | else { |
| 17134 | Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| @@ -17064,12 +17239,39 @@ | |
| 17239 | } |
| 17240 | |
| 17241 | |
| 17242 | static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17243 | { |
| 17244 | if (interp->framePtr->level == 0) { |
| 17245 | Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); |
| 17246 | return JIM_ERR; |
| 17247 | } |
| 17248 | else if (argc >= 2) { |
| 17249 | |
| 17250 | Jim_CallFrame *cf = interp->framePtr->parent; |
| 17251 | |
| 17252 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17253 | if (cmdPtr == NULL) { |
| 17254 | return JIM_ERR; |
| 17255 | } |
| 17256 | |
| 17257 | JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); |
| 17258 | |
| 17259 | |
| 17260 | JimIncrCmdRefCount(cmdPtr); |
| 17261 | cf->tailcallCmd = cmdPtr; |
| 17262 | |
| 17263 | |
| 17264 | JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); |
| 17265 | |
| 17266 | cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 17267 | Jim_IncrRefCount(cf->tailcallObj); |
| 17268 | |
| 17269 | |
| 17270 | return JIM_EVAL; |
| 17271 | } |
| 17272 | return JIM_OK; |
| 17273 | } |
| 17274 | |
| 17275 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17276 | { |
| 17277 | Jim_Obj *cmdList; |
| @@ -17354,11 +17556,11 @@ | |
| 17556 | for (i = 0; i < numMaps; i += 2) { |
| 17557 | Jim_Obj *objPtr; |
| 17558 | const char *k; |
| 17559 | int kl; |
| 17560 | |
| 17561 | objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); |
| 17562 | k = Jim_String(objPtr); |
| 17563 | kl = Jim_Utf8Length(interp, objPtr); |
| 17564 | |
| 17565 | if (strLen >= kl && kl) { |
| 17566 | int rc; |
| @@ -17366,12 +17568,11 @@ | |
| 17568 | if (rc == 0) { |
| 17569 | if (noMatchStart) { |
| 17570 | Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); |
| 17571 | noMatchStart = NULL; |
| 17572 | } |
| 17573 | Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1)); |
| 17574 | str += utf8_index(str, kl); |
| 17575 | strLen -= kl; |
| 17576 | break; |
| 17577 | } |
| 17578 | } |
| @@ -17851,15 +18052,17 @@ | |
| 18052 | |
| 18053 | exitCode = JIM_SIGNAL; |
| 18054 | } |
| 18055 | else { |
| 18056 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18057 | |
| 18058 | interp->errorFlag = 0; |
| 18059 | } |
| 18060 | interp->signal_level -= sig; |
| 18061 | |
| 18062 | |
| 18063 | if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 18064 | |
| 18065 | return exitCode; |
| 18066 | } |
| 18067 | |
| 18068 | if (sig && exitCode == JIM_SIGNAL) { |
| @@ -18009,11 +18212,11 @@ | |
| 18212 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18213 | |
| 18214 | JimInitHashTableIterator(&interp->references, &htiter); |
| 18215 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18216 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 18217 | Jim_Reference *refPtr = Jim_GetHashEntryVal(he); |
| 18218 | const unsigned long *refId = he->key; |
| 18219 | |
| 18220 | JimFormatReference(buf, refPtr, *refId); |
| 18221 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); |
| 18222 | } |
| @@ -18043,11 +18246,11 @@ | |
| 18246 | |
| 18247 | static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) |
| 18248 | { |
| 18249 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 18250 | if (type & JIM_DICTMATCH_VALUES) { |
| 18251 | Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); |
| 18252 | } |
| 18253 | } |
| 18254 | |
| 18255 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 18256 | JimDictMatchCallbackType *callback, int type) |
| @@ -18092,21 +18295,65 @@ | |
| 18295 | return -1; |
| 18296 | } |
| 18297 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18298 | } |
| 18299 | |
| 18300 | int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18301 | { |
| 18302 | Jim_HashTable *ht; |
| 18303 | unsigned int i; |
| 18304 | |
| 18305 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18306 | return JIM_ERR; |
| 18307 | } |
| 18308 | |
| 18309 | ht = (Jim_HashTable *)objPtr->internalRep.ptr; |
| 18310 | |
| 18311 | |
| 18312 | printf("%d entries in table, %d buckets\n", ht->used, ht->size); |
| 18313 | |
| 18314 | for (i = 0; i < ht->size; i++) { |
| 18315 | Jim_HashEntry *he = ht->table[i]; |
| 18316 | |
| 18317 | if (he) { |
| 18318 | printf("%d: ", i); |
| 18319 | |
| 18320 | while (he) { |
| 18321 | printf(" %s", Jim_String(he->key)); |
| 18322 | he = he->next; |
| 18323 | } |
| 18324 | printf("\n"); |
| 18325 | } |
| 18326 | } |
| 18327 | return JIM_OK; |
| 18328 | } |
| 18329 | |
| 18330 | static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) |
| 18331 | { |
| 18332 | Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1); |
| 18333 | |
| 18334 | Jim_AppendString(interp, prefixObj, " ", 1); |
| 18335 | Jim_AppendString(interp, prefixObj, subcmd, -1); |
| 18336 | |
| 18337 | return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); |
| 18338 | } |
| 18339 | |
| 18340 | |
| 18341 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18342 | { |
| 18343 | Jim_Obj *objPtr; |
| 18344 | int option; |
| 18345 | static const char * const options[] = { |
| 18346 | "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18347 | "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18348 | "replace", "update", NULL |
| 18349 | }; |
| 18350 | enum |
| 18351 | { |
| 18352 | OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, |
| 18353 | OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, |
| 18354 | OPT_REPLACE, OPT_UPDATE, |
| 18355 | }; |
| 18356 | |
| 18357 | if (argc < 2) { |
| 18358 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18359 | return JIM_ERR; |
| @@ -18117,11 +18364,11 @@ | |
| 18364 | } |
| 18365 | |
| 18366 | switch (option) { |
| 18367 | case OPT_GET: |
| 18368 | if (argc < 3) { |
| 18369 | Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); |
| 18370 | return JIM_ERR; |
| 18371 | } |
| 18372 | if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, |
| 18373 | JIM_ERRMSG) != JIM_OK) { |
| 18374 | return JIM_ERR; |
| @@ -18134,82 +18381,87 @@ | |
| 18381 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); |
| 18382 | return JIM_ERR; |
| 18383 | } |
| 18384 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); |
| 18385 | |
| 18386 | case OPT_EXISTS: |
| 18387 | if (argc < 4) { |
| 18388 | Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); |
| 18389 | return JIM_ERR; |
| 18390 | } |
| 18391 | else { |
| 18392 | int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); |
| 18393 | if (rc < 0) { |
| 18394 | return JIM_ERR; |
| 18395 | } |
| 18396 | Jim_SetResultBool(interp, rc == JIM_OK); |
| 18397 | return JIM_OK; |
| 18398 | } |
| 18399 | |
| 18400 | case OPT_UNSET: |
| 18401 | if (argc < 4) { |
| 18402 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); |
| 18403 | return JIM_ERR; |
| 18404 | } |
| 18405 | if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 18406 | return JIM_ERR; |
| 18407 | } |
| 18408 | return JIM_OK; |
| 18409 | |
| 18410 | case OPT_KEYS: |
| 18411 | if (argc != 3 && argc != 4) { |
| 18412 | Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18413 | return JIM_ERR; |
| 18414 | } |
| 18415 | return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); |
| 18416 | |
| 18417 | case OPT_SIZE: |
| 18418 | if (argc != 3) { |
| 18419 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18420 | return JIM_ERR; |
| 18421 | } |
| 18422 | else if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18423 | return JIM_ERR; |
| 18424 | } |
| 18425 | Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); |
| 18426 | return JIM_OK; |
| 18427 | |
| 18428 | case OPT_MERGE: |
| 18429 | if (argc == 2) { |
| 18430 | return JIM_OK; |
| 18431 | } |
| 18432 | if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18433 | return JIM_ERR; |
| 18434 | } |
| 18435 | |
| 18436 | break; |
| 18437 | |
| 18438 | case OPT_UPDATE: |
| 18439 | if (argc < 6 || argc % 2) { |
| 18440 | |
| 18441 | argc = 2; |
| 18442 | } |
| 18443 | break; |
| 18444 | |
| 18445 | case OPT_CREATE: |
| 18446 | if (argc % 2) { |
| 18447 | Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); |
| 18448 | return JIM_ERR; |
| 18449 | } |
| 18450 | objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); |
| 18451 | Jim_SetResult(interp, objPtr); |
| 18452 | return JIM_OK; |
| 18453 | |
| 18454 | case OPT_INFO: |
| 18455 | if (argc != 3) { |
| 18456 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18457 | return JIM_ERR; |
| 18458 | } |
| 18459 | return Jim_DictInfo(interp, argv[2]); |
| 18460 | } |
| 18461 | |
| 18462 | return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18463 | } |
| 18464 | |
| 18465 | |
| 18466 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18467 | { |
| @@ -18267,11 +18519,11 @@ | |
| 18519 | }; |
| 18520 | enum |
| 18521 | { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, |
| 18522 | INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, |
| 18523 | INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, |
| 18524 | INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, |
| 18525 | }; |
| 18526 | |
| 18527 | #ifdef jim_ext_namespace |
| 18528 | int nons = 0; |
| 18529 | |
| @@ -19047,11 +19299,11 @@ | |
| 19299 | } |
| 19300 | } |
| 19301 | |
| 19302 | static const struct { |
| 19303 | const char *name; |
| 19304 | Jim_CmdProc *cmdProc; |
| 19305 | } Jim_CoreCommandsTable[] = { |
| 19306 | {"alias", Jim_AliasCoreCommand}, |
| 19307 | {"set", Jim_SetCoreCommand}, |
| 19308 | {"unset", Jim_UnsetCoreCommand}, |
| 19309 | {"puts", Jim_PutsCoreCommand}, |
| @@ -19279,10 +19531,12 @@ | |
| 19531 | } |
| 19532 | |
| 19533 | len += extra; |
| 19534 | buf = Jim_Alloc(len + 1); |
| 19535 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19536 | |
| 19537 | va_end(args); |
| 19538 | |
| 19539 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19540 | } |
| 19541 | |
| 19542 | |
| @@ -19530,23 +19784,22 @@ | |
| 19784 | |
| 19785 | #include <ctype.h> |
| 19786 | #include <string.h> |
| 19787 | |
| 19788 | |
| 19789 | #define JIM_INTEGER_SPACE 24 |
| 19790 | #define MAX_FLOAT_WIDTH 320 |
| 19791 | |
| 19792 | Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) |
| 19793 | { |
| 19794 | const char *span, *format, *formatEnd, *msg; |
| 19795 | int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; |
| 19796 | static const char * const mixedXPG = |
| 19797 | "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 19798 | static const char * const badIndex[2] = { |
| 19799 | "not enough arguments for all format specifiers", |
| 19800 | "\"%n$\" argument index out of range" |
| 19801 | }; |
| 19802 | int formatLen; |
| 19803 | Jim_Obj *resultPtr; |
| 19804 | |
| 19805 | char *num_buffer = NULL; |
| @@ -19555,319 +19808,349 @@ | |
| 19808 | span = format = Jim_GetString(fmtObjPtr, &formatLen); |
| 19809 | formatEnd = format + formatLen; |
| 19810 | resultPtr = Jim_NewEmptyStringObj(interp); |
| 19811 | |
| 19812 | while (format != formatEnd) { |
| 19813 | char *end; |
| 19814 | int gotMinus, sawFlag; |
| 19815 | int gotPrecision, useShort; |
| 19816 | long width, precision; |
| 19817 | int newXpg; |
| 19818 | int ch; |
| 19819 | int step; |
| 19820 | int doubleType; |
| 19821 | char pad = ' '; |
| 19822 | char spec[2*JIM_INTEGER_SPACE + 12]; |
| 19823 | char *p; |
| 19824 | |
| 19825 | int formatted_chars; |
| 19826 | int formatted_bytes; |
| 19827 | const char *formatted_buf; |
| 19828 | |
| 19829 | step = utf8_tounicode(format, &ch); |
| 19830 | format += step; |
| 19831 | if (ch != '%') { |
| 19832 | numBytes += step; |
| 19833 | continue; |
| 19834 | } |
| 19835 | if (numBytes) { |
| 19836 | Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19837 | numBytes = 0; |
| 19838 | } |
| 19839 | |
| 19840 | |
| 19841 | step = utf8_tounicode(format, &ch); |
| 19842 | if (ch == '%') { |
| 19843 | span = format; |
| 19844 | numBytes = step; |
| 19845 | format += step; |
| 19846 | continue; |
| 19847 | } |
| 19848 | |
| 19849 | |
| 19850 | newXpg = 0; |
| 19851 | if (isdigit(ch)) { |
| 19852 | int position = strtoul(format, &end, 10); |
| 19853 | if (*end == '$') { |
| 19854 | newXpg = 1; |
| 19855 | objIndex = position - 1; |
| 19856 | format = end + 1; |
| 19857 | step = utf8_tounicode(format, &ch); |
| 19858 | } |
| 19859 | } |
| 19860 | if (newXpg) { |
| 19861 | if (gotSequential) { |
| 19862 | msg = mixedXPG; |
| 19863 | goto errorMsg; |
| 19864 | } |
| 19865 | gotXpg = 1; |
| 19866 | } else { |
| 19867 | if (gotXpg) { |
| 19868 | msg = mixedXPG; |
| 19869 | goto errorMsg; |
| 19870 | } |
| 19871 | gotSequential = 1; |
| 19872 | } |
| 19873 | if ((objIndex < 0) || (objIndex >= objc)) { |
| 19874 | msg = badIndex[gotXpg]; |
| 19875 | goto errorMsg; |
| 19876 | } |
| 19877 | |
| 19878 | p = spec; |
| 19879 | *p++ = '%'; |
| 19880 | |
| 19881 | gotMinus = 0; |
| 19882 | sawFlag = 1; |
| 19883 | do { |
| 19884 | switch (ch) { |
| 19885 | case '-': |
| 19886 | gotMinus = 1; |
| 19887 | break; |
| 19888 | case '0': |
| 19889 | pad = ch; |
| 19890 | break; |
| 19891 | case ' ': |
| 19892 | case '+': |
| 19893 | case '#': |
| 19894 | break; |
| 19895 | default: |
| 19896 | sawFlag = 0; |
| 19897 | continue; |
| 19898 | } |
| 19899 | *p++ = ch; |
| 19900 | format += step; |
| 19901 | step = utf8_tounicode(format, &ch); |
| 19902 | } while (sawFlag); |
| 19903 | |
| 19904 | |
| 19905 | width = 0; |
| 19906 | if (isdigit(ch)) { |
| 19907 | width = strtoul(format, &end, 10); |
| 19908 | format = end; |
| 19909 | step = utf8_tounicode(format, &ch); |
| 19910 | } else if (ch == '*') { |
| 19911 | if (objIndex >= objc - 1) { |
| 19912 | msg = badIndex[gotXpg]; |
| 19913 | goto errorMsg; |
| 19914 | } |
| 19915 | if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { |
| 19916 | goto error; |
| 19917 | } |
| 19918 | if (width < 0) { |
| 19919 | width = -width; |
| 19920 | if (!gotMinus) { |
| 19921 | *p++ = '-'; |
| 19922 | gotMinus = 1; |
| 19923 | } |
| 19924 | } |
| 19925 | objIndex++; |
| 19926 | format += step; |
| 19927 | step = utf8_tounicode(format, &ch); |
| 19928 | } |
| 19929 | |
| 19930 | |
| 19931 | gotPrecision = precision = 0; |
| 19932 | if (ch == '.') { |
| 19933 | gotPrecision = 1; |
| 19934 | format += step; |
| 19935 | step = utf8_tounicode(format, &ch); |
| 19936 | } |
| 19937 | if (isdigit(ch)) { |
| 19938 | precision = strtoul(format, &end, 10); |
| 19939 | format = end; |
| 19940 | step = utf8_tounicode(format, &ch); |
| 19941 | } else if (ch == '*') { |
| 19942 | if (objIndex >= objc - 1) { |
| 19943 | msg = badIndex[gotXpg]; |
| 19944 | goto errorMsg; |
| 19945 | } |
| 19946 | if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { |
| 19947 | goto error; |
| 19948 | } |
| 19949 | |
| 19950 | |
| 19951 | if (precision < 0) { |
| 19952 | precision = 0; |
| 19953 | } |
| 19954 | objIndex++; |
| 19955 | format += step; |
| 19956 | step = utf8_tounicode(format, &ch); |
| 19957 | } |
| 19958 | |
| 19959 | |
| 19960 | useShort = 0; |
| 19961 | if (ch == 'h') { |
| 19962 | useShort = 1; |
| 19963 | format += step; |
| 19964 | step = utf8_tounicode(format, &ch); |
| 19965 | } else if (ch == 'l') { |
| 19966 | |
| 19967 | format += step; |
| 19968 | step = utf8_tounicode(format, &ch); |
| 19969 | if (ch == 'l') { |
| 19970 | format += step; |
| 19971 | step = utf8_tounicode(format, &ch); |
| 19972 | } |
| 19973 | } |
| 19974 | |
| 19975 | format += step; |
| 19976 | span = format; |
| 19977 | |
| 19978 | |
| 19979 | if (ch == 'i') { |
| 19980 | ch = 'd'; |
| 19981 | } |
| 19982 | |
| 19983 | doubleType = 0; |
| 19984 | |
| 19985 | switch (ch) { |
| 19986 | case '\0': |
| 19987 | msg = "format string ended in middle of field specifier"; |
| 19988 | goto errorMsg; |
| 19989 | case 's': { |
| 19990 | formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 19991 | formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 19992 | if (gotPrecision && (precision < formatted_chars)) { |
| 19993 | |
| 19994 | formatted_chars = precision; |
| 19995 | formatted_bytes = utf8_index(formatted_buf, precision); |
| 19996 | } |
| 19997 | break; |
| 19998 | } |
| 19999 | case 'c': { |
| 20000 | jim_wide code; |
| 20001 | |
| 20002 | if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 20003 | goto error; |
| 20004 | } |
| 20005 | |
| 20006 | formatted_bytes = utf8_getchars(spec, code); |
| 20007 | formatted_buf = spec; |
| 20008 | formatted_chars = 1; |
| 20009 | break; |
| 20010 | } |
| 20011 | case 'b': { |
| 20012 | unsigned jim_wide w; |
| 20013 | int length; |
| 20014 | int i; |
| 20015 | int j; |
| 20016 | |
| 20017 | if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) { |
| 20018 | goto error; |
| 20019 | } |
| 20020 | length = sizeof(w) * 8; |
| 20021 | |
| 20022 | |
| 20023 | |
| 20024 | if (num_buffer_size < length + 1) { |
| 20025 | num_buffer_size = length + 1; |
| 20026 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20027 | } |
| 20028 | |
| 20029 | j = 0; |
| 20030 | for (i = length; i > 0; ) { |
| 20031 | i--; |
| 20032 | if (w & ((unsigned jim_wide)1 << i)) { |
| 20033 | num_buffer[j++] = '1'; |
| 20034 | } |
| 20035 | else if (j || i == 0) { |
| 20036 | num_buffer[j++] = '0'; |
| 20037 | } |
| 20038 | } |
| 20039 | num_buffer[j] = 0; |
| 20040 | formatted_chars = formatted_bytes = j; |
| 20041 | formatted_buf = num_buffer; |
| 20042 | break; |
| 20043 | } |
| 20044 | |
| 20045 | case 'e': |
| 20046 | case 'E': |
| 20047 | case 'f': |
| 20048 | case 'g': |
| 20049 | case 'G': |
| 20050 | doubleType = 1; |
| 20051 | |
| 20052 | case 'd': |
| 20053 | case 'u': |
| 20054 | case 'o': |
| 20055 | case 'x': |
| 20056 | case 'X': { |
| 20057 | jim_wide w; |
| 20058 | double d; |
| 20059 | int length; |
| 20060 | |
| 20061 | |
| 20062 | if (width) { |
| 20063 | p += sprintf(p, "%ld", width); |
| 20064 | } |
| 20065 | if (gotPrecision) { |
| 20066 | p += sprintf(p, ".%ld", precision); |
| 20067 | } |
| 20068 | |
| 20069 | |
| 20070 | if (doubleType) { |
| 20071 | if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 20072 | goto error; |
| 20073 | } |
| 20074 | length = MAX_FLOAT_WIDTH; |
| 20075 | } |
| 20076 | else { |
| 20077 | if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { |
| 20078 | goto error; |
| 20079 | } |
| 20080 | length = JIM_INTEGER_SPACE; |
| 20081 | if (useShort) { |
| 20082 | if (ch == 'd') { |
| 20083 | w = (short)w; |
| 20084 | } |
| 20085 | else { |
| 20086 | w = (unsigned short)w; |
| 20087 | } |
| 20088 | } |
| 20089 | *p++ = 'l'; |
| 20090 | #ifdef HAVE_LONG_LONG |
| 20091 | if (sizeof(long long) == sizeof(jim_wide)) { |
| 20092 | *p++ = 'l'; |
| 20093 | } |
| 20094 | #endif |
| 20095 | } |
| 20096 | |
| 20097 | *p++ = (char) ch; |
| 20098 | *p = '\0'; |
| 20099 | |
| 20100 | |
| 20101 | if (width > length) { |
| 20102 | length = width; |
| 20103 | } |
| 20104 | if (gotPrecision) { |
| 20105 | length += precision; |
| 20106 | } |
| 20107 | |
| 20108 | |
| 20109 | if (num_buffer_size < length + 1) { |
| 20110 | num_buffer_size = length + 1; |
| 20111 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20112 | } |
| 20113 | |
| 20114 | if (doubleType) { |
| 20115 | snprintf(num_buffer, length + 1, spec, d); |
| 20116 | } |
| 20117 | else { |
| 20118 | formatted_bytes = snprintf(num_buffer, length + 1, spec, w); |
| 20119 | } |
| 20120 | formatted_chars = formatted_bytes = strlen(num_buffer); |
| 20121 | formatted_buf = num_buffer; |
| 20122 | break; |
| 20123 | } |
| 20124 | |
| 20125 | default: { |
| 20126 | |
| 20127 | spec[0] = ch; |
| 20128 | spec[1] = '\0'; |
| 20129 | Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 20130 | goto error; |
| 20131 | } |
| 20132 | } |
| 20133 | |
| 20134 | if (!gotMinus) { |
| 20135 | while (formatted_chars < width) { |
| 20136 | Jim_AppendString(interp, resultPtr, &pad, 1); |
| 20137 | formatted_chars++; |
| 20138 | } |
| 20139 | } |
| 20140 | |
| 20141 | Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); |
| 20142 | |
| 20143 | while (formatted_chars < width) { |
| 20144 | Jim_AppendString(interp, resultPtr, &pad, 1); |
| 20145 | formatted_chars++; |
| 20146 | } |
| 20147 | |
| 20148 | objIndex += gotSequential; |
| 20149 | } |
| 20150 | if (numBytes) { |
| 20151 | Jim_AppendString(interp, resultPtr, span, numBytes); |
| 20152 | } |
| 20153 | |
| 20154 | Jim_Free(num_buffer); |
| 20155 | return resultPtr; |
| 20156 | |
| @@ -19876,21 +20159,22 @@ | |
| 20159 | error: |
| 20160 | Jim_FreeNewObj(interp, resultPtr); |
| 20161 | Jim_Free(num_buffer); |
| 20162 | return NULL; |
| 20163 | } |
| 20164 | |
| 20165 | |
| 20166 | #if defined(JIM_REGEXP) |
| 20167 | #include <stdio.h> |
| 20168 | #include <ctype.h> |
| 20169 | #include <stdlib.h> |
| 20170 | #include <string.h> |
| 20171 | |
| 20172 | |
| 20173 | |
| 20174 | #define REG_MAX_PAREN 100 |
| 20175 | |
| 20176 | |
| 20177 | |
| 20178 | #define END 0 |
| 20179 | #define BOL 1 |
| 20180 | #define EOL 2 |
| @@ -19899,23 +20183,27 @@ | |
| 20183 | #define ANYBUT 5 |
| 20184 | #define BRANCH 6 |
| 20185 | #define BACK 7 |
| 20186 | #define EXACTLY 8 |
| 20187 | #define NOTHING 9 |
| 20188 | #define REP 10 |
| 20189 | #define REPMIN 11 |
| 20190 | #define REPX 12 |
| 20191 | #define REPXMIN 13 |
| 20192 | |
| 20193 | #define WORDA 15 |
| 20194 | #define WORDZ 16 |
| 20195 | |
| 20196 | #define OPENNC 1000 |
| 20197 | #define OPEN 1001 |
| 20198 | |
| 20199 | |
| 20200 | |
| 20201 | |
| 20202 | #define CLOSENC 2000 |
| 20203 | #define CLOSE 2001 |
| 20204 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 20205 | |
| 20206 | #define REG_MAGIC 0xFADED00D |
| 20207 | |
| 20208 | |
| 20209 | #define OP(preg, p) (preg->program[p]) |
| @@ -19925,15 +20213,15 @@ | |
| 20213 | |
| 20214 | |
| 20215 | |
| 20216 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 20217 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 20218 | #define META "^$.[()|?{+*" |
| 20219 | |
| 20220 | #define HASWIDTH 1 |
| 20221 | #define SIMPLE 2 |
| 20222 | #define SPSTART 4 |
| 20223 | #define WORST 0 |
| 20224 | |
| 20225 | #define MAX_REP_COUNT 1000000 |
| 20226 | |
| 20227 | static int reg(regex_t *preg, int paren , int *flagp ); |
| @@ -19942,13 +20230,13 @@ | |
| 20230 | static int regatom(regex_t *preg, int *flagp ); |
| 20231 | static int regnode(regex_t *preg, int op ); |
| 20232 | static int regnext(regex_t *preg, int p ); |
| 20233 | static void regc(regex_t *preg, int b ); |
| 20234 | static int reginsert(regex_t *preg, int op, int size, int opnd ); |
| 20235 | static void regtail(regex_t *preg, int p, int val); |
| 20236 | static void regoptail(regex_t *preg, int p, int val ); |
| 20237 | static int regopsize(regex_t *preg, int p ); |
| 20238 | |
| 20239 | static int reg_range_find(const int *string, int c); |
| 20240 | static const char *str_find(const char *string, int c, int nocase); |
| 20241 | static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); |
| 20242 | |
| @@ -19985,13 +20273,10 @@ | |
| 20273 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 20274 | |
| 20275 | |
| 20276 | preg->cflags = cflags; |
| 20277 | preg->regparse = exp; |
| 20278 | |
| 20279 | |
| 20280 | preg->proglen = (strlen(exp) + 1) * 5; |
| 20281 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 20282 | if (preg->program == NULL) |
| @@ -20152,11 +20437,10 @@ | |
| 20437 | { |
| 20438 | int ret; |
| 20439 | char op; |
| 20440 | int next; |
| 20441 | int flags; |
| 20442 | int min; |
| 20443 | int max; |
| 20444 | |
| 20445 | ret = regatom(preg, &flags); |
| 20446 | if (ret == 0) |
| @@ -20235,11 +20519,11 @@ | |
| 20519 | if (ISMULT(*preg->regparse)) { |
| 20520 | preg->err = REG_ERR_NESTED_COUNT; |
| 20521 | return 0; |
| 20522 | } |
| 20523 | |
| 20524 | return ret; |
| 20525 | } |
| 20526 | |
| 20527 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20528 | { |
| 20529 | if (lower > upper) { |
| @@ -20329,10 +20613,11 @@ | |
| 20613 | break; |
| 20614 | case 'U': |
| 20615 | if ((n = parse_hex(s, 8, ch)) > 0) { |
| 20616 | s += n; |
| 20617 | } |
| 20618 | break; |
| 20619 | case 'x': |
| 20620 | if ((n = parse_hex(s, 2, ch)) > 0) { |
| 20621 | s += n; |
| 20622 | } |
| 20623 | break; |
| @@ -20577,10 +20862,11 @@ | |
| 20862 | |
| 20863 | static int regnode(regex_t *preg, int op) |
| 20864 | { |
| 20865 | reg_grow(preg, 2); |
| 20866 | |
| 20867 | |
| 20868 | preg->program[preg->p++] = op; |
| 20869 | preg->program[preg->p++] = 0; |
| 20870 | |
| 20871 | |
| 20872 | return preg->p - 2; |
| @@ -20606,11 +20892,11 @@ | |
| 20892 | preg->p += size; |
| 20893 | |
| 20894 | return opnd + size; |
| 20895 | } |
| 20896 | |
| 20897 | static void regtail(regex_t *preg, int p, int val) |
| 20898 | { |
| 20899 | int scan; |
| 20900 | int temp; |
| 20901 | int offset; |
| 20902 | |
| @@ -20669,36 +20955,16 @@ | |
| 20955 | preg->pmatch = pmatch; |
| 20956 | preg->nmatch = nmatch; |
| 20957 | preg->start = string; |
| 20958 | |
| 20959 | |
| 20960 | for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { |
| 20961 | int op = OP(preg, scan); |
| 20962 | if (op == END) |
| 20963 | break; |
| 20964 | if (op == REPX || op == REPXMIN) |
| 20965 | preg->program[scan + 4] = 0; |
| 20966 | } |
| 20967 | |
| 20968 | |
| 20969 | if (preg->regmust != 0) { |
| 20970 | s = string; |
| @@ -20950,10 +21216,11 @@ | |
| 21216 | |
| 21217 | static int regmatch(regex_t *preg, int prog) |
| 21218 | { |
| 21219 | int scan; |
| 21220 | int next; |
| 21221 | const char *save; |
| 21222 | |
| 21223 | scan = prog; |
| 21224 | |
| 21225 | #ifdef DEBUG |
| 21226 | if (scan != 0 && regnarrate) |
| @@ -21038,27 +21305,24 @@ | |
| 21305 | break; |
| 21306 | case NOTHING: |
| 21307 | break; |
| 21308 | case BACK: |
| 21309 | break; |
| 21310 | case BRANCH: |
| 21311 | if (OP(preg, next) != BRANCH) |
| 21312 | next = OPERAND(scan); |
| 21313 | else { |
| 21314 | do { |
| 21315 | save = preg->reginput; |
| 21316 | if (regmatch(preg, OPERAND(scan))) { |
| 21317 | return(1); |
| 21318 | } |
| 21319 | preg->reginput = save; |
| 21320 | scan = regnext(preg, scan); |
| 21321 | } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21322 | return(0); |
| 21323 | |
| 21324 | } |
| 21325 | break; |
| 21326 | case REP: |
| 21327 | case REPMIN: |
| 21328 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21066,43 +21330,35 @@ | |
| 21330 | case REPX: |
| 21331 | case REPXMIN: |
| 21332 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21333 | |
| 21334 | case END: |
| 21335 | return 1; |
| 21336 | |
| 21337 | case OPENNC: |
| 21338 | case CLOSENC: |
| 21339 | return regmatch(preg, next); |
| 21340 | |
| 21341 | default: |
| 21342 | if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { |
| 21343 | save = preg->reginput; |
| 21344 | if (regmatch(preg, next)) { |
| 21345 | if (OP(preg, scan) < CLOSE) { |
| 21346 | int no = OP(preg, scan) - OPEN; |
| 21347 | if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { |
| 21348 | preg->pmatch[no].rm_so = save - preg->start; |
| 21349 | } |
| 21350 | } |
| 21351 | else { |
| 21352 | int no = OP(preg, scan) - CLOSE; |
| 21353 | if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { |
| 21354 | preg->pmatch[no].rm_eo = save - preg->start; |
| 21355 | } |
| 21356 | } |
| 21357 | return(1); |
| 21358 | } |
| 21359 | return(0); |
| 21360 | } |
| 21361 | return REG_ERR_INTERNAL; |
| 21362 | } |
| 21363 | |
| 21364 | scan = next; |
| @@ -21181,10 +21437,32 @@ | |
| 21437 | if (OP(preg, p) == BACK) |
| 21438 | return(p-offset); |
| 21439 | else |
| 21440 | return(p+offset); |
| 21441 | } |
| 21442 | |
| 21443 | static int regopsize(regex_t *preg, int p ) |
| 21444 | { |
| 21445 | |
| 21446 | switch (OP(preg, p)) { |
| 21447 | case REP: |
| 21448 | case REPMIN: |
| 21449 | case REPX: |
| 21450 | case REPXMIN: |
| 21451 | return 5; |
| 21452 | |
| 21453 | case ANYOF: |
| 21454 | case ANYBUT: |
| 21455 | case EXACTLY: { |
| 21456 | int s = p + 2; |
| 21457 | while (preg->program[s++]) { |
| 21458 | } |
| 21459 | return s - p; |
| 21460 | } |
| 21461 | } |
| 21462 | return 2; |
| 21463 | } |
| 21464 | |
| 21465 | |
| 21466 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 21467 | { |
| 21468 | static const char *error_strings[] = { |
| @@ -21359,19 +21637,24 @@ | |
| 21637 | char *Jim_HistoryGetline(const char *prompt) |
| 21638 | { |
| 21639 | #ifdef USE_LINENOISE |
| 21640 | return linenoise(prompt); |
| 21641 | #else |
| 21642 | int len; |
| 21643 | char *line = malloc(MAX_LINE_LEN); |
| 21644 | |
| 21645 | fputs(prompt, stdout); |
| 21646 | fflush(stdout); |
| 21647 | |
| 21648 | if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { |
| 21649 | free(line); |
| 21650 | return NULL; |
| 21651 | } |
| 21652 | len = strlen(line); |
| 21653 | if (len && line[len - 1] == '\n') { |
| 21654 | line[len - 1] = '\0'; |
| 21655 | } |
| 21656 | return line; |
| 21657 | #endif |
| 21658 | } |
| 21659 | |
| 21660 | void Jim_HistoryLoad(const char *filename) |
| @@ -21422,11 +21705,11 @@ | |
| 21705 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 21706 | Jim_HistoryLoad(history_file); |
| 21707 | } |
| 21708 | #endif |
| 21709 | |
| 21710 | printf("Welcome to Jim version %d.%d\n", |
| 21711 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 21712 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| 21713 | |
| 21714 | while (1) { |
| 21715 | Jim_Obj *scriptObjPtr; |
| @@ -21534,10 +21817,16 @@ | |
| 21817 | } |
| 21818 | |
| 21819 | Jim_SetVariableStr(interp, "argv", listObj); |
| 21820 | Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); |
| 21821 | } |
| 21822 | |
| 21823 | static void JimPrintErrorMessage(Jim_Interp *interp) |
| 21824 | { |
| 21825 | Jim_MakeErrorMessage(interp); |
| 21826 | fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21827 | } |
| 21828 | |
| 21829 | int main(int argc, char *const argv[]) |
| 21830 | { |
| 21831 | int retcode; |
| 21832 | Jim_Interp *interp; |
| @@ -21551,22 +21840,20 @@ | |
| 21840 | interp = Jim_CreateInterp(); |
| 21841 | Jim_RegisterCoreCommands(interp); |
| 21842 | |
| 21843 | |
| 21844 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 21845 | JimPrintErrorMessage(interp); |
| 21846 | } |
| 21847 | |
| 21848 | Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); |
| 21849 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 21850 | retcode = Jim_initjimshInit(interp); |
| 21851 | |
| 21852 | if (argc == 1) { |
| 21853 | if (retcode == JIM_ERR) { |
| 21854 | JimPrintErrorMessage(interp); |
| 21855 | } |
| 21856 | if (retcode != JIM_EXIT) { |
| 21857 | JimSetArgv(interp, 0, NULL); |
| 21858 | retcode = Jim_InteractivePrompt(interp); |
| 21859 | } |
| @@ -21583,12 +21870,11 @@ | |
| 21870 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 21871 | JimSetArgv(interp, argc - 2, argv + 2); |
| 21872 | retcode = Jim_EvalFile(interp, argv[1]); |
| 21873 | } |
| 21874 | if (retcode == JIM_ERR) { |
| 21875 | JimPrintErrorMessage(interp); |
| 21876 | } |
| 21877 | } |
| 21878 | if (retcode == JIM_EXIT) { |
| 21879 | retcode = Jim_GetExitCode(interp); |
| 21880 | } |
| 21881 |