| | @@ -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 |
| | @@ -42,14 +42,19 @@ |
| 42 | 42 | #define HAVE_ISATTY |
| 43 | 43 | #define HAVE_SYS_TIME_H |
| 44 | 44 | #define HAVE_DIRENT_H |
| 45 | 45 | #define HAVE_UNISTD_H |
| 46 | 46 | #endif |
| 47 | +#define JIM_VERSION 75 |
| 47 | 48 | #ifndef JIM_WIN32COMPAT_H |
| 48 | 49 | #define JIM_WIN32COMPAT_H |
| 49 | 50 | |
| 50 | 51 | |
| 52 | + |
| 53 | +#ifdef __cplusplus |
| 54 | +extern "C" { |
| 55 | +#endif |
| 51 | 56 | |
| 52 | 57 | |
| 53 | 58 | #if defined(_WIN32) || defined(WIN32) |
| 54 | 59 | |
| 55 | 60 | #define HAVE_DLOPEN |
| | @@ -105,17 +110,31 @@ |
| 105 | 110 | } DIR; |
| 106 | 111 | |
| 107 | 112 | DIR *opendir(const char *name); |
| 108 | 113 | int closedir(DIR *dir); |
| 109 | 114 | struct dirent *readdir(DIR *dir); |
| 110 | | -#endif |
| 115 | + |
| 116 | +#elif defined(__MINGW32__) |
| 117 | + |
| 118 | +#define strtod __strtod |
| 119 | + |
| 120 | +#endif |
| 111 | 121 | |
| 112 | 122 | #endif |
| 123 | + |
| 124 | +#ifdef __cplusplus |
| 125 | +} |
| 126 | +#endif |
| 113 | 127 | |
| 114 | 128 | #endif |
| 115 | 129 | #ifndef UTF8_UTIL_H |
| 116 | 130 | #define UTF8_UTIL_H |
| 131 | + |
| 132 | +#ifdef __cplusplus |
| 133 | +extern "C" { |
| 134 | +#endif |
| 135 | + |
| 117 | 136 | |
| 118 | 137 | |
| 119 | 138 | #define MAX_UTF8_LEN 4 |
| 120 | 139 | |
| 121 | 140 | int utf8_fromunicode(char *p, unsigned uc); |
| | @@ -124,10 +143,11 @@ |
| 124 | 143 | #include <ctype.h> |
| 125 | 144 | |
| 126 | 145 | |
| 127 | 146 | #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) |
| 128 | 147 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 148 | +#define utf8_getchars(CP, C) (*(CP) = (C), 1) |
| 129 | 149 | #define utf8_upper(C) toupper(C) |
| 130 | 150 | #define utf8_title(C) toupper(C) |
| 131 | 151 | #define utf8_lower(C) tolower(C) |
| 132 | 152 | #define utf8_index(C, I) (I) |
| 133 | 153 | #define utf8_charlen(C) 1 |
| | @@ -134,10 +154,14 @@ |
| 134 | 154 | #define utf8_prev_len(S, L) 1 |
| 135 | 155 | |
| 136 | 156 | #else |
| 137 | 157 | |
| 138 | 158 | #endif |
| 159 | + |
| 160 | +#ifdef __cplusplus |
| 161 | +} |
| 162 | +#endif |
| 139 | 163 | |
| 140 | 164 | #endif |
| 141 | 165 | |
| 142 | 166 | #ifndef __JIM__H |
| 143 | 167 | #define __JIM__H |
| | @@ -185,12 +209,10 @@ |
| 185 | 209 | #endif |
| 186 | 210 | |
| 187 | 211 | #define UCHAR(c) ((unsigned char)(c)) |
| 188 | 212 | |
| 189 | 213 | |
| 190 | | -#define JIM_VERSION 73 |
| 191 | | - |
| 192 | 214 | #define JIM_OK 0 |
| 193 | 215 | #define JIM_ERR 1 |
| 194 | 216 | #define JIM_RETURN 2 |
| 195 | 217 | #define JIM_BREAK 3 |
| 196 | 218 | #define JIM_CONTINUE 4 |
| | @@ -200,44 +222,34 @@ |
| 200 | 222 | #define JIM_EVAL 7 |
| 201 | 223 | |
| 202 | 224 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 203 | 225 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 204 | 226 | |
| 205 | | -#define JIM_NONE 0 |
| 206 | | -#define JIM_ERRMSG 1 |
| 207 | | - |
| 208 | | -#define JIM_UNSHARED 4 |
| 209 | | -#define JIM_MUSTEXIST 8 |
| 210 | | - |
| 211 | | - |
| 212 | | -#define JIM_GLOBAL_ONLY 0x100 |
| 227 | + |
| 228 | +#define JIM_PRIV_FLAG_SHIFT 20 |
| 229 | + |
| 230 | +#define JIM_NONE 0 |
| 231 | +#define JIM_ERRMSG 1 |
| 232 | +#define JIM_ENUM_ABBREV 2 |
| 233 | +#define JIM_UNSHARED 4 |
| 234 | +#define JIM_MUSTEXIST 8 |
| 213 | 235 | |
| 214 | 236 | |
| 215 | 237 | #define JIM_SUBST_NOVAR 1 |
| 216 | 238 | #define JIM_SUBST_NOCMD 2 |
| 217 | 239 | #define JIM_SUBST_NOESC 4 |
| 218 | 240 | #define JIM_SUBST_FLAG 128 |
| 219 | 241 | |
| 220 | | - |
| 221 | | -#define JIM_NOTUSED(V) ((void) V) |
| 222 | | - |
| 223 | | - |
| 224 | | -#define JIM_ENUM_ABBREV 2 |
| 225 | | - |
| 226 | 242 | |
| 227 | 243 | #define JIM_CASESENS 0 |
| 228 | 244 | #define JIM_NOCASE 1 |
| 229 | 245 | |
| 230 | 246 | |
| 231 | 247 | #define JIM_PATH_LEN 1024 |
| 232 | 248 | |
| 233 | 249 | |
| 234 | | -#ifdef JIM_CRLF |
| 235 | | -#define JIM_NL "\r\n" |
| 236 | | -#else |
| 237 | | -#define JIM_NL "\n" |
| 238 | | -#endif |
| 250 | +#define JIM_NOTUSED(V) ((void) V) |
| 239 | 251 | |
| 240 | 252 | #define JIM_LIBPATH "auto_path" |
| 241 | 253 | #define JIM_INTERACTIVE "tcl_interactive" |
| 242 | 254 | |
| 243 | 255 | |
| | @@ -267,21 +279,22 @@ |
| 267 | 279 | } Jim_HashTableType; |
| 268 | 280 | |
| 269 | 281 | typedef struct Jim_HashTable { |
| 270 | 282 | Jim_HashEntry **table; |
| 271 | 283 | const Jim_HashTableType *type; |
| 284 | + void *privdata; |
| 272 | 285 | unsigned int size; |
| 273 | 286 | unsigned int sizemask; |
| 274 | 287 | unsigned int used; |
| 275 | 288 | unsigned int collisions; |
| 276 | | - void *privdata; |
| 289 | + unsigned int uniq; |
| 277 | 290 | } Jim_HashTable; |
| 278 | 291 | |
| 279 | 292 | typedef struct Jim_HashTableIterator { |
| 280 | 293 | Jim_HashTable *ht; |
| 281 | | - int index; |
| 282 | 294 | Jim_HashEntry *entry, *nextEntry; |
| 295 | + int index; |
| 283 | 296 | } Jim_HashTableIterator; |
| 284 | 297 | |
| 285 | 298 | |
| 286 | 299 | #define JIM_HT_INITIAL_SIZE 16 |
| 287 | 300 | |
| | @@ -290,45 +303,45 @@ |
| 290 | 303 | if ((ht)->type->valDestructor) \ |
| 291 | 304 | (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) |
| 292 | 305 | |
| 293 | 306 | #define Jim_SetHashVal(ht, entry, _val_) do { \ |
| 294 | 307 | if ((ht)->type->valDup) \ |
| 295 | | - entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ |
| 308 | + (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ |
| 296 | 309 | else \ |
| 297 | | - entry->u.val = (_val_); \ |
| 310 | + (entry)->u.val = (_val_); \ |
| 298 | 311 | } while(0) |
| 299 | 312 | |
| 300 | 313 | #define Jim_FreeEntryKey(ht, entry) \ |
| 301 | 314 | if ((ht)->type->keyDestructor) \ |
| 302 | 315 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) |
| 303 | 316 | |
| 304 | 317 | #define Jim_SetHashKey(ht, entry, _key_) do { \ |
| 305 | 318 | if ((ht)->type->keyDup) \ |
| 306 | | - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ |
| 319 | + (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \ |
| 307 | 320 | else \ |
| 308 | | - entry->key = (void *)(_key_); \ |
| 321 | + (entry)->key = (void *)(_key_); \ |
| 309 | 322 | } while(0) |
| 310 | 323 | |
| 311 | 324 | #define Jim_CompareHashKeys(ht, key1, key2) \ |
| 312 | 325 | (((ht)->type->keyCompare) ? \ |
| 313 | | - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ |
| 326 | + (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \ |
| 314 | 327 | (key1) == (key2)) |
| 315 | 328 | |
| 316 | | -#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) |
| 329 | +#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) |
| 317 | 330 | |
| 318 | 331 | #define Jim_GetHashEntryKey(he) ((he)->key) |
| 319 | | -#define Jim_GetHashEntryVal(he) ((he)->val) |
| 332 | +#define Jim_GetHashEntryVal(he) ((he)->u.val) |
| 320 | 333 | #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) |
| 321 | 334 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 322 | 335 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 323 | 336 | |
| 324 | 337 | |
| 325 | 338 | typedef struct Jim_Obj { |
| 326 | | - int refCount; |
| 327 | 339 | char *bytes; |
| 328 | | - int length; |
| 329 | 340 | const struct Jim_ObjType *typePtr; |
| 341 | + int refCount; |
| 342 | + int length; |
| 330 | 343 | |
| 331 | 344 | union { |
| 332 | 345 | |
| 333 | 346 | jim_wide wideValue; |
| 334 | 347 | |
| | @@ -342,19 +355,19 @@ |
| 342 | 355 | void *ptr1; |
| 343 | 356 | void *ptr2; |
| 344 | 357 | } twoPtrValue; |
| 345 | 358 | |
| 346 | 359 | struct { |
| 347 | | - unsigned long callFrameId; |
| 348 | 360 | struct Jim_Var *varPtr; |
| 361 | + unsigned long callFrameId; |
| 349 | 362 | int global; |
| 350 | 363 | } varValue; |
| 351 | 364 | |
| 352 | 365 | struct { |
| 353 | | - unsigned long procEpoch; |
| 354 | 366 | struct Jim_Obj *nsObj; |
| 355 | 367 | struct Jim_Cmd *cmdPtr; |
| 368 | + unsigned long procEpoch; |
| 356 | 369 | } cmdValue; |
| 357 | 370 | |
| 358 | 371 | struct { |
| 359 | 372 | struct Jim_Obj **ele; |
| 360 | 373 | int len; |
| | @@ -380,12 +393,12 @@ |
| 380 | 393 | struct Jim_Obj *varNameObjPtr; |
| 381 | 394 | struct Jim_Obj *indexObjPtr; |
| 382 | 395 | } dictSubstValue; |
| 383 | 396 | |
| 384 | 397 | struct { |
| 385 | | - unsigned flags; |
| 386 | 398 | void *compre; |
| 399 | + unsigned flags; |
| 387 | 400 | } regexpValue; |
| 388 | 401 | struct { |
| 389 | 402 | int line; |
| 390 | 403 | int argc; |
| 391 | 404 | } scriptLineValue; |
| | @@ -454,21 +467,24 @@ |
| 454 | 467 | struct Jim_CallFrame *next; |
| 455 | 468 | Jim_Obj *nsObj; |
| 456 | 469 | Jim_Obj *fileNameObj; |
| 457 | 470 | int line; |
| 458 | 471 | Jim_Stack *localCommands; |
| 472 | + int tailcall; |
| 473 | + struct Jim_Obj *tailcallObj; |
| 474 | + struct Jim_Cmd *tailcallCmd; |
| 459 | 475 | } Jim_CallFrame; |
| 460 | 476 | |
| 461 | 477 | typedef struct Jim_Var { |
| 462 | 478 | Jim_Obj *objPtr; |
| 463 | 479 | struct Jim_CallFrame *linkFramePtr; |
| 464 | 480 | } Jim_Var; |
| 465 | 481 | |
| 466 | 482 | |
| 467 | | -typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, |
| 483 | +typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, |
| 468 | 484 | Jim_Obj *const *argv); |
| 469 | | -typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); |
| 485 | +typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 470 | 486 | |
| 471 | 487 | |
| 472 | 488 | |
| 473 | 489 | typedef struct Jim_Cmd { |
| 474 | 490 | int inUse; |
| | @@ -475,12 +491,12 @@ |
| 475 | 491 | int isproc; |
| 476 | 492 | struct Jim_Cmd *prevCmd; |
| 477 | 493 | union { |
| 478 | 494 | struct { |
| 479 | 495 | |
| 480 | | - Jim_CmdProc cmdProc; |
| 481 | | - Jim_DelCmdProc delProc; |
| 496 | + Jim_CmdProc *cmdProc; |
| 497 | + Jim_DelCmdProc *delProc; |
| 482 | 498 | void *privData; |
| 483 | 499 | } native; |
| 484 | 500 | struct { |
| 485 | 501 | |
| 486 | 502 | Jim_Obj *argListObjPtr; |
| | @@ -590,15 +606,11 @@ |
| 590 | 606 | Jim_Obj *finalizerCmdNamePtr; |
| 591 | 607 | char tag[JIM_REFERENCE_TAGLEN+1]; |
| 592 | 608 | } Jim_Reference; |
| 593 | 609 | |
| 594 | 610 | |
| 595 | | - |
| 596 | 611 | #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) |
| 597 | | - |
| 598 | | - |
| 599 | | - |
| 600 | 612 | #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) |
| 601 | 613 | |
| 602 | 614 | #define JIM_EXPORT |
| 603 | 615 | |
| 604 | 616 | |
| | @@ -609,10 +621,11 @@ |
| 609 | 621 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 610 | 622 | |
| 611 | 623 | |
| 612 | 624 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 613 | 625 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 626 | +JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); |
| 614 | 627 | |
| 615 | 628 | |
| 616 | 629 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 617 | 630 | |
| 618 | 631 | |
| | @@ -665,12 +678,10 @@ |
| 665 | 678 | |
| 666 | 679 | |
| 667 | 680 | JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); |
| 668 | 681 | JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); |
| 669 | 682 | JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); |
| 670 | | -JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes, |
| 671 | | - int length); |
| 672 | 683 | JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, |
| 673 | 684 | Jim_Obj *objPtr); |
| 674 | 685 | JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, |
| 675 | 686 | int *lenPtr); |
| 676 | 687 | JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr); |
| | @@ -742,13 +753,12 @@ |
| 742 | 753 | JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, |
| 743 | 754 | const char *name, const char *val); |
| 744 | 755 | JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, |
| 745 | 756 | Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, |
| 746 | 757 | Jim_CallFrame *targetCallFrame); |
| 747 | | -JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp, |
| 748 | | - Jim_Obj *varNameObj, Jim_Obj *targetNameObj); |
| 749 | | -JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp); |
| 758 | +JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp, |
| 759 | + Jim_Obj *nameObjPtr); |
| 750 | 760 | JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, |
| 751 | 761 | Jim_Obj *nameObjPtr, int flags); |
| 752 | 762 | JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, |
| 753 | 763 | Jim_Obj *nameObjPtr, int flags); |
| 754 | 764 | JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, |
| | @@ -807,10 +817,11 @@ |
| 807 | 817 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 808 | 818 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 809 | 819 | JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); |
| 810 | 820 | JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); |
| 811 | 821 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 822 | +JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); |
| 812 | 823 | |
| 813 | 824 | |
| 814 | 825 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 815 | 826 | int *intPtr); |
| 816 | 827 | |
| | @@ -834,16 +845,10 @@ |
| 834 | 845 | double *doublePtr); |
| 835 | 846 | JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, |
| 836 | 847 | double doubleValue); |
| 837 | 848 | JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); |
| 838 | 849 | |
| 839 | | - |
| 840 | | -JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp, |
| 841 | | - const char *str); |
| 842 | | -JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp, |
| 843 | | - const char *str); |
| 844 | | - |
| 845 | 850 | |
| 846 | 851 | JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, |
| 847 | 852 | Jim_Obj *const *argv, const char *msg); |
| 848 | 853 | JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, |
| 849 | 854 | const char * const *tablePtr, int *indexPtr, const char *name, int flags); |
| | @@ -877,18 +882,20 @@ |
| 877 | 882 | JIM_EXPORT void Jim_HistoryShow(void); |
| 878 | 883 | |
| 879 | 884 | |
| 880 | 885 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| 881 | 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) |
| 882 | 890 | |
| 883 | 891 | |
| 884 | 892 | JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); |
| 885 | 893 | JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); |
| 886 | 894 | |
| 887 | 895 | |
| 888 | 896 | JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 889 | | - |
| 890 | 897 | |
| 891 | 898 | |
| 892 | 899 | JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); |
| 893 | 900 | JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); |
| 894 | 901 | |
| | @@ -910,16 +917,16 @@ |
| 910 | 917 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 911 | 918 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 912 | 919 | |
| 913 | 920 | |
| 914 | 921 | |
| 915 | | -typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 922 | +typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 916 | 923 | |
| 917 | 924 | typedef struct { |
| 918 | 925 | const char *cmd; |
| 919 | 926 | const char *args; |
| 920 | | - tclmod_cmd_function *function; |
| 927 | + jim_subcmd_function *function; |
| 921 | 928 | short minargs; |
| 922 | 929 | short maxargs; |
| 923 | 930 | unsigned short flags; |
| 924 | 931 | } jim_subcmd_type; |
| 925 | 932 | |
| | @@ -936,22 +943,16 @@ |
| 936 | 943 | |
| 937 | 944 | #endif |
| 938 | 945 | #ifndef JIMREGEXP_H |
| 939 | 946 | #define JIMREGEXP_H |
| 940 | 947 | |
| 941 | | -#ifndef _JIMAUTOCONF_H |
| 942 | | -#error Need jimautoconf.h |
| 948 | + |
| 949 | +#ifdef __cplusplus |
| 950 | +extern "C" { |
| 943 | 951 | #endif |
| 944 | 952 | |
| 945 | | -#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP) |
| 946 | | - |
| 947 | | -#include <regex.h> |
| 948 | | - |
| 949 | | -#else |
| 950 | | - |
| 951 | 953 | #include <stdlib.h> |
| 952 | | - |
| 953 | 954 | |
| 954 | 955 | typedef struct { |
| 955 | 956 | int rm_so; |
| 956 | 957 | int rm_eo; |
| 957 | 958 | } regmatch_t; |
| | @@ -1020,10 +1021,12 @@ |
| 1020 | 1021 | int regcomp(regex_t *preg, const char *regex, int cflags); |
| 1021 | 1022 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1022 | 1023 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1023 | 1024 | void regfree(regex_t *preg); |
| 1024 | 1025 | |
| 1026 | +#ifdef __cplusplus |
| 1027 | +} |
| 1025 | 1028 | #endif |
| 1026 | 1029 | |
| 1027 | 1030 | #endif |
| 1028 | 1031 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1029 | 1032 | { |
| | @@ -1086,10 +1089,15 @@ |
| 1086 | 1089 | "\n" |
| 1087 | 1090 | "package require readdir\n" |
| 1088 | 1091 | "\n" |
| 1089 | 1092 | "\n" |
| 1090 | 1093 | "proc glob.globdir {dir pattern} {\n" |
| 1094 | +" if {[file exists $dir/$pattern]} {\n" |
| 1095 | +"\n" |
| 1096 | +" return $pattern\n" |
| 1097 | +" }\n" |
| 1098 | +"\n" |
| 1091 | 1099 | " set result {}\n" |
| 1092 | 1100 | " set files [readdir $dir]\n" |
| 1093 | 1101 | " lappend files . ..\n" |
| 1094 | 1102 | "\n" |
| 1095 | 1103 | " foreach name $files {\n" |
| | @@ -1268,10 +1276,12 @@ |
| 1268 | 1276 | { |
| 1269 | 1277 | if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) |
| 1270 | 1278 | return JIM_ERR; |
| 1271 | 1279 | |
| 1272 | 1280 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1281 | +"\n" |
| 1282 | +"\n" |
| 1273 | 1283 | "\n" |
| 1274 | 1284 | "proc lambda {arglist args} {\n" |
| 1275 | 1285 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1276 | 1286 | "}\n" |
| 1277 | 1287 | "\n" |
| | @@ -1297,46 +1307,48 @@ |
| 1297 | 1307 | "}\n" |
| 1298 | 1308 | "\n" |
| 1299 | 1309 | "\n" |
| 1300 | 1310 | "\n" |
| 1301 | 1311 | "\n" |
| 1302 | | -"proc stacktrace {} {\n" |
| 1312 | +"proc stacktrace {{skip 0}} {\n" |
| 1303 | 1313 | " set trace {}\n" |
| 1304 | | -" foreach level [range 1 [info level]] {\n" |
| 1305 | | -" lassign [info frame -$level] p f l\n" |
| 1306 | | -" lappend trace $p $f $l\n" |
| 1314 | +" incr skip\n" |
| 1315 | +" foreach level [range $skip [info level]] {\n" |
| 1316 | +" lappend trace {*}[info frame -$level]\n" |
| 1307 | 1317 | " }\n" |
| 1308 | 1318 | " return $trace\n" |
| 1309 | 1319 | "}\n" |
| 1310 | 1320 | "\n" |
| 1311 | 1321 | "\n" |
| 1312 | 1322 | "proc stackdump {stacktrace} {\n" |
| 1313 | | -" set result {}\n" |
| 1314 | | -" set count 0\n" |
| 1323 | +" set lines {}\n" |
| 1315 | 1324 | " foreach {l f p} [lreverse $stacktrace] {\n" |
| 1316 | | -" if {$count} {\n" |
| 1317 | | -" append result \\n\n" |
| 1318 | | -" }\n" |
| 1319 | | -" incr count\n" |
| 1325 | +" set line {}\n" |
| 1320 | 1326 | " if {$p ne \"\"} {\n" |
| 1321 | | -" append result \"in procedure '$p' \"\n" |
| 1327 | +" append line \"in procedure '$p' \"\n" |
| 1322 | 1328 | " if {$f ne \"\"} {\n" |
| 1323 | | -" append result \"called \"\n" |
| 1329 | +" append line \"called \"\n" |
| 1324 | 1330 | " }\n" |
| 1325 | 1331 | " }\n" |
| 1326 | 1332 | " if {$f ne \"\"} {\n" |
| 1327 | | -" append result \"at file \\\"$f\\\", line $l\"\n" |
| 1333 | +" append line \"at file \\\"$f\\\", line $l\"\n" |
| 1334 | +" }\n" |
| 1335 | +" if {$line ne \"\"} {\n" |
| 1336 | +" lappend lines $line\n" |
| 1328 | 1337 | " }\n" |
| 1329 | 1338 | " }\n" |
| 1330 | | -" return $result\n" |
| 1339 | +" join $lines \\n\n" |
| 1331 | 1340 | "}\n" |
| 1332 | 1341 | "\n" |
| 1333 | 1342 | "\n" |
| 1334 | 1343 | "\n" |
| 1335 | 1344 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1336 | 1345 | " if {$stacktrace eq \"\"} {\n" |
| 1346 | +"\n" |
| 1337 | 1347 | " set stacktrace [info stacktrace]\n" |
| 1348 | +"\n" |
| 1349 | +" lappend stacktrace {*}[stacktrace 1]\n" |
| 1338 | 1350 | " }\n" |
| 1339 | 1351 | " lassign $stacktrace p f l\n" |
| 1340 | 1352 | " if {$f ne \"\"} {\n" |
| 1341 | 1353 | " set result \"Runtime Error: $f:$l: \"\n" |
| 1342 | 1354 | " }\n" |
| | @@ -1363,25 +1375,46 @@ |
| 1363 | 1375 | " }\n" |
| 1364 | 1376 | " return \"\"\n" |
| 1365 | 1377 | "}\n" |
| 1366 | 1378 | "\n" |
| 1367 | 1379 | "\n" |
| 1368 | | -"proc {dict with} {dictVar args script} {\n" |
| 1369 | | -" upvar $dictVar dict\n" |
| 1380 | +"proc {dict with} {&dictVar {args key} script} {\n" |
| 1370 | 1381 | " set keys {}\n" |
| 1371 | | -" foreach {n v} [dict get $dict {*}$args] {\n" |
| 1382 | +" foreach {n v} [dict get $dictVar {*}$key] {\n" |
| 1372 | 1383 | " upvar $n var_$n\n" |
| 1373 | 1384 | " set var_$n $v\n" |
| 1374 | 1385 | " lappend keys $n\n" |
| 1375 | 1386 | " }\n" |
| 1376 | 1387 | " catch {uplevel 1 $script} msg opts\n" |
| 1377 | | -" if {[info exists dict] && [dict exists $dict {*}$args]} {\n" |
| 1388 | +" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" |
| 1378 | 1389 | " foreach n $keys {\n" |
| 1379 | 1390 | " if {[info exists var_$n]} {\n" |
| 1380 | | -" dict set dict {*}$args $n [set var_$n]\n" |
| 1391 | +" dict set dictVar {*}$key $n [set var_$n]\n" |
| 1392 | +" } else {\n" |
| 1393 | +" dict unset dictVar {*}$key $n\n" |
| 1394 | +" }\n" |
| 1395 | +" }\n" |
| 1396 | +" }\n" |
| 1397 | +" return {*}$opts $msg\n" |
| 1398 | +"}\n" |
| 1399 | +"\n" |
| 1400 | +"\n" |
| 1401 | +"proc {dict update} {&varName args script} {\n" |
| 1402 | +" set keys {}\n" |
| 1403 | +" foreach {n v} $args {\n" |
| 1404 | +" upvar $v var_$v\n" |
| 1405 | +" if {[dict exists $varName $n]} {\n" |
| 1406 | +" set var_$v [dict get $varName $n]\n" |
| 1407 | +" }\n" |
| 1408 | +" }\n" |
| 1409 | +" catch {uplevel 1 $script} msg opts\n" |
| 1410 | +" if {[info exists varName]} {\n" |
| 1411 | +" foreach {n v} $args {\n" |
| 1412 | +" if {[info exists var_$v]} {\n" |
| 1413 | +" dict set varName $n [set var_$v]\n" |
| 1381 | 1414 | " } else {\n" |
| 1382 | | -" dict unset dict {*}$args $n\n" |
| 1415 | +" dict unset varName $n\n" |
| 1383 | 1416 | " }\n" |
| 1384 | 1417 | " }\n" |
| 1385 | 1418 | " }\n" |
| 1386 | 1419 | " return {*}$opts $msg\n" |
| 1387 | 1420 | "}\n" |
| | @@ -1396,10 +1429,69 @@ |
| 1396 | 1429 | " dict set dict $k $v\n" |
| 1397 | 1430 | " }\n" |
| 1398 | 1431 | " }\n" |
| 1399 | 1432 | " return $dict\n" |
| 1400 | 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" |
| 1401 | 1493 | ); |
| 1402 | 1494 | } |
| 1403 | 1495 | int Jim_tclcompatInit(Jim_Interp *interp) |
| 1404 | 1496 | { |
| 1405 | 1497 | if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG)) |
| | @@ -1410,12 +1502,14 @@ |
| 1410 | 1502 | "\n" |
| 1411 | 1503 | "\n" |
| 1412 | 1504 | "\n" |
| 1413 | 1505 | "\n" |
| 1414 | 1506 | "\n" |
| 1507 | +"\n" |
| 1415 | 1508 | "\n" |
| 1416 | 1509 | "set env [env]\n" |
| 1510 | +"\n" |
| 1417 | 1511 | "\n" |
| 1418 | 1512 | "if {[info commands stdout] ne \"\"} {\n" |
| 1419 | 1513 | "\n" |
| 1420 | 1514 | " foreach p {gets flush close eof seek tell} {\n" |
| 1421 | 1515 | " proc $p {chan args} {p} {\n" |
| | @@ -1462,51 +1556,10 @@ |
| 1462 | 1556 | " }\n" |
| 1463 | 1557 | " }\n" |
| 1464 | 1558 | " }\n" |
| 1465 | 1559 | "}\n" |
| 1466 | 1560 | "\n" |
| 1467 | | -"\n" |
| 1468 | | -"proc case {var args} {\n" |
| 1469 | | -"\n" |
| 1470 | | -" if {[lindex $args 0] eq \"in\"} {\n" |
| 1471 | | -" set args [lrange $args 1 end]\n" |
| 1472 | | -" }\n" |
| 1473 | | -"\n" |
| 1474 | | -"\n" |
| 1475 | | -" if {[llength $args] == 1} {\n" |
| 1476 | | -" set args [lindex $args 0]\n" |
| 1477 | | -" }\n" |
| 1478 | | -"\n" |
| 1479 | | -"\n" |
| 1480 | | -" if {[llength $args] % 2 != 0} {\n" |
| 1481 | | -" return -code error \"extra case pattern with no body\"\n" |
| 1482 | | -" }\n" |
| 1483 | | -"\n" |
| 1484 | | -"\n" |
| 1485 | | -" local proc case.checker {value pattern} {\n" |
| 1486 | | -" string match $pattern $value\n" |
| 1487 | | -" }\n" |
| 1488 | | -"\n" |
| 1489 | | -" foreach {value action} $args {\n" |
| 1490 | | -" if {$value eq \"default\"} {\n" |
| 1491 | | -" set do_action $action\n" |
| 1492 | | -" continue\n" |
| 1493 | | -" } elseif {[lsearch -bool -command case.checker $value $var]} {\n" |
| 1494 | | -" set do_action $action\n" |
| 1495 | | -" break\n" |
| 1496 | | -" }\n" |
| 1497 | | -" }\n" |
| 1498 | | -"\n" |
| 1499 | | -" if {[info exists do_action]} {\n" |
| 1500 | | -" set rc [catch [list uplevel 1 $do_action] result opts]\n" |
| 1501 | | -" if {$rc} {\n" |
| 1502 | | -" incr opts(-level)\n" |
| 1503 | | -" }\n" |
| 1504 | | -" return {*}$opts $result\n" |
| 1505 | | -" }\n" |
| 1506 | | -"}\n" |
| 1507 | | -"\n" |
| 1508 | 1561 | "\n" |
| 1509 | 1562 | "proc fileevent {args} {\n" |
| 1510 | 1563 | " tailcall {*}$args\n" |
| 1511 | 1564 | "}\n" |
| 1512 | 1565 | "\n" |
| | @@ -1536,13 +1589,25 @@ |
| 1536 | 1589 | " error \"bad option \\\"$force\\\": should be -force\"\n" |
| 1537 | 1590 | " }\n" |
| 1538 | 1591 | "\n" |
| 1539 | 1592 | " set in [open $source]\n" |
| 1540 | 1593 | "\n" |
| 1541 | | -" if {$force eq \"\" && [file exists $target]} {\n" |
| 1542 | | -" $in close\n" |
| 1543 | | -" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" |
| 1594 | +" if {[file exists $target]} {\n" |
| 1595 | +" if {$force eq \"\"} {\n" |
| 1596 | +" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" |
| 1597 | +" }\n" |
| 1598 | +"\n" |
| 1599 | +" if {$source eq $target} {\n" |
| 1600 | +" return\n" |
| 1601 | +" }\n" |
| 1602 | +"\n" |
| 1603 | +"\n" |
| 1604 | +" file stat $source ss\n" |
| 1605 | +" file stat $target ts\n" |
| 1606 | +" if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n" |
| 1607 | +" return\n" |
| 1608 | +" }\n" |
| 1544 | 1609 | " }\n" |
| 1545 | 1610 | " set out [open $target w]\n" |
| 1546 | 1611 | " $in copyto $out\n" |
| 1547 | 1612 | " $out close\n" |
| 1548 | 1613 | " } on error {msg opts} {\n" |
| | @@ -1587,18 +1652,18 @@ |
| 1587 | 1652 | " error $error\n" |
| 1588 | 1653 | " }\n" |
| 1589 | 1654 | "}\n" |
| 1590 | 1655 | "\n" |
| 1591 | 1656 | "\n" |
| 1592 | | -"local proc pid {{chan {}}} {\n" |
| 1593 | | -" if {$chan eq \"\"} {\n" |
| 1657 | +"local proc pid {{channelId {}}} {\n" |
| 1658 | +" if {$channelId eq \"\"} {\n" |
| 1594 | 1659 | " tailcall upcall pid\n" |
| 1595 | 1660 | " }\n" |
| 1596 | | -" if {[catch {$chan tell}]} {\n" |
| 1597 | | -" return -code error \"can not find channel named \\\"$chan\\\"\"\n" |
| 1661 | +" if {[catch {$channelId tell}]} {\n" |
| 1662 | +" return -code error \"can not find channel named \\\"$channelId\\\"\"\n" |
| 1598 | 1663 | " }\n" |
| 1599 | | -" if {[catch {$chan pid} pids]} {\n" |
| 1664 | +" if {[catch {$channelId pid} pids]} {\n" |
| 1600 | 1665 | " return \"\"\n" |
| 1601 | 1666 | " }\n" |
| 1602 | 1667 | " return $pids\n" |
| 1603 | 1668 | "}\n" |
| 1604 | 1669 | "\n" |
| | @@ -1687,23 +1752,25 @@ |
| 1687 | 1752 | "}\n" |
| 1688 | 1753 | ); |
| 1689 | 1754 | } |
| 1690 | 1755 | |
| 1691 | 1756 | |
| 1692 | | - |
| 1693 | 1757 | #include <stdio.h> |
| 1694 | 1758 | #include <string.h> |
| 1695 | 1759 | #include <errno.h> |
| 1696 | 1760 | #include <fcntl.h> |
| 1761 | +#ifdef HAVE_UNISTD_H |
| 1762 | +#include <unistd.h> |
| 1763 | +#include <sys/stat.h> |
| 1764 | +#endif |
| 1697 | 1765 | |
| 1698 | 1766 | |
| 1699 | 1767 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1700 | 1768 | #include <sys/socket.h> |
| 1701 | 1769 | #include <netinet/in.h> |
| 1702 | 1770 | #include <arpa/inet.h> |
| 1703 | 1771 | #include <netdb.h> |
| 1704 | | -#include <unistd.h> |
| 1705 | 1772 | #ifdef HAVE_SYS_UN_H |
| 1706 | 1773 | #include <sys/un.h> |
| 1707 | 1774 | #endif |
| 1708 | 1775 | #else |
| 1709 | 1776 | #define JIM_ANSIC |
| | @@ -1735,15 +1802,12 @@ |
| 1735 | 1802 | typedef struct AioFile |
| 1736 | 1803 | { |
| 1737 | 1804 | FILE *fp; |
| 1738 | 1805 | Jim_Obj *filename; |
| 1739 | 1806 | int type; |
| 1740 | | - int OpenFlags; |
| 1807 | + int openFlags; |
| 1741 | 1808 | int fd; |
| 1742 | | -#ifdef O_NDELAY |
| 1743 | | - int flags; |
| 1744 | | -#endif |
| 1745 | 1809 | Jim_Obj *rEvent; |
| 1746 | 1810 | Jim_Obj *wEvent; |
| 1747 | 1811 | Jim_Obj *eEvent; |
| 1748 | 1812 | int addr_family; |
| 1749 | 1813 | } AioFile; |
| | @@ -1767,28 +1831,21 @@ |
| 1767 | 1831 | { |
| 1768 | 1832 | AioFile *af = privData; |
| 1769 | 1833 | |
| 1770 | 1834 | JIM_NOTUSED(interp); |
| 1771 | 1835 | |
| 1772 | | - if (!(af->OpenFlags & AIO_KEEPOPEN)) { |
| 1773 | | - fclose(af->fp); |
| 1774 | | - } |
| 1775 | | - |
| 1776 | 1836 | Jim_DecrRefCount(interp, af->filename); |
| 1777 | 1837 | |
| 1778 | 1838 | #ifdef jim_ext_eventloop |
| 1779 | 1839 | |
| 1780 | | - if (af->rEvent) { |
| 1781 | | - Jim_DeleteFileHandler(interp, af->fp); |
| 1782 | | - } |
| 1783 | | - if (af->wEvent) { |
| 1784 | | - Jim_DeleteFileHandler(interp, af->fp); |
| 1785 | | - } |
| 1786 | | - if (af->eEvent) { |
| 1787 | | - Jim_DeleteFileHandler(interp, af->fp); |
| 1788 | | - } |
| 1789 | | -#endif |
| 1840 | + Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 1841 | +#endif |
| 1842 | + |
| 1843 | + if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 1844 | + fclose(af->fp); |
| 1845 | + } |
| 1846 | + |
| 1790 | 1847 | Jim_Free(af); |
| 1791 | 1848 | } |
| 1792 | 1849 | |
| 1793 | 1850 | static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) |
| 1794 | 1851 | { |
| | @@ -2035,12 +2092,31 @@ |
| 2035 | 2092 | return JIM_OK; |
| 2036 | 2093 | } |
| 2037 | 2094 | |
| 2038 | 2095 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2039 | 2096 | { |
| 2040 | | - Jim_DeleteCommand(interp, Jim_String(argv[0])); |
| 2041 | | - return JIM_OK; |
| 2097 | + if (argc == 3) { |
| 2098 | +#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) |
| 2099 | + static const char * const options[] = { "r", "w", NULL }; |
| 2100 | + enum { OPT_R, OPT_W, }; |
| 2101 | + int option; |
| 2102 | + AioFile *af = Jim_CmdPrivData(interp); |
| 2103 | + |
| 2104 | + if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2105 | + return JIM_ERR; |
| 2106 | + } |
| 2107 | + if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { |
| 2108 | + return JIM_OK; |
| 2109 | + } |
| 2110 | + JimAioSetError(interp, NULL); |
| 2111 | +#else |
| 2112 | + Jim_SetResultString(interp, "async close not supported", -1); |
| 2113 | +#endif |
| 2114 | + return JIM_ERR; |
| 2115 | + } |
| 2116 | + |
| 2117 | + return Jim_DeleteCommand(interp, Jim_String(argv[0])); |
| 2042 | 2118 | } |
| 2043 | 2119 | |
| 2044 | 2120 | static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2045 | 2121 | { |
| 2046 | 2122 | AioFile *af = Jim_CmdPrivData(interp); |
| | @@ -2087,11 +2163,11 @@ |
| 2087 | 2163 | #ifdef O_NDELAY |
| 2088 | 2164 | static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2089 | 2165 | { |
| 2090 | 2166 | AioFile *af = Jim_CmdPrivData(interp); |
| 2091 | 2167 | |
| 2092 | | - int fmode = af->flags; |
| 2168 | + int fmode = fcntl(af->fd, F_GETFL); |
| 2093 | 2169 | |
| 2094 | 2170 | if (argc) { |
| 2095 | 2171 | long nb; |
| 2096 | 2172 | |
| 2097 | 2173 | if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { |
| | @@ -2101,12 +2177,11 @@ |
| 2101 | 2177 | fmode |= O_NDELAY; |
| 2102 | 2178 | } |
| 2103 | 2179 | else { |
| 2104 | 2180 | fmode &= ~O_NDELAY; |
| 2105 | 2181 | } |
| 2106 | | - fcntl(af->fd, F_SETFL, fmode); |
| 2107 | | - af->flags = fmode; |
| 2182 | + (void)fcntl(af->fd, F_SETFL, fmode); |
| 2108 | 2183 | } |
| 2109 | 2184 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2110 | 2185 | return JIM_OK; |
| 2111 | 2186 | } |
| 2112 | 2187 | #endif |
| | @@ -2147,27 +2222,26 @@ |
| 2147 | 2222 | } |
| 2148 | 2223 | |
| 2149 | 2224 | #ifdef jim_ext_eventloop |
| 2150 | 2225 | static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData) |
| 2151 | 2226 | { |
| 2152 | | - Jim_Obj *objPtr = clientData; |
| 2227 | + Jim_Obj **objPtrPtr = clientData; |
| 2153 | 2228 | |
| 2154 | | - Jim_DecrRefCount(interp, objPtr); |
| 2229 | + Jim_DecrRefCount(interp, *objPtrPtr); |
| 2230 | + *objPtrPtr = NULL; |
| 2155 | 2231 | } |
| 2156 | 2232 | |
| 2157 | 2233 | static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask) |
| 2158 | 2234 | { |
| 2159 | | - Jim_Obj *objPtr = clientData; |
| 2235 | + Jim_Obj **objPtrPtr = clientData; |
| 2160 | 2236 | |
| 2161 | | - return Jim_EvalObjBackground(interp, objPtr); |
| 2237 | + return Jim_EvalObjBackground(interp, *objPtrPtr); |
| 2162 | 2238 | } |
| 2163 | 2239 | |
| 2164 | 2240 | static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, |
| 2165 | 2241 | int argc, Jim_Obj * const *argv) |
| 2166 | 2242 | { |
| 2167 | | - int scriptlen = 0; |
| 2168 | | - |
| 2169 | 2243 | if (argc == 0) { |
| 2170 | 2244 | |
| 2171 | 2245 | if (*scriptHandlerObj) { |
| 2172 | 2246 | Jim_SetResult(interp, *scriptHandlerObj); |
| 2173 | 2247 | } |
| | @@ -2174,27 +2248,25 @@ |
| 2174 | 2248 | return JIM_OK; |
| 2175 | 2249 | } |
| 2176 | 2250 | |
| 2177 | 2251 | if (*scriptHandlerObj) { |
| 2178 | 2252 | |
| 2179 | | - Jim_DeleteFileHandler(interp, af->fp); |
| 2180 | | - *scriptHandlerObj = NULL; |
| 2253 | + Jim_DeleteFileHandler(interp, af->fp, mask); |
| 2181 | 2254 | } |
| 2182 | 2255 | |
| 2183 | 2256 | |
| 2184 | | - Jim_GetString(argv[0], &scriptlen); |
| 2185 | | - if (scriptlen == 0) { |
| 2257 | + if (Jim_Length(argv[0]) == 0) { |
| 2186 | 2258 | |
| 2187 | 2259 | return JIM_OK; |
| 2188 | 2260 | } |
| 2189 | 2261 | |
| 2190 | 2262 | |
| 2191 | 2263 | Jim_IncrRefCount(argv[0]); |
| 2192 | 2264 | *scriptHandlerObj = argv[0]; |
| 2193 | 2265 | |
| 2194 | 2266 | Jim_CreateFileHandler(interp, af->fp, mask, |
| 2195 | | - JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer); |
| 2267 | + JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); |
| 2196 | 2268 | |
| 2197 | 2269 | return JIM_OK; |
| 2198 | 2270 | } |
| 2199 | 2271 | |
| 2200 | 2272 | static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -2213,11 +2285,11 @@ |
| 2213 | 2285 | |
| 2214 | 2286 | static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2215 | 2287 | { |
| 2216 | 2288 | AioFile *af = Jim_CmdPrivData(interp); |
| 2217 | 2289 | |
| 2218 | | - return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv); |
| 2290 | + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2219 | 2291 | } |
| 2220 | 2292 | #endif |
| 2221 | 2293 | |
| 2222 | 2294 | static const jim_subcmd_type aio_command_table[] = { |
| 2223 | 2295 | { "read", |
| | @@ -2268,14 +2340,14 @@ |
| 2268 | 2340 | 0, |
| 2269 | 2341 | 0, |
| 2270 | 2342 | |
| 2271 | 2343 | }, |
| 2272 | 2344 | { "close", |
| 2273 | | - NULL, |
| 2345 | + "?r(ead)|w(rite)?", |
| 2274 | 2346 | aio_cmd_close, |
| 2275 | 2347 | 0, |
| 2276 | | - 0, |
| 2348 | + 1, |
| 2277 | 2349 | JIM_MODFLAG_FULLARGV, |
| 2278 | 2350 | |
| 2279 | 2351 | }, |
| 2280 | 2352 | { "seek", |
| 2281 | 2353 | "offset ?start|current|end", |
| | @@ -2347,30 +2419,32 @@ |
| 2347 | 2419 | |
| 2348 | 2420 | static int JimAioOpenCommand(Jim_Interp *interp, int argc, |
| 2349 | 2421 | Jim_Obj *const *argv) |
| 2350 | 2422 | { |
| 2351 | 2423 | const char *mode; |
| 2352 | | - const char *filename; |
| 2353 | 2424 | |
| 2354 | 2425 | if (argc != 2 && argc != 3) { |
| 2355 | 2426 | Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); |
| 2356 | 2427 | return JIM_ERR; |
| 2357 | 2428 | } |
| 2358 | 2429 | |
| 2359 | 2430 | mode = (argc == 3) ? Jim_String(argv[2]) : "r"; |
| 2360 | | - filename = Jim_String(argv[1]); |
| 2361 | 2431 | |
| 2362 | 2432 | #ifdef jim_ext_tclcompat |
| 2363 | | - |
| 2364 | | - if (*filename == '|') { |
| 2365 | | - Jim_Obj *evalObj[3]; |
| 2366 | | - |
| 2367 | | - evalObj[0] = Jim_NewStringObj(interp, "popen", -1); |
| 2368 | | - evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| 2369 | | - evalObj[2] = Jim_NewStringObj(interp, mode, -1); |
| 2370 | | - |
| 2371 | | - return Jim_EvalObjVector(interp, 3, evalObj); |
| 2433 | + { |
| 2434 | + const char *filename = Jim_String(argv[1]); |
| 2435 | + |
| 2436 | + |
| 2437 | + if (*filename == '|') { |
| 2438 | + Jim_Obj *evalObj[3]; |
| 2439 | + |
| 2440 | + evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2441 | + evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| 2442 | + evalObj[2] = Jim_NewStringObj(interp, mode, -1); |
| 2443 | + |
| 2444 | + return Jim_EvalObjVector(interp, 3, evalObj); |
| 2445 | + } |
| 2372 | 2446 | } |
| 2373 | 2447 | #endif |
| 2374 | 2448 | return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode); |
| 2375 | 2449 | } |
| 2376 | 2450 | |
| | @@ -2377,70 +2451,129 @@ |
| 2377 | 2451 | static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2378 | 2452 | const char *hdlfmt, int family, const char *mode) |
| 2379 | 2453 | { |
| 2380 | 2454 | AioFile *af; |
| 2381 | 2455 | char buf[AIO_CMD_LEN]; |
| 2382 | | - int OpenFlags = 0; |
| 2456 | + int openFlags = 0; |
| 2383 | 2457 | |
| 2384 | | - if (filename == NULL) { |
| 2458 | + if (fh) { |
| 2385 | 2459 | filename = Jim_NewStringObj(interp, hdlfmt, -1); |
| 2460 | + openFlags = AIO_KEEPOPEN; |
| 2386 | 2461 | } |
| 2387 | 2462 | |
| 2388 | 2463 | Jim_IncrRefCount(filename); |
| 2389 | 2464 | |
| 2390 | 2465 | if (fh == NULL) { |
| 2391 | | - if (fd < 0) { |
| 2392 | | - fh = fopen(Jim_String(filename), mode); |
| 2393 | | - } |
| 2394 | | - else { |
| 2466 | +#if !defined(JIM_ANSIC) |
| 2467 | + if (fd >= 0) { |
| 2395 | 2468 | fh = fdopen(fd, mode); |
| 2396 | 2469 | } |
| 2397 | | - } |
| 2398 | | - else { |
| 2399 | | - OpenFlags = AIO_KEEPOPEN; |
| 2400 | | - } |
| 2470 | + else |
| 2471 | +#endif |
| 2472 | + fh = fopen(Jim_String(filename), mode); |
| 2401 | 2473 | |
| 2402 | | - if (fh == NULL) { |
| 2403 | | - JimAioSetError(interp, filename); |
| 2474 | + if (fh == NULL) { |
| 2475 | + JimAioSetError(interp, filename); |
| 2404 | 2476 | #if !defined(JIM_ANSIC) |
| 2405 | | - if (fd >= 0) { |
| 2406 | | - close(fd); |
| 2477 | + if (fd >= 0) { |
| 2478 | + close(fd); |
| 2479 | + } |
| 2480 | +#endif |
| 2481 | + Jim_DecrRefCount(interp, filename); |
| 2482 | + return JIM_ERR; |
| 2407 | 2483 | } |
| 2408 | | -#endif |
| 2409 | | - Jim_DecrRefCount(interp, filename); |
| 2410 | | - return JIM_ERR; |
| 2411 | 2484 | } |
| 2412 | 2485 | |
| 2413 | 2486 | |
| 2414 | 2487 | af = Jim_Alloc(sizeof(*af)); |
| 2415 | 2488 | memset(af, 0, sizeof(*af)); |
| 2416 | 2489 | af->fp = fh; |
| 2417 | 2490 | af->fd = fileno(fh); |
| 2418 | 2491 | af->filename = filename; |
| 2419 | 2492 | #ifdef FD_CLOEXEC |
| 2420 | | - if ((OpenFlags & AIO_KEEPOPEN) == 0) { |
| 2421 | | - fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2493 | + if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 2494 | + (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2422 | 2495 | } |
| 2423 | 2496 | #endif |
| 2424 | | - af->OpenFlags = OpenFlags; |
| 2425 | | -#ifdef O_NDELAY |
| 2426 | | - af->flags = fcntl(af->fd, F_GETFL); |
| 2427 | | -#endif |
| 2497 | + af->openFlags = openFlags; |
| 2428 | 2498 | af->addr_family = family; |
| 2429 | 2499 | snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2430 | 2500 | Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); |
| 2431 | 2501 | |
| 2432 | | - Jim_SetResultString(interp, buf, -1); |
| 2502 | + Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); |
| 2433 | 2503 | |
| 2434 | 2504 | return JIM_OK; |
| 2435 | 2505 | } |
| 2436 | 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 | +} |
| 2437 | 2569 | |
| 2438 | 2570 | FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2439 | 2571 | { |
| 2440 | 2572 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2441 | 2573 | |
| 2574 | + |
| 2442 | 2575 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2443 | 2576 | return ((AioFile *) cmdPtr->u.native.privData)->fp; |
| 2444 | 2577 | } |
| 2445 | 2578 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2446 | 2579 | return NULL; |
| | @@ -2461,11 +2594,10 @@ |
| 2461 | 2594 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2462 | 2595 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2463 | 2596 | |
| 2464 | 2597 | return JIM_OK; |
| 2465 | 2598 | } |
| 2466 | | - |
| 2467 | 2599 | |
| 2468 | 2600 | #include <errno.h> |
| 2469 | 2601 | #include <stdio.h> |
| 2470 | 2602 | #include <string.h> |
| 2471 | 2603 | |
| | @@ -2497,28 +2629,29 @@ |
| 2497 | 2629 | return JIM_OK; |
| 2498 | 2630 | } |
| 2499 | 2631 | Jim_SetResultString(interp, strerror(errno), -1); |
| 2500 | 2632 | return JIM_ERR; |
| 2501 | 2633 | } |
| 2502 | | - Jim_SetResultString(interp, strerror(errno), -1); |
| 2503 | | - |
| 2504 | | - Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); |
| 2505 | | - |
| 2506 | | - while ((entryPtr = readdir(dirPtr)) != NULL) { |
| 2507 | | - if (entryPtr->d_name[0] == '.') { |
| 2508 | | - if (entryPtr->d_name[1] == '\0') { |
| 2509 | | - continue; |
| 2510 | | - } |
| 2511 | | - if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) |
| 2512 | | - continue; |
| 2513 | | - } |
| 2514 | | - Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, |
| 2515 | | - entryPtr->d_name, -1)); |
| 2516 | | - } |
| 2517 | | - closedir(dirPtr); |
| 2518 | | - |
| 2519 | | - return JIM_OK; |
| 2634 | + else { |
| 2635 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 2636 | + |
| 2637 | + while ((entryPtr = readdir(dirPtr)) != NULL) { |
| 2638 | + if (entryPtr->d_name[0] == '.') { |
| 2639 | + if (entryPtr->d_name[1] == '\0') { |
| 2640 | + continue; |
| 2641 | + } |
| 2642 | + if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) |
| 2643 | + continue; |
| 2644 | + } |
| 2645 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); |
| 2646 | + } |
| 2647 | + closedir(dirPtr); |
| 2648 | + |
| 2649 | + Jim_SetResult(interp, listObj); |
| 2650 | + |
| 2651 | + return JIM_OK; |
| 2652 | + } |
| 2520 | 2653 | } |
| 2521 | 2654 | |
| 2522 | 2655 | int Jim_readdirInit(Jim_Interp *interp) |
| 2523 | 2656 | { |
| 2524 | 2657 | if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) |
| | @@ -2529,10 +2662,14 @@ |
| 2529 | 2662 | } |
| 2530 | 2663 | |
| 2531 | 2664 | #include <stdlib.h> |
| 2532 | 2665 | #include <string.h> |
| 2533 | 2666 | |
| 2667 | +#if defined(JIM_REGEXP) |
| 2668 | +#else |
| 2669 | + #include <regex.h> |
| 2670 | +#endif |
| 2534 | 2671 | |
| 2535 | 2672 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2536 | 2673 | { |
| 2537 | 2674 | regfree(objPtr->internalRep.regexpValue.compre); |
| 2538 | 2675 | Jim_Free(objPtr->internalRep.regexpValue.compre); |
| | @@ -3076,58 +3213,61 @@ |
| 3076 | 3213 | } |
| 3077 | 3214 | #endif |
| 3078 | 3215 | return "unknown"; |
| 3079 | 3216 | } |
| 3080 | 3217 | |
| 3081 | | - |
| 3082 | | -static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, |
| 3083 | | - jim_wide value) |
| 3084 | | -{ |
| 3085 | | - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); |
| 3086 | | - Jim_Obj *valobj = Jim_NewWideObj(interp, value); |
| 3087 | | - |
| 3088 | | - if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { |
| 3089 | | - Jim_FreeObj(interp, nameobj); |
| 3090 | | - Jim_FreeObj(interp, valobj); |
| 3091 | | - return JIM_ERR; |
| 3092 | | - } |
| 3093 | | - return JIM_OK; |
| 3094 | | -} |
| 3095 | | - |
| 3096 | | -static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, |
| 3097 | | - const char *value) |
| 3098 | | -{ |
| 3099 | | - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); |
| 3100 | | - Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); |
| 3101 | | - |
| 3102 | | - if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { |
| 3103 | | - Jim_FreeObj(interp, nameobj); |
| 3104 | | - Jim_FreeObj(interp, valobj); |
| 3105 | | - return JIM_ERR; |
| 3106 | | - } |
| 3107 | | - return JIM_OK; |
| 3218 | +static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value) |
| 3219 | +{ |
| 3220 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); |
| 3221 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3108 | 3222 | } |
| 3109 | 3223 | |
| 3110 | 3224 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3111 | 3225 | { |
| 3112 | | - if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { |
| 3113 | | - Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3114 | | - return JIM_ERR; |
| 3115 | | - } |
| 3116 | | - set_array_int_value(interp, varName, "ino", sb->st_ino); |
| 3117 | | - set_array_int_value(interp, varName, "mode", sb->st_mode); |
| 3118 | | - set_array_int_value(interp, varName, "nlink", sb->st_nlink); |
| 3119 | | - set_array_int_value(interp, varName, "uid", sb->st_uid); |
| 3120 | | - set_array_int_value(interp, varName, "gid", sb->st_gid); |
| 3121 | | - set_array_int_value(interp, varName, "size", sb->st_size); |
| 3122 | | - set_array_int_value(interp, varName, "atime", sb->st_atime); |
| 3123 | | - set_array_int_value(interp, varName, "mtime", sb->st_mtime); |
| 3124 | | - set_array_int_value(interp, varName, "ctime", sb->st_ctime); |
| 3125 | | - set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); |
| 3126 | | - |
| 3127 | | - |
| 3128 | | - Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); |
| 3226 | + |
| 3227 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3228 | + |
| 3229 | + AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| 3230 | + AppendStatElement(interp, listObj, "ino", sb->st_ino); |
| 3231 | + AppendStatElement(interp, listObj, "mode", sb->st_mode); |
| 3232 | + AppendStatElement(interp, listObj, "nlink", sb->st_nlink); |
| 3233 | + AppendStatElement(interp, listObj, "uid", sb->st_uid); |
| 3234 | + AppendStatElement(interp, listObj, "gid", sb->st_gid); |
| 3235 | + AppendStatElement(interp, listObj, "size", sb->st_size); |
| 3236 | + AppendStatElement(interp, listObj, "atime", sb->st_atime); |
| 3237 | + AppendStatElement(interp, listObj, "mtime", sb->st_mtime); |
| 3238 | + AppendStatElement(interp, listObj, "ctime", sb->st_ctime); |
| 3239 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 3240 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); |
| 3241 | + |
| 3242 | + |
| 3243 | + if (varName) { |
| 3244 | + Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); |
| 3245 | + if (objPtr) { |
| 3246 | + if (Jim_DictSize(interp, objPtr) < 0) { |
| 3247 | + |
| 3248 | + Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3249 | + Jim_FreeNewObj(interp, listObj); |
| 3250 | + return JIM_ERR; |
| 3251 | + } |
| 3252 | + |
| 3253 | + if (Jim_IsShared(objPtr)) |
| 3254 | + objPtr = Jim_DuplicateObj(interp, objPtr); |
| 3255 | + |
| 3256 | + |
| 3257 | + Jim_ListAppendList(interp, objPtr, listObj); |
| 3258 | + Jim_DictSize(interp, objPtr); |
| 3259 | + Jim_InvalidateStringRep(objPtr); |
| 3260 | + |
| 3261 | + Jim_FreeNewObj(interp, listObj); |
| 3262 | + listObj = objPtr; |
| 3263 | + } |
| 3264 | + Jim_SetVariable(interp, varName, listObj); |
| 3265 | + } |
| 3266 | + |
| 3267 | + |
| 3268 | + Jim_SetResult(interp, listObj); |
| 3129 | 3269 | |
| 3130 | 3270 | return JIM_OK; |
| 3131 | 3271 | } |
| 3132 | 3272 | |
| 3133 | 3273 | static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -3282,14 +3422,11 @@ |
| 3282 | 3422 | return JIM_OK; |
| 3283 | 3423 | } |
| 3284 | 3424 | |
| 3285 | 3425 | static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) |
| 3286 | 3426 | { |
| 3287 | | - const char *path = Jim_String(filename); |
| 3288 | | - int rc = access(path, mode); |
| 3289 | | - |
| 3290 | | - Jim_SetResultBool(interp, rc != -1); |
| 3427 | + Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1); |
| 3291 | 3428 | |
| 3292 | 3429 | return JIM_OK; |
| 3293 | 3430 | } |
| 3294 | 3431 | |
| 3295 | 3432 | static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -3305,10 +3442,11 @@ |
| 3305 | 3442 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3306 | 3443 | { |
| 3307 | 3444 | #ifdef X_OK |
| 3308 | 3445 | return file_access(interp, argv[0], X_OK); |
| 3309 | 3446 | #else |
| 3447 | + |
| 3310 | 3448 | Jim_SetResultBool(interp, 1); |
| 3311 | 3449 | return JIM_OK; |
| 3312 | 3450 | #endif |
| 3313 | 3451 | } |
| 3314 | 3452 | |
| | @@ -3409,33 +3547,21 @@ |
| 3409 | 3547 | argv++; |
| 3410 | 3548 | } |
| 3411 | 3549 | return JIM_OK; |
| 3412 | 3550 | } |
| 3413 | 3551 | |
| 3414 | | -#ifdef HAVE_MKSTEMP |
| 3415 | 3552 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3416 | 3553 | { |
| 3417 | | - int fd; |
| 3418 | | - char *filename; |
| 3419 | | - const char *template = "/tmp/tcl.tmp.XXXXXX"; |
| 3420 | | - |
| 3421 | | - if (argc >= 1) { |
| 3422 | | - template = Jim_String(argv[0]); |
| 3423 | | - } |
| 3424 | | - filename = Jim_StrDup(template); |
| 3425 | | - |
| 3426 | | - fd = mkstemp(filename); |
| 3427 | | - if (fd < 0) { |
| 3428 | | - Jim_SetResultString(interp, "Failed to create tempfile", -1); |
| 3554 | + int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); |
| 3555 | + |
| 3556 | + if (fd < 0) { |
| 3429 | 3557 | return JIM_ERR; |
| 3430 | 3558 | } |
| 3431 | 3559 | close(fd); |
| 3432 | 3560 | |
| 3433 | | - Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1)); |
| 3434 | 3561 | return JIM_OK; |
| 3435 | 3562 | } |
| 3436 | | -#endif |
| 3437 | 3563 | |
| 3438 | 3564 | static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3439 | 3565 | { |
| 3440 | 3566 | const char *source; |
| 3441 | 3567 | const char *dest; |
| | @@ -3477,14 +3603,11 @@ |
| 3477 | 3603 | return JIM_ERR; |
| 3478 | 3604 | } |
| 3479 | 3605 | return JIM_OK; |
| 3480 | 3606 | } |
| 3481 | 3607 | |
| 3482 | | -#ifndef HAVE_LSTAT |
| 3483 | | -#define lstat stat |
| 3484 | | -#endif |
| 3485 | | - |
| 3608 | +#ifdef HAVE_LSTAT |
| 3486 | 3609 | static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 3487 | 3610 | { |
| 3488 | 3611 | const char *path = Jim_String(filename); |
| 3489 | 3612 | |
| 3490 | 3613 | if (lstat(path, sb) == -1) { |
| | @@ -3491,10 +3614,13 @@ |
| 3491 | 3614 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3492 | 3615 | return JIM_ERR; |
| 3493 | 3616 | } |
| 3494 | 3617 | return JIM_OK; |
| 3495 | 3618 | } |
| 3619 | +#else |
| 3620 | +#define file_lstat file_stat |
| 3621 | +#endif |
| 3496 | 3622 | |
| 3497 | 3623 | static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3498 | 3624 | { |
| 3499 | 3625 | struct stat sb; |
| 3500 | 3626 | |
| | @@ -3619,28 +3745,32 @@ |
| 3619 | 3745 | } |
| 3620 | 3746 | Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); |
| 3621 | 3747 | return JIM_OK; |
| 3622 | 3748 | } |
| 3623 | 3749 | |
| 3750 | +#ifdef HAVE_LSTAT |
| 3624 | 3751 | static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3625 | 3752 | { |
| 3626 | 3753 | struct stat sb; |
| 3627 | 3754 | |
| 3628 | 3755 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 3629 | 3756 | return JIM_ERR; |
| 3630 | 3757 | } |
| 3631 | | - return StoreStatData(interp, argv[1], &sb); |
| 3758 | + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 3632 | 3759 | } |
| 3760 | +#else |
| 3761 | +#define file_cmd_lstat file_cmd_stat |
| 3762 | +#endif |
| 3633 | 3763 | |
| 3634 | 3764 | static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3635 | 3765 | { |
| 3636 | 3766 | struct stat sb; |
| 3637 | 3767 | |
| 3638 | 3768 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 3639 | 3769 | return JIM_ERR; |
| 3640 | 3770 | } |
| 3641 | | - return StoreStatData(interp, argv[1], &sb); |
| 3771 | + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 3642 | 3772 | } |
| 3643 | 3773 | |
| 3644 | 3774 | static const jim_subcmd_type file_command_table[] = { |
| 3645 | 3775 | { "atime", |
| 3646 | 3776 | "name", |
| | @@ -3745,19 +3875,17 @@ |
| 3745 | 3875 | file_cmd_mkdir, |
| 3746 | 3876 | 1, |
| 3747 | 3877 | -1, |
| 3748 | 3878 | |
| 3749 | 3879 | }, |
| 3750 | | -#ifdef HAVE_MKSTEMP |
| 3751 | 3880 | { "tempfile", |
| 3752 | 3881 | "?template?", |
| 3753 | 3882 | file_cmd_tempfile, |
| 3754 | 3883 | 0, |
| 3755 | 3884 | 1, |
| 3756 | 3885 | |
| 3757 | 3886 | }, |
| 3758 | | -#endif |
| 3759 | 3887 | { "rename", |
| 3760 | 3888 | "?-force? source dest", |
| 3761 | 3889 | file_cmd_rename, |
| 3762 | 3890 | 2, |
| 3763 | 3891 | 3, |
| | @@ -3778,20 +3906,20 @@ |
| 3778 | 3906 | 1, |
| 3779 | 3907 | 1, |
| 3780 | 3908 | |
| 3781 | 3909 | }, |
| 3782 | 3910 | { "stat", |
| 3783 | | - "name var", |
| 3911 | + "name ?var?", |
| 3784 | 3912 | file_cmd_stat, |
| 3785 | | - 2, |
| 3913 | + 1, |
| 3786 | 3914 | 2, |
| 3787 | 3915 | |
| 3788 | 3916 | }, |
| 3789 | 3917 | { "lstat", |
| 3790 | | - "name var", |
| 3918 | + "name ?var?", |
| 3791 | 3919 | file_cmd_lstat, |
| 3792 | | - 2, |
| 3920 | + 1, |
| 3793 | 3921 | 2, |
| 3794 | 3922 | |
| 3795 | 3923 | }, |
| 3796 | 3924 | { "type", |
| 3797 | 3925 | "name", |
| | @@ -3847,15 +3975,15 @@ |
| 3847 | 3975 | return JIM_OK; |
| 3848 | 3976 | } |
| 3849 | 3977 | |
| 3850 | 3978 | static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3851 | 3979 | { |
| 3852 | | - const int cwd_len = 2048; |
| 3853 | | - char *cwd = malloc(cwd_len); |
| 3980 | + char *cwd = Jim_Alloc(MAXPATHLEN); |
| 3854 | 3981 | |
| 3855 | | - if (getcwd(cwd, cwd_len) == NULL) { |
| 3982 | + if (getcwd(cwd, MAXPATHLEN) == NULL) { |
| 3856 | 3983 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 3984 | + Jim_Free(cwd); |
| 3857 | 3985 | return JIM_ERR; |
| 3858 | 3986 | } |
| 3859 | 3987 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 3860 | 3988 | { |
| 3861 | 3989 | |
| | @@ -3866,11 +3994,11 @@ |
| 3866 | 3994 | } |
| 3867 | 3995 | #endif |
| 3868 | 3996 | |
| 3869 | 3997 | Jim_SetResultString(interp, cwd, -1); |
| 3870 | 3998 | |
| 3871 | | - free(cwd); |
| 3999 | + Jim_Free(cwd); |
| 3872 | 4000 | return JIM_OK; |
| 3873 | 4001 | } |
| 3874 | 4002 | |
| 3875 | 4003 | int Jim_fileInit(Jim_Interp *interp) |
| 3876 | 4004 | { |
| | @@ -3935,10 +4063,11 @@ |
| 3935 | 4063 | |
| 3936 | 4064 | int Jim_execInit(Jim_Interp *interp) |
| 3937 | 4065 | { |
| 3938 | 4066 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 3939 | 4067 | return JIM_ERR; |
| 4068 | + |
| 3940 | 4069 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); |
| 3941 | 4070 | return JIM_OK; |
| 3942 | 4071 | } |
| 3943 | 4072 | #else |
| 3944 | 4073 | |
| | @@ -3978,10 +4107,11 @@ |
| 3978 | 4107 | static int JimErrno(void); |
| 3979 | 4108 | #else |
| 3980 | 4109 | #include <unistd.h> |
| 3981 | 4110 | #include <fcntl.h> |
| 3982 | 4111 | #include <sys/wait.h> |
| 4112 | + #include <sys/stat.h> |
| 3983 | 4113 | |
| 3984 | 4114 | typedef int fdtype; |
| 3985 | 4115 | typedef int pidtype; |
| 3986 | 4116 | #define JimPipe pipe |
| 3987 | 4117 | #define JimErrno() errno |
| | @@ -4005,11 +4135,11 @@ |
| 4005 | 4135 | static void JimRestoreEnv(char **env); |
| 4006 | 4136 | static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, |
| 4007 | 4137 | pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); |
| 4008 | 4138 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); |
| 4009 | 4139 | static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId); |
| 4010 | | -static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents); |
| 4140 | +static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len); |
| 4011 | 4141 | static fdtype JimOpenForWrite(const char *filename, int append); |
| 4012 | 4142 | static int JimRewindFd(fdtype fd); |
| 4013 | 4143 | |
| 4014 | 4144 | static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) |
| 4015 | 4145 | { |
| | @@ -4052,23 +4182,12 @@ |
| 4052 | 4182 | Jim_RemoveTrailingNewline(strObj); |
| 4053 | 4183 | fclose(fh); |
| 4054 | 4184 | return JIM_OK; |
| 4055 | 4185 | } |
| 4056 | 4186 | |
| 4057 | | -static void JimTrimTrailingNewline(Jim_Interp *interp) |
| 4058 | | -{ |
| 4059 | | - int len; |
| 4060 | | - const char *p = Jim_GetString(Jim_GetResult(interp), &len); |
| 4061 | | - |
| 4062 | | - if (len > 0 && p[len - 1] == '\n') { |
| 4063 | | - Jim_SetResultString(interp, p, len - 1); |
| 4064 | | - } |
| 4065 | | -} |
| 4066 | | - |
| 4067 | 4187 | static char **JimBuildEnv(Jim_Interp *interp) |
| 4068 | 4188 | { |
| 4069 | | -#if defined(jim_ext_tclcompat) |
| 4070 | 4189 | int i; |
| 4071 | 4190 | int size; |
| 4072 | 4191 | int num; |
| 4073 | 4192 | int n; |
| 4074 | 4193 | char **envptr; |
| | @@ -4082,10 +4201,11 @@ |
| 4082 | 4201 | |
| 4083 | 4202 | |
| 4084 | 4203 | |
| 4085 | 4204 | num = Jim_ListLength(interp, objPtr); |
| 4086 | 4205 | if (num % 2) { |
| 4206 | + |
| 4087 | 4207 | num--; |
| 4088 | 4208 | } |
| 4089 | 4209 | size = Jim_Length(objPtr) + 2; |
| 4090 | 4210 | |
| 4091 | 4211 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| | @@ -4108,22 +4228,17 @@ |
| 4108 | 4228 | } |
| 4109 | 4229 | envptr[n] = NULL; |
| 4110 | 4230 | *envdata = 0; |
| 4111 | 4231 | |
| 4112 | 4232 | return envptr; |
| 4113 | | -#else |
| 4114 | | - return Jim_GetEnviron(); |
| 4115 | | -#endif |
| 4116 | 4233 | } |
| 4117 | 4234 | |
| 4118 | 4235 | static void JimFreeEnv(char **env, char **original_environ) |
| 4119 | 4236 | { |
| 4120 | | -#ifdef jim_ext_tclcompat |
| 4121 | 4237 | if (env != original_environ) { |
| 4122 | 4238 | Jim_Free(env); |
| 4123 | 4239 | } |
| 4124 | | -#endif |
| 4125 | 4240 | } |
| 4126 | 4241 | |
| 4127 | 4242 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) |
| 4128 | 4243 | { |
| 4129 | 4244 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| | @@ -4172,19 +4287,19 @@ |
| 4172 | 4287 | } |
| 4173 | 4288 | |
| 4174 | 4289 | |
| 4175 | 4290 | struct WaitInfo |
| 4176 | 4291 | { |
| 4177 | | - pidtype pid; |
| 4292 | + pidtype pid; |
| 4178 | 4293 | int status; |
| 4179 | 4294 | int flags; |
| 4180 | 4295 | }; |
| 4181 | 4296 | |
| 4182 | 4297 | struct WaitInfoTable { |
| 4183 | | - struct WaitInfo *info; |
| 4184 | | - int size; |
| 4185 | | - int used; |
| 4298 | + struct WaitInfo *info; |
| 4299 | + int size; |
| 4300 | + int used; |
| 4186 | 4301 | }; |
| 4187 | 4302 | |
| 4188 | 4303 | |
| 4189 | 4304 | #define WI_DETACHED 2 |
| 4190 | 4305 | |
| | @@ -4207,14 +4322,12 @@ |
| 4207 | 4322 | return table; |
| 4208 | 4323 | } |
| 4209 | 4324 | |
| 4210 | 4325 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4211 | 4326 | { |
| 4212 | | - fdtype outputId; /* File id for output pipe. -1 |
| 4213 | | - * means command overrode. */ |
| 4214 | | - fdtype errorId; /* File id for temporary file |
| 4215 | | - * containing error output. */ |
| 4327 | + fdtype outputId; |
| 4328 | + fdtype errorId; |
| 4216 | 4329 | pidtype *pidPtr; |
| 4217 | 4330 | int numPids, result; |
| 4218 | 4331 | |
| 4219 | 4332 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4220 | 4333 | Jim_Obj *listObj; |
| | @@ -4261,26 +4374,32 @@ |
| 4261 | 4374 | |
| 4262 | 4375 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4263 | 4376 | { |
| 4264 | 4377 | struct WaitInfo *waitPtr; |
| 4265 | 4378 | int count; |
| 4379 | + int dest; |
| 4266 | 4380 | |
| 4267 | 4381 | if (!table) { |
| 4268 | 4382 | return; |
| 4269 | 4383 | } |
| 4270 | 4384 | |
| 4271 | | - for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) { |
| 4385 | + waitPtr = table->info; |
| 4386 | + dest = 0; |
| 4387 | + for (count = table->used; count > 0; waitPtr++, count--) { |
| 4272 | 4388 | if (waitPtr->flags & WI_DETACHED) { |
| 4273 | 4389 | int status; |
| 4274 | 4390 | pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); |
| 4275 | | - if (pid != JIM_BAD_PID) { |
| 4276 | | - if (waitPtr != &table->info[table->used - 1]) { |
| 4277 | | - *waitPtr = table->info[table->used - 1]; |
| 4278 | | - } |
| 4391 | + if (pid == waitPtr->pid) { |
| 4392 | + |
| 4279 | 4393 | table->used--; |
| 4394 | + continue; |
| 4280 | 4395 | } |
| 4281 | 4396 | } |
| 4397 | + if (waitPtr != &table->info[dest]) { |
| 4398 | + table->info[dest] = *waitPtr; |
| 4399 | + } |
| 4400 | + dest++; |
| 4282 | 4401 | } |
| 4283 | 4402 | } |
| 4284 | 4403 | |
| 4285 | 4404 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4286 | 4405 | { |
| | @@ -4302,11 +4421,10 @@ |
| 4302 | 4421 | } |
| 4303 | 4422 | |
| 4304 | 4423 | |
| 4305 | 4424 | return JIM_BAD_PID; |
| 4306 | 4425 | } |
| 4307 | | - |
| 4308 | 4426 | |
| 4309 | 4427 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) |
| 4310 | 4428 | { |
| 4311 | 4429 | int j; |
| 4312 | 4430 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| | @@ -4347,10 +4465,11 @@ |
| 4347 | 4465 | int cmdCount; /* Count of number of distinct commands |
| 4348 | 4466 | * found in argc/argv. */ |
| 4349 | 4467 | const char *input = NULL; /* Describes input for pipeline, depending |
| 4350 | 4468 | * on "inputFile". NULL means take input |
| 4351 | 4469 | * from stdin/pipe. */ |
| 4470 | + int input_len = 0; |
| 4352 | 4471 | |
| 4353 | 4472 | #define FILE_NAME 0 |
| 4354 | 4473 | #define FILE_APPEND 1 |
| 4355 | 4474 | #define FILE_HANDLE 2 |
| 4356 | 4475 | #define FILE_TEXT 3 |
| | @@ -4412,19 +4531,20 @@ |
| 4412 | 4531 | if (arg[0] == '<') { |
| 4413 | 4532 | inputFile = FILE_NAME; |
| 4414 | 4533 | input = arg + 1; |
| 4415 | 4534 | if (*input == '<') { |
| 4416 | 4535 | inputFile = FILE_TEXT; |
| 4536 | + input_len = Jim_Length(argv[i]) - 2; |
| 4417 | 4537 | input++; |
| 4418 | 4538 | } |
| 4419 | 4539 | else if (*input == '@') { |
| 4420 | 4540 | inputFile = FILE_HANDLE; |
| 4421 | 4541 | input++; |
| 4422 | 4542 | } |
| 4423 | 4543 | |
| 4424 | 4544 | if (!*input && ++i < argc) { |
| 4425 | | - input = Jim_String(argv[i]); |
| 4545 | + input = Jim_GetString(argv[i], &input_len); |
| 4426 | 4546 | } |
| 4427 | 4547 | } |
| 4428 | 4548 | else if (arg[0] == '>') { |
| 4429 | 4549 | int dup_error = 0; |
| 4430 | 4550 | |
| | @@ -4498,11 +4618,11 @@ |
| 4498 | 4618 | |
| 4499 | 4619 | save_environ = JimSaveEnv(JimBuildEnv(interp)); |
| 4500 | 4620 | |
| 4501 | 4621 | if (input != NULL) { |
| 4502 | 4622 | if (inputFile == FILE_TEXT) { |
| 4503 | | - inputId = JimCreateTemp(interp, input); |
| 4623 | + inputId = JimCreateTemp(interp, input, input_len); |
| 4504 | 4624 | if (inputId == JIM_BAD_FD) { |
| 4505 | 4625 | goto error; |
| 4506 | 4626 | } |
| 4507 | 4627 | } |
| 4508 | 4628 | else if (inputFile == FILE_HANDLE) { |
| | @@ -4587,11 +4707,11 @@ |
| 4587 | 4707 | goto error; |
| 4588 | 4708 | } |
| 4589 | 4709 | } |
| 4590 | 4710 | } |
| 4591 | 4711 | else if (errFilePtr != NULL) { |
| 4592 | | - errorId = JimCreateTemp(interp, NULL); |
| 4712 | + errorId = JimCreateTemp(interp, NULL, 0); |
| 4593 | 4713 | if (errorId == JIM_BAD_FD) { |
| 4594 | 4714 | goto error; |
| 4595 | 4715 | } |
| 4596 | 4716 | *errFilePtr = JimDupFd(errorId); |
| 4597 | 4717 | } |
| | @@ -4625,27 +4745,23 @@ |
| 4625 | 4745 | } |
| 4626 | 4746 | outputId = pipeIds[1]; |
| 4627 | 4747 | } |
| 4628 | 4748 | |
| 4629 | 4749 | |
| 4750 | + if (pipe_dup_err) { |
| 4751 | + errorId = outputId; |
| 4752 | + } |
| 4753 | + |
| 4754 | + |
| 4630 | 4755 | |
| 4631 | 4756 | #ifdef __MINGW32__ |
| 4632 | 4757 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); |
| 4633 | 4758 | if (pid == JIM_BAD_PID) { |
| 4634 | 4759 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4635 | 4760 | goto error; |
| 4636 | 4761 | } |
| 4637 | 4762 | #else |
| 4638 | | - if (table->info == NULL) { |
| 4639 | | - (void)signal(SIGPIPE, SIG_IGN); |
| 4640 | | - } |
| 4641 | | - |
| 4642 | | - |
| 4643 | | - if (pipe_dup_err) { |
| 4644 | | - errorId = outputId; |
| 4645 | | - } |
| 4646 | | - |
| 4647 | 4763 | pid = vfork(); |
| 4648 | 4764 | if (pid < 0) { |
| 4649 | 4765 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 4650 | 4766 | goto error; |
| 4651 | 4767 | } |
| | @@ -4658,14 +4774,17 @@ |
| 4658 | 4774 | |
| 4659 | 4775 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 4660 | 4776 | close(i); |
| 4661 | 4777 | } |
| 4662 | 4778 | |
| 4779 | + |
| 4780 | + (void)signal(SIGPIPE, SIG_DFL); |
| 4781 | + |
| 4663 | 4782 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 4664 | 4783 | |
| 4665 | 4784 | |
| 4666 | | - fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 4785 | + fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); |
| 4667 | 4786 | _exit(127); |
| 4668 | 4787 | } |
| 4669 | 4788 | #endif |
| 4670 | 4789 | |
| 4671 | 4790 | |
| | @@ -4767,19 +4886,24 @@ |
| 4767 | 4886 | if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { |
| 4768 | 4887 | result = JIM_ERR; |
| 4769 | 4888 | } |
| 4770 | 4889 | } |
| 4771 | 4890 | |
| 4772 | | - JimTrimTrailingNewline(interp); |
| 4891 | + Jim_RemoveTrailingNewline(Jim_GetResult(interp)); |
| 4773 | 4892 | |
| 4774 | 4893 | return result; |
| 4775 | 4894 | } |
| 4776 | 4895 | |
| 4777 | 4896 | int Jim_execInit(Jim_Interp *interp) |
| 4778 | 4897 | { |
| 4779 | 4898 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4780 | 4899 | return JIM_ERR; |
| 4900 | + |
| 4901 | +#ifdef SIGPIPE |
| 4902 | + (void)signal(SIGPIPE, SIG_IGN); |
| 4903 | +#endif |
| 4904 | + |
| 4781 | 4905 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); |
| 4782 | 4906 | return JIM_OK; |
| 4783 | 4907 | } |
| 4784 | 4908 | |
| 4785 | 4909 | #if defined(__MINGW32__) |
| | @@ -4953,11 +5077,11 @@ |
| 4953 | 5077 | *status = ret; |
| 4954 | 5078 | CloseHandle(pid); |
| 4955 | 5079 | return pid; |
| 4956 | 5080 | } |
| 4957 | 5081 | |
| 4958 | | -static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents) |
| 5082 | +static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 4959 | 5083 | { |
| 4960 | 5084 | char name[MAX_PATH]; |
| 4961 | 5085 | HANDLE handle; |
| 4962 | 5086 | |
| 4963 | 5087 | if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { |
| | @@ -4977,11 +5101,11 @@ |
| 4977 | 5101 | FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); |
| 4978 | 5102 | if (fh == NULL) { |
| 4979 | 5103 | goto error; |
| 4980 | 5104 | } |
| 4981 | 5105 | |
| 4982 | | - if (fwrite(contents, strlen(contents), 1, fh) != 1) { |
| 5106 | + if (fwrite(contents, len, 1, fh) != 1) { |
| 4983 | 5107 | fclose(fh); |
| 4984 | 5108 | goto error; |
| 4985 | 5109 | } |
| 4986 | 5110 | fseek(fh, 0, SEEK_SET); |
| 4987 | 5111 | fclose(fh); |
| | @@ -5104,28 +5228,26 @@ |
| 5104 | 5228 | { |
| 5105 | 5229 | STARTUPINFO startInfo; |
| 5106 | 5230 | PROCESS_INFORMATION procInfo; |
| 5107 | 5231 | HANDLE hProcess, h; |
| 5108 | 5232 | char execPath[MAX_PATH]; |
| 5109 | | - char *originalName; |
| 5110 | 5233 | pidtype pid = JIM_BAD_PID; |
| 5111 | 5234 | Jim_Obj *cmdLineObj; |
| 5112 | 5235 | |
| 5113 | 5236 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5114 | 5237 | return JIM_BAD_PID; |
| 5115 | 5238 | } |
| 5116 | | - originalName = argv[0]; |
| 5117 | 5239 | argv[0] = execPath; |
| 5118 | 5240 | |
| 5119 | 5241 | hProcess = GetCurrentProcess(); |
| 5120 | 5242 | cmdLineObj = JimWinBuildCommandLine(interp, argv); |
| 5121 | 5243 | |
| 5122 | 5244 | |
| 5123 | 5245 | ZeroMemory(&startInfo, sizeof(startInfo)); |
| 5124 | 5246 | startInfo.cb = sizeof(startInfo); |
| 5125 | 5247 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5126 | | - startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5248 | + startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5127 | 5249 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5128 | 5250 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5129 | 5251 | |
| 5130 | 5252 | if (inputId == JIM_BAD_FD) { |
| 5131 | 5253 | if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { |
| | @@ -5196,23 +5318,21 @@ |
| 5196 | 5318 | static int JimRewindFd(int fd) |
| 5197 | 5319 | { |
| 5198 | 5320 | return lseek(fd, 0L, SEEK_SET); |
| 5199 | 5321 | } |
| 5200 | 5322 | |
| 5201 | | -static int JimCreateTemp(Jim_Interp *interp, const char *contents) |
| 5323 | +static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5202 | 5324 | { |
| 5203 | | - char inName[] = "/tmp/tcl.tmp.XXXXXX"; |
| 5325 | + int fd = Jim_MakeTempFile(interp, NULL); |
| 5204 | 5326 | |
| 5205 | | - int fd = mkstemp(inName); |
| 5206 | 5327 | if (fd == JIM_BAD_FD) { |
| 5207 | 5328 | Jim_SetResultErrno(interp, "couldn't create temp file"); |
| 5208 | 5329 | return -1; |
| 5209 | 5330 | } |
| 5210 | | - unlink(inName); |
| 5331 | + unlink(Jim_String(Jim_GetResult(interp))); |
| 5211 | 5332 | if (contents) { |
| 5212 | | - int length = strlen(contents); |
| 5213 | | - if (write(fd, contents, length) != length) { |
| 5333 | + if (write(fd, contents, len) != len) { |
| 5214 | 5334 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5215 | 5335 | close(fd); |
| 5216 | 5336 | return -1; |
| 5217 | 5337 | } |
| 5218 | 5338 | lseek(fd, 0L, SEEK_SET); |
| | @@ -5234,11 +5354,10 @@ |
| 5234 | 5354 | } |
| 5235 | 5355 | #endif |
| 5236 | 5356 | #endif |
| 5237 | 5357 | |
| 5238 | 5358 | |
| 5239 | | - |
| 5240 | 5359 | #ifndef _XOPEN_SOURCE |
| 5241 | 5360 | #define _XOPEN_SOURCE 500 |
| 5242 | 5361 | #endif |
| 5243 | 5362 | |
| 5244 | 5363 | #include <stdlib.h> |
| | @@ -5256,11 +5375,11 @@ |
| 5256 | 5375 | |
| 5257 | 5376 | char buf[100]; |
| 5258 | 5377 | time_t t; |
| 5259 | 5378 | long seconds; |
| 5260 | 5379 | |
| 5261 | | - const char *format = "%a %b %d %H:%M:%S %Z %Y"; |
| 5380 | + const char *format = "%a %b %d %H:%M:%S %Z %Y"; |
| 5262 | 5381 | |
| 5263 | 5382 | if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { |
| 5264 | 5383 | return -1; |
| 5265 | 5384 | } |
| 5266 | 5385 | |
| | @@ -5271,11 +5390,14 @@ |
| 5271 | 5390 | if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { |
| 5272 | 5391 | return JIM_ERR; |
| 5273 | 5392 | } |
| 5274 | 5393 | t = seconds; |
| 5275 | 5394 | |
| 5276 | | - strftime(buf, sizeof(buf), format, localtime(&t)); |
| 5395 | + if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { |
| 5396 | + Jim_SetResultString(interp, "format string too long", -1); |
| 5397 | + return JIM_ERR; |
| 5398 | + } |
| 5277 | 5399 | |
| 5278 | 5400 | Jim_SetResultString(interp, buf, -1); |
| 5279 | 5401 | |
| 5280 | 5402 | return JIM_OK; |
| 5281 | 5403 | } |
| | @@ -5391,11 +5513,10 @@ |
| 5391 | 5513 | |
| 5392 | 5514 | Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); |
| 5393 | 5515 | return JIM_OK; |
| 5394 | 5516 | } |
| 5395 | 5517 | |
| 5396 | | - |
| 5397 | 5518 | #include <limits.h> |
| 5398 | 5519 | #include <stdlib.h> |
| 5399 | 5520 | #include <string.h> |
| 5400 | 5521 | #include <stdio.h> |
| 5401 | 5522 | #include <errno.h> |
| | @@ -5409,33 +5530,29 @@ |
| 5409 | 5530 | } |
| 5410 | 5531 | |
| 5411 | 5532 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5412 | 5533 | { |
| 5413 | 5534 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5535 | + Jim_Obj *patternObj; |
| 5414 | 5536 | |
| 5415 | 5537 | if (!objPtr) { |
| 5416 | 5538 | return JIM_OK; |
| 5417 | 5539 | } |
| 5418 | 5540 | |
| 5419 | | - if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { |
| 5420 | | - |
| 5421 | | - if (Jim_IsList(objPtr)) { |
| 5422 | | - if (Jim_ListLength(interp, objPtr) % 2 != 0) { |
| 5423 | | - |
| 5424 | | - return JIM_ERR; |
| 5425 | | - } |
| 5426 | | - } |
| 5427 | | - else if (Jim_DictSize(interp, objPtr) < 0) { |
| 5428 | | - |
| 5429 | | - return JIM_ERR; |
| 5430 | | - } |
| 5431 | | - Jim_SetResult(interp, objPtr); |
| 5432 | | - return JIM_OK; |
| 5541 | + patternObj = (argc == 1) ? NULL : argv[1]; |
| 5542 | + |
| 5543 | + |
| 5544 | + if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { |
| 5545 | + if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { |
| 5546 | + |
| 5547 | + Jim_SetResult(interp, objPtr); |
| 5548 | + return JIM_OK; |
| 5549 | + } |
| 5433 | 5550 | } |
| 5434 | 5551 | |
| 5435 | 5552 | |
| 5436 | | - return Jim_DictValues(interp, objPtr, argv[1]); |
| 5553 | + return Jim_DictValues(interp, objPtr, patternObj); |
| 5437 | 5554 | } |
| 5438 | 5555 | |
| 5439 | 5556 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5440 | 5557 | { |
| 5441 | 5558 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| | @@ -5460,10 +5577,15 @@ |
| 5460 | 5577 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5461 | 5578 | return JIM_OK; |
| 5462 | 5579 | } |
| 5463 | 5580 | |
| 5464 | 5581 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5582 | + |
| 5583 | + if (objPtr == NULL) { |
| 5584 | + |
| 5585 | + return JIM_OK; |
| 5586 | + } |
| 5465 | 5587 | |
| 5466 | 5588 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5467 | 5589 | return JIM_ERR; |
| 5468 | 5590 | } |
| 5469 | 5591 | |
| | @@ -5497,10 +5619,20 @@ |
| 5497 | 5619 | |
| 5498 | 5620 | Jim_SetResultInt(interp, len); |
| 5499 | 5621 | |
| 5500 | 5622 | return JIM_OK; |
| 5501 | 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 | +} |
| 5502 | 5634 | |
| 5503 | 5635 | static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5504 | 5636 | { |
| 5505 | 5637 | int i; |
| 5506 | 5638 | int len; |
| | @@ -5515,10 +5647,13 @@ |
| 5515 | 5647 | |
| 5516 | 5648 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5517 | 5649 | if (!dictObj) { |
| 5518 | 5650 | |
| 5519 | 5651 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5652 | + } |
| 5653 | + else if (Jim_DictSize(interp, dictObj) < 0) { |
| 5654 | + return JIM_ERR; |
| 5520 | 5655 | } |
| 5521 | 5656 | |
| 5522 | 5657 | if (Jim_IsShared(dictObj)) { |
| 5523 | 5658 | dictObj = Jim_DuplicateObj(interp, dictObj); |
| 5524 | 5659 | } |
| | @@ -5568,10 +5703,17 @@ |
| 5568 | 5703 | "arrayName", |
| 5569 | 5704 | array_cmd_size, |
| 5570 | 5705 | 1, |
| 5571 | 5706 | 1, |
| 5572 | 5707 | |
| 5708 | + }, |
| 5709 | + { "stat", |
| 5710 | + "arrayName", |
| 5711 | + array_cmd_stat, |
| 5712 | + 1, |
| 5713 | + 1, |
| 5714 | + |
| 5573 | 5715 | }, |
| 5574 | 5716 | { "unset", |
| 5575 | 5717 | "arrayName ?pattern?", |
| 5576 | 5718 | array_cmd_unset, |
| 5577 | 5719 | 1, |
| | @@ -5614,11 +5756,10 @@ |
| 5614 | 5756 | Jim_arrayInit(interp); |
| 5615 | 5757 | Jim_stdlibInit(interp); |
| 5616 | 5758 | Jim_tclcompatInit(interp); |
| 5617 | 5759 | return JIM_OK; |
| 5618 | 5760 | } |
| 5619 | | - |
| 5620 | 5761 | #define JIM_OPTIMIZATION |
| 5621 | 5762 | |
| 5622 | 5763 | #include <stdio.h> |
| 5623 | 5764 | #include <stdlib.h> |
| 5624 | 5765 | |
| | @@ -5671,29 +5812,33 @@ |
| 5671 | 5812 | #ifdef JIM_MAINTAINER |
| 5672 | 5813 | #define JIM_DEBUG_COMMAND |
| 5673 | 5814 | #define JIM_DEBUG_PANIC |
| 5674 | 5815 | #endif |
| 5675 | 5816 | |
| 5817 | + |
| 5818 | + |
| 5819 | +#define JIM_INTEGER_SPACE 24 |
| 5820 | + |
| 5676 | 5821 | const char *jim_tt_name(int type); |
| 5677 | 5822 | |
| 5678 | 5823 | #ifdef JIM_DEBUG_PANIC |
| 5679 | | -static void JimPanicDump(int panic_condition, const char *fmt, ...); |
| 5824 | +static void JimPanicDump(int fail_condition, const char *fmt, ...); |
| 5680 | 5825 | #define JimPanic(X) JimPanicDump X |
| 5681 | 5826 | #else |
| 5682 | 5827 | #define JimPanic(X) |
| 5683 | 5828 | #endif |
| 5684 | 5829 | |
| 5685 | 5830 | |
| 5686 | 5831 | static char JimEmptyStringRep[] = ""; |
| 5687 | 5832 | |
| 5688 | | -static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); |
| 5689 | | -static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); |
| 5833 | +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 5690 | 5834 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| 5691 | 5835 | int flags); |
| 5692 | 5836 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); |
| 5693 | 5837 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); |
| 5694 | 5838 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| 5839 | +static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len); |
| 5695 | 5840 | static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, |
| 5696 | 5841 | const char *prefix, const char *const *tablePtr, const char *name); |
| 5697 | 5842 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); |
| 5698 | 5843 | static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); |
| 5699 | 5844 | static int JimSign(jim_wide w); |
| | @@ -5934,17 +6079,10 @@ |
| 5934 | 6079 | } |
| 5935 | 6080 | return n; |
| 5936 | 6081 | } |
| 5937 | 6082 | #endif |
| 5938 | 6083 | |
| 5939 | | -int Jim_WideToString(char *buf, jim_wide wideValue) |
| 5940 | | -{ |
| 5941 | | - const char *fmt = "%" JIM_WIDE_MODIFIER; |
| 5942 | | - |
| 5943 | | - return sprintf(buf, fmt, wideValue); |
| 5944 | | -} |
| 5945 | | - |
| 5946 | 6084 | static int JimCheckConversion(const char *str, const char *endptr) |
| 5947 | 6085 | { |
| 5948 | 6086 | if (str[0] == '\0' || str == endptr) { |
| 5949 | 6087 | return JIM_ERR; |
| 5950 | 6088 | } |
| | @@ -5998,11 +6136,12 @@ |
| 5998 | 6136 | if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { |
| 5999 | 6137 | |
| 6000 | 6138 | return i; |
| 6001 | 6139 | } |
| 6002 | 6140 | |
| 6003 | | - return 10; |
| 6141 | + *base = 10; |
| 6142 | + return 0; |
| 6004 | 6143 | } |
| 6005 | 6144 | |
| 6006 | 6145 | static long jim_strtol(const char *str, char **endptr) |
| 6007 | 6146 | { |
| 6008 | 6147 | int sign; |
| | @@ -6054,46 +6193,10 @@ |
| 6054 | 6193 | } |
| 6055 | 6194 | |
| 6056 | 6195 | return JimCheckConversion(str, endptr); |
| 6057 | 6196 | } |
| 6058 | 6197 | |
| 6059 | | -int Jim_DoubleToString(char *buf, double doubleValue) |
| 6060 | | -{ |
| 6061 | | - int len; |
| 6062 | | - int i; |
| 6063 | | - |
| 6064 | | - len = sprintf(buf, "%.12g", doubleValue); |
| 6065 | | - |
| 6066 | | - |
| 6067 | | - for (i = 0; i < len; i++) { |
| 6068 | | - if (buf[i] == '.' || buf[i] == 'e') { |
| 6069 | | -#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 6070 | | - char *e = strchr(buf, 'e'); |
| 6071 | | - if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 6072 | | - |
| 6073 | | - e += 2; |
| 6074 | | - memmove(e, e + 1, len - (e - buf)); |
| 6075 | | - return len - 1; |
| 6076 | | - } |
| 6077 | | -#endif |
| 6078 | | - return len; |
| 6079 | | - } |
| 6080 | | - |
| 6081 | | - if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') { |
| 6082 | | - buf[i] = toupper(UCHAR(buf[i])); |
| 6083 | | - buf[i + 3] = 0; |
| 6084 | | - return i + 3; |
| 6085 | | - } |
| 6086 | | - } |
| 6087 | | - |
| 6088 | | - buf[i++] = '.'; |
| 6089 | | - buf[i++] = '0'; |
| 6090 | | - buf[i] = '\0'; |
| 6091 | | - |
| 6092 | | - return i; |
| 6093 | | -} |
| 6094 | | - |
| 6095 | 6198 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6096 | 6199 | { |
| 6097 | 6200 | char *endptr; |
| 6098 | 6201 | |
| 6099 | 6202 | |
| | @@ -6115,23 +6218,23 @@ |
| 6115 | 6218 | } |
| 6116 | 6219 | return res; |
| 6117 | 6220 | } |
| 6118 | 6221 | |
| 6119 | 6222 | #ifdef JIM_DEBUG_PANIC |
| 6120 | | -void JimPanicDump(int condition, const char *fmt, ...) |
| 6223 | +static void JimPanicDump(int condition, const char *fmt, ...) |
| 6121 | 6224 | { |
| 6122 | 6225 | va_list ap; |
| 6123 | 6226 | |
| 6124 | 6227 | if (!condition) { |
| 6125 | 6228 | return; |
| 6126 | 6229 | } |
| 6127 | 6230 | |
| 6128 | 6231 | va_start(ap, fmt); |
| 6129 | 6232 | |
| 6130 | | - fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); |
| 6233 | + fprintf(stderr, "\nJIM INTERPRETER PANIC: "); |
| 6131 | 6234 | vfprintf(stderr, fmt, ap); |
| 6132 | | - fprintf(stderr, JIM_NL JIM_NL); |
| 6235 | + fprintf(stderr, "\n\n"); |
| 6133 | 6236 | va_end(ap); |
| 6134 | 6237 | |
| 6135 | 6238 | #ifdef HAVE_BACKTRACE |
| 6136 | 6239 | { |
| 6137 | 6240 | void *array[40]; |
| | @@ -6139,13 +6242,13 @@ |
| 6139 | 6242 | char **strings; |
| 6140 | 6243 | |
| 6141 | 6244 | size = backtrace(array, 40); |
| 6142 | 6245 | strings = backtrace_symbols(array, size); |
| 6143 | 6246 | for (i = 0; i < size; i++) |
| 6144 | | - fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]); |
| 6145 | | - fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL); |
| 6146 | | - fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL); |
| 6247 | + fprintf(stderr, "[backtrace] %s\n", strings[i]); |
| 6248 | + fprintf(stderr, "[backtrace] Include the above lines and the output\n"); |
| 6249 | + fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n"); |
| 6147 | 6250 | } |
| 6148 | 6251 | #endif |
| 6149 | 6252 | |
| 6150 | 6253 | exit(1); |
| 6151 | 6254 | } |
| | @@ -6219,18 +6322,32 @@ |
| 6219 | 6322 | h += (h << 3) + *buf++; |
| 6220 | 6323 | return h; |
| 6221 | 6324 | } |
| 6222 | 6325 | |
| 6223 | 6326 | |
| 6327 | + |
| 6224 | 6328 | |
| 6225 | 6329 | static void JimResetHashTable(Jim_HashTable *ht) |
| 6226 | 6330 | { |
| 6227 | 6331 | ht->table = NULL; |
| 6228 | 6332 | ht->size = 0; |
| 6229 | 6333 | ht->sizemask = 0; |
| 6230 | 6334 | ht->used = 0; |
| 6231 | 6335 | ht->collisions = 0; |
| 6336 | +#ifdef JIM_RANDOMISE_HASH |
| 6337 | + ht->uniq = (rand() ^ time(NULL) ^ clock()); |
| 6338 | +#else |
| 6339 | + ht->uniq = 0; |
| 6340 | +#endif |
| 6341 | +} |
| 6342 | + |
| 6343 | +static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) |
| 6344 | +{ |
| 6345 | + iter->ht = ht; |
| 6346 | + iter->index = -1; |
| 6347 | + iter->entry = NULL; |
| 6348 | + iter->nextEntry = NULL; |
| 6232 | 6349 | } |
| 6233 | 6350 | |
| 6234 | 6351 | |
| 6235 | 6352 | int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) |
| 6236 | 6353 | { |
| | @@ -6260,10 +6377,12 @@ |
| 6260 | 6377 | |
| 6261 | 6378 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6262 | 6379 | n.size = realsize; |
| 6263 | 6380 | n.sizemask = realsize - 1; |
| 6264 | 6381 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6382 | + |
| 6383 | + n.uniq = ht->uniq; |
| 6265 | 6384 | |
| 6266 | 6385 | |
| 6267 | 6386 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6268 | 6387 | |
| 6269 | 6388 | n.used = ht->used; |
| | @@ -6316,20 +6435,27 @@ |
| 6316 | 6435 | int existed; |
| 6317 | 6436 | Jim_HashEntry *entry; |
| 6318 | 6437 | |
| 6319 | 6438 | entry = JimInsertHashEntry(ht, key, 1); |
| 6320 | 6439 | if (entry->key) { |
| 6321 | | - |
| 6322 | | - Jim_FreeEntryVal(ht, entry); |
| 6440 | + if (ht->type->valDestructor && ht->type->valDup) { |
| 6441 | + void *newval = ht->type->valDup(ht->privdata, val); |
| 6442 | + ht->type->valDestructor(ht->privdata, entry->u.val); |
| 6443 | + entry->u.val = newval; |
| 6444 | + } |
| 6445 | + else { |
| 6446 | + Jim_FreeEntryVal(ht, entry); |
| 6447 | + Jim_SetHashVal(ht, entry, val); |
| 6448 | + } |
| 6323 | 6449 | existed = 1; |
| 6324 | 6450 | } |
| 6325 | 6451 | else { |
| 6326 | 6452 | |
| 6327 | 6453 | Jim_SetHashKey(ht, entry, key); |
| 6454 | + Jim_SetHashVal(ht, entry, val); |
| 6328 | 6455 | existed = 0; |
| 6329 | 6456 | } |
| 6330 | | - Jim_SetHashVal(ht, entry, val); |
| 6331 | 6457 | |
| 6332 | 6458 | return existed; |
| 6333 | 6459 | } |
| 6334 | 6460 | |
| 6335 | 6461 | |
| | @@ -6408,15 +6534,11 @@ |
| 6408 | 6534 | } |
| 6409 | 6535 | |
| 6410 | 6536 | Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) |
| 6411 | 6537 | { |
| 6412 | 6538 | Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); |
| 6413 | | - |
| 6414 | | - iter->ht = ht; |
| 6415 | | - iter->index = -1; |
| 6416 | | - iter->entry = NULL; |
| 6417 | | - iter->nextEntry = NULL; |
| 6539 | + JimInitHashTableIterator(ht, iter); |
| 6418 | 6540 | return iter; |
| 6419 | 6541 | } |
| 6420 | 6542 | |
| 6421 | 6543 | Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) |
| 6422 | 6544 | { |
| | @@ -6498,11 +6620,11 @@ |
| 6498 | 6620 | return Jim_GenHashFunction(key, strlen(key)); |
| 6499 | 6621 | } |
| 6500 | 6622 | |
| 6501 | 6623 | static void *JimStringCopyHTDup(void *privdata, const void *key) |
| 6502 | 6624 | { |
| 6503 | | - return strdup(key); |
| 6625 | + return Jim_StrDup(key); |
| 6504 | 6626 | } |
| 6505 | 6627 | |
| 6506 | 6628 | static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 6507 | 6629 | { |
| 6508 | 6630 | return strcmp(key1, key2) == 0; |
| | @@ -6598,11 +6720,11 @@ |
| 6598 | 6720 | freeFunc(stack->vector[i]); |
| 6599 | 6721 | } |
| 6600 | 6722 | |
| 6601 | 6723 | |
| 6602 | 6724 | |
| 6603 | | -#define JIM_TT_NONE 0 |
| 6725 | +#define JIM_TT_NONE 0 |
| 6604 | 6726 | #define JIM_TT_STR 1 |
| 6605 | 6727 | #define JIM_TT_ESC 2 |
| 6606 | 6728 | #define JIM_TT_VAR 3 |
| 6607 | 6729 | #define JIM_TT_DICTSUGAR 4 |
| 6608 | 6730 | #define JIM_TT_CMD 5 |
| | @@ -6630,10 +6752,15 @@ |
| 6630 | 6752 | |
| 6631 | 6753 | |
| 6632 | 6754 | #define JIM_PS_DEF 0 |
| 6633 | 6755 | #define JIM_PS_QUOTE 1 |
| 6634 | 6756 | #define JIM_PS_DICTSUGAR 2 |
| 6757 | + |
| 6758 | +struct JimParseMissing { |
| 6759 | + int ch; |
| 6760 | + int line; |
| 6761 | +}; |
| 6635 | 6762 | |
| 6636 | 6763 | struct JimParserCtx |
| 6637 | 6764 | { |
| 6638 | 6765 | const char *p; |
| 6639 | 6766 | int len; |
| | @@ -6643,17 +6770,11 @@ |
| 6643 | 6770 | int tline; |
| 6644 | 6771 | int tt; |
| 6645 | 6772 | int eof; |
| 6646 | 6773 | int state; |
| 6647 | 6774 | int comment; |
| 6648 | | - char missing; |
| 6649 | | - int missingline; |
| 6650 | | -}; |
| 6651 | | - |
| 6652 | | -struct JimParseResult { |
| 6653 | | - char missing; |
| 6654 | | - int line; |
| 6775 | + struct JimParseMissing missing; |
| 6655 | 6776 | }; |
| 6656 | 6777 | |
| 6657 | 6778 | static int JimParseScript(struct JimParserCtx *pc); |
| 6658 | 6779 | static int JimParseSep(struct JimParserCtx *pc); |
| 6659 | 6780 | static int JimParseEol(struct JimParserCtx *pc); |
| | @@ -6663,11 +6784,10 @@ |
| 6663 | 6784 | static int JimParseBrace(struct JimParserCtx *pc); |
| 6664 | 6785 | static int JimParseStr(struct JimParserCtx *pc); |
| 6665 | 6786 | static int JimParseComment(struct JimParserCtx *pc); |
| 6666 | 6787 | static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6667 | 6788 | static int JimParseSubQuote(struct JimParserCtx *pc); |
| 6668 | | -static void JimParseSubCmd(struct JimParserCtx *pc); |
| 6669 | 6789 | static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); |
| 6670 | 6790 | |
| 6671 | 6791 | static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) |
| 6672 | 6792 | { |
| 6673 | 6793 | pc->p = prg; |
| | @@ -6678,12 +6798,12 @@ |
| 6678 | 6798 | pc->tt = JIM_TT_NONE; |
| 6679 | 6799 | pc->eof = 0; |
| 6680 | 6800 | pc->state = JIM_PS_DEF; |
| 6681 | 6801 | pc->linenr = linenr; |
| 6682 | 6802 | pc->comment = 1; |
| 6683 | | - pc->missing = ' '; |
| 6684 | | - pc->missingline = linenr; |
| 6803 | + pc->missing.ch = ' '; |
| 6804 | + pc->missing.line = linenr; |
| 6685 | 6805 | } |
| 6686 | 6806 | |
| 6687 | 6807 | static int JimParseScript(struct JimParserCtx *pc) |
| 6688 | 6808 | { |
| 6689 | 6809 | while (1) { |
| | @@ -6815,12 +6935,12 @@ |
| 6815 | 6935 | break; |
| 6816 | 6936 | } |
| 6817 | 6937 | pc->p++; |
| 6818 | 6938 | pc->len--; |
| 6819 | 6939 | } |
| 6820 | | - pc->missing = '{'; |
| 6821 | | - pc->missingline = pc->tline; |
| 6940 | + pc->missing.ch = '{'; |
| 6941 | + pc->missing.line = pc->tline; |
| 6822 | 6942 | pc->tend = pc->p - 1; |
| 6823 | 6943 | } |
| 6824 | 6944 | |
| 6825 | 6945 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 6826 | 6946 | { |
| | @@ -6862,12 +6982,12 @@ |
| 6862 | 6982 | break; |
| 6863 | 6983 | } |
| 6864 | 6984 | pc->p++; |
| 6865 | 6985 | pc->len--; |
| 6866 | 6986 | } |
| 6867 | | - pc->missing = '"'; |
| 6868 | | - pc->missingline = line; |
| 6987 | + pc->missing.ch = '"'; |
| 6988 | + pc->missing.line = line; |
| 6869 | 6989 | pc->tend = pc->p - 1; |
| 6870 | 6990 | return tt; |
| 6871 | 6991 | } |
| 6872 | 6992 | |
| 6873 | 6993 | static void JimParseSubCmd(struct JimParserCtx *pc) |
| | @@ -6921,12 +7041,12 @@ |
| 6921 | 7041 | } |
| 6922 | 7042 | startofword = isspace(UCHAR(*pc->p)); |
| 6923 | 7043 | pc->p++; |
| 6924 | 7044 | pc->len--; |
| 6925 | 7045 | } |
| 6926 | | - pc->missing = '['; |
| 6927 | | - pc->missingline = line; |
| 7046 | + pc->missing.ch = '['; |
| 7047 | + pc->missing.line = line; |
| 6928 | 7048 | pc->tend = pc->p - 1; |
| 6929 | 7049 | } |
| 6930 | 7050 | |
| 6931 | 7051 | static int JimParseBrace(struct JimParserCtx *pc) |
| 6932 | 7052 | { |
| | @@ -7066,19 +7186,19 @@ |
| 7066 | 7186 | if (*pc->p == '"') { |
| 7067 | 7187 | pc->state = JIM_PS_QUOTE; |
| 7068 | 7188 | pc->p++; |
| 7069 | 7189 | pc->len--; |
| 7070 | 7190 | |
| 7071 | | - pc->missingline = pc->tline; |
| 7191 | + pc->missing.line = pc->tline; |
| 7072 | 7192 | } |
| 7073 | 7193 | } |
| 7074 | 7194 | pc->tstart = pc->p; |
| 7075 | 7195 | pc->tline = pc->linenr; |
| 7076 | 7196 | while (1) { |
| 7077 | 7197 | if (pc->len == 0) { |
| 7078 | 7198 | if (pc->state == JIM_PS_QUOTE) { |
| 7079 | | - pc->missing = '"'; |
| 7199 | + pc->missing.ch = '"'; |
| 7080 | 7200 | } |
| 7081 | 7201 | pc->tend = pc->p - 1; |
| 7082 | 7202 | pc->tt = JIM_TT_ESC; |
| 7083 | 7203 | return JIM_OK; |
| 7084 | 7204 | } |
| | @@ -7094,10 +7214,14 @@ |
| 7094 | 7214 | pc->linenr++; |
| 7095 | 7215 | } |
| 7096 | 7216 | pc->p++; |
| 7097 | 7217 | pc->len--; |
| 7098 | 7218 | } |
| 7219 | + else if (pc->len == 1) { |
| 7220 | + |
| 7221 | + pc->missing.ch = '\\'; |
| 7222 | + } |
| 7099 | 7223 | break; |
| 7100 | 7224 | case '(': |
| 7101 | 7225 | |
| 7102 | 7226 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7103 | 7227 | break; |
| | @@ -7154,17 +7278,26 @@ |
| 7154 | 7278 | } |
| 7155 | 7279 | |
| 7156 | 7280 | static int JimParseComment(struct JimParserCtx *pc) |
| 7157 | 7281 | { |
| 7158 | 7282 | while (*pc->p) { |
| 7159 | | - if (*pc->p == '\n') { |
| 7283 | + if (*pc->p == '\\') { |
| 7284 | + pc->p++; |
| 7285 | + pc->len--; |
| 7286 | + if (pc->len == 0) { |
| 7287 | + pc->missing.ch = '\\'; |
| 7288 | + return JIM_OK; |
| 7289 | + } |
| 7290 | + if (*pc->p == '\n') { |
| 7291 | + pc->linenr++; |
| 7292 | + } |
| 7293 | + } |
| 7294 | + else if (*pc->p == '\n') { |
| 7295 | + pc->p++; |
| 7296 | + pc->len--; |
| 7160 | 7297 | pc->linenr++; |
| 7161 | | - if (*(pc->p - 1) != '\\') { |
| 7162 | | - pc->p++; |
| 7163 | | - pc->len--; |
| 7164 | | - return JIM_OK; |
| 7165 | | - } |
| 7298 | + break; |
| 7166 | 7299 | } |
| 7167 | 7300 | pc->p++; |
| 7168 | 7301 | pc->len--; |
| 7169 | 7302 | } |
| 7170 | 7303 | return JIM_OK; |
| | @@ -7382,13 +7515,13 @@ |
| 7382 | 7515 | JimParserInit(&parser, s, len, 1); |
| 7383 | 7516 | while (!parser.eof) { |
| 7384 | 7517 | JimParseScript(&parser); |
| 7385 | 7518 | } |
| 7386 | 7519 | if (stateCharPtr) { |
| 7387 | | - *stateCharPtr = parser.missing; |
| 7520 | + *stateCharPtr = parser.missing.ch; |
| 7388 | 7521 | } |
| 7389 | | - return parser.missing == ' '; |
| 7522 | + return parser.missing.ch == ' '; |
| 7390 | 7523 | } |
| 7391 | 7524 | |
| 7392 | 7525 | static int JimParseListSep(struct JimParserCtx *pc); |
| 7393 | 7526 | static int JimParseListStr(struct JimParserCtx *pc); |
| 7394 | 7527 | static int JimParseListQuote(struct JimParserCtx *pc); |
| | @@ -7546,17 +7679,21 @@ |
| 7546 | 7679 | objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; |
| 7547 | 7680 | if (objPtr->nextObjPtr) |
| 7548 | 7681 | objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; |
| 7549 | 7682 | if (interp->liveList == objPtr) |
| 7550 | 7683 | interp->liveList = objPtr->nextObjPtr; |
| 7684 | +#ifdef JIM_DISABLE_OBJECT_POOL |
| 7685 | + Jim_Free(objPtr); |
| 7686 | +#else |
| 7551 | 7687 | |
| 7552 | 7688 | objPtr->prevObjPtr = NULL; |
| 7553 | 7689 | objPtr->nextObjPtr = interp->freeList; |
| 7554 | 7690 | if (interp->freeList) |
| 7555 | 7691 | interp->freeList->prevObjPtr = objPtr; |
| 7556 | 7692 | interp->freeList = objPtr; |
| 7557 | 7693 | objPtr->refCount = -1; |
| 7694 | +#endif |
| 7558 | 7695 | } |
| 7559 | 7696 | |
| 7560 | 7697 | |
| 7561 | 7698 | void Jim_InvalidateStringRep(Jim_Obj *objPtr) |
| 7562 | 7699 | { |
| | @@ -7636,10 +7773,16 @@ |
| 7636 | 7773 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7637 | 7774 | objPtr->typePtr->updateStringProc(objPtr); |
| 7638 | 7775 | } |
| 7639 | 7776 | return objPtr->bytes; |
| 7640 | 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 | +} |
| 7641 | 7784 | |
| 7642 | 7785 | static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 7643 | 7786 | static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 7644 | 7787 | |
| 7645 | 7788 | static const Jim_ObjType dictSubstObjType = { |
| | @@ -7677,11 +7820,10 @@ |
| 7677 | 7820 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 7678 | 7821 | { |
| 7679 | 7822 | JIM_NOTUSED(interp); |
| 7680 | 7823 | |
| 7681 | 7824 | dupPtr->internalRep.strValue.maxLength = srcPtr->length; |
| 7682 | | - |
| 7683 | 7825 | dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; |
| 7684 | 7826 | } |
| 7685 | 7827 | |
| 7686 | 7828 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7687 | 7829 | { |
| | @@ -7726,18 +7868,17 @@ |
| 7726 | 7868 | if (len == -1) |
| 7727 | 7869 | len = strlen(s); |
| 7728 | 7870 | |
| 7729 | 7871 | if (len == 0) { |
| 7730 | 7872 | objPtr->bytes = JimEmptyStringRep; |
| 7731 | | - objPtr->length = 0; |
| 7732 | 7873 | } |
| 7733 | 7874 | else { |
| 7734 | 7875 | objPtr->bytes = Jim_Alloc(len + 1); |
| 7735 | | - objPtr->length = len; |
| 7736 | 7876 | memcpy(objPtr->bytes, s, len); |
| 7737 | 7877 | objPtr->bytes[len] = '\0'; |
| 7738 | 7878 | } |
| 7879 | + objPtr->length = len; |
| 7739 | 7880 | |
| 7740 | 7881 | |
| 7741 | 7882 | objPtr->typePtr = NULL; |
| 7742 | 7883 | return objPtr; |
| 7743 | 7884 | } |
| | @@ -7765,11 +7906,11 @@ |
| 7765 | 7906 | Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) |
| 7766 | 7907 | { |
| 7767 | 7908 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 7768 | 7909 | |
| 7769 | 7910 | objPtr->bytes = s; |
| 7770 | | - objPtr->length = len == -1 ? strlen(s) : len; |
| 7911 | + objPtr->length = (len == -1) ? strlen(s) : len; |
| 7771 | 7912 | objPtr->typePtr = NULL; |
| 7772 | 7913 | return objPtr; |
| 7773 | 7914 | } |
| 7774 | 7915 | |
| 7775 | 7916 | static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) |
| | @@ -7794,17 +7935,17 @@ |
| 7794 | 7935 | } |
| 7795 | 7936 | objPtr->internalRep.strValue.maxLength = needlen; |
| 7796 | 7937 | } |
| 7797 | 7938 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 7798 | 7939 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 7940 | + |
| 7799 | 7941 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 7800 | 7942 | |
| 7801 | 7943 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 7802 | 7944 | } |
| 7803 | 7945 | objPtr->length += len; |
| 7804 | 7946 | } |
| 7805 | | - |
| 7806 | 7947 | |
| 7807 | 7948 | void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) |
| 7808 | 7949 | { |
| 7809 | 7950 | JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); |
| 7810 | 7951 | SetStringFromAny(interp, objPtr); |
| | @@ -7812,13 +7953,11 @@ |
| 7812 | 7953 | } |
| 7813 | 7954 | |
| 7814 | 7955 | void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) |
| 7815 | 7956 | { |
| 7816 | 7957 | int len; |
| 7817 | | - const char *str; |
| 7818 | | - |
| 7819 | | - str = Jim_GetString(appendObjPtr, &len); |
| 7958 | + const char *str = Jim_GetString(appendObjPtr, &len); |
| 7820 | 7959 | Jim_AppendString(interp, objPtr, str, len); |
| 7821 | 7960 | } |
| 7822 | 7961 | |
| 7823 | 7962 | void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) |
| 7824 | 7963 | { |
| | @@ -7825,11 +7964,11 @@ |
| 7825 | 7964 | va_list ap; |
| 7826 | 7965 | |
| 7827 | 7966 | SetStringFromAny(interp, objPtr); |
| 7828 | 7967 | va_start(ap, objPtr); |
| 7829 | 7968 | while (1) { |
| 7830 | | - char *s = va_arg(ap, char *); |
| 7969 | + const char *s = va_arg(ap, const char *); |
| 7831 | 7970 | |
| 7832 | 7971 | if (s == NULL) |
| 7833 | 7972 | break; |
| 7834 | 7973 | Jim_AppendString(interp, objPtr, s, -1); |
| 7835 | 7974 | } |
| | @@ -7836,20 +7975,20 @@ |
| 7836 | 7975 | va_end(ap); |
| 7837 | 7976 | } |
| 7838 | 7977 | |
| 7839 | 7978 | int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) |
| 7840 | 7979 | { |
| 7841 | | - const char *aStr, *bStr; |
| 7842 | | - int aLen, bLen; |
| 7843 | | - |
| 7844 | | - if (aObjPtr == bObjPtr) |
| 7980 | + if (aObjPtr == bObjPtr) { |
| 7845 | 7981 | return 1; |
| 7846 | | - aStr = Jim_GetString(aObjPtr, &aLen); |
| 7847 | | - bStr = Jim_GetString(bObjPtr, &bLen); |
| 7848 | | - if (aLen != bLen) |
| 7849 | | - return 0; |
| 7850 | | - return JimStringCompare(aStr, aLen, bStr, bLen) == 0; |
| 7982 | + } |
| 7983 | + else { |
| 7984 | + int Alen, Blen; |
| 7985 | + const char *sA = Jim_GetString(aObjPtr, &Alen); |
| 7986 | + const char *sB = Jim_GetString(bObjPtr, &Blen); |
| 7987 | + |
| 7988 | + return Alen == Blen && memcmp(sA, sB, Alen) == 0; |
| 7989 | + } |
| 7851 | 7990 | } |
| 7852 | 7991 | |
| 7853 | 7992 | int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) |
| 7854 | 7993 | { |
| 7855 | 7994 | return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); |
| | @@ -8010,11 +8149,11 @@ |
| 8010 | 8149 | static void JimStrCopyUpperLower(char *dest, const char *str, int uc) |
| 8011 | 8150 | { |
| 8012 | 8151 | while (*str) { |
| 8013 | 8152 | int c; |
| 8014 | 8153 | str += utf8_tounicode(str, &c); |
| 8015 | | - dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c)); |
| 8154 | + dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c)); |
| 8016 | 8155 | } |
| 8017 | 8156 | *dest = 0; |
| 8018 | 8157 | } |
| 8019 | 8158 | |
| 8020 | 8159 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) |
| | @@ -8070,11 +8209,11 @@ |
| 8070 | 8209 | len *= 2; |
| 8071 | 8210 | #endif |
| 8072 | 8211 | buf = p = Jim_Alloc(len + 1); |
| 8073 | 8212 | |
| 8074 | 8213 | str += utf8_tounicode(str, &c); |
| 8075 | | - p += utf8_fromunicode(p, utf8_title(c)); |
| 8214 | + p += utf8_getchars(p, utf8_title(c)); |
| 8076 | 8215 | |
| 8077 | 8216 | JimStrCopyUpperLower(p, str, 0); |
| 8078 | 8217 | |
| 8079 | 8218 | return Jim_NewStringObjNoAlloc(interp, buf, -1); |
| 8080 | 8219 | } |
| | @@ -8177,10 +8316,11 @@ |
| 8177 | 8316 | if (nontrim == NULL) { |
| 8178 | 8317 | |
| 8179 | 8318 | return Jim_NewEmptyStringObj(interp); |
| 8180 | 8319 | } |
| 8181 | 8320 | if (nontrim == strObjPtr->bytes + len) { |
| 8321 | + |
| 8182 | 8322 | return strObjPtr; |
| 8183 | 8323 | } |
| 8184 | 8324 | |
| 8185 | 8325 | if (Jim_IsShared(strObjPtr)) { |
| 8186 | 8326 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| | @@ -8200,19 +8340,28 @@ |
| 8200 | 8340 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8201 | 8341 | |
| 8202 | 8342 | |
| 8203 | 8343 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8204 | 8344 | |
| 8205 | | - if (objPtr != strObjPtr) { |
| 8345 | + |
| 8346 | + if (objPtr != strObjPtr && objPtr->refCount == 0) { |
| 8206 | 8347 | |
| 8207 | | - Jim_IncrRefCount(objPtr); |
| 8208 | | - Jim_DecrRefCount(interp, objPtr); |
| 8348 | + Jim_FreeNewObj(interp, objPtr); |
| 8209 | 8349 | } |
| 8210 | 8350 | |
| 8211 | 8351 | return strObjPtr; |
| 8212 | 8352 | } |
| 8213 | 8353 | |
| 8354 | + |
| 8355 | +#ifdef HAVE_ISASCII |
| 8356 | +#define jim_isascii isascii |
| 8357 | +#else |
| 8358 | +static int jim_isascii(int c) |
| 8359 | +{ |
| 8360 | + return !(c & ~0x7f); |
| 8361 | +} |
| 8362 | +#endif |
| 8214 | 8363 | |
| 8215 | 8364 | static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) |
| 8216 | 8365 | { |
| 8217 | 8366 | static const char * const strclassnames[] = { |
| 8218 | 8367 | "integer", "alpha", "alnum", "ascii", "digit", |
| | @@ -8235,32 +8384,32 @@ |
| 8235 | 8384 | return JIM_ERR; |
| 8236 | 8385 | } |
| 8237 | 8386 | |
| 8238 | 8387 | str = Jim_GetString(strObjPtr, &len); |
| 8239 | 8388 | if (len == 0) { |
| 8240 | | - Jim_SetResultInt(interp, !strict); |
| 8389 | + Jim_SetResultBool(interp, !strict); |
| 8241 | 8390 | return JIM_OK; |
| 8242 | 8391 | } |
| 8243 | 8392 | |
| 8244 | 8393 | switch (strclass) { |
| 8245 | 8394 | case STR_IS_INTEGER: |
| 8246 | 8395 | { |
| 8247 | 8396 | jim_wide w; |
| 8248 | | - Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); |
| 8397 | + Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); |
| 8249 | 8398 | return JIM_OK; |
| 8250 | 8399 | } |
| 8251 | 8400 | |
| 8252 | 8401 | case STR_IS_DOUBLE: |
| 8253 | 8402 | { |
| 8254 | 8403 | double d; |
| 8255 | | - Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8404 | + Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8256 | 8405 | return JIM_OK; |
| 8257 | 8406 | } |
| 8258 | 8407 | |
| 8259 | 8408 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8260 | 8409 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| 8261 | | - case STR_IS_ASCII: isclassfunc = isascii; break; |
| 8410 | + case STR_IS_ASCII: isclassfunc = jim_isascii; break; |
| 8262 | 8411 | case STR_IS_DIGIT: isclassfunc = isdigit; break; |
| 8263 | 8412 | case STR_IS_LOWER: isclassfunc = islower; break; |
| 8264 | 8413 | case STR_IS_UPPER: isclassfunc = isupper; break; |
| 8265 | 8414 | case STR_IS_SPACE: isclassfunc = isspace; break; |
| 8266 | 8415 | case STR_IS_XDIGIT: isclassfunc = isxdigit; break; |
| | @@ -8272,15 +8421,15 @@ |
| 8272 | 8421 | return JIM_ERR; |
| 8273 | 8422 | } |
| 8274 | 8423 | |
| 8275 | 8424 | for (i = 0; i < len; i++) { |
| 8276 | 8425 | if (!isclassfunc(str[i])) { |
| 8277 | | - Jim_SetResultInt(interp, 0); |
| 8426 | + Jim_SetResultBool(interp, 0); |
| 8278 | 8427 | return JIM_OK; |
| 8279 | 8428 | } |
| 8280 | 8429 | } |
| 8281 | | - Jim_SetResultInt(interp, 1); |
| 8430 | + Jim_SetResultBool(interp, 1); |
| 8282 | 8431 | return JIM_OK; |
| 8283 | 8432 | } |
| 8284 | 8433 | |
| 8285 | 8434 | |
| 8286 | 8435 | |
| | @@ -8292,17 +8441,19 @@ |
| 8292 | 8441 | JIM_TYPE_REFERENCES, |
| 8293 | 8442 | }; |
| 8294 | 8443 | |
| 8295 | 8444 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) |
| 8296 | 8445 | { |
| 8297 | | - if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) |
| 8446 | + if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { |
| 8298 | 8447 | return 1; |
| 8448 | + } |
| 8299 | 8449 | else { |
| 8300 | 8450 | const char *objStr = Jim_String(objPtr); |
| 8301 | 8451 | |
| 8302 | 8452 | if (strcmp(str, objStr) != 0) |
| 8303 | 8453 | return 0; |
| 8454 | + |
| 8304 | 8455 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8305 | 8456 | Jim_FreeIntRep(interp, objPtr); |
| 8306 | 8457 | objPtr->typePtr = &comparedStringObjType; |
| 8307 | 8458 | } |
| 8308 | 8459 | objPtr->internalRep.ptr = (char *)str; |
| | @@ -8344,24 +8495,23 @@ |
| 8344 | 8495 | |
| 8345 | 8496 | static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, |
| 8346 | 8497 | Jim_Obj *fileNameObj, int lineNumber) |
| 8347 | 8498 | { |
| 8348 | 8499 | JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); |
| 8349 | | - JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object")); |
| 8500 | + JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); |
| 8350 | 8501 | Jim_IncrRefCount(fileNameObj); |
| 8351 | 8502 | objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; |
| 8352 | 8503 | objPtr->internalRep.sourceValue.lineNumber = lineNumber; |
| 8353 | 8504 | objPtr->typePtr = &sourceObjType; |
| 8354 | 8505 | } |
| 8355 | 8506 | |
| 8356 | | - |
| 8357 | 8507 | static const Jim_ObjType scriptLineObjType = { |
| 8358 | 8508 | "scriptline", |
| 8359 | 8509 | NULL, |
| 8360 | 8510 | NULL, |
| 8361 | 8511 | NULL, |
| 8362 | | - 0, |
| 8512 | + JIM_NONE, |
| 8363 | 8513 | }; |
| 8364 | 8514 | |
| 8365 | 8515 | static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) |
| 8366 | 8516 | { |
| 8367 | 8517 | Jim_Obj *objPtr; |
| | @@ -8378,15 +8528,14 @@ |
| 8378 | 8528 | objPtr->internalRep.scriptLineValue.line = line; |
| 8379 | 8529 | |
| 8380 | 8530 | return objPtr; |
| 8381 | 8531 | } |
| 8382 | 8532 | |
| 8383 | | -#define JIM_CMDSTRUCT_EXPAND -1 |
| 8384 | | - |
| 8385 | 8533 | static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 8386 | 8534 | static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8387 | | -static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result); |
| 8535 | +static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8536 | +static int JimParseCheckMissing(Jim_Interp *interp, int ch); |
| 8388 | 8537 | |
| 8389 | 8538 | static const Jim_ObjType scriptObjType = { |
| 8390 | 8539 | "script", |
| 8391 | 8540 | FreeScriptInternalRep, |
| 8392 | 8541 | DupScriptInternalRep, |
| | @@ -8394,34 +8543,33 @@ |
| 8394 | 8543 | JIM_TYPE_REFERENCES, |
| 8395 | 8544 | }; |
| 8396 | 8545 | |
| 8397 | 8546 | typedef struct ScriptToken |
| 8398 | 8547 | { |
| 8399 | | - int type; |
| 8400 | 8548 | Jim_Obj *objPtr; |
| 8549 | + int type; |
| 8401 | 8550 | } ScriptToken; |
| 8402 | 8551 | |
| 8403 | 8552 | typedef struct ScriptObj |
| 8404 | 8553 | { |
| 8405 | | - int len; |
| 8406 | 8554 | ScriptToken *token; |
| 8555 | + Jim_Obj *fileNameObj; |
| 8556 | + int len; |
| 8407 | 8557 | int substFlags; |
| 8408 | 8558 | int inUse; /* Used to share a ScriptObj. Currently |
| 8409 | 8559 | only used by Jim_EvalObj() as protection against |
| 8410 | 8560 | shimmering of the currently evaluated object. */ |
| 8411 | | - Jim_Obj *fileNameObj; |
| 8412 | 8561 | int firstline; |
| 8413 | 8562 | int linenr; |
| 8414 | 8563 | } ScriptObj; |
| 8415 | 8564 | |
| 8416 | 8565 | void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8417 | 8566 | { |
| 8418 | 8567 | int i; |
| 8419 | 8568 | struct ScriptObj *script = (void *)objPtr->internalRep.ptr; |
| 8420 | 8569 | |
| 8421 | | - script->inUse--; |
| 8422 | | - if (script->inUse != 0) |
| 8570 | + if (--script->inUse != 0) |
| 8423 | 8571 | return; |
| 8424 | 8572 | for (i = 0; i < script->len; i++) { |
| 8425 | 8573 | Jim_DecrRefCount(interp, script->token[i].objPtr); |
| 8426 | 8574 | } |
| 8427 | 8575 | Jim_Free(script->token); |
| | @@ -8432,11 +8580,10 @@ |
| 8432 | 8580 | void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 8433 | 8581 | { |
| 8434 | 8582 | JIM_NOTUSED(interp); |
| 8435 | 8583 | JIM_NOTUSED(srcPtr); |
| 8436 | 8584 | |
| 8437 | | - |
| 8438 | 8585 | dupPtr->typePtr = NULL; |
| 8439 | 8586 | } |
| 8440 | 8587 | |
| 8441 | 8588 | typedef struct |
| 8442 | 8589 | { |
| | @@ -8631,11 +8778,11 @@ |
| 8631 | 8778 | token--; |
| 8632 | 8779 | } |
| 8633 | 8780 | |
| 8634 | 8781 | script->len = token - script->token; |
| 8635 | 8782 | |
| 8636 | | - assert(script->len < count); |
| 8783 | + JimPanic((script->len >= count, "allocated script array is too short")); |
| 8637 | 8784 | |
| 8638 | 8785 | #ifdef DEBUG_SHOW_SCRIPT |
| 8639 | 8786 | printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); |
| 8640 | 8787 | for (i = 0; i < script->len; i++) { |
| 8641 | 8788 | const ScriptToken *t = &script->token[i]; |
| | @@ -8642,10 +8789,35 @@ |
| 8642 | 8789 | printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); |
| 8643 | 8790 | } |
| 8644 | 8791 | #endif |
| 8645 | 8792 | |
| 8646 | 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 | +} |
| 8647 | 8819 | |
| 8648 | 8820 | static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8649 | 8821 | ParseTokenList *tokenlist) |
| 8650 | 8822 | { |
| 8651 | 8823 | int i; |
| | @@ -8664,18 +8836,19 @@ |
| 8664 | 8836 | } |
| 8665 | 8837 | |
| 8666 | 8838 | script->len = i; |
| 8667 | 8839 | } |
| 8668 | 8840 | |
| 8669 | | -static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result) |
| 8841 | +static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 8670 | 8842 | { |
| 8671 | 8843 | int scriptTextLen; |
| 8672 | 8844 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 8673 | 8845 | struct JimParserCtx parser; |
| 8674 | 8846 | struct ScriptObj *script; |
| 8675 | 8847 | ParseTokenList tokenlist; |
| 8676 | 8848 | int line = 1; |
| 8849 | + int retcode = JIM_OK; |
| 8677 | 8850 | |
| 8678 | 8851 | |
| 8679 | 8852 | if (objPtr->typePtr == &sourceObjType) { |
| 8680 | 8853 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 8681 | 8854 | } |
| | @@ -8687,16 +8860,12 @@ |
| 8687 | 8860 | while (!parser.eof) { |
| 8688 | 8861 | JimParseScript(&parser); |
| 8689 | 8862 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 8690 | 8863 | parser.tline); |
| 8691 | 8864 | } |
| 8692 | | - if (result && parser.missing != ' ') { |
| 8693 | | - ScriptTokenListFree(&tokenlist); |
| 8694 | | - result->missing = parser.missing; |
| 8695 | | - result->line = parser.missingline; |
| 8696 | | - return JIM_ERR; |
| 8697 | | - } |
| 8865 | + |
| 8866 | + retcode = JimParseCheckMissing(interp, parser.missing.ch); |
| 8698 | 8867 | |
| 8699 | 8868 | |
| 8700 | 8869 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 8701 | 8870 | |
| 8702 | 8871 | |
| | @@ -8707,10 +8876,11 @@ |
| 8707 | 8876 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 8708 | 8877 | } |
| 8709 | 8878 | else { |
| 8710 | 8879 | script->fileNameObj = interp->emptyObj; |
| 8711 | 8880 | } |
| 8881 | + script->linenr = parser.missing.line; |
| 8712 | 8882 | Jim_IncrRefCount(script->fileNameObj); |
| 8713 | 8883 | |
| 8714 | 8884 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 8715 | 8885 | |
| 8716 | 8886 | |
| | @@ -8719,11 +8889,11 @@ |
| 8719 | 8889 | |
| 8720 | 8890 | Jim_FreeIntRep(interp, objPtr); |
| 8721 | 8891 | Jim_SetIntRepPtr(objPtr, script); |
| 8722 | 8892 | objPtr->typePtr = &scriptObjType; |
| 8723 | 8893 | |
| 8724 | | - return JIM_OK; |
| 8894 | + return retcode; |
| 8725 | 8895 | } |
| 8726 | 8896 | |
| 8727 | 8897 | ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8728 | 8898 | { |
| 8729 | 8899 | if (objPtr == interp->emptyObj) { |
| | @@ -8730,11 +8900,13 @@ |
| 8730 | 8900 | |
| 8731 | 8901 | objPtr = interp->nullScriptObj; |
| 8732 | 8902 | } |
| 8733 | 8903 | |
| 8734 | 8904 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 8735 | | - SetScriptFromAny(interp, objPtr, NULL); |
| 8905 | + if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) { |
| 8906 | + return NULL; |
| 8907 | + } |
| 8736 | 8908 | } |
| 8737 | 8909 | return (ScriptObj *) Jim_GetIntRepPtr(objPtr); |
| 8738 | 8910 | } |
| 8739 | 8911 | |
| 8740 | 8912 | static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) |
| | @@ -8815,10 +8987,26 @@ |
| 8815 | 8987 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 8816 | 8988 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 8817 | 8989 | } |
| 8818 | 8990 | return nsObj; |
| 8819 | 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 | +} |
| 8820 | 9008 | |
| 8821 | 9009 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 8822 | 9010 | { |
| 8823 | 9011 | Jim_Obj *objPtr = interp->emptyObj; |
| 8824 | 9012 | |
| | @@ -8842,10 +9030,15 @@ |
| 8842 | 9030 | |
| 8843 | 9031 | #else |
| 8844 | 9032 | |
| 8845 | 9033 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 8846 | 9034 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9035 | + |
| 9036 | +Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9037 | +{ |
| 9038 | + return nameObjPtr; |
| 9039 | +} |
| 8847 | 9040 | #endif |
| 8848 | 9041 | |
| 8849 | 9042 | static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) |
| 8850 | 9043 | { |
| 8851 | 9044 | Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); |
| | @@ -8854,12 +9047,12 @@ |
| 8854 | 9047 | Jim_InterpIncrProcEpoch(interp); |
| 8855 | 9048 | } |
| 8856 | 9049 | |
| 8857 | 9050 | if (he && interp->local) { |
| 8858 | 9051 | |
| 8859 | | - cmd->prevCmd = he->u.val; |
| 8860 | | - he->u.val = cmd; |
| 9052 | + cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9053 | + Jim_SetHashVal(&interp->commands, he, cmd); |
| 8861 | 9054 | } |
| 8862 | 9055 | else { |
| 8863 | 9056 | if (he) { |
| 8864 | 9057 | |
| 8865 | 9058 | Jim_DeleteHashEntry(&interp->commands, name); |
| | @@ -8898,19 +9091,19 @@ |
| 8898 | 9091 | } |
| 8899 | 9092 | |
| 8900 | 9093 | cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); |
| 8901 | 9094 | Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); |
| 8902 | 9095 | for (i = 0; i < len; i++) { |
| 8903 | | - Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL; |
| 9096 | + Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 8904 | 9097 | Jim_Var *varPtr; |
| 8905 | 9098 | int subLen; |
| 8906 | 9099 | |
| 8907 | | - Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE); |
| 9100 | + objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 8908 | 9101 | |
| 8909 | 9102 | subLen = Jim_ListLength(interp, objPtr); |
| 8910 | 9103 | if (subLen == 1 || subLen == 2) { |
| 8911 | | - Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE); |
| 9104 | + nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 8912 | 9105 | if (subLen == 1) { |
| 8913 | 9106 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 8914 | 9107 | if (initObjPtr == NULL) { |
| 8915 | 9108 | Jim_SetResultFormatted(interp, |
| 8916 | 9109 | "variable for initialization of static \"%#s\" not found in the local context", |
| | @@ -8917,11 +9110,11 @@ |
| 8917 | 9110 | nameObjPtr); |
| 8918 | 9111 | return JIM_ERR; |
| 8919 | 9112 | } |
| 8920 | 9113 | } |
| 8921 | 9114 | else { |
| 8922 | | - Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE); |
| 9115 | + initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); |
| 8923 | 9116 | } |
| 8924 | 9117 | if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { |
| 8925 | 9118 | return JIM_ERR; |
| 8926 | 9119 | } |
| 8927 | 9120 | |
| | @@ -9003,11 +9196,11 @@ |
| 9003 | 9196 | Jim_Obj *nameObjPtr; |
| 9004 | 9197 | Jim_Obj *defaultObjPtr; |
| 9005 | 9198 | int len; |
| 9006 | 9199 | |
| 9007 | 9200 | |
| 9008 | | - Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE); |
| 9201 | + argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); |
| 9009 | 9202 | len = Jim_ListLength(interp, argPtr); |
| 9010 | 9203 | if (len == 0) { |
| 9011 | 9204 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9012 | 9205 | err: |
| 9013 | 9206 | JimDecrCmdRefCount(interp, cmdPtr); |
| | @@ -9018,12 +9211,12 @@ |
| 9018 | 9211 | goto err; |
| 9019 | 9212 | } |
| 9020 | 9213 | |
| 9021 | 9214 | if (len == 2) { |
| 9022 | 9215 | |
| 9023 | | - Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE); |
| 9024 | | - Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE); |
| 9216 | + nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); |
| 9217 | + defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); |
| 9025 | 9218 | } |
| 9026 | 9219 | else { |
| 9027 | 9220 | |
| 9028 | 9221 | nameObjPtr = argPtr; |
| 9029 | 9222 | defaultObjPtr = NULL; |
| | @@ -9097,11 +9290,11 @@ |
| 9097 | 9290 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9098 | 9291 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9099 | 9292 | } |
| 9100 | 9293 | else { |
| 9101 | 9294 | |
| 9102 | | - cmdPtr = he->u.val; |
| 9295 | + cmdPtr = Jim_GetHashEntryVal(he); |
| 9103 | 9296 | JimIncrCmdRefCount(cmdPtr); |
| 9104 | 9297 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9105 | 9298 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9106 | 9299 | |
| 9107 | 9300 | |
| | @@ -9182,11 +9375,11 @@ |
| 9182 | 9375 | return NULL; |
| 9183 | 9376 | } |
| 9184 | 9377 | #ifdef jim_ext_namespace |
| 9185 | 9378 | found: |
| 9186 | 9379 | #endif |
| 9187 | | - cmd = (Jim_Cmd *)he->u.val; |
| 9380 | + cmd = Jim_GetHashEntryVal(he); |
| 9188 | 9381 | |
| 9189 | 9382 | |
| 9190 | 9383 | Jim_FreeIntRep(interp, objPtr); |
| 9191 | 9384 | objPtr->typePtr = &commandObjType; |
| 9192 | 9385 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| | @@ -9288,11 +9481,11 @@ |
| 9288 | 9481 | |
| 9289 | 9482 | |
| 9290 | 9483 | Jim_FreeIntRep(interp, objPtr); |
| 9291 | 9484 | objPtr->typePtr = &variableObjType; |
| 9292 | 9485 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9293 | | - objPtr->internalRep.varValue.varPtr = he->u.val; |
| 9486 | + objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 9294 | 9487 | objPtr->internalRep.varValue.global = global; |
| 9295 | 9488 | return JIM_OK; |
| 9296 | 9489 | } |
| 9297 | 9490 | |
| 9298 | 9491 | |
| | @@ -9606,11 +9799,11 @@ |
| 9606 | 9799 | } |
| 9607 | 9800 | |
| 9608 | 9801 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 9609 | 9802 | if (retval == JIM_OK) { |
| 9610 | 9803 | |
| 9611 | | - JimChangeCallFrameId(interp, framePtr); |
| 9804 | + framePtr->id = interp->callFrameEpoch++; |
| 9612 | 9805 | } |
| 9613 | 9806 | } |
| 9614 | 9807 | } |
| 9615 | 9808 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| 9616 | 9809 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); |
| | @@ -9690,28 +9883,17 @@ |
| 9690 | 9883 | return NULL; |
| 9691 | 9884 | } |
| 9692 | 9885 | |
| 9693 | 9886 | ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9694 | 9887 | if (ret != JIM_OK) { |
| 9695 | | - resObjPtr = NULL; |
| 9696 | | - if (ret < 0) { |
| 9697 | | - Jim_SetResultFormatted(interp, |
| 9698 | | - "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr); |
| 9699 | | - } |
| 9700 | | - else { |
| 9701 | | - Jim_SetResultFormatted(interp, |
| 9702 | | - "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr); |
| 9703 | | - } |
| 9888 | + Jim_SetResultFormatted(interp, |
| 9889 | + "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, |
| 9890 | + ret < 0 ? "variable isn't" : "no such element in"); |
| 9704 | 9891 | } |
| 9705 | 9892 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 9706 | | - dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr); |
| 9707 | | - if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) { |
| 9708 | | - |
| 9709 | | - JimPanic((1, "SetVariable failed for JIM_UNSHARED")); |
| 9710 | | - } |
| 9711 | 9893 | |
| 9712 | | - Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); |
| 9894 | + Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); |
| 9713 | 9895 | } |
| 9714 | 9896 | |
| 9715 | 9897 | return resObjPtr; |
| 9716 | 9898 | } |
| 9717 | 9899 | |
| | @@ -9808,68 +9990,67 @@ |
| 9808 | 9990 | Jim_CallFrame *cf; |
| 9809 | 9991 | |
| 9810 | 9992 | if (interp->freeFramesList) { |
| 9811 | 9993 | cf = interp->freeFramesList; |
| 9812 | 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; |
| 9813 | 10006 | } |
| 9814 | 10007 | else { |
| 9815 | 10008 | cf = Jim_Alloc(sizeof(*cf)); |
| 9816 | | - cf->vars.table = NULL; |
| 10009 | + memset(cf, 0, sizeof(*cf)); |
| 10010 | + |
| 10011 | + Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); |
| 9817 | 10012 | } |
| 9818 | 10013 | |
| 9819 | 10014 | cf->id = interp->callFrameEpoch++; |
| 9820 | 10015 | cf->parent = parent; |
| 9821 | 10016 | cf->level = parent ? parent->level + 1 : 0; |
| 9822 | | - cf->argv = NULL; |
| 9823 | | - cf->argc = 0; |
| 9824 | | - cf->procArgsObjPtr = NULL; |
| 9825 | | - cf->procBodyObjPtr = NULL; |
| 9826 | | - cf->next = NULL; |
| 9827 | | - cf->staticVars = NULL; |
| 9828 | | - cf->localCommands = NULL; |
| 9829 | | - |
| 9830 | 10017 | cf->nsObj = nsObj; |
| 9831 | 10018 | Jim_IncrRefCount(nsObj); |
| 9832 | | - if (cf->vars.table == NULL) |
| 9833 | | - Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); |
| 10019 | + |
| 9834 | 10020 | return cf; |
| 9835 | 10021 | } |
| 9836 | 10022 | |
| 9837 | | - |
| 9838 | | -static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf) |
| 9839 | | -{ |
| 9840 | | - cf->id = interp->callFrameEpoch++; |
| 9841 | | -} |
| 9842 | | - |
| 9843 | 10023 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 9844 | 10024 | { |
| 9845 | 10025 | |
| 9846 | 10026 | if (localCommands) { |
| 9847 | 10027 | Jim_Obj *cmdNameObj; |
| 9848 | 10028 | |
| 9849 | 10029 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 9850 | 10030 | Jim_HashEntry *he; |
| 9851 | 10031 | Jim_Obj *fqObjName; |
| 10032 | + Jim_HashTable *ht = &interp->commands; |
| 9852 | 10033 | |
| 9853 | 10034 | const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); |
| 9854 | 10035 | |
| 9855 | | - he = Jim_FindHashEntry(&interp->commands, fqname); |
| 10036 | + he = Jim_FindHashEntry(ht, fqname); |
| 9856 | 10037 | |
| 9857 | 10038 | if (he) { |
| 9858 | | - Jim_Cmd *cmd = he->u.val; |
| 10039 | + Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 9859 | 10040 | if (cmd->prevCmd) { |
| 9860 | 10041 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 9861 | 10042 | cmd->prevCmd = NULL; |
| 9862 | 10043 | |
| 9863 | 10044 | |
| 9864 | 10045 | JimDecrCmdRefCount(interp, cmd); |
| 9865 | 10046 | |
| 9866 | 10047 | |
| 9867 | | - he->u.val = prevCmd; |
| 10048 | + Jim_SetHashVal(ht, he, prevCmd); |
| 9868 | 10049 | } |
| 9869 | 10050 | else { |
| 9870 | | - Jim_DeleteHashEntry(&interp->commands, fqname); |
| 10051 | + Jim_DeleteHashEntry(ht, fqname); |
| 9871 | 10052 | Jim_InterpIncrProcEpoch(interp); |
| 9872 | 10053 | } |
| 9873 | 10054 | } |
| 9874 | 10055 | Jim_DecrRefCount(interp, cmdNameObj); |
| 9875 | 10056 | JimFreeQualifiedName(interp, fqObjName); |
| | @@ -9879,47 +10060,45 @@ |
| 9879 | 10060 | } |
| 9880 | 10061 | return JIM_OK; |
| 9881 | 10062 | } |
| 9882 | 10063 | |
| 9883 | 10064 | |
| 9884 | | -#define JIM_FCF_NONE 0 |
| 9885 | | -#define JIM_FCF_NOHT 1 |
| 9886 | | -static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags) |
| 9887 | | -{ |
| 10065 | +#define JIM_FCF_FULL 0 |
| 10066 | +#define JIM_FCF_REUSE 1 |
| 10067 | +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) |
| 10068 | + { |
| 10069 | + JimDeleteLocalProcs(interp, cf->localCommands); |
| 10070 | + |
| 9888 | 10071 | if (cf->procArgsObjPtr) |
| 9889 | 10072 | Jim_DecrRefCount(interp, cf->procArgsObjPtr); |
| 9890 | 10073 | if (cf->procBodyObjPtr) |
| 9891 | 10074 | Jim_DecrRefCount(interp, cf->procBodyObjPtr); |
| 9892 | 10075 | Jim_DecrRefCount(interp, cf->nsObj); |
| 9893 | | - if (!(flags & JIM_FCF_NOHT)) |
| 10076 | + if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) |
| 9894 | 10077 | Jim_FreeHashTable(&cf->vars); |
| 9895 | 10078 | else { |
| 9896 | 10079 | int i; |
| 9897 | 10080 | Jim_HashEntry **table = cf->vars.table, *he; |
| 9898 | 10081 | |
| 9899 | 10082 | for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { |
| 9900 | 10083 | he = table[i]; |
| 9901 | 10084 | while (he != NULL) { |
| 9902 | 10085 | Jim_HashEntry *nextEntry = he->next; |
| 9903 | | - Jim_Var *varPtr = (void *)he->u.val; |
| 10086 | + Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 9904 | 10087 | |
| 9905 | 10088 | Jim_DecrRefCount(interp, varPtr->objPtr); |
| 9906 | | - Jim_Free(he->u.val); |
| 9907 | | - Jim_Free((void *)he->key); |
| 10089 | + Jim_Free(Jim_GetHashEntryKey(he)); |
| 10090 | + Jim_Free(varPtr); |
| 9908 | 10091 | Jim_Free(he); |
| 9909 | 10092 | table[i] = NULL; |
| 9910 | 10093 | he = nextEntry; |
| 9911 | 10094 | } |
| 9912 | 10095 | } |
| 9913 | 10096 | cf->vars.used = 0; |
| 9914 | 10097 | } |
| 9915 | | - |
| 9916 | | - JimDeleteLocalProcs(interp, cf->localCommands); |
| 9917 | | - |
| 9918 | 10098 | cf->next = interp->freeFramesList; |
| 9919 | 10099 | interp->freeFramesList = cf; |
| 9920 | | - |
| 9921 | 10100 | } |
| 9922 | 10101 | |
| 9923 | 10102 | |
| 9924 | 10103 | #ifdef JIM_REFERENCES |
| 9925 | 10104 | |
| | @@ -9996,21 +10175,16 @@ |
| 9996 | 10175 | NULL, |
| 9997 | 10176 | UpdateStringOfReference, |
| 9998 | 10177 | JIM_TYPE_REFERENCES, |
| 9999 | 10178 | }; |
| 10000 | 10179 | |
| 10001 | | -void UpdateStringOfReference(struct Jim_Obj *objPtr) |
| 10180 | +static void UpdateStringOfReference(struct Jim_Obj *objPtr) |
| 10002 | 10181 | { |
| 10003 | | - int len; |
| 10004 | 10182 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 10005 | | - Jim_Reference *refPtr; |
| 10006 | 10183 | |
| 10007 | | - refPtr = objPtr->internalRep.refValue.refPtr; |
| 10008 | | - len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id); |
| 10009 | | - objPtr->bytes = Jim_Alloc(len + 1); |
| 10010 | | - memcpy(objPtr->bytes, buf, len + 1); |
| 10011 | | - objPtr->length = len; |
| 10184 | + JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); |
| 10185 | + JimSetStringBytes(objPtr, buf); |
| 10012 | 10186 | } |
| 10013 | 10187 | |
| 10014 | 10188 | static int isrefchar(int c) |
| 10015 | 10189 | { |
| 10016 | 10190 | return (c == '_' || isalnum(c)); |
| | @@ -10061,11 +10235,11 @@ |
| 10061 | 10235 | he = Jim_FindHashEntry(&interp->references, &value); |
| 10062 | 10236 | if (he == NULL) { |
| 10063 | 10237 | Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); |
| 10064 | 10238 | return JIM_ERR; |
| 10065 | 10239 | } |
| 10066 | | - refPtr = he->u.val; |
| 10240 | + refPtr = Jim_GetHashEntryVal(he); |
| 10067 | 10241 | |
| 10068 | 10242 | Jim_FreeIntRep(interp, objPtr); |
| 10069 | 10243 | objPtr->typePtr = &referenceObjType; |
| 10070 | 10244 | objPtr->internalRep.refValue.id = value; |
| 10071 | 10245 | objPtr->internalRep.refValue.refPtr = refPtr; |
| | @@ -10178,11 +10352,11 @@ |
| 10178 | 10352 | Jim_Collect(interp); |
| 10179 | 10353 | } |
| 10180 | 10354 | } |
| 10181 | 10355 | #endif |
| 10182 | 10356 | |
| 10183 | | -static int JimIsBigEndian(void) |
| 10357 | +int Jim_IsBigEndian(void) |
| 10184 | 10358 | { |
| 10185 | 10359 | union { |
| 10186 | 10360 | unsigned short s; |
| 10187 | 10361 | unsigned char c[2]; |
| 10188 | 10362 | } uval = {0x0102}; |
| | @@ -10234,23 +10408,30 @@ |
| 10234 | 10408 | Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); |
| 10235 | 10409 | |
| 10236 | 10410 | Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); |
| 10237 | 10411 | Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); |
| 10238 | 10412 | Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); |
| 10239 | | - Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian"); |
| 10413 | + Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian"); |
| 10240 | 10414 | Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); |
| 10241 | 10415 | Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); |
| 10242 | 10416 | Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); |
| 10243 | 10417 | |
| 10244 | 10418 | return i; |
| 10245 | 10419 | } |
| 10246 | 10420 | |
| 10247 | 10421 | void Jim_FreeInterp(Jim_Interp *i) |
| 10248 | 10422 | { |
| 10249 | | - Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf; |
| 10423 | + Jim_CallFrame *cf, *cfx; |
| 10424 | + |
| 10250 | 10425 | Jim_Obj *objPtr, *nextObjPtr; |
| 10251 | 10426 | |
| 10427 | + |
| 10428 | + for (cf = i->framePtr; cf; cf = cfx) { |
| 10429 | + cfx = cf->parent; |
| 10430 | + JimFreeCallFrame(i, cf, JIM_FCF_FULL); |
| 10431 | + } |
| 10432 | + |
| 10252 | 10433 | Jim_DecrRefCount(i, i->emptyObj); |
| 10253 | 10434 | Jim_DecrRefCount(i, i->trueObj); |
| 10254 | 10435 | Jim_DecrRefCount(i, i->falseObj); |
| 10255 | 10436 | Jim_DecrRefCount(i, i->result); |
| 10256 | 10437 | Jim_DecrRefCount(i, i->stackTrace); |
| | @@ -10265,61 +10446,54 @@ |
| 10265 | 10446 | #endif |
| 10266 | 10447 | Jim_FreeHashTable(&i->packages); |
| 10267 | 10448 | Jim_Free(i->prngState); |
| 10268 | 10449 | Jim_FreeHashTable(&i->assocData); |
| 10269 | 10450 | |
| 10270 | | - |
| 10271 | | - while (cf) { |
| 10272 | | - prevcf = cf->parent; |
| 10273 | | - JimFreeCallFrame(i, cf, JIM_FCF_NONE); |
| 10274 | | - cf = prevcf; |
| 10275 | | - } |
| 10451 | +#ifdef JIM_MAINTAINER |
| 10276 | 10452 | if (i->liveList != NULL) { |
| 10277 | 10453 | objPtr = i->liveList; |
| 10278 | 10454 | |
| 10279 | | - printf(JIM_NL "-------------------------------------" JIM_NL); |
| 10280 | | - printf("Objects still in the free list:" JIM_NL); |
| 10455 | + printf("\n-------------------------------------\n"); |
| 10456 | + printf("Objects still in the free list:\n"); |
| 10281 | 10457 | while (objPtr) { |
| 10282 | 10458 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10283 | 10459 | |
| 10284 | 10460 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10285 | | - printf("%p (%d) %-10s: '%.20s...'" JIM_NL, |
| 10461 | + printf("%p (%d) %-10s: '%.20s...'\n", |
| 10286 | 10462 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10287 | 10463 | } |
| 10288 | 10464 | else { |
| 10289 | | - printf("%p (%d) %-10s: '%s'" JIM_NL, |
| 10465 | + printf("%p (%d) %-10s: '%s'\n", |
| 10290 | 10466 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); |
| 10291 | 10467 | } |
| 10292 | 10468 | if (objPtr->typePtr == &sourceObjType) { |
| 10293 | | - printf("FILE %s LINE %d" JIM_NL, |
| 10469 | + printf("FILE %s LINE %d\n", |
| 10294 | 10470 | Jim_String(objPtr->internalRep.sourceValue.fileNameObj), |
| 10295 | 10471 | objPtr->internalRep.sourceValue.lineNumber); |
| 10296 | 10472 | } |
| 10297 | 10473 | objPtr = objPtr->nextObjPtr; |
| 10298 | 10474 | } |
| 10299 | | - printf("-------------------------------------" JIM_NL JIM_NL); |
| 10475 | + printf("-------------------------------------\n\n"); |
| 10300 | 10476 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10301 | 10477 | } |
| 10478 | +#endif |
| 10479 | + |
| 10302 | 10480 | |
| 10303 | 10481 | objPtr = i->freeList; |
| 10304 | 10482 | while (objPtr) { |
| 10305 | 10483 | nextObjPtr = objPtr->nextObjPtr; |
| 10306 | 10484 | Jim_Free(objPtr); |
| 10307 | 10485 | objPtr = nextObjPtr; |
| 10308 | 10486 | } |
| 10487 | + |
| 10309 | 10488 | |
| 10310 | | - cf = i->freeFramesList; |
| 10311 | | - while (cf) { |
| 10312 | | - nextcf = cf->next; |
| 10313 | | - if (cf->vars.table != NULL) |
| 10314 | | - Jim_Free(cf->vars.table); |
| 10489 | + for (cf = i->freeFramesList; cf; cf = cfx) { |
| 10490 | + cfx = cf->next; |
| 10491 | + if (cf->vars.table) |
| 10492 | + Jim_FreeHashTable(&cf->vars); |
| 10315 | 10493 | Jim_Free(cf); |
| 10316 | | - cf = nextcf; |
| 10317 | 10494 | } |
| 10318 | | -#ifdef jim_ext_load |
| 10319 | | - Jim_FreeLoadHandles(i); |
| 10320 | | -#endif |
| 10321 | 10495 | |
| 10322 | 10496 | |
| 10323 | 10497 | Jim_Free(i); |
| 10324 | 10498 | } |
| 10325 | 10499 | |
| | @@ -10414,22 +10588,15 @@ |
| 10414 | 10588 | interp->stackTrace = stackTraceObj; |
| 10415 | 10589 | interp->errorFlag = 1; |
| 10416 | 10590 | |
| 10417 | 10591 | len = Jim_ListLength(interp, interp->stackTrace); |
| 10418 | 10592 | if (len >= 3) { |
| 10419 | | - Jim_Obj *filenameObj; |
| 10420 | | - |
| 10421 | | - Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE); |
| 10422 | | - |
| 10423 | | - Jim_GetString(filenameObj, &len); |
| 10424 | | - |
| 10425 | | - if (!Jim_Length(filenameObj)) { |
| 10593 | + if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) { |
| 10426 | 10594 | interp->addStackTrace = 1; |
| 10427 | 10595 | } |
| 10428 | 10596 | } |
| 10429 | 10597 | } |
| 10430 | | - |
| 10431 | 10598 | |
| 10432 | 10599 | static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, |
| 10433 | 10600 | Jim_Obj *fileNameObj, int linenr) |
| 10434 | 10601 | { |
| 10435 | 10602 | if (strcmp(procname, "unknown") == 0) { |
| | @@ -10450,14 +10617,15 @@ |
| 10450 | 10617 | if (!*procname && Jim_Length(fileNameObj)) { |
| 10451 | 10618 | |
| 10452 | 10619 | int len = Jim_ListLength(interp, interp->stackTrace); |
| 10453 | 10620 | |
| 10454 | 10621 | if (len >= 3) { |
| 10455 | | - Jim_Obj *objPtr; |
| 10456 | | - if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) { |
| 10622 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); |
| 10623 | + if (Jim_Length(objPtr)) { |
| 10457 | 10624 | |
| 10458 | | - if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) { |
| 10625 | + objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); |
| 10626 | + if (Jim_Length(objPtr) == 0) { |
| 10459 | 10627 | |
| 10460 | 10628 | ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); |
| 10461 | 10629 | ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); |
| 10462 | 10630 | return; |
| 10463 | 10631 | } |
| | @@ -10483,12 +10651,11 @@ |
| 10483 | 10651 | void *Jim_GetAssocData(Jim_Interp *interp, const char *key) |
| 10484 | 10652 | { |
| 10485 | 10653 | Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); |
| 10486 | 10654 | |
| 10487 | 10655 | if (entryPtr != NULL) { |
| 10488 | | - AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val; |
| 10489 | | - |
| 10656 | + AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr); |
| 10490 | 10657 | return assocEntryPtr->data; |
| 10491 | 10658 | } |
| 10492 | 10659 | return NULL; |
| 10493 | 10660 | } |
| 10494 | 10661 | |
| | @@ -10500,12 +10667,10 @@ |
| 10500 | 10667 | int Jim_GetExitCode(Jim_Interp *interp) |
| 10501 | 10668 | { |
| 10502 | 10669 | return interp->exitCode; |
| 10503 | 10670 | } |
| 10504 | 10671 | |
| 10505 | | -#define JIM_INTEGER_SPACE 24 |
| 10506 | | - |
| 10507 | 10672 | static void UpdateStringOfInt(struct Jim_Obj *objPtr); |
| 10508 | 10673 | static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); |
| 10509 | 10674 | |
| 10510 | 10675 | static const Jim_ObjType intObjType = { |
| 10511 | 10676 | "int", |
| | @@ -10522,22 +10687,46 @@ |
| 10522 | 10687 | UpdateStringOfInt, |
| 10523 | 10688 | JIM_TYPE_NONE, |
| 10524 | 10689 | }; |
| 10525 | 10690 | |
| 10526 | 10691 | |
| 10527 | | -void UpdateStringOfInt(struct Jim_Obj *objPtr) |
| 10692 | +static void UpdateStringOfInt(struct Jim_Obj *objPtr) |
| 10528 | 10693 | { |
| 10529 | | - int len; |
| 10530 | 10694 | char buf[JIM_INTEGER_SPACE + 1]; |
| 10695 | + jim_wide wideValue = JimWideValue(objPtr); |
| 10696 | + int pos = 0; |
| 10531 | 10697 | |
| 10532 | | - len = Jim_WideToString(buf, JimWideValue(objPtr)); |
| 10533 | | - objPtr->bytes = Jim_Alloc(len + 1); |
| 10534 | | - memcpy(objPtr->bytes, buf, len + 1); |
| 10535 | | - objPtr->length = len; |
| 10698 | + if (wideValue == 0) { |
| 10699 | + buf[pos++] = '0'; |
| 10700 | + } |
| 10701 | + else { |
| 10702 | + char tmp[JIM_INTEGER_SPACE]; |
| 10703 | + int num = 0; |
| 10704 | + int i; |
| 10705 | + |
| 10706 | + if (wideValue < 0) { |
| 10707 | + buf[pos++] = '-'; |
| 10708 | + i = wideValue % 10; |
| 10709 | + tmp[num++] = (i > 0) ? (10 - i) : -i; |
| 10710 | + wideValue /= -10; |
| 10711 | + } |
| 10712 | + |
| 10713 | + while (wideValue) { |
| 10714 | + tmp[num++] = wideValue % 10; |
| 10715 | + wideValue /= 10; |
| 10716 | + } |
| 10717 | + |
| 10718 | + for (i = 0; i < num; i++) { |
| 10719 | + buf[pos++] = '0' + tmp[num - i - 1]; |
| 10720 | + } |
| 10721 | + } |
| 10722 | + buf[pos] = 0; |
| 10723 | + |
| 10724 | + JimSetStringBytes(objPtr, buf); |
| 10536 | 10725 | } |
| 10537 | 10726 | |
| 10538 | | -int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 10727 | +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 10539 | 10728 | { |
| 10540 | 10729 | jim_wide wideValue; |
| 10541 | 10730 | const char *str; |
| 10542 | 10731 | |
| 10543 | 10732 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| | @@ -10625,22 +10814,65 @@ |
| 10625 | 10814 | NULL, |
| 10626 | 10815 | UpdateStringOfDouble, |
| 10627 | 10816 | JIM_TYPE_NONE, |
| 10628 | 10817 | }; |
| 10629 | 10818 | |
| 10630 | | -void UpdateStringOfDouble(struct Jim_Obj *objPtr) |
| 10631 | | -{ |
| 10632 | | - int len; |
| 10633 | | - char buf[JIM_DOUBLE_SPACE + 1]; |
| 10634 | | - |
| 10635 | | - len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); |
| 10636 | | - objPtr->bytes = Jim_Alloc(len + 1); |
| 10637 | | - memcpy(objPtr->bytes, buf, len + 1); |
| 10638 | | - objPtr->length = len; |
| 10819 | +#ifndef HAVE_ISNAN |
| 10820 | +#undef isnan |
| 10821 | +#define isnan(X) ((X) != (X)) |
| 10822 | +#endif |
| 10823 | +#ifndef HAVE_ISINF |
| 10824 | +#undef isinf |
| 10825 | +#define isinf(X) (1.0 / (X) == 0.0) |
| 10826 | +#endif |
| 10827 | + |
| 10828 | +static void UpdateStringOfDouble(struct Jim_Obj *objPtr) |
| 10829 | +{ |
| 10830 | + double value = objPtr->internalRep.doubleValue; |
| 10831 | + |
| 10832 | + if (isnan(value)) { |
| 10833 | + JimSetStringBytes(objPtr, "NaN"); |
| 10834 | + return; |
| 10835 | + } |
| 10836 | + if (isinf(value)) { |
| 10837 | + if (value < 0) { |
| 10838 | + JimSetStringBytes(objPtr, "-Inf"); |
| 10839 | + } |
| 10840 | + else { |
| 10841 | + JimSetStringBytes(objPtr, "Inf"); |
| 10842 | + } |
| 10843 | + return; |
| 10844 | + } |
| 10845 | + { |
| 10846 | + char buf[JIM_DOUBLE_SPACE + 1]; |
| 10847 | + int i; |
| 10848 | + int len = sprintf(buf, "%.12g", value); |
| 10849 | + |
| 10850 | + |
| 10851 | + for (i = 0; i < len; i++) { |
| 10852 | + if (buf[i] == '.' || buf[i] == 'e') { |
| 10853 | +#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 10854 | + char *e = strchr(buf, 'e'); |
| 10855 | + if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 10856 | + |
| 10857 | + e += 2; |
| 10858 | + memmove(e, e + 1, len - (e - buf)); |
| 10859 | + } |
| 10860 | +#endif |
| 10861 | + break; |
| 10862 | + } |
| 10863 | + } |
| 10864 | + if (buf[i] == '\0') { |
| 10865 | + buf[i++] = '.'; |
| 10866 | + buf[i++] = '0'; |
| 10867 | + buf[i] = '\0'; |
| 10868 | + } |
| 10869 | + JimSetStringBytes(objPtr, buf); |
| 10870 | + } |
| 10639 | 10871 | } |
| 10640 | 10872 | |
| 10641 | | -int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10873 | +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10642 | 10874 | { |
| 10643 | 10875 | double doubleValue; |
| 10644 | 10876 | jim_wide wideValue; |
| 10645 | 10877 | const char *str; |
| 10646 | 10878 | |
| | @@ -10755,11 +10987,11 @@ |
| 10755 | 10987 | } |
| 10756 | 10988 | |
| 10757 | 10989 | #define JIM_ELESTR_SIMPLE 0 |
| 10758 | 10990 | #define JIM_ELESTR_BRACE 1 |
| 10759 | 10991 | #define JIM_ELESTR_QUOTE 2 |
| 10760 | | -static int ListElementQuotingType(const char *s, int len) |
| 10992 | +static unsigned char ListElementQuotingType(const char *s, int len) |
| 10761 | 10993 | { |
| 10762 | 10994 | int i, level, blevel, trySimple = 1; |
| 10763 | 10995 | |
| 10764 | 10996 | |
| 10765 | 10997 | if (len == 0) |
| | @@ -10848,15 +11080,15 @@ |
| 10848 | 11080 | return JIM_ELESTR_SIMPLE; |
| 10849 | 11081 | } |
| 10850 | 11082 | return JIM_ELESTR_QUOTE; |
| 10851 | 11083 | } |
| 10852 | 11084 | |
| 10853 | | -static int BackslashQuoteString(const char *s, char *q) |
| 11085 | +static int BackslashQuoteString(const char *s, int len, char *q) |
| 10854 | 11086 | { |
| 10855 | 11087 | char *p = q; |
| 10856 | 11088 | |
| 10857 | | - while (*s) { |
| 11089 | + while (len--) { |
| 10858 | 11090 | switch (*s) { |
| 10859 | 11091 | case ' ': |
| 10860 | 11092 | case '$': |
| 10861 | 11093 | case '"': |
| 10862 | 11094 | case '[': |
| | @@ -10903,17 +11135,23 @@ |
| 10903 | 11135 | return p - q; |
| 10904 | 11136 | } |
| 10905 | 11137 | |
| 10906 | 11138 | static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc) |
| 10907 | 11139 | { |
| 11140 | + #define STATIC_QUOTING_LEN 32 |
| 10908 | 11141 | int i, bufLen, realLength; |
| 10909 | 11142 | const char *strRep; |
| 10910 | 11143 | char *p; |
| 10911 | | - int *quotingType; |
| 11144 | + unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; |
| 10912 | 11145 | |
| 10913 | 11146 | |
| 10914 | | - quotingType = Jim_Alloc(sizeof(int) * objc + 1); |
| 11147 | + if (objc > STATIC_QUOTING_LEN) { |
| 11148 | + quotingType = Jim_Alloc(objc); |
| 11149 | + } |
| 11150 | + else { |
| 11151 | + quotingType = staticQuoting; |
| 11152 | + } |
| 10915 | 11153 | bufLen = 0; |
| 10916 | 11154 | for (i = 0; i < objc; i++) { |
| 10917 | 11155 | int len; |
| 10918 | 11156 | |
| 10919 | 11157 | strRep = Jim_GetString(objv[i], &len); |
| | @@ -10962,11 +11200,11 @@ |
| 10962 | 11200 | case JIM_ELESTR_QUOTE: |
| 10963 | 11201 | if (i == 0 && strRep[0] == '#') { |
| 10964 | 11202 | *p++ = '\\'; |
| 10965 | 11203 | realLength++; |
| 10966 | 11204 | } |
| 10967 | | - qlen = BackslashQuoteString(strRep, p); |
| 11205 | + qlen = BackslashQuoteString(strRep, len, p); |
| 10968 | 11206 | p += qlen; |
| 10969 | 11207 | realLength += qlen; |
| 10970 | 11208 | break; |
| 10971 | 11209 | } |
| 10972 | 11210 | |
| | @@ -10975,11 +11213,14 @@ |
| 10975 | 11213 | realLength++; |
| 10976 | 11214 | } |
| 10977 | 11215 | } |
| 10978 | 11216 | *p = '\0'; |
| 10979 | 11217 | objPtr->length = realLength; |
| 10980 | | - Jim_Free(quotingType); |
| 11218 | + |
| 11219 | + if (quotingType != staticQuoting) { |
| 11220 | + Jim_Free(quotingType); |
| 11221 | + } |
| 10981 | 11222 | } |
| 10982 | 11223 | |
| 10983 | 11224 | static void UpdateStringOfList(struct Jim_Obj *objPtr) |
| 10984 | 11225 | { |
| 10985 | 11226 | JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len); |
| | @@ -10995,16 +11236,16 @@ |
| 10995 | 11236 | |
| 10996 | 11237 | if (objPtr->typePtr == &listObjType) { |
| 10997 | 11238 | return JIM_OK; |
| 10998 | 11239 | } |
| 10999 | 11240 | |
| 11000 | | - if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) { |
| 11241 | + if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { |
| 11001 | 11242 | Jim_Obj **listObjPtrPtr; |
| 11002 | 11243 | int len; |
| 11003 | 11244 | int i; |
| 11004 | 11245 | |
| 11005 | | - Jim_DictPairs(interp, objPtr, &listObjPtrPtr, &len); |
| 11246 | + listObjPtrPtr = JimDictPairs(objPtr, &len); |
| 11006 | 11247 | for (i = 0; i < len; i++) { |
| 11007 | 11248 | Jim_IncrRefCount(listObjPtrPtr[i]); |
| 11008 | 11249 | } |
| 11009 | 11250 | |
| 11010 | 11251 | |
| | @@ -11099,15 +11340,17 @@ |
| 11099 | 11340 | Jim_Interp *interp; |
| 11100 | 11341 | enum { |
| 11101 | 11342 | JIM_LSORT_ASCII, |
| 11102 | 11343 | JIM_LSORT_NOCASE, |
| 11103 | 11344 | JIM_LSORT_INTEGER, |
| 11345 | + JIM_LSORT_REAL, |
| 11104 | 11346 | JIM_LSORT_COMMAND |
| 11105 | 11347 | } type; |
| 11106 | 11348 | int order; |
| 11107 | 11349 | int index; |
| 11108 | 11350 | int indexed; |
| 11351 | + int unique; |
| 11109 | 11352 | int (*subfn)(Jim_Obj **, Jim_Obj **); |
| 11110 | 11353 | }; |
| 11111 | 11354 | |
| 11112 | 11355 | static struct lsort_info *sort_info; |
| 11113 | 11356 | |
| | @@ -11142,10 +11385,27 @@ |
| 11142 | 11385 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11143 | 11386 | } |
| 11144 | 11387 | |
| 11145 | 11388 | return JimSign(lhs - rhs) * sort_info->order; |
| 11146 | 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 | +} |
| 11147 | 11407 | |
| 11148 | 11408 | static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11149 | 11409 | { |
| 11150 | 11410 | Jim_Obj *compare_script; |
| 11151 | 11411 | int rc; |
| | @@ -11164,10 +11424,34 @@ |
| 11164 | 11424 | } |
| 11165 | 11425 | |
| 11166 | 11426 | return JimSign(ret) * sort_info->order; |
| 11167 | 11427 | } |
| 11168 | 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 | + |
| 11169 | 11453 | |
| 11170 | 11454 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| 11171 | 11455 | { |
| 11172 | 11456 | struct lsort_info *prev_info; |
| 11173 | 11457 | |
| | @@ -11175,11 +11459,11 @@ |
| 11175 | 11459 | int (*fn) (Jim_Obj **, Jim_Obj **); |
| 11176 | 11460 | Jim_Obj **vector; |
| 11177 | 11461 | int len; |
| 11178 | 11462 | int rc; |
| 11179 | 11463 | |
| 11180 | | - JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object")); |
| 11464 | + JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); |
| 11181 | 11465 | SetListFromAny(interp, listObjPtr); |
| 11182 | 11466 | |
| 11183 | 11467 | |
| 11184 | 11468 | prev_info = sort_info; |
| 11185 | 11469 | sort_info = info; |
| | @@ -11194,10 +11478,13 @@ |
| 11194 | 11478 | fn = ListSortStringNoCase; |
| 11195 | 11479 | break; |
| 11196 | 11480 | case JIM_LSORT_INTEGER: |
| 11197 | 11481 | fn = ListSortInteger; |
| 11198 | 11482 | break; |
| 11483 | + case JIM_LSORT_REAL: |
| 11484 | + fn = ListSortReal; |
| 11485 | + break; |
| 11199 | 11486 | case JIM_LSORT_COMMAND: |
| 11200 | 11487 | fn = ListSortCommand; |
| 11201 | 11488 | break; |
| 11202 | 11489 | default: |
| 11203 | 11490 | fn = NULL; |
| | @@ -11210,12 +11497,17 @@ |
| 11210 | 11497 | fn = ListSortIndexHelper; |
| 11211 | 11498 | } |
| 11212 | 11499 | |
| 11213 | 11500 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| 11214 | 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); |
| 11215 | 11508 | } |
| 11216 | | - Jim_InvalidateStringRep(listObjPtr); |
| 11217 | 11509 | sort_info = prev_info; |
| 11218 | 11510 | |
| 11219 | 11511 | return rc; |
| 11220 | 11512 | } |
| 11221 | 11513 | |
| | @@ -11225,14 +11517,22 @@ |
| 11225 | 11517 | int requiredLen = currentLen + elemc; |
| 11226 | 11518 | int i; |
| 11227 | 11519 | Jim_Obj **point; |
| 11228 | 11520 | |
| 11229 | 11521 | if (requiredLen > listPtr->internalRep.listValue.maxLen) { |
| 11230 | | - listPtr->internalRep.listValue.maxLen = requiredLen * 2; |
| 11522 | + if (requiredLen < 2) { |
| 11523 | + |
| 11524 | + requiredLen = 4; |
| 11525 | + } |
| 11526 | + else { |
| 11527 | + requiredLen *= 2; |
| 11528 | + } |
| 11231 | 11529 | |
| 11232 | 11530 | listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, |
| 11233 | | - sizeof(Jim_Obj *) * listPtr->internalRep.listValue.maxLen); |
| 11531 | + sizeof(Jim_Obj *) * requiredLen); |
| 11532 | + |
| 11533 | + listPtr->internalRep.listValue.maxLen = requiredLen; |
| 11234 | 11534 | } |
| 11235 | 11535 | if (idx < 0) { |
| 11236 | 11536 | idx = currentLen; |
| 11237 | 11537 | } |
| 11238 | 11538 | point = listPtr->internalRep.listValue.ele + idx; |
| | @@ -11332,11 +11632,11 @@ |
| 11332 | 11632 | listPtr->internalRep.listValue.ele[idx] = newObjPtr; |
| 11333 | 11633 | Jim_IncrRefCount(newObjPtr); |
| 11334 | 11634 | return JIM_OK; |
| 11335 | 11635 | } |
| 11336 | 11636 | |
| 11337 | | -int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, |
| 11637 | +int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, |
| 11338 | 11638 | Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) |
| 11339 | 11639 | { |
| 11340 | 11640 | Jim_Obj *varObjPtr, *objPtr, *listObjPtr; |
| 11341 | 11641 | int shared, i, idx; |
| 11342 | 11642 | |
| | @@ -11380,14 +11680,11 @@ |
| 11380 | 11680 | int i; |
| 11381 | 11681 | int listLen = Jim_ListLength(interp, listObjPtr); |
| 11382 | 11682 | Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); |
| 11383 | 11683 | |
| 11384 | 11684 | for (i = 0; i < listLen; ) { |
| 11385 | | - Jim_Obj *objPtr; |
| 11386 | | - |
| 11387 | | - Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); |
| 11388 | | - Jim_AppendObj(interp, resObjPtr, objPtr); |
| 11685 | + Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i)); |
| 11389 | 11686 | if (++i != listLen) { |
| 11390 | 11687 | Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); |
| 11391 | 11688 | } |
| 11392 | 11689 | } |
| 11393 | 11690 | return resObjPtr; |
| | @@ -11413,43 +11710,42 @@ |
| 11413 | 11710 | int len = 0, objLen; |
| 11414 | 11711 | char *bytes, *p; |
| 11415 | 11712 | |
| 11416 | 11713 | |
| 11417 | 11714 | for (i = 0; i < objc; i++) { |
| 11418 | | - Jim_GetString(objv[i], &objLen); |
| 11419 | | - len += objLen; |
| 11715 | + len += Jim_Length(objv[i]); |
| 11420 | 11716 | } |
| 11421 | 11717 | if (objc) |
| 11422 | 11718 | len += objc - 1; |
| 11423 | 11719 | |
| 11424 | 11720 | p = bytes = Jim_Alloc(len + 1); |
| 11425 | 11721 | for (i = 0; i < objc; i++) { |
| 11426 | 11722 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11427 | 11723 | |
| 11428 | 11724 | |
| 11429 | | - while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) { |
| 11725 | + while (objLen && isspace(UCHAR(*s))) { |
| 11430 | 11726 | s++; |
| 11431 | 11727 | objLen--; |
| 11432 | 11728 | len--; |
| 11433 | 11729 | } |
| 11434 | 11730 | |
| 11435 | | - while (objLen && (s[objLen - 1] == ' ' || |
| 11436 | | - s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) { |
| 11731 | + while (objLen && isspace(UCHAR(s[objLen - 1]))) { |
| 11437 | 11732 | |
| 11438 | 11733 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11439 | 11734 | break; |
| 11440 | 11735 | } |
| 11441 | 11736 | objLen--; |
| 11442 | 11737 | len--; |
| 11443 | 11738 | } |
| 11444 | 11739 | memcpy(p, s, objLen); |
| 11445 | 11740 | p += objLen; |
| 11446 | | - if (objLen && i + 1 != objc) { |
| 11447 | | - *p++ = ' '; |
| 11448 | | - } |
| 11449 | | - else if (i + 1 != objc) { |
| 11450 | | - len--; |
| 11741 | + if (i + 1 != objc) { |
| 11742 | + if (objLen) |
| 11743 | + *p++ = ' '; |
| 11744 | + else { |
| 11745 | + len--; |
| 11746 | + } |
| 11451 | 11747 | } |
| 11452 | 11748 | } |
| 11453 | 11749 | *p = '\0'; |
| 11454 | 11750 | return Jim_NewStringObjNoAlloc(interp, bytes, len); |
| 11455 | 11751 | } |
| | @@ -11489,20 +11785,26 @@ |
| 11489 | 11785 | |
| 11490 | 11786 | static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 11491 | 11787 | { |
| 11492 | 11788 | return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 11493 | 11789 | } |
| 11790 | + |
| 11791 | +static void *JimObjectHTKeyValDup(void *privdata, const void *val) |
| 11792 | +{ |
| 11793 | + Jim_IncrRefCount((Jim_Obj *)val); |
| 11794 | + return (void *)val; |
| 11795 | +} |
| 11494 | 11796 | |
| 11495 | 11797 | static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 11496 | 11798 | { |
| 11497 | 11799 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11498 | 11800 | } |
| 11499 | 11801 | |
| 11500 | 11802 | static const Jim_HashTableType JimDictHashTableType = { |
| 11501 | 11803 | JimObjectHTHashFunction, |
| 11502 | | - NULL, |
| 11503 | | - NULL, |
| 11804 | + JimObjectHTKeyValDup, |
| 11805 | + JimObjectHTKeyValDup, |
| 11504 | 11806 | JimObjectHTKeyCompare, |
| 11505 | 11807 | JimObjectHTKeyValDestructor, |
| 11506 | 11808 | JimObjectHTKeyValDestructor |
| 11507 | 11809 | }; |
| 11508 | 11810 | |
| | @@ -11523,64 +11825,58 @@ |
| 11523 | 11825 | } |
| 11524 | 11826 | |
| 11525 | 11827 | void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 11526 | 11828 | { |
| 11527 | 11829 | Jim_HashTable *ht, *dupHt; |
| 11528 | | - Jim_HashTableIterator *htiter; |
| 11830 | + Jim_HashTableIterator htiter; |
| 11529 | 11831 | Jim_HashEntry *he; |
| 11530 | 11832 | |
| 11531 | 11833 | |
| 11532 | 11834 | ht = srcPtr->internalRep.ptr; |
| 11533 | 11835 | dupHt = Jim_Alloc(sizeof(*dupHt)); |
| 11534 | 11836 | Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); |
| 11535 | 11837 | if (ht->size != 0) |
| 11536 | 11838 | Jim_ExpandHashTable(dupHt, ht->size); |
| 11537 | 11839 | |
| 11538 | | - htiter = Jim_GetHashTableIterator(ht); |
| 11539 | | - while ((he = Jim_NextHashEntry(htiter)) != NULL) { |
| 11540 | | - const Jim_Obj *keyObjPtr = he->key; |
| 11541 | | - Jim_Obj *valObjPtr = he->u.val; |
| 11542 | | - |
| 11543 | | - Jim_IncrRefCount((Jim_Obj *)keyObjPtr); |
| 11544 | | - Jim_IncrRefCount(valObjPtr); |
| 11545 | | - Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); |
| 11546 | | - } |
| 11547 | | - Jim_FreeHashTableIterator(htiter); |
| 11840 | + JimInitHashTableIterator(ht, &htiter); |
| 11841 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11842 | + Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 11843 | + } |
| 11548 | 11844 | |
| 11549 | 11845 | dupPtr->internalRep.ptr = dupHt; |
| 11550 | 11846 | dupPtr->typePtr = &dictObjType; |
| 11551 | 11847 | } |
| 11552 | 11848 | |
| 11553 | 11849 | static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len) |
| 11554 | 11850 | { |
| 11555 | 11851 | Jim_HashTable *ht; |
| 11556 | | - Jim_HashTableIterator *htiter; |
| 11852 | + Jim_HashTableIterator htiter; |
| 11557 | 11853 | Jim_HashEntry *he; |
| 11558 | 11854 | Jim_Obj **objv; |
| 11559 | 11855 | int i; |
| 11560 | 11856 | |
| 11561 | 11857 | ht = dictPtr->internalRep.ptr; |
| 11562 | 11858 | |
| 11563 | 11859 | |
| 11564 | 11860 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 11565 | | - htiter = Jim_GetHashTableIterator(ht); |
| 11861 | + JimInitHashTableIterator(ht, &htiter); |
| 11566 | 11862 | i = 0; |
| 11567 | | - while ((he = Jim_NextHashEntry(htiter)) != NULL) { |
| 11568 | | - objv[i++] = (Jim_Obj *)he->key; |
| 11569 | | - objv[i++] = he->u.val; |
| 11863 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11864 | + objv[i++] = Jim_GetHashEntryKey(he); |
| 11865 | + objv[i++] = Jim_GetHashEntryVal(he); |
| 11570 | 11866 | } |
| 11571 | 11867 | *len = i; |
| 11572 | | - Jim_FreeHashTableIterator(htiter); |
| 11573 | 11868 | return objv; |
| 11574 | 11869 | } |
| 11575 | 11870 | |
| 11576 | 11871 | static void UpdateStringOfDict(struct Jim_Obj *objPtr) |
| 11577 | 11872 | { |
| 11578 | 11873 | |
| 11579 | 11874 | int len; |
| 11580 | 11875 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 11581 | 11876 | |
| 11877 | + |
| 11582 | 11878 | JimMakeListStringRep(objPtr, objv, len); |
| 11583 | 11879 | |
| 11584 | 11880 | Jim_Free(objv); |
| 11585 | 11881 | } |
| 11586 | 11882 | |
| | @@ -11590,11 +11886,13 @@ |
| 11590 | 11886 | |
| 11591 | 11887 | if (objPtr->typePtr == &dictObjType) { |
| 11592 | 11888 | return JIM_OK; |
| 11593 | 11889 | } |
| 11594 | 11890 | |
| 11595 | | - Jim_String(objPtr); |
| 11891 | + if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 11892 | + Jim_String(objPtr); |
| 11893 | + } |
| 11596 | 11894 | |
| 11597 | 11895 | |
| 11598 | 11896 | listlen = Jim_ListLength(interp, objPtr); |
| 11599 | 11897 | if (listlen % 2) { |
| 11600 | 11898 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| | @@ -11607,28 +11905,14 @@ |
| 11607 | 11905 | |
| 11608 | 11906 | ht = Jim_Alloc(sizeof(*ht)); |
| 11609 | 11907 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| 11610 | 11908 | |
| 11611 | 11909 | for (i = 0; i < listlen; i += 2) { |
| 11612 | | - Jim_Obj *keyObjPtr; |
| 11613 | | - Jim_Obj *valObjPtr; |
| 11614 | | - |
| 11615 | | - Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE); |
| 11616 | | - Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE); |
| 11617 | | - |
| 11618 | | - Jim_IncrRefCount(keyObjPtr); |
| 11619 | | - Jim_IncrRefCount(valObjPtr); |
| 11620 | | - |
| 11621 | | - if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) { |
| 11622 | | - Jim_HashEntry *he; |
| 11623 | | - |
| 11624 | | - he = Jim_FindHashEntry(ht, keyObjPtr); |
| 11625 | | - Jim_DecrRefCount(interp, keyObjPtr); |
| 11626 | | - |
| 11627 | | - Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); |
| 11628 | | - he->u.val = valObjPtr; |
| 11629 | | - } |
| 11910 | + Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); |
| 11911 | + Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); |
| 11912 | + |
| 11913 | + Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); |
| 11630 | 11914 | } |
| 11631 | 11915 | |
| 11632 | 11916 | Jim_FreeIntRep(interp, objPtr); |
| 11633 | 11917 | objPtr->typePtr = &dictObjType; |
| 11634 | 11918 | objPtr->internalRep.ptr = ht; |
| | @@ -11645,31 +11929,23 @@ |
| 11645 | 11929 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 11646 | 11930 | |
| 11647 | 11931 | if (valueObjPtr == NULL) { |
| 11648 | 11932 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 11649 | 11933 | } |
| 11650 | | - Jim_IncrRefCount(keyObjPtr); |
| 11651 | | - Jim_IncrRefCount(valueObjPtr); |
| 11652 | | - if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) { |
| 11653 | | - |
| 11654 | | - Jim_DecrRefCount(interp, keyObjPtr); |
| 11655 | | - } |
| 11934 | + Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 11656 | 11935 | return JIM_OK; |
| 11657 | 11936 | } |
| 11658 | 11937 | |
| 11659 | 11938 | int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 11660 | 11939 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 11661 | 11940 | { |
| 11662 | | - int retcode; |
| 11663 | | - |
| 11664 | 11941 | JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); |
| 11665 | 11942 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 11666 | 11943 | return JIM_ERR; |
| 11667 | 11944 | } |
| 11668 | | - retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); |
| 11669 | 11945 | Jim_InvalidateStringRep(objPtr); |
| 11670 | | - return retcode; |
| 11946 | + return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); |
| 11671 | 11947 | } |
| 11672 | 11948 | |
| 11673 | 11949 | Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) |
| 11674 | 11950 | { |
| 11675 | 11951 | Jim_Obj *objPtr; |
| | @@ -11796,10 +12072,11 @@ |
| 11796 | 12072 | } |
| 11797 | 12073 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 11798 | 12074 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 11799 | 12075 | } |
| 11800 | 12076 | } |
| 12077 | + |
| 11801 | 12078 | Jim_InvalidateStringRep(objPtr); |
| 11802 | 12079 | Jim_InvalidateStringRep(varObjPtr); |
| 11803 | 12080 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 11804 | 12081 | goto err; |
| 11805 | 12082 | } |
| | @@ -11821,28 +12098,29 @@ |
| 11821 | 12098 | NULL, |
| 11822 | 12099 | UpdateStringOfIndex, |
| 11823 | 12100 | JIM_TYPE_NONE, |
| 11824 | 12101 | }; |
| 11825 | 12102 | |
| 11826 | | -void UpdateStringOfIndex(struct Jim_Obj *objPtr) |
| 11827 | | -{ |
| 11828 | | - int len; |
| 11829 | | - char buf[JIM_INTEGER_SPACE + 1]; |
| 11830 | | - |
| 11831 | | - if (objPtr->internalRep.intValue >= 0) |
| 11832 | | - len = sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 11833 | | - else if (objPtr->internalRep.intValue == -1) |
| 11834 | | - len = sprintf(buf, "end"); |
| 12103 | +static void UpdateStringOfIndex(struct Jim_Obj *objPtr) |
| 12104 | +{ |
| 12105 | + if (objPtr->internalRep.intValue == -1) { |
| 12106 | + JimSetStringBytes(objPtr, "end"); |
| 12107 | + } |
| 11835 | 12108 | else { |
| 11836 | | - len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12109 | + char buf[JIM_INTEGER_SPACE + 1]; |
| 12110 | + if (objPtr->internalRep.intValue >= 0) { |
| 12111 | + sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12112 | + } |
| 12113 | + else { |
| 12114 | + |
| 12115 | + sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12116 | + } |
| 12117 | + JimSetStringBytes(objPtr, buf); |
| 11837 | 12118 | } |
| 11838 | | - objPtr->bytes = Jim_Alloc(len + 1); |
| 11839 | | - memcpy(objPtr->bytes, buf, len + 1); |
| 11840 | | - objPtr->length = len; |
| 11841 | 12119 | } |
| 11842 | 12120 | |
| 11843 | | -int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12121 | +static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 11844 | 12122 | { |
| 11845 | 12123 | int idx, end = 0; |
| 11846 | 12124 | const char *str; |
| 11847 | 12125 | char *endptr; |
| 11848 | 12126 | |
| | @@ -11910,14 +12188,17 @@ |
| 11910 | 12188 | { |
| 11911 | 12189 | |
| 11912 | 12190 | if (objPtr->typePtr == &intObjType) { |
| 11913 | 12191 | jim_wide val = JimWideValue(objPtr); |
| 11914 | 12192 | |
| 11915 | | - if (!(val < LONG_MIN) && !(val > LONG_MAX)) { |
| 11916 | | - *indexPtr = (val < 0) ? -INT_MAX : (long)val;; |
| 11917 | | - return JIM_OK; |
| 11918 | | - } |
| 12193 | + if (val < 0) |
| 12194 | + *indexPtr = -INT_MAX; |
| 12195 | + else if (val > INT_MAX) |
| 12196 | + *indexPtr = INT_MAX; |
| 12197 | + else |
| 12198 | + *indexPtr = (int)val; |
| 12199 | + return JIM_OK; |
| 11919 | 12200 | } |
| 11920 | 12201 | if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) |
| 11921 | 12202 | return JIM_ERR; |
| 11922 | 12203 | *indexPtr = objPtr->internalRep.intValue; |
| 11923 | 12204 | return JIM_OK; |
| | @@ -11937,12 +12218,10 @@ |
| 11937 | 12218 | NULL |
| 11938 | 12219 | }; |
| 11939 | 12220 | |
| 11940 | 12221 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) |
| 11941 | 12222 | |
| 11942 | | -static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| 11943 | | - |
| 11944 | 12223 | static const Jim_ObjType returnCodeObjType = { |
| 11945 | 12224 | "return-code", |
| 11946 | 12225 | NULL, |
| 11947 | 12226 | NULL, |
| 11948 | 12227 | NULL, |
| | @@ -11957,11 +12236,11 @@ |
| 11957 | 12236 | else { |
| 11958 | 12237 | return jimReturnCodes[code]; |
| 11959 | 12238 | } |
| 11960 | 12239 | } |
| 11961 | 12240 | |
| 11962 | | -int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12241 | +static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 11963 | 12242 | { |
| 11964 | 12243 | int returnCode; |
| 11965 | 12244 | jim_wide wideValue; |
| 11966 | 12245 | |
| 11967 | 12246 | |
| | @@ -12089,14 +12368,15 @@ |
| 12089 | 12368 | |
| 12090 | 12369 | |
| 12091 | 12370 | typedef struct Jim_ExprOperator |
| 12092 | 12371 | { |
| 12093 | 12372 | const char *name; |
| 12094 | | - int precedence; |
| 12095 | | - int arity; |
| 12096 | 12373 | int (*funcop) (Jim_Interp *interp, struct JimExprState * e); |
| 12097 | | - int lazy; |
| 12374 | + unsigned char precedence; |
| 12375 | + unsigned char arity; |
| 12376 | + unsigned char lazy; |
| 12377 | + unsigned char namelen; |
| 12098 | 12378 | } Jim_ExprOperator; |
| 12099 | 12379 | |
| 12100 | 12380 | static void ExprPush(struct JimExprState *e, Jim_Obj *obj) |
| 12101 | 12381 | { |
| 12102 | 12382 | Jim_IncrRefCount(obj); |
| | @@ -12108,24 +12388,21 @@ |
| 12108 | 12388 | return e->stack[--e->stacklen]; |
| 12109 | 12389 | } |
| 12110 | 12390 | |
| 12111 | 12391 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12112 | 12392 | { |
| 12113 | | - int intresult = 0; |
| 12393 | + int intresult = 1; |
| 12114 | 12394 | int rc = JIM_OK; |
| 12115 | 12395 | Jim_Obj *A = ExprPop(e); |
| 12116 | 12396 | double dA, dC = 0; |
| 12117 | 12397 | jim_wide wA, wC = 0; |
| 12118 | 12398 | |
| 12119 | 12399 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12120 | | - intresult = 1; |
| 12121 | | - |
| 12122 | 12400 | switch (e->opcode) { |
| 12123 | 12401 | case JIM_EXPROP_FUNC_INT: |
| 12124 | | - wC = wA; |
| 12125 | | - break; |
| 12126 | 12402 | case JIM_EXPROP_FUNC_ROUND: |
| 12403 | + case JIM_EXPROP_UNARYPLUS: |
| 12127 | 12404 | wC = wA; |
| 12128 | 12405 | break; |
| 12129 | 12406 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12130 | 12407 | dC = wA; |
| 12131 | 12408 | intresult = 0; |
| | @@ -12134,13 +12411,10 @@ |
| 12134 | 12411 | wC = wA >= 0 ? wA : -wA; |
| 12135 | 12412 | break; |
| 12136 | 12413 | case JIM_EXPROP_UNARYMINUS: |
| 12137 | 12414 | wC = -wA; |
| 12138 | 12415 | break; |
| 12139 | | - case JIM_EXPROP_UNARYPLUS: |
| 12140 | | - wC = wA; |
| 12141 | | - break; |
| 12142 | 12416 | case JIM_EXPROP_NOT: |
| 12143 | 12417 | wC = !wA; |
| 12144 | 12418 | break; |
| 12145 | 12419 | default: |
| 12146 | 12420 | abort(); |
| | @@ -12148,31 +12422,29 @@ |
| 12148 | 12422 | } |
| 12149 | 12423 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12150 | 12424 | switch (e->opcode) { |
| 12151 | 12425 | case JIM_EXPROP_FUNC_INT: |
| 12152 | 12426 | wC = dA; |
| 12153 | | - intresult = 1; |
| 12154 | 12427 | break; |
| 12155 | 12428 | case JIM_EXPROP_FUNC_ROUND: |
| 12156 | 12429 | wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); |
| 12157 | | - intresult = 1; |
| 12158 | 12430 | break; |
| 12159 | 12431 | case JIM_EXPROP_FUNC_DOUBLE: |
| 12432 | + case JIM_EXPROP_UNARYPLUS: |
| 12160 | 12433 | dC = dA; |
| 12434 | + intresult = 0; |
| 12161 | 12435 | break; |
| 12162 | 12436 | case JIM_EXPROP_FUNC_ABS: |
| 12163 | 12437 | dC = dA >= 0 ? dA : -dA; |
| 12438 | + intresult = 0; |
| 12164 | 12439 | break; |
| 12165 | 12440 | case JIM_EXPROP_UNARYMINUS: |
| 12166 | 12441 | dC = -dA; |
| 12167 | | - break; |
| 12168 | | - case JIM_EXPROP_UNARYPLUS: |
| 12169 | | - dC = dA; |
| 12442 | + intresult = 0; |
| 12170 | 12443 | break; |
| 12171 | 12444 | case JIM_EXPROP_NOT: |
| 12172 | 12445 | wC = !dA; |
| 12173 | | - intresult = 1; |
| 12174 | 12446 | break; |
| 12175 | 12447 | default: |
| 12176 | 12448 | abort(); |
| 12177 | 12449 | } |
| 12178 | 12450 | } |
| | @@ -12383,11 +12655,11 @@ |
| 12383 | 12655 | |
| 12384 | 12656 | |
| 12385 | 12657 | |
| 12386 | 12658 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) |
| 12387 | 12659 | { |
| 12388 | | - int intresult = 0; |
| 12660 | + int intresult = 1; |
| 12389 | 12661 | int rc = JIM_OK; |
| 12390 | 12662 | double dA, dB, dC = 0; |
| 12391 | 12663 | jim_wide wA, wB, wC = 0; |
| 12392 | 12664 | |
| 12393 | 12665 | Jim_Obj *B = ExprPop(e); |
| | @@ -12397,12 +12669,10 @@ |
| 12397 | 12669 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12398 | 12670 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12399 | 12671 | |
| 12400 | 12672 | |
| 12401 | 12673 | |
| 12402 | | - intresult = 1; |
| 12403 | | - |
| 12404 | 12674 | switch (e->opcode) { |
| 12405 | 12675 | case JIM_EXPROP_POW: |
| 12406 | 12676 | case JIM_EXPROP_FUNC_POW: |
| 12407 | 12677 | wC = JimPowWide(wA, wB); |
| 12408 | 12678 | break; |
| | @@ -12452,10 +12722,11 @@ |
| 12452 | 12722 | default: |
| 12453 | 12723 | abort(); |
| 12454 | 12724 | } |
| 12455 | 12725 | } |
| 12456 | 12726 | else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12727 | + intresult = 0; |
| 12457 | 12728 | switch (e->opcode) { |
| 12458 | 12729 | case JIM_EXPROP_POW: |
| 12459 | 12730 | case JIM_EXPROP_FUNC_POW: |
| 12460 | 12731 | #ifdef JIM_MATH_FUNCTIONS |
| 12461 | 12732 | dC = pow(dA, dB); |
| | @@ -12517,12 +12788,10 @@ |
| 12517 | 12788 | |
| 12518 | 12789 | |
| 12519 | 12790 | |
| 12520 | 12791 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 12521 | 12792 | |
| 12522 | | - intresult = 1; |
| 12523 | | - |
| 12524 | 12793 | switch (e->opcode) { |
| 12525 | 12794 | case JIM_EXPROP_LT: |
| 12526 | 12795 | wC = i < 0; |
| 12527 | 12796 | break; |
| 12528 | 12797 | case JIM_EXPROP_GT: |
| | @@ -12566,15 +12835,11 @@ |
| 12566 | 12835 | int listlen; |
| 12567 | 12836 | int i; |
| 12568 | 12837 | |
| 12569 | 12838 | listlen = Jim_ListLength(interp, listObjPtr); |
| 12570 | 12839 | for (i = 0; i < listlen; i++) { |
| 12571 | | - Jim_Obj *objPtr; |
| 12572 | | - |
| 12573 | | - Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); |
| 12574 | | - |
| 12575 | | - if (Jim_StringEqObj(objPtr, valObj)) { |
| 12840 | + if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { |
| 12576 | 12841 | return 1; |
| 12577 | 12842 | } |
| 12578 | 12843 | } |
| 12579 | 12844 | return 0; |
| 12580 | 12845 | } |
| | @@ -12586,23 +12851,16 @@ |
| 12586 | 12851 | |
| 12587 | 12852 | jim_wide wC; |
| 12588 | 12853 | |
| 12589 | 12854 | switch (e->opcode) { |
| 12590 | 12855 | case JIM_EXPROP_STREQ: |
| 12591 | | - case JIM_EXPROP_STRNE: { |
| 12592 | | - int Alen, Blen; |
| 12593 | | - const char *sA = Jim_GetString(A, &Alen); |
| 12594 | | - const char *sB = Jim_GetString(B, &Blen); |
| 12595 | | - |
| 12596 | | - if (e->opcode == JIM_EXPROP_STREQ) { |
| 12597 | | - wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0); |
| 12598 | | - } |
| 12599 | | - else { |
| 12600 | | - wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0); |
| 12856 | + case JIM_EXPROP_STRNE: |
| 12857 | + wC = Jim_StringEqObj(A, B); |
| 12858 | + if (e->opcode == JIM_EXPROP_STRNE) { |
| 12859 | + wC = !wC; |
| 12601 | 12860 | } |
| 12602 | 12861 | break; |
| 12603 | | - } |
| 12604 | 12862 | case JIM_EXPROP_STRIN: |
| 12605 | 12863 | wC = JimSearchList(interp, B, A); |
| 12606 | 12864 | break; |
| 12607 | 12865 | case JIM_EXPROP_STRNI: |
| 12608 | 12866 | wC = !JimSearchList(interp, B, A); |
| | @@ -12774,93 +13032,98 @@ |
| 12774 | 13032 | LAZY_OP, |
| 12775 | 13033 | LAZY_LEFT, |
| 12776 | 13034 | LAZY_RIGHT |
| 12777 | 13035 | }; |
| 12778 | 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 | + |
| 12779 | 13040 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 12780 | | - {"*", 200, 2, JimExprOpBin, LAZY_NONE}, |
| 12781 | | - {"/", 200, 2, JimExprOpBin, LAZY_NONE}, |
| 12782 | | - {"%", 200, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12783 | | - |
| 12784 | | - {"-", 100, 2, JimExprOpBin, LAZY_NONE}, |
| 12785 | | - {"+", 100, 2, JimExprOpBin, LAZY_NONE}, |
| 12786 | | - |
| 12787 | | - {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12788 | | - {">>", 90, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12789 | | - |
| 12790 | | - {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12791 | | - {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12792 | | - |
| 12793 | | - {"<", 80, 2, JimExprOpBin, LAZY_NONE}, |
| 12794 | | - {">", 80, 2, JimExprOpBin, LAZY_NONE}, |
| 12795 | | - {"<=", 80, 2, JimExprOpBin, LAZY_NONE}, |
| 12796 | | - {">=", 80, 2, JimExprOpBin, LAZY_NONE}, |
| 12797 | | - |
| 12798 | | - {"==", 70, 2, JimExprOpBin, LAZY_NONE}, |
| 12799 | | - {"!=", 70, 2, JimExprOpBin, LAZY_NONE}, |
| 12800 | | - |
| 12801 | | - {"&", 50, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12802 | | - {"^", 49, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12803 | | - {"|", 48, 2, JimExprOpIntBin, LAZY_NONE}, |
| 12804 | | - |
| 12805 | | - {"&&", 10, 2, NULL, LAZY_OP}, |
| 12806 | | - {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT}, |
| 12807 | | - {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT}, |
| 12808 | | - |
| 12809 | | - {"||", 9, 2, NULL, LAZY_OP}, |
| 12810 | | - {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT}, |
| 12811 | | - {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT}, |
| 12812 | | - |
| 12813 | | - {"?", 5, 2, JimExprOpNull, LAZY_OP}, |
| 12814 | | - {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT}, |
| 12815 | | - {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, |
| 12816 | | - |
| 12817 | | - {":", 5, 2, JimExprOpNull, LAZY_OP}, |
| 12818 | | - {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT}, |
| 12819 | | - {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, |
| 12820 | | - |
| 12821 | | - {"**", 250, 2, JimExprOpBin, LAZY_NONE}, |
| 12822 | | - |
| 12823 | | - {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE}, |
| 12824 | | - {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE}, |
| 12825 | | - |
| 12826 | | - {"in", 55, 2, JimExprOpStrBin, LAZY_NONE}, |
| 12827 | | - {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE}, |
| 12828 | | - |
| 12829 | | - {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12830 | | - {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE}, |
| 12831 | | - {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12832 | | - {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12833 | | - |
| 12834 | | - |
| 12835 | | - |
| 12836 | | - {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12837 | | - {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12838 | | - {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12839 | | - {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE}, |
| 12840 | | - {"rand", 400, 0, JimExprOpNone, LAZY_NONE}, |
| 12841 | | - {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE}, |
| 13041 | + OPRINIT("*", 110, 2, JimExprOpBin), |
| 13042 | + OPRINIT("/", 110, 2, JimExprOpBin), |
| 13043 | + OPRINIT("%", 110, 2, JimExprOpIntBin), |
| 13044 | + |
| 13045 | + OPRINIT("-", 100, 2, JimExprOpBin), |
| 13046 | + OPRINIT("+", 100, 2, JimExprOpBin), |
| 13047 | + |
| 13048 | + OPRINIT("<<", 90, 2, JimExprOpIntBin), |
| 13049 | + OPRINIT(">>", 90, 2, JimExprOpIntBin), |
| 13050 | + |
| 13051 | + OPRINIT("<<<", 90, 2, JimExprOpIntBin), |
| 13052 | + OPRINIT(">>>", 90, 2, JimExprOpIntBin), |
| 13053 | + |
| 13054 | + OPRINIT("<", 80, 2, JimExprOpBin), |
| 13055 | + OPRINIT(">", 80, 2, JimExprOpBin), |
| 13056 | + OPRINIT("<=", 80, 2, JimExprOpBin), |
| 13057 | + OPRINIT(">=", 80, 2, JimExprOpBin), |
| 13058 | + |
| 13059 | + OPRINIT("==", 70, 2, JimExprOpBin), |
| 13060 | + OPRINIT("!=", 70, 2, JimExprOpBin), |
| 13061 | + |
| 13062 | + OPRINIT("&", 50, 2, JimExprOpIntBin), |
| 13063 | + OPRINIT("^", 49, 2, JimExprOpIntBin), |
| 13064 | + OPRINIT("|", 48, 2, JimExprOpIntBin), |
| 13065 | + |
| 13066 | + OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), |
| 13067 | + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), |
| 13068 | + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13069 | + |
| 13070 | + OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), |
| 13071 | + OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), |
| 13072 | + OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13073 | + |
| 13074 | + OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), |
| 13075 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), |
| 13076 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13077 | + |
| 13078 | + OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), |
| 13079 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), |
| 13080 | + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13081 | + |
| 13082 | + OPRINIT("**", 250, 2, JimExprOpBin), |
| 13083 | + |
| 13084 | + OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13085 | + OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13086 | + |
| 13087 | + OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13088 | + OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 13089 | + |
| 13090 | + OPRINIT("!", 150, 1, JimExprOpNumUnary), |
| 13091 | + OPRINIT("~", 150, 1, JimExprOpIntUnary), |
| 13092 | + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13093 | + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13094 | + |
| 13095 | + |
| 13096 | + |
| 13097 | + OPRINIT("int", 200, 1, JimExprOpNumUnary), |
| 13098 | + OPRINIT("abs", 200, 1, JimExprOpNumUnary), |
| 13099 | + OPRINIT("double", 200, 1, JimExprOpNumUnary), |
| 13100 | + OPRINIT("round", 200, 1, JimExprOpNumUnary), |
| 13101 | + OPRINIT("rand", 200, 0, JimExprOpNone), |
| 13102 | + OPRINIT("srand", 200, 1, JimExprOpIntUnary), |
| 12842 | 13103 | |
| 12843 | 13104 | #ifdef JIM_MATH_FUNCTIONS |
| 12844 | | - {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12845 | | - {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12846 | | - {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12847 | | - {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12848 | | - {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12849 | | - {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12850 | | - {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12851 | | - {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12852 | | - {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12853 | | - {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12854 | | - {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12855 | | - {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12856 | | - {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12857 | | - {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12858 | | - {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, |
| 12859 | | - {"pow", 400, 2, JimExprOpBin, LAZY_NONE}, |
| 13105 | + OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), |
| 13106 | + OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), |
| 13107 | + OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), |
| 13108 | + OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), |
| 13109 | + OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), |
| 13110 | + OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), |
| 13111 | + OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), |
| 13112 | + OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), |
| 13113 | + OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), |
| 13114 | + OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), |
| 13115 | + OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), |
| 13116 | + OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), |
| 13117 | + OPRINIT("log", 200, 1, JimExprOpDoubleUnary), |
| 13118 | + OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), |
| 13119 | + OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), |
| 13120 | + OPRINIT("pow", 200, 2, JimExprOpBin), |
| 12860 | 13121 | #endif |
| 12861 | 13122 | }; |
| 13123 | +#undef OPRINIT |
| 13124 | +#undef OPRINIT_LAZY |
| 12862 | 13125 | |
| 12863 | 13126 | #define JIM_EXPR_OPERATORS_NUM \ |
| 12864 | 13127 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 12865 | 13128 | |
| 12866 | 13129 | static int JimParseExpression(struct JimParserCtx *pc) |
| | @@ -12872,13 +13135,16 @@ |
| 12872 | 13135 | } |
| 12873 | 13136 | pc->p++; |
| 12874 | 13137 | pc->len--; |
| 12875 | 13138 | } |
| 12876 | 13139 | |
| 13140 | + |
| 13141 | + pc->tline = pc->linenr; |
| 13142 | + pc->tstart = pc->p; |
| 13143 | + |
| 12877 | 13144 | if (pc->len == 0) { |
| 12878 | | - pc->tstart = pc->tend = pc->p; |
| 12879 | | - pc->tline = pc->linenr; |
| 13145 | + pc->tend = pc->p; |
| 12880 | 13146 | pc->tt = JIM_TT_EOL; |
| 12881 | 13147 | pc->eof = 1; |
| 12882 | 13148 | return JIM_OK; |
| 12883 | 13149 | } |
| 12884 | 13150 | switch (*(pc->p)) { |
| | @@ -12889,12 +13155,11 @@ |
| 12889 | 13155 | pc->tt = JIM_TT_SUBEXPR_END; |
| 12890 | 13156 | goto singlechar; |
| 12891 | 13157 | case ',': |
| 12892 | 13158 | pc->tt = JIM_TT_SUBEXPR_COMMA; |
| 12893 | 13159 | singlechar: |
| 12894 | | - pc->tstart = pc->tend = pc->p; |
| 12895 | | - pc->tline = pc->linenr; |
| 13160 | + pc->tend = pc->p; |
| 12896 | 13161 | pc->p++; |
| 12897 | 13162 | pc->len--; |
| 12898 | 13163 | break; |
| 12899 | 13164 | case '[': |
| 12900 | 13165 | return JimParseCmd(pc); |
| | @@ -12940,82 +13205,44 @@ |
| 12940 | 13205 | return JIM_OK; |
| 12941 | 13206 | } |
| 12942 | 13207 | |
| 12943 | 13208 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 12944 | 13209 | { |
| 12945 | | - int allowdot = 1; |
| 12946 | | - int base = 10; |
| 13210 | + char *end; |
| 12947 | 13211 | |
| 12948 | 13212 | |
| 12949 | 13213 | pc->tt = JIM_TT_EXPR_INT; |
| 12950 | | - pc->tstart = pc->p; |
| 12951 | | - pc->tline = pc->linenr; |
| 12952 | | - |
| 12953 | | - |
| 12954 | | - if (pc->p[0] == '0') { |
| 12955 | | - switch (pc->p[1]) { |
| 12956 | | - case 'x': |
| 12957 | | - case 'X': |
| 12958 | | - base = 16; |
| 12959 | | - allowdot = 0; |
| 12960 | | - pc->p += 2; |
| 12961 | | - pc->len -= 2; |
| 12962 | | - break; |
| 12963 | | - case 'o': |
| 12964 | | - case 'O': |
| 12965 | | - base = 8; |
| 12966 | | - allowdot = 0; |
| 12967 | | - pc->p += 2; |
| 12968 | | - pc->len -= 2; |
| 12969 | | - break; |
| 12970 | | - case 'b': |
| 12971 | | - case 'B': |
| 12972 | | - base = 2; |
| 12973 | | - allowdot = 0; |
| 12974 | | - pc->p += 2; |
| 12975 | | - pc->len -= 2; |
| 12976 | | - break; |
| 12977 | | - } |
| 12978 | | - } |
| 12979 | | - |
| 12980 | | - while (isdigit(UCHAR(*pc->p)) |
| 12981 | | - || (base == 16 && isxdigit(UCHAR(*pc->p))) |
| 12982 | | - || (base == 8 && *pc->p >= '0' && *pc->p <= '7') |
| 12983 | | - || (base == 2 && (*pc->p == '0' || *pc->p == '1')) |
| 12984 | | - || (allowdot && *pc->p == '.') |
| 12985 | | - ) { |
| 12986 | | - if (*pc->p == '.') { |
| 12987 | | - allowdot = 0; |
| 12988 | | - pc->tt = JIM_TT_EXPR_DOUBLE; |
| 12989 | | - } |
| 12990 | | - pc->p++; |
| 12991 | | - pc->len--; |
| 12992 | | - if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+' |
| 12993 | | - || isdigit(UCHAR(pc->p[1])))) { |
| 12994 | | - pc->p += 2; |
| 12995 | | - pc->len -= 2; |
| 12996 | | - pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13214 | + |
| 13215 | + jim_strtoull(pc->p, (char **)&pc->p); |
| 13216 | + |
| 13217 | + if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { |
| 13218 | + if (strtod(pc->tstart, &end)) { } |
| 13219 | + if (end == pc->tstart) |
| 13220 | + return JIM_ERR; |
| 13221 | + if (end > pc->p) { |
| 13222 | + |
| 13223 | + pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13224 | + pc->p = end; |
| 12997 | 13225 | } |
| 12998 | 13226 | } |
| 12999 | 13227 | pc->tend = pc->p - 1; |
| 13228 | + pc->len -= (pc->p - pc->tstart); |
| 13000 | 13229 | return JIM_OK; |
| 13001 | 13230 | } |
| 13002 | 13231 | |
| 13003 | 13232 | static int JimParseExprIrrational(struct JimParserCtx *pc) |
| 13004 | 13233 | { |
| 13005 | | - const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; |
| 13006 | | - const char **token; |
| 13007 | | - |
| 13008 | | - for (token = Tokens; *token != NULL; token++) { |
| 13009 | | - int len = strlen(*token); |
| 13010 | | - |
| 13011 | | - if (strncmp(*token, pc->p, len) == 0) { |
| 13012 | | - pc->tstart = pc->p; |
| 13013 | | - pc->tend = pc->p + len - 1; |
| 13014 | | - pc->p += len; |
| 13015 | | - pc->len -= len; |
| 13016 | | - pc->tline = pc->linenr; |
| 13234 | + const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; |
| 13235 | + int i; |
| 13236 | + |
| 13237 | + for (i = 0; irrationals[i]; i++) { |
| 13238 | + const char *irr = irrationals[i]; |
| 13239 | + |
| 13240 | + if (strncmp(irr, pc->p, 3) == 0) { |
| 13241 | + pc->p += 3; |
| 13242 | + pc->len -= 3; |
| 13243 | + pc->tend = pc->p - 1; |
| 13017 | 13244 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13018 | 13245 | return JIM_OK; |
| 13019 | 13246 | } |
| 13020 | 13247 | } |
| 13021 | 13248 | return JIM_ERR; |
| | @@ -13026,20 +13253,18 @@ |
| 13026 | 13253 | int i; |
| 13027 | 13254 | int bestIdx = -1, bestLen = 0; |
| 13028 | 13255 | |
| 13029 | 13256 | |
| 13030 | 13257 | for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { |
| 13031 | | - const char *opname; |
| 13032 | | - int oplen; |
| 13258 | + const char * const opname = Jim_ExprOperators[i].name; |
| 13259 | + const int oplen = Jim_ExprOperators[i].namelen; |
| 13033 | 13260 | |
| 13034 | | - opname = Jim_ExprOperators[i].name; |
| 13035 | | - if (opname == NULL) { |
| 13261 | + if (opname == NULL || opname[0] != pc->p[0]) { |
| 13036 | 13262 | continue; |
| 13037 | 13263 | } |
| 13038 | | - oplen = strlen(opname); |
| 13039 | 13264 | |
| 13040 | | - if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) { |
| 13265 | + if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { |
| 13041 | 13266 | bestIdx = i + JIM_TT_EXPR_OP; |
| 13042 | 13267 | bestLen = oplen; |
| 13043 | 13268 | } |
| 13044 | 13269 | } |
| 13045 | 13270 | if (bestIdx == -1) { |
| | @@ -13057,15 +13282,13 @@ |
| 13057 | 13282 | } |
| 13058 | 13283 | if (*p != '(') { |
| 13059 | 13284 | return JIM_ERR; |
| 13060 | 13285 | } |
| 13061 | 13286 | } |
| 13062 | | - pc->tstart = pc->p; |
| 13063 | 13287 | pc->tend = pc->p + bestLen - 1; |
| 13064 | 13288 | pc->p += bestLen; |
| 13065 | 13289 | pc->len -= bestLen; |
| 13066 | | - pc->tline = pc->linenr; |
| 13067 | 13290 | |
| 13068 | 13291 | pc->tt = bestIdx; |
| 13069 | 13292 | return JIM_OK; |
| 13070 | 13293 | } |
| 13071 | 13294 | |
| | @@ -13111,12 +13334,12 @@ |
| 13111 | 13334 | }; |
| 13112 | 13335 | |
| 13113 | 13336 | |
| 13114 | 13337 | typedef struct ExprByteCode |
| 13115 | 13338 | { |
| 13116 | | - int len; |
| 13117 | 13339 | ScriptToken *token; |
| 13340 | + int len; |
| 13118 | 13341 | int inUse; |
| 13119 | 13342 | } ExprByteCode; |
| 13120 | 13343 | |
| 13121 | 13344 | static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) |
| 13122 | 13345 | { |
| | @@ -13563,17 +13786,23 @@ |
| 13563 | 13786 | } |
| 13564 | 13787 | |
| 13565 | 13788 | #ifdef DEBUG_SHOW_EXPR_TOKENS |
| 13566 | 13789 | { |
| 13567 | 13790 | int i; |
| 13568 | | - printf("==== Expr Tokens ====\n"); |
| 13791 | + printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj)); |
| 13569 | 13792 | for (i = 0; i < tokenlist.count; i++) { |
| 13570 | 13793 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), |
| 13571 | 13794 | tokenlist.list[i].len, tokenlist.list[i].token); |
| 13572 | 13795 | } |
| 13573 | 13796 | } |
| 13574 | 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 | + } |
| 13575 | 13804 | |
| 13576 | 13805 | |
| 13577 | 13806 | expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); |
| 13578 | 13807 | |
| 13579 | 13808 | |
| | @@ -13620,10 +13849,24 @@ |
| 13620 | 13849 | return NULL; |
| 13621 | 13850 | } |
| 13622 | 13851 | } |
| 13623 | 13852 | return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); |
| 13624 | 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 |
| 13625 | 13868 | |
| 13626 | 13869 | #define JIM_EE_STATICSTACK_LEN 10 |
| 13627 | 13870 | |
| 13628 | 13871 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) |
| 13629 | 13872 | { |
| | @@ -13643,102 +13886,69 @@ |
| 13643 | 13886 | Jim_Obj *objPtr; |
| 13644 | 13887 | |
| 13645 | 13888 | |
| 13646 | 13889 | switch (expr->len) { |
| 13647 | 13890 | case 1: |
| 13648 | | - if (expr->token[0].type == JIM_TT_EXPR_INT) { |
| 13649 | | - *exprResultPtrPtr = expr->token[0].objPtr; |
| 13650 | | - Jim_IncrRefCount(*exprResultPtrPtr); |
| 13651 | | - return JIM_OK; |
| 13652 | | - } |
| 13653 | | - if (expr->token[0].type == JIM_TT_VAR) { |
| 13654 | | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG); |
| 13655 | | - if (objPtr) { |
| 13656 | | - *exprResultPtrPtr = objPtr; |
| 13657 | | - Jim_IncrRefCount(*exprResultPtrPtr); |
| 13658 | | - return JIM_OK; |
| 13659 | | - } |
| 13891 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13892 | + if (objPtr) { |
| 13893 | + Jim_IncrRefCount(objPtr); |
| 13894 | + *exprResultPtrPtr = objPtr; |
| 13895 | + return JIM_OK; |
| 13660 | 13896 | } |
| 13661 | 13897 | break; |
| 13662 | 13898 | |
| 13663 | 13899 | case 2: |
| 13664 | | - if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) { |
| 13665 | | - jim_wide wideValue; |
| 13900 | + if (expr->token[1].type == JIM_EXPROP_NOT) { |
| 13901 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13666 | 13902 | |
| 13667 | | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); |
| 13668 | | - if (objPtr && JimIsWide(objPtr) |
| 13669 | | - && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) { |
| 13670 | | - *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj; |
| 13903 | + if (objPtr && JimIsWide(objPtr)) { |
| 13904 | + *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; |
| 13671 | 13905 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 13672 | 13906 | return JIM_OK; |
| 13673 | 13907 | } |
| 13674 | 13908 | } |
| 13675 | 13909 | break; |
| 13676 | 13910 | |
| 13677 | 13911 | case 3: |
| 13678 | | - if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT |
| 13679 | | - || expr->token[1].type == JIM_TT_VAR)) { |
| 13680 | | - switch (expr->token[2].type) { |
| 13681 | | - case JIM_EXPROP_LT: |
| 13682 | | - case JIM_EXPROP_LTE: |
| 13683 | | - case JIM_EXPROP_GT: |
| 13684 | | - case JIM_EXPROP_GTE: |
| 13685 | | - case JIM_EXPROP_NUMEQ: |
| 13686 | | - case JIM_EXPROP_NUMNE:{ |
| 13687 | | - |
| 13688 | | - jim_wide wideValueA; |
| 13689 | | - jim_wide wideValueB; |
| 13690 | | - |
| 13691 | | - objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); |
| 13692 | | - if (objPtr && JimIsWide(objPtr) |
| 13693 | | - && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) { |
| 13694 | | - if (expr->token[1].type == JIM_TT_VAR) { |
| 13695 | | - objPtr = |
| 13696 | | - Jim_GetVariable(interp, expr->token[1].objPtr, |
| 13697 | | - JIM_NONE); |
| 13698 | | - } |
| 13699 | | - else { |
| 13700 | | - objPtr = expr->token[1].objPtr; |
| 13701 | | - } |
| 13702 | | - if (objPtr && JimIsWide(objPtr) |
| 13703 | | - && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) { |
| 13704 | | - int cmpRes; |
| 13705 | | - |
| 13706 | | - switch (expr->token[2].type) { |
| 13707 | | - case JIM_EXPROP_LT: |
| 13708 | | - cmpRes = wideValueA < wideValueB; |
| 13709 | | - break; |
| 13710 | | - case JIM_EXPROP_LTE: |
| 13711 | | - cmpRes = wideValueA <= wideValueB; |
| 13712 | | - break; |
| 13713 | | - case JIM_EXPROP_GT: |
| 13714 | | - cmpRes = wideValueA > wideValueB; |
| 13715 | | - break; |
| 13716 | | - case JIM_EXPROP_GTE: |
| 13717 | | - cmpRes = wideValueA >= wideValueB; |
| 13718 | | - break; |
| 13719 | | - case JIM_EXPROP_NUMEQ: |
| 13720 | | - cmpRes = wideValueA == wideValueB; |
| 13721 | | - break; |
| 13722 | | - case JIM_EXPROP_NUMNE: |
| 13723 | | - cmpRes = wideValueA != wideValueB; |
| 13724 | | - break; |
| 13725 | | - default: |
| 13726 | | - cmpRes = 0; |
| 13727 | | - } |
| 13728 | | - *exprResultPtrPtr = |
| 13729 | | - cmpRes ? interp->trueObj : interp->falseObj; |
| 13730 | | - Jim_IncrRefCount(*exprResultPtrPtr); |
| 13731 | | - return JIM_OK; |
| 13732 | | - } |
| 13733 | | - } |
| 13734 | | - } |
| 13735 | | - } |
| 13736 | | - } |
| 13737 | | - break; |
| 13738 | | - } |
| 13739 | | - } |
| 13912 | + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 13913 | + if (objPtr && JimIsWide(objPtr)) { |
| 13914 | + Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); |
| 13915 | + if (objPtr2 && JimIsWide(objPtr2)) { |
| 13916 | + jim_wide wideValueA = JimWideValue(objPtr); |
| 13917 | + jim_wide wideValueB = JimWideValue(objPtr2); |
| 13918 | + int cmpRes; |
| 13919 | + switch (expr->token[2].type) { |
| 13920 | + case JIM_EXPROP_LT: |
| 13921 | + cmpRes = wideValueA < wideValueB; |
| 13922 | + break; |
| 13923 | + case JIM_EXPROP_LTE: |
| 13924 | + cmpRes = wideValueA <= wideValueB; |
| 13925 | + break; |
| 13926 | + case JIM_EXPROP_GT: |
| 13927 | + cmpRes = wideValueA > wideValueB; |
| 13928 | + break; |
| 13929 | + case JIM_EXPROP_GTE: |
| 13930 | + cmpRes = wideValueA >= wideValueB; |
| 13931 | + break; |
| 13932 | + case JIM_EXPROP_NUMEQ: |
| 13933 | + cmpRes = wideValueA == wideValueB; |
| 13934 | + break; |
| 13935 | + case JIM_EXPROP_NUMNE: |
| 13936 | + cmpRes = wideValueA != wideValueB; |
| 13937 | + break; |
| 13938 | + default: |
| 13939 | + goto noopt; |
| 13940 | + } |
| 13941 | + *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; |
| 13942 | + Jim_IncrRefCount(*exprResultPtrPtr); |
| 13943 | + return JIM_OK; |
| 13944 | + } |
| 13945 | + } |
| 13946 | + break; |
| 13947 | + } |
| 13948 | + } |
| 13949 | +noopt: |
| 13740 | 13950 | #endif |
| 13741 | 13951 | |
| 13742 | 13952 | expr->inUse++; |
| 13743 | 13953 | |
| 13744 | 13954 | |
| | @@ -13855,16 +14065,16 @@ |
| 13855 | 14065 | |
| 13856 | 14066 | |
| 13857 | 14067 | |
| 13858 | 14068 | typedef struct ScanFmtPartDescr |
| 13859 | 14069 | { |
| 13860 | | - char type; |
| 13861 | | - char modifier; |
| 14070 | + char *arg; |
| 14071 | + char *prefix; |
| 13862 | 14072 | size_t width; |
| 13863 | 14073 | int pos; |
| 13864 | | - char *arg; |
| 13865 | | - char *prefix; |
| 14074 | + char type; |
| 14075 | + char modifier; |
| 13866 | 14076 | } ScanFmtPartDescr; |
| 13867 | 14077 | |
| 13868 | 14078 | |
| 13869 | 14079 | typedef struct ScanFmtStringObj |
| 13870 | 14080 | { |
| | @@ -13907,16 +14117,13 @@ |
| 13907 | 14117 | memcpy(newVec, srcPtr->internalRep.ptr, size); |
| 13908 | 14118 | dupPtr->internalRep.ptr = newVec; |
| 13909 | 14119 | dupPtr->typePtr = &scanFmtStringObjType; |
| 13910 | 14120 | } |
| 13911 | 14121 | |
| 13912 | | -void UpdateStringOfScanFmt(Jim_Obj *objPtr) |
| 14122 | +static void UpdateStringOfScanFmt(Jim_Obj *objPtr) |
| 13913 | 14123 | { |
| 13914 | | - char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep; |
| 13915 | | - |
| 13916 | | - objPtr->bytes = Jim_StrDup(bytes); |
| 13917 | | - objPtr->length = strlen(bytes); |
| 14124 | + JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep); |
| 13918 | 14125 | } |
| 13919 | 14126 | |
| 13920 | 14127 | |
| 13921 | 14128 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13922 | 14129 | { |
| | @@ -14126,11 +14333,10 @@ |
| 14126 | 14333 | Jim_Obj *tmpObj = NULL; |
| 14127 | 14334 | |
| 14128 | 14335 | |
| 14129 | 14336 | *valObjPtr = 0; |
| 14130 | 14337 | if (descr->prefix) { |
| 14131 | | - |
| 14132 | 14338 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14133 | 14339 | |
| 14134 | 14340 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14135 | 14341 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14136 | 14342 | ++pos; |
| | @@ -14467,34 +14673,55 @@ |
| 14467 | 14673 | } |
| 14468 | 14674 | |
| 14469 | 14675 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14470 | 14676 | { |
| 14471 | 14677 | int retcode; |
| 14472 | | - Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| 14678 | + Jim_Cmd *cmdPtr; |
| 14473 | 14679 | |
| 14474 | | - if (cmdPtr == NULL) { |
| 14475 | | - return JimUnknown(interp, objc, objv); |
| 14680 | +#if 0 |
| 14681 | + printf("invoke"); |
| 14682 | + int j; |
| 14683 | + for (j = 0; j < objc; j++) { |
| 14684 | + printf(" '%s'", Jim_String(objv[j])); |
| 14476 | 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 | + |
| 14477 | 14702 | if (interp->evalDepth == interp->maxEvalDepth) { |
| 14478 | 14703 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14479 | | - return JIM_ERR; |
| 14704 | + retcode = JIM_ERR; |
| 14705 | + goto out; |
| 14480 | 14706 | } |
| 14481 | 14707 | interp->evalDepth++; |
| 14482 | 14708 | |
| 14483 | 14709 | |
| 14484 | | - JimIncrCmdRefCount(cmdPtr); |
| 14485 | 14710 | Jim_SetEmptyResult(interp); |
| 14486 | 14711 | if (cmdPtr->isproc) { |
| 14487 | 14712 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14488 | 14713 | } |
| 14489 | 14714 | else { |
| 14490 | 14715 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14491 | 14716 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14492 | 14717 | } |
| 14493 | | - JimDecrCmdRefCount(interp, cmdPtr); |
| 14494 | 14718 | interp->evalDepth--; |
| 14495 | 14719 | |
| 14720 | +out: |
| 14721 | + JimDecrCmdRefCount(interp, cmdPtr); |
| 14722 | + |
| 14496 | 14723 | return retcode; |
| 14497 | 14724 | } |
| 14498 | 14725 | |
| 14499 | 14726 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14500 | 14727 | { |
| | @@ -14672,10 +14899,15 @@ |
| 14672 | 14899 | objPtr->typePtr = &interpolatedObjType; |
| 14673 | 14900 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 14674 | 14901 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 14675 | 14902 | Jim_IncrRefCount(intv[2]); |
| 14676 | 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 | + |
| 14677 | 14909 | |
| 14678 | 14910 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| 14679 | 14911 | objPtr->length = totlen; |
| 14680 | 14912 | for (i = 0; i < tokens; i++) { |
| 14681 | 14913 | if (intv[i]) { |
| | @@ -14727,10 +14959,14 @@ |
| 14727 | 14959 | return JimEvalObjList(interp, scriptObjPtr); |
| 14728 | 14960 | } |
| 14729 | 14961 | |
| 14730 | 14962 | Jim_IncrRefCount(scriptObjPtr); |
| 14731 | 14963 | script = Jim_GetScript(interp, scriptObjPtr); |
| 14964 | + if (script == NULL) { |
| 14965 | + Jim_DecrRefCount(interp, scriptObjPtr); |
| 14966 | + return JIM_ERR; |
| 14967 | + } |
| 14732 | 14968 | |
| 14733 | 14969 | Jim_SetEmptyResult(interp); |
| 14734 | 14970 | |
| 14735 | 14971 | token = script->token; |
| 14736 | 14972 | |
| | @@ -14871,12 +15107,12 @@ |
| 14871 | 15107 | } |
| 14872 | 15108 | |
| 14873 | 15109 | if (retcode == JIM_OK && argc) { |
| 14874 | 15110 | |
| 14875 | 15111 | retcode = JimInvokeCommand(interp, argc, argv); |
| 14876 | | - if (interp->signal_level && interp->sigmask) { |
| 14877 | | - |
| 15112 | + |
| 15113 | + if (Jim_CheckSignal(interp)) { |
| 14878 | 15114 | retcode = JIM_SIGNAL; |
| 14879 | 15115 | } |
| 14880 | 15116 | } |
| 14881 | 15117 | |
| 14882 | 15118 | |
| | @@ -15001,26 +15237,20 @@ |
| 15001 | 15237 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15002 | 15238 | } |
| 15003 | 15239 | |
| 15004 | 15240 | |
| 15005 | 15241 | interp->framePtr = interp->framePtr->parent; |
| 15006 | | - if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { |
| 15007 | | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); |
| 15008 | | - } |
| 15009 | | - else { |
| 15010 | | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); |
| 15011 | | - } |
| 15242 | + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15012 | 15243 | |
| 15013 | 15244 | return retcode; |
| 15014 | 15245 | } |
| 15015 | 15246 | #endif |
| 15016 | 15247 | |
| 15017 | 15248 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) |
| 15018 | 15249 | { |
| 15019 | 15250 | Jim_CallFrame *callFramePtr; |
| 15020 | 15251 | int i, d, retcode, optargs; |
| 15021 | | - Jim_Stack *localCommands; |
| 15022 | 15252 | ScriptObj *script; |
| 15023 | 15253 | |
| 15024 | 15254 | |
| 15025 | 15255 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15026 | 15256 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| | @@ -15100,37 +15330,42 @@ |
| 15100 | 15330 | |
| 15101 | 15331 | |
| 15102 | 15332 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15103 | 15333 | |
| 15104 | 15334 | badargset: |
| 15335 | + |
| 15105 | 15336 | |
| 15106 | | - |
| 15107 | | - localCommands = callFramePtr->localCommands; |
| 15108 | | - callFramePtr->localCommands = NULL; |
| 15109 | | - |
| 15110 | 15337 | interp->framePtr = interp->framePtr->parent; |
| 15111 | | - if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { |
| 15112 | | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); |
| 15113 | | - } |
| 15114 | | - else { |
| 15115 | | - JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); |
| 15116 | | - } |
| 15117 | | - |
| 15118 | | - |
| 15119 | | - while (retcode == JIM_EVAL) { |
| 15120 | | - Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); |
| 15121 | | - |
| 15122 | | - Jim_IncrRefCount(resultScriptObjPtr); |
| 15123 | | - |
| 15124 | | - JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list")); |
| 15125 | | - |
| 15126 | | - retcode = JimEvalObjList(interp, resultScriptObjPtr); |
| 15127 | | - if (retcode == JIM_RETURN) { |
| 15128 | | - interp->returnLevel++; |
| 15129 | | - } |
| 15130 | | - Jim_DecrRefCount(interp, resultScriptObjPtr); |
| 15131 | | - } |
| 15338 | + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15339 | + |
| 15340 | + if (interp->framePtr->tailcallObj) { |
| 15341 | + |
| 15342 | + if (interp->framePtr->tailcall++ == 0) { |
| 15343 | + |
| 15344 | + do { |
| 15345 | + Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15346 | + |
| 15347 | + interp->framePtr->tailcallObj = NULL; |
| 15348 | + |
| 15349 | + if (retcode == JIM_EVAL) { |
| 15350 | + retcode = Jim_EvalObjList(interp, tailcallObj); |
| 15351 | + if (retcode == JIM_RETURN) { |
| 15352 | + interp->returnLevel++; |
| 15353 | + } |
| 15354 | + } |
| 15355 | + Jim_DecrRefCount(interp, tailcallObj); |
| 15356 | + } while (interp->framePtr->tailcallObj); |
| 15357 | + |
| 15358 | + |
| 15359 | + if (interp->framePtr->tailcallCmd) { |
| 15360 | + JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15361 | + interp->framePtr->tailcallCmd = NULL; |
| 15362 | + } |
| 15363 | + } |
| 15364 | + interp->framePtr->tailcall--; |
| 15365 | + } |
| 15366 | + |
| 15132 | 15367 | |
| 15133 | 15368 | if (retcode == JIM_RETURN) { |
| 15134 | 15369 | if (--interp->returnLevel <= 0) { |
| 15135 | 15370 | retcode = interp->returnCode; |
| 15136 | 15371 | interp->returnCode = JIM_OK; |
| | @@ -15142,13 +15377,10 @@ |
| 15142 | 15377 | Jim_DecrRefCount(interp, interp->errorProc); |
| 15143 | 15378 | interp->errorProc = argv[0]; |
| 15144 | 15379 | Jim_IncrRefCount(interp->errorProc); |
| 15145 | 15380 | } |
| 15146 | 15381 | |
| 15147 | | - |
| 15148 | | - JimDeleteLocalProcs(interp, localCommands); |
| 15149 | | - |
| 15150 | 15382 | return retcode; |
| 15151 | 15383 | } |
| 15152 | 15384 | |
| 15153 | 15385 | int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) |
| 15154 | 15386 | { |
| | @@ -15216,11 +15448,10 @@ |
| 15216 | 15448 | Jim_Obj *scriptObjPtr; |
| 15217 | 15449 | Jim_Obj *prevScriptObj; |
| 15218 | 15450 | struct stat sb; |
| 15219 | 15451 | int retcode; |
| 15220 | 15452 | int readlen; |
| 15221 | | - struct JimParseResult result; |
| 15222 | 15453 | |
| 15223 | 15454 | if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { |
| 15224 | 15455 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); |
| 15225 | 15456 | return JIM_ERR; |
| 15226 | 15457 | } |
| | @@ -15243,31 +15474,13 @@ |
| 15243 | 15474 | scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 15244 | 15475 | JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); |
| 15245 | 15476 | Jim_IncrRefCount(scriptObjPtr); |
| 15246 | 15477 | |
| 15247 | 15478 | |
| 15248 | | - if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) { |
| 15249 | | - const char *msg; |
| 15250 | | - char linebuf[20]; |
| 15251 | | - |
| 15252 | | - switch (result.missing) { |
| 15253 | | - case '[': |
| 15254 | | - msg = "unmatched \"[\""; |
| 15255 | | - break; |
| 15256 | | - case '{': |
| 15257 | | - msg = "missing close-brace"; |
| 15258 | | - break; |
| 15259 | | - case '"': |
| 15260 | | - default: |
| 15261 | | - msg = "missing quote"; |
| 15262 | | - break; |
| 15263 | | - } |
| 15264 | | - |
| 15265 | | - snprintf(linebuf, sizeof(linebuf), "%d", result.line); |
| 15266 | | - |
| 15267 | | - Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s", |
| 15268 | | - msg, filename, linebuf); |
| 15479 | + if (Jim_GetScript(interp, scriptObjPtr) == NULL) { |
| 15480 | + |
| 15481 | + JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr)); |
| 15269 | 15482 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15270 | 15483 | return JIM_ERR; |
| 15271 | 15484 | } |
| 15272 | 15485 | |
| 15273 | 15486 | prevScriptObj = interp->currentScriptObj; |
| | @@ -15430,11 +15643,11 @@ |
| 15430 | 15643 | } |
| 15431 | 15644 | |
| 15432 | 15645 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15433 | 15646 | Jim_HashEntry *he, int type); |
| 15434 | 15647 | |
| 15435 | | -#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) |
| 15648 | +#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) |
| 15436 | 15649 | |
| 15437 | 15650 | static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 15438 | 15651 | JimHashtableIteratorCallbackType *callback, int type) |
| 15439 | 15652 | { |
| 15440 | 15653 | Jim_HashEntry *he; |
| | @@ -15446,17 +15659,17 @@ |
| 15446 | 15659 | if (he) { |
| 15447 | 15660 | callback(interp, listObjPtr, he, type); |
| 15448 | 15661 | } |
| 15449 | 15662 | } |
| 15450 | 15663 | else { |
| 15451 | | - Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht); |
| 15452 | | - while ((he = Jim_NextHashEntry(htiter)) != NULL) { |
| 15664 | + Jim_HashTableIterator htiter; |
| 15665 | + JimInitHashTableIterator(ht, &htiter); |
| 15666 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 15453 | 15667 | if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) { |
| 15454 | 15668 | callback(interp, listObjPtr, he, type); |
| 15455 | 15669 | } |
| 15456 | 15670 | } |
| 15457 | | - Jim_FreeHashTableIterator(htiter); |
| 15458 | 15671 | } |
| 15459 | 15672 | return listObjPtr; |
| 15460 | 15673 | } |
| 15461 | 15674 | |
| 15462 | 15675 | |
| | @@ -15465,11 +15678,11 @@ |
| 15465 | 15678 | #define JIM_CMDLIST_CHANNELS 2 |
| 15466 | 15679 | |
| 15467 | 15680 | static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15468 | 15681 | Jim_HashEntry *he, int type) |
| 15469 | 15682 | { |
| 15470 | | - Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val; |
| 15683 | + Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15471 | 15684 | Jim_Obj *objPtr; |
| 15472 | 15685 | |
| 15473 | 15686 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15474 | 15687 | |
| 15475 | 15688 | return; |
| | @@ -15498,11 +15711,11 @@ |
| 15498 | 15711 | #define JIM_VARLIST_VALUES 0x1000 |
| 15499 | 15712 | |
| 15500 | 15713 | static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15501 | 15714 | Jim_HashEntry *he, int type) |
| 15502 | 15715 | { |
| 15503 | | - Jim_Var *varPtr = (Jim_Var *)he->u.val; |
| 15716 | + Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 15504 | 15717 | |
| 15505 | 15718 | if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { |
| 15506 | 15719 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); |
| 15507 | 15720 | if (type & JIM_VARLIST_VALUES) { |
| 15508 | 15721 | Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); |
| | @@ -15820,11 +16033,11 @@ |
| 15820 | 16033 | |
| 15821 | 16034 | expr = JimGetExpression(interp, argv[2]); |
| 15822 | 16035 | incrScript = Jim_GetScript(interp, argv[3]); |
| 15823 | 16036 | |
| 15824 | 16037 | |
| 15825 | | - if (incrScript->len != 3 || !expr || expr->len != 3) { |
| 16038 | + if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { |
| 15826 | 16039 | goto evalstart; |
| 15827 | 16040 | } |
| 15828 | 16041 | |
| 15829 | 16042 | if (incrScript->token[1].type != JIM_TT_ESC || |
| 15830 | 16043 | expr->token[0].type != JIM_TT_VAR || |
| | @@ -16043,11 +16256,11 @@ |
| 16043 | 16256 | } |
| 16044 | 16257 | |
| 16045 | 16258 | |
| 16046 | 16259 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16047 | 16260 | { |
| 16048 | | - int result = JIM_ERR; |
| 16261 | + int result = JIM_OK; |
| 16049 | 16262 | int i, numargs; |
| 16050 | 16263 | Jim_ListIter twoiters[2]; |
| 16051 | 16264 | Jim_ListIter *iters; |
| 16052 | 16265 | Jim_Obj *script; |
| 16053 | 16266 | Jim_Obj *resultObj; |
| | @@ -16066,13 +16279,16 @@ |
| 16066 | 16279 | iters = Jim_Alloc(numargs * sizeof(*iters)); |
| 16067 | 16280 | } |
| 16068 | 16281 | for (i = 0; i < numargs; i++) { |
| 16069 | 16282 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16070 | 16283 | if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { |
| 16071 | | - Jim_SetResultString(interp, "foreach varlist is empty", -1); |
| 16072 | | - return JIM_ERR; |
| 16284 | + result = JIM_ERR; |
| 16073 | 16285 | } |
| 16286 | + } |
| 16287 | + if (result != JIM_OK) { |
| 16288 | + Jim_SetResultString(interp, "foreach varlist is empty", -1); |
| 16289 | + return result; |
| 16074 | 16290 | } |
| 16075 | 16291 | |
| 16076 | 16292 | if (doMap) { |
| 16077 | 16293 | resultObj = Jim_NewListObj(interp, NULL, 0); |
| 16078 | 16294 | } |
| | @@ -16385,12 +16601,12 @@ |
| 16385 | 16601 | { |
| 16386 | 16602 | Jim_Obj *objPtr, *listObjPtr; |
| 16387 | 16603 | int i; |
| 16388 | 16604 | int idx; |
| 16389 | 16605 | |
| 16390 | | - if (argc < 3) { |
| 16391 | | - Jim_WrongNumArgs(interp, 1, argv, "list index ?...?"); |
| 16606 | + if (argc < 2) { |
| 16607 | + Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); |
| 16392 | 16608 | return JIM_ERR; |
| 16393 | 16609 | } |
| 16394 | 16610 | objPtr = argv[1]; |
| 16395 | 16611 | Jim_IncrRefCount(objPtr); |
| 16396 | 16612 | for (i = 2; i < argc; i++) { |
| | @@ -16502,14 +16718,13 @@ |
| 16502 | 16718 | Jim_IncrRefCount(commandObj); |
| 16503 | 16719 | } |
| 16504 | 16720 | |
| 16505 | 16721 | listlen = Jim_ListLength(interp, argv[0]); |
| 16506 | 16722 | for (i = 0; i < listlen; i++) { |
| 16507 | | - Jim_Obj *objPtr; |
| 16508 | 16723 | int eq = 0; |
| 16724 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); |
| 16509 | 16725 | |
| 16510 | | - Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE); |
| 16511 | 16726 | switch (opt_match) { |
| 16512 | 16727 | case OPT_EXACT: |
| 16513 | 16728 | eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; |
| 16514 | 16729 | break; |
| 16515 | 16730 | |
| | @@ -16699,29 +16914,27 @@ |
| 16699 | 16914 | if (argc < 3) { |
| 16700 | 16915 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 16701 | 16916 | return JIM_ERR; |
| 16702 | 16917 | } |
| 16703 | 16918 | else if (argc == 3) { |
| 16919 | + |
| 16704 | 16920 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16705 | 16921 | return JIM_ERR; |
| 16706 | 16922 | Jim_SetResult(interp, argv[2]); |
| 16707 | 16923 | return JIM_OK; |
| 16708 | 16924 | } |
| 16709 | | - if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]) |
| 16710 | | - == JIM_ERR) |
| 16711 | | - return JIM_ERR; |
| 16712 | | - return JIM_OK; |
| 16925 | + return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]); |
| 16713 | 16926 | } |
| 16714 | 16927 | |
| 16715 | 16928 | |
| 16716 | 16929 | static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) |
| 16717 | 16930 | { |
| 16718 | 16931 | static const char * const options[] = { |
| 16719 | | - "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL |
| 16932 | + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL |
| 16720 | 16933 | }; |
| 16721 | 16934 | enum |
| 16722 | | - { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX }; |
| 16935 | + { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 16723 | 16936 | Jim_Obj *resObj; |
| 16724 | 16937 | int i; |
| 16725 | 16938 | int retCode; |
| 16726 | 16939 | |
| 16727 | 16940 | struct lsort_info info; |
| | @@ -16732,17 +16945,18 @@ |
| 16732 | 16945 | } |
| 16733 | 16946 | |
| 16734 | 16947 | info.type = JIM_LSORT_ASCII; |
| 16735 | 16948 | info.order = 1; |
| 16736 | 16949 | info.indexed = 0; |
| 16950 | + info.unique = 0; |
| 16737 | 16951 | info.command = NULL; |
| 16738 | 16952 | info.interp = interp; |
| 16739 | 16953 | |
| 16740 | 16954 | for (i = 1; i < (argc - 1); i++) { |
| 16741 | 16955 | int option; |
| 16742 | 16956 | |
| 16743 | | - if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) |
| 16957 | + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) |
| 16744 | 16958 | != JIM_OK) |
| 16745 | 16959 | return JIM_ERR; |
| 16746 | 16960 | switch (option) { |
| 16747 | 16961 | case OPT_ASCII: |
| 16748 | 16962 | info.type = JIM_LSORT_ASCII; |
| | @@ -16751,16 +16965,22 @@ |
| 16751 | 16965 | info.type = JIM_LSORT_NOCASE; |
| 16752 | 16966 | break; |
| 16753 | 16967 | case OPT_INTEGER: |
| 16754 | 16968 | info.type = JIM_LSORT_INTEGER; |
| 16755 | 16969 | break; |
| 16970 | + case OPT_REAL: |
| 16971 | + info.type = JIM_LSORT_REAL; |
| 16972 | + break; |
| 16756 | 16973 | case OPT_INCREASING: |
| 16757 | 16974 | info.order = 1; |
| 16758 | 16975 | break; |
| 16759 | 16976 | case OPT_DECREASING: |
| 16760 | 16977 | info.order = -1; |
| 16761 | 16978 | break; |
| 16979 | + case OPT_UNIQUE: |
| 16980 | + info.unique = 1; |
| 16981 | + break; |
| 16762 | 16982 | case OPT_COMMAND: |
| 16763 | 16983 | if (i >= (argc - 2)) { |
| 16764 | 16984 | Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); |
| 16765 | 16985 | return JIM_ERR; |
| 16766 | 16986 | } |
| | @@ -16870,20 +17090,20 @@ |
| 16870 | 17090 | static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16871 | 17091 | { |
| 16872 | 17092 | if (argc >= 2) { |
| 16873 | 17093 | int retcode; |
| 16874 | 17094 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 16875 | | - Jim_Obj *objPtr; |
| 17095 | + int savedTailcall; |
| 16876 | 17096 | const char *str; |
| 16877 | 17097 | |
| 16878 | 17098 | |
| 16879 | 17099 | savedCallFrame = interp->framePtr; |
| 16880 | 17100 | |
| 16881 | 17101 | |
| 16882 | 17102 | str = Jim_String(argv[1]); |
| 16883 | 17103 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 16884 | | - targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17104 | + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 16885 | 17105 | argc--; |
| 16886 | 17106 | argv++; |
| 16887 | 17107 | } |
| 16888 | 17108 | else { |
| 16889 | 17109 | targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); |
| | @@ -16890,25 +17110,25 @@ |
| 16890 | 17110 | } |
| 16891 | 17111 | if (targetCallFrame == NULL) { |
| 16892 | 17112 | return JIM_ERR; |
| 16893 | 17113 | } |
| 16894 | 17114 | if (argc < 2) { |
| 16895 | | - argv--; |
| 16896 | | - Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| 17115 | + Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); |
| 16897 | 17116 | return JIM_ERR; |
| 16898 | 17117 | } |
| 16899 | 17118 | |
| 16900 | 17119 | interp->framePtr = targetCallFrame; |
| 17120 | + |
| 17121 | + savedTailcall = interp->framePtr->tailcall; |
| 17122 | + interp->framePtr->tailcall = 0; |
| 16901 | 17123 | if (argc == 2) { |
| 16902 | 17124 | retcode = Jim_EvalObj(interp, argv[1]); |
| 16903 | 17125 | } |
| 16904 | 17126 | else { |
| 16905 | | - objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 16906 | | - Jim_IncrRefCount(objPtr); |
| 16907 | | - retcode = Jim_EvalObj(interp, objPtr); |
| 16908 | | - Jim_DecrRefCount(interp, objPtr); |
| 17127 | + retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 16909 | 17128 | } |
| 17129 | + interp->framePtr->tailcall = savedTailcall; |
| 16910 | 17130 | interp->framePtr = savedCallFrame; |
| 16911 | 17131 | return retcode; |
| 16912 | 17132 | } |
| 16913 | 17133 | else { |
| 16914 | 17134 | Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); |
| | @@ -17019,12 +17239,39 @@ |
| 17019 | 17239 | } |
| 17020 | 17240 | |
| 17021 | 17241 | |
| 17022 | 17242 | static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17023 | 17243 | { |
| 17024 | | - Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1)); |
| 17025 | | - return JIM_EVAL; |
| 17244 | + if (interp->framePtr->level == 0) { |
| 17245 | + Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); |
| 17246 | + return JIM_ERR; |
| 17247 | + } |
| 17248 | + else if (argc >= 2) { |
| 17249 | + |
| 17250 | + Jim_CallFrame *cf = interp->framePtr->parent; |
| 17251 | + |
| 17252 | + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17253 | + if (cmdPtr == NULL) { |
| 17254 | + return JIM_ERR; |
| 17255 | + } |
| 17256 | + |
| 17257 | + JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); |
| 17258 | + |
| 17259 | + |
| 17260 | + JimIncrCmdRefCount(cmdPtr); |
| 17261 | + cf->tailcallCmd = cmdPtr; |
| 17262 | + |
| 17263 | + |
| 17264 | + JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); |
| 17265 | + |
| 17266 | + cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 17267 | + Jim_IncrRefCount(cf->tailcallObj); |
| 17268 | + |
| 17269 | + |
| 17270 | + return JIM_EVAL; |
| 17271 | + } |
| 17272 | + return JIM_OK; |
| 17026 | 17273 | } |
| 17027 | 17274 | |
| 17028 | 17275 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17029 | 17276 | { |
| 17030 | 17277 | Jim_Obj *cmdList; |
| | @@ -17108,10 +17355,15 @@ |
| 17108 | 17355 | |
| 17109 | 17356 | |
| 17110 | 17357 | static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17111 | 17358 | { |
| 17112 | 17359 | int retcode; |
| 17360 | + |
| 17361 | + if (argc < 2) { |
| 17362 | + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); |
| 17363 | + return JIM_ERR; |
| 17364 | + } |
| 17113 | 17365 | |
| 17114 | 17366 | |
| 17115 | 17367 | interp->local++; |
| 17116 | 17368 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17117 | 17369 | interp->local--; |
| | @@ -17304,11 +17556,11 @@ |
| 17304 | 17556 | for (i = 0; i < numMaps; i += 2) { |
| 17305 | 17557 | Jim_Obj *objPtr; |
| 17306 | 17558 | const char *k; |
| 17307 | 17559 | int kl; |
| 17308 | 17560 | |
| 17309 | | - Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE); |
| 17561 | + objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); |
| 17310 | 17562 | k = Jim_String(objPtr); |
| 17311 | 17563 | kl = Jim_Utf8Length(interp, objPtr); |
| 17312 | 17564 | |
| 17313 | 17565 | if (strLen >= kl && kl) { |
| 17314 | 17566 | int rc; |
| | @@ -17316,12 +17568,11 @@ |
| 17316 | 17568 | if (rc == 0) { |
| 17317 | 17569 | if (noMatchStart) { |
| 17318 | 17570 | Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); |
| 17319 | 17571 | noMatchStart = NULL; |
| 17320 | 17572 | } |
| 17321 | | - Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE); |
| 17322 | | - Jim_AppendObj(interp, resultObjPtr, objPtr); |
| 17573 | + Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1)); |
| 17323 | 17574 | str += utf8_index(str, kl); |
| 17324 | 17575 | strLen -= kl; |
| 17325 | 17576 | break; |
| 17326 | 17577 | } |
| 17327 | 17578 | } |
| | @@ -17795,21 +18046,23 @@ |
| 17795 | 18046 | if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { |
| 17796 | 18047 | sig++; |
| 17797 | 18048 | } |
| 17798 | 18049 | |
| 17799 | 18050 | interp->signal_level += sig; |
| 17800 | | - if (interp->signal_level && interp->sigmask) { |
| 18051 | + if (Jim_CheckSignal(interp)) { |
| 17801 | 18052 | |
| 17802 | 18053 | exitCode = JIM_SIGNAL; |
| 17803 | 18054 | } |
| 17804 | 18055 | else { |
| 17805 | 18056 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18057 | + |
| 18058 | + interp->errorFlag = 0; |
| 17806 | 18059 | } |
| 17807 | 18060 | interp->signal_level -= sig; |
| 17808 | 18061 | |
| 17809 | 18062 | |
| 17810 | | - if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) { |
| 18063 | + if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 17811 | 18064 | |
| 17812 | 18065 | return exitCode; |
| 17813 | 18066 | } |
| 17814 | 18067 | |
| 17815 | 18068 | if (sig && exitCode == JIM_SIGNAL) { |
| | @@ -17951,25 +18204,24 @@ |
| 17951 | 18204 | |
| 17952 | 18205 | |
| 17953 | 18206 | static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17954 | 18207 | { |
| 17955 | 18208 | Jim_Obj *listObjPtr; |
| 17956 | | - Jim_HashTableIterator *htiter; |
| 18209 | + Jim_HashTableIterator htiter; |
| 17957 | 18210 | Jim_HashEntry *he; |
| 17958 | 18211 | |
| 17959 | 18212 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 17960 | 18213 | |
| 17961 | | - htiter = Jim_GetHashTableIterator(&interp->references); |
| 17962 | | - while ((he = Jim_NextHashEntry(htiter)) != NULL) { |
| 18214 | + JimInitHashTableIterator(&interp->references, &htiter); |
| 18215 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 17963 | 18216 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 17964 | | - Jim_Reference *refPtr = he->u.val; |
| 18217 | + Jim_Reference *refPtr = Jim_GetHashEntryVal(he); |
| 17965 | 18218 | const unsigned long *refId = he->key; |
| 17966 | 18219 | |
| 17967 | 18220 | JimFormatReference(buf, refPtr, *refId); |
| 17968 | 18221 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); |
| 17969 | 18222 | } |
| 17970 | | - Jim_FreeHashTableIterator(htiter); |
| 17971 | 18223 | Jim_SetResult(interp, listObjPtr); |
| 17972 | 18224 | return JIM_OK; |
| 17973 | 18225 | } |
| 17974 | 18226 | #endif |
| 17975 | 18227 | |
| | @@ -17994,11 +18246,11 @@ |
| 17994 | 18246 | |
| 17995 | 18247 | static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) |
| 17996 | 18248 | { |
| 17997 | 18249 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 17998 | 18250 | if (type & JIM_DICTMATCH_VALUES) { |
| 17999 | | - Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val); |
| 18251 | + Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); |
| 18000 | 18252 | } |
| 18001 | 18253 | } |
| 18002 | 18254 | |
| 18003 | 18255 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 18004 | 18256 | JimDictMatchCallbackType *callback, int type) |
| | @@ -18005,17 +18257,17 @@ |
| 18005 | 18257 | { |
| 18006 | 18258 | Jim_HashEntry *he; |
| 18007 | 18259 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18008 | 18260 | |
| 18009 | 18261 | |
| 18010 | | - Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht); |
| 18011 | | - while ((he = Jim_NextHashEntry(htiter)) != NULL) { |
| 18262 | + Jim_HashTableIterator htiter; |
| 18263 | + JimInitHashTableIterator(ht, &htiter); |
| 18264 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18012 | 18265 | if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { |
| 18013 | 18266 | callback(interp, listObjPtr, he, type); |
| 18014 | 18267 | } |
| 18015 | 18268 | } |
| 18016 | | - Jim_FreeHashTableIterator(htiter); |
| 18017 | 18269 | |
| 18018 | 18270 | return listObjPtr; |
| 18019 | 18271 | } |
| 18020 | 18272 | |
| 18021 | 18273 | |
| | @@ -18043,21 +18295,65 @@ |
| 18043 | 18295 | return -1; |
| 18044 | 18296 | } |
| 18045 | 18297 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18046 | 18298 | } |
| 18047 | 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 | + |
| 18048 | 18340 | |
| 18049 | 18341 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18050 | 18342 | { |
| 18051 | 18343 | Jim_Obj *objPtr; |
| 18052 | 18344 | int option; |
| 18053 | 18345 | static const char * const options[] = { |
| 18054 | | - "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL |
| 18346 | + "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18347 | + "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18348 | + "replace", "update", NULL |
| 18055 | 18349 | }; |
| 18056 | 18350 | enum |
| 18057 | 18351 | { |
| 18058 | | - OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH, |
| 18352 | + OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, |
| 18353 | + OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, |
| 18354 | + OPT_REPLACE, OPT_UPDATE, |
| 18059 | 18355 | }; |
| 18060 | 18356 | |
| 18061 | 18357 | if (argc < 2) { |
| 18062 | 18358 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18063 | 18359 | return JIM_ERR; |
| | @@ -18068,11 +18364,11 @@ |
| 18068 | 18364 | } |
| 18069 | 18365 | |
| 18070 | 18366 | switch (option) { |
| 18071 | 18367 | case OPT_GET: |
| 18072 | 18368 | if (argc < 3) { |
| 18073 | | - Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); |
| 18369 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); |
| 18074 | 18370 | return JIM_ERR; |
| 18075 | 18371 | } |
| 18076 | 18372 | if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, |
| 18077 | 18373 | JIM_ERRMSG) != JIM_OK) { |
| 18078 | 18374 | return JIM_ERR; |
| | @@ -18085,82 +18381,87 @@ |
| 18085 | 18381 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); |
| 18086 | 18382 | return JIM_ERR; |
| 18087 | 18383 | } |
| 18088 | 18384 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); |
| 18089 | 18385 | |
| 18090 | | - case OPT_EXIST: |
| 18091 | | - if (argc < 3) { |
| 18092 | | - Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); |
| 18386 | + case OPT_EXISTS: |
| 18387 | + if (argc < 4) { |
| 18388 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); |
| 18093 | 18389 | return JIM_ERR; |
| 18094 | 18390 | } |
| 18095 | | - Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, |
| 18096 | | - &objPtr, JIM_ERRMSG) == JIM_OK); |
| 18097 | | - return JIM_OK; |
| 18391 | + else { |
| 18392 | + int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); |
| 18393 | + if (rc < 0) { |
| 18394 | + return JIM_ERR; |
| 18395 | + } |
| 18396 | + Jim_SetResultBool(interp, rc == JIM_OK); |
| 18397 | + return JIM_OK; |
| 18398 | + } |
| 18098 | 18399 | |
| 18099 | 18400 | case OPT_UNSET: |
| 18100 | 18401 | if (argc < 4) { |
| 18101 | 18402 | Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); |
| 18102 | 18403 | return JIM_ERR; |
| 18103 | 18404 | } |
| 18104 | | - return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE); |
| 18405 | + if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 18406 | + return JIM_ERR; |
| 18407 | + } |
| 18408 | + return JIM_OK; |
| 18105 | 18409 | |
| 18106 | 18410 | case OPT_KEYS: |
| 18107 | 18411 | if (argc != 3 && argc != 4) { |
| 18108 | | - Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?"); |
| 18412 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18109 | 18413 | return JIM_ERR; |
| 18110 | 18414 | } |
| 18111 | 18415 | return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); |
| 18112 | 18416 | |
| 18113 | | - case OPT_SIZE: { |
| 18114 | | - int size; |
| 18115 | | - |
| 18417 | + case OPT_SIZE: |
| 18116 | 18418 | if (argc != 3) { |
| 18117 | | - Jim_WrongNumArgs(interp, 2, argv, "dictVar"); |
| 18419 | + Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18118 | 18420 | return JIM_ERR; |
| 18119 | 18421 | } |
| 18120 | | - |
| 18121 | | - size = Jim_DictSize(interp, argv[2]); |
| 18122 | | - if (size < 0) { |
| 18422 | + else if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18123 | 18423 | return JIM_ERR; |
| 18124 | 18424 | } |
| 18125 | | - Jim_SetResultInt(interp, size); |
| 18425 | + Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); |
| 18126 | 18426 | return JIM_OK; |
| 18127 | | - } |
| 18128 | 18427 | |
| 18129 | 18428 | case OPT_MERGE: |
| 18130 | 18429 | if (argc == 2) { |
| 18131 | 18430 | return JIM_OK; |
| 18132 | 18431 | } |
| 18133 | | - else if (SetDictFromAny(interp, argv[2]) != JIM_OK) { |
| 18134 | | - return JIM_ERR; |
| 18135 | | - } |
| 18136 | | - else { |
| 18137 | | - return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2); |
| 18138 | | - } |
| 18139 | | - |
| 18140 | | - case OPT_WITH: |
| 18141 | | - if (argc < 4) { |
| 18142 | | - Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); |
| 18143 | | - return JIM_ERR; |
| 18144 | | - } |
| 18145 | | - else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) { |
| 18146 | | - return JIM_ERR; |
| 18147 | | - } |
| 18148 | | - else { |
| 18149 | | - return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2); |
| 18150 | | - } |
| 18432 | + if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18433 | + return JIM_ERR; |
| 18434 | + } |
| 18435 | + |
| 18436 | + break; |
| 18437 | + |
| 18438 | + case OPT_UPDATE: |
| 18439 | + if (argc < 6 || argc % 2) { |
| 18440 | + |
| 18441 | + argc = 2; |
| 18442 | + } |
| 18443 | + break; |
| 18151 | 18444 | |
| 18152 | 18445 | case OPT_CREATE: |
| 18153 | 18446 | if (argc % 2) { |
| 18154 | 18447 | Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); |
| 18155 | 18448 | return JIM_ERR; |
| 18156 | 18449 | } |
| 18157 | 18450 | objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); |
| 18158 | 18451 | Jim_SetResult(interp, objPtr); |
| 18159 | 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]); |
| 18160 | 18460 | } |
| 18161 | | - return JIM_ERR; |
| 18461 | + |
| 18462 | + return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18162 | 18463 | } |
| 18163 | 18464 | |
| 18164 | 18465 | |
| 18165 | 18466 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18166 | 18467 | { |
| | @@ -18218,11 +18519,11 @@ |
| 18218 | 18519 | }; |
| 18219 | 18520 | enum |
| 18220 | 18521 | { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, |
| 18221 | 18522 | INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, |
| 18222 | 18523 | INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, |
| 18223 | | - INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS |
| 18524 | + INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, |
| 18224 | 18525 | }; |
| 18225 | 18526 | |
| 18226 | 18527 | #ifdef jim_ext_namespace |
| 18227 | 18528 | int nons = 0; |
| 18228 | 18529 | |
| | @@ -18998,11 +19299,11 @@ |
| 18998 | 19299 | } |
| 18999 | 19300 | } |
| 19000 | 19301 | |
| 19001 | 19302 | static const struct { |
| 19002 | 19303 | const char *name; |
| 19003 | | - Jim_CmdProc cmdProc; |
| 19304 | + Jim_CmdProc *cmdProc; |
| 19004 | 19305 | } Jim_CoreCommandsTable[] = { |
| 19005 | 19306 | {"alias", Jim_AliasCoreCommand}, |
| 19006 | 19307 | {"set", Jim_SetCoreCommand}, |
| 19007 | 19308 | {"unset", Jim_UnsetCoreCommand}, |
| 19008 | 19309 | {"puts", Jim_PutsCoreCommand}, |
| | @@ -19230,10 +19531,12 @@ |
| 19230 | 19531 | } |
| 19231 | 19532 | |
| 19232 | 19533 | len += extra; |
| 19233 | 19534 | buf = Jim_Alloc(len + 1); |
| 19234 | 19535 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19536 | + |
| 19537 | + va_end(args); |
| 19235 | 19538 | |
| 19236 | 19539 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19237 | 19540 | } |
| 19238 | 19541 | |
| 19239 | 19542 | |
| | @@ -19481,344 +19784,373 @@ |
| 19481 | 19784 | |
| 19482 | 19785 | #include <ctype.h> |
| 19483 | 19786 | #include <string.h> |
| 19484 | 19787 | |
| 19485 | 19788 | |
| 19486 | | -#define JIM_UTF_MAX 3 |
| 19487 | 19789 | #define JIM_INTEGER_SPACE 24 |
| 19488 | 19790 | #define MAX_FLOAT_WIDTH 320 |
| 19489 | 19791 | |
| 19490 | 19792 | Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) |
| 19491 | 19793 | { |
| 19492 | 19794 | const char *span, *format, *formatEnd, *msg; |
| 19493 | 19795 | int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; |
| 19494 | 19796 | static const char * const mixedXPG = |
| 19495 | | - "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 19797 | + "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 19496 | 19798 | static const char * const badIndex[2] = { |
| 19497 | | - "not enough arguments for all format specifiers", |
| 19498 | | - "\"%n$\" argument index out of range" |
| 19799 | + "not enough arguments for all format specifiers", |
| 19800 | + "\"%n$\" argument index out of range" |
| 19499 | 19801 | }; |
| 19500 | 19802 | int formatLen; |
| 19501 | 19803 | Jim_Obj *resultPtr; |
| 19502 | 19804 | |
| 19503 | 19805 | char *num_buffer = NULL; |
| 19504 | 19806 | int num_buffer_size = 0; |
| 19505 | 19807 | |
| 19506 | 19808 | span = format = Jim_GetString(fmtObjPtr, &formatLen); |
| 19507 | 19809 | formatEnd = format + formatLen; |
| 19508 | | - resultPtr = Jim_NewStringObj(interp, "", 0); |
| 19810 | + resultPtr = Jim_NewEmptyStringObj(interp); |
| 19509 | 19811 | |
| 19510 | 19812 | while (format != formatEnd) { |
| 19511 | | - char *end; |
| 19512 | | - int gotMinus, sawFlag; |
| 19513 | | - int gotPrecision, useShort; |
| 19514 | | - long width, precision; |
| 19515 | | - int newXpg; |
| 19516 | | - int ch; |
| 19517 | | - int step; |
| 19518 | | - int doubleType; |
| 19519 | | - char pad = ' '; |
| 19520 | | - char spec[2*JIM_INTEGER_SPACE + 12]; |
| 19521 | | - char *p; |
| 19522 | | - |
| 19523 | | - int formatted_chars; |
| 19524 | | - int formatted_bytes; |
| 19525 | | - const char *formatted_buf; |
| 19526 | | - |
| 19527 | | - step = utf8_tounicode(format, &ch); |
| 19528 | | - format += step; |
| 19529 | | - if (ch != '%') { |
| 19530 | | - numBytes += step; |
| 19531 | | - continue; |
| 19532 | | - } |
| 19533 | | - if (numBytes) { |
| 19534 | | - Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19535 | | - numBytes = 0; |
| 19536 | | - } |
| 19537 | | - |
| 19538 | | - |
| 19539 | | - step = utf8_tounicode(format, &ch); |
| 19540 | | - if (ch == '%') { |
| 19541 | | - span = format; |
| 19542 | | - numBytes = step; |
| 19543 | | - format += step; |
| 19544 | | - continue; |
| 19545 | | - } |
| 19546 | | - |
| 19547 | | - |
| 19548 | | - newXpg = 0; |
| 19549 | | - if (isdigit(ch)) { |
| 19550 | | - int position = strtoul(format, &end, 10); |
| 19551 | | - if (*end == '$') { |
| 19552 | | - newXpg = 1; |
| 19553 | | - objIndex = position - 1; |
| 19554 | | - format = end + 1; |
| 19555 | | - step = utf8_tounicode(format, &ch); |
| 19556 | | - } |
| 19557 | | - } |
| 19558 | | - if (newXpg) { |
| 19559 | | - if (gotSequential) { |
| 19560 | | - msg = mixedXPG; |
| 19561 | | - goto errorMsg; |
| 19562 | | - } |
| 19563 | | - gotXpg = 1; |
| 19564 | | - } else { |
| 19565 | | - if (gotXpg) { |
| 19566 | | - msg = mixedXPG; |
| 19567 | | - goto errorMsg; |
| 19568 | | - } |
| 19569 | | - gotSequential = 1; |
| 19570 | | - } |
| 19571 | | - if ((objIndex < 0) || (objIndex >= objc)) { |
| 19572 | | - msg = badIndex[gotXpg]; |
| 19573 | | - goto errorMsg; |
| 19574 | | - } |
| 19575 | | - |
| 19576 | | - p = spec; |
| 19577 | | - *p++ = '%'; |
| 19578 | | - |
| 19579 | | - gotMinus = 0; |
| 19580 | | - sawFlag = 1; |
| 19581 | | - do { |
| 19582 | | - switch (ch) { |
| 19583 | | - case '-': |
| 19584 | | - gotMinus = 1; |
| 19585 | | - break; |
| 19586 | | - case '0': |
| 19587 | | - pad = ch; |
| 19588 | | - break; |
| 19589 | | - case ' ': |
| 19590 | | - case '+': |
| 19591 | | - case '#': |
| 19592 | | - break; |
| 19593 | | - default: |
| 19594 | | - sawFlag = 0; |
| 19595 | | - continue; |
| 19596 | | - } |
| 19597 | | - *p++ = ch; |
| 19598 | | - format += step; |
| 19599 | | - step = utf8_tounicode(format, &ch); |
| 19600 | | - } while (sawFlag); |
| 19601 | | - |
| 19602 | | - |
| 19603 | | - width = 0; |
| 19604 | | - if (isdigit(ch)) { |
| 19605 | | - width = strtoul(format, &end, 10); |
| 19606 | | - format = end; |
| 19607 | | - step = utf8_tounicode(format, &ch); |
| 19608 | | - } else if (ch == '*') { |
| 19609 | | - if (objIndex >= objc - 1) { |
| 19610 | | - msg = badIndex[gotXpg]; |
| 19611 | | - goto errorMsg; |
| 19612 | | - } |
| 19613 | | - if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { |
| 19614 | | - goto error; |
| 19615 | | - } |
| 19616 | | - if (width < 0) { |
| 19617 | | - width = -width; |
| 19618 | | - if (!gotMinus) { |
| 19619 | | - *p++ = '-'; |
| 19620 | | - gotMinus = 1; |
| 19621 | | - } |
| 19622 | | - } |
| 19623 | | - objIndex++; |
| 19624 | | - format += step; |
| 19625 | | - step = utf8_tounicode(format, &ch); |
| 19626 | | - } |
| 19627 | | - |
| 19628 | | - |
| 19629 | | - gotPrecision = precision = 0; |
| 19630 | | - if (ch == '.') { |
| 19631 | | - gotPrecision = 1; |
| 19632 | | - format += step; |
| 19633 | | - step = utf8_tounicode(format, &ch); |
| 19634 | | - } |
| 19635 | | - if (isdigit(ch)) { |
| 19636 | | - precision = strtoul(format, &end, 10); |
| 19637 | | - format = end; |
| 19638 | | - step = utf8_tounicode(format, &ch); |
| 19639 | | - } else if (ch == '*') { |
| 19640 | | - if (objIndex >= objc - 1) { |
| 19641 | | - msg = badIndex[gotXpg]; |
| 19642 | | - goto errorMsg; |
| 19643 | | - } |
| 19644 | | - if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { |
| 19645 | | - goto error; |
| 19646 | | - } |
| 19647 | | - |
| 19648 | | - |
| 19649 | | - if (precision < 0) { |
| 19650 | | - precision = 0; |
| 19651 | | - } |
| 19652 | | - objIndex++; |
| 19653 | | - format += step; |
| 19654 | | - step = utf8_tounicode(format, &ch); |
| 19655 | | - } |
| 19656 | | - |
| 19657 | | - |
| 19658 | | - useShort = 0; |
| 19659 | | - if (ch == 'h') { |
| 19660 | | - useShort = 1; |
| 19661 | | - format += step; |
| 19662 | | - step = utf8_tounicode(format, &ch); |
| 19663 | | - } else if (ch == 'l') { |
| 19664 | | - |
| 19665 | | - format += step; |
| 19666 | | - step = utf8_tounicode(format, &ch); |
| 19667 | | - if (ch == 'l') { |
| 19668 | | - format += step; |
| 19669 | | - step = utf8_tounicode(format, &ch); |
| 19670 | | - } |
| 19671 | | - } |
| 19672 | | - |
| 19673 | | - format += step; |
| 19674 | | - span = format; |
| 19675 | | - |
| 19676 | | - |
| 19677 | | - if (ch == 'i') { |
| 19678 | | - ch = 'd'; |
| 19679 | | - } |
| 19680 | | - |
| 19681 | | - doubleType = 0; |
| 19682 | | - |
| 19683 | | - switch (ch) { |
| 19684 | | - case '\0': |
| 19685 | | - msg = "format string ended in middle of field specifier"; |
| 19686 | | - goto errorMsg; |
| 19687 | | - case 's': { |
| 19688 | | - formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 19689 | | - formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 19690 | | - if (gotPrecision && (precision < formatted_chars)) { |
| 19691 | | - |
| 19692 | | - formatted_chars = precision; |
| 19693 | | - formatted_bytes = utf8_index(formatted_buf, precision); |
| 19694 | | - } |
| 19695 | | - break; |
| 19696 | | - } |
| 19697 | | - case 'c': { |
| 19698 | | - jim_wide code; |
| 19699 | | - |
| 19700 | | - if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 19701 | | - goto error; |
| 19702 | | - } |
| 19703 | | - |
| 19704 | | - formatted_bytes = utf8_fromunicode(spec, code); |
| 19705 | | - formatted_buf = spec; |
| 19706 | | - formatted_chars = 1; |
| 19707 | | - break; |
| 19708 | | - } |
| 19709 | | - |
| 19710 | | - case 'e': |
| 19711 | | - case 'E': |
| 19712 | | - case 'f': |
| 19713 | | - case 'g': |
| 19714 | | - case 'G': |
| 19715 | | - doubleType = 1; |
| 19716 | | - |
| 19717 | | - case 'd': |
| 19718 | | - case 'u': |
| 19719 | | - case 'o': |
| 19720 | | - case 'x': |
| 19721 | | - case 'X': { |
| 19722 | | - jim_wide w; |
| 19723 | | - double d; |
| 19724 | | - int length; |
| 19725 | | - |
| 19726 | | - |
| 19727 | | - if (width) { |
| 19728 | | - p += sprintf(p, "%ld", width); |
| 19729 | | - } |
| 19730 | | - if (gotPrecision) { |
| 19731 | | - p += sprintf(p, ".%ld", precision); |
| 19732 | | - } |
| 19733 | | - |
| 19734 | | - |
| 19735 | | - if (doubleType) { |
| 19736 | | - if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 19737 | | - goto error; |
| 19738 | | - } |
| 19739 | | - length = MAX_FLOAT_WIDTH; |
| 19740 | | - } |
| 19741 | | - else { |
| 19742 | | - if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { |
| 19743 | | - goto error; |
| 19744 | | - } |
| 19745 | | - length = JIM_INTEGER_SPACE; |
| 19746 | | - if (useShort) { |
| 19747 | | - *p++ = 'h'; |
| 19748 | | - if (ch == 'd') { |
| 19749 | | - w = (short)w; |
| 19750 | | - } |
| 19751 | | - else { |
| 19752 | | - w = (unsigned short)w; |
| 19753 | | - } |
| 19754 | | - } |
| 19755 | | - else { |
| 19756 | | - *p++ = 'l'; |
| 19757 | | -#ifdef HAVE_LONG_LONG |
| 19758 | | - if (sizeof(long long) == sizeof(jim_wide)) { |
| 19759 | | - *p++ = 'l'; |
| 19760 | | - } |
| 19761 | | -#endif |
| 19762 | | - } |
| 19763 | | - } |
| 19764 | | - |
| 19765 | | - *p++ = (char) ch; |
| 19766 | | - *p = '\0'; |
| 19767 | | - |
| 19768 | | - |
| 19769 | | - if (width > length) { |
| 19770 | | - length = width; |
| 19771 | | - } |
| 19772 | | - if (gotPrecision) { |
| 19773 | | - length += precision; |
| 19774 | | - } |
| 19775 | | - |
| 19776 | | - |
| 19777 | | - if (num_buffer_size < length + 1) { |
| 19778 | | - num_buffer_size = length + 1; |
| 19779 | | - num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 19780 | | - } |
| 19781 | | - |
| 19782 | | - if (doubleType) { |
| 19783 | | - snprintf(num_buffer, length + 1, spec, d); |
| 19784 | | - } |
| 19785 | | - else { |
| 19786 | | - formatted_bytes = snprintf(num_buffer, length + 1, spec, w); |
| 19787 | | - } |
| 19788 | | - formatted_chars = formatted_bytes = strlen(num_buffer); |
| 19789 | | - formatted_buf = num_buffer; |
| 19790 | | - break; |
| 19791 | | - } |
| 19792 | | - |
| 19793 | | - default: { |
| 19794 | | - |
| 19795 | | - spec[0] = ch; |
| 19796 | | - spec[1] = '\0'; |
| 19797 | | - Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 19798 | | - goto error; |
| 19799 | | - } |
| 19800 | | - } |
| 19801 | | - |
| 19802 | | - if (!gotMinus) { |
| 19803 | | - while (formatted_chars < width) { |
| 19804 | | - Jim_AppendString(interp, resultPtr, &pad, 1); |
| 19805 | | - formatted_chars++; |
| 19806 | | - } |
| 19807 | | - } |
| 19808 | | - |
| 19809 | | - Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); |
| 19810 | | - |
| 19811 | | - while (formatted_chars < width) { |
| 19812 | | - Jim_AppendString(interp, resultPtr, &pad, 1); |
| 19813 | | - formatted_chars++; |
| 19814 | | - } |
| 19815 | | - |
| 19816 | | - objIndex += gotSequential; |
| 19817 | | - } |
| 19818 | | - if (numBytes) { |
| 19819 | | - Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19813 | + char *end; |
| 19814 | + int gotMinus, sawFlag; |
| 19815 | + int gotPrecision, useShort; |
| 19816 | + long width, precision; |
| 19817 | + int newXpg; |
| 19818 | + int ch; |
| 19819 | + int step; |
| 19820 | + int doubleType; |
| 19821 | + char pad = ' '; |
| 19822 | + char spec[2*JIM_INTEGER_SPACE + 12]; |
| 19823 | + char *p; |
| 19824 | + |
| 19825 | + int formatted_chars; |
| 19826 | + int formatted_bytes; |
| 19827 | + const char *formatted_buf; |
| 19828 | + |
| 19829 | + step = utf8_tounicode(format, &ch); |
| 19830 | + format += step; |
| 19831 | + if (ch != '%') { |
| 19832 | + numBytes += step; |
| 19833 | + continue; |
| 19834 | + } |
| 19835 | + if (numBytes) { |
| 19836 | + Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19837 | + numBytes = 0; |
| 19838 | + } |
| 19839 | + |
| 19840 | + |
| 19841 | + step = utf8_tounicode(format, &ch); |
| 19842 | + if (ch == '%') { |
| 19843 | + span = format; |
| 19844 | + numBytes = step; |
| 19845 | + format += step; |
| 19846 | + continue; |
| 19847 | + } |
| 19848 | + |
| 19849 | + |
| 19850 | + newXpg = 0; |
| 19851 | + if (isdigit(ch)) { |
| 19852 | + int position = strtoul(format, &end, 10); |
| 19853 | + if (*end == '$') { |
| 19854 | + newXpg = 1; |
| 19855 | + objIndex = position - 1; |
| 19856 | + format = end + 1; |
| 19857 | + step = utf8_tounicode(format, &ch); |
| 19858 | + } |
| 19859 | + } |
| 19860 | + if (newXpg) { |
| 19861 | + if (gotSequential) { |
| 19862 | + msg = mixedXPG; |
| 19863 | + goto errorMsg; |
| 19864 | + } |
| 19865 | + gotXpg = 1; |
| 19866 | + } else { |
| 19867 | + if (gotXpg) { |
| 19868 | + msg = mixedXPG; |
| 19869 | + goto errorMsg; |
| 19870 | + } |
| 19871 | + gotSequential = 1; |
| 19872 | + } |
| 19873 | + if ((objIndex < 0) || (objIndex >= objc)) { |
| 19874 | + msg = badIndex[gotXpg]; |
| 19875 | + goto errorMsg; |
| 19876 | + } |
| 19877 | + |
| 19878 | + p = spec; |
| 19879 | + *p++ = '%'; |
| 19880 | + |
| 19881 | + gotMinus = 0; |
| 19882 | + sawFlag = 1; |
| 19883 | + do { |
| 19884 | + switch (ch) { |
| 19885 | + case '-': |
| 19886 | + gotMinus = 1; |
| 19887 | + break; |
| 19888 | + case '0': |
| 19889 | + pad = ch; |
| 19890 | + break; |
| 19891 | + case ' ': |
| 19892 | + case '+': |
| 19893 | + case '#': |
| 19894 | + break; |
| 19895 | + default: |
| 19896 | + sawFlag = 0; |
| 19897 | + continue; |
| 19898 | + } |
| 19899 | + *p++ = ch; |
| 19900 | + format += step; |
| 19901 | + step = utf8_tounicode(format, &ch); |
| 19902 | + } while (sawFlag); |
| 19903 | + |
| 19904 | + |
| 19905 | + width = 0; |
| 19906 | + if (isdigit(ch)) { |
| 19907 | + width = strtoul(format, &end, 10); |
| 19908 | + format = end; |
| 19909 | + step = utf8_tounicode(format, &ch); |
| 19910 | + } else if (ch == '*') { |
| 19911 | + if (objIndex >= objc - 1) { |
| 19912 | + msg = badIndex[gotXpg]; |
| 19913 | + goto errorMsg; |
| 19914 | + } |
| 19915 | + if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { |
| 19916 | + goto error; |
| 19917 | + } |
| 19918 | + if (width < 0) { |
| 19919 | + width = -width; |
| 19920 | + if (!gotMinus) { |
| 19921 | + *p++ = '-'; |
| 19922 | + gotMinus = 1; |
| 19923 | + } |
| 19924 | + } |
| 19925 | + objIndex++; |
| 19926 | + format += step; |
| 19927 | + step = utf8_tounicode(format, &ch); |
| 19928 | + } |
| 19929 | + |
| 19930 | + |
| 19931 | + gotPrecision = precision = 0; |
| 19932 | + if (ch == '.') { |
| 19933 | + gotPrecision = 1; |
| 19934 | + format += step; |
| 19935 | + step = utf8_tounicode(format, &ch); |
| 19936 | + } |
| 19937 | + if (isdigit(ch)) { |
| 19938 | + precision = strtoul(format, &end, 10); |
| 19939 | + format = end; |
| 19940 | + step = utf8_tounicode(format, &ch); |
| 19941 | + } else if (ch == '*') { |
| 19942 | + if (objIndex >= objc - 1) { |
| 19943 | + msg = badIndex[gotXpg]; |
| 19944 | + goto errorMsg; |
| 19945 | + } |
| 19946 | + if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { |
| 19947 | + goto error; |
| 19948 | + } |
| 19949 | + |
| 19950 | + |
| 19951 | + if (precision < 0) { |
| 19952 | + precision = 0; |
| 19953 | + } |
| 19954 | + objIndex++; |
| 19955 | + format += step; |
| 19956 | + step = utf8_tounicode(format, &ch); |
| 19957 | + } |
| 19958 | + |
| 19959 | + |
| 19960 | + useShort = 0; |
| 19961 | + if (ch == 'h') { |
| 19962 | + useShort = 1; |
| 19963 | + format += step; |
| 19964 | + step = utf8_tounicode(format, &ch); |
| 19965 | + } else if (ch == 'l') { |
| 19966 | + |
| 19967 | + format += step; |
| 19968 | + step = utf8_tounicode(format, &ch); |
| 19969 | + if (ch == 'l') { |
| 19970 | + format += step; |
| 19971 | + step = utf8_tounicode(format, &ch); |
| 19972 | + } |
| 19973 | + } |
| 19974 | + |
| 19975 | + format += step; |
| 19976 | + span = format; |
| 19977 | + |
| 19978 | + |
| 19979 | + if (ch == 'i') { |
| 19980 | + ch = 'd'; |
| 19981 | + } |
| 19982 | + |
| 19983 | + doubleType = 0; |
| 19984 | + |
| 19985 | + switch (ch) { |
| 19986 | + case '\0': |
| 19987 | + msg = "format string ended in middle of field specifier"; |
| 19988 | + goto errorMsg; |
| 19989 | + case 's': { |
| 19990 | + formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 19991 | + formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 19992 | + if (gotPrecision && (precision < formatted_chars)) { |
| 19993 | + |
| 19994 | + formatted_chars = precision; |
| 19995 | + formatted_bytes = utf8_index(formatted_buf, precision); |
| 19996 | + } |
| 19997 | + break; |
| 19998 | + } |
| 19999 | + case 'c': { |
| 20000 | + jim_wide code; |
| 20001 | + |
| 20002 | + if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 20003 | + goto error; |
| 20004 | + } |
| 20005 | + |
| 20006 | + formatted_bytes = utf8_getchars(spec, code); |
| 20007 | + formatted_buf = spec; |
| 20008 | + formatted_chars = 1; |
| 20009 | + break; |
| 20010 | + } |
| 20011 | + case 'b': { |
| 20012 | + unsigned jim_wide w; |
| 20013 | + int length; |
| 20014 | + int i; |
| 20015 | + int j; |
| 20016 | + |
| 20017 | + if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) { |
| 20018 | + goto error; |
| 20019 | + } |
| 20020 | + length = sizeof(w) * 8; |
| 20021 | + |
| 20022 | + |
| 20023 | + |
| 20024 | + if (num_buffer_size < length + 1) { |
| 20025 | + num_buffer_size = length + 1; |
| 20026 | + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20027 | + } |
| 20028 | + |
| 20029 | + j = 0; |
| 20030 | + for (i = length; i > 0; ) { |
| 20031 | + i--; |
| 20032 | + if (w & ((unsigned jim_wide)1 << i)) { |
| 20033 | + num_buffer[j++] = '1'; |
| 20034 | + } |
| 20035 | + else if (j || i == 0) { |
| 20036 | + num_buffer[j++] = '0'; |
| 20037 | + } |
| 20038 | + } |
| 20039 | + num_buffer[j] = 0; |
| 20040 | + formatted_chars = formatted_bytes = j; |
| 20041 | + formatted_buf = num_buffer; |
| 20042 | + break; |
| 20043 | + } |
| 20044 | + |
| 20045 | + case 'e': |
| 20046 | + case 'E': |
| 20047 | + case 'f': |
| 20048 | + case 'g': |
| 20049 | + case 'G': |
| 20050 | + doubleType = 1; |
| 20051 | + |
| 20052 | + case 'd': |
| 20053 | + case 'u': |
| 20054 | + case 'o': |
| 20055 | + case 'x': |
| 20056 | + case 'X': { |
| 20057 | + jim_wide w; |
| 20058 | + double d; |
| 20059 | + int length; |
| 20060 | + |
| 20061 | + |
| 20062 | + if (width) { |
| 20063 | + p += sprintf(p, "%ld", width); |
| 20064 | + } |
| 20065 | + if (gotPrecision) { |
| 20066 | + p += sprintf(p, ".%ld", precision); |
| 20067 | + } |
| 20068 | + |
| 20069 | + |
| 20070 | + if (doubleType) { |
| 20071 | + if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 20072 | + goto error; |
| 20073 | + } |
| 20074 | + length = MAX_FLOAT_WIDTH; |
| 20075 | + } |
| 20076 | + else { |
| 20077 | + if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { |
| 20078 | + goto error; |
| 20079 | + } |
| 20080 | + length = JIM_INTEGER_SPACE; |
| 20081 | + if (useShort) { |
| 20082 | + if (ch == 'd') { |
| 20083 | + w = (short)w; |
| 20084 | + } |
| 20085 | + else { |
| 20086 | + w = (unsigned short)w; |
| 20087 | + } |
| 20088 | + } |
| 20089 | + *p++ = 'l'; |
| 20090 | +#ifdef HAVE_LONG_LONG |
| 20091 | + if (sizeof(long long) == sizeof(jim_wide)) { |
| 20092 | + *p++ = 'l'; |
| 20093 | + } |
| 20094 | +#endif |
| 20095 | + } |
| 20096 | + |
| 20097 | + *p++ = (char) ch; |
| 20098 | + *p = '\0'; |
| 20099 | + |
| 20100 | + |
| 20101 | + if (width > length) { |
| 20102 | + length = width; |
| 20103 | + } |
| 20104 | + if (gotPrecision) { |
| 20105 | + length += precision; |
| 20106 | + } |
| 20107 | + |
| 20108 | + |
| 20109 | + if (num_buffer_size < length + 1) { |
| 20110 | + num_buffer_size = length + 1; |
| 20111 | + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20112 | + } |
| 20113 | + |
| 20114 | + if (doubleType) { |
| 20115 | + snprintf(num_buffer, length + 1, spec, d); |
| 20116 | + } |
| 20117 | + else { |
| 20118 | + formatted_bytes = snprintf(num_buffer, length + 1, spec, w); |
| 20119 | + } |
| 20120 | + formatted_chars = formatted_bytes = strlen(num_buffer); |
| 20121 | + formatted_buf = num_buffer; |
| 20122 | + break; |
| 20123 | + } |
| 20124 | + |
| 20125 | + default: { |
| 20126 | + |
| 20127 | + spec[0] = ch; |
| 20128 | + spec[1] = '\0'; |
| 20129 | + Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 20130 | + goto error; |
| 20131 | + } |
| 20132 | + } |
| 20133 | + |
| 20134 | + if (!gotMinus) { |
| 20135 | + while (formatted_chars < width) { |
| 20136 | + Jim_AppendString(interp, resultPtr, &pad, 1); |
| 20137 | + formatted_chars++; |
| 20138 | + } |
| 20139 | + } |
| 20140 | + |
| 20141 | + Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); |
| 20142 | + |
| 20143 | + while (formatted_chars < width) { |
| 20144 | + Jim_AppendString(interp, resultPtr, &pad, 1); |
| 20145 | + formatted_chars++; |
| 20146 | + } |
| 20147 | + |
| 20148 | + objIndex += gotSequential; |
| 20149 | + } |
| 20150 | + if (numBytes) { |
| 20151 | + Jim_AppendString(interp, resultPtr, span, numBytes); |
| 19820 | 20152 | } |
| 19821 | 20153 | |
| 19822 | 20154 | Jim_Free(num_buffer); |
| 19823 | 20155 | return resultPtr; |
| 19824 | 20156 | |
| | @@ -19827,21 +20159,22 @@ |
| 19827 | 20159 | error: |
| 19828 | 20160 | Jim_FreeNewObj(interp, resultPtr); |
| 19829 | 20161 | Jim_Free(num_buffer); |
| 19830 | 20162 | return NULL; |
| 19831 | 20163 | } |
| 20164 | + |
| 20165 | + |
| 20166 | +#if defined(JIM_REGEXP) |
| 19832 | 20167 | #include <stdio.h> |
| 19833 | 20168 | #include <ctype.h> |
| 19834 | 20169 | #include <stdlib.h> |
| 19835 | 20170 | #include <string.h> |
| 19836 | 20171 | |
| 19837 | | - |
| 19838 | | -#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP) |
| 19839 | | - |
| 19840 | 20172 | |
| 19841 | 20173 | |
| 19842 | 20174 | #define REG_MAX_PAREN 100 |
| 20175 | + |
| 19843 | 20176 | |
| 19844 | 20177 | |
| 19845 | 20178 | #define END 0 |
| 19846 | 20179 | #define BOL 1 |
| 19847 | 20180 | #define EOL 2 |
| | @@ -19850,23 +20183,27 @@ |
| 19850 | 20183 | #define ANYBUT 5 |
| 19851 | 20184 | #define BRANCH 6 |
| 19852 | 20185 | #define BACK 7 |
| 19853 | 20186 | #define EXACTLY 8 |
| 19854 | 20187 | #define NOTHING 9 |
| 19855 | | -#define REP 10 |
| 20188 | +#define REP 10 |
| 19856 | 20189 | #define REPMIN 11 |
| 19857 | 20190 | #define REPX 12 |
| 19858 | 20191 | #define REPXMIN 13 |
| 19859 | 20192 | |
| 19860 | 20193 | #define WORDA 15 |
| 19861 | 20194 | #define WORDZ 16 |
| 19862 | | -#define OPENNC 19 |
| 19863 | | -#define OPEN 20 |
| 20195 | + |
| 20196 | +#define OPENNC 1000 |
| 20197 | +#define OPEN 1001 |
| 19864 | 20198 | |
| 19865 | | -#define CLOSE (OPEN+REG_MAX_PAREN+1) |
| 20199 | + |
| 20200 | + |
| 20201 | + |
| 20202 | +#define CLOSENC 2000 |
| 20203 | +#define CLOSE 2001 |
| 19866 | 20204 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 19867 | | -#define CLOSENC (CLOSE-1) |
| 19868 | 20205 | |
| 19869 | 20206 | #define REG_MAGIC 0xFADED00D |
| 19870 | 20207 | |
| 19871 | 20208 | |
| 19872 | 20209 | #define OP(preg, p) (preg->program[p]) |
| | @@ -19876,15 +20213,15 @@ |
| 19876 | 20213 | |
| 19877 | 20214 | |
| 19878 | 20215 | |
| 19879 | 20216 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 19880 | 20217 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 19881 | | -#define META "^$.[()|?{+*" |
| 20218 | +#define META "^$.[()|?{+*" |
| 19882 | 20219 | |
| 19883 | | -#define HASWIDTH 01 |
| 19884 | | -#define SIMPLE 02 |
| 19885 | | -#define SPSTART 04 |
| 20220 | +#define HASWIDTH 1 |
| 20221 | +#define SIMPLE 2 |
| 20222 | +#define SPSTART 4 |
| 19886 | 20223 | #define WORST 0 |
| 19887 | 20224 | |
| 19888 | 20225 | #define MAX_REP_COUNT 1000000 |
| 19889 | 20226 | |
| 19890 | 20227 | static int reg(regex_t *preg, int paren , int *flagp ); |
| | @@ -19893,13 +20230,13 @@ |
| 19893 | 20230 | static int regatom(regex_t *preg, int *flagp ); |
| 19894 | 20231 | static int regnode(regex_t *preg, int op ); |
| 19895 | 20232 | static int regnext(regex_t *preg, int p ); |
| 19896 | 20233 | static void regc(regex_t *preg, int b ); |
| 19897 | 20234 | static int reginsert(regex_t *preg, int op, int size, int opnd ); |
| 19898 | | -static void regtail_(regex_t *preg, int p, int val, int line ); |
| 20235 | +static void regtail(regex_t *preg, int p, int val); |
| 19899 | 20236 | static void regoptail(regex_t *preg, int p, int val ); |
| 19900 | | -#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__) |
| 20237 | +static int regopsize(regex_t *preg, int p ); |
| 19901 | 20238 | |
| 19902 | 20239 | static int reg_range_find(const int *string, int c); |
| 19903 | 20240 | static const char *str_find(const char *string, int c, int nocase); |
| 19904 | 20241 | static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); |
| 19905 | 20242 | |
| | @@ -19936,13 +20273,10 @@ |
| 19936 | 20273 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 19937 | 20274 | |
| 19938 | 20275 | |
| 19939 | 20276 | preg->cflags = cflags; |
| 19940 | 20277 | preg->regparse = exp; |
| 19941 | | - |
| 19942 | | - preg->program = NULL; |
| 19943 | | - preg->proglen = 0; |
| 19944 | 20278 | |
| 19945 | 20279 | |
| 19946 | 20280 | preg->proglen = (strlen(exp) + 1) * 5; |
| 19947 | 20281 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 19948 | 20282 | if (preg->program == NULL) |
| | @@ -20103,11 +20437,10 @@ |
| 20103 | 20437 | { |
| 20104 | 20438 | int ret; |
| 20105 | 20439 | char op; |
| 20106 | 20440 | int next; |
| 20107 | 20441 | int flags; |
| 20108 | | - int chain = 0; |
| 20109 | 20442 | int min; |
| 20110 | 20443 | int max; |
| 20111 | 20444 | |
| 20112 | 20445 | ret = regatom(preg, &flags); |
| 20113 | 20446 | if (ret == 0) |
| | @@ -20186,11 +20519,11 @@ |
| 20186 | 20519 | if (ISMULT(*preg->regparse)) { |
| 20187 | 20520 | preg->err = REG_ERR_NESTED_COUNT; |
| 20188 | 20521 | return 0; |
| 20189 | 20522 | } |
| 20190 | 20523 | |
| 20191 | | - return chain ? chain : ret; |
| 20524 | + return ret; |
| 20192 | 20525 | } |
| 20193 | 20526 | |
| 20194 | 20527 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20195 | 20528 | { |
| 20196 | 20529 | if (lower > upper) { |
| | @@ -20280,10 +20613,11 @@ |
| 20280 | 20613 | break; |
| 20281 | 20614 | case 'U': |
| 20282 | 20615 | if ((n = parse_hex(s, 8, ch)) > 0) { |
| 20283 | 20616 | s += n; |
| 20284 | 20617 | } |
| 20618 | + break; |
| 20285 | 20619 | case 'x': |
| 20286 | 20620 | if ((n = parse_hex(s, 2, ch)) > 0) { |
| 20287 | 20621 | s += n; |
| 20288 | 20622 | } |
| 20289 | 20623 | break; |
| | @@ -20528,10 +20862,11 @@ |
| 20528 | 20862 | |
| 20529 | 20863 | static int regnode(regex_t *preg, int op) |
| 20530 | 20864 | { |
| 20531 | 20865 | reg_grow(preg, 2); |
| 20532 | 20866 | |
| 20867 | + |
| 20533 | 20868 | preg->program[preg->p++] = op; |
| 20534 | 20869 | preg->program[preg->p++] = 0; |
| 20535 | 20870 | |
| 20536 | 20871 | |
| 20537 | 20872 | return preg->p - 2; |
| | @@ -20557,11 +20892,11 @@ |
| 20557 | 20892 | preg->p += size; |
| 20558 | 20893 | |
| 20559 | 20894 | return opnd + size; |
| 20560 | 20895 | } |
| 20561 | 20896 | |
| 20562 | | -static void regtail_(regex_t *preg, int p, int val, int line ) |
| 20897 | +static void regtail(regex_t *preg, int p, int val) |
| 20563 | 20898 | { |
| 20564 | 20899 | int scan; |
| 20565 | 20900 | int temp; |
| 20566 | 20901 | int offset; |
| 20567 | 20902 | |
| | @@ -20620,36 +20955,16 @@ |
| 20620 | 20955 | preg->pmatch = pmatch; |
| 20621 | 20956 | preg->nmatch = nmatch; |
| 20622 | 20957 | preg->start = string; |
| 20623 | 20958 | |
| 20624 | 20959 | |
| 20625 | | - for (scan = OPERAND(1); scan != 0; ) { |
| 20626 | | - switch (OP(preg, scan)) { |
| 20627 | | - case REP: |
| 20628 | | - case REPMIN: |
| 20629 | | - case REPX: |
| 20630 | | - case REPXMIN: |
| 20631 | | - preg->program[scan + 4] = 0; |
| 20632 | | - scan += 5; |
| 20633 | | - break; |
| 20634 | | - |
| 20635 | | - case ANYOF: |
| 20636 | | - case ANYBUT: |
| 20637 | | - case EXACTLY: |
| 20638 | | - scan += 2; |
| 20639 | | - while (preg->program[scan++]) { |
| 20640 | | - } |
| 20641 | | - break; |
| 20642 | | - |
| 20643 | | - case END: |
| 20644 | | - scan = 0; |
| 20645 | | - break; |
| 20646 | | - |
| 20647 | | - default: |
| 20648 | | - scan += 2; |
| 20649 | | - break; |
| 20650 | | - } |
| 20960 | + for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { |
| 20961 | + int op = OP(preg, scan); |
| 20962 | + if (op == END) |
| 20963 | + break; |
| 20964 | + if (op == REPX || op == REPXMIN) |
| 20965 | + preg->program[scan + 4] = 0; |
| 20651 | 20966 | } |
| 20652 | 20967 | |
| 20653 | 20968 | |
| 20654 | 20969 | if (preg->regmust != 0) { |
| 20655 | 20970 | s = string; |
| | @@ -20901,10 +21216,11 @@ |
| 20901 | 21216 | |
| 20902 | 21217 | static int regmatch(regex_t *preg, int prog) |
| 20903 | 21218 | { |
| 20904 | 21219 | int scan; |
| 20905 | 21220 | int next; |
| 21221 | + const char *save; |
| 20906 | 21222 | |
| 20907 | 21223 | scan = prog; |
| 20908 | 21224 | |
| 20909 | 21225 | #ifdef DEBUG |
| 20910 | 21226 | if (scan != 0 && regnarrate) |
| | @@ -20989,27 +21305,24 @@ |
| 20989 | 21305 | break; |
| 20990 | 21306 | case NOTHING: |
| 20991 | 21307 | break; |
| 20992 | 21308 | case BACK: |
| 20993 | 21309 | break; |
| 20994 | | - case BRANCH: { |
| 20995 | | - const char *save; |
| 20996 | | - |
| 20997 | | - if (OP(preg, next) != BRANCH) |
| 20998 | | - next = OPERAND(scan); |
| 20999 | | - else { |
| 21000 | | - do { |
| 21001 | | - save = preg->reginput; |
| 21002 | | - if (regmatch(preg, OPERAND(scan))) { |
| 21003 | | - return(1); |
| 21004 | | - } |
| 21005 | | - preg->reginput = save; |
| 21006 | | - scan = regnext(preg, scan); |
| 21007 | | - } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21008 | | - return(0); |
| 21009 | | - |
| 21010 | | - } |
| 21310 | + case BRANCH: |
| 21311 | + if (OP(preg, next) != BRANCH) |
| 21312 | + next = OPERAND(scan); |
| 21313 | + else { |
| 21314 | + do { |
| 21315 | + save = preg->reginput; |
| 21316 | + if (regmatch(preg, OPERAND(scan))) { |
| 21317 | + return(1); |
| 21318 | + } |
| 21319 | + preg->reginput = save; |
| 21320 | + scan = regnext(preg, scan); |
| 21321 | + } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21322 | + return(0); |
| 21323 | + |
| 21011 | 21324 | } |
| 21012 | 21325 | break; |
| 21013 | 21326 | case REP: |
| 21014 | 21327 | case REPMIN: |
| 21015 | 21328 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| | @@ -21017,43 +21330,35 @@ |
| 21017 | 21330 | case REPX: |
| 21018 | 21331 | case REPXMIN: |
| 21019 | 21332 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21020 | 21333 | |
| 21021 | 21334 | case END: |
| 21022 | | - return(1); |
| 21023 | | - break; |
| 21335 | + return 1; |
| 21024 | 21336 | |
| 21025 | 21337 | case OPENNC: |
| 21026 | 21338 | case CLOSENC: |
| 21027 | | - if (regmatch(preg, next)) { |
| 21028 | | - return 1; |
| 21029 | | - } |
| 21030 | | - return 0; |
| 21339 | + return regmatch(preg, next); |
| 21031 | 21340 | |
| 21032 | 21341 | default: |
| 21033 | 21342 | if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { |
| 21034 | | - const char *save; |
| 21035 | | - |
| 21036 | 21343 | save = preg->reginput; |
| 21037 | | - |
| 21038 | 21344 | if (regmatch(preg, next)) { |
| 21039 | | - int no; |
| 21040 | 21345 | if (OP(preg, scan) < CLOSE) { |
| 21041 | | - no = OP(preg, scan) - OPEN; |
| 21346 | + int no = OP(preg, scan) - OPEN; |
| 21042 | 21347 | if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { |
| 21043 | 21348 | preg->pmatch[no].rm_so = save - preg->start; |
| 21044 | 21349 | } |
| 21045 | 21350 | } |
| 21046 | 21351 | else { |
| 21047 | | - no = OP(preg, scan) - CLOSE; |
| 21352 | + int no = OP(preg, scan) - CLOSE; |
| 21048 | 21353 | if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { |
| 21049 | 21354 | preg->pmatch[no].rm_eo = save - preg->start; |
| 21050 | 21355 | } |
| 21051 | 21356 | } |
| 21052 | 21357 | return(1); |
| 21053 | | - } else |
| 21054 | | - return(0); |
| 21358 | + } |
| 21359 | + return(0); |
| 21055 | 21360 | } |
| 21056 | 21361 | return REG_ERR_INTERNAL; |
| 21057 | 21362 | } |
| 21058 | 21363 | |
| 21059 | 21364 | scan = next; |
| | @@ -21132,10 +21437,32 @@ |
| 21132 | 21437 | if (OP(preg, p) == BACK) |
| 21133 | 21438 | return(p-offset); |
| 21134 | 21439 | else |
| 21135 | 21440 | return(p+offset); |
| 21136 | 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 | +} |
| 21137 | 21464 | |
| 21138 | 21465 | |
| 21139 | 21466 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 21140 | 21467 | { |
| 21141 | 21468 | static const char *error_strings[] = { |
| | @@ -21310,19 +21637,24 @@ |
| 21310 | 21637 | char *Jim_HistoryGetline(const char *prompt) |
| 21311 | 21638 | { |
| 21312 | 21639 | #ifdef USE_LINENOISE |
| 21313 | 21640 | return linenoise(prompt); |
| 21314 | 21641 | #else |
| 21642 | + int len; |
| 21315 | 21643 | char *line = malloc(MAX_LINE_LEN); |
| 21316 | 21644 | |
| 21317 | 21645 | fputs(prompt, stdout); |
| 21318 | 21646 | fflush(stdout); |
| 21319 | 21647 | |
| 21320 | 21648 | if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { |
| 21321 | 21649 | free(line); |
| 21322 | 21650 | return NULL; |
| 21323 | 21651 | } |
| 21652 | + len = strlen(line); |
| 21653 | + if (len && line[len - 1] == '\n') { |
| 21654 | + line[len - 1] = '\0'; |
| 21655 | + } |
| 21324 | 21656 | return line; |
| 21325 | 21657 | #endif |
| 21326 | 21658 | } |
| 21327 | 21659 | |
| 21328 | 21660 | void Jim_HistoryLoad(const char *filename) |
| | @@ -21373,11 +21705,11 @@ |
| 21373 | 21705 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 21374 | 21706 | Jim_HistoryLoad(history_file); |
| 21375 | 21707 | } |
| 21376 | 21708 | #endif |
| 21377 | 21709 | |
| 21378 | | - printf("Welcome to Jim version %d.%d" JIM_NL, |
| 21710 | + printf("Welcome to Jim version %d.%d\n", |
| 21379 | 21711 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 21380 | 21712 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| 21381 | 21713 | |
| 21382 | 21714 | while (1) { |
| 21383 | 21715 | Jim_Obj *scriptObjPtr; |
| | @@ -21485,10 +21817,16 @@ |
| 21485 | 21817 | } |
| 21486 | 21818 | |
| 21487 | 21819 | Jim_SetVariableStr(interp, "argv", listObj); |
| 21488 | 21820 | Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); |
| 21489 | 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 | +} |
| 21490 | 21828 | |
| 21491 | 21829 | int main(int argc, char *const argv[]) |
| 21492 | 21830 | { |
| 21493 | 21831 | int retcode; |
| 21494 | 21832 | Jim_Interp *interp; |
| | @@ -21502,22 +21840,20 @@ |
| 21502 | 21840 | interp = Jim_CreateInterp(); |
| 21503 | 21841 | Jim_RegisterCoreCommands(interp); |
| 21504 | 21842 | |
| 21505 | 21843 | |
| 21506 | 21844 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 21507 | | - Jim_MakeErrorMessage(interp); |
| 21508 | | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21845 | + JimPrintErrorMessage(interp); |
| 21509 | 21846 | } |
| 21510 | 21847 | |
| 21511 | 21848 | Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); |
| 21512 | 21849 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 21513 | 21850 | retcode = Jim_initjimshInit(interp); |
| 21514 | 21851 | |
| 21515 | 21852 | if (argc == 1) { |
| 21516 | 21853 | if (retcode == JIM_ERR) { |
| 21517 | | - Jim_MakeErrorMessage(interp); |
| 21518 | | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21854 | + JimPrintErrorMessage(interp); |
| 21519 | 21855 | } |
| 21520 | 21856 | if (retcode != JIM_EXIT) { |
| 21521 | 21857 | JimSetArgv(interp, 0, NULL); |
| 21522 | 21858 | retcode = Jim_InteractivePrompt(interp); |
| 21523 | 21859 | } |
| | @@ -21534,12 +21870,11 @@ |
| 21534 | 21870 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 21535 | 21871 | JimSetArgv(interp, argc - 2, argv + 2); |
| 21536 | 21872 | retcode = Jim_EvalFile(interp, argv[1]); |
| 21537 | 21873 | } |
| 21538 | 21874 | if (retcode == JIM_ERR) { |
| 21539 | | - Jim_MakeErrorMessage(interp); |
| 21540 | | - fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); |
| 21875 | + JimPrintErrorMessage(interp); |
| 21541 | 21876 | } |
| 21542 | 21877 | } |
| 21543 | 21878 | if (retcode == JIM_EXIT) { |
| 21544 | 21879 | retcode = Jim_GetExitCode(interp); |
| 21545 | 21880 | } |
| 21546 | 21881 | |