| | @@ -10,10 +10,11 @@ |
| 10 | 10 | #define jim_ext_readdir |
| 11 | 11 | #define jim_ext_regexp |
| 12 | 12 | #define jim_ext_file |
| 13 | 13 | #define jim_ext_glob |
| 14 | 14 | #define jim_ext_exec |
| 15 | +#define jim_ext_posix |
| 15 | 16 | #define jim_ext_clock |
| 16 | 17 | #define jim_ext_array |
| 17 | 18 | #define jim_ext_stdlib |
| 18 | 19 | #define jim_ext_tclcompat |
| 19 | 20 | #if defined(_MSC_VER) |
| | @@ -47,21 +48,23 @@ |
| 47 | 48 | #define vfork fork |
| 48 | 49 | #define _POSIX_SOURCE |
| 49 | 50 | #else |
| 50 | 51 | #define _GNU_SOURCE |
| 51 | 52 | #endif |
| 52 | | -#define HAVE_VFORK |
| 53 | +#define HAVE_FORK |
| 53 | 54 | #define HAVE_WAITPID |
| 54 | 55 | #define HAVE_ISATTY |
| 55 | 56 | #define HAVE_MKSTEMP |
| 56 | 57 | #define HAVE_LINK |
| 57 | 58 | #define HAVE_SYS_TIME_H |
| 58 | 59 | #define HAVE_DIRENT_H |
| 59 | 60 | #define HAVE_UNISTD_H |
| 60 | 61 | #define HAVE_UMASK |
| 62 | +#define HAVE_PIPE |
| 63 | +#define _FILE_OFFSET_BITS 64 |
| 61 | 64 | #endif |
| 62 | | -#define JIM_VERSION 78 |
| 65 | +#define JIM_VERSION 82 |
| 63 | 66 | #ifndef JIM_WIN32COMPAT_H |
| 64 | 67 | #define JIM_WIN32COMPAT_H |
| 65 | 68 | |
| 66 | 69 | |
| 67 | 70 | |
| | @@ -184,11 +187,10 @@ |
| 184 | 187 | extern "C" { |
| 185 | 188 | #endif |
| 186 | 189 | |
| 187 | 190 | #include <time.h> |
| 188 | 191 | #include <limits.h> |
| 189 | | -#include <stdio.h> |
| 190 | 192 | #include <stdlib.h> |
| 191 | 193 | #include <stdarg.h> |
| 192 | 194 | |
| 193 | 195 | |
| 194 | 196 | #ifndef HAVE_NO_AUTOCONF |
| | @@ -223,10 +225,13 @@ |
| 223 | 225 | #endif |
| 224 | 226 | |
| 225 | 227 | #define UCHAR(c) ((unsigned char)(c)) |
| 226 | 228 | |
| 227 | 229 | |
| 230 | + |
| 231 | +#define JIM_ABI_VERSION 101 |
| 232 | + |
| 228 | 233 | #define JIM_OK 0 |
| 229 | 234 | #define JIM_ERR 1 |
| 230 | 235 | #define JIM_RETURN 2 |
| 231 | 236 | #define JIM_BREAK 3 |
| 232 | 237 | #define JIM_CONTINUE 4 |
| | @@ -244,10 +249,11 @@ |
| 244 | 249 | #define JIM_NONE 0 |
| 245 | 250 | #define JIM_ERRMSG 1 |
| 246 | 251 | #define JIM_ENUM_ABBREV 2 |
| 247 | 252 | #define JIM_UNSHARED 4 |
| 248 | 253 | #define JIM_MUSTEXIST 8 |
| 254 | +#define JIM_NORESULT 16 |
| 249 | 255 | |
| 250 | 256 | |
| 251 | 257 | #define JIM_SUBST_NOVAR 1 |
| 252 | 258 | #define JIM_SUBST_NOCMD 2 |
| 253 | 259 | #define JIM_SUBST_NOESC 4 |
| | @@ -254,10 +260,11 @@ |
| 254 | 260 | #define JIM_SUBST_FLAG 128 |
| 255 | 261 | |
| 256 | 262 | |
| 257 | 263 | #define JIM_CASESENS 0 |
| 258 | 264 | #define JIM_NOCASE 1 |
| 265 | +#define JIM_OPT_END 2 |
| 259 | 266 | |
| 260 | 267 | |
| 261 | 268 | #define JIM_PATH_LEN 1024 |
| 262 | 269 | |
| 263 | 270 | |
| | @@ -322,10 +329,12 @@ |
| 322 | 329 | (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ |
| 323 | 330 | else \ |
| 324 | 331 | (entry)->u.val = (_val_); \ |
| 325 | 332 | } while(0) |
| 326 | 333 | |
| 334 | +#define Jim_SetHashIntVal(ht, entry, _val_) (entry)->u.intval = (_val_) |
| 335 | + |
| 327 | 336 | #define Jim_FreeEntryKey(ht, entry) \ |
| 328 | 337 | if ((ht)->type->keyDestructor) \ |
| 329 | 338 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) |
| 330 | 339 | |
| 331 | 340 | #define Jim_SetHashKey(ht, entry, _key_) do { \ |
| | @@ -342,10 +351,11 @@ |
| 342 | 351 | |
| 343 | 352 | #define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) |
| 344 | 353 | |
| 345 | 354 | #define Jim_GetHashEntryKey(he) ((he)->key) |
| 346 | 355 | #define Jim_GetHashEntryVal(he) ((he)->u.val) |
| 356 | +#define Jim_GetHashEntryIntVal(he) ((he)->u.intval) |
| 347 | 357 | #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) |
| 348 | 358 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 349 | 359 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 350 | 360 | |
| 351 | 361 | |
| | @@ -375,11 +385,11 @@ |
| 375 | 385 | int int1; |
| 376 | 386 | int int2; |
| 377 | 387 | } ptrIntValue; |
| 378 | 388 | |
| 379 | 389 | struct { |
| 380 | | - struct Jim_Var *varPtr; |
| 390 | + struct Jim_VarVal *vv; |
| 381 | 391 | unsigned long callFrameId; |
| 382 | 392 | int global; |
| 383 | 393 | } varValue; |
| 384 | 394 | |
| 385 | 395 | struct { |
| | @@ -391,10 +401,12 @@ |
| 391 | 401 | struct { |
| 392 | 402 | struct Jim_Obj **ele; |
| 393 | 403 | int len; |
| 394 | 404 | int maxLen; |
| 395 | 405 | } listValue; |
| 406 | + |
| 407 | + struct Jim_Dict *dictValue; |
| 396 | 408 | |
| 397 | 409 | struct { |
| 398 | 410 | int maxLength; |
| 399 | 411 | int charLength; |
| 400 | 412 | } strValue; |
| | @@ -477,33 +489,59 @@ |
| 477 | 489 | int argc; |
| 478 | 490 | Jim_Obj *procArgsObjPtr; |
| 479 | 491 | Jim_Obj *procBodyObjPtr; |
| 480 | 492 | struct Jim_CallFrame *next; |
| 481 | 493 | Jim_Obj *nsObj; |
| 482 | | - Jim_Obj *fileNameObj; |
| 483 | | - int line; |
| 494 | + Jim_Obj *unused_fileNameObj; |
| 495 | + int unused_line; |
| 484 | 496 | Jim_Stack *localCommands; |
| 485 | 497 | struct Jim_Obj *tailcallObj; |
| 486 | 498 | struct Jim_Cmd *tailcallCmd; |
| 487 | 499 | } Jim_CallFrame; |
| 488 | 500 | |
| 489 | | -typedef struct Jim_Var { |
| 501 | + |
| 502 | +typedef struct Jim_EvalFrame { |
| 503 | + Jim_CallFrame *framePtr; |
| 504 | + int level; |
| 505 | + int procLevel; |
| 506 | + struct Jim_Cmd *cmd; |
| 507 | + struct Jim_EvalFrame *parent; |
| 508 | + Jim_Obj *const *argv; |
| 509 | + int argc; |
| 510 | + Jim_Obj *scriptObj; |
| 511 | +} Jim_EvalFrame; |
| 512 | + |
| 513 | +typedef struct Jim_VarVal { |
| 490 | 514 | Jim_Obj *objPtr; |
| 491 | 515 | struct Jim_CallFrame *linkFramePtr; |
| 492 | | -} Jim_Var; |
| 516 | + int refCount; |
| 517 | +} Jim_VarVal; |
| 493 | 518 | |
| 494 | 519 | |
| 495 | 520 | typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, |
| 496 | 521 | Jim_Obj *const *argv); |
| 497 | 522 | typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 498 | 523 | |
| 499 | | - |
| 524 | +typedef struct Jim_Dict { |
| 525 | + struct JimDictHashEntry { |
| 526 | + int offset; |
| 527 | + unsigned hash; |
| 528 | + } *ht; |
| 529 | + unsigned int size; |
| 530 | + unsigned int sizemask; |
| 531 | + unsigned int uniq; |
| 532 | + Jim_Obj **table; |
| 533 | + int len; |
| 534 | + int maxLen; |
| 535 | + unsigned int dummy; |
| 536 | +} Jim_Dict; |
| 500 | 537 | |
| 501 | 538 | typedef struct Jim_Cmd { |
| 502 | 539 | int inUse; |
| 503 | 540 | int isproc; |
| 504 | 541 | struct Jim_Cmd *prevCmd; |
| 542 | + Jim_Obj *cmdNameObj; |
| 505 | 543 | union { |
| 506 | 544 | struct { |
| 507 | 545 | |
| 508 | 546 | Jim_CmdProc *cmdProc; |
| 509 | 547 | Jim_DelCmdProc *delProc; |
| | @@ -534,13 +572,13 @@ |
| 534 | 572 | unsigned int i, j; |
| 535 | 573 | } Jim_PrngState; |
| 536 | 574 | |
| 537 | 575 | typedef struct Jim_Interp { |
| 538 | 576 | Jim_Obj *result; |
| 539 | | - int errorLine; |
| 540 | | - Jim_Obj *errorFileNameObj; |
| 541 | | - int addStackTrace; |
| 577 | + int unused_errorLine; |
| 578 | + Jim_Obj *currentFilenameObj; |
| 579 | + int unused_addStackTrace; |
| 542 | 580 | int maxCallFrameDepth; |
| 543 | 581 | int maxEvalDepth; |
| 544 | 582 | int evalDepth; |
| 545 | 583 | int returnCode; |
| 546 | 584 | int returnLevel; |
| | @@ -558,13 +596,19 @@ |
| 558 | 596 | unsigned long callFrameEpoch; /* Incremented every time a new |
| 559 | 597 | callframe is created. This id is used for the |
| 560 | 598 | 'ID' field contained in the Jim_CallFrame |
| 561 | 599 | structure. */ |
| 562 | 600 | int local; |
| 601 | + int quitting; |
| 602 | + int safeexpr; |
| 563 | 603 | Jim_Obj *liveList; |
| 564 | 604 | Jim_Obj *freeList; |
| 565 | | - Jim_Obj *currentScriptObj; |
| 605 | + Jim_Obj *unused_currentScriptObj; |
| 606 | + Jim_EvalFrame topEvalFrame; |
| 607 | + Jim_EvalFrame *evalFrame; |
| 608 | + int procLevel; |
| 609 | + Jim_Obj * const *unused_argv; |
| 566 | 610 | Jim_Obj *nullScriptObj; |
| 567 | 611 | Jim_Obj *emptyObj; |
| 568 | 612 | Jim_Obj *trueObj; |
| 569 | 613 | Jim_Obj *falseObj; |
| 570 | 614 | unsigned long referenceNextId; |
| | @@ -572,28 +616,31 @@ |
| 572 | 616 | unsigned long lastCollectId; /* reference max Id of the last GC |
| 573 | 617 | execution. It's set to ~0 while the collection |
| 574 | 618 | is running as sentinel to avoid to recursive |
| 575 | 619 | calls via the [collect] command inside |
| 576 | 620 | finalizers. */ |
| 577 | | - time_t lastCollectTime; |
| 621 | + jim_wide lastCollectTime; |
| 578 | 622 | Jim_Obj *stackTrace; |
| 579 | 623 | Jim_Obj *errorProc; |
| 580 | 624 | Jim_Obj *unknown; |
| 625 | + Jim_Obj *defer; |
| 626 | + Jim_Obj *traceCmdObj; |
| 581 | 627 | int unknown_called; |
| 582 | 628 | int errorFlag; |
| 583 | 629 | void *cmdPrivData; /* Used to pass the private data pointer to |
| 584 | 630 | a command. It is set to what the user specified |
| 585 | 631 | via Jim_CreateCommand(). */ |
| 586 | 632 | |
| 633 | + Jim_Cmd *oldCmdCache; |
| 634 | + int oldCmdCacheSize; |
| 587 | 635 | struct Jim_CallFrame *freeFramesList; |
| 588 | 636 | struct Jim_HashTable assocData; |
| 589 | 637 | Jim_PrngState *prngState; |
| 590 | 638 | struct Jim_HashTable packages; |
| 591 | 639 | Jim_Stack *loadHandles; |
| 592 | 640 | } Jim_Interp; |
| 593 | 641 | |
| 594 | | -#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ |
| 595 | 642 | #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) |
| 596 | 643 | #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) |
| 597 | 644 | |
| 598 | 645 | #define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) |
| 599 | 646 | #define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) |
| | @@ -621,23 +668,36 @@ |
| 621 | 668 | |
| 622 | 669 | |
| 623 | 670 | #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) |
| 624 | 671 | #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) |
| 625 | 672 | |
| 626 | | -#define JIM_EXPORT |
| 673 | +#define JIM_EXPORT extern |
| 627 | 674 | |
| 628 | 675 | |
| 629 | | -JIM_EXPORT void *Jim_Alloc (int size); |
| 630 | | -JIM_EXPORT void *Jim_Realloc(void *ptr, int size); |
| 631 | | -JIM_EXPORT void Jim_Free (void *ptr); |
| 676 | + |
| 677 | +JIM_EXPORT void *(*Jim_Allocator)(void *ptr, size_t size); |
| 678 | + |
| 679 | +#define Jim_Free(P) Jim_Allocator((P), 0) |
| 680 | +#define Jim_Realloc(P, S) Jim_Allocator((P), (S)) |
| 681 | +#define Jim_Alloc(S) Jim_Allocator(NULL, (S)) |
| 632 | 682 | JIM_EXPORT char * Jim_StrDup (const char *s); |
| 633 | 683 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 634 | 684 | |
| 635 | 685 | |
| 636 | 686 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 637 | 687 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 638 | 688 | JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file); |
| 689 | +#ifndef CLOCK_REALTIME |
| 690 | +# define CLOCK_REALTIME 0 |
| 691 | +#endif |
| 692 | +#ifndef CLOCK_MONOTONIC |
| 693 | +# define CLOCK_MONOTONIC 1 |
| 694 | +#endif |
| 695 | +#ifndef CLOCK_MONOTONIC_RAW |
| 696 | +# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC |
| 697 | +#endif |
| 698 | +JIM_EXPORT jim_wide Jim_GetTimeUsec(unsigned type); |
| 639 | 699 | |
| 640 | 700 | |
| 641 | 701 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 642 | 702 | |
| 643 | 703 | |
| | @@ -680,11 +740,10 @@ |
| 680 | 740 | JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, |
| 681 | 741 | const void *key); |
| 682 | 742 | JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); |
| 683 | 743 | JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, |
| 684 | 744 | const void *key); |
| 685 | | -JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht); |
| 686 | 745 | JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator |
| 687 | 746 | (Jim_HashTable *ht); |
| 688 | 747 | JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry |
| 689 | 748 | (Jim_HashTableIterator *iter); |
| 690 | 749 | |
| | @@ -724,12 +783,10 @@ |
| 724 | 783 | Jim_Obj *fmtObjPtr, int flags); |
| 725 | 784 | JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, |
| 726 | 785 | Jim_Obj *objPtr, const char *str); |
| 727 | 786 | JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, |
| 728 | 787 | Jim_Obj *secondObjPtr, int nocase); |
| 729 | | -JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, |
| 730 | | - Jim_Obj *secondObjPtr, int nocase); |
| 731 | 788 | JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); |
| 732 | 789 | |
| 733 | 790 | |
| 734 | 791 | JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, |
| 735 | 792 | Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); |
| | @@ -749,13 +806,13 @@ |
| 749 | 806 | JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); |
| 750 | 807 | JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, |
| 751 | 808 | const char *cmdName, Jim_CmdProc *cmdProc, void *privData, |
| 752 | 809 | Jim_DelCmdProc *delProc); |
| 753 | 810 | JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, |
| 754 | | - const char *cmdName); |
| 811 | + Jim_Obj *cmdNameObj); |
| 755 | 812 | JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, |
| 756 | | - const char *oldName, const char *newName); |
| 813 | + Jim_Obj *oldNameObj, Jim_Obj *newNameObj); |
| 757 | 814 | JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, |
| 758 | 815 | Jim_Obj *objPtr, int flags); |
| 759 | 816 | JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, |
| 760 | 817 | Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); |
| 761 | 818 | JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, |
| | @@ -822,12 +879,12 @@ |
| 822 | 879 | Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, |
| 823 | 880 | Jim_Obj **objPtrPtr, int flags); |
| 824 | 881 | JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, |
| 825 | 882 | Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, |
| 826 | 883 | Jim_Obj *newObjPtr, int flags); |
| 827 | | -JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, |
| 828 | | - Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); |
| 884 | +JIM_EXPORT Jim_Obj **Jim_DictPairs(Jim_Interp *interp, |
| 885 | + Jim_Obj *dictPtr, int *len); |
| 829 | 886 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 830 | 887 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 831 | 888 | |
| 832 | 889 | #define JIM_DICTMATCH_KEYS 0x0001 |
| 833 | 890 | #define JIM_DICTMATCH_VALUES 0x002 |
| | @@ -851,10 +908,12 @@ |
| 851 | 908 | JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, |
| 852 | 909 | int *booleanPtr); |
| 853 | 910 | |
| 854 | 911 | |
| 855 | 912 | JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, |
| 913 | + jim_wide *widePtr); |
| 914 | +JIM_EXPORT int Jim_GetWideExpr(Jim_Interp *interp, Jim_Obj *objPtr, |
| 856 | 915 | jim_wide *widePtr); |
| 857 | 916 | JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, |
| 858 | 917 | long *longPtr); |
| 859 | 918 | #define Jim_NewWideObj Jim_NewIntObj |
| 860 | 919 | JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, |
| | @@ -883,43 +942,52 @@ |
| 883 | 942 | typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); |
| 884 | 943 | JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); |
| 885 | 944 | JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, |
| 886 | 945 | Jim_InterpDeleteProc *delProc, void *data); |
| 887 | 946 | JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); |
| 947 | +JIM_EXPORT int Jim_CheckAbiVersion(Jim_Interp *interp, int abi_version); |
| 948 | + |
| 888 | 949 | |
| 889 | 950 | |
| 890 | 951 | |
| 891 | 952 | JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, |
| 892 | 953 | const char *name, const char *ver, int flags); |
| 893 | 954 | JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, |
| 894 | 955 | const char *name, int flags); |
| 956 | +#define Jim_PackageProvideCheck(INTERP, NAME) \ |
| 957 | + if (Jim_CheckAbiVersion(INTERP, JIM_ABI_VERSION) == JIM_ERR || Jim_PackageProvide(INTERP, NAME, "1.0", JIM_ERRMSG)) \ |
| 958 | + return JIM_ERR |
| 895 | 959 | |
| 896 | 960 | |
| 897 | 961 | JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); |
| 898 | 962 | |
| 899 | 963 | |
| 900 | 964 | JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); |
| 901 | 965 | JIM_EXPORT void Jim_HistoryLoad(const char *filename); |
| 902 | 966 | JIM_EXPORT void Jim_HistorySave(const char *filename); |
| 903 | 967 | JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt); |
| 904 | | -JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj); |
| 968 | +JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *completionCommandObj); |
| 969 | +JIM_EXPORT void Jim_HistorySetHints(Jim_Interp *interp, Jim_Obj *hintsCommandObj); |
| 905 | 970 | JIM_EXPORT void Jim_HistoryAdd(const char *line); |
| 906 | 971 | JIM_EXPORT void Jim_HistoryShow(void); |
| 972 | +JIM_EXPORT void Jim_HistorySetMaxLen(int length); |
| 973 | +JIM_EXPORT int Jim_HistoryGetMaxLen(void); |
| 907 | 974 | |
| 908 | 975 | |
| 909 | 976 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| 910 | 977 | JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); |
| 911 | 978 | JIM_EXPORT int Jim_IsBigEndian(void); |
| 912 | 979 | |
| 913 | 980 | #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) |
| 981 | +JIM_EXPORT void Jim_SignalSetIgnored(jim_wide mask); |
| 914 | 982 | |
| 915 | 983 | |
| 916 | 984 | JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); |
| 917 | 985 | JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); |
| 918 | 986 | |
| 919 | 987 | |
| 920 | | -JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 988 | +JIM_EXPORT int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
| 921 | 989 | |
| 922 | 990 | |
| 923 | 991 | JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); |
| 924 | 992 | JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); |
| 925 | 993 | |
| | @@ -952,16 +1020,21 @@ |
| 952 | 1020 | short minargs; |
| 953 | 1021 | short maxargs; |
| 954 | 1022 | unsigned short flags; |
| 955 | 1023 | } jim_subcmd_type; |
| 956 | 1024 | |
| 1025 | +#define JIM_DEF_SUBCMD(name, args, minargs, maxargs) { name, args, NULL, minargs, maxargs } |
| 1026 | +#define JIM_DEF_SUBCMD_HIDDEN(name, args, minargs, maxargs) { name, args, NULL, minargs, maxargs, JIM_MODFLAG_HIDDEN } |
| 1027 | + |
| 957 | 1028 | const jim_subcmd_type * |
| 958 | 1029 | Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); |
| 959 | 1030 | |
| 960 | 1031 | int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 961 | 1032 | |
| 962 | 1033 | int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv); |
| 1034 | + |
| 1035 | +void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type *ct, Jim_Obj *subcmd); |
| 963 | 1036 | |
| 964 | 1037 | #ifdef __cplusplus |
| 965 | 1038 | } |
| 966 | 1039 | #endif |
| 967 | 1040 | |
| | @@ -1034,20 +1107,21 @@ |
| 1034 | 1107 | REG_ERR_JUNK_ON_END, |
| 1035 | 1108 | REG_ERR_OPERAND_COULD_BE_EMPTY, |
| 1036 | 1109 | REG_ERR_NESTED_COUNT, |
| 1037 | 1110 | REG_ERR_INTERNAL, |
| 1038 | 1111 | REG_ERR_COUNT_FOLLOWS_NOTHING, |
| 1039 | | - REG_ERR_TRAILING_BACKSLASH, |
| 1112 | + REG_ERR_INVALID_ESCAPE, |
| 1040 | 1113 | REG_ERR_CORRUPTED, |
| 1041 | 1114 | REG_ERR_NULL_CHAR, |
| 1115 | + REG_ERR_UNMATCHED_BRACKET, |
| 1042 | 1116 | REG_ERR_NUM |
| 1043 | 1117 | }; |
| 1044 | 1118 | |
| 1045 | | -int regcomp(regex_t *preg, const char *regex, int cflags); |
| 1046 | | -int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1047 | | -size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1048 | | -void regfree(regex_t *preg); |
| 1119 | +int jim_regcomp(regex_t *preg, const char *regex, int cflags); |
| 1120 | +int jim_regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); |
| 1121 | +size_t jim_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); |
| 1122 | +void jim_regfree(regex_t *preg); |
| 1049 | 1123 | |
| 1050 | 1124 | #ifdef __cplusplus |
| 1051 | 1125 | } |
| 1052 | 1126 | #endif |
| 1053 | 1127 | |
| | @@ -1070,10 +1144,11 @@ |
| 1070 | 1144 | #define JIMIOCOMPAT_H |
| 1071 | 1145 | |
| 1072 | 1146 | |
| 1073 | 1147 | #include <stdio.h> |
| 1074 | 1148 | #include <errno.h> |
| 1149 | +#include <sys/stat.h> |
| 1075 | 1150 | |
| 1076 | 1151 | |
| 1077 | 1152 | void Jim_SetResultErrno(Jim_Interp *interp, const char *msg); |
| 1078 | 1153 | |
| 1079 | 1154 | int Jim_OpenForWrite(const char *filename, int append); |
| | @@ -1088,67 +1163,109 @@ |
| 1088 | 1163 | #include <windows.h> |
| 1089 | 1164 | #include <fcntl.h> |
| 1090 | 1165 | #include <io.h> |
| 1091 | 1166 | #include <process.h> |
| 1092 | 1167 | |
| 1093 | | - typedef HANDLE pidtype; |
| 1094 | | - #define JIM_BAD_PID INVALID_HANDLE_VALUE |
| 1095 | | - |
| 1096 | | - #define JIM_NO_PID INVALID_HANDLE_VALUE |
| 1168 | + typedef HANDLE phandle_t; |
| 1169 | + #define JIM_BAD_PHANDLE INVALID_HANDLE_VALUE |
| 1097 | 1170 | |
| 1098 | 1171 | |
| 1099 | 1172 | #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0) |
| 1100 | 1173 | #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff) |
| 1101 | 1174 | #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0) |
| 1102 | 1175 | #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff) |
| 1103 | 1176 | #define WNOHANG 1 |
| 1104 | 1177 | |
| 1105 | 1178 | int Jim_Errno(void); |
| 1106 | | - pidtype waitpid(pidtype pid, int *status, int nohang); |
| 1179 | + |
| 1180 | + long waitpid(phandle_t phandle, int *status, int nohang); |
| 1181 | + |
| 1182 | + phandle_t JimWaitPid(long processid, int *status, int nohang); |
| 1183 | + |
| 1184 | + long JimProcessPid(phandle_t phandle); |
| 1107 | 1185 | |
| 1108 | 1186 | #define HAVE_PIPE |
| 1109 | 1187 | #define pipe(P) _pipe((P), 0, O_NOINHERIT) |
| 1110 | 1188 | |
| 1111 | | -#elif defined(HAVE_UNISTD_H) |
| 1112 | | - #include <unistd.h> |
| 1113 | | - #include <fcntl.h> |
| 1114 | | - #include <sys/wait.h> |
| 1115 | | - #include <sys/stat.h> |
| 1116 | | - |
| 1117 | | - typedef int pidtype; |
| 1118 | | - #define Jim_Errno() errno |
| 1119 | | - #define JIM_BAD_PID -1 |
| 1120 | | - #define JIM_NO_PID 0 |
| 1121 | | - |
| 1122 | | - #ifndef HAVE_EXECVPE |
| 1123 | | - #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) |
| 1189 | + typedef struct __stat64 jim_stat_t; |
| 1190 | + #define Jim_Stat _stat64 |
| 1191 | + #define Jim_FileStat _fstat64 |
| 1192 | + #define Jim_Lseek _lseeki64 |
| 1193 | + |
| 1194 | +#else |
| 1195 | + #if defined(HAVE_STAT64) |
| 1196 | + typedef struct stat64 jim_stat_t; |
| 1197 | + #define Jim_Stat stat64 |
| 1198 | + #if defined(HAVE_FSTAT64) |
| 1199 | + #define Jim_FileStat fstat64 |
| 1200 | + #endif |
| 1201 | + #if defined(HAVE_LSTAT64) |
| 1202 | + #define Jim_LinkStat lstat64 |
| 1203 | + #endif |
| 1204 | + #else |
| 1205 | + typedef struct stat jim_stat_t; |
| 1206 | + #define Jim_Stat stat |
| 1207 | + #if defined(HAVE_FSTAT) |
| 1208 | + #define Jim_FileStat fstat |
| 1209 | + #endif |
| 1210 | + #if defined(HAVE_LSTAT) |
| 1211 | + #define Jim_LinkStat lstat |
| 1212 | + #endif |
| 1213 | + #endif |
| 1214 | + #if defined(HAVE_LSEEK64) |
| 1215 | + #define Jim_Lseek lseek64 |
| 1216 | + #else |
| 1217 | + #define Jim_Lseek lseek |
| 1218 | + #endif |
| 1219 | + |
| 1220 | + #if defined(HAVE_UNISTD_H) |
| 1221 | + #include <unistd.h> |
| 1222 | + #include <fcntl.h> |
| 1223 | + #include <sys/wait.h> |
| 1224 | + |
| 1225 | + typedef int phandle_t; |
| 1226 | + #define Jim_Errno() errno |
| 1227 | + #define JIM_BAD_PHANDLE -1 |
| 1228 | + #define JimProcessPid(PIDTYPE) (PIDTYPE) |
| 1229 | + #define JimWaitPid waitpid |
| 1230 | + |
| 1231 | + #ifndef HAVE_EXECVPE |
| 1232 | + #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) |
| 1233 | + #endif |
| 1124 | 1234 | #endif |
| 1125 | 1235 | #endif |
| 1126 | 1236 | |
| 1237 | +#ifndef O_TEXT |
| 1238 | +#define O_TEXT 0 |
| 1239 | +#endif |
| 1240 | + |
| 1241 | + |
| 1242 | +int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb); |
| 1243 | + |
| 1127 | 1244 | #endif |
| 1128 | 1245 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1129 | 1246 | { |
| 1130 | 1247 | if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) |
| 1131 | 1248 | return JIM_ERR; |
| 1132 | 1249 | |
| 1133 | 1250 | return Jim_EvalSource(interp, "bootstrap.tcl", 1, |
| 1134 | 1251 | "\n" |
| 1135 | | -"\n" |
| 1136 | | -"proc package {cmd pkg args} {\n" |
| 1252 | +"proc package {cmd args} {\n" |
| 1137 | 1253 | " if {$cmd eq \"require\"} {\n" |
| 1138 | 1254 | " foreach path $::auto_path {\n" |
| 1255 | +" lassign $args pkg\n" |
| 1139 | 1256 | " set pkgpath $path/$pkg.tcl\n" |
| 1140 | 1257 | " if {$path eq \".\"} {\n" |
| 1141 | 1258 | " set pkgpath $pkg.tcl\n" |
| 1142 | 1259 | " }\n" |
| 1143 | 1260 | " if {[file exists $pkgpath]} {\n" |
| 1144 | | -" uplevel #0 [list source $pkgpath]\n" |
| 1145 | | -" return\n" |
| 1261 | +" tailcall uplevel #0 [list source $pkgpath]\n" |
| 1146 | 1262 | " }\n" |
| 1147 | 1263 | " }\n" |
| 1148 | 1264 | " }\n" |
| 1149 | 1265 | "}\n" |
| 1266 | +"set tcl_platform(bootstrap) 1\n" |
| 1150 | 1267 | ); |
| 1151 | 1268 | } |
| 1152 | 1269 | int Jim_initjimshInit(Jim_Interp *interp) |
| 1153 | 1270 | { |
| 1154 | 1271 | if (Jim_PackageProvide(interp, "initjimsh", "1.0", JIM_ERRMSG)) |
| | @@ -1199,11 +1316,11 @@ |
| 1199 | 1316 | "if {$tcl_platform(platform) eq \"windows\"} {\n" |
| 1200 | 1317 | " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n" |
| 1201 | 1318 | "}\n" |
| 1202 | 1319 | "\n" |
| 1203 | 1320 | "\n" |
| 1204 | | -"set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n" |
| 1321 | +"set tcl::autocomplete_commands {array clock debug dict file history info namespace package signal socket string tcl::prefix zlib}\n" |
| 1205 | 1322 | "\n" |
| 1206 | 1323 | "\n" |
| 1207 | 1324 | "\n" |
| 1208 | 1325 | "proc tcl::autocomplete {prefix} {\n" |
| 1209 | 1326 | " if {[set space [string first \" \" $prefix]] != -1} {\n" |
| | @@ -1231,10 +1348,67 @@ |
| 1231 | 1348 | " }\n" |
| 1232 | 1349 | " function $p\n" |
| 1233 | 1350 | " }]\n" |
| 1234 | 1351 | "}\n" |
| 1235 | 1352 | "\n" |
| 1353 | +"\n" |
| 1354 | +"set tcl::stdhint_commands {array clock debug dict file history info namespace package signal string zlib}\n" |
| 1355 | +"\n" |
| 1356 | +"set tcl::stdhint_cols {\n" |
| 1357 | +" none {0}\n" |
| 1358 | +" black {30}\n" |
| 1359 | +" red {31}\n" |
| 1360 | +" green {32}\n" |
| 1361 | +" yellow {33}\n" |
| 1362 | +" blue {34}\n" |
| 1363 | +" purple {35}\n" |
| 1364 | +" cyan {36}\n" |
| 1365 | +" normal {37}\n" |
| 1366 | +" grey {30 1}\n" |
| 1367 | +" gray {30 1}\n" |
| 1368 | +" lred {31 1}\n" |
| 1369 | +" lgreen {32 1}\n" |
| 1370 | +" lyellow {33 1}\n" |
| 1371 | +" lblue {34 1}\n" |
| 1372 | +" lpurple {35 1}\n" |
| 1373 | +" lcyan {36 1}\n" |
| 1374 | +" white {37 1}\n" |
| 1375 | +"}\n" |
| 1376 | +"\n" |
| 1377 | +"\n" |
| 1378 | +"set tcl::stdhint_col $tcl::stdhint_cols(lcyan)\n" |
| 1379 | +"\n" |
| 1380 | +"\n" |
| 1381 | +"proc tcl::stdhint {string} {\n" |
| 1382 | +" set result \"\"\n" |
| 1383 | +" if {[llength $string] >= 2} {\n" |
| 1384 | +" lassign $string cmd arg\n" |
| 1385 | +" if {$cmd in $::tcl::stdhint_commands || [info channel $cmd] ne \"\"} {\n" |
| 1386 | +" catch {\n" |
| 1387 | +" set help [$cmd -help $arg]\n" |
| 1388 | +" if {[string match \"Usage: $cmd *\" $help]} {\n" |
| 1389 | +" set n [llength $string]\n" |
| 1390 | +" set subcmd [lindex $help $n]\n" |
| 1391 | +" incr n\n" |
| 1392 | +" set hint [join [lrange $help $n end]]\n" |
| 1393 | +" set prefix \"\"\n" |
| 1394 | +" if {![string match \"* \" $string]} {\n" |
| 1395 | +" if {$n == 3 && $subcmd ne $arg} {\n" |
| 1396 | +"\n" |
| 1397 | +" set prefix \"[string range $subcmd [string length $arg] end] \"\n" |
| 1398 | +" } else {\n" |
| 1399 | +" set prefix \" \"\n" |
| 1400 | +" }\n" |
| 1401 | +" }\n" |
| 1402 | +" set result [list $prefix$hint {*}$::tcl::stdhint_col]\n" |
| 1403 | +" }\n" |
| 1404 | +" }\n" |
| 1405 | +" }\n" |
| 1406 | +" }\n" |
| 1407 | +" return $result\n" |
| 1408 | +"}\n" |
| 1409 | +"\n" |
| 1236 | 1410 | "_jimsh_init\n" |
| 1237 | 1411 | ); |
| 1238 | 1412 | } |
| 1239 | 1413 | int Jim_globInit(Jim_Interp *interp) |
| 1240 | 1414 | { |
| | @@ -1480,40 +1654,35 @@ |
| 1480 | 1654 | "proc function {value} {\n" |
| 1481 | 1655 | " return $value\n" |
| 1482 | 1656 | "}\n" |
| 1483 | 1657 | "\n" |
| 1484 | 1658 | "\n" |
| 1485 | | -"\n" |
| 1486 | | -"\n" |
| 1487 | | -"proc stacktrace {{skip 0}} {\n" |
| 1488 | | -" set trace {}\n" |
| 1489 | | -" incr skip\n" |
| 1490 | | -" foreach level [range $skip [info level]] {\n" |
| 1491 | | -" lappend trace {*}[info frame -$level]\n" |
| 1492 | | -" }\n" |
| 1493 | | -" return $trace\n" |
| 1494 | | -"}\n" |
| 1495 | | -"\n" |
| 1496 | | -"\n" |
| 1497 | 1659 | "proc stackdump {stacktrace} {\n" |
| 1498 | 1660 | " set lines {}\n" |
| 1499 | | -" foreach {l f p} [lreverse $stacktrace] {\n" |
| 1661 | +" lappend lines \"Traceback (most recent call last):\"\n" |
| 1662 | +" foreach {cmd l f p} [lreverse $stacktrace] {\n" |
| 1500 | 1663 | " set line {}\n" |
| 1664 | +" if {$f ne \"\"} {\n" |
| 1665 | +" append line \" File \\\"$f\\\", line $l\"\n" |
| 1666 | +" }\n" |
| 1501 | 1667 | " if {$p ne \"\"} {\n" |
| 1502 | | -" append line \"in procedure '$p' \"\n" |
| 1503 | | -" if {$f ne \"\"} {\n" |
| 1504 | | -" append line \"called \"\n" |
| 1505 | | -" }\n" |
| 1506 | | -" }\n" |
| 1507 | | -" if {$f ne \"\"} {\n" |
| 1508 | | -" append line \"at file \\\"$f\\\", line $l\"\n" |
| 1668 | +" append line \", in $p\"\n" |
| 1509 | 1669 | " }\n" |
| 1510 | 1670 | " if {$line ne \"\"} {\n" |
| 1511 | 1671 | " lappend lines $line\n" |
| 1672 | +" if {$cmd ne \"\"} {\n" |
| 1673 | +" set nl [string first \\n $cmd 1]\n" |
| 1674 | +" if {$nl >= 0} {\n" |
| 1675 | +" set cmd [string range $cmd 0 $nl-1]...\n" |
| 1676 | +" }\n" |
| 1677 | +" lappend lines \" $cmd\"\n" |
| 1678 | +" }\n" |
| 1512 | 1679 | " }\n" |
| 1513 | 1680 | " }\n" |
| 1514 | | -" join $lines \\n\n" |
| 1681 | +" if {[llength $lines] > 1} {\n" |
| 1682 | +" return [join $lines \\n]\n" |
| 1683 | +" }\n" |
| 1515 | 1684 | "}\n" |
| 1516 | 1685 | "\n" |
| 1517 | 1686 | "\n" |
| 1518 | 1687 | "\n" |
| 1519 | 1688 | "proc defer {script} {\n" |
| | @@ -1525,14 +1694,12 @@ |
| 1525 | 1694 | "\n" |
| 1526 | 1695 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1527 | 1696 | " if {$stacktrace eq \"\"} {\n" |
| 1528 | 1697 | "\n" |
| 1529 | 1698 | " set stacktrace [info stacktrace]\n" |
| 1530 | | -"\n" |
| 1531 | | -" lappend stacktrace {*}[stacktrace 1]\n" |
| 1532 | 1699 | " }\n" |
| 1533 | | -" lassign $stacktrace p f l\n" |
| 1700 | +" lassign $stacktrace p f l cmd\n" |
| 1534 | 1701 | " if {$f ne \"\"} {\n" |
| 1535 | 1702 | " set result \"$f:$l: Error: \"\n" |
| 1536 | 1703 | " }\n" |
| 1537 | 1704 | " append result \"$msg\\n\"\n" |
| 1538 | 1705 | " append result [stackdump $stacktrace]\n" |
| | @@ -1641,11 +1808,11 @@ |
| 1641 | 1808 | "\n" |
| 1642 | 1809 | "\n" |
| 1643 | 1810 | "set env [env]\n" |
| 1644 | 1811 | "\n" |
| 1645 | 1812 | "\n" |
| 1646 | | -"if {[info commands stdout] ne \"\"} {\n" |
| 1813 | +"if {[exists -command stdout]} {\n" |
| 1647 | 1814 | "\n" |
| 1648 | 1815 | " foreach p {gets flush close eof seek tell} {\n" |
| 1649 | 1816 | " proc $p {chan args} {p} {\n" |
| 1650 | 1817 | " tailcall $chan $p {*}$args\n" |
| 1651 | 1818 | " }\n" |
| | @@ -1815,76 +1982,10 @@ |
| 1815 | 1982 | " return $pids\n" |
| 1816 | 1983 | "}\n" |
| 1817 | 1984 | "\n" |
| 1818 | 1985 | "\n" |
| 1819 | 1986 | "\n" |
| 1820 | | -"\n" |
| 1821 | | -"\n" |
| 1822 | | -"\n" |
| 1823 | | -"\n" |
| 1824 | | -"\n" |
| 1825 | | -"\n" |
| 1826 | | -"\n" |
| 1827 | | -"proc try {args} {\n" |
| 1828 | | -" set catchopts {}\n" |
| 1829 | | -" while {[string match -* [lindex $args 0]]} {\n" |
| 1830 | | -" set args [lassign $args opt]\n" |
| 1831 | | -" if {$opt eq \"--\"} {\n" |
| 1832 | | -" break\n" |
| 1833 | | -" }\n" |
| 1834 | | -" lappend catchopts $opt\n" |
| 1835 | | -" }\n" |
| 1836 | | -" if {[llength $args] == 0} {\n" |
| 1837 | | -" return -code error {wrong # args: should be \"try ?options? script ?argument ...?\"}\n" |
| 1838 | | -" }\n" |
| 1839 | | -" set args [lassign $args script]\n" |
| 1840 | | -" set code [catch -eval {*}$catchopts {uplevel 1 $script} msg opts]\n" |
| 1841 | | -"\n" |
| 1842 | | -" set handled 0\n" |
| 1843 | | -"\n" |
| 1844 | | -" foreach {on codes vars script} $args {\n" |
| 1845 | | -" switch -- $on \\\n" |
| 1846 | | -" on {\n" |
| 1847 | | -" if {!$handled && ($codes eq \"*\" || [info returncode $code] in $codes)} {\n" |
| 1848 | | -" lassign $vars msgvar optsvar\n" |
| 1849 | | -" if {$msgvar ne \"\"} {\n" |
| 1850 | | -" upvar $msgvar hmsg\n" |
| 1851 | | -" set hmsg $msg\n" |
| 1852 | | -" }\n" |
| 1853 | | -" if {$optsvar ne \"\"} {\n" |
| 1854 | | -" upvar $optsvar hopts\n" |
| 1855 | | -" set hopts $opts\n" |
| 1856 | | -" }\n" |
| 1857 | | -"\n" |
| 1858 | | -" set code [catch {uplevel 1 $script} msg opts]\n" |
| 1859 | | -" incr handled\n" |
| 1860 | | -" }\n" |
| 1861 | | -" } \\\n" |
| 1862 | | -" finally {\n" |
| 1863 | | -" set finalcode [catch {uplevel 1 $codes} finalmsg finalopts]\n" |
| 1864 | | -" if {$finalcode} {\n" |
| 1865 | | -"\n" |
| 1866 | | -" set code $finalcode\n" |
| 1867 | | -" set msg $finalmsg\n" |
| 1868 | | -" set opts $finalopts\n" |
| 1869 | | -" }\n" |
| 1870 | | -" break\n" |
| 1871 | | -" } \\\n" |
| 1872 | | -" default {\n" |
| 1873 | | -" return -code error \"try: expected 'on' or 'finally', got '$on'\"\n" |
| 1874 | | -" }\n" |
| 1875 | | -" }\n" |
| 1876 | | -"\n" |
| 1877 | | -" if {$code} {\n" |
| 1878 | | -" incr opts(-level)\n" |
| 1879 | | -" return {*}$opts $msg\n" |
| 1880 | | -" }\n" |
| 1881 | | -" return $msg\n" |
| 1882 | | -"}\n" |
| 1883 | | -"\n" |
| 1884 | | -"\n" |
| 1885 | | -"\n" |
| 1886 | 1987 | "proc throw {code {msg \"\"}} {\n" |
| 1887 | 1988 | " return -code $code $msg\n" |
| 1888 | 1989 | "}\n" |
| 1889 | 1990 | "\n" |
| 1890 | 1991 | "\n" |
| | @@ -1896,20 +1997,24 @@ |
| 1896 | 1997 | "}\n" |
| 1897 | 1998 | ); |
| 1898 | 1999 | } |
| 1899 | 2000 | |
| 1900 | 2001 | |
| 1901 | | -#ifndef _GNU_SOURCE |
| 1902 | | -#define _GNU_SOURCE |
| 1903 | | -#endif |
| 1904 | 2002 | #include <stdio.h> |
| 1905 | 2003 | #include <string.h> |
| 1906 | 2004 | #include <errno.h> |
| 1907 | 2005 | #include <fcntl.h> |
| 2006 | +#include <assert.h> |
| 1908 | 2007 | #ifdef HAVE_UNISTD_H |
| 1909 | 2008 | #include <unistd.h> |
| 1910 | 2009 | #include <sys/stat.h> |
| 2010 | +#endif |
| 2011 | +#ifdef HAVE_UTIL_H |
| 2012 | +#include <util.h> |
| 2013 | +#endif |
| 2014 | +#ifdef HAVE_PTY_H |
| 2015 | +#include <pty.h> |
| 1911 | 2016 | #endif |
| 1912 | 2017 | |
| 1913 | 2018 | |
| 1914 | 2019 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1915 | 2020 | #include <sys/socket.h> |
| | @@ -1921,12 +2026,10 @@ |
| 1921 | 2026 | #include <sys/un.h> |
| 1922 | 2027 | #endif |
| 1923 | 2028 | #define HAVE_SOCKETS |
| 1924 | 2029 | #elif defined (__MINGW32__) |
| 1925 | 2030 | |
| 1926 | | -#else |
| 1927 | | -#define JIM_ANSIC |
| 1928 | 2031 | #endif |
| 1929 | 2032 | |
| 1930 | 2033 | #if defined(JIM_SSL) |
| 1931 | 2034 | #include <openssl/ssl.h> |
| 1932 | 2035 | #include <openssl/err.h> |
| | @@ -1936,98 +2039,136 @@ |
| 1936 | 2039 | #endif |
| 1937 | 2040 | |
| 1938 | 2041 | |
| 1939 | 2042 | #define AIO_CMD_LEN 32 |
| 1940 | 2043 | #define AIO_BUF_LEN 256 |
| 1941 | | - |
| 1942 | | -#ifndef HAVE_FTELLO |
| 1943 | | - #define ftello ftell |
| 1944 | | -#endif |
| 1945 | | -#ifndef HAVE_FSEEKO |
| 1946 | | - #define fseeko fseek |
| 1947 | | -#endif |
| 2044 | +#define AIO_WBUF_FULL_SIZE (64 * 1024) |
| 1948 | 2045 | |
| 1949 | 2046 | #define AIO_KEEPOPEN 1 |
| 2047 | +#define AIO_NODELETE 2 |
| 2048 | +#define AIO_EOF 4 |
| 2049 | +#define AIO_WBUF_NONE 8 |
| 2050 | +#define AIO_NONBLOCK 16 |
| 2051 | + |
| 2052 | +enum wbuftype { |
| 2053 | + WBUF_OPT_NONE, |
| 2054 | + WBUF_OPT_LINE, |
| 2055 | + WBUF_OPT_FULL, |
| 2056 | +}; |
| 1950 | 2057 | |
| 1951 | 2058 | #if defined(JIM_IPV6) |
| 1952 | 2059 | #define IPV6 1 |
| 1953 | 2060 | #else |
| 1954 | 2061 | #define IPV6 0 |
| 1955 | 2062 | #ifndef PF_INET6 |
| 1956 | 2063 | #define PF_INET6 0 |
| 1957 | 2064 | #endif |
| 1958 | 2065 | #endif |
| 2066 | +#if defined(HAVE_SYS_UN_H) && defined(PF_UNIX) |
| 2067 | +#define UNIX_SOCKETS 1 |
| 2068 | +#else |
| 2069 | +#define UNIX_SOCKETS 0 |
| 2070 | +#endif |
| 1959 | 2071 | |
| 1960 | | -#ifdef JIM_ANSIC |
| 2072 | +#ifndef MAXPATHLEN |
| 2073 | +#define MAXPATHLEN JIM_PATH_LEN |
| 2074 | +#endif |
| 1961 | 2075 | |
| 1962 | | -#undef HAVE_PIPE |
| 1963 | | -#undef HAVE_SOCKETPAIR |
| 2076 | + |
| 2077 | + |
| 2078 | + |
| 2079 | +static int JimReadableTimeout(int fd, long ms) |
| 2080 | +{ |
| 2081 | +#ifdef HAVE_SELECT |
| 2082 | + int retval; |
| 2083 | + struct timeval tv; |
| 2084 | + fd_set rfds; |
| 2085 | + |
| 2086 | + FD_ZERO(&rfds); |
| 2087 | + |
| 2088 | + FD_SET(fd, &rfds); |
| 2089 | + tv.tv_sec = ms / 1000; |
| 2090 | + tv.tv_usec = (ms % 1000) * 1000; |
| 2091 | + |
| 2092 | + retval = select(fd + 1, &rfds, NULL, NULL, ms == 0 ? NULL : &tv); |
| 2093 | + |
| 2094 | + if (retval > 0) { |
| 2095 | + return JIM_OK; |
| 2096 | + } |
| 2097 | + return JIM_ERR; |
| 2098 | +#else |
| 2099 | + return JIM_OK; |
| 1964 | 2100 | #endif |
| 2101 | +} |
| 1965 | 2102 | |
| 1966 | 2103 | |
| 1967 | 2104 | struct AioFile; |
| 1968 | 2105 | |
| 1969 | 2106 | typedef struct { |
| 1970 | 2107 | int (*writer)(struct AioFile *af, const char *buf, int len); |
| 1971 | | - int (*reader)(struct AioFile *af, char *buf, int len); |
| 1972 | | - const char *(*getline)(struct AioFile *af, char *buf, int len); |
| 2108 | + int (*reader)(struct AioFile *af, char *buf, int len, int pending); |
| 1973 | 2109 | int (*error)(const struct AioFile *af); |
| 1974 | 2110 | const char *(*strerror)(struct AioFile *af); |
| 1975 | 2111 | int (*verify)(struct AioFile *af); |
| 1976 | 2112 | } JimAioFopsType; |
| 1977 | 2113 | |
| 1978 | 2114 | typedef struct AioFile |
| 1979 | 2115 | { |
| 1980 | | - FILE *fp; |
| 1981 | 2116 | Jim_Obj *filename; |
| 1982 | | - int type; |
| 1983 | | - int openFlags; |
| 2117 | + int wbuft; |
| 2118 | + int flags; |
| 2119 | + long timeout; |
| 1984 | 2120 | int fd; |
| 1985 | | - Jim_Obj *rEvent; |
| 1986 | | - Jim_Obj *wEvent; |
| 1987 | | - Jim_Obj *eEvent; |
| 1988 | 2121 | int addr_family; |
| 1989 | 2122 | void *ssl; |
| 1990 | 2123 | const JimAioFopsType *fops; |
| 2124 | + Jim_Obj *readbuf; |
| 2125 | + Jim_Obj *writebuf; |
| 1991 | 2126 | } AioFile; |
| 1992 | 2127 | |
| 1993 | 2128 | static int stdio_writer(struct AioFile *af, const char *buf, int len) |
| 1994 | 2129 | { |
| 1995 | | - return fwrite(buf, 1, len, af->fp); |
| 2130 | + return write(af->fd, buf, len); |
| 1996 | 2131 | } |
| 1997 | 2132 | |
| 1998 | | -static int stdio_reader(struct AioFile *af, char *buf, int len) |
| 1999 | | -{ |
| 2000 | | - return fread(buf, 1, len, af->fp); |
| 2001 | | -} |
| 2002 | | - |
| 2003 | | -static const char *stdio_getline(struct AioFile *af, char *buf, int len) |
| 2004 | | -{ |
| 2005 | | - return fgets(buf, len, af->fp); |
| 2133 | +static int stdio_reader(struct AioFile *af, char *buf, int len, int nb) |
| 2134 | +{ |
| 2135 | + if (nb || af->timeout == 0 || JimReadableTimeout(af->fd, af->timeout) == JIM_OK) { |
| 2136 | + |
| 2137 | + int ret; |
| 2138 | + |
| 2139 | + errno = 0; |
| 2140 | + ret = read(af->fd, buf, len); |
| 2141 | + if (ret <= 0 && errno != EAGAIN && errno != EINTR) { |
| 2142 | + af->flags |= AIO_EOF; |
| 2143 | + } |
| 2144 | + return ret; |
| 2145 | + } |
| 2146 | + errno = ETIMEDOUT; |
| 2147 | + return -1; |
| 2006 | 2148 | } |
| 2007 | 2149 | |
| 2008 | 2150 | static int stdio_error(const AioFile *af) |
| 2009 | 2151 | { |
| 2010 | | - if (!ferror(af->fp)) { |
| 2152 | + if (af->flags & AIO_EOF) { |
| 2011 | 2153 | return JIM_OK; |
| 2012 | 2154 | } |
| 2013 | | - clearerr(af->fp); |
| 2014 | 2155 | |
| 2015 | | - if (feof(af->fp) || errno == EAGAIN || errno == EINTR) { |
| 2016 | | - return JIM_OK; |
| 2017 | | - } |
| 2156 | + switch (errno) { |
| 2157 | + case EAGAIN: |
| 2158 | + case EINTR: |
| 2159 | + case ETIMEDOUT: |
| 2018 | 2160 | #ifdef ECONNRESET |
| 2019 | | - if (errno == ECONNRESET) { |
| 2020 | | - return JIM_OK; |
| 2021 | | - } |
| 2161 | + case ECONNRESET: |
| 2022 | 2162 | #endif |
| 2023 | 2163 | #ifdef ECONNABORTED |
| 2024 | | - if (errno == ECONNABORTED) { |
| 2025 | | - return JIM_OK; |
| 2164 | + case ECONNABORTED: |
| 2165 | +#endif |
| 2166 | + return JIM_OK; |
| 2167 | + default: |
| 2168 | + return JIM_ERR; |
| 2026 | 2169 | } |
| 2027 | | -#endif |
| 2028 | | - return JIM_ERR; |
| 2029 | 2170 | } |
| 2030 | 2171 | |
| 2031 | 2172 | static const char *stdio_strerror(struct AioFile *af) |
| 2032 | 2173 | { |
| 2033 | 2174 | return strerror(errno); |
| | @@ -2034,20 +2175,47 @@ |
| 2034 | 2175 | } |
| 2035 | 2176 | |
| 2036 | 2177 | static const JimAioFopsType stdio_fops = { |
| 2037 | 2178 | stdio_writer, |
| 2038 | 2179 | stdio_reader, |
| 2039 | | - stdio_getline, |
| 2040 | 2180 | stdio_error, |
| 2041 | 2181 | stdio_strerror, |
| 2042 | | - NULL |
| 2182 | + NULL, |
| 2043 | 2183 | }; |
| 2044 | 2184 | |
| 2185 | + |
| 2186 | +static void aio_set_nonblocking(AioFile *af, int nb) |
| 2187 | +{ |
| 2188 | +#ifdef O_NDELAY |
| 2189 | + int old = !!(af->flags & AIO_NONBLOCK); |
| 2190 | + if (old != nb) { |
| 2191 | + int fmode = fcntl(af->fd, F_GETFL); |
| 2192 | + if (nb) { |
| 2193 | + fmode |= O_NDELAY; |
| 2194 | + af->flags |= AIO_NONBLOCK; |
| 2195 | + } |
| 2196 | + else { |
| 2197 | + fmode &= ~O_NDELAY; |
| 2198 | + af->flags &= ~AIO_NONBLOCK; |
| 2199 | + } |
| 2200 | + (void)fcntl(af->fd, F_SETFL, fmode); |
| 2201 | + } |
| 2202 | +#endif |
| 2203 | +} |
| 2204 | + |
| 2205 | +static int aio_start_nonblocking(AioFile *af) |
| 2206 | +{ |
| 2207 | + int old = !!(af->flags & AIO_NONBLOCK); |
| 2208 | + if (af->timeout) { |
| 2209 | + aio_set_nonblocking(af, 1); |
| 2210 | + } |
| 2211 | + return old; |
| 2212 | +} |
| 2045 | 2213 | |
| 2046 | 2214 | static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 2047 | | -static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2048 | | - const char *hdlfmt, int family, const char *mode); |
| 2215 | +static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename, |
| 2216 | + const char *hdlfmt, int family, int flags); |
| 2049 | 2217 | |
| 2050 | 2218 | |
| 2051 | 2219 | static const char *JimAioErrorString(AioFile *af) |
| 2052 | 2220 | { |
| 2053 | 2221 | if (af && af->fops) |
| | @@ -2065,26 +2233,171 @@ |
| 2065 | 2233 | } |
| 2066 | 2234 | else { |
| 2067 | 2235 | Jim_SetResultString(interp, JimAioErrorString(af), -1); |
| 2068 | 2236 | } |
| 2069 | 2237 | } |
| 2238 | + |
| 2239 | +static int aio_eof(AioFile *af) |
| 2240 | +{ |
| 2241 | + return af->flags & AIO_EOF; |
| 2242 | +} |
| 2070 | 2243 | |
| 2071 | 2244 | static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) |
| 2072 | 2245 | { |
| 2073 | | - int ret = af->fops->error(af); |
| 2074 | | - if (ret) { |
| 2075 | | - JimAioSetError(interp, af->filename); |
| 2076 | | - } |
| 2077 | | - return ret; |
| 2246 | + int ret = 0; |
| 2247 | + if (!aio_eof(af)) { |
| 2248 | + ret = af->fops->error(af); |
| 2249 | + if (ret) { |
| 2250 | + JimAioSetError(interp, af->filename); |
| 2251 | + } |
| 2252 | + } |
| 2253 | + return ret; |
| 2254 | +} |
| 2255 | + |
| 2256 | +static void aio_consume(Jim_Obj *objPtr, int n) |
| 2257 | +{ |
| 2258 | + assert(objPtr->bytes); |
| 2259 | + assert(n <= objPtr->length); |
| 2260 | + |
| 2261 | + |
| 2262 | + memmove(objPtr->bytes, objPtr->bytes + n, objPtr->length - n + 1); |
| 2263 | + objPtr->length -= n; |
| 2264 | +} |
| 2265 | + |
| 2266 | + |
| 2267 | +static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask); |
| 2268 | + |
| 2269 | +static int aio_flush(Jim_Interp *interp, AioFile *af) |
| 2270 | +{ |
| 2271 | + int len; |
| 2272 | + const char *pt = Jim_GetString(af->writebuf, &len); |
| 2273 | + if (len) { |
| 2274 | + int ret = af->fops->writer(af, pt, len); |
| 2275 | + if (ret > 0) { |
| 2276 | + |
| 2277 | + aio_consume(af->writebuf, ret); |
| 2278 | + } |
| 2279 | + if (ret < 0) { |
| 2280 | + return JimCheckStreamError(interp, af); |
| 2281 | + } |
| 2282 | + if (Jim_Length(af->writebuf)) { |
| 2283 | +#ifdef jim_ext_eventloop |
| 2284 | + void *handler = Jim_FindFileHandler(interp, af->fd, JIM_EVENT_WRITABLE); |
| 2285 | + if (handler == NULL) { |
| 2286 | + Jim_CreateFileHandler(interp, af->fd, JIM_EVENT_WRITABLE, aio_autoflush, af, NULL); |
| 2287 | + return JIM_OK; |
| 2288 | + } |
| 2289 | + else if (handler == af) { |
| 2290 | + |
| 2291 | + return JIM_OK; |
| 2292 | + } |
| 2293 | +#endif |
| 2294 | + |
| 2295 | + Jim_SetResultString(interp, "send buffer is full", -1); |
| 2296 | + return JIM_ERR; |
| 2297 | + } |
| 2298 | + } |
| 2299 | + return JIM_OK; |
| 2300 | +} |
| 2301 | + |
| 2302 | +static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask) |
| 2303 | +{ |
| 2304 | + AioFile *af = clientData; |
| 2305 | + |
| 2306 | + aio_flush(interp, af); |
| 2307 | + if (Jim_Length(af->writebuf) == 0) { |
| 2308 | + |
| 2309 | + return -1; |
| 2310 | + } |
| 2311 | + return 0; |
| 2312 | +} |
| 2313 | + |
| 2314 | +static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size_t buflen, int neededLen) |
| 2315 | +{ |
| 2316 | + if (!af->readbuf) { |
| 2317 | + af->readbuf = Jim_NewStringObj(interp, NULL, 0); |
| 2318 | + } |
| 2319 | + |
| 2320 | + if (neededLen >= 0) { |
| 2321 | + neededLen -= Jim_Length(af->readbuf); |
| 2322 | + if (neededLen <= 0) { |
| 2323 | + return JIM_OK; |
| 2324 | + } |
| 2325 | + } |
| 2326 | + |
| 2327 | + while (neededLen && !aio_eof(af)) { |
| 2328 | + int retval; |
| 2329 | + int readlen; |
| 2330 | + |
| 2331 | + if (neededLen == -1) { |
| 2332 | + readlen = AIO_BUF_LEN; |
| 2333 | + } |
| 2334 | + else { |
| 2335 | + readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); |
| 2336 | + } |
| 2337 | + retval = af->fops->reader(af, buf, readlen, nb); |
| 2338 | + if (retval > 0) { |
| 2339 | + Jim_AppendString(interp, af->readbuf, buf, retval); |
| 2340 | + if (neededLen != -1) { |
| 2341 | + neededLen -= retval; |
| 2342 | + } |
| 2343 | + continue; |
| 2344 | + } |
| 2345 | + if (JimCheckStreamError(interp, af)) { |
| 2346 | + return JIM_ERR; |
| 2347 | + } |
| 2348 | + if (nb || af->timeout) { |
| 2349 | + return JIM_OK; |
| 2350 | + } |
| 2351 | + } |
| 2352 | + |
| 2353 | + return JIM_OK; |
| 2354 | +} |
| 2355 | + |
| 2356 | +static Jim_Obj *aio_read_consume(Jim_Interp *interp, AioFile *af, int neededLen) |
| 2357 | +{ |
| 2358 | + Jim_Obj *objPtr = NULL; |
| 2359 | + |
| 2360 | + if (neededLen < 0 || af->readbuf == NULL || Jim_Length(af->readbuf) <= neededLen) { |
| 2361 | + objPtr = af->readbuf; |
| 2362 | + af->readbuf = NULL; |
| 2363 | + } |
| 2364 | + else if (af->readbuf) { |
| 2365 | + |
| 2366 | + int len; |
| 2367 | + const char *pt = Jim_GetString(af->readbuf, &len); |
| 2368 | + |
| 2369 | + objPtr = Jim_NewStringObj(interp, pt, neededLen); |
| 2370 | + aio_consume(af->readbuf, neededLen); |
| 2371 | + } |
| 2372 | + |
| 2373 | + return objPtr; |
| 2078 | 2374 | } |
| 2079 | 2375 | |
| 2080 | 2376 | static void JimAioDelProc(Jim_Interp *interp, void *privData) |
| 2081 | 2377 | { |
| 2082 | 2378 | AioFile *af = privData; |
| 2083 | 2379 | |
| 2084 | 2380 | JIM_NOTUSED(interp); |
| 2085 | 2381 | |
| 2382 | + |
| 2383 | + aio_flush(interp, af); |
| 2384 | + Jim_DecrRefCount(interp, af->writebuf); |
| 2385 | + |
| 2386 | +#if UNIX_SOCKETS |
| 2387 | + if (af->addr_family == PF_UNIX && (af->flags & AIO_NODELETE) == 0) { |
| 2388 | + |
| 2389 | + Jim_Obj *filenameObj = aio_sockname(interp, af->fd); |
| 2390 | + if (filenameObj) { |
| 2391 | + if (Jim_Length(filenameObj)) { |
| 2392 | + remove(Jim_String(filenameObj)); |
| 2393 | + } |
| 2394 | + Jim_FreeNewObj(interp, filenameObj); |
| 2395 | + } |
| 2396 | + } |
| 2397 | +#endif |
| 2398 | + |
| 2086 | 2399 | Jim_DecrRefCount(interp, af->filename); |
| 2087 | 2400 | |
| 2088 | 2401 | #ifdef jim_ext_eventloop |
| 2089 | 2402 | |
| 2090 | 2403 | Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| | @@ -2093,144 +2406,180 @@ |
| 2093 | 2406 | #if defined(JIM_SSL) |
| 2094 | 2407 | if (af->ssl != NULL) { |
| 2095 | 2408 | SSL_free(af->ssl); |
| 2096 | 2409 | } |
| 2097 | 2410 | #endif |
| 2098 | | - if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 2099 | | - fclose(af->fp); |
| 2411 | + if (!(af->flags & AIO_KEEPOPEN)) { |
| 2412 | + close(af->fd); |
| 2413 | + } |
| 2414 | + if (af->readbuf) { |
| 2415 | + Jim_FreeNewObj(interp, af->readbuf); |
| 2100 | 2416 | } |
| 2101 | 2417 | |
| 2102 | 2418 | Jim_Free(af); |
| 2103 | 2419 | } |
| 2104 | 2420 | |
| 2105 | 2421 | static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2106 | 2422 | { |
| 2107 | 2423 | AioFile *af = Jim_CmdPrivData(interp); |
| 2108 | | - char buf[AIO_BUF_LEN]; |
| 2109 | | - Jim_Obj *objPtr; |
| 2110 | 2424 | int nonewline = 0; |
| 2111 | 2425 | jim_wide neededLen = -1; |
| 2426 | + static const char * const options[] = { "-pending", "-nonewline", NULL }; |
| 2427 | + enum { OPT_PENDING, OPT_NONEWLINE }; |
| 2428 | + int option; |
| 2429 | + int nb; |
| 2430 | + Jim_Obj *objPtr; |
| 2431 | + char buf[AIO_BUF_LEN]; |
| 2112 | 2432 | |
| 2113 | | - if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { |
| 2114 | | - nonewline = 1; |
| 2115 | | - argv++; |
| 2433 | + if (argc) { |
| 2434 | + if (*Jim_String(argv[0]) == '-') { |
| 2435 | + if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2436 | + return JIM_ERR; |
| 2437 | + } |
| 2438 | + switch (option) { |
| 2439 | + case OPT_PENDING: |
| 2440 | + |
| 2441 | + break; |
| 2442 | + case OPT_NONEWLINE: |
| 2443 | + nonewline++; |
| 2444 | + break; |
| 2445 | + } |
| 2446 | + } |
| 2447 | + else { |
| 2448 | + if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK) |
| 2449 | + return JIM_ERR; |
| 2450 | + if (neededLen < 0) { |
| 2451 | + Jim_SetResultString(interp, "invalid parameter: negative len", -1); |
| 2452 | + return JIM_ERR; |
| 2453 | + } |
| 2454 | + } |
| 2116 | 2455 | argc--; |
| 2117 | | - } |
| 2118 | | - if (argc == 1) { |
| 2119 | | - if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK) |
| 2120 | | - return JIM_ERR; |
| 2121 | | - if (neededLen < 0) { |
| 2122 | | - Jim_SetResultString(interp, "invalid parameter: negative len", -1); |
| 2123 | | - return JIM_ERR; |
| 2124 | | - } |
| 2125 | | - } |
| 2126 | | - else if (argc) { |
| 2456 | + argv++; |
| 2457 | + } |
| 2458 | + if (argc) { |
| 2127 | 2459 | return -1; |
| 2128 | 2460 | } |
| 2129 | | - objPtr = Jim_NewStringObj(interp, NULL, 0); |
| 2130 | | - while (neededLen != 0) { |
| 2131 | | - int retval; |
| 2132 | | - int readlen; |
| 2133 | | - |
| 2134 | | - if (neededLen == -1) { |
| 2135 | | - readlen = AIO_BUF_LEN; |
| 2136 | | - } |
| 2137 | | - else { |
| 2138 | | - readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); |
| 2139 | | - } |
| 2140 | | - retval = af->fops->reader(af, buf, readlen); |
| 2141 | | - if (retval > 0) { |
| 2142 | | - Jim_AppendString(interp, objPtr, buf, retval); |
| 2143 | | - if (neededLen != -1) { |
| 2144 | | - neededLen -= retval; |
| 2145 | | - } |
| 2146 | | - } |
| 2147 | | - if (retval != readlen) |
| 2148 | | - break; |
| 2149 | | - } |
| 2150 | | - |
| 2151 | | - if (JimCheckStreamError(interp, af)) { |
| 2152 | | - Jim_FreeNewObj(interp, objPtr); |
| 2153 | | - return JIM_ERR; |
| 2154 | | - } |
| 2155 | | - if (nonewline) { |
| 2156 | | - int len; |
| 2157 | | - const char *s = Jim_GetString(objPtr, &len); |
| 2158 | | - |
| 2159 | | - if (len > 0 && s[len - 1] == '\n') { |
| 2160 | | - objPtr->length--; |
| 2161 | | - objPtr->bytes[objPtr->length] = '\0'; |
| 2162 | | - } |
| 2163 | | - } |
| 2164 | | - Jim_SetResult(interp, objPtr); |
| 2461 | + |
| 2462 | + |
| 2463 | + nb = aio_start_nonblocking(af); |
| 2464 | + |
| 2465 | + if (aio_read_len(interp, af, nb, buf, sizeof(buf), neededLen) != JIM_OK) { |
| 2466 | + aio_set_nonblocking(af, nb); |
| 2467 | + return JIM_ERR; |
| 2468 | + } |
| 2469 | + objPtr = aio_read_consume(interp, af, neededLen); |
| 2470 | + |
| 2471 | + aio_set_nonblocking(af, nb); |
| 2472 | + |
| 2473 | + if (objPtr) { |
| 2474 | + if (nonewline) { |
| 2475 | + int len; |
| 2476 | + const char *s = Jim_GetString(objPtr, &len); |
| 2477 | + |
| 2478 | + if (len > 0 && s[len - 1] == '\n') { |
| 2479 | + objPtr->length--; |
| 2480 | + objPtr->bytes[objPtr->length] = '\0'; |
| 2481 | + } |
| 2482 | + } |
| 2483 | + Jim_SetResult(interp, objPtr); |
| 2484 | + } |
| 2485 | + else { |
| 2486 | + Jim_SetEmptyResult(interp); |
| 2487 | + } |
| 2165 | 2488 | return JIM_OK; |
| 2166 | 2489 | } |
| 2167 | 2490 | |
| 2168 | | -AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command) |
| 2491 | +int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2169 | 2492 | { |
| 2170 | 2493 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2171 | 2494 | |
| 2172 | 2495 | |
| 2173 | 2496 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2174 | | - return (AioFile *) cmdPtr->u.native.privData; |
| 2497 | + return ((AioFile *) cmdPtr->u.native.privData)->fd; |
| 2175 | 2498 | } |
| 2176 | 2499 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2177 | | - return NULL; |
| 2178 | | -} |
| 2179 | | - |
| 2180 | | -FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) |
| 2181 | | -{ |
| 2182 | | - AioFile *af; |
| 2183 | | - |
| 2184 | | - af = Jim_AioFile(interp, command); |
| 2185 | | - if (af == NULL) { |
| 2186 | | - return NULL; |
| 2187 | | - } |
| 2188 | | - |
| 2189 | | - return af->fp; |
| 2500 | + return -1; |
| 2190 | 2501 | } |
| 2191 | 2502 | |
| 2192 | 2503 | static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2193 | 2504 | { |
| 2194 | 2505 | AioFile *af = Jim_CmdPrivData(interp); |
| 2195 | 2506 | |
| 2196 | | - fflush(af->fp); |
| 2197 | | - Jim_SetResultInt(interp, fileno(af->fp)); |
| 2507 | + |
| 2508 | + aio_flush(interp, af); |
| 2509 | + |
| 2510 | + Jim_SetResultInt(interp, af->fd); |
| 2198 | 2511 | |
| 2199 | 2512 | return JIM_OK; |
| 2200 | 2513 | } |
| 2201 | 2514 | |
| 2202 | 2515 | static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2203 | 2516 | { |
| 2204 | 2517 | AioFile *af = Jim_CmdPrivData(interp); |
| 2205 | 2518 | jim_wide count = 0; |
| 2206 | 2519 | jim_wide maxlen = JIM_WIDE_MAX; |
| 2207 | | - AioFile *outf = Jim_AioFile(interp, argv[0]); |
| 2208 | 2520 | |
| 2209 | | - if (outf == NULL) { |
| 2210 | | - return JIM_ERR; |
| 2211 | | - } |
| 2521 | + char buf[AIO_BUF_LEN]; |
| 2522 | + |
| 2523 | + char *bufp = buf; |
| 2524 | + int buflen = sizeof(buf); |
| 2525 | + int ok = 1; |
| 2526 | + Jim_Obj *objv[4]; |
| 2212 | 2527 | |
| 2213 | 2528 | if (argc == 2) { |
| 2214 | 2529 | if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) { |
| 2215 | 2530 | return JIM_ERR; |
| 2216 | 2531 | } |
| 2217 | 2532 | } |
| 2218 | 2533 | |
| 2534 | + objv[0] = argv[0]; |
| 2535 | + objv[1] = Jim_NewStringObj(interp, "flush", -1); |
| 2536 | + if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) { |
| 2537 | + Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", argv[0]); |
| 2538 | + return JIM_ERR; |
| 2539 | + } |
| 2540 | + |
| 2541 | + |
| 2542 | + objv[0] = argv[0]; |
| 2543 | + objv[1] = Jim_NewStringObj(interp, "puts", -1); |
| 2544 | + objv[2] = Jim_NewStringObj(interp, "-nonewline", -1); |
| 2545 | + Jim_IncrRefCount(objv[1]); |
| 2546 | + Jim_IncrRefCount(objv[2]); |
| 2547 | + |
| 2219 | 2548 | while (count < maxlen) { |
| 2220 | | - char ch; |
| 2221 | | - |
| 2222 | | - if (af->fops->reader(af, &ch, 1) != 1) { |
| 2549 | + jim_wide len = maxlen - count; |
| 2550 | + if (len > buflen) { |
| 2551 | + len = buflen; |
| 2552 | + } |
| 2553 | + if (aio_read_len(interp, af, 0, bufp, buflen, len) != JIM_OK) { |
| 2554 | + ok = 0; |
| 2223 | 2555 | break; |
| 2224 | 2556 | } |
| 2225 | | - if (outf->fops->writer(outf, &ch, 1) != 1) { |
| 2557 | + objv[3] = aio_read_consume(interp, af, len); |
| 2558 | + count += Jim_Length(objv[3]); |
| 2559 | + if (Jim_EvalObjVector(interp, 4, objv) != JIM_OK) { |
| 2560 | + ok = 0; |
| 2226 | 2561 | break; |
| 2227 | 2562 | } |
| 2228 | | - count++; |
| 2563 | + if (aio_eof(af)) { |
| 2564 | + break; |
| 2565 | + } |
| 2566 | + if (count >= 16384 && bufp == buf) { |
| 2567 | + |
| 2568 | + buflen = 65536; |
| 2569 | + bufp = Jim_Alloc(buflen); |
| 2570 | + } |
| 2229 | 2571 | } |
| 2230 | 2572 | |
| 2231 | | - if (JimCheckStreamError(interp, af) || JimCheckStreamError(interp, outf)) { |
| 2573 | + if (bufp != buf) { |
| 2574 | + Jim_Free(bufp); |
| 2575 | + } |
| 2576 | + |
| 2577 | + Jim_DecrRefCount(interp, objv[1]); |
| 2578 | + Jim_DecrRefCount(interp, objv[2]); |
| 2579 | + |
| 2580 | + if (!ok) { |
| 2232 | 2581 | return JIM_ERR; |
| 2233 | 2582 | } |
| 2234 | 2583 | |
| 2235 | 2584 | Jim_SetResultInt(interp, count); |
| 2236 | 2585 | |
| | @@ -2239,42 +2588,58 @@ |
| 2239 | 2588 | |
| 2240 | 2589 | static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2241 | 2590 | { |
| 2242 | 2591 | AioFile *af = Jim_CmdPrivData(interp); |
| 2243 | 2592 | char buf[AIO_BUF_LEN]; |
| 2244 | | - Jim_Obj *objPtr; |
| 2593 | + Jim_Obj *objPtr = NULL; |
| 2245 | 2594 | int len; |
| 2595 | + int nb; |
| 2596 | + char *nl = NULL; |
| 2597 | + int offset = 0; |
| 2246 | 2598 | |
| 2247 | 2599 | errno = 0; |
| 2248 | 2600 | |
| 2249 | | - objPtr = Jim_NewStringObj(interp, NULL, 0); |
| 2250 | | - while (1) { |
| 2251 | | - buf[AIO_BUF_LEN - 1] = '_'; |
| 2252 | | - |
| 2253 | | - if (af->fops->getline(af, buf, AIO_BUF_LEN) == NULL) |
| 2254 | | - break; |
| 2255 | | - |
| 2256 | | - if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') { |
| 2257 | | - Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1); |
| 2258 | | - } |
| 2259 | | - else { |
| 2260 | | - len = strlen(buf); |
| 2261 | | - |
| 2262 | | - if (len && (buf[len - 1] == '\n')) { |
| 2263 | | - |
| 2264 | | - len--; |
| 2265 | | - } |
| 2266 | | - |
| 2267 | | - Jim_AppendString(interp, objPtr, buf, len); |
| 2268 | | - break; |
| 2269 | | - } |
| 2270 | | - } |
| 2271 | | - |
| 2272 | | - if (JimCheckStreamError(interp, af)) { |
| 2273 | | - |
| 2274 | | - Jim_FreeNewObj(interp, objPtr); |
| 2275 | | - return JIM_ERR; |
| 2601 | + |
| 2602 | + nb = aio_start_nonblocking(af); |
| 2603 | + |
| 2604 | + if (!af->readbuf) { |
| 2605 | + af->readbuf = Jim_NewStringObj(interp, NULL, 0); |
| 2606 | + } |
| 2607 | + |
| 2608 | + while (!aio_eof(af)) { |
| 2609 | + const char *pt = Jim_GetString(af->readbuf, &len); |
| 2610 | + nl = memchr(pt + offset, '\n', len - offset); |
| 2611 | + if (nl) { |
| 2612 | + |
| 2613 | + objPtr = Jim_NewStringObj(interp, pt, nl - pt); |
| 2614 | + |
| 2615 | + aio_consume(af->readbuf, nl - pt + 1); |
| 2616 | + break; |
| 2617 | + } |
| 2618 | + |
| 2619 | + offset = len; |
| 2620 | + len = af->fops->reader(af, buf, AIO_BUF_LEN, nb); |
| 2621 | + if (len <= 0) { |
| 2622 | + if (nb || af->timeout) { |
| 2623 | + |
| 2624 | + break; |
| 2625 | + } |
| 2626 | + } |
| 2627 | + else { |
| 2628 | + Jim_AppendString(interp, af->readbuf, buf, len); |
| 2629 | + } |
| 2630 | + } |
| 2631 | + |
| 2632 | + aio_set_nonblocking(af, nb); |
| 2633 | + |
| 2634 | + if (!nl && aio_eof(af)) { |
| 2635 | + |
| 2636 | + objPtr = af->readbuf; |
| 2637 | + af->readbuf = NULL; |
| 2638 | + } |
| 2639 | + else if (!objPtr) { |
| 2640 | + objPtr = Jim_NewStringObj(interp, NULL, 0); |
| 2276 | 2641 | } |
| 2277 | 2642 | |
| 2278 | 2643 | if (argc) { |
| 2279 | 2644 | if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) { |
| 2280 | 2645 | Jim_FreeNewObj(interp, objPtr); |
| | @@ -2281,11 +2646,11 @@ |
| 2281 | 2646 | return JIM_ERR; |
| 2282 | 2647 | } |
| 2283 | 2648 | |
| 2284 | 2649 | len = Jim_Length(objPtr); |
| 2285 | 2650 | |
| 2286 | | - if (len == 0 && feof(af->fp)) { |
| 2651 | + if (!nl && len == 0) { |
| 2287 | 2652 | |
| 2288 | 2653 | len = -1; |
| 2289 | 2654 | } |
| 2290 | 2655 | Jim_SetResultInt(interp, len); |
| 2291 | 2656 | } |
| | @@ -2299,36 +2664,62 @@ |
| 2299 | 2664 | { |
| 2300 | 2665 | AioFile *af = Jim_CmdPrivData(interp); |
| 2301 | 2666 | int wlen; |
| 2302 | 2667 | const char *wdata; |
| 2303 | 2668 | Jim_Obj *strObj; |
| 2669 | + int wnow = 0; |
| 2670 | + int nl = 1; |
| 2304 | 2671 | |
| 2305 | 2672 | if (argc == 2) { |
| 2306 | 2673 | if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { |
| 2307 | 2674 | return -1; |
| 2308 | 2675 | } |
| 2309 | 2676 | strObj = argv[1]; |
| 2677 | + nl = 0; |
| 2310 | 2678 | } |
| 2311 | 2679 | else { |
| 2312 | 2680 | strObj = argv[0]; |
| 2313 | 2681 | } |
| 2314 | 2682 | |
| 2315 | | - wdata = Jim_GetString(strObj, &wlen); |
| 2316 | | - if (af->fops->writer(af, wdata, wlen) == wlen) { |
| 2317 | | - if (argc == 2 || af->fops->writer(af, "\n", 1) == 1) { |
| 2318 | | - return JIM_OK; |
| 2319 | | - } |
| 2320 | | - } |
| 2321 | | - JimAioSetError(interp, af->filename); |
| 2322 | | - return JIM_ERR; |
| 2683 | + Jim_AppendObj(interp, af->writebuf, strObj); |
| 2684 | + if (nl) { |
| 2685 | + Jim_AppendString(interp, af->writebuf, "\n", 1); |
| 2686 | + } |
| 2687 | + |
| 2688 | + |
| 2689 | + wdata = Jim_GetString(af->writebuf, &wlen); |
| 2690 | + switch (af->wbuft) { |
| 2691 | + case WBUF_OPT_NONE: |
| 2692 | + |
| 2693 | + wnow = 1; |
| 2694 | + break; |
| 2695 | + |
| 2696 | + case WBUF_OPT_LINE: |
| 2697 | + |
| 2698 | + if (nl || memchr(wdata, '\n', wlen) != NULL) { |
| 2699 | + wnow = 1; |
| 2700 | + } |
| 2701 | + break; |
| 2702 | + |
| 2703 | + case WBUF_OPT_FULL: |
| 2704 | + if (wlen >= AIO_WBUF_FULL_SIZE) { |
| 2705 | + wnow = 1; |
| 2706 | + } |
| 2707 | + break; |
| 2708 | + } |
| 2709 | + |
| 2710 | + if (wnow) { |
| 2711 | + return aio_flush(interp, af); |
| 2712 | + } |
| 2713 | + return JIM_OK; |
| 2323 | 2714 | } |
| 2324 | 2715 | |
| 2325 | 2716 | static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2326 | 2717 | { |
| 2327 | 2718 | #ifdef HAVE_ISATTY |
| 2328 | 2719 | AioFile *af = Jim_CmdPrivData(interp); |
| 2329 | | - Jim_SetResultInt(interp, isatty(fileno(af->fp))); |
| 2720 | + Jim_SetResultInt(interp, isatty(af->fd)); |
| 2330 | 2721 | #else |
| 2331 | 2722 | Jim_SetResultInt(interp, 0); |
| 2332 | 2723 | #endif |
| 2333 | 2724 | |
| 2334 | 2725 | return JIM_OK; |
| | @@ -2336,49 +2727,62 @@ |
| 2336 | 2727 | |
| 2337 | 2728 | |
| 2338 | 2729 | static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2339 | 2730 | { |
| 2340 | 2731 | AioFile *af = Jim_CmdPrivData(interp); |
| 2341 | | - |
| 2342 | | - if (fflush(af->fp) == EOF) { |
| 2343 | | - JimAioSetError(interp, af->filename); |
| 2344 | | - return JIM_ERR; |
| 2345 | | - } |
| 2346 | | - return JIM_OK; |
| 2732 | + return aio_flush(interp, af); |
| 2347 | 2733 | } |
| 2348 | 2734 | |
| 2349 | 2735 | static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2350 | 2736 | { |
| 2351 | 2737 | AioFile *af = Jim_CmdPrivData(interp); |
| 2352 | 2738 | |
| 2353 | | - Jim_SetResultInt(interp, feof(af->fp)); |
| 2739 | + Jim_SetResultInt(interp, !!aio_eof(af)); |
| 2354 | 2740 | return JIM_OK; |
| 2355 | 2741 | } |
| 2356 | 2742 | |
| 2357 | 2743 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2358 | 2744 | { |
| 2745 | + AioFile *af = Jim_CmdPrivData(interp); |
| 2359 | 2746 | if (argc == 3) { |
| 2360 | | -#if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN) |
| 2361 | | - static const char * const options[] = { "r", "w", NULL }; |
| 2362 | | - enum { OPT_R, OPT_W, }; |
| 2363 | | - int option; |
| 2364 | | - AioFile *af = Jim_CmdPrivData(interp); |
| 2747 | + int option = -1; |
| 2748 | +#if defined(HAVE_SOCKETS) |
| 2749 | + static const char * const options[] = { "r", "w", "-nodelete", NULL }; |
| 2750 | + enum { OPT_R, OPT_W, OPT_NODELETE }; |
| 2365 | 2751 | |
| 2366 | 2752 | if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2367 | 2753 | return JIM_ERR; |
| 2368 | 2754 | } |
| 2369 | | - if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { |
| 2370 | | - return JIM_OK; |
| 2371 | | - } |
| 2372 | | - JimAioSetError(interp, NULL); |
| 2373 | | -#else |
| 2374 | | - Jim_SetResultString(interp, "async close not supported", -1); |
| 2375 | | -#endif |
| 2376 | | - return JIM_ERR; |
| 2755 | +#endif |
| 2756 | + switch (option) { |
| 2757 | +#if defined(HAVE_SHUTDOWN) |
| 2758 | + case OPT_R: |
| 2759 | + case OPT_W: |
| 2760 | + if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { |
| 2761 | + return JIM_OK; |
| 2762 | + } |
| 2763 | + JimAioSetError(interp, NULL); |
| 2764 | + return JIM_ERR; |
| 2765 | +#endif |
| 2766 | +#if UNIX_SOCKETS |
| 2767 | + case OPT_NODELETE: |
| 2768 | + if (af->addr_family == PF_UNIX) { |
| 2769 | + af->flags |= AIO_NODELETE; |
| 2770 | + break; |
| 2771 | + } |
| 2772 | + |
| 2773 | +#endif |
| 2774 | + default: |
| 2775 | + Jim_SetResultString(interp, "not supported", -1); |
| 2776 | + return JIM_ERR; |
| 2777 | + } |
| 2377 | 2778 | } |
| 2378 | 2779 | |
| 2379 | | - return Jim_DeleteCommand(interp, Jim_String(argv[0])); |
| 2780 | + |
| 2781 | + af->flags &= ~AIO_KEEPOPEN; |
| 2782 | + |
| 2783 | + return Jim_DeleteCommand(interp, argv[0]); |
| 2380 | 2784 | } |
| 2381 | 2785 | |
| 2382 | 2786 | static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2383 | 2787 | { |
| 2384 | 2788 | AioFile *af = Jim_CmdPrivData(interp); |
| | @@ -2397,22 +2801,31 @@ |
| 2397 | 2801 | } |
| 2398 | 2802 | } |
| 2399 | 2803 | if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) { |
| 2400 | 2804 | return JIM_ERR; |
| 2401 | 2805 | } |
| 2402 | | - if (fseeko(af->fp, offset, orig) == -1) { |
| 2806 | + if (orig != SEEK_CUR || offset != 0) { |
| 2807 | + |
| 2808 | + aio_flush(interp, af); |
| 2809 | + } |
| 2810 | + if (Jim_Lseek(af->fd, offset, orig) == -1) { |
| 2403 | 2811 | JimAioSetError(interp, af->filename); |
| 2404 | 2812 | return JIM_ERR; |
| 2405 | 2813 | } |
| 2814 | + if (af->readbuf) { |
| 2815 | + Jim_FreeNewObj(interp, af->readbuf); |
| 2816 | + af->readbuf = NULL; |
| 2817 | + } |
| 2818 | + af->flags &= ~AIO_EOF; |
| 2406 | 2819 | return JIM_OK; |
| 2407 | 2820 | } |
| 2408 | 2821 | |
| 2409 | 2822 | static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2410 | 2823 | { |
| 2411 | 2824 | AioFile *af = Jim_CmdPrivData(interp); |
| 2412 | 2825 | |
| 2413 | | - Jim_SetResultInt(interp, ftello(af->fp)); |
| 2826 | + Jim_SetResultInt(interp, Jim_Lseek(af->fd, 0, SEEK_CUR)); |
| 2414 | 2827 | return JIM_OK; |
| 2415 | 2828 | } |
| 2416 | 2829 | |
| 2417 | 2830 | static int aio_cmd_filename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2418 | 2831 | { |
| | @@ -2425,27 +2838,19 @@ |
| 2425 | 2838 | #ifdef O_NDELAY |
| 2426 | 2839 | static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2427 | 2840 | { |
| 2428 | 2841 | AioFile *af = Jim_CmdPrivData(interp); |
| 2429 | 2842 | |
| 2430 | | - int fmode = fcntl(af->fd, F_GETFL); |
| 2431 | | - |
| 2432 | 2843 | if (argc) { |
| 2433 | 2844 | long nb; |
| 2434 | 2845 | |
| 2435 | 2846 | if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { |
| 2436 | 2847 | return JIM_ERR; |
| 2437 | 2848 | } |
| 2438 | | - if (nb) { |
| 2439 | | - fmode |= O_NDELAY; |
| 2440 | | - } |
| 2441 | | - else { |
| 2442 | | - fmode &= ~O_NDELAY; |
| 2443 | | - } |
| 2444 | | - (void)fcntl(af->fd, F_SETFL, fmode); |
| 2445 | | - } |
| 2446 | | - Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2849 | + aio_set_nonblocking(af, nb); |
| 2850 | + } |
| 2851 | + Jim_SetResultInt(interp, (af->flags & AIO_NONBLOCK) ? 1 : 0); |
| 2447 | 2852 | return JIM_OK; |
| 2448 | 2853 | } |
| 2449 | 2854 | #endif |
| 2450 | 2855 | |
| 2451 | 2856 | |
| | @@ -2452,11 +2857,13 @@ |
| 2452 | 2857 | #ifdef HAVE_FSYNC |
| 2453 | 2858 | static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2454 | 2859 | { |
| 2455 | 2860 | AioFile *af = Jim_CmdPrivData(interp); |
| 2456 | 2861 | |
| 2457 | | - fflush(af->fp); |
| 2862 | + if (aio_flush(interp, af) != JIM_OK) { |
| 2863 | + return JIM_ERR; |
| 2864 | + } |
| 2458 | 2865 | fsync(af->fd); |
| 2459 | 2866 | return JIM_OK; |
| 2460 | 2867 | } |
| 2461 | 2868 | #endif |
| 2462 | 2869 | |
| | @@ -2468,111 +2875,105 @@ |
| 2468 | 2875 | "none", |
| 2469 | 2876 | "line", |
| 2470 | 2877 | "full", |
| 2471 | 2878 | NULL |
| 2472 | 2879 | }; |
| 2473 | | - enum |
| 2474 | | - { |
| 2475 | | - OPT_NONE, |
| 2476 | | - OPT_LINE, |
| 2477 | | - OPT_FULL, |
| 2478 | | - }; |
| 2479 | | - int option; |
| 2480 | | - |
| 2481 | | - if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2880 | + |
| 2881 | + if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) { |
| 2482 | 2882 | return JIM_ERR; |
| 2483 | 2883 | } |
| 2484 | | - switch (option) { |
| 2485 | | - case OPT_NONE: |
| 2486 | | - setvbuf(af->fp, NULL, _IONBF, 0); |
| 2487 | | - break; |
| 2488 | | - case OPT_LINE: |
| 2489 | | - setvbuf(af->fp, NULL, _IOLBF, BUFSIZ); |
| 2490 | | - break; |
| 2491 | | - case OPT_FULL: |
| 2492 | | - setvbuf(af->fp, NULL, _IOFBF, BUFSIZ); |
| 2493 | | - break; |
| 2494 | | - } |
| 2495 | | - return JIM_OK; |
| 2884 | + |
| 2885 | + if (af->wbuft == WBUF_OPT_NONE) { |
| 2886 | + return aio_flush(interp, af); |
| 2887 | + } |
| 2888 | + |
| 2889 | + return JIM_OK; |
| 2890 | +} |
| 2891 | + |
| 2892 | +static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2893 | +{ |
| 2894 | +#ifdef HAVE_SELECT |
| 2895 | + AioFile *af = Jim_CmdPrivData(interp); |
| 2896 | + if (argc == 1) { |
| 2897 | + if (Jim_GetLong(interp, argv[0], &af->timeout) != JIM_OK) { |
| 2898 | + return JIM_ERR; |
| 2899 | + } |
| 2900 | + } |
| 2901 | + Jim_SetResultInt(interp, af->timeout); |
| 2902 | + return JIM_OK; |
| 2903 | +#else |
| 2904 | + Jim_SetResultString(interp, "timeout not supported", -1); |
| 2905 | + return JIM_ERR; |
| 2906 | +#endif |
| 2496 | 2907 | } |
| 2497 | 2908 | |
| 2498 | 2909 | #ifdef jim_ext_eventloop |
| 2499 | | -static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData) |
| 2500 | | -{ |
| 2501 | | - Jim_Obj **objPtrPtr = clientData; |
| 2502 | | - |
| 2503 | | - Jim_DecrRefCount(interp, *objPtrPtr); |
| 2504 | | - *objPtrPtr = NULL; |
| 2505 | | -} |
| 2506 | | - |
| 2507 | | -static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask) |
| 2508 | | -{ |
| 2509 | | - Jim_Obj **objPtrPtr = clientData; |
| 2510 | | - |
| 2511 | | - return Jim_EvalObjBackground(interp, *objPtrPtr); |
| 2512 | | -} |
| 2513 | | - |
| 2514 | | -static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, |
| 2910 | +static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, |
| 2515 | 2911 | int argc, Jim_Obj * const *argv) |
| 2516 | 2912 | { |
| 2517 | 2913 | if (argc == 0) { |
| 2518 | 2914 | |
| 2519 | | - if (*scriptHandlerObj) { |
| 2520 | | - Jim_SetResult(interp, *scriptHandlerObj); |
| 2915 | + Jim_Obj *objPtr = Jim_FindFileHandler(interp, af->fd, mask); |
| 2916 | + if (objPtr) { |
| 2917 | + Jim_SetResult(interp, objPtr); |
| 2521 | 2918 | } |
| 2522 | 2919 | return JIM_OK; |
| 2523 | 2920 | } |
| 2524 | 2921 | |
| 2525 | | - if (*scriptHandlerObj) { |
| 2526 | | - |
| 2527 | | - Jim_DeleteFileHandler(interp, af->fd, mask); |
| 2528 | | - } |
| 2529 | | - |
| 2530 | | - |
| 2531 | | - if (Jim_Length(argv[0]) == 0) { |
| 2532 | | - |
| 2533 | | - return JIM_OK; |
| 2534 | | - } |
| 2535 | | - |
| 2536 | | - |
| 2537 | | - Jim_IncrRefCount(argv[0]); |
| 2538 | | - *scriptHandlerObj = argv[0]; |
| 2539 | | - |
| 2540 | | - Jim_CreateFileHandler(interp, af->fd, mask, |
| 2541 | | - JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); |
| 2922 | + |
| 2923 | + Jim_DeleteFileHandler(interp, af->fd, mask); |
| 2924 | + |
| 2925 | + |
| 2926 | + if (Jim_Length(argv[0])) { |
| 2927 | + Jim_CreateScriptFileHandler(interp, af->fd, mask, argv[0]); |
| 2928 | + } |
| 2542 | 2929 | |
| 2543 | 2930 | return JIM_OK; |
| 2544 | 2931 | } |
| 2545 | 2932 | |
| 2546 | 2933 | static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2547 | 2934 | { |
| 2548 | 2935 | AioFile *af = Jim_CmdPrivData(interp); |
| 2549 | 2936 | |
| 2550 | | - return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv); |
| 2937 | + return aio_eventinfo(interp, af, JIM_EVENT_READABLE, argc, argv); |
| 2551 | 2938 | } |
| 2552 | 2939 | |
| 2553 | 2940 | static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2554 | 2941 | { |
| 2555 | 2942 | AioFile *af = Jim_CmdPrivData(interp); |
| 2556 | 2943 | |
| 2557 | | - return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv); |
| 2944 | + return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, argc, argv); |
| 2558 | 2945 | } |
| 2559 | 2946 | |
| 2560 | 2947 | static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2561 | 2948 | { |
| 2562 | 2949 | AioFile *af = Jim_CmdPrivData(interp); |
| 2563 | 2950 | |
| 2564 | | - return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2951 | + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, argc, argv); |
| 2952 | +} |
| 2953 | +#endif |
| 2954 | + |
| 2955 | +#if defined(jim_ext_file) && defined(Jim_FileStat) |
| 2956 | +static int aio_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2957 | +{ |
| 2958 | + jim_stat_t sb; |
| 2959 | + AioFile *af = Jim_CmdPrivData(interp); |
| 2960 | + |
| 2961 | + if (Jim_FileStat(af->fd, &sb) == -1) { |
| 2962 | + JimAioSetError(interp, NULL); |
| 2963 | + return JIM_ERR; |
| 2964 | + } |
| 2965 | + return Jim_FileStoreStatData(interp, argc == 0 ? NULL : argv[0], &sb); |
| 2565 | 2966 | } |
| 2566 | 2967 | #endif |
| 2567 | 2968 | |
| 2568 | 2969 | |
| 2569 | 2970 | |
| 2570 | 2971 | |
| 2571 | 2972 | static const jim_subcmd_type aio_command_table[] = { |
| 2572 | 2973 | { "read", |
| 2573 | | - "?-nonewline? ?len?", |
| 2974 | + "?-nonewline|len?", |
| 2574 | 2975 | aio_cmd_read, |
| 2575 | 2976 | 0, |
| 2576 | 2977 | 2, |
| 2577 | 2978 | |
| 2578 | 2979 | }, |
| | @@ -2677,10 +3078,19 @@ |
| 2677 | 3078 | aio_cmd_buffering, |
| 2678 | 3079 | 1, |
| 2679 | 3080 | 1, |
| 2680 | 3081 | |
| 2681 | 3082 | }, |
| 3083 | +#if defined(jim_ext_file) && defined(Jim_FileStat) |
| 3084 | + { "stat", |
| 3085 | + "?var?", |
| 3086 | + aio_cmd_stat, |
| 3087 | + 0, |
| 3088 | + 1, |
| 3089 | + |
| 3090 | + }, |
| 3091 | +#endif |
| 2682 | 3092 | #ifdef jim_ext_eventloop |
| 2683 | 3093 | { "readable", |
| 2684 | 3094 | "?readable-script?", |
| 2685 | 3095 | aio_cmd_readable, |
| 2686 | 3096 | 0, |
| | @@ -2698,126 +3108,235 @@ |
| 2698 | 3108 | "?exception-script?", |
| 2699 | 3109 | aio_cmd_onexception, |
| 2700 | 3110 | 0, |
| 2701 | 3111 | 1, |
| 2702 | 3112 | |
| 3113 | + }, |
| 3114 | + { "timeout", |
| 3115 | + "?ms?", |
| 3116 | + aio_cmd_timeout, |
| 3117 | + 0, |
| 3118 | + 1, |
| 3119 | + |
| 2703 | 3120 | }, |
| 2704 | 3121 | #endif |
| 2705 | 3122 | { NULL } |
| 2706 | 3123 | }; |
| 2707 | 3124 | |
| 2708 | 3125 | static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2709 | 3126 | { |
| 2710 | 3127 | return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv); |
| 2711 | 3128 | } |
| 3129 | + |
| 3130 | +static int parse_posix_open_mode(Jim_Interp *interp, Jim_Obj *modeObj) |
| 3131 | +{ |
| 3132 | + int i; |
| 3133 | + int flags = 0; |
| 3134 | + #ifndef O_NOCTTY |
| 3135 | + |
| 3136 | + #define O_NOCTTY 0 |
| 3137 | + #endif |
| 3138 | + static const char * const modetypes[] = { |
| 3139 | + "RDONLY", "WRONLY", "RDWR", "APPEND", "BINARY", "CREAT", "EXCL", "NOCTTY", "TRUNC", NULL |
| 3140 | + }; |
| 3141 | + static const int modeflags[] = { |
| 3142 | + O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, 0, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, |
| 3143 | + }; |
| 3144 | + |
| 3145 | + for (i = 0; i < Jim_ListLength(interp, modeObj); i++) { |
| 3146 | + int opt; |
| 3147 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, modeObj, i); |
| 3148 | + if (Jim_GetEnum(interp, objPtr, modetypes, &opt, "access mode", JIM_ERRMSG) != JIM_OK) { |
| 3149 | + return -1; |
| 3150 | + } |
| 3151 | + flags |= modeflags[opt]; |
| 3152 | + } |
| 3153 | + return flags; |
| 3154 | +} |
| 3155 | + |
| 3156 | +static int parse_open_mode(Jim_Interp *interp, Jim_Obj *filenameObj, Jim_Obj *modeObj) |
| 3157 | +{ |
| 3158 | + |
| 3159 | + int flags; |
| 3160 | + const char *mode = Jim_String(modeObj); |
| 3161 | + if (*mode == 'R' || *mode == 'W') { |
| 3162 | + return parse_posix_open_mode(interp, modeObj); |
| 3163 | + } |
| 3164 | + if (*mode == 'r') { |
| 3165 | + flags = O_RDONLY; |
| 3166 | + } |
| 3167 | + else if (*mode == 'w') { |
| 3168 | + flags = O_WRONLY | O_CREAT | O_TRUNC; |
| 3169 | + } |
| 3170 | + else if (*mode == 'a') { |
| 3171 | + flags = O_WRONLY | O_CREAT | O_APPEND; |
| 3172 | + } |
| 3173 | + else { |
| 3174 | + Jim_SetResultFormatted(interp, "%s: invalid open mode '%s'", Jim_String(filenameObj), mode); |
| 3175 | + return -1; |
| 3176 | + } |
| 3177 | + mode++; |
| 3178 | + |
| 3179 | + if (*mode == 'b') { |
| 3180 | +#ifdef O_BINARY |
| 3181 | + flags |= O_BINARY; |
| 3182 | +#endif |
| 3183 | + mode++; |
| 3184 | + } |
| 3185 | + |
| 3186 | + if (*mode == 't') { |
| 3187 | +#ifdef O_TEXT |
| 3188 | + flags |= O_TEXT; |
| 3189 | +#endif |
| 3190 | + mode++; |
| 3191 | + } |
| 3192 | + |
| 3193 | + if (*mode == '+') { |
| 3194 | + mode++; |
| 3195 | + |
| 3196 | + flags &= ~(O_RDONLY | O_WRONLY); |
| 3197 | + flags |= O_RDWR; |
| 3198 | + } |
| 3199 | + |
| 3200 | + if (*mode == 'x') { |
| 3201 | + mode++; |
| 3202 | +#ifdef O_EXCL |
| 3203 | + flags |= O_EXCL; |
| 3204 | +#endif |
| 3205 | + } |
| 3206 | + |
| 3207 | + if (*mode == 'F') { |
| 3208 | + mode++; |
| 3209 | +#ifdef O_LARGEFILE |
| 3210 | + flags |= O_LARGEFILE; |
| 3211 | +#endif |
| 3212 | + } |
| 3213 | + |
| 3214 | + if (*mode == 'e') { |
| 3215 | + |
| 3216 | + mode++; |
| 3217 | + } |
| 3218 | + return flags; |
| 3219 | +} |
| 2712 | 3220 | |
| 2713 | 3221 | static int JimAioOpenCommand(Jim_Interp *interp, int argc, |
| 2714 | 3222 | Jim_Obj *const *argv) |
| 2715 | 3223 | { |
| 2716 | | - const char *mode; |
| 3224 | + int openflags; |
| 3225 | + const char *filename; |
| 3226 | + int fd = -1; |
| 3227 | + int n = 0; |
| 3228 | + int flags = 0; |
| 2717 | 3229 | |
| 2718 | | - if (argc != 2 && argc != 3) { |
| 2719 | | - Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); |
| 3230 | + if (argc > 2 && Jim_CompareStringImmediate(interp, argv[2], "-noclose")) { |
| 3231 | + flags = AIO_KEEPOPEN; |
| 3232 | + n++; |
| 3233 | + } |
| 3234 | + if (argc < 2 || argc > 3 + n) { |
| 3235 | + Jim_WrongNumArgs(interp, 1, argv, "filename ?-noclose? ?mode?"); |
| 2720 | 3236 | return JIM_ERR; |
| 2721 | 3237 | } |
| 2722 | 3238 | |
| 2723 | | - mode = (argc == 3) ? Jim_String(argv[2]) : "r"; |
| 3239 | + filename = Jim_String(argv[1]); |
| 2724 | 3240 | |
| 2725 | 3241 | #ifdef jim_ext_tclcompat |
| 2726 | 3242 | { |
| 2727 | | - const char *filename = Jim_String(argv[1]); |
| 2728 | 3243 | |
| 2729 | 3244 | |
| 2730 | 3245 | if (*filename == '|') { |
| 2731 | 3246 | Jim_Obj *evalObj[3]; |
| 3247 | + int i = 0; |
| 2732 | 3248 | |
| 2733 | | - evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2734 | | - evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| 2735 | | - evalObj[2] = Jim_NewStringObj(interp, mode, -1); |
| 3249 | + evalObj[i++] = Jim_NewStringObj(interp, "::popen", -1); |
| 3250 | + evalObj[i++] = Jim_NewStringObj(interp, filename + 1, -1); |
| 3251 | + if (argc == 3 + n) { |
| 3252 | + evalObj[i++] = argv[2 + n]; |
| 3253 | + } |
| 2736 | 3254 | |
| 2737 | | - return Jim_EvalObjVector(interp, 3, evalObj); |
| 3255 | + return Jim_EvalObjVector(interp, i, evalObj); |
| 2738 | 3256 | } |
| 2739 | 3257 | } |
| 2740 | 3258 | #endif |
| 2741 | | - return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode) ? JIM_OK : JIM_ERR; |
| 3259 | + if (argc == 3 + n) { |
| 3260 | + openflags = parse_open_mode(interp, argv[1], argv[2 + n]); |
| 3261 | + if (openflags == -1) { |
| 3262 | + return JIM_ERR; |
| 3263 | + } |
| 3264 | + } |
| 3265 | + else { |
| 3266 | + openflags = O_RDONLY; |
| 3267 | + } |
| 3268 | + fd = open(filename, openflags, 0666); |
| 3269 | + if (fd < 0) { |
| 3270 | + JimAioSetError(interp, argv[1]); |
| 3271 | + return JIM_ERR; |
| 3272 | + } |
| 3273 | + |
| 3274 | + return JimMakeChannel(interp, fd, argv[1], "aio.handle%ld", 0, flags) ? JIM_OK : JIM_ERR; |
| 2742 | 3275 | } |
| 2743 | 3276 | |
| 2744 | 3277 | |
| 2745 | | -static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, |
| 2746 | | - const char *hdlfmt, int family, const char *mode) |
| 3278 | +static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename, |
| 3279 | + const char *hdlfmt, int family, int flags) |
| 2747 | 3280 | { |
| 2748 | 3281 | AioFile *af; |
| 2749 | 3282 | char buf[AIO_CMD_LEN]; |
| 2750 | | - int openFlags = 0; |
| 2751 | | - |
| 2752 | | - snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2753 | | - |
| 2754 | | - if (fh) { |
| 2755 | | - openFlags = AIO_KEEPOPEN; |
| 2756 | | - } |
| 2757 | | - |
| 2758 | | - snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 2759 | | - if (!filename) { |
| 2760 | | - filename = Jim_NewStringObj(interp, buf, -1); |
| 2761 | | - } |
| 2762 | | - |
| 2763 | | - Jim_IncrRefCount(filename); |
| 2764 | | - |
| 2765 | | - if (fh == NULL) { |
| 2766 | | - if (fd >= 0) { |
| 2767 | | -#ifndef JIM_ANSIC |
| 2768 | | - fh = fdopen(fd, mode); |
| 2769 | | -#endif |
| 2770 | | - } |
| 2771 | | - else |
| 2772 | | - fh = fopen(Jim_String(filename), mode); |
| 2773 | | - |
| 2774 | | - if (fh == NULL) { |
| 2775 | | - JimAioSetError(interp, filename); |
| 2776 | | -#ifndef JIM_ANSIC |
| 2777 | | - if (fd >= 0) { |
| 2778 | | - close(fd); |
| 2779 | | - } |
| 2780 | | -#endif |
| 2781 | | - Jim_DecrRefCount(interp, filename); |
| 2782 | | - return NULL; |
| 2783 | | - } |
| 2784 | | - } |
| 3283 | + Jim_Obj *cmdname; |
| 3284 | + |
| 3285 | + snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); |
| 3286 | + cmdname = Jim_NewStringObj(interp, buf, -1); |
| 3287 | + if (!filename) { |
| 3288 | + filename = cmdname; |
| 3289 | + } |
| 3290 | + Jim_IncrRefCount(filename); |
| 2785 | 3291 | |
| 2786 | 3292 | |
| 2787 | 3293 | af = Jim_Alloc(sizeof(*af)); |
| 2788 | 3294 | memset(af, 0, sizeof(*af)); |
| 2789 | | - af->fp = fh; |
| 2790 | 3295 | af->filename = filename; |
| 2791 | | - af->openFlags = openFlags; |
| 2792 | | -#ifndef JIM_ANSIC |
| 2793 | | - af->fd = fileno(fh); |
| 3296 | + af->fd = fd; |
| 3297 | + af->addr_family = family; |
| 3298 | + af->fops = &stdio_fops; |
| 3299 | + af->ssl = NULL; |
| 3300 | + if (flags & AIO_WBUF_NONE) { |
| 3301 | + af->wbuft = WBUF_OPT_NONE; |
| 3302 | + } |
| 3303 | + else { |
| 3304 | +#ifdef HAVE_ISATTY |
| 3305 | + af->wbuft = isatty(af->fd) ? WBUF_OPT_LINE : WBUF_OPT_FULL; |
| 3306 | +#else |
| 3307 | + af->wbuft = WBUF_OPT_FULL; |
| 3308 | +#endif |
| 3309 | + } |
| 3310 | + |
| 2794 | 3311 | #ifdef FD_CLOEXEC |
| 2795 | | - if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 3312 | + if ((flags & AIO_KEEPOPEN) == 0) { |
| 2796 | 3313 | (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2797 | 3314 | } |
| 2798 | 3315 | #endif |
| 2799 | | -#endif |
| 2800 | | - af->addr_family = family; |
| 2801 | | - af->fops = &stdio_fops; |
| 2802 | | - af->ssl = NULL; |
| 3316 | + aio_set_nonblocking(af, !!(flags & AIO_NONBLOCK)); |
| 3317 | + |
| 3318 | + af->flags |= flags; |
| 3319 | + |
| 3320 | + af->writebuf = Jim_NewStringObj(interp, NULL, 0); |
| 3321 | + Jim_IncrRefCount(af->writebuf); |
| 2803 | 3322 | |
| 2804 | 3323 | Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); |
| 2805 | 3324 | |
| 2806 | | - Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); |
| 3325 | + Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, cmdname)); |
| 2807 | 3326 | |
| 2808 | 3327 | return af; |
| 2809 | 3328 | } |
| 2810 | 3329 | |
| 2811 | | -#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H)) |
| 3330 | +#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && UNIX_SOCKETS) || defined(HAVE_OPENPTY) |
| 2812 | 3331 | static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename, |
| 2813 | | - const char *hdlfmt, int family, const char *mode[2]) |
| 3332 | + const char *hdlfmt, int family, int flags) |
| 2814 | 3333 | { |
| 2815 | | - if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) { |
| 3334 | + if (JimMakeChannel(interp, p[0], filename, hdlfmt, family, flags)) { |
| 2816 | 3335 | Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); |
| 2817 | 3336 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2818 | | - if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) { |
| 3337 | + if (JimMakeChannel(interp, p[1], filename, hdlfmt, family, flags)) { |
| 2819 | 3338 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2820 | 3339 | Jim_SetResult(interp, objPtr); |
| 2821 | 3340 | return JIM_OK; |
| 2822 | 3341 | } |
| 2823 | 3342 | } |
| | @@ -2829,26 +3348,52 @@ |
| 2829 | 3348 | return JIM_ERR; |
| 2830 | 3349 | } |
| 2831 | 3350 | #endif |
| 2832 | 3351 | |
| 2833 | 3352 | #ifdef HAVE_PIPE |
| 2834 | | -static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3353 | +static int JimCreatePipe(Jim_Interp *interp, Jim_Obj *filenameObj, int flags) |
| 2835 | 3354 | { |
| 2836 | 3355 | int p[2]; |
| 2837 | | - static const char *mode[2] = { "r", "w" }; |
| 2838 | | - |
| 2839 | | - if (argc != 1) { |
| 2840 | | - Jim_WrongNumArgs(interp, 1, argv, ""); |
| 2841 | | - return JIM_ERR; |
| 2842 | | - } |
| 2843 | 3356 | |
| 2844 | 3357 | if (pipe(p) != 0) { |
| 2845 | 3358 | JimAioSetError(interp, NULL); |
| 2846 | 3359 | return JIM_ERR; |
| 2847 | 3360 | } |
| 2848 | 3361 | |
| 2849 | | - return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode); |
| 3362 | + return JimMakeChannelPair(interp, p, filenameObj, "aio.pipe%ld", 0, flags); |
| 3363 | +} |
| 3364 | + |
| 3365 | + |
| 3366 | +static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3367 | +{ |
| 3368 | + if (argc != 1) { |
| 3369 | + Jim_WrongNumArgs(interp, 1, argv, ""); |
| 3370 | + return JIM_ERR; |
| 3371 | + } |
| 3372 | + return JimCreatePipe(interp, argv[0], 0); |
| 3373 | +} |
| 3374 | +#endif |
| 3375 | + |
| 3376 | +#ifdef HAVE_OPENPTY |
| 3377 | +static int JimAioOpenPtyCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3378 | +{ |
| 3379 | + int p[2]; |
| 3380 | + char path[MAXPATHLEN]; |
| 3381 | + |
| 3382 | + if (argc != 1) { |
| 3383 | + Jim_WrongNumArgs(interp, 1, argv, ""); |
| 3384 | + return JIM_ERR; |
| 3385 | + } |
| 3386 | + |
| 3387 | + if (openpty(&p[0], &p[1], path, NULL, NULL) != 0) { |
| 3388 | + JimAioSetError(interp, NULL); |
| 3389 | + return JIM_ERR; |
| 3390 | + } |
| 3391 | + |
| 3392 | + |
| 3393 | + return JimMakeChannelPair(interp, p, Jim_NewStringObj(interp, path, -1), "aio.pty%ld", 0, 0); |
| 3394 | + return JimMakeChannelPair(interp, p, Jim_NewStringObj(interp, path, -1), "aio.pty%ld", 0, 0); |
| 2850 | 3395 | } |
| 2851 | 3396 | #endif |
| 2852 | 3397 | |
| 2853 | 3398 | |
| 2854 | 3399 | |
| | @@ -2868,13 +3413,13 @@ |
| 2868 | 3413 | #ifdef HAVE_PIPE |
| 2869 | 3414 | Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL); |
| 2870 | 3415 | #endif |
| 2871 | 3416 | |
| 2872 | 3417 | |
| 2873 | | - JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); |
| 2874 | | - JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2875 | | - JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 3418 | + JimMakeChannel(interp, fileno(stdin), NULL, "stdin", 0, AIO_KEEPOPEN); |
| 3419 | + JimMakeChannel(interp, fileno(stdout), NULL, "stdout", 0, AIO_KEEPOPEN); |
| 3420 | + JimMakeChannel(interp, fileno(stderr), NULL, "stderr", 0, AIO_KEEPOPEN | AIO_WBUF_NONE); |
| 2876 | 3421 | |
| 2877 | 3422 | return JIM_OK; |
| 2878 | 3423 | } |
| 2879 | 3424 | |
| 2880 | 3425 | #include <errno.h> |
| | @@ -2932,13 +3477,11 @@ |
| 2932 | 3477 | } |
| 2933 | 3478 | } |
| 2934 | 3479 | |
| 2935 | 3480 | int Jim_readdirInit(Jim_Interp *interp) |
| 2936 | 3481 | { |
| 2937 | | - if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) |
| 2938 | | - return JIM_ERR; |
| 2939 | | - |
| 3482 | + Jim_PackageProvideCheck(interp, "readdir"); |
| 2940 | 3483 | Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL); |
| 2941 | 3484 | return JIM_OK; |
| 2942 | 3485 | } |
| 2943 | 3486 | |
| 2944 | 3487 | #include <stdlib.h> |
| | @@ -2945,15 +3488,19 @@ |
| 2945 | 3488 | #include <string.h> |
| 2946 | 3489 | |
| 2947 | 3490 | #if defined(JIM_REGEXP) |
| 2948 | 3491 | #else |
| 2949 | 3492 | #include <regex.h> |
| 3493 | + #define jim_regcomp regcomp |
| 3494 | + #define jim_regexec regexec |
| 3495 | + #define jim_regerror regerror |
| 3496 | + #define jim_regfree regfree |
| 2950 | 3497 | #endif |
| 2951 | 3498 | |
| 2952 | 3499 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2953 | 3500 | { |
| 2954 | | - regfree(objPtr->internalRep.ptrIntValue.ptr); |
| 3501 | + jim_regfree(objPtr->internalRep.ptrIntValue.ptr); |
| 2955 | 3502 | Jim_Free(objPtr->internalRep.ptrIntValue.ptr); |
| 2956 | 3503 | } |
| 2957 | 3504 | |
| 2958 | 3505 | static const Jim_ObjType regexpObjType = { |
| 2959 | 3506 | "regexp", |
| | @@ -2980,16 +3527,16 @@ |
| 2980 | 3527 | |
| 2981 | 3528 | |
| 2982 | 3529 | pattern = Jim_String(objPtr); |
| 2983 | 3530 | compre = Jim_Alloc(sizeof(regex_t)); |
| 2984 | 3531 | |
| 2985 | | - if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { |
| 3532 | + if ((ret = jim_regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { |
| 2986 | 3533 | char buf[100]; |
| 2987 | 3534 | |
| 2988 | | - regerror(ret, compre, buf, sizeof(buf)); |
| 3535 | + jim_regerror(ret, compre, buf, sizeof(buf)); |
| 2989 | 3536 | Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf); |
| 2990 | | - regfree(compre); |
| 3537 | + jim_regfree(compre); |
| 2991 | 3538 | Jim_Free(compre); |
| 2992 | 3539 | return NULL; |
| 2993 | 3540 | } |
| 2994 | 3541 | |
| 2995 | 3542 | Jim_FreeIntRep(interp, objPtr); |
| | @@ -3110,25 +3657,25 @@ |
| 3110 | 3657 | } |
| 3111 | 3658 | if (offset > source_len) { |
| 3112 | 3659 | source_str += source_len; |
| 3113 | 3660 | } |
| 3114 | 3661 | else if (offset > 0) { |
| 3115 | | - source_str += offset; |
| 3662 | + source_str += utf8_index(source_str, offset); |
| 3116 | 3663 | } |
| 3117 | 3664 | eflags |= REG_NOTBOL; |
| 3118 | 3665 | } |
| 3119 | 3666 | |
| 3120 | 3667 | if (opt_inline) { |
| 3121 | 3668 | resultListObj = Jim_NewListObj(interp, NULL, 0); |
| 3122 | 3669 | } |
| 3123 | 3670 | |
| 3124 | 3671 | next_match: |
| 3125 | | - match = regexec(regex, source_str, num_vars + 1, pmatch, eflags); |
| 3672 | + match = jim_regexec(regex, source_str, num_vars + 1, pmatch, eflags); |
| 3126 | 3673 | if (match >= REG_BADPAT) { |
| 3127 | 3674 | char buf[100]; |
| 3128 | 3675 | |
| 3129 | | - regerror(match, regex, buf, sizeof(buf)); |
| 3676 | + jim_regerror(match, regex, buf, sizeof(buf)); |
| 3130 | 3677 | Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); |
| 3131 | 3678 | result = JIM_ERR; |
| 3132 | 3679 | goto done; |
| 3133 | 3680 | } |
| 3134 | 3681 | |
| | @@ -3160,20 +3707,19 @@ |
| 3160 | 3707 | Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); |
| 3161 | 3708 | Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); |
| 3162 | 3709 | } |
| 3163 | 3710 | } |
| 3164 | 3711 | else { |
| 3165 | | - int len = pmatch[j].rm_eo - pmatch[j].rm_so; |
| 3166 | | - |
| 3167 | 3712 | if (opt_indices) { |
| 3168 | | - Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, |
| 3169 | | - offset + pmatch[j].rm_so)); |
| 3170 | | - Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, |
| 3171 | | - offset + pmatch[j].rm_so + len - 1)); |
| 3713 | + |
| 3714 | + int so = utf8_strlen(source_str, pmatch[j].rm_so); |
| 3715 | + int eo = utf8_strlen(source_str, pmatch[j].rm_eo); |
| 3716 | + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + so)); |
| 3717 | + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + eo - 1)); |
| 3172 | 3718 | } |
| 3173 | 3719 | else { |
| 3174 | | - Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len); |
| 3720 | + Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, pmatch[j].rm_eo - pmatch[j].rm_so); |
| 3175 | 3721 | } |
| 3176 | 3722 | } |
| 3177 | 3723 | |
| 3178 | 3724 | if (opt_inline) { |
| 3179 | 3725 | Jim_ListAppendElement(interp, resultListObj, resultObj); |
| | @@ -3190,11 +3736,11 @@ |
| 3190 | 3736 | } |
| 3191 | 3737 | |
| 3192 | 3738 | try_next_match: |
| 3193 | 3739 | if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) { |
| 3194 | 3740 | if (pmatch[0].rm_eo) { |
| 3195 | | - offset += pmatch[0].rm_eo; |
| 3741 | + offset += utf8_strlen(source_str, pmatch[0].rm_eo); |
| 3196 | 3742 | source_str += pmatch[0].rm_eo; |
| 3197 | 3743 | } |
| 3198 | 3744 | else { |
| 3199 | 3745 | source_str++; |
| 3200 | 3746 | offset++; |
| | @@ -3319,23 +3865,25 @@ |
| 3319 | 3865 | else if (offset < 0) { |
| 3320 | 3866 | offset = 0; |
| 3321 | 3867 | } |
| 3322 | 3868 | } |
| 3323 | 3869 | |
| 3870 | + offset = utf8_index(source_str, offset); |
| 3871 | + |
| 3324 | 3872 | |
| 3325 | 3873 | Jim_AppendString(interp, resultObj, source_str, offset); |
| 3326 | 3874 | |
| 3327 | 3875 | |
| 3328 | 3876 | n = source_len - offset; |
| 3329 | 3877 | p = source_str + offset; |
| 3330 | 3878 | do { |
| 3331 | | - int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags); |
| 3879 | + int match = jim_regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags); |
| 3332 | 3880 | |
| 3333 | 3881 | if (match >= REG_BADPAT) { |
| 3334 | 3882 | char buf[100]; |
| 3335 | 3883 | |
| 3336 | | - regerror(match, regex, buf, sizeof(buf)); |
| 3884 | + jim_regerror(match, regex, buf, sizeof(buf)); |
| 3337 | 3885 | Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); |
| 3338 | 3886 | return JIM_ERR; |
| 3339 | 3887 | } |
| 3340 | 3888 | if (match == REG_NOMATCH) { |
| 3341 | 3889 | break; |
| | @@ -3396,11 +3944,18 @@ |
| 3396 | 3944 | Jim_AppendString(interp, resultObj, p, 1); |
| 3397 | 3945 | p++; |
| 3398 | 3946 | n--; |
| 3399 | 3947 | } |
| 3400 | 3948 | |
| 3401 | | - regexec_flags |= REG_NOTBOL; |
| 3949 | + if (pmatch[0].rm_eo == pmatch[0].rm_so) { |
| 3950 | + |
| 3951 | + regexec_flags = REG_NOTBOL; |
| 3952 | + } |
| 3953 | + else { |
| 3954 | + regexec_flags = 0; |
| 3955 | + } |
| 3956 | + |
| 3402 | 3957 | } while (n); |
| 3403 | 3958 | |
| 3404 | 3959 | Jim_AppendString(interp, resultObj, p, -1); |
| 3405 | 3960 | |
| 3406 | 3961 | |
| | @@ -3422,13 +3977,11 @@ |
| 3422 | 3977 | return result; |
| 3423 | 3978 | } |
| 3424 | 3979 | |
| 3425 | 3980 | int Jim_regexpInit(Jim_Interp *interp) |
| 3426 | 3981 | { |
| 3427 | | - if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG)) |
| 3428 | | - return JIM_ERR; |
| 3429 | | - |
| 3982 | + Jim_PackageProvideCheck(interp, "regexp"); |
| 3430 | 3983 | Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL); |
| 3431 | 3984 | Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL); |
| 3432 | 3985 | return JIM_OK; |
| 3433 | 3986 | } |
| 3434 | 3987 | |
| | @@ -3435,11 +3988,10 @@ |
| 3435 | 3988 | #include <limits.h> |
| 3436 | 3989 | #include <stdlib.h> |
| 3437 | 3990 | #include <string.h> |
| 3438 | 3991 | #include <stdio.h> |
| 3439 | 3992 | #include <errno.h> |
| 3440 | | -#include <sys/stat.h> |
| 3441 | 3993 | |
| 3442 | 3994 | |
| 3443 | 3995 | #ifdef HAVE_UTIMES |
| 3444 | 3996 | #include <sys/time.h> |
| 3445 | 3997 | #endif |
| | @@ -3453,15 +4005,21 @@ |
| 3453 | 4005 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
| 3454 | 4006 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
| 3455 | 4007 | #endif |
| 3456 | 4008 | |
| 3457 | 4009 | # ifndef MAXPATHLEN |
| 4010 | +# ifdef PATH_MAX |
| 4011 | +# define MAXPATHLEN PATH_MAX |
| 4012 | +# else |
| 3458 | 4013 | # define MAXPATHLEN JIM_PATH_LEN |
| 4014 | +# endif |
| 3459 | 4015 | # endif |
| 3460 | 4016 | |
| 3461 | 4017 | #if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER) |
| 3462 | 4018 | #define ISWINDOWS 1 |
| 4019 | + |
| 4020 | +#undef HAVE_SYMLINK |
| 3463 | 4021 | #else |
| 3464 | 4022 | #define ISWINDOWS 0 |
| 3465 | 4023 | #endif |
| 3466 | 4024 | |
| 3467 | 4025 | |
| | @@ -3469,10 +4027,22 @@ |
| 3469 | 4027 | #define STAT_MTIME_US(STAT) ((STAT).st_mtimespec.tv_sec * 1000000ll + (STAT).st_mtimespec.tv_nsec / 1000) |
| 3470 | 4028 | #elif defined(HAVE_STRUCT_STAT_ST_MTIM) |
| 3471 | 4029 | #define STAT_MTIME_US(STAT) ((STAT).st_mtim.tv_sec * 1000000ll + (STAT).st_mtim.tv_nsec / 1000) |
| 3472 | 4030 | #endif |
| 3473 | 4031 | |
| 4032 | + |
| 4033 | +static void JimFixPath(char *path) |
| 4034 | +{ |
| 4035 | + if (ISWINDOWS) { |
| 4036 | + |
| 4037 | + char *p = path; |
| 4038 | + while ((p = strchr(p, '\\')) != NULL) { |
| 4039 | + *p++ = '/'; |
| 4040 | + } |
| 4041 | + } |
| 4042 | +} |
| 4043 | + |
| 3474 | 4044 | |
| 3475 | 4045 | static const char *JimGetFileType(int mode) |
| 3476 | 4046 | { |
| 3477 | 4047 | if (S_ISREG(mode)) { |
| 3478 | 4048 | return "file"; |
| | @@ -3512,11 +4082,11 @@ |
| 3512 | 4082 | { |
| 3513 | 4083 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); |
| 3514 | 4084 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3515 | 4085 | } |
| 3516 | 4086 | |
| 3517 | | -static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 4087 | +int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb) |
| 3518 | 4088 | { |
| 3519 | 4089 | |
| 3520 | 4090 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3521 | 4091 | |
| 3522 | 4092 | AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| | @@ -3565,31 +4135,91 @@ |
| 3565 | 4135 | |
| 3566 | 4136 | Jim_SetResult(interp, listObj); |
| 3567 | 4137 | |
| 3568 | 4138 | return JIM_OK; |
| 3569 | 4139 | } |
| 4140 | + |
| 4141 | +static int JimPathLenNoTrailingSlashes(const char *path, int len) |
| 4142 | +{ |
| 4143 | + int i; |
| 4144 | + for (i = len; i > 1 && path[i - 1] == '/'; i--) { |
| 4145 | + |
| 4146 | + if (ISWINDOWS && path[i - 2] == ':') { |
| 4147 | + |
| 4148 | + break; |
| 4149 | + } |
| 4150 | + } |
| 4151 | + return i; |
| 4152 | +} |
| 4153 | + |
| 4154 | +static Jim_Obj *JimStripTrailingSlashes(Jim_Interp *interp, Jim_Obj *objPtr) |
| 4155 | +{ |
| 4156 | + int len = Jim_Length(objPtr); |
| 4157 | + const char *path = Jim_String(objPtr); |
| 4158 | + int i = JimPathLenNoTrailingSlashes(path, len); |
| 4159 | + if (i != len) { |
| 4160 | + objPtr = Jim_NewStringObj(interp, path, i); |
| 4161 | + } |
| 4162 | + Jim_IncrRefCount(objPtr); |
| 4163 | + return objPtr; |
| 4164 | +} |
| 3570 | 4165 | |
| 3571 | 4166 | static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3572 | 4167 | { |
| 3573 | | - const char *path = Jim_String(argv[0]); |
| 4168 | + Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]); |
| 4169 | + const char *path = Jim_String(objPtr); |
| 3574 | 4170 | const char *p = strrchr(path, '/'); |
| 3575 | 4171 | |
| 3576 | | - if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') { |
| 3577 | | - Jim_SetResultString(interp, "..", -1); |
| 3578 | | - } else if (!p) { |
| 4172 | + if (!p) { |
| 3579 | 4173 | Jim_SetResultString(interp, ".", -1); |
| 3580 | 4174 | } |
| 4175 | + else if (p[1] == 0) { |
| 4176 | + |
| 4177 | + Jim_SetResult(interp, objPtr); |
| 4178 | + } |
| 3581 | 4179 | else if (p == path) { |
| 3582 | 4180 | Jim_SetResultString(interp, "/", -1); |
| 3583 | 4181 | } |
| 3584 | 4182 | else if (ISWINDOWS && p[-1] == ':') { |
| 3585 | 4183 | |
| 3586 | 4184 | Jim_SetResultString(interp, path, p - path + 1); |
| 3587 | 4185 | } |
| 3588 | 4186 | else { |
| 3589 | | - Jim_SetResultString(interp, path, p - path); |
| 4187 | + |
| 4188 | + int len = JimPathLenNoTrailingSlashes(path, p - path); |
| 4189 | + Jim_SetResultString(interp, path, len); |
| 3590 | 4190 | } |
| 4191 | + Jim_DecrRefCount(interp, objPtr); |
| 4192 | + return JIM_OK; |
| 4193 | +} |
| 4194 | + |
| 4195 | +static int file_cmd_split(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4196 | +{ |
| 4197 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 4198 | + const char *path = Jim_String(argv[0]); |
| 4199 | + |
| 4200 | + if (*path == '/') { |
| 4201 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "/", 1)); |
| 4202 | + } |
| 4203 | + |
| 4204 | + while (1) { |
| 4205 | + |
| 4206 | + while (*path == '/') { |
| 4207 | + path++; |
| 4208 | + } |
| 4209 | + if (*path) { |
| 4210 | + const char *pt = strchr(path, '/'); |
| 4211 | + if (pt) { |
| 4212 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, path, pt - path)); |
| 4213 | + path = pt; |
| 4214 | + continue; |
| 4215 | + } |
| 4216 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, path, -1)); |
| 4217 | + } |
| 4218 | + break; |
| 4219 | + } |
| 4220 | + Jim_SetResult(interp, listObj); |
| 3591 | 4221 | return JIM_OK; |
| 3592 | 4222 | } |
| 3593 | 4223 | |
| 3594 | 4224 | static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3595 | 4225 | { |
| | @@ -3606,54 +4236,67 @@ |
| 3606 | 4236 | return JIM_OK; |
| 3607 | 4237 | } |
| 3608 | 4238 | |
| 3609 | 4239 | static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3610 | 4240 | { |
| 3611 | | - const char *path = Jim_String(argv[0]); |
| 4241 | + Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]); |
| 4242 | + const char *path = Jim_String(objPtr); |
| 3612 | 4243 | const char *lastSlash = strrchr(path, '/'); |
| 3613 | 4244 | const char *p = strrchr(path, '.'); |
| 3614 | 4245 | |
| 3615 | 4246 | if (p == NULL || (lastSlash != NULL && lastSlash >= p)) { |
| 3616 | 4247 | p = ""; |
| 3617 | 4248 | } |
| 3618 | 4249 | Jim_SetResultString(interp, p, -1); |
| 4250 | + Jim_DecrRefCount(interp, objPtr); |
| 3619 | 4251 | return JIM_OK; |
| 3620 | 4252 | } |
| 3621 | 4253 | |
| 3622 | 4254 | static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3623 | 4255 | { |
| 3624 | | - const char *path = Jim_String(argv[0]); |
| 4256 | + Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]); |
| 4257 | + const char *path = Jim_String(objPtr); |
| 3625 | 4258 | const char *lastSlash = strrchr(path, '/'); |
| 3626 | 4259 | |
| 3627 | 4260 | if (lastSlash) { |
| 3628 | 4261 | Jim_SetResultString(interp, lastSlash + 1, -1); |
| 3629 | 4262 | } |
| 3630 | 4263 | else { |
| 3631 | | - Jim_SetResult(interp, argv[0]); |
| 4264 | + Jim_SetResult(interp, objPtr); |
| 3632 | 4265 | } |
| 4266 | + Jim_DecrRefCount(interp, objPtr); |
| 3633 | 4267 | return JIM_OK; |
| 3634 | 4268 | } |
| 4269 | + |
| 4270 | +#ifndef HAVE_RESTRICT |
| 4271 | +#define restrict |
| 4272 | +#endif |
| 4273 | + |
| 4274 | +static char *JimRealPath(const char *restrict path, char *restrict resolved_path, size_t len) |
| 4275 | +{ |
| 4276 | +#if defined(HAVE__FULLPATH) |
| 4277 | + return _fullpath(resolved_path, path, len); |
| 4278 | +#elif defined(HAVE_REALPATH) |
| 4279 | + return realpath(path, resolved_path); |
| 4280 | +#else |
| 4281 | + return NULL; |
| 4282 | +#endif |
| 4283 | +} |
| 3635 | 4284 | |
| 3636 | 4285 | static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3637 | 4286 | { |
| 3638 | | -#ifdef HAVE_REALPATH |
| 3639 | 4287 | const char *path = Jim_String(argv[0]); |
| 3640 | | - char *newname = Jim_Alloc(MAXPATHLEN + 1); |
| 4288 | + char *newname = Jim_Alloc(MAXPATHLEN); |
| 3641 | 4289 | |
| 3642 | | - if (realpath(path, newname)) { |
| 4290 | + if (JimRealPath(path, newname, MAXPATHLEN)) { |
| 4291 | + JimFixPath(newname); |
| 3643 | 4292 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1)); |
| 3644 | 4293 | return JIM_OK; |
| 3645 | 4294 | } |
| 3646 | | - else { |
| 3647 | | - Jim_Free(newname); |
| 3648 | | - Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno)); |
| 3649 | | - return JIM_ERR; |
| 3650 | | - } |
| 3651 | | -#else |
| 3652 | | - Jim_SetResultString(interp, "Not implemented", -1); |
| 3653 | | - return JIM_ERR; |
| 3654 | | -#endif |
| 4295 | + Jim_Free(newname); |
| 4296 | + Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno)); |
| 4297 | + return JIM_ERR; |
| 3655 | 4298 | } |
| 3656 | 4299 | |
| 3657 | 4300 | static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3658 | 4301 | { |
| 3659 | 4302 | int i; |
| | @@ -3755,12 +4398,12 @@ |
| 3755 | 4398 | static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3756 | 4399 | { |
| 3757 | 4400 | int force = Jim_CompareStringImmediate(interp, argv[0], "-force"); |
| 3758 | 4401 | |
| 3759 | 4402 | if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) { |
| 3760 | | - argc++; |
| 3761 | | - argv--; |
| 4403 | + argc--; |
| 4404 | + argv++; |
| 3762 | 4405 | } |
| 3763 | 4406 | |
| 3764 | 4407 | while (argc--) { |
| 3765 | 4408 | const char *path = Jim_String(argv[0]); |
| 3766 | 4409 | |
| | @@ -3813,13 +4456,13 @@ |
| 3813 | 4456 | |
| 3814 | 4457 | continue; |
| 3815 | 4458 | } |
| 3816 | 4459 | |
| 3817 | 4460 | if (errno == EEXIST) { |
| 3818 | | - struct stat sb; |
| 4461 | + jim_stat_t sb; |
| 3819 | 4462 | |
| 3820 | | - if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
| 4463 | + if (Jim_Stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
| 3821 | 4464 | return 0; |
| 3822 | 4465 | } |
| 3823 | 4466 | |
| 3824 | 4467 | errno = EEXIST; |
| 3825 | 4468 | } |
| | @@ -3879,11 +4522,16 @@ |
| 3879 | 4522 | if (!force && access(dest, F_OK) == 0) { |
| 3880 | 4523 | Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": target exists", argv[0], |
| 3881 | 4524 | argv[1]); |
| 3882 | 4525 | return JIM_ERR; |
| 3883 | 4526 | } |
| 4527 | +#if ISWINDOWS |
| 4528 | + if (access(dest, F_OK) == 0) { |
| 3884 | 4529 | |
| 4530 | + remove(dest); |
| 4531 | + } |
| 4532 | +#endif |
| 3885 | 4533 | if (rename(source, dest) != 0) { |
| 3886 | 4534 | Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1], |
| 3887 | 4535 | strerror(errno)); |
| 3888 | 4536 | return JIM_ERR; |
| 3889 | 4537 | } |
| | @@ -3927,27 +4575,27 @@ |
| 3927 | 4575 | |
| 3928 | 4576 | return JIM_OK; |
| 3929 | 4577 | } |
| 3930 | 4578 | #endif |
| 3931 | 4579 | |
| 3932 | | -static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 4580 | +static int file_stat(Jim_Interp *interp, Jim_Obj *filename, jim_stat_t *sb) |
| 3933 | 4581 | { |
| 3934 | 4582 | const char *path = Jim_String(filename); |
| 3935 | 4583 | |
| 3936 | | - if (stat(path, sb) == -1) { |
| 4584 | + if (Jim_Stat(path, sb) == -1) { |
| 3937 | 4585 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3938 | 4586 | return JIM_ERR; |
| 3939 | 4587 | } |
| 3940 | 4588 | return JIM_OK; |
| 3941 | 4589 | } |
| 3942 | 4590 | |
| 3943 | | -#ifdef HAVE_LSTAT |
| 3944 | | -static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) |
| 4591 | +#ifdef Jim_LinkStat |
| 4592 | +static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, jim_stat_t *sb) |
| 3945 | 4593 | { |
| 3946 | 4594 | const char *path = Jim_String(filename); |
| 3947 | 4595 | |
| 3948 | | - if (lstat(path, sb) == -1) { |
| 4596 | + if (Jim_LinkStat(path, sb) == -1) { |
| 3949 | 4597 | Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); |
| 3950 | 4598 | return JIM_ERR; |
| 3951 | 4599 | } |
| 3952 | 4600 | return JIM_OK; |
| 3953 | 4601 | } |
| | @@ -3955,11 +4603,11 @@ |
| 3955 | 4603 | #define file_lstat file_stat |
| 3956 | 4604 | #endif |
| 3957 | 4605 | |
| 3958 | 4606 | static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3959 | 4607 | { |
| 3960 | | - struct stat sb; |
| 4608 | + jim_stat_t sb; |
| 3961 | 4609 | |
| 3962 | 4610 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 3963 | 4611 | return JIM_ERR; |
| 3964 | 4612 | } |
| 3965 | 4613 | Jim_SetResultInt(interp, sb.st_atime); |
| | @@ -3985,11 +4633,11 @@ |
| 3985 | 4633 | #endif |
| 3986 | 4634 | } |
| 3987 | 4635 | |
| 3988 | 4636 | static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3989 | 4637 | { |
| 3990 | | - struct stat sb; |
| 4638 | + jim_stat_t sb; |
| 3991 | 4639 | |
| 3992 | 4640 | if (argc == 2) { |
| 3993 | 4641 | jim_wide secs; |
| 3994 | 4642 | if (Jim_GetWide(interp, argv[1], &secs) != JIM_OK) { |
| 3995 | 4643 | return JIM_ERR; |
| | @@ -4004,11 +4652,11 @@ |
| 4004 | 4652 | } |
| 4005 | 4653 | |
| 4006 | 4654 | #ifdef STAT_MTIME_US |
| 4007 | 4655 | static int file_cmd_mtimeus(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4008 | 4656 | { |
| 4009 | | - struct stat sb; |
| 4657 | + jim_stat_t sb; |
| 4010 | 4658 | |
| 4011 | 4659 | if (argc == 2) { |
| 4012 | 4660 | jim_wide us; |
| 4013 | 4661 | if (Jim_GetWide(interp, argv[1], &us) != JIM_OK) { |
| 4014 | 4662 | return JIM_ERR; |
| | @@ -4028,11 +4676,11 @@ |
| 4028 | 4676 | return Jim_EvalPrefix(interp, "file copy", argc, argv); |
| 4029 | 4677 | } |
| 4030 | 4678 | |
| 4031 | 4679 | static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4032 | 4680 | { |
| 4033 | | - struct stat sb; |
| 4681 | + jim_stat_t sb; |
| 4034 | 4682 | |
| 4035 | 4683 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 4036 | 4684 | return JIM_ERR; |
| 4037 | 4685 | } |
| 4038 | 4686 | Jim_SetResultInt(interp, sb.st_size); |
| | @@ -4039,11 +4687,11 @@ |
| 4039 | 4687 | return JIM_OK; |
| 4040 | 4688 | } |
| 4041 | 4689 | |
| 4042 | 4690 | static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4043 | 4691 | { |
| 4044 | | - struct stat sb; |
| 4692 | + jim_stat_t sb; |
| 4045 | 4693 | int ret = 0; |
| 4046 | 4694 | |
| 4047 | 4695 | if (file_stat(interp, argv[0], &sb) == JIM_OK) { |
| 4048 | 4696 | ret = S_ISDIR(sb.st_mode); |
| 4049 | 4697 | } |
| | @@ -4051,11 +4699,11 @@ |
| 4051 | 4699 | return JIM_OK; |
| 4052 | 4700 | } |
| 4053 | 4701 | |
| 4054 | 4702 | static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4055 | 4703 | { |
| 4056 | | - struct stat sb; |
| 4704 | + jim_stat_t sb; |
| 4057 | 4705 | int ret = 0; |
| 4058 | 4706 | |
| 4059 | 4707 | if (file_stat(interp, argv[0], &sb) == JIM_OK) { |
| 4060 | 4708 | ret = S_ISREG(sb.st_mode); |
| 4061 | 4709 | } |
| | @@ -4064,11 +4712,11 @@ |
| 4064 | 4712 | } |
| 4065 | 4713 | |
| 4066 | 4714 | #ifdef HAVE_GETEUID |
| 4067 | 4715 | static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4068 | 4716 | { |
| 4069 | | - struct stat sb; |
| 4717 | + jim_stat_t sb; |
| 4070 | 4718 | int ret = 0; |
| 4071 | 4719 | |
| 4072 | 4720 | if (file_stat(interp, argv[0], &sb) == JIM_OK) { |
| 4073 | 4721 | ret = (geteuid() == sb.st_uid); |
| 4074 | 4722 | } |
| | @@ -4085,11 +4733,11 @@ |
| 4085 | 4733 | |
| 4086 | 4734 | int linkLength = readlink(path, linkValue, MAXPATHLEN); |
| 4087 | 4735 | |
| 4088 | 4736 | if (linkLength == -1) { |
| 4089 | 4737 | Jim_Free(linkValue); |
| 4090 | | - Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno)); |
| 4738 | + Jim_SetResultFormatted(interp, "could not read link \"%#s\": %s", argv[0], strerror(errno)); |
| 4091 | 4739 | return JIM_ERR; |
| 4092 | 4740 | } |
| 4093 | 4741 | linkValue[linkLength] = 0; |
| 4094 | 4742 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, linkValue, linkLength)); |
| 4095 | 4743 | return JIM_OK; |
| | @@ -4096,41 +4744,41 @@ |
| 4096 | 4744 | } |
| 4097 | 4745 | #endif |
| 4098 | 4746 | |
| 4099 | 4747 | static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4100 | 4748 | { |
| 4101 | | - struct stat sb; |
| 4749 | + jim_stat_t sb; |
| 4102 | 4750 | |
| 4103 | 4751 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 4104 | 4752 | return JIM_ERR; |
| 4105 | 4753 | } |
| 4106 | 4754 | Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); |
| 4107 | 4755 | return JIM_OK; |
| 4108 | 4756 | } |
| 4109 | 4757 | |
| 4110 | | -#ifdef HAVE_LSTAT |
| 4758 | +#ifdef Jim_LinkStat |
| 4111 | 4759 | static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4112 | 4760 | { |
| 4113 | | - struct stat sb; |
| 4761 | + jim_stat_t sb; |
| 4114 | 4762 | |
| 4115 | 4763 | if (file_lstat(interp, argv[0], &sb) != JIM_OK) { |
| 4116 | 4764 | return JIM_ERR; |
| 4117 | 4765 | } |
| 4118 | | - return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 4766 | + return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 4119 | 4767 | } |
| 4120 | 4768 | #else |
| 4121 | 4769 | #define file_cmd_lstat file_cmd_stat |
| 4122 | 4770 | #endif |
| 4123 | 4771 | |
| 4124 | 4772 | static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4125 | 4773 | { |
| 4126 | | - struct stat sb; |
| 4774 | + jim_stat_t sb; |
| 4127 | 4775 | |
| 4128 | 4776 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { |
| 4129 | 4777 | return JIM_ERR; |
| 4130 | 4778 | } |
| 4131 | | - return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 4779 | + return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); |
| 4132 | 4780 | } |
| 4133 | 4781 | |
| 4134 | 4782 | static const jim_subcmd_type file_command_table[] = { |
| 4135 | 4783 | { "atime", |
| 4136 | 4784 | "name", |
| | @@ -4187,10 +4835,17 @@ |
| 4187 | 4835 | "name", |
| 4188 | 4836 | file_cmd_tail, |
| 4189 | 4837 | 1, |
| 4190 | 4838 | 1, |
| 4191 | 4839 | |
| 4840 | + }, |
| 4841 | + { "split", |
| 4842 | + "name", |
| 4843 | + file_cmd_split, |
| 4844 | + 1, |
| 4845 | + 1, |
| 4846 | + |
| 4192 | 4847 | }, |
| 4193 | 4848 | { "normalize", |
| 4194 | 4849 | "name", |
| 4195 | 4850 | file_cmd_normalize, |
| 4196 | 4851 | 1, |
| | @@ -4360,43 +5015,31 @@ |
| 4360 | 5015 | if (getcwd(cwd, MAXPATHLEN) == NULL) { |
| 4361 | 5016 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 4362 | 5017 | Jim_Free(cwd); |
| 4363 | 5018 | return JIM_ERR; |
| 4364 | 5019 | } |
| 4365 | | - else if (ISWINDOWS) { |
| 4366 | | - |
| 4367 | | - char *p = cwd; |
| 4368 | | - while ((p = strchr(p, '\\')) != NULL) { |
| 4369 | | - *p++ = '/'; |
| 4370 | | - } |
| 4371 | | - } |
| 4372 | | - |
| 5020 | + JimFixPath(cwd); |
| 4373 | 5021 | Jim_SetResultString(interp, cwd, -1); |
| 4374 | 5022 | |
| 4375 | 5023 | Jim_Free(cwd); |
| 4376 | 5024 | return JIM_OK; |
| 4377 | 5025 | } |
| 4378 | 5026 | |
| 4379 | 5027 | int Jim_fileInit(Jim_Interp *interp) |
| 4380 | 5028 | { |
| 4381 | | - if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG)) |
| 4382 | | - return JIM_ERR; |
| 4383 | | - |
| 5029 | + Jim_PackageProvideCheck(interp, "file"); |
| 4384 | 5030 | Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL); |
| 4385 | 5031 | Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); |
| 4386 | 5032 | Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); |
| 4387 | 5033 | return JIM_OK; |
| 4388 | 5034 | } |
| 4389 | 5035 | |
| 4390 | | -#ifndef _GNU_SOURCE |
| 4391 | | -#define _GNU_SOURCE |
| 4392 | | -#endif |
| 4393 | 5036 | #include <string.h> |
| 4394 | 5037 | #include <ctype.h> |
| 4395 | 5038 | |
| 4396 | 5039 | |
| 4397 | | -#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) |
| 5040 | +#if (!(defined(HAVE_VFORK) || defined(HAVE_FORK)) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) |
| 4398 | 5041 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4399 | 5042 | { |
| 4400 | 5043 | Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); |
| 4401 | 5044 | int i, j; |
| 4402 | 5045 | int rc; |
| | @@ -4440,13 +5083,11 @@ |
| 4440 | 5083 | return JIM_OK; |
| 4441 | 5084 | } |
| 4442 | 5085 | |
| 4443 | 5086 | int Jim_execInit(Jim_Interp *interp) |
| 4444 | 5087 | { |
| 4445 | | - if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 4446 | | - return JIM_ERR; |
| 4447 | | - |
| 5088 | + Jim_PackageProvideCheck(interp, "exec"); |
| 4448 | 5089 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); |
| 4449 | 5090 | return JIM_OK; |
| 4450 | 5091 | } |
| 4451 | 5092 | #else |
| 4452 | 5093 | |
| | @@ -4459,17 +5100,17 @@ |
| 4459 | 5100 | |
| 4460 | 5101 | static char **JimOriginalEnviron(void); |
| 4461 | 5102 | static char **JimSaveEnv(char **env); |
| 4462 | 5103 | static void JimRestoreEnv(char **env); |
| 4463 | 5104 | static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, |
| 4464 | | - pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr); |
| 4465 | | -static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr); |
| 4466 | | -static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj); |
| 5105 | + phandle_t **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr); |
| 5106 | +static void JimDetachPids(struct WaitInfoTable *table, int numPids, const phandle_t *pidPtr); |
| 5107 | +static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj); |
| 4467 | 5108 | static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 4468 | 5109 | |
| 4469 | 5110 | #if defined(__MINGW32__) |
| 4470 | | -static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId); |
| 5111 | +static phandle_t JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId); |
| 4471 | 5112 | #endif |
| 4472 | 5113 | |
| 4473 | 5114 | static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) |
| 4474 | 5115 | { |
| 4475 | 5116 | int len; |
| | @@ -4482,28 +5123,23 @@ |
| 4482 | 5123 | } |
| 4483 | 5124 | |
| 4484 | 5125 | static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj) |
| 4485 | 5126 | { |
| 4486 | 5127 | char buf[256]; |
| 4487 | | - FILE *fh = fdopen(fd, "r"); |
| 4488 | 5128 | int ret = 0; |
| 4489 | 5129 | |
| 4490 | | - if (fh == NULL) { |
| 4491 | | - return -1; |
| 4492 | | - } |
| 4493 | | - |
| 4494 | 5130 | while (1) { |
| 4495 | | - int retval = fread(buf, 1, sizeof(buf), fh); |
| 5131 | + int retval = read(fd, buf, sizeof(buf)); |
| 4496 | 5132 | if (retval > 0) { |
| 4497 | 5133 | ret = 1; |
| 4498 | 5134 | Jim_AppendString(interp, strObj, buf, retval); |
| 4499 | 5135 | } |
| 4500 | | - if (retval != sizeof(buf)) { |
| 5136 | + if (retval <= 0) { |
| 4501 | 5137 | break; |
| 4502 | 5138 | } |
| 4503 | 5139 | } |
| 4504 | | - fclose(fh); |
| 5140 | + close(fd); |
| 4505 | 5141 | return ret; |
| 4506 | 5142 | } |
| 4507 | 5143 | |
| 4508 | 5144 | static char **JimBuildEnv(Jim_Interp *interp) |
| 4509 | 5145 | { |
| | @@ -4558,22 +5194,22 @@ |
| 4558 | 5194 | if (env != original_environ) { |
| 4559 | 5195 | Jim_Free(env); |
| 4560 | 5196 | } |
| 4561 | 5197 | } |
| 4562 | 5198 | |
| 4563 | | -static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) |
| 5199 | +static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, long pid, int waitStatus, Jim_Obj *errStrObj) |
| 4564 | 5200 | { |
| 4565 | 5201 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| 4566 | 5202 | |
| 4567 | | - if (pid == JIM_BAD_PID || pid == JIM_NO_PID) { |
| 5203 | + if (pid <= 0) { |
| 4568 | 5204 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); |
| 4569 | | - Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 5205 | + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); |
| 4570 | 5206 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1)); |
| 4571 | 5207 | } |
| 4572 | 5208 | else if (WIFEXITED(waitStatus)) { |
| 4573 | 5209 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); |
| 4574 | | - Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 5210 | + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); |
| 4575 | 5211 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); |
| 4576 | 5212 | } |
| 4577 | 5213 | else { |
| 4578 | 5214 | const char *type; |
| 4579 | 5215 | const char *action; |
| | @@ -4594,17 +5230,17 @@ |
| 4594 | 5230 | |
| 4595 | 5231 | if (errStrObj) { |
| 4596 | 5232 | Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL); |
| 4597 | 5233 | } |
| 4598 | 5234 | |
| 4599 | | - Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 5235 | + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); |
| 4600 | 5236 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1)); |
| 4601 | 5237 | } |
| 4602 | 5238 | return errorCode; |
| 4603 | 5239 | } |
| 4604 | 5240 | |
| 4605 | | -static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) |
| 5241 | +static int JimCheckWaitStatus(Jim_Interp *interp, long pid, int waitStatus, Jim_Obj *errStrObj) |
| 4606 | 5242 | { |
| 4607 | 5243 | if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { |
| 4608 | 5244 | return JIM_OK; |
| 4609 | 5245 | } |
| 4610 | 5246 | Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj)); |
| | @@ -4613,11 +5249,11 @@ |
| 4613 | 5249 | } |
| 4614 | 5250 | |
| 4615 | 5251 | |
| 4616 | 5252 | struct WaitInfo |
| 4617 | 5253 | { |
| 4618 | | - pidtype pid; |
| 5254 | + phandle_t phandle; |
| 4619 | 5255 | int status; |
| 4620 | 5256 | int flags; |
| 4621 | 5257 | }; |
| 4622 | 5258 | |
| 4623 | 5259 | |
| | @@ -4651,17 +5287,17 @@ |
| 4651 | 5287 | table->refcount = 1; |
| 4652 | 5288 | |
| 4653 | 5289 | return table; |
| 4654 | 5290 | } |
| 4655 | 5291 | |
| 4656 | | -static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid) |
| 5292 | +static int JimWaitRemove(struct WaitInfoTable *table, phandle_t phandle) |
| 4657 | 5293 | { |
| 4658 | 5294 | int i; |
| 4659 | 5295 | |
| 4660 | 5296 | |
| 4661 | 5297 | for (i = 0; i < table->used; i++) { |
| 4662 | | - if (pid == table->info[i].pid) { |
| 5298 | + if (phandle == table->info[i].phandle) { |
| 4663 | 5299 | if (i != table->used - 1) { |
| 4664 | 5300 | table->info[i] = table->info[table->used - 1]; |
| 4665 | 5301 | } |
| 4666 | 5302 | table->used--; |
| 4667 | 5303 | return 0; |
| | @@ -4672,11 +5308,11 @@ |
| 4672 | 5308 | |
| 4673 | 5309 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4674 | 5310 | { |
| 4675 | 5311 | int outputId; |
| 4676 | 5312 | int errorId; |
| 4677 | | - pidtype *pidPtr; |
| 5313 | + phandle_t *pidPtr; |
| 4678 | 5314 | int numPids, result; |
| 4679 | 5315 | int child_siginfo = 1; |
| 4680 | 5316 | Jim_Obj *childErrObj; |
| 4681 | 5317 | Jim_Obj *errStrObj; |
| 4682 | 5318 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| | @@ -4691,11 +5327,11 @@ |
| 4691 | 5327 | return JIM_ERR; |
| 4692 | 5328 | } |
| 4693 | 5329 | |
| 4694 | 5330 | listObj = Jim_NewListObj(interp, NULL, 0); |
| 4695 | 5331 | for (i = 0; i < numPids; i++) { |
| 4696 | | - Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); |
| 5332 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, JimProcessPid(pidPtr[i]))); |
| 4697 | 5333 | } |
| 4698 | 5334 | Jim_SetResult(interp, listObj); |
| 4699 | 5335 | JimDetachPids(table, numPids, pidPtr); |
| 4700 | 5336 | Jim_Free(pidPtr); |
| 4701 | 5337 | return JIM_OK; |
| | @@ -4728,11 +5364,11 @@ |
| 4728 | 5364 | result = JIM_ERR; |
| 4729 | 5365 | } |
| 4730 | 5366 | |
| 4731 | 5367 | if (errorId != -1) { |
| 4732 | 5368 | int ret; |
| 4733 | | - lseek(errorId, 0, SEEK_SET); |
| 5369 | + Jim_Lseek(errorId, 0, SEEK_SET); |
| 4734 | 5370 | ret = JimAppendStreamToString(interp, errorId, errStrObj); |
| 4735 | 5371 | if (ret < 0) { |
| 4736 | 5372 | Jim_SetResultErrno(interp, "error reading from error pipe"); |
| 4737 | 5373 | result = JIM_ERR; |
| 4738 | 5374 | } |
| | @@ -4755,31 +5391,30 @@ |
| 4755 | 5391 | Jim_SetResult(interp, errStrObj); |
| 4756 | 5392 | |
| 4757 | 5393 | return result; |
| 4758 | 5394 | } |
| 4759 | 5395 | |
| 4760 | | -static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 5396 | +static long JimWaitForProcess(struct WaitInfoTable *table, phandle_t phandle, int *statusPtr) |
| 4761 | 5397 | { |
| 4762 | | - if (JimWaitRemove(table, pid) == 0) { |
| 5398 | + if (JimWaitRemove(table, phandle) == 0) { |
| 4763 | 5399 | |
| 4764 | | - waitpid(pid, statusPtr, 0); |
| 4765 | | - return pid; |
| 5400 | + return waitpid(phandle, statusPtr, 0); |
| 4766 | 5401 | } |
| 4767 | 5402 | |
| 4768 | 5403 | |
| 4769 | | - return JIM_BAD_PID; |
| 5404 | + return -1; |
| 4770 | 5405 | } |
| 4771 | 5406 | |
| 4772 | | -static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr) |
| 5407 | +static void JimDetachPids(struct WaitInfoTable *table, int numPids, const phandle_t *pidPtr) |
| 4773 | 5408 | { |
| 4774 | 5409 | int j; |
| 4775 | 5410 | |
| 4776 | 5411 | for (j = 0; j < numPids; j++) { |
| 4777 | 5412 | |
| 4778 | 5413 | int i; |
| 4779 | 5414 | for (i = 0; i < table->used; i++) { |
| 4780 | | - if (pidPtr[j] == table->info[i].pid) { |
| 5415 | + if (pidPtr[j] == table->info[i].phandle) { |
| 4781 | 5416 | table->info[i].flags |= WI_DETACHED; |
| 4782 | 5417 | break; |
| 4783 | 5418 | } |
| 4784 | 5419 | } |
| 4785 | 5420 | } |
| | @@ -4814,12 +5449,12 @@ |
| 4814 | 5449 | waitPtr = table->info; |
| 4815 | 5450 | dest = 0; |
| 4816 | 5451 | for (count = table->used; count > 0; waitPtr++, count--) { |
| 4817 | 5452 | if (waitPtr->flags & WI_DETACHED) { |
| 4818 | 5453 | int status; |
| 4819 | | - pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG); |
| 4820 | | - if (pid == waitPtr->pid) { |
| 5454 | + long pid = waitpid(waitPtr->phandle, &status, WNOHANG); |
| 5455 | + if (pid > 0) { |
| 4821 | 5456 | |
| 4822 | 5457 | table->used--; |
| 4823 | 5458 | continue; |
| 4824 | 5459 | } |
| 4825 | 5460 | } |
| | @@ -4832,12 +5467,12 @@ |
| 4832 | 5467 | |
| 4833 | 5468 | static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4834 | 5469 | { |
| 4835 | 5470 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4836 | 5471 | int nohang = 0; |
| 4837 | | - pidtype pid; |
| 4838 | | - long pidarg; |
| 5472 | + long pid; |
| 5473 | + phandle_t phandle; |
| 4839 | 5474 | int status; |
| 4840 | 5475 | Jim_Obj *errCodeObj; |
| 4841 | 5476 | |
| 4842 | 5477 | |
| 4843 | 5478 | if (argc == 1) { |
| | @@ -4850,21 +5485,30 @@ |
| 4850 | 5485 | } |
| 4851 | 5486 | if (argc != nohang + 2) { |
| 4852 | 5487 | Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?"); |
| 4853 | 5488 | return JIM_ERR; |
| 4854 | 5489 | } |
| 4855 | | - if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) { |
| 5490 | + if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) { |
| 4856 | 5491 | return JIM_ERR; |
| 4857 | 5492 | } |
| 4858 | 5493 | |
| 4859 | | - pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0); |
| 5494 | + |
| 5495 | + phandle = JimWaitPid(pid, &status, nohang ? WNOHANG : 0); |
| 5496 | + if (phandle == JIM_BAD_PHANDLE) { |
| 5497 | + pid = -1; |
| 5498 | + } |
| 5499 | +#ifndef __MINGW32__ |
| 5500 | + else if (pid < 0) { |
| 5501 | + pid = phandle; |
| 5502 | + } |
| 5503 | +#endif |
| 4860 | 5504 | |
| 4861 | 5505 | errCodeObj = JimMakeErrorCode(interp, pid, status, NULL); |
| 4862 | 5506 | |
| 4863 | | - if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) { |
| 5507 | + if (phandle != JIM_BAD_PHANDLE && (WIFEXITED(status) || WIFSIGNALED(status))) { |
| 4864 | 5508 | |
| 4865 | | - JimWaitRemove(table, pid); |
| 5509 | + JimWaitRemove(table, phandle); |
| 4866 | 5510 | } |
| 4867 | 5511 | Jim_SetResult(interp, errCodeObj); |
| 4868 | 5512 | return JIM_OK; |
| 4869 | 5513 | } |
| 4870 | 5514 | |
| | @@ -4878,14 +5522,14 @@ |
| 4878 | 5522 | Jim_SetResultInt(interp, (jim_wide)getpid()); |
| 4879 | 5523 | return JIM_OK; |
| 4880 | 5524 | } |
| 4881 | 5525 | |
| 4882 | 5526 | static int |
| 4883 | | -JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, |
| 5527 | +JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, phandle_t **pidArrayPtr, |
| 4884 | 5528 | int *inPipePtr, int *outPipePtr, int *errFilePtr) |
| 4885 | 5529 | { |
| 4886 | | - pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all |
| 5530 | + phandle_t *pidPtr = NULL; /* Points to alloc-ed array holding all |
| 4887 | 5531 | * the pids of child processes. */ |
| 4888 | 5532 | int numPids = 0; /* Actual number of processes that exist |
| 4889 | 5533 | * at *pidPtr right now. */ |
| 4890 | 5534 | int cmdCount; /* Count of number of distinct commands |
| 4891 | 5535 | * found in argc/argv. */ |
| | @@ -4925,13 +5569,13 @@ |
| 4925 | 5569 | int pipeIds[2]; |
| 4926 | 5570 | int firstArg, lastArg; /* Indexes of first and last arguments in |
| 4927 | 5571 | * current command. */ |
| 4928 | 5572 | int lastBar; |
| 4929 | 5573 | int i; |
| 4930 | | - pidtype pid; |
| 5574 | + phandle_t phandle; |
| 4931 | 5575 | char **save_environ; |
| 4932 | | -#ifndef __MINGW32__ |
| 5576 | +#if defined(HAVE_EXECVPE) && !defined(__MINGW32__) |
| 4933 | 5577 | char **child_environ; |
| 4934 | 5578 | #endif |
| 4935 | 5579 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4936 | 5580 | |
| 4937 | 5581 | |
| | @@ -5053,11 +5697,11 @@ |
| 5053 | 5697 | if (write(inputId, input, input_len) != input_len) { |
| 5054 | 5698 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5055 | 5699 | close(inputId); |
| 5056 | 5700 | goto error; |
| 5057 | 5701 | } |
| 5058 | | - lseek(inputId, 0L, SEEK_SET); |
| 5702 | + Jim_Lseek(inputId, 0L, SEEK_SET); |
| 5059 | 5703 | } |
| 5060 | 5704 | else if (inputFile == FILE_HANDLE) { |
| 5061 | 5705 | int fd = JimGetChannelFd(interp, input); |
| 5062 | 5706 | |
| 5063 | 5707 | if (fd < 0) { |
| | @@ -5145,13 +5789,10 @@ |
| 5145 | 5789 | *errFilePtr = dup(errorId); |
| 5146 | 5790 | } |
| 5147 | 5791 | |
| 5148 | 5792 | |
| 5149 | 5793 | pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); |
| 5150 | | - for (i = 0; i < numPids; i++) { |
| 5151 | | - pidPtr[i] = JIM_BAD_PID; |
| 5152 | | - } |
| 5153 | 5794 | for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { |
| 5154 | 5795 | int pipe_dup_err = 0; |
| 5155 | 5796 | int origErrorId = errorId; |
| 5156 | 5797 | |
| 5157 | 5798 | for (lastArg = firstArg; lastArg < arg_count; lastArg++) { |
| | @@ -5189,58 +5830,61 @@ |
| 5189 | 5830 | } |
| 5190 | 5831 | |
| 5191 | 5832 | |
| 5192 | 5833 | |
| 5193 | 5834 | #ifdef __MINGW32__ |
| 5194 | | - pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId); |
| 5195 | | - if (pid == JIM_BAD_PID) { |
| 5835 | + phandle = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId); |
| 5836 | + if (phandle == JIM_BAD_PHANDLE) { |
| 5196 | 5837 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 5197 | 5838 | goto error; |
| 5198 | 5839 | } |
| 5199 | 5840 | #else |
| 5200 | 5841 | i = strlen(arg_array[firstArg]); |
| 5201 | 5842 | |
| 5843 | +#ifdef HAVE_EXECVPE |
| 5202 | 5844 | child_environ = Jim_GetEnviron(); |
| 5203 | | - pid = vfork(); |
| 5204 | | - if (pid < 0) { |
| 5845 | +#endif |
| 5846 | +#ifdef HAVE_VFORK |
| 5847 | + phandle = vfork(); |
| 5848 | +#else |
| 5849 | + phandle = fork(); |
| 5850 | +#endif |
| 5851 | + if (phandle < 0) { |
| 5205 | 5852 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 5206 | 5853 | goto error; |
| 5207 | 5854 | } |
| 5208 | | - if (pid == 0) { |
| 5855 | + if (phandle == 0) { |
| 5209 | 5856 | |
| 5210 | 5857 | |
| 5211 | | - if (inputId != -1) { |
| 5858 | + if (inputId != -1 && inputId != fileno(stdin)) { |
| 5212 | 5859 | dup2(inputId, fileno(stdin)); |
| 5213 | 5860 | close(inputId); |
| 5214 | 5861 | } |
| 5215 | | - if (outputId != -1) { |
| 5862 | + if (outputId != -1 && outputId != fileno(stdout)) { |
| 5216 | 5863 | dup2(outputId, fileno(stdout)); |
| 5217 | 5864 | if (outputId != errorId) { |
| 5218 | 5865 | close(outputId); |
| 5219 | 5866 | } |
| 5220 | 5867 | } |
| 5221 | | - if (errorId != -1) { |
| 5868 | + if (errorId != -1 && errorId != fileno(stderr)) { |
| 5222 | 5869 | dup2(errorId, fileno(stderr)); |
| 5223 | 5870 | close(errorId); |
| 5224 | 5871 | } |
| 5225 | 5872 | |
| 5226 | | - if (outPipePtr) { |
| 5873 | + if (outPipePtr && *outPipePtr != -1) { |
| 5227 | 5874 | close(*outPipePtr); |
| 5228 | 5875 | } |
| 5229 | | - if (errFilePtr) { |
| 5876 | + if (errFilePtr && *errFilePtr != -1) { |
| 5230 | 5877 | close(*errFilePtr); |
| 5231 | 5878 | } |
| 5232 | 5879 | if (pipeIds[0] != -1) { |
| 5233 | 5880 | close(pipeIds[0]); |
| 5234 | 5881 | } |
| 5235 | 5882 | if (lastOutputId != -1) { |
| 5236 | 5883 | close(lastOutputId); |
| 5237 | 5884 | } |
| 5238 | 5885 | |
| 5239 | | - |
| 5240 | | - (void)signal(SIGPIPE, SIG_DFL); |
| 5241 | | - |
| 5242 | 5886 | execvpe(arg_array[firstArg], &arg_array[firstArg], child_environ); |
| 5243 | 5887 | |
| 5244 | 5888 | if (write(fileno(stderr), "couldn't exec \"", 15) && |
| 5245 | 5889 | write(fileno(stderr), arg_array[firstArg], i) && |
| 5246 | 5890 | write(fileno(stderr), "\"\n", 2)) { |
| | @@ -5262,15 +5906,15 @@ |
| 5262 | 5906 | if (table->used == table->size) { |
| 5263 | 5907 | table->size += WAIT_TABLE_GROW_BY; |
| 5264 | 5908 | table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); |
| 5265 | 5909 | } |
| 5266 | 5910 | |
| 5267 | | - table->info[table->used].pid = pid; |
| 5911 | + table->info[table->used].phandle = phandle; |
| 5268 | 5912 | table->info[table->used].flags = 0; |
| 5269 | 5913 | table->used++; |
| 5270 | 5914 | |
| 5271 | | - pidPtr[numPids] = pid; |
| 5915 | + pidPtr[numPids] = phandle; |
| 5272 | 5916 | |
| 5273 | 5917 | |
| 5274 | 5918 | errorId = origErrorId; |
| 5275 | 5919 | |
| 5276 | 5920 | |
| | @@ -5322,11 +5966,11 @@ |
| 5322 | 5966 | if (pipeIds[1] != -1) { |
| 5323 | 5967 | close(pipeIds[1]); |
| 5324 | 5968 | } |
| 5325 | 5969 | if (pidPtr != NULL) { |
| 5326 | 5970 | for (i = 0; i < numPids; i++) { |
| 5327 | | - if (pidPtr[i] != JIM_BAD_PID) { |
| 5971 | + if (pidPtr[i] != JIM_BAD_PHANDLE) { |
| 5328 | 5972 | JimDetachPids(table, 1, &pidPtr[i]); |
| 5329 | 5973 | } |
| 5330 | 5974 | } |
| 5331 | 5975 | Jim_Free(pidPtr); |
| 5332 | 5976 | } |
| | @@ -5333,21 +5977,22 @@ |
| 5333 | 5977 | numPids = -1; |
| 5334 | 5978 | goto cleanup; |
| 5335 | 5979 | } |
| 5336 | 5980 | |
| 5337 | 5981 | |
| 5338 | | -static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj) |
| 5982 | +static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj) |
| 5339 | 5983 | { |
| 5340 | 5984 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 5341 | 5985 | int result = JIM_OK; |
| 5342 | 5986 | int i; |
| 5343 | 5987 | |
| 5344 | 5988 | |
| 5345 | 5989 | for (i = 0; i < numPids; i++) { |
| 5346 | 5990 | int waitStatus = 0; |
| 5347 | | - if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { |
| 5348 | | - if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) { |
| 5991 | + long pid = JimWaitForProcess(table, pidPtr[i], &waitStatus); |
| 5992 | + if (pid > 0) { |
| 5993 | + if (JimCheckWaitStatus(interp, pid, waitStatus, errStrObj) != JIM_OK) { |
| 5349 | 5994 | result = JIM_ERR; |
| 5350 | 5995 | } |
| 5351 | 5996 | } |
| 5352 | 5997 | } |
| 5353 | 5998 | Jim_Free(pidPtr); |
| | @@ -5356,16 +6001,12 @@ |
| 5356 | 6001 | } |
| 5357 | 6002 | |
| 5358 | 6003 | int Jim_execInit(Jim_Interp *interp) |
| 5359 | 6004 | { |
| 5360 | 6005 | struct WaitInfoTable *waitinfo; |
| 5361 | | - if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 5362 | | - return JIM_ERR; |
| 5363 | 6006 | |
| 5364 | | -#ifdef SIGPIPE |
| 5365 | | - (void)signal(SIGPIPE, SIG_IGN); |
| 5366 | | -#endif |
| 6007 | + Jim_PackageProvideCheck(interp, "exec"); |
| 5367 | 6008 | |
| 5368 | 6009 | waitinfo = JimAllocWaitInfoTable(); |
| 5369 | 6010 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable); |
| 5370 | 6011 | waitinfo->refcount++; |
| 5371 | 6012 | Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable); |
| | @@ -5483,23 +6124,23 @@ |
| 5483 | 6124 | } |
| 5484 | 6125 | } |
| 5485 | 6126 | return strObj; |
| 5486 | 6127 | } |
| 5487 | 6128 | |
| 5488 | | -static pidtype |
| 6129 | +static phandle_t |
| 5489 | 6130 | JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId) |
| 5490 | 6131 | { |
| 5491 | 6132 | STARTUPINFO startInfo; |
| 5492 | 6133 | PROCESS_INFORMATION procInfo; |
| 5493 | 6134 | HANDLE hProcess; |
| 5494 | 6135 | char execPath[MAX_PATH]; |
| 5495 | | - pidtype pid = JIM_BAD_PID; |
| 6136 | + phandle_t phandle = INVALID_HANDLE_VALUE; |
| 5496 | 6137 | Jim_Obj *cmdLineObj; |
| 5497 | 6138 | char *winenv; |
| 5498 | 6139 | |
| 5499 | 6140 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5500 | | - return JIM_BAD_PID; |
| 6141 | + return phandle; |
| 5501 | 6142 | } |
| 5502 | 6143 | argv[0] = execPath; |
| 5503 | 6144 | |
| 5504 | 6145 | hProcess = GetCurrentProcess(); |
| 5505 | 6146 | cmdLineObj = JimWinBuildCommandLine(interp, argv); |
| | @@ -5558,11 +6199,11 @@ |
| 5558 | 6199 | |
| 5559 | 6200 | |
| 5560 | 6201 | WaitForInputIdle(procInfo.hProcess, 5000); |
| 5561 | 6202 | CloseHandle(procInfo.hThread); |
| 5562 | 6203 | |
| 5563 | | - pid = procInfo.hProcess; |
| 6204 | + phandle = procInfo.hProcess; |
| 5564 | 6205 | |
| 5565 | 6206 | end: |
| 5566 | 6207 | Jim_FreeNewObj(interp, cmdLineObj); |
| 5567 | 6208 | if (startInfo.hStdInput != INVALID_HANDLE_VALUE) { |
| 5568 | 6209 | CloseHandle(startInfo.hStdInput); |
| | @@ -5571,11 +6212,11 @@ |
| 5571 | 6212 | CloseHandle(startInfo.hStdOutput); |
| 5572 | 6213 | } |
| 5573 | 6214 | if (startInfo.hStdError != INVALID_HANDLE_VALUE) { |
| 5574 | 6215 | CloseHandle(startInfo.hStdError); |
| 5575 | 6216 | } |
| 5576 | | - return pid; |
| 6217 | + return phandle; |
| 5577 | 6218 | } |
| 5578 | 6219 | |
| 5579 | 6220 | #else |
| 5580 | 6221 | |
| 5581 | 6222 | static char **JimOriginalEnviron(void) |
| | @@ -5597,22 +6238,10 @@ |
| 5597 | 6238 | } |
| 5598 | 6239 | #endif |
| 5599 | 6240 | #endif |
| 5600 | 6241 | |
| 5601 | 6242 | |
| 5602 | | - |
| 5603 | | -#ifdef STRPTIME_NEEDS_XOPEN_SOURCE |
| 5604 | | -#ifndef _XOPEN_SOURCE |
| 5605 | | -#define _XOPEN_SOURCE 500 |
| 5606 | | -#endif |
| 5607 | | -#endif |
| 5608 | | - |
| 5609 | | - |
| 5610 | | -#ifndef _GNU_SOURCE |
| 5611 | | -#define _GNU_SOURCE |
| 5612 | | -#endif |
| 5613 | | - |
| 5614 | 6243 | #include <stdlib.h> |
| 5615 | 6244 | #include <string.h> |
| 5616 | 6245 | #include <stdio.h> |
| 5617 | 6246 | #include <time.h> |
| 5618 | 6247 | |
| | @@ -5732,41 +6361,36 @@ |
| 5732 | 6361 | } |
| 5733 | 6362 | #endif |
| 5734 | 6363 | |
| 5735 | 6364 | static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5736 | 6365 | { |
| 5737 | | - Jim_SetResultInt(interp, time(NULL)); |
| 6366 | + Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000000); |
| 6367 | + return JIM_OK; |
| 6368 | +} |
| 5738 | 6369 | |
| 6370 | +static int clock_cmd_clicks(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 6371 | +{ |
| 6372 | + Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW)); |
| 5739 | 6373 | return JIM_OK; |
| 5740 | 6374 | } |
| 5741 | 6375 | |
| 5742 | 6376 | static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5743 | 6377 | { |
| 5744 | | - struct timeval tv; |
| 5745 | | - |
| 5746 | | - gettimeofday(&tv, NULL); |
| 5747 | | - |
| 5748 | | - Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec); |
| 5749 | | - |
| 6378 | + Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME)); |
| 5750 | 6379 | return JIM_OK; |
| 5751 | 6380 | } |
| 5752 | 6381 | |
| 5753 | 6382 | static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5754 | 6383 | { |
| 5755 | | - struct timeval tv; |
| 5756 | | - |
| 5757 | | - gettimeofday(&tv, NULL); |
| 5758 | | - |
| 5759 | | - Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); |
| 5760 | | - |
| 6384 | + Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000); |
| 5761 | 6385 | return JIM_OK; |
| 5762 | 6386 | } |
| 5763 | 6387 | |
| 5764 | 6388 | static const jim_subcmd_type clock_command_table[] = { |
| 5765 | 6389 | { "clicks", |
| 5766 | 6390 | NULL, |
| 5767 | | - clock_cmd_micros, |
| 6391 | + clock_cmd_clicks, |
| 5768 | 6392 | 0, |
| 5769 | 6393 | 0, |
| 5770 | 6394 | |
| 5771 | 6395 | }, |
| 5772 | 6396 | { "format", |
| | @@ -5809,13 +6433,11 @@ |
| 5809 | 6433 | { NULL } |
| 5810 | 6434 | }; |
| 5811 | 6435 | |
| 5812 | 6436 | int Jim_clockInit(Jim_Interp *interp) |
| 5813 | 6437 | { |
| 5814 | | - if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) |
| 5815 | | - return JIM_ERR; |
| 5816 | | - |
| 6438 | + Jim_PackageProvideCheck(interp, "clock"); |
| 5817 | 6439 | Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); |
| 5818 | 6440 | return JIM_OK; |
| 5819 | 6441 | } |
| 5820 | 6442 | |
| 5821 | 6443 | #include <limits.h> |
| | @@ -5886,11 +6508,12 @@ |
| 5886 | 6508 | if (objPtr == NULL) { |
| 5887 | 6509 | |
| 5888 | 6510 | return JIM_OK; |
| 5889 | 6511 | } |
| 5890 | 6512 | |
| 5891 | | - if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 6513 | + dictValuesObj = Jim_DictPairs(interp, objPtr, &len); |
| 6514 | + if (dictValuesObj == NULL) { |
| 5892 | 6515 | |
| 5893 | 6516 | Jim_SetResultString(interp, "", -1); |
| 5894 | 6517 | return JIM_OK; |
| 5895 | 6518 | } |
| 5896 | 6519 | |
| | @@ -5900,11 +6523,10 @@ |
| 5900 | 6523 | for (i = 0; i < len; i += 2) { |
| 5901 | 6524 | if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { |
| 5902 | 6525 | Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); |
| 5903 | 6526 | } |
| 5904 | 6527 | } |
| 5905 | | - Jim_Free(dictValuesObj); |
| 5906 | 6528 | |
| 5907 | 6529 | Jim_SetVariable(interp, argv[0], resultObj); |
| 5908 | 6530 | return JIM_OK; |
| 5909 | 6531 | } |
| 5910 | 6532 | |
| | @@ -6031,25 +6653,71 @@ |
| 6031 | 6653 | } |
| 6032 | 6654 | }; |
| 6033 | 6655 | |
| 6034 | 6656 | int Jim_arrayInit(Jim_Interp *interp) |
| 6035 | 6657 | { |
| 6036 | | - if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG)) |
| 6037 | | - return JIM_ERR; |
| 6038 | | - |
| 6658 | + Jim_PackageProvideCheck(interp, "array"); |
| 6039 | 6659 | Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL); |
| 6040 | 6660 | return JIM_OK; |
| 6041 | 6661 | } |
| 6662 | + |
| 6663 | +#include <sys/types.h> |
| 6664 | +#include <sys/time.h> |
| 6665 | +#include <sys/wait.h> |
| 6666 | +#include <unistd.h> |
| 6667 | +#include <string.h> |
| 6668 | +#include <errno.h> |
| 6669 | + |
| 6670 | + |
| 6671 | +#ifdef HAVE_SYS_SYSINFO_H |
| 6672 | +#include <sys/sysinfo.h> |
| 6673 | +#endif |
| 6674 | + |
| 6675 | +static void Jim_PosixSetError(Jim_Interp *interp) |
| 6676 | +{ |
| 6677 | + Jim_SetResultString(interp, strerror(errno), -1); |
| 6678 | +} |
| 6679 | + |
| 6680 | +#if defined(HAVE_FORK) |
| 6681 | +static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 6682 | +{ |
| 6683 | + pid_t pid; |
| 6684 | + |
| 6685 | + JIM_NOTUSED(argv); |
| 6686 | + |
| 6687 | + if (argc != 1) { |
| 6688 | + Jim_WrongNumArgs(interp, 1, argv, ""); |
| 6689 | + return JIM_ERR; |
| 6690 | + } |
| 6691 | + if ((pid = fork()) == -1) { |
| 6692 | + Jim_PosixSetError(interp); |
| 6693 | + return JIM_ERR; |
| 6694 | + } |
| 6695 | + Jim_SetResultInt(interp, (jim_wide) pid); |
| 6696 | + return JIM_OK; |
| 6697 | +} |
| 6698 | +#endif |
| 6699 | + |
| 6700 | + |
| 6701 | +int Jim_posixInit(Jim_Interp *interp) |
| 6702 | +{ |
| 6703 | + Jim_PackageProvideCheck(interp, "posix"); |
| 6704 | +#ifdef HAVE_FORK |
| 6705 | + Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); |
| 6706 | +#endif |
| 6707 | + return JIM_OK; |
| 6708 | +} |
| 6042 | 6709 | int Jim_InitStaticExtensions(Jim_Interp *interp) |
| 6043 | 6710 | { |
| 6044 | 6711 | extern int Jim_bootstrapInit(Jim_Interp *); |
| 6045 | 6712 | extern int Jim_aioInit(Jim_Interp *); |
| 6046 | 6713 | extern int Jim_readdirInit(Jim_Interp *); |
| 6047 | 6714 | extern int Jim_regexpInit(Jim_Interp *); |
| 6048 | 6715 | extern int Jim_fileInit(Jim_Interp *); |
| 6049 | 6716 | extern int Jim_globInit(Jim_Interp *); |
| 6050 | 6717 | extern int Jim_execInit(Jim_Interp *); |
| 6718 | +extern int Jim_posixInit(Jim_Interp *); |
| 6051 | 6719 | extern int Jim_clockInit(Jim_Interp *); |
| 6052 | 6720 | extern int Jim_arrayInit(Jim_Interp *); |
| 6053 | 6721 | extern int Jim_stdlibInit(Jim_Interp *); |
| 6054 | 6722 | extern int Jim_tclcompatInit(Jim_Interp *); |
| 6055 | 6723 | Jim_bootstrapInit(interp); |
| | @@ -6057,20 +6725,18 @@ |
| 6057 | 6725 | Jim_readdirInit(interp); |
| 6058 | 6726 | Jim_regexpInit(interp); |
| 6059 | 6727 | Jim_fileInit(interp); |
| 6060 | 6728 | Jim_globInit(interp); |
| 6061 | 6729 | Jim_execInit(interp); |
| 6730 | +Jim_posixInit(interp); |
| 6062 | 6731 | Jim_clockInit(interp); |
| 6063 | 6732 | Jim_arrayInit(interp); |
| 6064 | 6733 | Jim_stdlibInit(interp); |
| 6065 | 6734 | Jim_tclcompatInit(interp); |
| 6066 | 6735 | return JIM_OK; |
| 6067 | 6736 | } |
| 6068 | 6737 | #define JIM_OPTIMIZATION |
| 6069 | | -#ifndef _GNU_SOURCE |
| 6070 | | -#define _GNU_SOURCE |
| 6071 | | -#endif |
| 6072 | 6738 | |
| 6073 | 6739 | #include <stdio.h> |
| 6074 | 6740 | #include <stdlib.h> |
| 6075 | 6741 | |
| 6076 | 6742 | #include <string.h> |
| | @@ -6084,11 +6750,11 @@ |
| 6084 | 6750 | |
| 6085 | 6751 | |
| 6086 | 6752 | #ifdef HAVE_SYS_TIME_H |
| 6087 | 6753 | #include <sys/time.h> |
| 6088 | 6754 | #endif |
| 6089 | | -#ifdef HAVE_BACKTRACE |
| 6755 | +#ifdef HAVE_EXECINFO_H |
| 6090 | 6756 | #include <execinfo.h> |
| 6091 | 6757 | #endif |
| 6092 | 6758 | #ifdef HAVE_CRT_EXTERNS_H |
| 6093 | 6759 | #include <crt_externs.h> |
| 6094 | 6760 | #endif |
| | @@ -6136,10 +6802,11 @@ |
| 6136 | 6802 | #else |
| 6137 | 6803 | #define JimPanic(X) |
| 6138 | 6804 | #endif |
| 6139 | 6805 | |
| 6140 | 6806 | #ifdef JIM_OPTIMIZATION |
| 6807 | +static int JimIsWide(Jim_Obj *objPtr); |
| 6141 | 6808 | #define JIM_IF_OPTIM(X) X |
| 6142 | 6809 | #else |
| 6143 | 6810 | #define JIM_IF_OPTIM(X) |
| 6144 | 6811 | #endif |
| 6145 | 6812 | |
| | @@ -6147,22 +6814,29 @@ |
| 6147 | 6814 | static char JimEmptyStringRep[] = ""; |
| 6148 | 6815 | |
| 6149 | 6816 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 6150 | 6817 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| 6151 | 6818 | int flags); |
| 6819 | +static int Jim_ListIndices(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *const *indexv, int indexc, |
| 6820 | + Jim_Obj **resultObj, int flags); |
| 6152 | 6821 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); |
| 6153 | 6822 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); |
| 6154 | 6823 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); |
| 6155 | | -static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len); |
| 6156 | 6824 | static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, |
| 6157 | 6825 | const char *prefix, const char *const *tablePtr, const char *name); |
| 6158 | 6826 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); |
| 6159 | 6827 | static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); |
| 6160 | 6828 | static int JimSign(jim_wide w); |
| 6161 | | -static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); |
| 6162 | 6829 | static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); |
| 6163 | 6830 | static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len); |
| 6831 | +static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv); |
| 6832 | +static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr); |
| 6833 | +static void JimSetErrorStack(Jim_Interp *interp); |
| 6834 | +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 6835 | + |
| 6836 | +#define JIM_DICT_SUGAR 100 |
| 6837 | + |
| 6164 | 6838 | |
| 6165 | 6839 | |
| 6166 | 6840 | |
| 6167 | 6841 | #define JimWideValue(objPtr) (objPtr)->internalRep.wideValue |
| 6168 | 6842 | |
| | @@ -6175,20 +6849,32 @@ |
| 6175 | 6849 | *uc = utf8_upper(*uc); |
| 6176 | 6850 | } |
| 6177 | 6851 | return l; |
| 6178 | 6852 | } |
| 6179 | 6853 | |
| 6854 | +static Jim_Obj *JimPushInterpObjImpl(Jim_Obj **iop, Jim_Obj *no) |
| 6855 | +{ |
| 6856 | + Jim_Obj *io = *iop; |
| 6857 | + Jim_IncrRefCount(no); |
| 6858 | + *iop = no; |
| 6859 | + return io; |
| 6860 | +} |
| 6861 | + |
| 6862 | +#define JimPushInterpObj(IO, NO) JimPushInterpObjImpl(&(IO), NO) |
| 6863 | +#define JimPopInterpObj(I, IO, SO) do { Jim_DecrRefCount(I, IO); IO = SO; } while (0) |
| 6864 | + |
| 6180 | 6865 | |
| 6181 | 6866 | #define JIM_CHARSET_SCAN 2 |
| 6182 | 6867 | #define JIM_CHARSET_GLOB 0 |
| 6183 | 6868 | |
| 6184 | | -static const char *JimCharsetMatch(const char *pattern, int c, int flags) |
| 6869 | +static const char *JimCharsetMatch(const char *pattern, int plen, int c, int flags) |
| 6185 | 6870 | { |
| 6186 | 6871 | int not = 0; |
| 6187 | 6872 | int pchar; |
| 6188 | 6873 | int match = 0; |
| 6189 | 6874 | int nocase = 0; |
| 6875 | + int n; |
| 6190 | 6876 | |
| 6191 | 6877 | if (flags & JIM_NOCASE) { |
| 6192 | 6878 | nocase++; |
| 6193 | 6879 | c = utf8_upper(c); |
| 6194 | 6880 | } |
| | @@ -6195,34 +6881,40 @@ |
| 6195 | 6881 | |
| 6196 | 6882 | if (flags & JIM_CHARSET_SCAN) { |
| 6197 | 6883 | if (*pattern == '^') { |
| 6198 | 6884 | not++; |
| 6199 | 6885 | pattern++; |
| 6886 | + plen--; |
| 6200 | 6887 | } |
| 6201 | 6888 | |
| 6202 | 6889 | |
| 6203 | 6890 | if (*pattern == ']') { |
| 6204 | 6891 | goto first; |
| 6205 | 6892 | } |
| 6206 | 6893 | } |
| 6207 | 6894 | |
| 6208 | | - while (*pattern && *pattern != ']') { |
| 6895 | + while (plen && *pattern != ']') { |
| 6209 | 6896 | |
| 6210 | 6897 | if (pattern[0] == '\\') { |
| 6211 | 6898 | first: |
| 6212 | | - pattern += utf8_tounicode_case(pattern, &pchar, nocase); |
| 6899 | + n = utf8_tounicode_case(pattern, &pchar, nocase); |
| 6900 | + pattern += n; |
| 6901 | + plen -= n; |
| 6213 | 6902 | } |
| 6214 | 6903 | else { |
| 6215 | 6904 | |
| 6216 | 6905 | int start; |
| 6217 | 6906 | int end; |
| 6218 | 6907 | |
| 6219 | | - pattern += utf8_tounicode_case(pattern, &start, nocase); |
| 6220 | | - if (pattern[0] == '-' && pattern[1]) { |
| 6908 | + n = utf8_tounicode_case(pattern, &start, nocase); |
| 6909 | + pattern += n; |
| 6910 | + plen -= n; |
| 6911 | + if (pattern[0] == '-' && plen > 1) { |
| 6221 | 6912 | |
| 6222 | | - pattern++; |
| 6223 | | - pattern += utf8_tounicode_case(pattern, &end, nocase); |
| 6913 | + n = 1 + utf8_tounicode_case(pattern + 1, &end, nocase); |
| 6914 | + pattern += n; |
| 6915 | + plen -= n; |
| 6224 | 6916 | |
| 6225 | 6917 | |
| 6226 | 6918 | if ((c >= start && c <= end) || (c >= end && c <= start)) { |
| 6227 | 6919 | match = 1; |
| 6228 | 6920 | } |
| | @@ -6242,108 +6934,115 @@ |
| 6242 | 6934 | return match ? pattern : NULL; |
| 6243 | 6935 | } |
| 6244 | 6936 | |
| 6245 | 6937 | |
| 6246 | 6938 | |
| 6247 | | -static int JimGlobMatch(const char *pattern, const char *string, int nocase) |
| 6939 | +static int JimGlobMatch(const char *pattern, int plen, const char *string, int slen, int nocase) |
| 6248 | 6940 | { |
| 6249 | 6941 | int c; |
| 6250 | 6942 | int pchar; |
| 6251 | | - while (*pattern) { |
| 6252 | | - switch (pattern[0]) { |
| 6253 | | - case '*': |
| 6254 | | - while (pattern[1] == '*') { |
| 6255 | | - pattern++; |
| 6256 | | - } |
| 6257 | | - pattern++; |
| 6258 | | - if (!pattern[0]) { |
| 6259 | | - return 1; |
| 6260 | | - } |
| 6261 | | - while (*string) { |
| 6262 | | - |
| 6263 | | - if (JimGlobMatch(pattern, string, nocase)) |
| 6264 | | - return 1; |
| 6265 | | - string += utf8_tounicode(string, &c); |
| 6943 | + int n; |
| 6944 | + const char *p; |
| 6945 | + while (plen) { |
| 6946 | + switch (pattern[0]) { |
| 6947 | + case '*': |
| 6948 | + while (pattern[1] == '*' && plen) { |
| 6949 | + pattern++; |
| 6950 | + plen--; |
| 6951 | + } |
| 6952 | + pattern++; |
| 6953 | + plen--; |
| 6954 | + if (!plen) { |
| 6955 | + return 1; |
| 6956 | + } |
| 6957 | + while (slen) { |
| 6958 | + |
| 6959 | + if (JimGlobMatch(pattern, plen, string, slen, nocase)) |
| 6960 | + return 1; |
| 6961 | + n = utf8_tounicode(string, &c); |
| 6962 | + string += n; |
| 6963 | + slen -= n; |
| 6266 | 6964 | } |
| 6267 | 6965 | return 0; |
| 6268 | 6966 | |
| 6269 | 6967 | case '?': |
| 6270 | | - string += utf8_tounicode(string, &c); |
| 6968 | + n = utf8_tounicode(string, &c); |
| 6969 | + string += n; |
| 6970 | + slen -= n; |
| 6271 | 6971 | break; |
| 6272 | 6972 | |
| 6273 | 6973 | case '[': { |
| 6274 | | - string += utf8_tounicode(string, &c); |
| 6275 | | - pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); |
| 6276 | | - if (!pattern) { |
| 6974 | + n = utf8_tounicode(string, &c); |
| 6975 | + string += n; |
| 6976 | + slen -= n; |
| 6977 | + p = JimCharsetMatch(pattern + 1, plen - 1, c, nocase ? JIM_NOCASE : 0); |
| 6978 | + if (!p) { |
| 6277 | 6979 | return 0; |
| 6278 | 6980 | } |
| 6279 | | - if (!*pattern) { |
| 6981 | + plen -= p - pattern; |
| 6982 | + pattern = p; |
| 6983 | + |
| 6984 | + if (!plen) { |
| 6280 | 6985 | |
| 6281 | 6986 | continue; |
| 6282 | 6987 | } |
| 6283 | 6988 | break; |
| 6284 | 6989 | } |
| 6285 | 6990 | case '\\': |
| 6286 | 6991 | if (pattern[1]) { |
| 6287 | 6992 | pattern++; |
| 6993 | + plen--; |
| 6288 | 6994 | } |
| 6289 | 6995 | |
| 6290 | 6996 | default: |
| 6291 | | - string += utf8_tounicode_case(string, &c, nocase); |
| 6997 | + n = utf8_tounicode_case(string, &c, nocase); |
| 6998 | + string += n; |
| 6999 | + slen -= n; |
| 6292 | 7000 | utf8_tounicode_case(pattern, &pchar, nocase); |
| 6293 | 7001 | if (pchar != c) { |
| 6294 | 7002 | return 0; |
| 6295 | 7003 | } |
| 6296 | 7004 | break; |
| 6297 | 7005 | } |
| 6298 | | - pattern += utf8_tounicode_case(pattern, &pchar, nocase); |
| 6299 | | - if (!*string) { |
| 6300 | | - while (*pattern == '*') { |
| 7006 | + n = utf8_tounicode_case(pattern, &pchar, nocase); |
| 7007 | + pattern += n; |
| 7008 | + plen -= n; |
| 7009 | + if (!slen) { |
| 7010 | + while (*pattern == '*' && plen) { |
| 6301 | 7011 | pattern++; |
| 7012 | + plen--; |
| 6302 | 7013 | } |
| 6303 | 7014 | break; |
| 6304 | 7015 | } |
| 6305 | 7016 | } |
| 6306 | | - if (!*pattern && !*string) { |
| 7017 | + if (!plen && !slen) { |
| 6307 | 7018 | return 1; |
| 6308 | 7019 | } |
| 6309 | 7020 | return 0; |
| 6310 | 7021 | } |
| 6311 | 7022 | |
| 6312 | | -static int JimStringCompare(const char *s1, int l1, const char *s2, int l2) |
| 6313 | | -{ |
| 6314 | | - if (l1 < l2) { |
| 6315 | | - return memcmp(s1, s2, l1) <= 0 ? -1 : 1; |
| 6316 | | - } |
| 6317 | | - else if (l2 < l1) { |
| 6318 | | - return memcmp(s1, s2, l2) >= 0 ? 1 : -1; |
| 6319 | | - } |
| 6320 | | - else { |
| 6321 | | - return JimSign(memcmp(s1, s2, l1)); |
| 6322 | | - } |
| 6323 | | -} |
| 6324 | | - |
| 6325 | | -static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase) |
| 6326 | | -{ |
| 6327 | | - while (*s1 && *s2 && maxchars) { |
| 7023 | +static int JimStringCompareUtf8(const char *s1, int l1, const char *s2, int l2, int nocase) |
| 7024 | +{ |
| 7025 | + int minlen = l1; |
| 7026 | + if (l2 < l1) { |
| 7027 | + minlen = l2; |
| 7028 | + } |
| 7029 | + while (minlen) { |
| 6328 | 7030 | int c1, c2; |
| 6329 | 7031 | s1 += utf8_tounicode_case(s1, &c1, nocase); |
| 6330 | 7032 | s2 += utf8_tounicode_case(s2, &c2, nocase); |
| 6331 | 7033 | if (c1 != c2) { |
| 6332 | 7034 | return JimSign(c1 - c2); |
| 6333 | 7035 | } |
| 6334 | | - maxchars--; |
| 6335 | | - } |
| 6336 | | - if (!maxchars) { |
| 6337 | | - return 0; |
| 7036 | + minlen--; |
| 6338 | 7037 | } |
| 6339 | 7038 | |
| 6340 | | - if (*s1) { |
| 6341 | | - return 1; |
| 6342 | | - } |
| 6343 | | - if (*s2) { |
| 7039 | + if (l1 < l2) { |
| 6344 | 7040 | return -1; |
| 7041 | + } |
| 7042 | + if (l1 > l2) { |
| 7043 | + return 1; |
| 6345 | 7044 | } |
| 6346 | 7045 | return 0; |
| 6347 | 7046 | } |
| 6348 | 7047 | |
| 6349 | 7048 | static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx) |
| | @@ -6416,11 +7115,11 @@ |
| 6416 | 7115 | |
| 6417 | 7116 | static int JimNumberBase(const char *str, int *base, int *sign) |
| 6418 | 7117 | { |
| 6419 | 7118 | int i = 0; |
| 6420 | 7119 | |
| 6421 | | - *base = 10; |
| 7120 | + *base = 0; |
| 6422 | 7121 | |
| 6423 | 7122 | while (isspace(UCHAR(str[i]))) { |
| 6424 | 7123 | i++; |
| 6425 | 7124 | } |
| 6426 | 7125 | |
| | @@ -6443,30 +7142,31 @@ |
| 6443 | 7142 | |
| 6444 | 7143 | switch (str[i + 1]) { |
| 6445 | 7144 | case 'x': case 'X': *base = 16; break; |
| 6446 | 7145 | case 'o': case 'O': *base = 8; break; |
| 6447 | 7146 | case 'b': case 'B': *base = 2; break; |
| 7147 | + case 'd': case 'D': *base = 10; break; |
| 6448 | 7148 | default: return 0; |
| 6449 | 7149 | } |
| 6450 | 7150 | i += 2; |
| 6451 | 7151 | |
| 6452 | 7152 | if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { |
| 6453 | 7153 | |
| 6454 | 7154 | return i; |
| 6455 | 7155 | } |
| 6456 | 7156 | |
| 6457 | | - *base = 10; |
| 7157 | + *base = 0; |
| 6458 | 7158 | return 0; |
| 6459 | 7159 | } |
| 6460 | 7160 | |
| 6461 | 7161 | static long jim_strtol(const char *str, char **endptr) |
| 6462 | 7162 | { |
| 6463 | 7163 | int sign; |
| 6464 | 7164 | int base; |
| 6465 | 7165 | int i = JimNumberBase(str, &base, &sign); |
| 6466 | 7166 | |
| 6467 | | - if (base != 10) { |
| 7167 | + if (base != 0) { |
| 6468 | 7168 | long value = strtol(str + i, endptr, base); |
| 6469 | 7169 | if (endptr == NULL || *endptr != str + i) { |
| 6470 | 7170 | return value * sign; |
| 6471 | 7171 | } |
| 6472 | 7172 | } |
| | @@ -6481,11 +7181,11 @@ |
| 6481 | 7181 | #ifdef HAVE_LONG_LONG |
| 6482 | 7182 | int sign; |
| 6483 | 7183 | int base; |
| 6484 | 7184 | int i = JimNumberBase(str, &base, &sign); |
| 6485 | 7185 | |
| 6486 | | - if (base != 10) { |
| 7186 | + if (base != 0) { |
| 6487 | 7187 | jim_wide value = strtoull(str + i, endptr, base); |
| 6488 | 7188 | if (endptr == NULL || *endptr != str + i) { |
| 6489 | 7189 | return value * sign; |
| 6490 | 7190 | } |
| 6491 | 7191 | } |
| | @@ -6563,11 +7263,11 @@ |
| 6563 | 7263 | fprintf(stderr, "\nJIM INTERPRETER PANIC: "); |
| 6564 | 7264 | vfprintf(stderr, fmt, ap); |
| 6565 | 7265 | fprintf(stderr, "\n\n"); |
| 6566 | 7266 | va_end(ap); |
| 6567 | 7267 | |
| 6568 | | -#ifdef HAVE_BACKTRACE |
| 7268 | +#if defined(HAVE_BACKTRACE) |
| 6569 | 7269 | { |
| 6570 | 7270 | void *array[40]; |
| 6571 | 7271 | int size, i; |
| 6572 | 7272 | char **strings; |
| 6573 | 7273 | |
| | @@ -6583,48 +7283,64 @@ |
| 6583 | 7283 | exit(1); |
| 6584 | 7284 | } |
| 6585 | 7285 | #endif |
| 6586 | 7286 | |
| 6587 | 7287 | |
| 6588 | | -void *Jim_Alloc(int size) |
| 7288 | +void *JimDefaultAllocator(void *ptr, size_t size) |
| 6589 | 7289 | { |
| 6590 | | - return size ? malloc(size) : NULL; |
| 7290 | + if (size == 0) { |
| 7291 | + free(ptr); |
| 7292 | + return NULL; |
| 7293 | + } |
| 7294 | + else if (ptr) { |
| 7295 | + return realloc(ptr, size); |
| 7296 | + } |
| 7297 | + else { |
| 7298 | + return malloc(size); |
| 7299 | + } |
| 6591 | 7300 | } |
| 6592 | 7301 | |
| 6593 | | -void Jim_Free(void *ptr) |
| 6594 | | -{ |
| 6595 | | - free(ptr); |
| 6596 | | -} |
| 6597 | | - |
| 6598 | | -void *Jim_Realloc(void *ptr, int size) |
| 6599 | | -{ |
| 6600 | | - return realloc(ptr, size); |
| 6601 | | -} |
| 7302 | +void *(*Jim_Allocator)(void *ptr, size_t size) = JimDefaultAllocator; |
| 6602 | 7303 | |
| 6603 | 7304 | char *Jim_StrDup(const char *s) |
| 6604 | 7305 | { |
| 6605 | | - return strdup(s); |
| 7306 | + return Jim_StrDupLen(s, strlen(s)); |
| 6606 | 7307 | } |
| 6607 | 7308 | |
| 6608 | 7309 | char *Jim_StrDupLen(const char *s, int l) |
| 6609 | 7310 | { |
| 6610 | 7311 | char *copy = Jim_Alloc(l + 1); |
| 6611 | 7312 | |
| 6612 | | - memcpy(copy, s, l + 1); |
| 7313 | + memcpy(copy, s, l); |
| 6613 | 7314 | copy[l] = 0; |
| 6614 | 7315 | return copy; |
| 6615 | 7316 | } |
| 6616 | 7317 | |
| 6617 | 7318 | |
| 6618 | | - |
| 6619 | | -static jim_wide JimClock(void) |
| 7319 | +jim_wide Jim_GetTimeUsec(unsigned type) |
| 6620 | 7320 | { |
| 7321 | + long long now; |
| 6621 | 7322 | struct timeval tv; |
| 6622 | 7323 | |
| 6623 | | - gettimeofday(&tv, NULL); |
| 6624 | | - return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec; |
| 7324 | +#if defined(HAVE_CLOCK_GETTIME) |
| 7325 | + struct timespec ts; |
| 7326 | + |
| 7327 | + if (clock_gettime(type, &ts) == 0) { |
| 7328 | + now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; |
| 7329 | + } |
| 7330 | + else |
| 7331 | +#endif |
| 7332 | + { |
| 7333 | + gettimeofday(&tv, NULL); |
| 7334 | + |
| 7335 | + now = tv.tv_sec * 1000000LL + tv.tv_usec; |
| 7336 | + } |
| 7337 | + |
| 7338 | + return now; |
| 6625 | 7339 | } |
| 7340 | + |
| 7341 | + |
| 6626 | 7342 | |
| 6627 | 7343 | |
| 6628 | 7344 | |
| 6629 | 7345 | static void JimExpandHashTableIfNeeded(Jim_HashTable *ht); |
| 6630 | 7346 | static unsigned int JimHashTableNextPower(unsigned int size); |
| | @@ -6642,19 +7358,20 @@ |
| 6642 | 7358 | key += ~(key << 11); |
| 6643 | 7359 | key ^= (key >> 16); |
| 6644 | 7360 | return key; |
| 6645 | 7361 | } |
| 6646 | 7362 | |
| 6647 | | -unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) |
| 6648 | | -{ |
| 6649 | | - unsigned int h = 0; |
| 6650 | | - |
| 6651 | | - while (len--) |
| 6652 | | - h += (h << 3) + *buf++; |
| 6653 | | - return h; |
| 6654 | | -} |
| 6655 | | - |
| 7363 | + |
| 7364 | +unsigned int Jim_GenHashFunction(const unsigned char *string, int length) |
| 7365 | +{ |
| 7366 | + unsigned result = 0; |
| 7367 | + string += length; |
| 7368 | + while (length--) { |
| 7369 | + result += (result << 3) + (unsigned char)(*--string); |
| 7370 | + } |
| 7371 | + return result; |
| 7372 | +} |
| 6656 | 7373 | |
| 6657 | 7374 | |
| 6658 | 7375 | |
| 6659 | 7376 | static void JimResetHashTable(Jim_HashTable *ht) |
| 6660 | 7377 | { |
| | @@ -6685,19 +7402,10 @@ |
| 6685 | 7402 | ht->type = type; |
| 6686 | 7403 | ht->privdata = privDataPtr; |
| 6687 | 7404 | return JIM_OK; |
| 6688 | 7405 | } |
| 6689 | 7406 | |
| 6690 | | -void Jim_ResizeHashTable(Jim_HashTable *ht) |
| 6691 | | -{ |
| 6692 | | - int minimal = ht->used; |
| 6693 | | - |
| 6694 | | - if (minimal < JIM_HT_INITIAL_SIZE) |
| 6695 | | - minimal = JIM_HT_INITIAL_SIZE; |
| 6696 | | - Jim_ExpandHashTable(ht, minimal); |
| 6697 | | -} |
| 6698 | | - |
| 6699 | 7407 | |
| 6700 | 7408 | void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) |
| 6701 | 7409 | { |
| 6702 | 7410 | Jim_HashTable n; |
| 6703 | 7411 | unsigned int realsize = JimHashTableNextPower(size), i; |
| | @@ -6742,16 +7450,13 @@ |
| 6742 | 7450 | |
| 6743 | 7451 | |
| 6744 | 7452 | *ht = n; |
| 6745 | 7453 | } |
| 6746 | 7454 | |
| 6747 | | - |
| 6748 | 7455 | int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) |
| 6749 | 7456 | { |
| 6750 | | - Jim_HashEntry *entry; |
| 6751 | | - |
| 6752 | | - entry = JimInsertHashEntry(ht, key, 0); |
| 7457 | + Jim_HashEntry *entry = JimInsertHashEntry(ht, key, 0);; |
| 6753 | 7458 | if (entry == NULL) |
| 6754 | 7459 | return JIM_ERR; |
| 6755 | 7460 | |
| 6756 | 7461 | |
| 6757 | 7462 | Jim_SetHashKey(ht, entry, key); |
| | @@ -6786,61 +7491,62 @@ |
| 6786 | 7491 | } |
| 6787 | 7492 | |
| 6788 | 7493 | return existed; |
| 6789 | 7494 | } |
| 6790 | 7495 | |
| 6791 | | - |
| 6792 | 7496 | int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key) |
| 6793 | 7497 | { |
| 6794 | | - unsigned int h; |
| 6795 | | - Jim_HashEntry *he, *prevHe; |
| 6796 | | - |
| 6797 | | - if (ht->used == 0) |
| 6798 | | - return JIM_ERR; |
| 6799 | | - h = Jim_HashKey(ht, key) & ht->sizemask; |
| 6800 | | - he = ht->table[h]; |
| 6801 | | - |
| 6802 | | - prevHe = NULL; |
| 6803 | | - while (he) { |
| 6804 | | - if (Jim_CompareHashKeys(ht, key, he->key)) { |
| 6805 | | - |
| 6806 | | - if (prevHe) |
| 6807 | | - prevHe->next = he->next; |
| 6808 | | - else |
| 6809 | | - ht->table[h] = he->next; |
| 6810 | | - Jim_FreeEntryKey(ht, he); |
| 6811 | | - Jim_FreeEntryVal(ht, he); |
| 6812 | | - Jim_Free(he); |
| 6813 | | - ht->used--; |
| 6814 | | - return JIM_OK; |
| 6815 | | - } |
| 6816 | | - prevHe = he; |
| 6817 | | - he = he->next; |
| 6818 | | - } |
| 6819 | | - return JIM_ERR; |
| 6820 | | -} |
| 6821 | | - |
| 6822 | | - |
| 6823 | | -int Jim_FreeHashTable(Jim_HashTable *ht) |
| 7498 | + if (ht->used) { |
| 7499 | + unsigned int h = Jim_HashKey(ht, key) & ht->sizemask; |
| 7500 | + Jim_HashEntry *prevHe = NULL; |
| 7501 | + Jim_HashEntry *he = ht->table[h]; |
| 7502 | + |
| 7503 | + while (he) { |
| 7504 | + if (Jim_CompareHashKeys(ht, key, he->key)) { |
| 7505 | + |
| 7506 | + if (prevHe) |
| 7507 | + prevHe->next = he->next; |
| 7508 | + else |
| 7509 | + ht->table[h] = he->next; |
| 7510 | + ht->used--; |
| 7511 | + Jim_FreeEntryKey(ht, he); |
| 7512 | + Jim_FreeEntryVal(ht, he); |
| 7513 | + Jim_Free(he); |
| 7514 | + return JIM_OK; |
| 7515 | + } |
| 7516 | + prevHe = he; |
| 7517 | + he = he->next; |
| 7518 | + } |
| 7519 | + } |
| 7520 | + |
| 7521 | + return JIM_ERR; |
| 7522 | +} |
| 7523 | + |
| 7524 | +void Jim_ClearHashTable(Jim_HashTable *ht) |
| 6824 | 7525 | { |
| 6825 | 7526 | unsigned int i; |
| 6826 | 7527 | |
| 6827 | 7528 | |
| 6828 | 7529 | for (i = 0; ht->used > 0; i++) { |
| 6829 | 7530 | Jim_HashEntry *he, *nextHe; |
| 6830 | 7531 | |
| 6831 | | - if ((he = ht->table[i]) == NULL) |
| 6832 | | - continue; |
| 7532 | + he = ht->table[i]; |
| 6833 | 7533 | while (he) { |
| 6834 | 7534 | nextHe = he->next; |
| 6835 | 7535 | Jim_FreeEntryKey(ht, he); |
| 6836 | 7536 | Jim_FreeEntryVal(ht, he); |
| 6837 | 7537 | Jim_Free(he); |
| 6838 | 7538 | ht->used--; |
| 6839 | 7539 | he = nextHe; |
| 6840 | 7540 | } |
| 7541 | + ht->table[i] = NULL; |
| 6841 | 7542 | } |
| 7543 | +} |
| 7544 | + |
| 7545 | +int Jim_FreeHashTable(Jim_HashTable *ht) |
| 7546 | +{ |
| 7547 | + Jim_ClearHashTable(ht); |
| 6842 | 7548 | |
| 6843 | 7549 | Jim_Free(ht->table); |
| 6844 | 7550 | |
| 6845 | 7551 | JimResetHashTable(ht); |
| 6846 | 7552 | return JIM_OK; |
| | @@ -7140,10 +7846,13 @@ |
| 7140 | 7846 | if (!pc->len) { |
| 7141 | 7847 | pc->tstart = pc->p; |
| 7142 | 7848 | pc->tend = pc->p - 1; |
| 7143 | 7849 | pc->tline = pc->linenr; |
| 7144 | 7850 | pc->tt = JIM_TT_EOL; |
| 7851 | + if (pc->inquote) { |
| 7852 | + pc->missing.ch = '"'; |
| 7853 | + } |
| 7145 | 7854 | pc->eof = 1; |
| 7146 | 7855 | return JIM_OK; |
| 7147 | 7856 | } |
| 7148 | 7857 | switch (*(pc->p)) { |
| 7149 | 7858 | case '\\': |
| | @@ -7354,10 +8063,13 @@ |
| 7354 | 8063 | break; |
| 7355 | 8064 | |
| 7356 | 8065 | case '"': |
| 7357 | 8066 | if (startofword) { |
| 7358 | 8067 | JimParseSubQuote(pc); |
| 8068 | + if (pc->missing.ch == '"') { |
| 8069 | + return; |
| 8070 | + } |
| 7359 | 8071 | continue; |
| 7360 | 8072 | } |
| 7361 | 8073 | break; |
| 7362 | 8074 | |
| 7363 | 8075 | case '{': |
| | @@ -8305,37 +9017,28 @@ |
| 8305 | 9017 | } |
| 8306 | 9018 | } |
| 8307 | 9019 | |
| 8308 | 9020 | int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) |
| 8309 | 9021 | { |
| 8310 | | - return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); |
| 9022 | + int plen, slen; |
| 9023 | + const char *pattern = Jim_GetString(patternObjPtr, &plen); |
| 9024 | + const char *string = Jim_GetString(objPtr, &slen); |
| 9025 | + return JimGlobMatch(pattern, plen, string, slen, nocase); |
| 8311 | 9026 | } |
| 8312 | 9027 | |
| 8313 | 9028 | int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) |
| 8314 | 9029 | { |
| 8315 | | - int l1, l2; |
| 8316 | | - const char *s1 = Jim_GetString(firstObjPtr, &l1); |
| 8317 | | - const char *s2 = Jim_GetString(secondObjPtr, &l2); |
| 8318 | | - |
| 8319 | | - if (nocase) { |
| 8320 | | - |
| 8321 | | - return JimStringCompareLen(s1, s2, -1, nocase); |
| 8322 | | - } |
| 8323 | | - return JimStringCompare(s1, l1, s2, l2); |
| 8324 | | -} |
| 8325 | | - |
| 8326 | | -int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) |
| 8327 | | -{ |
| 8328 | 9030 | const char *s1 = Jim_String(firstObjPtr); |
| 9031 | + int l1 = Jim_Utf8Length(interp, firstObjPtr); |
| 8329 | 9032 | const char *s2 = Jim_String(secondObjPtr); |
| 8330 | | - |
| 8331 | | - return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase); |
| 9033 | + int l2 = Jim_Utf8Length(interp, secondObjPtr); |
| 9034 | + return JimStringCompareUtf8(s1, l1, s2, l2, nocase); |
| 8332 | 9035 | } |
| 8333 | 9036 | |
| 8334 | 9037 | static int JimRelToAbsIndex(int len, int idx) |
| 8335 | 9038 | { |
| 8336 | | - if (idx < 0) |
| 9039 | + if (idx < 0 && idx > -INT_MAX) |
| 8337 | 9040 | return len + idx; |
| 8338 | 9041 | return idx; |
| 8339 | 9042 | } |
| 8340 | 9043 | |
| 8341 | 9044 | static void JimRelToAbsRange(int len, int *firstPtr, int *lastPtr, int *rangeLenPtr) |
| | @@ -8849,11 +9552,11 @@ |
| 8849 | 9552 | static const Jim_ObjType scriptObjType = { |
| 8850 | 9553 | "script", |
| 8851 | 9554 | FreeScriptInternalRep, |
| 8852 | 9555 | DupScriptInternalRep, |
| 8853 | 9556 | NULL, |
| 8854 | | - JIM_TYPE_REFERENCES, |
| 9557 | + JIM_TYPE_NONE, |
| 8855 | 9558 | }; |
| 8856 | 9559 | |
| 8857 | 9560 | typedef struct ScriptToken |
| 8858 | 9561 | { |
| 8859 | 9562 | Jim_Obj *objPtr; |
| | @@ -9223,12 +9926,10 @@ |
| 9223 | 9926 | Jim_FreeIntRep(interp, objPtr); |
| 9224 | 9927 | Jim_SetIntRepPtr(objPtr, script); |
| 9225 | 9928 | objPtr->typePtr = &scriptObjType; |
| 9226 | 9929 | } |
| 9227 | 9930 | |
| 9228 | | -static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); |
| 9229 | | - |
| 9230 | 9931 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 9231 | 9932 | { |
| 9232 | 9933 | if (objPtr == interp->emptyObj) { |
| 9233 | 9934 | |
| 9234 | 9935 | objPtr = interp->nullScriptObj; |
| | @@ -9239,19 +9940,22 @@ |
| 9239 | 9940 | } |
| 9240 | 9941 | |
| 9241 | 9942 | return (ScriptObj *)Jim_GetIntRepPtr(objPtr); |
| 9242 | 9943 | } |
| 9243 | 9944 | |
| 9244 | | -static int JimScriptValid(Jim_Interp *interp, ScriptObj *script) |
| 9245 | | -{ |
| 9246 | | - if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) { |
| 9247 | | - JimAddErrorToStack(interp, script); |
| 9248 | | - return 0; |
| 9249 | | - } |
| 9250 | | - return 1; |
| 9251 | | -} |
| 9252 | | - |
| 9945 | +void Jim_InterpIncrProcEpoch(Jim_Interp *interp) |
| 9946 | +{ |
| 9947 | + interp->procEpoch++; |
| 9948 | + |
| 9949 | + |
| 9950 | + while (interp->oldCmdCache) { |
| 9951 | + Jim_Cmd *next = interp->oldCmdCache->prevCmd; |
| 9952 | + Jim_Free(interp->oldCmdCache); |
| 9953 | + interp->oldCmdCache = next; |
| 9954 | + } |
| 9955 | + interp->oldCmdCacheSize = 0; |
| 9956 | +} |
| 9253 | 9957 | |
| 9254 | 9958 | static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) |
| 9255 | 9959 | { |
| 9256 | 9960 | cmdPtr->inUse++; |
| 9257 | 9961 | } |
| | @@ -9276,65 +9980,156 @@ |
| 9276 | 9980 | } |
| 9277 | 9981 | if (cmdPtr->prevCmd) { |
| 9278 | 9982 | |
| 9279 | 9983 | JimDecrCmdRefCount(interp, cmdPtr->prevCmd); |
| 9280 | 9984 | } |
| 9281 | | - Jim_Free(cmdPtr); |
| 9985 | + |
| 9986 | + cmdPtr->prevCmd = interp->oldCmdCache; |
| 9987 | + interp->oldCmdCache = cmdPtr; |
| 9988 | + if (!interp->quitting && ++interp->oldCmdCacheSize >= 1000) { |
| 9989 | + Jim_InterpIncrProcEpoch(interp); |
| 9990 | + } |
| 9991 | + } |
| 9992 | +} |
| 9993 | + |
| 9994 | +static void JimIncrVarRef(Jim_VarVal *vv) |
| 9995 | +{ |
| 9996 | + vv->refCount++; |
| 9997 | +} |
| 9998 | + |
| 9999 | +static void JimDecrVarRef(Jim_Interp *interp, Jim_VarVal *vv) |
| 10000 | +{ |
| 10001 | + assert(vv->refCount > 0); |
| 10002 | + if (--vv->refCount == 0) { |
| 10003 | + if (vv->objPtr) { |
| 10004 | + Jim_DecrRefCount(interp, vv->objPtr); |
| 10005 | + } |
| 10006 | + Jim_Free(vv); |
| 9282 | 10007 | } |
| 9283 | 10008 | } |
| 9284 | 10009 | |
| 9285 | 10010 | static void JimVariablesHTValDestructor(void *interp, void *val) |
| 9286 | 10011 | { |
| 9287 | | - Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); |
| 9288 | | - Jim_Free(val); |
| 10012 | + JimDecrVarRef(interp, val); |
| 10013 | +} |
| 10014 | + |
| 10015 | +static unsigned int JimObjectHTHashFunction(const void *key) |
| 10016 | +{ |
| 10017 | + Jim_Obj *keyObj = (Jim_Obj *)key; |
| 10018 | + int length; |
| 10019 | + const char *string; |
| 10020 | + |
| 10021 | +#ifdef JIM_OPTIMIZATION |
| 10022 | + if (JimIsWide(keyObj) && keyObj->bytes == NULL) { |
| 10023 | + |
| 10024 | + jim_wide objValue = JimWideValue(keyObj); |
| 10025 | + if (objValue > INT_MIN && objValue < INT_MAX) { |
| 10026 | + unsigned result = 0; |
| 10027 | + unsigned value = (unsigned)objValue; |
| 10028 | + |
| 10029 | + if (objValue < 0) { |
| 10030 | + value = (unsigned)-objValue; |
| 10031 | + } |
| 10032 | + |
| 10033 | + |
| 10034 | + do { |
| 10035 | + result += (result << 3) + (value % 10 + '0'); |
| 10036 | + value /= 10; |
| 10037 | + } while (value); |
| 10038 | + |
| 10039 | + if (objValue < 0) { |
| 10040 | + result += (result << 3) + '-'; |
| 10041 | + } |
| 10042 | + return result; |
| 10043 | + } |
| 10044 | + } |
| 10045 | +#endif |
| 10046 | + string = Jim_GetString(keyObj, &length); |
| 10047 | + return Jim_GenHashFunction((const unsigned char *)string, length); |
| 10048 | +} |
| 10049 | + |
| 10050 | +static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 10051 | +{ |
| 10052 | + return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 10053 | +} |
| 10054 | + |
| 10055 | +static void *JimObjectHTKeyValDup(void *privdata, const void *val) |
| 10056 | +{ |
| 10057 | + Jim_IncrRefCount((Jim_Obj *)val); |
| 10058 | + return (void *)val; |
| 10059 | +} |
| 10060 | + |
| 10061 | +static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 10062 | +{ |
| 10063 | + Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 10064 | +} |
| 10065 | + |
| 10066 | + |
| 10067 | +static void *JimVariablesHTValDup(void *privdata, const void *val) |
| 10068 | +{ |
| 10069 | + JimIncrVarRef((Jim_VarVal *)val); |
| 10070 | + return (void *)val; |
| 9289 | 10071 | } |
| 9290 | 10072 | |
| 9291 | 10073 | static const Jim_HashTableType JimVariablesHashTableType = { |
| 9292 | | - JimStringCopyHTHashFunction, |
| 9293 | | - JimStringCopyHTDup, |
| 9294 | | - NULL, |
| 9295 | | - JimStringCopyHTKeyCompare, |
| 9296 | | - JimStringCopyHTKeyDestructor, |
| 10074 | + JimObjectHTHashFunction, |
| 10075 | + JimObjectHTKeyValDup, |
| 10076 | + JimVariablesHTValDup, |
| 10077 | + JimObjectHTKeyCompare, |
| 10078 | + JimObjectHTKeyValDestructor, |
| 9297 | 10079 | JimVariablesHTValDestructor |
| 9298 | 10080 | }; |
| 9299 | 10081 | |
| 10082 | + |
| 10083 | +static const char *Jim_GetStringNoQualifier(Jim_Obj *objPtr, int *length) |
| 10084 | +{ |
| 10085 | + int len; |
| 10086 | + const char *str = Jim_GetString(objPtr, &len); |
| 10087 | + if (len >= 2 && str[0] == ':' && str[1] == ':') { |
| 10088 | + while (len && *str == ':') { |
| 10089 | + len--; |
| 10090 | + str++; |
| 10091 | + } |
| 10092 | + } |
| 10093 | + *length = len; |
| 10094 | + return str; |
| 10095 | +} |
| 10096 | + |
| 10097 | +static unsigned int JimCommandsHT_HashFunction(const void *key) |
| 10098 | +{ |
| 10099 | + int len; |
| 10100 | + const char *str = Jim_GetStringNoQualifier((Jim_Obj *)key, &len); |
| 10101 | + return Jim_GenHashFunction((const unsigned char *)str, len); |
| 10102 | +} |
| 10103 | + |
| 10104 | +static int JimCommandsHT_KeyCompare(void *privdata, const void *key1, const void *key2) |
| 10105 | +{ |
| 10106 | + int len1, len2; |
| 10107 | + const char *str1 = Jim_GetStringNoQualifier((Jim_Obj *)key1, &len1); |
| 10108 | + const char *str2 = Jim_GetStringNoQualifier((Jim_Obj *)key2, &len2); |
| 10109 | + return len1 == len2 && memcmp(str1, str2, len1) == 0; |
| 10110 | +} |
| 10111 | + |
| 9300 | 10112 | static void JimCommandsHT_ValDestructor(void *interp, void *val) |
| 9301 | 10113 | { |
| 9302 | 10114 | JimDecrCmdRefCount(interp, val); |
| 9303 | 10115 | } |
| 9304 | 10116 | |
| 9305 | 10117 | static const Jim_HashTableType JimCommandsHashTableType = { |
| 9306 | | - JimStringCopyHTHashFunction, |
| 9307 | | - JimStringCopyHTDup, |
| 10118 | + JimCommandsHT_HashFunction, |
| 10119 | + JimObjectHTKeyValDup, |
| 9308 | 10120 | NULL, |
| 9309 | | - JimStringCopyHTKeyCompare, |
| 9310 | | - JimStringCopyHTKeyDestructor, |
| 10121 | + JimCommandsHT_KeyCompare, |
| 10122 | + JimObjectHTKeyValDestructor, |
| 9311 | 10123 | JimCommandsHT_ValDestructor |
| 9312 | 10124 | }; |
| 9313 | 10125 | |
| 9314 | 10126 | |
| 9315 | 10127 | |
| 9316 | | -#ifdef jim_ext_namespace |
| 9317 | | -static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) |
| 9318 | | -{ |
| 9319 | | - const char *name = Jim_String(nsObj); |
| 9320 | | - if (name[0] == ':' && name[1] == ':') { |
| 9321 | | - |
| 9322 | | - while (*++name == ':') { |
| 9323 | | - } |
| 9324 | | - nsObj = Jim_NewStringObj(interp, name, -1); |
| 9325 | | - } |
| 9326 | | - else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9327 | | - |
| 9328 | | - nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9329 | | - Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 9330 | | - } |
| 9331 | | - return nsObj; |
| 9332 | | -} |
| 9333 | | - |
| 9334 | 10128 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9335 | 10129 | { |
| 10130 | +#ifdef jim_ext_namespace |
| 9336 | 10131 | Jim_Obj *resultObj; |
| 9337 | 10132 | |
| 9338 | 10133 | const char *name = Jim_String(nameObjPtr); |
| 9339 | 10134 | if (name[0] == ':' && name[1] == ':') { |
| 9340 | 10135 | return nameObjPtr; |
| | @@ -9343,71 +10138,54 @@ |
| 9343 | 10138 | resultObj = Jim_NewStringObj(interp, "::", -1); |
| 9344 | 10139 | Jim_AppendObj(interp, resultObj, nameObjPtr); |
| 9345 | 10140 | Jim_DecrRefCount(interp, nameObjPtr); |
| 9346 | 10141 | |
| 9347 | 10142 | return resultObj; |
| 9348 | | -} |
| 9349 | | - |
| 9350 | | -static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 9351 | | -{ |
| 9352 | | - Jim_Obj *objPtr = interp->emptyObj; |
| 9353 | | - |
| 9354 | | - if (name[0] == ':' && name[1] == ':') { |
| 9355 | | - |
| 9356 | | - while (*++name == ':') { |
| 9357 | | - } |
| 9358 | | - } |
| 9359 | | - else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9360 | | - |
| 9361 | | - objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9362 | | - Jim_AppendStrings(interp, objPtr, "::", name, NULL); |
| 9363 | | - name = Jim_String(objPtr); |
| 9364 | | - } |
| 9365 | | - Jim_IncrRefCount(objPtr); |
| 9366 | | - *objPtrPtr = objPtr; |
| 9367 | | - return name; |
| 9368 | | -} |
| 9369 | | - |
| 9370 | | - #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) |
| 9371 | | - |
| 9372 | | -#else |
| 9373 | | - |
| 9374 | | - #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 9375 | | - #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9376 | | - |
| 9377 | | -Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9378 | | -{ |
| 9379 | | - return nameObjPtr; |
| 9380 | | -} |
| 9381 | | -#endif |
| 9382 | | - |
| 9383 | | -static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) |
| 9384 | | -{ |
| 9385 | | - Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); |
| 9386 | | - if (he) { |
| 9387 | | - |
| 9388 | | - Jim_InterpIncrProcEpoch(interp); |
| 9389 | | - } |
| 9390 | | - |
| 9391 | | - if (he && interp->local) { |
| 9392 | | - |
| 9393 | | - cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9394 | | - Jim_SetHashVal(&interp->commands, he, cmd); |
| 9395 | | - } |
| 9396 | | - else { |
| 9397 | | - if (he) { |
| 9398 | | - |
| 9399 | | - Jim_DeleteHashEntry(&interp->commands, name); |
| 9400 | | - } |
| 9401 | | - |
| 9402 | | - Jim_AddHashEntry(&interp->commands, name, cmd); |
| 9403 | | - } |
| 9404 | | - return JIM_OK; |
| 9405 | | -} |
| 9406 | | - |
| 9407 | | - |
| 9408 | | -int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, |
| 10143 | +#else |
| 10144 | + return nameObjPtr; |
| 10145 | +#endif |
| 10146 | +} |
| 10147 | + |
| 10148 | +static Jim_Obj *JimQualifyName(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10149 | +{ |
| 10150 | +#ifdef jim_ext_namespace |
| 10151 | + if (Jim_Length(interp->framePtr->nsObj)) { |
| 10152 | + int len; |
| 10153 | + const char *name = Jim_GetString(objPtr, &len); |
| 10154 | + if (len < 2 || name[0] != ':' || name[1] != ':') { |
| 10155 | + |
| 10156 | + objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 10157 | + Jim_AppendStrings(interp, objPtr, "::", name, NULL); |
| 10158 | + } |
| 10159 | + } |
| 10160 | +#endif |
| 10161 | + Jim_IncrRefCount(objPtr); |
| 10162 | + return objPtr; |
| 10163 | +} |
| 10164 | + |
| 10165 | +static void JimCreateCommand(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Cmd *cmd) |
| 10166 | +{ |
| 10167 | + JimPanic((nameObjPtr->refCount == 0, "JimCreateCommand called with zero ref count name")); |
| 10168 | + |
| 10169 | + if (interp->local) { |
| 10170 | + Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, nameObjPtr); |
| 10171 | + if (he) { |
| 10172 | + |
| 10173 | + cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 10174 | + Jim_SetHashVal(&interp->commands, he, cmd); |
| 10175 | + |
| 10176 | + Jim_InterpIncrProcEpoch(interp); |
| 10177 | + return; |
| 10178 | + } |
| 10179 | + } |
| 10180 | + |
| 10181 | + |
| 10182 | + |
| 10183 | + Jim_ReplaceHashEntry(&interp->commands, nameObjPtr, cmd); |
| 10184 | +} |
| 10185 | + |
| 10186 | +int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj, |
| 9409 | 10187 | Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) |
| 9410 | 10188 | { |
| 9411 | 10189 | Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); |
| 9412 | 10190 | |
| 9413 | 10191 | |
| | @@ -9415,15 +10193,24 @@ |
| 9415 | 10193 | cmdPtr->inUse = 1; |
| 9416 | 10194 | cmdPtr->u.native.delProc = delProc; |
| 9417 | 10195 | cmdPtr->u.native.cmdProc = cmdProc; |
| 9418 | 10196 | cmdPtr->u.native.privData = privData; |
| 9419 | 10197 | |
| 9420 | | - JimCreateCommand(interp, cmdNameStr, cmdPtr); |
| 10198 | + Jim_IncrRefCount(cmdNameObj); |
| 10199 | + JimCreateCommand(interp, cmdNameObj, cmdPtr); |
| 10200 | + Jim_DecrRefCount(interp, cmdNameObj); |
| 9421 | 10201 | |
| 9422 | 10202 | return JIM_OK; |
| 9423 | 10203 | } |
| 9424 | 10204 | |
| 10205 | + |
| 10206 | +int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, |
| 10207 | + Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) |
| 10208 | +{ |
| 10209 | + return Jim_CreateCommandObj(interp, Jim_NewStringObj(interp, cmdNameStr, -1), cmdProc, privData, delProc); |
| 10210 | +} |
| 10211 | + |
| 9425 | 10212 | static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr) |
| 9426 | 10213 | { |
| 9427 | 10214 | int len, i; |
| 9428 | 10215 | |
| 9429 | 10216 | len = Jim_ListLength(interp, staticsListObjPtr); |
| | @@ -9432,72 +10219,129 @@ |
| 9432 | 10219 | } |
| 9433 | 10220 | |
| 9434 | 10221 | cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); |
| 9435 | 10222 | Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); |
| 9436 | 10223 | for (i = 0; i < len; i++) { |
| 9437 | | - Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 9438 | | - Jim_Var *varPtr; |
| 9439 | | - int subLen; |
| 9440 | | - |
| 9441 | | - objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 9442 | | - |
| 9443 | | - subLen = Jim_ListLength(interp, objPtr); |
| 9444 | | - if (subLen == 1 || subLen == 2) { |
| 9445 | | - nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 9446 | | - if (subLen == 1) { |
| 9447 | | - initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 9448 | | - if (initObjPtr == NULL) { |
| 9449 | | - Jim_SetResultFormatted(interp, |
| 9450 | | - "variable for initialization of static \"%#s\" not found in the local context", |
| 9451 | | - nameObjPtr); |
| 9452 | | - return JIM_ERR; |
| 9453 | | - } |
| 9454 | | - } |
| 9455 | | - else { |
| 9456 | | - initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); |
| 9457 | | - } |
| 9458 | | - if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { |
| 9459 | | - return JIM_ERR; |
| 9460 | | - } |
| 9461 | | - |
| 9462 | | - varPtr = Jim_Alloc(sizeof(*varPtr)); |
| 9463 | | - varPtr->objPtr = initObjPtr; |
| 9464 | | - Jim_IncrRefCount(initObjPtr); |
| 9465 | | - varPtr->linkFramePtr = NULL; |
| 9466 | | - if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars, |
| 9467 | | - Jim_String(nameObjPtr), varPtr) != JIM_OK) { |
| 9468 | | - Jim_SetResultFormatted(interp, |
| 9469 | | - "static variable name \"%#s\" duplicated in statics list", nameObjPtr); |
| 9470 | | - Jim_DecrRefCount(interp, initObjPtr); |
| 9471 | | - Jim_Free(varPtr); |
| 9472 | | - return JIM_ERR; |
| 9473 | | - } |
| 9474 | | - } |
| 9475 | | - else { |
| 10224 | + Jim_Obj *initObjPtr = NULL; |
| 10225 | + Jim_Obj *nameObjPtr; |
| 10226 | + Jim_VarVal *vv = NULL; |
| 10227 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 10228 | + int subLen = Jim_ListLength(interp, objPtr); |
| 10229 | + int byref = 0; |
| 10230 | + |
| 10231 | + |
| 10232 | + if (subLen != 1 && subLen != 2) { |
| 9476 | 10233 | Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"", |
| 9477 | 10234 | objPtr); |
| 9478 | 10235 | return JIM_ERR; |
| 9479 | 10236 | } |
| 10237 | + |
| 10238 | + nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 10239 | + |
| 10240 | + |
| 10241 | + if (subLen == 1) { |
| 10242 | + int len; |
| 10243 | + const char *pt = Jim_GetString(nameObjPtr, &len); |
| 10244 | + if (*pt == '&') { |
| 10245 | + |
| 10246 | + nameObjPtr = Jim_NewStringObj(interp, pt + 1, len - 1); |
| 10247 | + byref = 1; |
| 10248 | + } |
| 10249 | + } |
| 10250 | + Jim_IncrRefCount(nameObjPtr); |
| 10251 | + |
| 10252 | + if (subLen == 1) { |
| 10253 | + switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 10254 | + case JIM_DICT_SUGAR: |
| 10255 | + |
| 10256 | + if (byref) { |
| 10257 | + Jim_SetResultFormatted(interp, "Can't link to array element \"%#s\"", nameObjPtr); |
| 10258 | + } |
| 10259 | + else { |
| 10260 | + Jim_SetResultFormatted(interp, "Can't initialise array element \"%#s\"", nameObjPtr); |
| 10261 | + } |
| 10262 | + Jim_DecrRefCount(interp, nameObjPtr); |
| 10263 | + return JIM_ERR; |
| 10264 | + |
| 10265 | + case JIM_OK: |
| 10266 | + if (byref) { |
| 10267 | + vv = nameObjPtr->internalRep.varValue.vv; |
| 10268 | + } |
| 10269 | + else { |
| 10270 | + initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| 10271 | + } |
| 10272 | + break; |
| 10273 | + |
| 10274 | + case JIM_ERR: |
| 10275 | + |
| 10276 | + Jim_SetResultFormatted(interp, |
| 10277 | + "variable for initialization of static \"%#s\" not found in the local context", |
| 10278 | + nameObjPtr); |
| 10279 | + Jim_DecrRefCount(interp, nameObjPtr); |
| 10280 | + return JIM_ERR; |
| 10281 | + } |
| 10282 | + } |
| 10283 | + else { |
| 10284 | + initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); |
| 10285 | + } |
| 10286 | + |
| 10287 | + if (vv == NULL) { |
| 10288 | + vv = Jim_Alloc(sizeof(*vv)); |
| 10289 | + vv->objPtr = initObjPtr; |
| 10290 | + Jim_IncrRefCount(vv->objPtr); |
| 10291 | + vv->linkFramePtr = NULL; |
| 10292 | + vv->refCount = 0; |
| 10293 | + } |
| 10294 | + |
| 10295 | + if (JimSetNewVariable(cmdPtr->u.proc.staticVars, nameObjPtr, vv) != JIM_OK) { |
| 10296 | + Jim_SetResultFormatted(interp, |
| 10297 | + "static variable name \"%#s\" duplicated in statics list", nameObjPtr); |
| 10298 | + JimIncrVarRef(vv); |
| 10299 | + JimDecrVarRef(interp, vv); |
| 10300 | + Jim_DecrRefCount(interp, nameObjPtr); |
| 10301 | + return JIM_ERR; |
| 10302 | + } |
| 10303 | + |
| 10304 | + Jim_DecrRefCount(interp, nameObjPtr); |
| 9480 | 10305 | } |
| 9481 | 10306 | return JIM_OK; |
| 9482 | 10307 | } |
| 9483 | 10308 | |
| 9484 | | -static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) |
| 10309 | + |
| 10310 | +#ifdef jim_ext_namespace |
| 10311 | +static const char *Jim_memrchr(const char *p, int c, int len) |
| 10312 | +{ |
| 10313 | + int i; |
| 10314 | + for (i = len; i > 0; i--) { |
| 10315 | + if (p[i] == c) { |
| 10316 | + return p + i; |
| 10317 | + } |
| 10318 | + } |
| 10319 | + return NULL; |
| 10320 | +} |
| 10321 | +#endif |
| 10322 | + |
| 10323 | +static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *nameObjPtr) |
| 9485 | 10324 | { |
| 9486 | 10325 | #ifdef jim_ext_namespace |
| 9487 | 10326 | if (cmdPtr->isproc) { |
| 10327 | + int len; |
| 10328 | + const char *cmdname = Jim_GetStringNoQualifier(nameObjPtr, &len); |
| 9488 | 10329 | |
| 9489 | | - const char *pt = strrchr(cmdname, ':'); |
| 10330 | + const char *pt = Jim_memrchr(cmdname, ':', len); |
| 9490 | 10331 | if (pt && pt != cmdname && pt[-1] == ':') { |
| 10332 | + pt++; |
| 9491 | 10333 | Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); |
| 9492 | | - cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); |
| 10334 | + cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 2); |
| 9493 | 10335 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9494 | 10336 | |
| 9495 | | - if (Jim_FindHashEntry(&interp->commands, pt + 1)) { |
| 10337 | + Jim_Obj *tempObj = Jim_NewStringObj(interp, pt, len - (pt - cmdname)); |
| 10338 | + if (Jim_FindHashEntry(&interp->commands, tempObj)) { |
| 9496 | 10339 | |
| 9497 | 10340 | Jim_InterpIncrProcEpoch(interp); |
| 9498 | 10341 | } |
| 10342 | + Jim_FreeNewObj(interp, tempObj); |
| 9499 | 10343 | } |
| 9500 | 10344 | } |
| 9501 | 10345 | #endif |
| 9502 | 10346 | } |
| 9503 | 10347 | |
| | @@ -9510,10 +10354,11 @@ |
| 9510 | 10354 | |
| 9511 | 10355 | argListLen = Jim_ListLength(interp, argListObjPtr); |
| 9512 | 10356 | |
| 9513 | 10357 | |
| 9514 | 10358 | cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); |
| 10359 | + assert(cmdPtr); |
| 9515 | 10360 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9516 | 10361 | cmdPtr->inUse = 1; |
| 9517 | 10362 | cmdPtr->isproc = 1; |
| 9518 | 10363 | cmdPtr->u.proc.argListObjPtr = argListObjPtr; |
| 9519 | 10364 | cmdPtr->u.proc.argListLen = argListLen; |
| | @@ -9585,72 +10430,71 @@ |
| 9585 | 10430 | } |
| 9586 | 10431 | |
| 9587 | 10432 | return cmdPtr; |
| 9588 | 10433 | } |
| 9589 | 10434 | |
| 9590 | | -int Jim_DeleteCommand(Jim_Interp *interp, const char *name) |
| 10435 | +int Jim_DeleteCommand(Jim_Interp *interp, Jim_Obj *nameObj) |
| 9591 | 10436 | { |
| 9592 | 10437 | int ret = JIM_OK; |
| 9593 | | - Jim_Obj *qualifiedNameObj; |
| 9594 | | - const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj); |
| 9595 | 10438 | |
| 9596 | | - if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) { |
| 9597 | | - Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name); |
| 10439 | + nameObj = JimQualifyName(interp, nameObj); |
| 10440 | + |
| 10441 | + if (Jim_DeleteHashEntry(&interp->commands, nameObj) == JIM_ERR) { |
| 10442 | + Jim_SetResultFormatted(interp, "can't delete \"%#s\": command doesn't exist", nameObj); |
| 9598 | 10443 | ret = JIM_ERR; |
| 9599 | 10444 | } |
| 9600 | | - else { |
| 9601 | | - Jim_InterpIncrProcEpoch(interp); |
| 9602 | | - } |
| 9603 | | - |
| 9604 | | - JimFreeQualifiedName(interp, qualifiedNameObj); |
| 10445 | + Jim_DecrRefCount(interp, nameObj); |
| 9605 | 10446 | |
| 9606 | 10447 | return ret; |
| 9607 | 10448 | } |
| 9608 | 10449 | |
| 9609 | | -int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName) |
| 10450 | +int Jim_RenameCommand(Jim_Interp *interp, Jim_Obj *oldNameObj, Jim_Obj *newNameObj) |
| 9610 | 10451 | { |
| 9611 | 10452 | int ret = JIM_ERR; |
| 9612 | 10453 | Jim_HashEntry *he; |
| 9613 | 10454 | Jim_Cmd *cmdPtr; |
| 9614 | | - Jim_Obj *qualifiedOldNameObj; |
| 9615 | | - Jim_Obj *qualifiedNewNameObj; |
| 9616 | | - const char *fqold; |
| 9617 | | - const char *fqnew; |
| 9618 | 10455 | |
| 9619 | | - if (newName[0] == 0) { |
| 9620 | | - return Jim_DeleteCommand(interp, oldName); |
| 10456 | + if (Jim_Length(newNameObj) == 0) { |
| 10457 | + return Jim_DeleteCommand(interp, oldNameObj); |
| 9621 | 10458 | } |
| 9622 | 10459 | |
| 9623 | | - fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); |
| 9624 | | - fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); |
| 9625 | 10460 | |
| 9626 | 10461 | |
| 9627 | | - he = Jim_FindHashEntry(&interp->commands, fqold); |
| 10462 | + oldNameObj = JimQualifyName(interp, oldNameObj); |
| 10463 | + newNameObj = JimQualifyName(interp, newNameObj); |
| 10464 | + |
| 10465 | + |
| 10466 | + he = Jim_FindHashEntry(&interp->commands, oldNameObj); |
| 9628 | 10467 | if (he == NULL) { |
| 9629 | | - Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); |
| 10468 | + Jim_SetResultFormatted(interp, "can't rename \"%#s\": command doesn't exist", oldNameObj); |
| 9630 | 10469 | } |
| 9631 | | - else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9632 | | - Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 10470 | + else if (Jim_FindHashEntry(&interp->commands, newNameObj)) { |
| 10471 | + Jim_SetResultFormatted(interp, "can't rename to \"%#s\": command already exists", newNameObj); |
| 9633 | 10472 | } |
| 9634 | 10473 | else { |
| 9635 | | - |
| 9636 | 10474 | cmdPtr = Jim_GetHashEntryVal(he); |
| 9637 | | - JimIncrCmdRefCount(cmdPtr); |
| 9638 | | - JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9639 | | - Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9640 | | - |
| 9641 | | - |
| 9642 | | - Jim_DeleteHashEntry(&interp->commands, fqold); |
| 9643 | | - |
| 9644 | | - |
| 9645 | | - Jim_InterpIncrProcEpoch(interp); |
| 9646 | | - |
| 9647 | | - ret = JIM_OK; |
| 9648 | | - } |
| 9649 | | - |
| 9650 | | - JimFreeQualifiedName(interp, qualifiedOldNameObj); |
| 9651 | | - JimFreeQualifiedName(interp, qualifiedNewNameObj); |
| 10475 | + if (cmdPtr->prevCmd) { |
| 10476 | + Jim_SetResultFormatted(interp, "can't rename local command \"%#s\"", oldNameObj); |
| 10477 | + } |
| 10478 | + else { |
| 10479 | + |
| 10480 | + JimIncrCmdRefCount(cmdPtr); |
| 10481 | + JimUpdateProcNamespace(interp, cmdPtr, newNameObj); |
| 10482 | + Jim_AddHashEntry(&interp->commands, newNameObj, cmdPtr); |
| 10483 | + |
| 10484 | + |
| 10485 | + Jim_DeleteHashEntry(&interp->commands, oldNameObj); |
| 10486 | + |
| 10487 | + |
| 10488 | + Jim_InterpIncrProcEpoch(interp); |
| 10489 | + |
| 10490 | + ret = JIM_OK; |
| 10491 | + } |
| 10492 | + } |
| 10493 | + |
| 10494 | + Jim_DecrRefCount(interp, oldNameObj); |
| 10495 | + Jim_DecrRefCount(interp, newNameObj); |
| 9652 | 10496 | |
| 9653 | 10497 | return ret; |
| 9654 | 10498 | } |
| 9655 | 10499 | |
| 9656 | 10500 | |
| | @@ -9676,104 +10520,70 @@ |
| 9676 | 10520 | |
| 9677 | 10521 | Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 9678 | 10522 | { |
| 9679 | 10523 | Jim_Cmd *cmd; |
| 9680 | 10524 | |
| 9681 | | - if (objPtr->typePtr != &commandObjType || |
| 9682 | | - objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch |
| 9683 | | -#ifdef jim_ext_namespace |
| 9684 | | - || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) |
| 9685 | | -#endif |
| 9686 | | - ) { |
| 9687 | | - |
| 9688 | | - |
| 9689 | | - |
| 9690 | | - const char *name = Jim_String(objPtr); |
| 9691 | | - Jim_HashEntry *he; |
| 9692 | | - |
| 9693 | | - if (name[0] == ':' && name[1] == ':') { |
| 9694 | | - while (*++name == ':') { |
| 9695 | | - } |
| 9696 | | - } |
| 9697 | | -#ifdef jim_ext_namespace |
| 9698 | | - else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9699 | | - |
| 9700 | | - Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9701 | | - Jim_AppendStrings(interp, nameObj, "::", name, NULL); |
| 9702 | | - he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); |
| 9703 | | - Jim_FreeNewObj(interp, nameObj); |
| 9704 | | - if (he) { |
| 9705 | | - goto found; |
| 9706 | | - } |
| 9707 | | - } |
| 9708 | | -#endif |
| 9709 | | - |
| 9710 | | - |
| 9711 | | - he = Jim_FindHashEntry(&interp->commands, name); |
| 10525 | + if (objPtr->typePtr == &commandObjType |
| 10526 | + && objPtr->internalRep.cmdValue.procEpoch == interp->procEpoch |
| 10527 | +#ifdef jim_ext_namespace |
| 10528 | + && Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) |
| 10529 | +#endif |
| 10530 | + && objPtr->internalRep.cmdValue.cmdPtr->inUse) { |
| 10531 | + |
| 10532 | + cmd = objPtr->internalRep.cmdValue.cmdPtr; |
| 10533 | + } |
| 10534 | + else { |
| 10535 | + Jim_Obj *qualifiedNameObj = JimQualifyName(interp, objPtr); |
| 10536 | + Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, qualifiedNameObj); |
| 10537 | +#ifdef jim_ext_namespace |
| 10538 | + if (he == NULL && Jim_Length(interp->framePtr->nsObj)) { |
| 10539 | + he = Jim_FindHashEntry(&interp->commands, objPtr); |
| 10540 | + } |
| 10541 | +#endif |
| 9712 | 10542 | if (he == NULL) { |
| 9713 | 10543 | if (flags & JIM_ERRMSG) { |
| 9714 | 10544 | Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); |
| 9715 | 10545 | } |
| 10546 | + Jim_DecrRefCount(interp, qualifiedNameObj); |
| 9716 | 10547 | return NULL; |
| 9717 | 10548 | } |
| 9718 | | -#ifdef jim_ext_namespace |
| 9719 | | -found: |
| 9720 | | -#endif |
| 9721 | 10549 | cmd = Jim_GetHashEntryVal(he); |
| 10550 | + |
| 10551 | + cmd->cmdNameObj = Jim_GetHashEntryKey(he); |
| 9722 | 10552 | |
| 9723 | 10553 | |
| 9724 | 10554 | Jim_FreeIntRep(interp, objPtr); |
| 9725 | 10555 | objPtr->typePtr = &commandObjType; |
| 9726 | 10556 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| 9727 | 10557 | objPtr->internalRep.cmdValue.cmdPtr = cmd; |
| 9728 | 10558 | objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; |
| 9729 | 10559 | Jim_IncrRefCount(interp->framePtr->nsObj); |
| 9730 | | - } |
| 9731 | | - else { |
| 9732 | | - cmd = objPtr->internalRep.cmdValue.cmdPtr; |
| 10560 | + Jim_DecrRefCount(interp, qualifiedNameObj); |
| 9733 | 10561 | } |
| 9734 | 10562 | while (cmd->u.proc.upcall) { |
| 9735 | 10563 | cmd = cmd->prevCmd; |
| 9736 | 10564 | } |
| 9737 | 10565 | return cmd; |
| 9738 | 10566 | } |
| 9739 | 10567 | |
| 9740 | 10568 | |
| 9741 | 10569 | |
| 9742 | | -#define JIM_DICT_SUGAR 100 |
| 9743 | | - |
| 9744 | | -static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 9745 | | - |
| 9746 | 10570 | static const Jim_ObjType variableObjType = { |
| 9747 | 10571 | "variable", |
| 9748 | 10572 | NULL, |
| 9749 | 10573 | NULL, |
| 9750 | 10574 | NULL, |
| 9751 | 10575 | JIM_TYPE_REFERENCES, |
| 9752 | 10576 | }; |
| 9753 | 10577 | |
| 9754 | | -static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) |
| 9755 | | -{ |
| 9756 | | - |
| 9757 | | - if (nameObjPtr->typePtr != &variableObjType) { |
| 9758 | | - int len; |
| 9759 | | - const char *str = Jim_GetString(nameObjPtr, &len); |
| 9760 | | - if (memchr(str, '\0', len)) { |
| 9761 | | - Jim_SetResultFormatted(interp, "%s name contains embedded null", type); |
| 9762 | | - return JIM_ERR; |
| 9763 | | - } |
| 9764 | | - } |
| 9765 | | - return JIM_OK; |
| 9766 | | -} |
| 9767 | | - |
| 9768 | 10578 | static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 9769 | 10579 | { |
| 9770 | 10580 | const char *varName; |
| 9771 | 10581 | Jim_CallFrame *framePtr; |
| 9772 | | - Jim_HashEntry *he; |
| 9773 | 10582 | int global; |
| 9774 | 10583 | int len; |
| 10584 | + Jim_VarVal *vv; |
| 9775 | 10585 | |
| 9776 | 10586 | |
| 9777 | 10587 | if (objPtr->typePtr == &variableObjType) { |
| 9778 | 10588 | framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; |
| 9779 | 10589 | if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { |
| | @@ -9783,126 +10593,144 @@ |
| 9783 | 10593 | |
| 9784 | 10594 | } |
| 9785 | 10595 | else if (objPtr->typePtr == &dictSubstObjType) { |
| 9786 | 10596 | return JIM_DICT_SUGAR; |
| 9787 | 10597 | } |
| 9788 | | - else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { |
| 9789 | | - return JIM_ERR; |
| 9790 | | - } |
| 9791 | | - |
| 9792 | 10598 | |
| 9793 | 10599 | varName = Jim_GetString(objPtr, &len); |
| 9794 | 10600 | |
| 9795 | 10601 | |
| 9796 | 10602 | if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { |
| 9797 | 10603 | return JIM_DICT_SUGAR; |
| 9798 | 10604 | } |
| 9799 | 10605 | |
| 9800 | 10606 | if (varName[0] == ':' && varName[1] == ':') { |
| 9801 | | - while (*++varName == ':') { |
| 10607 | + while (*varName == ':') { |
| 10608 | + varName++; |
| 10609 | + len--; |
| 9802 | 10610 | } |
| 9803 | 10611 | global = 1; |
| 9804 | 10612 | framePtr = interp->topFramePtr; |
| 10613 | + |
| 10614 | + Jim_Obj *tempObj = Jim_NewStringObj(interp, varName, len); |
| 10615 | + vv = JimFindVariable(&framePtr->vars, tempObj); |
| 10616 | + Jim_FreeNewObj(interp, tempObj); |
| 9805 | 10617 | } |
| 9806 | 10618 | else { |
| 9807 | 10619 | global = 0; |
| 9808 | 10620 | framePtr = interp->framePtr; |
| 10621 | + |
| 10622 | + vv = JimFindVariable(&framePtr->vars, objPtr); |
| 10623 | + if (vv == NULL && framePtr->staticVars) { |
| 10624 | + |
| 10625 | + vv = JimFindVariable(framePtr->staticVars, objPtr); |
| 10626 | + } |
| 9809 | 10627 | } |
| 9810 | 10628 | |
| 9811 | | - |
| 9812 | | - he = Jim_FindHashEntry(&framePtr->vars, varName); |
| 9813 | | - if (he == NULL) { |
| 9814 | | - if (!global && framePtr->staticVars) { |
| 9815 | | - |
| 9816 | | - he = Jim_FindHashEntry(framePtr->staticVars, varName); |
| 9817 | | - } |
| 9818 | | - if (he == NULL) { |
| 9819 | | - return JIM_ERR; |
| 9820 | | - } |
| 10629 | + if (vv == NULL) { |
| 10630 | + return JIM_ERR; |
| 9821 | 10631 | } |
| 9822 | 10632 | |
| 9823 | 10633 | |
| 9824 | 10634 | Jim_FreeIntRep(interp, objPtr); |
| 9825 | 10635 | objPtr->typePtr = &variableObjType; |
| 9826 | 10636 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9827 | | - objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 10637 | + objPtr->internalRep.varValue.vv = vv; |
| 9828 | 10638 | objPtr->internalRep.varValue.global = global; |
| 9829 | 10639 | return JIM_OK; |
| 9830 | 10640 | } |
| 9831 | 10641 | |
| 9832 | 10642 | |
| 9833 | 10643 | static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr); |
| 9834 | 10644 | static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags); |
| 9835 | 10645 | |
| 9836 | | -static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) |
| 10646 | +static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv) |
| 10647 | +{ |
| 10648 | + return Jim_AddHashEntry(ht, nameObjPtr, vv); |
| 10649 | +} |
| 10650 | + |
| 10651 | +static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr) |
| 10652 | +{ |
| 10653 | + Jim_HashEntry *he = Jim_FindHashEntry(ht, nameObjPtr); |
| 10654 | + if (he) { |
| 10655 | + return (Jim_VarVal *)Jim_GetHashEntryVal(he); |
| 10656 | + } |
| 10657 | + return NULL; |
| 10658 | +} |
| 10659 | + |
| 10660 | +static int JimUnsetVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr) |
| 10661 | +{ |
| 10662 | + return Jim_DeleteHashEntry(ht, nameObjPtr); |
| 10663 | +} |
| 10664 | + |
| 10665 | +static Jim_VarVal *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) |
| 9837 | 10666 | { |
| 9838 | 10667 | const char *name; |
| 9839 | 10668 | Jim_CallFrame *framePtr; |
| 9840 | 10669 | int global; |
| 10670 | + int len; |
| 9841 | 10671 | |
| 9842 | 10672 | |
| 9843 | | - Jim_Var *var = Jim_Alloc(sizeof(*var)); |
| 10673 | + Jim_VarVal *vv = Jim_Alloc(sizeof(*vv)); |
| 9844 | 10674 | |
| 9845 | | - var->objPtr = valObjPtr; |
| 10675 | + vv->objPtr = valObjPtr; |
| 9846 | 10676 | Jim_IncrRefCount(valObjPtr); |
| 9847 | | - var->linkFramePtr = NULL; |
| 10677 | + vv->linkFramePtr = NULL; |
| 10678 | + vv->refCount = 0; |
| 9848 | 10679 | |
| 9849 | | - name = Jim_String(nameObjPtr); |
| 10680 | + name = Jim_GetString(nameObjPtr, &len); |
| 9850 | 10681 | if (name[0] == ':' && name[1] == ':') { |
| 9851 | | - while (*++name == ':') { |
| 10682 | + while (*name == ':') { |
| 10683 | + name++; |
| 10684 | + len--; |
| 9852 | 10685 | } |
| 9853 | 10686 | framePtr = interp->topFramePtr; |
| 9854 | 10687 | global = 1; |
| 10688 | + JimSetNewVariable(&framePtr->vars, Jim_NewStringObj(interp, name, len), vv); |
| 9855 | 10689 | } |
| 9856 | 10690 | else { |
| 9857 | 10691 | framePtr = interp->framePtr; |
| 9858 | 10692 | global = 0; |
| 10693 | + JimSetNewVariable(&framePtr->vars, nameObjPtr, vv); |
| 9859 | 10694 | } |
| 9860 | 10695 | |
| 9861 | | - |
| 9862 | | - Jim_AddHashEntry(&framePtr->vars, name, var); |
| 9863 | | - |
| 9864 | 10696 | |
| 9865 | 10697 | Jim_FreeIntRep(interp, nameObjPtr); |
| 9866 | 10698 | nameObjPtr->typePtr = &variableObjType; |
| 9867 | 10699 | nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9868 | | - nameObjPtr->internalRep.varValue.varPtr = var; |
| 10700 | + nameObjPtr->internalRep.varValue.vv = vv; |
| 9869 | 10701 | nameObjPtr->internalRep.varValue.global = global; |
| 9870 | 10702 | |
| 9871 | | - return var; |
| 10703 | + return vv; |
| 9872 | 10704 | } |
| 9873 | | - |
| 9874 | 10705 | |
| 9875 | 10706 | int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) |
| 9876 | 10707 | { |
| 9877 | 10708 | int err; |
| 9878 | | - Jim_Var *var; |
| 10709 | + Jim_VarVal *vv; |
| 9879 | 10710 | |
| 9880 | 10711 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 9881 | 10712 | case JIM_DICT_SUGAR: |
| 9882 | 10713 | return JimDictSugarSet(interp, nameObjPtr, valObjPtr); |
| 9883 | 10714 | |
| 9884 | 10715 | case JIM_ERR: |
| 9885 | | - if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) { |
| 9886 | | - return JIM_ERR; |
| 9887 | | - } |
| 9888 | 10716 | JimCreateVariable(interp, nameObjPtr, valObjPtr); |
| 9889 | 10717 | break; |
| 9890 | 10718 | |
| 9891 | 10719 | case JIM_OK: |
| 9892 | | - var = nameObjPtr->internalRep.varValue.varPtr; |
| 9893 | | - if (var->linkFramePtr == NULL) { |
| 10720 | + vv = nameObjPtr->internalRep.varValue.vv; |
| 10721 | + if (vv->linkFramePtr == NULL) { |
| 9894 | 10722 | Jim_IncrRefCount(valObjPtr); |
| 9895 | | - Jim_DecrRefCount(interp, var->objPtr); |
| 9896 | | - var->objPtr = valObjPtr; |
| 10723 | + Jim_DecrRefCount(interp, vv->objPtr); |
| 10724 | + vv->objPtr = valObjPtr; |
| 9897 | 10725 | } |
| 9898 | 10726 | else { |
| 9899 | 10727 | Jim_CallFrame *savedCallFrame; |
| 9900 | 10728 | |
| 9901 | 10729 | savedCallFrame = interp->framePtr; |
| 9902 | | - interp->framePtr = var->linkFramePtr; |
| 9903 | | - err = Jim_SetVariable(interp, var->objPtr, valObjPtr); |
| 10730 | + interp->framePtr = vv->linkFramePtr; |
| 10731 | + err = Jim_SetVariable(interp, vv->objPtr, valObjPtr); |
| 9904 | 10732 | interp->framePtr = savedCallFrame; |
| 9905 | 10733 | if (err != JIM_OK) |
| 9906 | 10734 | return err; |
| 9907 | 10735 | } |
| 9908 | 10736 | } |
| | @@ -9949,51 +10777,57 @@ |
| 9949 | 10777 | Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) |
| 9950 | 10778 | { |
| 9951 | 10779 | const char *varName; |
| 9952 | 10780 | const char *targetName; |
| 9953 | 10781 | Jim_CallFrame *framePtr; |
| 9954 | | - Jim_Var *varPtr; |
| 10782 | + Jim_VarVal *vv; |
| 10783 | + int len; |
| 10784 | + int varnamelen; |
| 9955 | 10785 | |
| 9956 | 10786 | |
| 9957 | 10787 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 9958 | 10788 | case JIM_DICT_SUGAR: |
| 9959 | 10789 | |
| 9960 | 10790 | Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); |
| 9961 | 10791 | return JIM_ERR; |
| 9962 | 10792 | |
| 9963 | 10793 | case JIM_OK: |
| 9964 | | - varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10794 | + vv = nameObjPtr->internalRep.varValue.vv; |
| 9965 | 10795 | |
| 9966 | | - if (varPtr->linkFramePtr == NULL) { |
| 10796 | + if (vv->linkFramePtr == NULL) { |
| 9967 | 10797 | Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); |
| 9968 | 10798 | return JIM_ERR; |
| 9969 | 10799 | } |
| 9970 | 10800 | |
| 9971 | 10801 | |
| 9972 | | - varPtr->linkFramePtr = NULL; |
| 10802 | + vv->linkFramePtr = NULL; |
| 9973 | 10803 | break; |
| 9974 | 10804 | } |
| 9975 | 10805 | |
| 9976 | 10806 | |
| 9977 | 10807 | |
| 9978 | | - varName = Jim_String(nameObjPtr); |
| 10808 | + varName = Jim_GetString(nameObjPtr, &varnamelen); |
| 9979 | 10809 | |
| 9980 | 10810 | if (varName[0] == ':' && varName[1] == ':') { |
| 9981 | | - while (*++varName == ':') { |
| 10811 | + while (*varName == ':') { |
| 10812 | + varName++; |
| 10813 | + varnamelen--; |
| 9982 | 10814 | } |
| 9983 | 10815 | |
| 9984 | 10816 | framePtr = interp->topFramePtr; |
| 9985 | 10817 | } |
| 9986 | 10818 | else { |
| 9987 | 10819 | framePtr = interp->framePtr; |
| 9988 | 10820 | } |
| 9989 | 10821 | |
| 9990 | | - targetName = Jim_String(targetNameObjPtr); |
| 10822 | + targetName = Jim_GetString(targetNameObjPtr, &len); |
| 9991 | 10823 | if (targetName[0] == ':' && targetName[1] == ':') { |
| 9992 | | - while (*++targetName == ':') { |
| 10824 | + while (*targetName == ':') { |
| 10825 | + targetName++; |
| 10826 | + len--; |
| 9993 | 10827 | } |
| 9994 | | - targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1); |
| 10828 | + targetNameObjPtr = Jim_NewStringObj(interp, targetName, len); |
| 9995 | 10829 | targetCallFrame = interp->topFramePtr; |
| 9996 | 10830 | } |
| 9997 | 10831 | Jim_IncrRefCount(targetNameObjPtr); |
| 9998 | 10832 | |
| 9999 | 10833 | if (framePtr->level < targetCallFrame->level) { |
| | @@ -10008,49 +10842,52 @@ |
| 10008 | 10842 | if (framePtr == targetCallFrame) { |
| 10009 | 10843 | Jim_Obj *objPtr = targetNameObjPtr; |
| 10010 | 10844 | |
| 10011 | 10845 | |
| 10012 | 10846 | while (1) { |
| 10013 | | - if (strcmp(Jim_String(objPtr), varName) == 0) { |
| 10847 | + if (Jim_Length(objPtr) == varnamelen && memcmp(Jim_String(objPtr), varName, varnamelen) == 0) { |
| 10014 | 10848 | Jim_SetResultString(interp, "can't upvar from variable to itself", -1); |
| 10015 | 10849 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 10016 | 10850 | return JIM_ERR; |
| 10017 | 10851 | } |
| 10018 | 10852 | if (SetVariableFromAny(interp, objPtr) != JIM_OK) |
| 10019 | 10853 | break; |
| 10020 | | - varPtr = objPtr->internalRep.varValue.varPtr; |
| 10021 | | - if (varPtr->linkFramePtr != targetCallFrame) |
| 10854 | + vv = objPtr->internalRep.varValue.vv; |
| 10855 | + if (vv->linkFramePtr != targetCallFrame) |
| 10022 | 10856 | break; |
| 10023 | | - objPtr = varPtr->objPtr; |
| 10857 | + objPtr = vv->objPtr; |
| 10024 | 10858 | } |
| 10025 | 10859 | } |
| 10026 | 10860 | |
| 10027 | 10861 | |
| 10028 | 10862 | Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); |
| 10029 | 10863 | |
| 10030 | | - nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; |
| 10864 | + nameObjPtr->internalRep.varValue.vv->linkFramePtr = targetCallFrame; |
| 10031 | 10865 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 10032 | 10866 | return JIM_OK; |
| 10033 | 10867 | } |
| 10034 | 10868 | |
| 10035 | 10869 | Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) |
| 10036 | 10870 | { |
| 10871 | + if (interp->safeexpr) { |
| 10872 | + return nameObjPtr; |
| 10873 | + } |
| 10037 | 10874 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 10038 | 10875 | case JIM_OK:{ |
| 10039 | | - Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10876 | + Jim_VarVal *vv = nameObjPtr->internalRep.varValue.vv; |
| 10040 | 10877 | |
| 10041 | | - if (varPtr->linkFramePtr == NULL) { |
| 10042 | | - return varPtr->objPtr; |
| 10878 | + if (vv->linkFramePtr == NULL) { |
| 10879 | + return vv->objPtr; |
| 10043 | 10880 | } |
| 10044 | 10881 | else { |
| 10045 | 10882 | Jim_Obj *objPtr; |
| 10046 | 10883 | |
| 10047 | 10884 | |
| 10048 | 10885 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 10049 | 10886 | |
| 10050 | | - interp->framePtr = varPtr->linkFramePtr; |
| 10051 | | - objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); |
| 10887 | + interp->framePtr = vv->linkFramePtr; |
| 10888 | + objPtr = Jim_GetVariable(interp, vv->objPtr, flags); |
| 10052 | 10889 | interp->framePtr = savedCallFrame; |
| 10053 | 10890 | if (objPtr) { |
| 10054 | 10891 | return objPtr; |
| 10055 | 10892 | } |
| 10056 | 10893 | |
| | @@ -10105,40 +10942,47 @@ |
| 10105 | 10942 | return objPtr; |
| 10106 | 10943 | } |
| 10107 | 10944 | |
| 10108 | 10945 | int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) |
| 10109 | 10946 | { |
| 10110 | | - Jim_Var *varPtr; |
| 10947 | + Jim_VarVal *vv; |
| 10111 | 10948 | int retval; |
| 10112 | 10949 | Jim_CallFrame *framePtr; |
| 10113 | 10950 | |
| 10114 | 10951 | retval = SetVariableFromAny(interp, nameObjPtr); |
| 10115 | 10952 | if (retval == JIM_DICT_SUGAR) { |
| 10116 | 10953 | |
| 10117 | 10954 | return JimDictSugarSet(interp, nameObjPtr, NULL); |
| 10118 | 10955 | } |
| 10119 | 10956 | else if (retval == JIM_OK) { |
| 10120 | | - varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10957 | + vv = nameObjPtr->internalRep.varValue.vv; |
| 10121 | 10958 | |
| 10122 | 10959 | |
| 10123 | | - if (varPtr->linkFramePtr) { |
| 10960 | + if (vv->linkFramePtr) { |
| 10124 | 10961 | framePtr = interp->framePtr; |
| 10125 | | - interp->framePtr = varPtr->linkFramePtr; |
| 10126 | | - retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); |
| 10962 | + interp->framePtr = vv->linkFramePtr; |
| 10963 | + retval = Jim_UnsetVariable(interp, vv->objPtr, JIM_NONE); |
| 10127 | 10964 | interp->framePtr = framePtr; |
| 10128 | 10965 | } |
| 10129 | 10966 | else { |
| 10130 | | - const char *name = Jim_String(nameObjPtr); |
| 10131 | 10967 | if (nameObjPtr->internalRep.varValue.global) { |
| 10132 | | - name += 2; |
| 10968 | + int len; |
| 10969 | + const char *name = Jim_GetString(nameObjPtr, &len); |
| 10970 | + while (*name == ':') { |
| 10971 | + name++; |
| 10972 | + len--; |
| 10973 | + } |
| 10133 | 10974 | framePtr = interp->topFramePtr; |
| 10975 | + Jim_Obj *tempObj = Jim_NewStringObj(interp, name, len); |
| 10976 | + retval = JimUnsetVariable(&framePtr->vars, tempObj); |
| 10977 | + Jim_FreeNewObj(interp, tempObj); |
| 10134 | 10978 | } |
| 10135 | 10979 | else { |
| 10136 | 10980 | framePtr = interp->framePtr; |
| 10981 | + retval = JimUnsetVariable(&framePtr->vars, nameObjPtr); |
| 10137 | 10982 | } |
| 10138 | 10983 | |
| 10139 | | - retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 10140 | 10984 | if (retval == JIM_OK) { |
| 10141 | 10985 | |
| 10142 | 10986 | framePtr->id = interp->callFrameEpoch++; |
| 10143 | 10987 | } |
| 10144 | 10988 | } |
| | @@ -10290,10 +11134,14 @@ |
| 10290 | 11134 | |
| 10291 | 11135 | static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10292 | 11136 | { |
| 10293 | 11137 | Jim_Obj *resObjPtr = NULL; |
| 10294 | 11138 | Jim_Obj *substKeyObjPtr = NULL; |
| 11139 | + |
| 11140 | + if (interp->safeexpr) { |
| 11141 | + return objPtr; |
| 11142 | + } |
| 10295 | 11143 | |
| 10296 | 11144 | SetDictSubstFromAny(interp, objPtr); |
| 10297 | 11145 | |
| 10298 | 11146 | if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr, |
| 10299 | 11147 | &substKeyObjPtr, JIM_NONE) |
| | @@ -10307,18 +11155,10 @@ |
| 10307 | 11155 | Jim_DecrRefCount(interp, substKeyObjPtr); |
| 10308 | 11156 | |
| 10309 | 11157 | return resObjPtr; |
| 10310 | 11158 | } |
| 10311 | 11159 | |
| 10312 | | -static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10313 | | -{ |
| 10314 | | - if (Jim_EvalExpression(interp, objPtr) == JIM_OK) { |
| 10315 | | - return Jim_GetResult(interp); |
| 10316 | | - } |
| 10317 | | - return NULL; |
| 10318 | | -} |
| 10319 | | - |
| 10320 | 11160 | |
| 10321 | 11161 | static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj) |
| 10322 | 11162 | { |
| 10323 | 11163 | Jim_CallFrame *cf; |
| 10324 | 11164 | |
| | @@ -10357,18 +11197,12 @@ |
| 10357 | 11197 | |
| 10358 | 11198 | if (localCommands) { |
| 10359 | 11199 | Jim_Obj *cmdNameObj; |
| 10360 | 11200 | |
| 10361 | 11201 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 10362 | | - Jim_HashEntry *he; |
| 10363 | | - Jim_Obj *fqObjName; |
| 10364 | 11202 | Jim_HashTable *ht = &interp->commands; |
| 10365 | | - |
| 10366 | | - const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); |
| 10367 | | - |
| 10368 | | - he = Jim_FindHashEntry(ht, fqname); |
| 10369 | | - |
| 11203 | + Jim_HashEntry *he = Jim_FindHashEntry(ht, cmdNameObj); |
| 10370 | 11204 | if (he) { |
| 10371 | 11205 | Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 10372 | 11206 | if (cmd->prevCmd) { |
| 10373 | 11207 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 10374 | 11208 | cmd->prevCmd = NULL; |
| | @@ -10378,16 +11212,14 @@ |
| 10378 | 11212 | |
| 10379 | 11213 | |
| 10380 | 11214 | Jim_SetHashVal(ht, he, prevCmd); |
| 10381 | 11215 | } |
| 10382 | 11216 | else { |
| 10383 | | - Jim_DeleteHashEntry(ht, fqname); |
| 11217 | + Jim_DeleteHashEntry(ht, cmdNameObj); |
| 10384 | 11218 | } |
| 10385 | | - Jim_InterpIncrProcEpoch(interp); |
| 10386 | 11219 | } |
| 10387 | 11220 | Jim_DecrRefCount(interp, cmdNameObj); |
| 10388 | | - JimFreeQualifiedName(interp, fqObjName); |
| 10389 | 11221 | } |
| 10390 | 11222 | Jim_FreeStack(localCommands); |
| 10391 | 11223 | Jim_Free(localCommands); |
| 10392 | 11224 | } |
| 10393 | 11225 | return JIM_OK; |
| | @@ -10396,15 +11228,14 @@ |
| 10396 | 11228 | static int JimInvokeDefer(Jim_Interp *interp, int retcode) |
| 10397 | 11229 | { |
| 10398 | 11230 | Jim_Obj *objPtr; |
| 10399 | 11231 | |
| 10400 | 11232 | |
| 10401 | | - if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) { |
| 11233 | + if (JimFindVariable(&interp->framePtr->vars, interp->defer) == NULL) { |
| 10402 | 11234 | return retcode; |
| 10403 | 11235 | } |
| 10404 | | - |
| 10405 | | - objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE); |
| 11236 | + objPtr = Jim_GetVariable(interp, interp->defer, JIM_NONE); |
| 10406 | 11237 | |
| 10407 | 11238 | if (objPtr) { |
| 10408 | 11239 | int ret = JIM_OK; |
| 10409 | 11240 | int i; |
| 10410 | 11241 | int listLen = Jim_ListLength(interp, objPtr); |
| | @@ -10452,28 +11283,11 @@ |
| 10452 | 11283 | Jim_DecrRefCount(interp, cf->procBodyObjPtr); |
| 10453 | 11284 | Jim_DecrRefCount(interp, cf->nsObj); |
| 10454 | 11285 | if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) |
| 10455 | 11286 | Jim_FreeHashTable(&cf->vars); |
| 10456 | 11287 | else { |
| 10457 | | - int i; |
| 10458 | | - Jim_HashEntry **table = cf->vars.table, *he; |
| 10459 | | - |
| 10460 | | - for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { |
| 10461 | | - he = table[i]; |
| 10462 | | - while (he != NULL) { |
| 10463 | | - Jim_HashEntry *nextEntry = he->next; |
| 10464 | | - Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 10465 | | - |
| 10466 | | - Jim_DecrRefCount(interp, varPtr->objPtr); |
| 10467 | | - Jim_Free(Jim_GetHashEntryKey(he)); |
| 10468 | | - Jim_Free(varPtr); |
| 10469 | | - Jim_Free(he); |
| 10470 | | - table[i] = NULL; |
| 10471 | | - he = nextEntry; |
| 10472 | | - } |
| 10473 | | - } |
| 10474 | | - cf->vars.used = 0; |
| 11288 | + Jim_ClearHashTable(&cf->vars); |
| 10475 | 11289 | } |
| 10476 | 11290 | cf->next = interp->freeFramesList; |
| 10477 | 11291 | interp->freeFramesList = cf; |
| 10478 | 11292 | } |
| 10479 | 11293 | |
| | @@ -10496,11 +11310,11 @@ |
| 10496 | 11310 | |
| 10497 | 11311 | memset(i, 0, sizeof(*i)); |
| 10498 | 11312 | |
| 10499 | 11313 | i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH; |
| 10500 | 11314 | i->maxEvalDepth = JIM_MAX_EVAL_DEPTH; |
| 10501 | | - i->lastCollectTime = time(NULL); |
| 11315 | + i->lastCollectTime = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW); |
| 10502 | 11316 | |
| 10503 | 11317 | Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i); |
| 10504 | 11318 | #ifdef JIM_REFERENCES |
| 10505 | 11319 | Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); |
| 10506 | 11320 | #endif |
| | @@ -10508,27 +11322,28 @@ |
| 10508 | 11322 | Jim_InitHashTable(&i->packages, &JimPackageHashTableType, NULL); |
| 10509 | 11323 | i->emptyObj = Jim_NewEmptyStringObj(i); |
| 10510 | 11324 | i->trueObj = Jim_NewIntObj(i, 1); |
| 10511 | 11325 | i->falseObj = Jim_NewIntObj(i, 0); |
| 10512 | 11326 | i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj); |
| 10513 | | - i->errorFileNameObj = i->emptyObj; |
| 10514 | 11327 | i->result = i->emptyObj; |
| 10515 | 11328 | i->stackTrace = Jim_NewListObj(i, NULL, 0); |
| 10516 | 11329 | i->unknown = Jim_NewStringObj(i, "unknown", -1); |
| 11330 | + i->defer = Jim_NewStringObj(i, "jim::defer", -1); |
| 10517 | 11331 | i->errorProc = i->emptyObj; |
| 10518 | | - i->currentScriptObj = Jim_NewEmptyStringObj(i); |
| 10519 | 11332 | i->nullScriptObj = Jim_NewEmptyStringObj(i); |
| 11333 | + i->evalFrame = &i->topEvalFrame; |
| 11334 | + i->currentFilenameObj = Jim_NewEmptyStringObj(i); |
| 10520 | 11335 | Jim_IncrRefCount(i->emptyObj); |
| 10521 | | - Jim_IncrRefCount(i->errorFileNameObj); |
| 10522 | 11336 | Jim_IncrRefCount(i->result); |
| 10523 | 11337 | Jim_IncrRefCount(i->stackTrace); |
| 10524 | 11338 | Jim_IncrRefCount(i->unknown); |
| 10525 | | - Jim_IncrRefCount(i->currentScriptObj); |
| 11339 | + Jim_IncrRefCount(i->defer); |
| 10526 | 11340 | Jim_IncrRefCount(i->nullScriptObj); |
| 10527 | 11341 | Jim_IncrRefCount(i->errorProc); |
| 10528 | 11342 | Jim_IncrRefCount(i->trueObj); |
| 10529 | 11343 | Jim_IncrRefCount(i->falseObj); |
| 11344 | + Jim_IncrRefCount(i->currentFilenameObj); |
| 10530 | 11345 | |
| 10531 | 11346 | |
| 10532 | 11347 | Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); |
| 10533 | 11348 | Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); |
| 10534 | 11349 | |
| | @@ -10536,21 +11351,25 @@ |
| 10536 | 11351 | Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); |
| 10537 | 11352 | Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); |
| 10538 | 11353 | Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); |
| 10539 | 11354 | Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian"); |
| 10540 | 11355 | Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); |
| 11356 | + Jim_SetVariableStrWithStr(i, "tcl_platform(bootstrap)", "0"); |
| 10541 | 11357 | Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); |
| 10542 | 11358 | Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); |
| 11359 | + Jim_SetVariableStr(i, "tcl_platform(stackFormat)", Jim_NewIntObj(i, 4)); |
| 10543 | 11360 | |
| 10544 | 11361 | return i; |
| 10545 | 11362 | } |
| 10546 | 11363 | |
| 10547 | 11364 | void Jim_FreeInterp(Jim_Interp *i) |
| 10548 | 11365 | { |
| 10549 | 11366 | Jim_CallFrame *cf, *cfx; |
| 10550 | 11367 | |
| 10551 | 11368 | Jim_Obj *objPtr, *nextObjPtr; |
| 11369 | + |
| 11370 | + i->quitting = 1; |
| 10552 | 11371 | |
| 10553 | 11372 | |
| 10554 | 11373 | for (cf = i->framePtr; cf; cf = cfx) { |
| 10555 | 11374 | |
| 10556 | 11375 | JimInvokeDefer(i, JIM_OK); |
| | @@ -10563,20 +11382,27 @@ |
| 10563 | 11382 | Jim_DecrRefCount(i, i->falseObj); |
| 10564 | 11383 | Jim_DecrRefCount(i, i->result); |
| 10565 | 11384 | Jim_DecrRefCount(i, i->stackTrace); |
| 10566 | 11385 | Jim_DecrRefCount(i, i->errorProc); |
| 10567 | 11386 | Jim_DecrRefCount(i, i->unknown); |
| 10568 | | - Jim_DecrRefCount(i, i->errorFileNameObj); |
| 10569 | | - Jim_DecrRefCount(i, i->currentScriptObj); |
| 11387 | + Jim_DecrRefCount(i, i->defer); |
| 10570 | 11388 | Jim_DecrRefCount(i, i->nullScriptObj); |
| 11389 | + Jim_DecrRefCount(i, i->currentFilenameObj); |
| 11390 | + |
| 11391 | + |
| 11392 | + Jim_InterpIncrProcEpoch(i); |
| 11393 | + |
| 10571 | 11394 | Jim_FreeHashTable(&i->commands); |
| 10572 | 11395 | #ifdef JIM_REFERENCES |
| 10573 | 11396 | Jim_FreeHashTable(&i->references); |
| 10574 | 11397 | #endif |
| 10575 | 11398 | Jim_FreeHashTable(&i->packages); |
| 10576 | 11399 | Jim_Free(i->prngState); |
| 10577 | 11400 | Jim_FreeHashTable(&i->assocData); |
| 11401 | + if (i->traceCmdObj) { |
| 11402 | + Jim_DecrRefCount(i, i->traceCmdObj); |
| 11403 | + } |
| 10578 | 11404 | |
| 10579 | 11405 | #ifdef JIM_MAINTAINER |
| 10580 | 11406 | if (i->liveList != NULL) { |
| 10581 | 11407 | objPtr = i->liveList; |
| 10582 | 11408 | |
| | @@ -10671,102 +11497,115 @@ |
| 10671 | 11497 | |
| 10672 | 11498 | Jim_SetResultFormatted(interp, "bad level \"%s\"", str); |
| 10673 | 11499 | return NULL; |
| 10674 | 11500 | } |
| 10675 | 11501 | |
| 10676 | | -static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr) |
| 11502 | +static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, long level) |
| 10677 | 11503 | { |
| 10678 | | - long level; |
| 10679 | 11504 | Jim_CallFrame *framePtr; |
| 10680 | 11505 | |
| 10681 | | - if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 10682 | | - if (level <= 0) { |
| 10683 | | - |
| 10684 | | - level = interp->framePtr->level + level; |
| 10685 | | - } |
| 10686 | | - |
| 10687 | | - if (level == 0) { |
| 10688 | | - return interp->topFramePtr; |
| 10689 | | - } |
| 10690 | | - |
| 11506 | + if (level == 0) { |
| 11507 | + return interp->framePtr; |
| 11508 | + } |
| 11509 | + |
| 11510 | + if (level < 0) { |
| 11511 | + |
| 11512 | + level = interp->framePtr->level + level; |
| 11513 | + } |
| 11514 | + |
| 11515 | + if (level > 0) { |
| 10691 | 11516 | |
| 10692 | 11517 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10693 | 11518 | if (framePtr->level == level) { |
| 10694 | 11519 | return framePtr; |
| 10695 | 11520 | } |
| 10696 | 11521 | } |
| 10697 | 11522 | } |
| 11523 | + return NULL; |
| 11524 | +} |
| 10698 | 11525 | |
| 10699 | | - Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 11526 | +static Jim_EvalFrame *JimGetEvalFrameByProcLevel(Jim_Interp *interp, int proclevel) |
| 11527 | +{ |
| 11528 | + Jim_EvalFrame *evalFrame; |
| 11529 | + |
| 11530 | + if (proclevel == 0) { |
| 11531 | + return interp->evalFrame; |
| 11532 | + } |
| 11533 | + |
| 11534 | + if (proclevel < 0) { |
| 11535 | + |
| 11536 | + proclevel = interp->procLevel + proclevel; |
| 11537 | + } |
| 11538 | + |
| 11539 | + if (proclevel >= 0) { |
| 11540 | + |
| 11541 | + for (evalFrame = interp->evalFrame; evalFrame; evalFrame = evalFrame->parent) { |
| 11542 | + if (evalFrame->procLevel == proclevel) { |
| 11543 | + return evalFrame; |
| 11544 | + } |
| 11545 | + } |
| 11546 | + } |
| 11547 | + return NULL; |
| 11548 | +} |
| 11549 | + |
| 11550 | +static Jim_Obj *JimProcForEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame) |
| 11551 | +{ |
| 11552 | + if (frame == interp->evalFrame || (frame->cmd && frame->cmd->cmdNameObj)) { |
| 11553 | + Jim_EvalFrame *e; |
| 11554 | + for (e = frame->parent; e; e = e->parent) { |
| 11555 | + if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) { |
| 11556 | + break; |
| 11557 | + } |
| 11558 | + } |
| 11559 | + if (e && e->cmd && e->cmd->cmdNameObj) { |
| 11560 | + return e->cmd->cmdNameObj; |
| 11561 | + } |
| 11562 | + } |
| 10700 | 11563 | return NULL; |
| 10701 | 11564 | } |
| 10702 | 11565 | |
| 10703 | | -static void JimResetStackTrace(Jim_Interp *interp) |
| 11566 | +static void JimAddStackFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *listObj) |
| 10704 | 11567 | { |
| 10705 | | - Jim_DecrRefCount(interp, interp->stackTrace); |
| 10706 | | - interp->stackTrace = Jim_NewListObj(interp, NULL, 0); |
| 10707 | | - Jim_IncrRefCount(interp->stackTrace); |
| 11568 | + Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame); |
| 11569 | + Jim_Obj *fileNameObj = interp->emptyObj; |
| 11570 | + int linenr = 1; |
| 11571 | + |
| 11572 | + if (frame->scriptObj) { |
| 11573 | + ScriptObj *script = JimGetScript(interp, frame->scriptObj); |
| 11574 | + fileNameObj = script->fileNameObj; |
| 11575 | + linenr = script->linenr; |
| 11576 | + } |
| 11577 | + |
| 11578 | + Jim_ListAppendElement(interp, listObj, procNameObj ? procNameObj : interp->emptyObj); |
| 11579 | + Jim_ListAppendElement(interp, listObj, fileNameObj); |
| 11580 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, linenr)); |
| 11581 | + Jim_ListAppendElement(interp, listObj, Jim_NewListObj(interp, frame->argv, frame->argc)); |
| 10708 | 11582 | } |
| 10709 | 11583 | |
| 10710 | 11584 | static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) |
| 10711 | 11585 | { |
| 10712 | | - int len; |
| 10713 | | - |
| 10714 | 11586 | |
| 10715 | 11587 | Jim_IncrRefCount(stackTraceObj); |
| 10716 | 11588 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10717 | 11589 | interp->stackTrace = stackTraceObj; |
| 10718 | 11590 | interp->errorFlag = 1; |
| 10719 | | - |
| 10720 | | - len = Jim_ListLength(interp, interp->stackTrace); |
| 10721 | | - if (len >= 3) { |
| 10722 | | - if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) { |
| 10723 | | - interp->addStackTrace = 1; |
| 10724 | | - } |
| 10725 | | - } |
| 10726 | | -} |
| 10727 | | - |
| 10728 | | -static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, |
| 10729 | | - Jim_Obj *fileNameObj, int linenr) |
| 10730 | | -{ |
| 10731 | | - if (strcmp(procname, "unknown") == 0) { |
| 10732 | | - procname = ""; |
| 10733 | | - } |
| 10734 | | - if (!*procname && !Jim_Length(fileNameObj)) { |
| 10735 | | - |
| 10736 | | - return; |
| 10737 | | - } |
| 10738 | | - |
| 10739 | | - if (Jim_IsShared(interp->stackTrace)) { |
| 10740 | | - Jim_DecrRefCount(interp, interp->stackTrace); |
| 10741 | | - interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); |
| 10742 | | - Jim_IncrRefCount(interp->stackTrace); |
| 10743 | | - } |
| 10744 | | - |
| 10745 | | - |
| 10746 | | - if (!*procname && Jim_Length(fileNameObj)) { |
| 10747 | | - |
| 10748 | | - int len = Jim_ListLength(interp, interp->stackTrace); |
| 10749 | | - |
| 10750 | | - if (len >= 3) { |
| 10751 | | - Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); |
| 10752 | | - if (Jim_Length(objPtr)) { |
| 10753 | | - |
| 10754 | | - objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); |
| 10755 | | - if (Jim_Length(objPtr) == 0) { |
| 10756 | | - |
| 10757 | | - ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); |
| 10758 | | - ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); |
| 10759 | | - return; |
| 10760 | | - } |
| 10761 | | - } |
| 10762 | | - } |
| 10763 | | - } |
| 10764 | | - |
| 10765 | | - Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1)); |
| 10766 | | - Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj); |
| 10767 | | - Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr)); |
| 11591 | +} |
| 11592 | + |
| 11593 | +static void JimSetErrorStack(Jim_Interp *interp) |
| 11594 | +{ |
| 11595 | + if (!interp->errorFlag) { |
| 11596 | + int i; |
| 11597 | + Jim_Obj *stackTrace = Jim_NewListObj(interp, NULL, 0); |
| 11598 | + |
| 11599 | + for (i = 0; i <= interp->procLevel; i++) { |
| 11600 | + Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i); |
| 11601 | + if (frame) { |
| 11602 | + JimAddStackFrame(interp, frame, stackTrace); |
| 11603 | + } |
| 11604 | + } |
| 11605 | + JimSetStackTrace(interp, stackTrace); |
| 11606 | + } |
| 10768 | 11607 | } |
| 10769 | 11608 | |
| 10770 | 11609 | int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc, |
| 10771 | 11610 | void *data) |
| 10772 | 11611 | { |
| | @@ -10897,10 +11736,36 @@ |
| 10897 | 11736 | return JIM_ERR; |
| 10898 | 11737 | *widePtr = JimWideValue(objPtr); |
| 10899 | 11738 | return JIM_OK; |
| 10900 | 11739 | } |
| 10901 | 11740 | |
| 11741 | +int Jim_GetWideExpr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) |
| 11742 | +{ |
| 11743 | + int ret = JIM_OK; |
| 11744 | + |
| 11745 | + if (objPtr->typePtr == &sourceObjType || objPtr->typePtr == NULL) { |
| 11746 | + SetIntFromAny(interp, objPtr, 0); |
| 11747 | + } |
| 11748 | + if (objPtr->typePtr == &intObjType) { |
| 11749 | + *widePtr = JimWideValue(objPtr); |
| 11750 | + } |
| 11751 | + else { |
| 11752 | + JimPanic((interp->safeexpr, "interp->safeexpr is set")); |
| 11753 | + interp->safeexpr++; |
| 11754 | + ret = Jim_EvalExpression(interp, objPtr); |
| 11755 | + interp->safeexpr--; |
| 11756 | + |
| 11757 | + if (ret == JIM_OK) { |
| 11758 | + ret = Jim_GetWide(interp, Jim_GetResult(interp), widePtr); |
| 11759 | + } |
| 11760 | + if (ret != JIM_OK) { |
| 11761 | + Jim_SetResultFormatted(interp, "expected integer expression but got \"%#s\"", objPtr); |
| 11762 | + } |
| 11763 | + } |
| 11764 | + return ret; |
| 11765 | +} |
| 11766 | + |
| 10902 | 11767 | |
| 10903 | 11768 | static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) |
| 10904 | 11769 | { |
| 10905 | 11770 | if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR) |
| 10906 | 11771 | return JIM_ERR; |
| | @@ -10943,15 +11808,15 @@ |
| 10943 | 11808 | NULL, |
| 10944 | 11809 | UpdateStringOfDouble, |
| 10945 | 11810 | JIM_TYPE_NONE, |
| 10946 | 11811 | }; |
| 10947 | 11812 | |
| 10948 | | -#ifndef HAVE_ISNAN |
| 11813 | +#if !HAVE_DECL_ISNAN |
| 10949 | 11814 | #undef isnan |
| 10950 | 11815 | #define isnan(X) ((X) != (X)) |
| 10951 | 11816 | #endif |
| 10952 | | -#ifndef HAVE_ISINF |
| 11817 | +#if !HAVE_DECL_ISINF |
| 10953 | 11818 | #undef isinf |
| 10954 | 11819 | #define isinf(X) (1.0 / (X) == 0.0) |
| 10955 | 11820 | #endif |
| 10956 | 11821 | |
| 10957 | 11822 | static void UpdateStringOfDouble(struct Jim_Obj *objPtr) |
| | @@ -11078,38 +11943,37 @@ |
| 11078 | 11943 | if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) |
| 11079 | 11944 | return JIM_ERR; |
| 11080 | 11945 | *booleanPtr = (int) JimWideValue(objPtr); |
| 11081 | 11946 | return JIM_OK; |
| 11082 | 11947 | } |
| 11948 | + |
| 11949 | +static const char * const jim_true_false_strings[8] = { |
| 11950 | + "1", "true", "yes", "on", |
| 11951 | + "0", "false", "no", "off" |
| 11952 | +}; |
| 11953 | + |
| 11954 | +static const int jim_true_false_lens[8] = { |
| 11955 | + 1, 4, 3, 2, |
| 11956 | + 1, 5, 2, 3, |
| 11957 | +}; |
| 11083 | 11958 | |
| 11084 | 11959 | static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 11085 | 11960 | { |
| 11086 | | - static const char * const falses[] = { |
| 11087 | | - "0", "false", "no", "off", NULL |
| 11088 | | - }; |
| 11089 | | - static const char * const trues[] = { |
| 11090 | | - "1", "true", "yes", "on", NULL |
| 11091 | | - }; |
| 11092 | | - |
| 11093 | | - int boolean; |
| 11094 | | - |
| 11095 | | - int index; |
| 11096 | | - if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) { |
| 11097 | | - boolean = 0; |
| 11098 | | - } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) { |
| 11099 | | - boolean = 1; |
| 11100 | | - } else { |
| 11961 | + int index = Jim_FindByName(Jim_String(objPtr), jim_true_false_strings, |
| 11962 | + sizeof(jim_true_false_strings) / sizeof(*jim_true_false_strings)); |
| 11963 | + if (index < 0) { |
| 11101 | 11964 | if (flags & JIM_ERRMSG) { |
| 11102 | 11965 | Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr); |
| 11103 | 11966 | } |
| 11104 | 11967 | return JIM_ERR; |
| 11105 | 11968 | } |
| 11106 | 11969 | |
| 11107 | 11970 | |
| 11108 | 11971 | Jim_FreeIntRep(interp, objPtr); |
| 11109 | 11972 | objPtr->typePtr = &intObjType; |
| 11110 | | - objPtr->internalRep.wideValue = boolean; |
| 11973 | + |
| 11974 | + objPtr->internalRep.wideValue = index < 4 ? 1 : 0; |
| 11111 | 11975 | return JIM_OK; |
| 11112 | 11976 | } |
| 11113 | 11977 | |
| 11114 | 11978 | static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); |
| 11115 | 11979 | static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); |
| | @@ -11404,28 +12268,26 @@ |
| 11404 | 12268 | int linenr; |
| 11405 | 12269 | |
| 11406 | 12270 | if (objPtr->typePtr == &listObjType) { |
| 11407 | 12271 | return JIM_OK; |
| 11408 | 12272 | } |
| 12273 | + |
| 11409 | 12274 | |
| 11410 | 12275 | if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { |
| 11411 | | - Jim_Obj **listObjPtrPtr; |
| 11412 | | - int len; |
| 11413 | | - int i; |
| 11414 | | - |
| 11415 | | - listObjPtrPtr = JimDictPairs(objPtr, &len); |
| 11416 | | - for (i = 0; i < len; i++) { |
| 11417 | | - Jim_IncrRefCount(listObjPtrPtr[i]); |
| 11418 | | - } |
| 12276 | + Jim_Dict *dict = objPtr->internalRep.dictValue; |
| 11419 | 12277 | |
| 11420 | 12278 | |
| 11421 | | - Jim_FreeIntRep(interp, objPtr); |
| 11422 | 12279 | objPtr->typePtr = &listObjType; |
| 11423 | | - objPtr->internalRep.listValue.len = len; |
| 11424 | | - objPtr->internalRep.listValue.maxLen = len; |
| 11425 | | - objPtr->internalRep.listValue.ele = listObjPtrPtr; |
| 12280 | + objPtr->internalRep.listValue.len = dict->len; |
| 12281 | + objPtr->internalRep.listValue.maxLen = dict->maxLen; |
| 12282 | + objPtr->internalRep.listValue.ele = dict->table; |
| 11426 | 12283 | |
| 12284 | + |
| 12285 | + Jim_Free(dict->ht); |
| 12286 | + |
| 12287 | + |
| 12288 | + Jim_Free(dict); |
| 11427 | 12289 | return JIM_OK; |
| 11428 | 12290 | } |
| 11429 | 12291 | |
| 11430 | 12292 | |
| 11431 | 12293 | if (objPtr->typePtr == &sourceObjType) { |
| | @@ -11513,12 +12375,12 @@ |
| 11513 | 12375 | JIM_LSORT_INTEGER, |
| 11514 | 12376 | JIM_LSORT_REAL, |
| 11515 | 12377 | JIM_LSORT_COMMAND |
| 11516 | 12378 | } type; |
| 11517 | 12379 | int order; |
| 11518 | | - int index; |
| 11519 | | - int indexed; |
| 12380 | + Jim_Obj **indexv; |
| 12381 | + int indexc; |
| 11520 | 12382 | int unique; |
| 11521 | 12383 | int (*subfn)(Jim_Obj **, Jim_Obj **); |
| 11522 | 12384 | }; |
| 11523 | 12385 | |
| 11524 | 12386 | static struct lsort_info *sort_info; |
| | @@ -11525,12 +12387,12 @@ |
| 11525 | 12387 | |
| 11526 | 12388 | static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj) |
| 11527 | 12389 | { |
| 11528 | 12390 | Jim_Obj *lObj, *rObj; |
| 11529 | 12391 | |
| 11530 | | - if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK || |
| 11531 | | - Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) { |
| 12392 | + if (Jim_ListIndices(sort_info->interp, *lhsObj, sort_info->indexv, sort_info->indexc, &lObj, JIM_ERRMSG) != JIM_OK || |
| 12393 | + Jim_ListIndices(sort_info->interp, *rhsObj, sort_info->indexv, sort_info->indexc, &rObj, JIM_ERRMSG) != JIM_OK) { |
| 11532 | 12394 | longjmp(sort_info->jmpbuf, JIM_ERR); |
| 11533 | 12395 | } |
| 11534 | 12396 | return sort_info->subfn(&lObj, &rObj); |
| 11535 | 12397 | } |
| 11536 | 12398 | |
| | @@ -11663,11 +12525,11 @@ |
| 11663 | 12525 | fn = NULL; |
| 11664 | 12526 | JimPanic((1, "ListSort called with invalid sort type")); |
| 11665 | 12527 | return -1; |
| 11666 | 12528 | } |
| 11667 | 12529 | |
| 11668 | | - if (info->indexed) { |
| 12530 | + if (info->indexc) { |
| 11669 | 12531 | |
| 11670 | 12532 | info->subfn = fn; |
| 11671 | 12533 | fn = ListSortIndexHelper; |
| 11672 | 12534 | } |
| 11673 | 12535 | |
| | @@ -11683,30 +12545,39 @@ |
| 11683 | 12545 | sort_info = prev_info; |
| 11684 | 12546 | |
| 11685 | 12547 | return rc; |
| 11686 | 12548 | } |
| 11687 | 12549 | |
| 12550 | + |
| 12551 | +static void ListEnsureLength(Jim_Obj *listPtr, int idx) |
| 12552 | +{ |
| 12553 | + assert(idx >= 0); |
| 12554 | + if (idx >= listPtr->internalRep.listValue.maxLen) { |
| 12555 | + if (idx < 4) { |
| 12556 | + |
| 12557 | + idx = 4; |
| 12558 | + } |
| 12559 | + listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, |
| 12560 | + sizeof(Jim_Obj *) * idx); |
| 12561 | + |
| 12562 | + listPtr->internalRep.listValue.maxLen = idx; |
| 12563 | + } |
| 12564 | +} |
| 12565 | + |
| 11688 | 12566 | static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec) |
| 11689 | 12567 | { |
| 11690 | 12568 | int currentLen = listPtr->internalRep.listValue.len; |
| 11691 | 12569 | int requiredLen = currentLen + elemc; |
| 11692 | 12570 | int i; |
| 11693 | 12571 | Jim_Obj **point; |
| 11694 | 12572 | |
| 11695 | 12573 | if (requiredLen > listPtr->internalRep.listValue.maxLen) { |
| 11696 | | - if (requiredLen < 2) { |
| 12574 | + if (currentLen) { |
| 11697 | 12575 | |
| 11698 | | - requiredLen = 4; |
| 11699 | | - } |
| 11700 | | - else { |
| 11701 | 12576 | requiredLen *= 2; |
| 11702 | 12577 | } |
| 11703 | | - |
| 11704 | | - listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, |
| 11705 | | - sizeof(Jim_Obj *) * requiredLen); |
| 11706 | | - |
| 11707 | | - listPtr->internalRep.listValue.maxLen = requiredLen; |
| 12578 | + ListEnsureLength(listPtr, requiredLen); |
| 11708 | 12579 | } |
| 11709 | 12580 | if (idx < 0) { |
| 11710 | 12581 | idx = currentLen; |
| 11711 | 12582 | } |
| 11712 | 12583 | point = listPtr->internalRep.listValue.ele + idx; |
| | @@ -11786,10 +12657,51 @@ |
| 11786 | 12657 | } |
| 11787 | 12658 | return JIM_ERR; |
| 11788 | 12659 | } |
| 11789 | 12660 | return JIM_OK; |
| 11790 | 12661 | } |
| 12662 | + |
| 12663 | +static int Jim_ListIndices(Jim_Interp *interp, Jim_Obj *listPtr, |
| 12664 | + Jim_Obj *const *indexv, int indexc, Jim_Obj **resultObj, int flags) |
| 12665 | +{ |
| 12666 | + int i; |
| 12667 | + int static_idxes[5]; |
| 12668 | + int *idxes = static_idxes; |
| 12669 | + int ret = JIM_OK; |
| 12670 | + |
| 12671 | + if (indexc > sizeof(static_idxes) / sizeof(*static_idxes)) { |
| 12672 | + idxes = Jim_Alloc(indexc * sizeof(*idxes)); |
| 12673 | + } |
| 12674 | + |
| 12675 | + for (i = 0; i < indexc; i++) { |
| 12676 | + ret = Jim_GetIndex(interp, indexv[i], &idxes[i]); |
| 12677 | + if (ret != JIM_OK) { |
| 12678 | + goto err; |
| 12679 | + } |
| 12680 | + } |
| 12681 | + |
| 12682 | + for (i = 0; i < indexc; i++) { |
| 12683 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, listPtr, idxes[i]); |
| 12684 | + if (!objPtr) { |
| 12685 | + if (flags & JIM_ERRMSG) { |
| 12686 | + if (idxes[i] < 0 || idxes[i] > Jim_ListLength(interp, listPtr)) { |
| 12687 | + Jim_SetResultFormatted(interp, "index \"%#s\" out of range", indexv[i]); |
| 12688 | + } |
| 12689 | + else { |
| 12690 | + Jim_SetResultFormatted(interp, "element %#s missing from sublist \"%#s\"", indexv[i], listPtr); |
| 12691 | + } |
| 12692 | + } |
| 12693 | + return -1; |
| 12694 | + } |
| 12695 | + listPtr = objPtr; |
| 12696 | + } |
| 12697 | + *resultObj = listPtr; |
| 12698 | +err: |
| 12699 | + if (idxes != static_idxes) |
| 12700 | + Jim_Free(idxes); |
| 12701 | + return ret; |
| 12702 | +} |
| 11791 | 12703 | |
| 11792 | 12704 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, |
| 11793 | 12705 | Jim_Obj *newObjPtr, int flags) |
| 11794 | 12706 | { |
| 11795 | 12707 | SetListFromAny(interp, listPtr); |
| | @@ -11821,11 +12733,14 @@ |
| 11821 | 12733 | varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); |
| 11822 | 12734 | for (i = 0; i < indexc - 1; i++) { |
| 11823 | 12735 | listObjPtr = objPtr; |
| 11824 | 12736 | if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK) |
| 11825 | 12737 | goto err; |
| 11826 | | - if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) { |
| 12738 | + |
| 12739 | + objPtr = Jim_ListGetIndex(interp, listObjPtr, idx); |
| 12740 | + if (objPtr == NULL) { |
| 12741 | + Jim_SetResultFormatted(interp, "index \"%#s\" out of range", indexv[i]); |
| 11827 | 12742 | goto err; |
| 11828 | 12743 | } |
| 11829 | 12744 | if (Jim_IsShared(objPtr)) { |
| 11830 | 12745 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| 11831 | 12746 | ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE); |
| | @@ -11948,112 +12863,186 @@ |
| 11948 | 12863 | static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 11949 | 12864 | static void UpdateStringOfDict(struct Jim_Obj *objPtr); |
| 11950 | 12865 | static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 11951 | 12866 | |
| 11952 | 12867 | |
| 11953 | | -static unsigned int JimObjectHTHashFunction(const void *key) |
| 11954 | | -{ |
| 11955 | | - int len; |
| 11956 | | - const char *str = Jim_GetString((Jim_Obj *)key, &len); |
| 11957 | | - return Jim_GenHashFunction((const unsigned char *)str, len); |
| 11958 | | -} |
| 11959 | | - |
| 11960 | | -static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 11961 | | -{ |
| 11962 | | - return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); |
| 11963 | | -} |
| 11964 | | - |
| 11965 | | -static void *JimObjectHTKeyValDup(void *privdata, const void *val) |
| 11966 | | -{ |
| 11967 | | - Jim_IncrRefCount((Jim_Obj *)val); |
| 11968 | | - return (void *)val; |
| 11969 | | -} |
| 11970 | | - |
| 11971 | | -static void JimObjectHTKeyValDestructor(void *interp, void *val) |
| 11972 | | -{ |
| 11973 | | - Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11974 | | -} |
| 11975 | | - |
| 11976 | | -static const Jim_HashTableType JimDictHashTableType = { |
| 11977 | | - JimObjectHTHashFunction, |
| 11978 | | - JimObjectHTKeyValDup, |
| 11979 | | - JimObjectHTKeyValDup, |
| 11980 | | - JimObjectHTKeyCompare, |
| 11981 | | - JimObjectHTKeyValDestructor, |
| 11982 | | - JimObjectHTKeyValDestructor |
| 11983 | | -}; |
| 11984 | | - |
| 11985 | 12868 | static const Jim_ObjType dictObjType = { |
| 11986 | 12869 | "dict", |
| 11987 | 12870 | FreeDictInternalRep, |
| 11988 | 12871 | DupDictInternalRep, |
| 11989 | 12872 | UpdateStringOfDict, |
| 11990 | 12873 | JIM_TYPE_NONE, |
| 11991 | 12874 | }; |
| 11992 | 12875 | |
| 11993 | | -void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 11994 | | -{ |
| 11995 | | - JIM_NOTUSED(interp); |
| 11996 | | - |
| 11997 | | - Jim_FreeHashTable(objPtr->internalRep.ptr); |
| 11998 | | - Jim_Free(objPtr->internalRep.ptr); |
| 11999 | | -} |
| 12000 | | - |
| 12001 | | -void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 12002 | | -{ |
| 12003 | | - Jim_HashTable *ht, *dupHt; |
| 12004 | | - Jim_HashTableIterator htiter; |
| 12005 | | - Jim_HashEntry *he; |
| 12006 | | - |
| 12007 | | - |
| 12008 | | - ht = srcPtr->internalRep.ptr; |
| 12009 | | - dupHt = Jim_Alloc(sizeof(*dupHt)); |
| 12010 | | - Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); |
| 12011 | | - if (ht->size != 0) |
| 12012 | | - Jim_ExpandHashTable(dupHt, ht->size); |
| 12013 | | - |
| 12014 | | - JimInitHashTableIterator(ht, &htiter); |
| 12015 | | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12016 | | - Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 12017 | | - } |
| 12018 | | - |
| 12019 | | - dupPtr->internalRep.ptr = dupHt; |
| 12020 | | - dupPtr->typePtr = &dictObjType; |
| 12021 | | -} |
| 12022 | | - |
| 12023 | | -static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len) |
| 12024 | | -{ |
| 12025 | | - Jim_HashTable *ht; |
| 12026 | | - Jim_HashTableIterator htiter; |
| 12027 | | - Jim_HashEntry *he; |
| 12028 | | - Jim_Obj **objv; |
| 12876 | +static void JimFreeDict(Jim_Interp *interp, Jim_Dict *dict) |
| 12877 | +{ |
| 12878 | + int i; |
| 12879 | + for (i = 0; i < dict->len; i++) { |
| 12880 | + Jim_DecrRefCount(interp, dict->table[i]); |
| 12881 | + } |
| 12882 | + Jim_Free(dict->table); |
| 12883 | + Jim_Free(dict->ht); |
| 12884 | + Jim_Free(dict); |
| 12885 | +} |
| 12886 | + |
| 12887 | +enum { |
| 12888 | + DICT_HASH_FIND = -1, |
| 12889 | + DICT_HASH_REMOVE = -2, |
| 12890 | + DICT_HASH_ADD = -3, |
| 12891 | +}; |
| 12892 | + |
| 12893 | +static int JimDictHashFind(Jim_Dict *dict, Jim_Obj *keyObjPtr, int op_tvoffset) |
| 12894 | +{ |
| 12895 | + unsigned h = (JimObjectHTHashFunction(keyObjPtr) + dict->uniq); |
| 12896 | + unsigned idx = h & dict->sizemask; |
| 12897 | + int tvoffset = 0; |
| 12898 | + unsigned peturb = h; |
| 12899 | + unsigned first_removed = ~0; |
| 12900 | + |
| 12901 | + if (dict->len) { |
| 12902 | + while ((tvoffset = dict->ht[idx].offset)) { |
| 12903 | + if (tvoffset == -1) { |
| 12904 | + if (first_removed == ~0) { |
| 12905 | + first_removed = idx; |
| 12906 | + } |
| 12907 | + } |
| 12908 | + else if (dict->ht[idx].hash == h) { |
| 12909 | + if (Jim_StringEqObj(keyObjPtr, dict->table[tvoffset - 1])) { |
| 12910 | + break; |
| 12911 | + } |
| 12912 | + } |
| 12913 | + |
| 12914 | + peturb >>= 5; |
| 12915 | + idx = (5 * idx + 1 + peturb) & dict->sizemask; |
| 12916 | + } |
| 12917 | + } |
| 12918 | + |
| 12919 | + switch (op_tvoffset) { |
| 12920 | + case DICT_HASH_FIND: |
| 12921 | + |
| 12922 | + break; |
| 12923 | + case DICT_HASH_REMOVE: |
| 12924 | + if (tvoffset) { |
| 12925 | + |
| 12926 | + dict->ht[idx].offset = -1; |
| 12927 | + dict->dummy++; |
| 12928 | + } |
| 12929 | + |
| 12930 | + break; |
| 12931 | + case DICT_HASH_ADD: |
| 12932 | + if (tvoffset == 0) { |
| 12933 | + |
| 12934 | + if (first_removed != ~0) { |
| 12935 | + idx = first_removed; |
| 12936 | + dict->dummy--; |
| 12937 | + } |
| 12938 | + dict->ht[idx].offset = dict->len + 1; |
| 12939 | + dict->ht[idx].hash = h; |
| 12940 | + } |
| 12941 | + |
| 12942 | + break; |
| 12943 | + default: |
| 12944 | + assert(tvoffset); |
| 12945 | + |
| 12946 | + dict->ht[idx].offset = op_tvoffset; |
| 12947 | + break; |
| 12948 | + } |
| 12949 | + |
| 12950 | + return tvoffset; |
| 12951 | +} |
| 12952 | + |
| 12953 | +static void JimDictExpandHashTable(Jim_Dict *dict, unsigned int size) |
| 12954 | +{ |
| 12955 | + int i; |
| 12956 | + struct JimDictHashEntry *prevht = dict->ht; |
| 12957 | + int prevsize = dict->size; |
| 12958 | + |
| 12959 | + dict->size = JimHashTableNextPower(size); |
| 12960 | + dict->sizemask = dict->size - 1; |
| 12961 | + |
| 12962 | + |
| 12963 | + dict->ht = Jim_Alloc(dict->size * sizeof(*dict->ht)); |
| 12964 | + memset(dict->ht, 0, dict->size * sizeof(*dict->ht)); |
| 12965 | + |
| 12966 | + |
| 12967 | + for (i = 0; i < prevsize; i++) { |
| 12968 | + if (prevht[i].offset > 0) { |
| 12969 | + |
| 12970 | + unsigned h = prevht[i].hash; |
| 12971 | + unsigned idx = h & dict->sizemask; |
| 12972 | + unsigned peturb = h; |
| 12973 | + |
| 12974 | + while (dict->ht[idx].offset) { |
| 12975 | + peturb >>= 5; |
| 12976 | + idx = (5 * idx + 1 + peturb) & dict->sizemask; |
| 12977 | + } |
| 12978 | + dict->ht[idx].offset = prevht[i].offset; |
| 12979 | + dict->ht[idx].hash = h; |
| 12980 | + } |
| 12981 | + } |
| 12982 | + Jim_Free(prevht); |
| 12983 | +} |
| 12984 | + |
| 12985 | +static int JimDictAdd(Jim_Dict *dict, Jim_Obj *keyObjPtr) |
| 12986 | +{ |
| 12987 | + if (dict->size <= dict->len + dict->dummy) { |
| 12988 | + JimDictExpandHashTable(dict, dict->size ? dict->size * 2 : 8); |
| 12989 | + } |
| 12990 | + return JimDictHashFind(dict, keyObjPtr, DICT_HASH_ADD); |
| 12991 | +} |
| 12992 | + |
| 12993 | +static Jim_Dict *JimDictNew(Jim_Interp *interp, int table_size, int ht_size) |
| 12994 | +{ |
| 12995 | + Jim_Dict *dict = Jim_Alloc(sizeof(*dict)); |
| 12996 | + memset(dict, 0, sizeof(*dict)); |
| 12997 | + |
| 12998 | + if (ht_size) { |
| 12999 | + JimDictExpandHashTable(dict, ht_size); |
| 13000 | + } |
| 13001 | + if (table_size) { |
| 13002 | + dict->table = Jim_Alloc(table_size * sizeof(*dict->table)); |
| 13003 | + dict->maxLen = table_size; |
| 13004 | + } |
| 13005 | +#ifdef JIM_RANDOMISE_HASH |
| 13006 | + dict->uniq = (rand() ^ time(NULL) ^ clock()); |
| 13007 | +#endif |
| 13008 | + return dict; |
| 13009 | +} |
| 13010 | + |
| 13011 | +static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13012 | +{ |
| 13013 | + JimFreeDict(interp, objPtr->internalRep.dictValue); |
| 13014 | +} |
| 13015 | + |
| 13016 | +static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 13017 | +{ |
| 13018 | + Jim_Dict *oldDict = srcPtr->internalRep.dictValue; |
| 12029 | 13019 | int i; |
| 12030 | 13020 | |
| 12031 | | - ht = dictPtr->internalRep.ptr; |
| 13021 | + |
| 13022 | + Jim_Dict *newDict = JimDictNew(interp, oldDict->maxLen, oldDict->size); |
| 12032 | 13023 | |
| 12033 | 13024 | |
| 12034 | | - objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 12035 | | - JimInitHashTableIterator(ht, &htiter); |
| 12036 | | - i = 0; |
| 12037 | | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12038 | | - objv[i++] = Jim_GetHashEntryKey(he); |
| 12039 | | - objv[i++] = Jim_GetHashEntryVal(he); |
| 12040 | | - } |
| 12041 | | - *len = i; |
| 12042 | | - return objv; |
| 13025 | + for (i = 0; i < oldDict->len; i++) { |
| 13026 | + newDict->table[i] = oldDict->table[i]; |
| 13027 | + Jim_IncrRefCount(newDict->table[i]); |
| 13028 | + } |
| 13029 | + newDict->len = oldDict->len; |
| 13030 | + |
| 13031 | + |
| 13032 | + newDict->uniq = oldDict->uniq; |
| 13033 | + |
| 13034 | + |
| 13035 | + memcpy(newDict->ht, oldDict->ht, sizeof(*oldDict->ht) * oldDict->size); |
| 13036 | + |
| 13037 | + dupPtr->internalRep.dictValue = newDict; |
| 13038 | + dupPtr->typePtr = &dictObjType; |
| 12043 | 13039 | } |
| 12044 | 13040 | |
| 12045 | 13041 | static void UpdateStringOfDict(struct Jim_Obj *objPtr) |
| 12046 | 13042 | { |
| 12047 | | - |
| 12048 | | - int len; |
| 12049 | | - Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 12050 | | - |
| 12051 | | - |
| 12052 | | - JimMakeListStringRep(objPtr, objv, len); |
| 12053 | | - |
| 12054 | | - Jim_Free(objv); |
| 13043 | + JimMakeListStringRep(objPtr, objPtr->internalRep.dictValue->table, objPtr->internalRep.dictValue->len); |
| 12055 | 13044 | } |
| 12056 | 13045 | |
| 12057 | 13046 | static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 12058 | 13047 | { |
| 12059 | 13048 | int listlen; |
| | @@ -12064,34 +13053,49 @@ |
| 12064 | 13053 | |
| 12065 | 13054 | if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 12066 | 13055 | Jim_String(objPtr); |
| 12067 | 13056 | } |
| 12068 | 13057 | |
| 12069 | | - |
| 12070 | 13058 | listlen = Jim_ListLength(interp, objPtr); |
| 12071 | 13059 | if (listlen % 2) { |
| 12072 | 13060 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| 12073 | 13061 | return JIM_ERR; |
| 12074 | 13062 | } |
| 12075 | 13063 | else { |
| 12076 | 13064 | |
| 12077 | | - Jim_HashTable *ht; |
| 13065 | + Jim_Dict *dict = JimDictNew(interp, 0, listlen); |
| 12078 | 13066 | int i; |
| 12079 | 13067 | |
| 12080 | | - ht = Jim_Alloc(sizeof(*ht)); |
| 12081 | | - Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| 13068 | + |
| 13069 | + dict->table = objPtr->internalRep.listValue.ele; |
| 13070 | + dict->maxLen = objPtr->internalRep.listValue.maxLen; |
| 13071 | + |
| 12082 | 13072 | |
| 12083 | 13073 | for (i = 0; i < listlen; i += 2) { |
| 12084 | | - Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); |
| 12085 | | - Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); |
| 13074 | + int tvoffset = JimDictAdd(dict, dict->table[i]); |
| 13075 | + if (tvoffset) { |
| 12086 | 13076 | |
| 12087 | | - Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); |
| 13077 | + |
| 13078 | + Jim_DecrRefCount(interp, dict->table[tvoffset]); |
| 13079 | + |
| 13080 | + dict->table[tvoffset] = dict->table[i + 1]; |
| 13081 | + |
| 13082 | + Jim_DecrRefCount(interp, dict->table[i]); |
| 13083 | + } |
| 13084 | + else { |
| 13085 | + if (dict->len != i) { |
| 13086 | + dict->table[dict->len++] = dict->table[i]; |
| 13087 | + dict->table[dict->len++] = dict->table[i + 1]; |
| 13088 | + } |
| 13089 | + else { |
| 13090 | + dict->len += 2; |
| 13091 | + } |
| 13092 | + } |
| 12088 | 13093 | } |
| 12089 | 13094 | |
| 12090 | | - Jim_FreeIntRep(interp, objPtr); |
| 12091 | 13095 | objPtr->typePtr = &dictObjType; |
| 12092 | | - objPtr->internalRep.ptr = ht; |
| 13096 | + objPtr->internalRep.dictValue = dict; |
| 12093 | 13097 | |
| 12094 | 13098 | return JIM_OK; |
| 12095 | 13099 | } |
| 12096 | 13100 | } |
| 12097 | 13101 | |
| | @@ -12098,17 +13102,60 @@ |
| 12098 | 13102 | |
| 12099 | 13103 | |
| 12100 | 13104 | static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 12101 | 13105 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 12102 | 13106 | { |
| 12103 | | - Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 12104 | | - |
| 13107 | + Jim_Dict *dict = objPtr->internalRep.dictValue; |
| 12105 | 13108 | if (valueObjPtr == NULL) { |
| 12106 | | - return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 13109 | + |
| 13110 | + int tvoffset = JimDictHashFind(dict, keyObjPtr, DICT_HASH_REMOVE); |
| 13111 | + if (tvoffset) { |
| 13112 | + |
| 13113 | + Jim_DecrRefCount(interp, dict->table[tvoffset - 1]); |
| 13114 | + Jim_DecrRefCount(interp, dict->table[tvoffset]); |
| 13115 | + dict->len -= 2; |
| 13116 | + if (tvoffset != dict->len + 1) { |
| 13117 | + |
| 13118 | + dict->table[tvoffset - 1] = dict->table[dict->len]; |
| 13119 | + dict->table[tvoffset] = dict->table[dict->len + 1]; |
| 13120 | + |
| 13121 | + |
| 13122 | + JimDictHashFind(dict, dict->table[tvoffset - 1], tvoffset); |
| 13123 | + } |
| 13124 | + return JIM_OK; |
| 13125 | + } |
| 13126 | + return JIM_ERR; |
| 12107 | 13127 | } |
| 12108 | | - Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 12109 | | - return JIM_OK; |
| 13128 | + else { |
| 13129 | + |
| 13130 | + int tvoffset = JimDictAdd(dict, keyObjPtr); |
| 13131 | + if (tvoffset) { |
| 13132 | + |
| 13133 | + Jim_IncrRefCount(valueObjPtr); |
| 13134 | + Jim_DecrRefCount(interp, dict->table[tvoffset]); |
| 13135 | + dict->table[tvoffset] = valueObjPtr; |
| 13136 | + } |
| 13137 | + else { |
| 13138 | + if (dict->maxLen == dict->len) { |
| 13139 | + |
| 13140 | + if (dict->maxLen < 4) { |
| 13141 | + dict->maxLen = 4; |
| 13142 | + } |
| 13143 | + else { |
| 13144 | + dict->maxLen *= 2; |
| 13145 | + } |
| 13146 | + dict->table = Jim_Realloc(dict->table, dict->maxLen * sizeof(*dict->table)); |
| 13147 | + } |
| 13148 | + Jim_IncrRefCount(keyObjPtr); |
| 13149 | + Jim_IncrRefCount(valueObjPtr); |
| 13150 | + |
| 13151 | + dict->table[dict->len++] = keyObjPtr; |
| 13152 | + dict->table[dict->len++] = valueObjPtr; |
| 13153 | + |
| 13154 | + } |
| 13155 | + return JIM_OK; |
| 13156 | + } |
| 12110 | 13157 | } |
| 12111 | 13158 | |
| 12112 | 13159 | int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 12113 | 13160 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 12114 | 13161 | { |
| | @@ -12128,50 +13175,57 @@ |
| 12128 | 13175 | JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even")); |
| 12129 | 13176 | |
| 12130 | 13177 | objPtr = Jim_NewObj(interp); |
| 12131 | 13178 | objPtr->typePtr = &dictObjType; |
| 12132 | 13179 | objPtr->bytes = NULL; |
| 12133 | | - objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable)); |
| 12134 | | - Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp); |
| 13180 | + |
| 13181 | + objPtr->internalRep.dictValue = JimDictNew(interp, len, len); |
| 12135 | 13182 | for (i = 0; i < len; i += 2) |
| 12136 | 13183 | DictAddElement(interp, objPtr, elements[i], elements[i + 1]); |
| 12137 | 13184 | return objPtr; |
| 12138 | 13185 | } |
| 12139 | 13186 | |
| 12140 | 13187 | int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, |
| 12141 | 13188 | Jim_Obj **objPtrPtr, int flags) |
| 12142 | 13189 | { |
| 12143 | | - Jim_HashEntry *he; |
| 12144 | | - Jim_HashTable *ht; |
| 13190 | + int tvoffset; |
| 13191 | + Jim_Dict *dict; |
| 12145 | 13192 | |
| 12146 | 13193 | if (SetDictFromAny(interp, dictPtr) != JIM_OK) { |
| 12147 | 13194 | return -1; |
| 12148 | 13195 | } |
| 12149 | | - ht = dictPtr->internalRep.ptr; |
| 12150 | | - if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) { |
| 13196 | + dict = dictPtr->internalRep.dictValue; |
| 13197 | + tvoffset = JimDictHashFind(dict, keyPtr, DICT_HASH_FIND); |
| 13198 | + if (tvoffset == 0) { |
| 12151 | 13199 | if (flags & JIM_ERRMSG) { |
| 12152 | 13200 | Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); |
| 12153 | 13201 | } |
| 12154 | 13202 | return JIM_ERR; |
| 12155 | 13203 | } |
| 12156 | | - else { |
| 12157 | | - *objPtrPtr = Jim_GetHashEntryVal(he); |
| 12158 | | - return JIM_OK; |
| 12159 | | - } |
| 13204 | + *objPtrPtr = dict->table[tvoffset]; |
| 13205 | + return JIM_OK; |
| 12160 | 13206 | } |
| 12161 | 13207 | |
| 13208 | +Jim_Obj **Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, int *len) |
| 13209 | +{ |
| 12162 | 13210 | |
| 12163 | | -int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) |
| 12164 | | -{ |
| 13211 | + if (Jim_IsList(dictPtr)) { |
| 13212 | + Jim_Obj **table; |
| 13213 | + JimListGetElements(interp, dictPtr, len, &table); |
| 13214 | + if (*len % 2 == 0) { |
| 13215 | + return table; |
| 13216 | + } |
| 13217 | + |
| 13218 | + } |
| 12165 | 13219 | if (SetDictFromAny(interp, dictPtr) != JIM_OK) { |
| 12166 | | - return JIM_ERR; |
| 13220 | + |
| 13221 | + *len = 1; |
| 13222 | + return NULL; |
| 12167 | 13223 | } |
| 12168 | | - *objPtrPtr = JimDictPairs(dictPtr, len); |
| 12169 | | - |
| 12170 | | - return JIM_OK; |
| 13224 | + *len = dictPtr->internalRep.dictValue->len; |
| 13225 | + return dictPtr->internalRep.dictValue->table; |
| 12171 | 13226 | } |
| 12172 | | - |
| 12173 | 13227 | |
| 12174 | 13228 | |
| 12175 | 13229 | int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr, |
| 12176 | 13230 | Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags) |
| 12177 | 13231 | { |
| | @@ -12254,11 +13308,14 @@ |
| 12254 | 13308 | Jim_InvalidateStringRep(objPtr); |
| 12255 | 13309 | Jim_InvalidateStringRep(varObjPtr); |
| 12256 | 13310 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 12257 | 13311 | goto err; |
| 12258 | 13312 | } |
| 12259 | | - Jim_SetResult(interp, varObjPtr); |
| 13313 | + |
| 13314 | + if (!(flags & JIM_NORESULT)) { |
| 13315 | + Jim_SetResult(interp, varObjPtr); |
| 13316 | + } |
| 12260 | 13317 | return JIM_OK; |
| 12261 | 13318 | err: |
| 12262 | 13319 | if (shared) { |
| 12263 | 13320 | Jim_FreeNewObj(interp, varObjPtr); |
| 12264 | 13321 | } |
| | @@ -12281,11 +13338,11 @@ |
| 12281 | 13338 | if (objPtr->internalRep.intValue == -1) { |
| 12282 | 13339 | JimSetStringBytes(objPtr, "end"); |
| 12283 | 13340 | } |
| 12284 | 13341 | else { |
| 12285 | 13342 | char buf[JIM_INTEGER_SPACE + 1]; |
| 12286 | | - if (objPtr->internalRep.intValue >= 0) { |
| 13343 | + if (objPtr->internalRep.intValue >= 0 || objPtr->internalRep.intValue == -INT_MAX) { |
| 12287 | 13344 | sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12288 | 13345 | } |
| 12289 | 13346 | else { |
| 12290 | 13347 | |
| 12291 | 13348 | sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| | @@ -12294,49 +13351,49 @@ |
| 12294 | 13351 | } |
| 12295 | 13352 | } |
| 12296 | 13353 | |
| 12297 | 13354 | static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12298 | 13355 | { |
| 12299 | | - int idx, end = 0; |
| 13356 | + jim_wide idx; |
| 13357 | + int end = 0; |
| 12300 | 13358 | const char *str; |
| 12301 | | - char *endptr; |
| 13359 | + Jim_Obj *exprObj = objPtr; |
| 13360 | + |
| 13361 | + JimPanic((objPtr->refCount == 0, "SetIndexFromAny() called with zero refcount object")); |
| 12302 | 13362 | |
| 12303 | 13363 | |
| 12304 | 13364 | str = Jim_String(objPtr); |
| 12305 | 13365 | |
| 12306 | 13366 | |
| 12307 | 13367 | if (strncmp(str, "end", 3) == 0) { |
| 12308 | 13368 | end = 1; |
| 12309 | 13369 | str += 3; |
| 12310 | 13370 | idx = 0; |
| 12311 | | - } |
| 12312 | | - else { |
| 12313 | | - idx = jim_strtol(str, &endptr); |
| 12314 | | - |
| 12315 | | - if (endptr == str) { |
| 12316 | | - goto badindex; |
| 12317 | | - } |
| 12318 | | - str = endptr; |
| 12319 | | - } |
| 12320 | | - |
| 12321 | | - |
| 12322 | | - if (*str == '+' || *str == '-') { |
| 12323 | | - int sign = (*str == '+' ? 1 : -1); |
| 12324 | | - |
| 12325 | | - idx += sign * jim_strtol(++str, &endptr); |
| 12326 | | - if (str == endptr || *endptr) { |
| 12327 | | - goto badindex; |
| 12328 | | - } |
| 12329 | | - str = endptr; |
| 12330 | | - } |
| 12331 | | - |
| 12332 | | - while (isspace(UCHAR(*str))) { |
| 12333 | | - str++; |
| 12334 | | - } |
| 12335 | | - if (*str) { |
| 12336 | | - goto badindex; |
| 12337 | | - } |
| 13371 | + switch (*str) { |
| 13372 | + case '\0': |
| 13373 | + exprObj = NULL; |
| 13374 | + break; |
| 13375 | + |
| 13376 | + case '-': |
| 13377 | + case '+': |
| 13378 | + exprObj = Jim_NewStringObj(interp, str, -1); |
| 13379 | + break; |
| 13380 | + |
| 13381 | + default: |
| 13382 | + goto badindex; |
| 13383 | + } |
| 13384 | + } |
| 13385 | + if (exprObj) { |
| 13386 | + int ret; |
| 13387 | + Jim_IncrRefCount(exprObj); |
| 13388 | + ret = Jim_GetWideExpr(interp, exprObj, &idx); |
| 13389 | + Jim_DecrRefCount(interp, exprObj); |
| 13390 | + if (ret != JIM_OK) { |
| 13391 | + goto badindex; |
| 13392 | + } |
| 13393 | + } |
| 13394 | + |
| 12338 | 13395 | if (end) { |
| 12339 | 13396 | if (idx > 0) { |
| 12340 | 13397 | idx = INT_MAX; |
| 12341 | 13398 | } |
| 12342 | 13399 | else { |
| | @@ -12354,11 +13411,11 @@ |
| 12354 | 13411 | objPtr->internalRep.intValue = idx; |
| 12355 | 13412 | return JIM_OK; |
| 12356 | 13413 | |
| 12357 | 13414 | badindex: |
| 12358 | 13415 | Jim_SetResultFormatted(interp, |
| 12359 | | - "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr); |
| 13416 | + "bad index \"%#s\": must be intexpr or end?[+-]intexpr?", objPtr); |
| 12360 | 13417 | return JIM_ERR; |
| 12361 | 13418 | } |
| 12362 | 13419 | |
| 12363 | 13420 | int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) |
| 12364 | 13421 | { |
| | @@ -12479,10 +13536,14 @@ |
| 12479 | 13536 | |
| 12480 | 13537 | JIM_EXPROP_STREQ, |
| 12481 | 13538 | JIM_EXPROP_STRNE, |
| 12482 | 13539 | JIM_EXPROP_STRIN, |
| 12483 | 13540 | JIM_EXPROP_STRNI, |
| 13541 | + JIM_EXPROP_STRLT, |
| 13542 | + JIM_EXPROP_STRGT, |
| 13543 | + JIM_EXPROP_STRLE, |
| 13544 | + JIM_EXPROP_STRGE, |
| 12484 | 13545 | |
| 12485 | 13546 | |
| 12486 | 13547 | JIM_EXPROP_NOT, |
| 12487 | 13548 | JIM_EXPROP_BITNOT, |
| 12488 | 13549 | JIM_EXPROP_UNARYMINUS, |
| | @@ -12544,11 +13605,11 @@ |
| 12544 | 13605 | static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node); |
| 12545 | 13606 | |
| 12546 | 13607 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node) |
| 12547 | 13608 | { |
| 12548 | 13609 | int intresult = 1; |
| 12549 | | - int rc; |
| 13610 | + int rc, bA = 0; |
| 12550 | 13611 | double dA, dC = 0; |
| 12551 | 13612 | jim_wide wA, wC = 0; |
| 12552 | 13613 | Jim_Obj *A; |
| 12553 | 13614 | |
| 12554 | 13615 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| | @@ -12611,10 +13672,19 @@ |
| 12611 | 13672 | break; |
| 12612 | 13673 | default: |
| 12613 | 13674 | abort(); |
| 12614 | 13675 | } |
| 12615 | 13676 | } |
| 13677 | + else if ((rc = Jim_GetBoolean(interp, A, &bA)) == JIM_OK) { |
| 13678 | + switch (node->type) { |
| 13679 | + case JIM_EXPROP_NOT: |
| 13680 | + wC = !bA; |
| 13681 | + break; |
| 13682 | + default: |
| 13683 | + abort(); |
| 13684 | + } |
| 13685 | + } |
| 12616 | 13686 | |
| 12617 | 13687 | if (rc == JIM_OK) { |
| 12618 | 13688 | if (intresult) { |
| 12619 | 13689 | Jim_SetResultInt(interp, wC); |
| 12620 | 13690 | } |
| | @@ -12631,11 +13701,11 @@ |
| 12631 | 13701 | static double JimRandDouble(Jim_Interp *interp) |
| 12632 | 13702 | { |
| 12633 | 13703 | unsigned long x; |
| 12634 | 13704 | JimRandomBytes(interp, &x, sizeof(x)); |
| 12635 | 13705 | |
| 12636 | | - return (double)x / (unsigned long)~0; |
| 13706 | + return (double)x / (double)~0UL; |
| 12637 | 13707 | } |
| 12638 | 13708 | |
| 12639 | 13709 | static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node) |
| 12640 | 13710 | { |
| 12641 | 13711 | jim_wide wA; |
| | @@ -13040,11 +14110,11 @@ |
| 13040 | 14110 | |
| 13041 | 14111 | static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node) |
| 13042 | 14112 | { |
| 13043 | 14113 | Jim_Obj *A, *B; |
| 13044 | 14114 | jim_wide wC; |
| 13045 | | - int rc; |
| 14115 | + int comp, rc; |
| 13046 | 14116 | |
| 13047 | 14117 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 13048 | 14118 | return rc; |
| 13049 | 14119 | } |
| 13050 | 14120 | if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { |
| | @@ -13057,10 +14127,25 @@ |
| 13057 | 14127 | case JIM_EXPROP_STRNE: |
| 13058 | 14128 | wC = Jim_StringEqObj(A, B); |
| 13059 | 14129 | if (node->type == JIM_EXPROP_STRNE) { |
| 13060 | 14130 | wC = !wC; |
| 13061 | 14131 | } |
| 14132 | + break; |
| 14133 | + case JIM_EXPROP_STRLT: |
| 14134 | + case JIM_EXPROP_STRGT: |
| 14135 | + case JIM_EXPROP_STRLE: |
| 14136 | + case JIM_EXPROP_STRGE: |
| 14137 | + comp = Jim_StringCompareObj(interp, A, B, 0); |
| 14138 | + if (node->type == JIM_EXPROP_STRLT) { |
| 14139 | + wC = comp == -1; |
| 14140 | + } else if (node->type == JIM_EXPROP_STRGT) { |
| 14141 | + wC = comp == 1; |
| 14142 | + } else if (node->type == JIM_EXPROP_STRLE) { |
| 14143 | + wC = comp == -1 || comp == 0; |
| 14144 | + } else { |
| 14145 | + wC = comp == 0 || comp == 1; |
| 14146 | + } |
| 13062 | 14147 | break; |
| 13063 | 14148 | case JIM_EXPROP_STRIN: |
| 13064 | 14149 | wC = JimSearchList(interp, B, A); |
| 13065 | 14150 | break; |
| 13066 | 14151 | case JIM_EXPROP_STRNI: |
| | @@ -13196,10 +14281,15 @@ |
| 13196 | 14281 | OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13197 | 14282 | OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13198 | 14283 | |
| 13199 | 14284 | OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13200 | 14285 | OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 14286 | + |
| 14287 | + OPRINIT("lt", 75, 2, JimExprOpStrBin), |
| 14288 | + OPRINIT("gt", 75, 2, JimExprOpStrBin), |
| 14289 | + OPRINIT("le", 75, 2, JimExprOpStrBin), |
| 14290 | + OPRINIT("ge", 75, 2, JimExprOpStrBin), |
| 13201 | 14291 | |
| 13202 | 14292 | OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| 13203 | 14293 | OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC), |
| 13204 | 14294 | OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| 13205 | 14295 | OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| | @@ -13242,17 +14332,26 @@ |
| 13242 | 14332 | #define JIM_EXPR_OPERATORS_NUM \ |
| 13243 | 14333 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 13244 | 14334 | |
| 13245 | 14335 | static int JimParseExpression(struct JimParserCtx *pc) |
| 13246 | 14336 | { |
| 14337 | + while (1) { |
| 13247 | 14338 | |
| 13248 | | - while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { |
| 13249 | | - if (*pc->p == '\n') { |
| 13250 | | - pc->linenr++; |
| 14339 | + while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { |
| 14340 | + if (*pc->p == '\n') { |
| 14341 | + pc->linenr++; |
| 14342 | + } |
| 14343 | + pc->p++; |
| 14344 | + pc->len--; |
| 13251 | 14345 | } |
| 13252 | | - pc->p++; |
| 13253 | | - pc->len--; |
| 14346 | + |
| 14347 | + if (*pc->p == '#') { |
| 14348 | + JimParseComment(pc); |
| 14349 | + |
| 14350 | + continue; |
| 14351 | + } |
| 14352 | + break; |
| 13254 | 14353 | } |
| 13255 | 14354 | |
| 13256 | 14355 | |
| 13257 | 14356 | pc->tline = pc->linenr; |
| 13258 | 14357 | pc->tstart = pc->p; |
| | @@ -13372,21 +14471,15 @@ |
| 13372 | 14471 | return JIM_ERR; |
| 13373 | 14472 | } |
| 13374 | 14473 | |
| 13375 | 14474 | static int JimParseExprBoolean(struct JimParserCtx *pc) |
| 13376 | 14475 | { |
| 13377 | | - const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL }; |
| 13378 | | - const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 }; |
| 13379 | 14476 | int i; |
| 13380 | | - |
| 13381 | | - for (i = 0; booleans[i]; i++) { |
| 13382 | | - const char *boolean = booleans[i]; |
| 13383 | | - int length = lengths[i]; |
| 13384 | | - |
| 13385 | | - if (strncmp(boolean, pc->p, length) == 0) { |
| 13386 | | - pc->p += length; |
| 13387 | | - pc->len -= length; |
| 14477 | + for (i = 0; i < sizeof(jim_true_false_strings) / sizeof(*jim_true_false_strings); i++) { |
| 14478 | + if (strncmp(pc->p, jim_true_false_strings[i], jim_true_false_lens[i]) == 0) { |
| 14479 | + pc->p += jim_true_false_lens[i]; |
| 14480 | + pc->len -= jim_true_false_lens[i]; |
| 13388 | 14481 | pc->tend = pc->p - 1; |
| 13389 | 14482 | pc->tt = JIM_TT_EXPR_BOOLEAN; |
| 13390 | 14483 | return JIM_OK; |
| 13391 | 14484 | } |
| 13392 | 14485 | } |
| | @@ -13479,11 +14572,11 @@ |
| 13479 | 14572 | static const Jim_ObjType exprObjType = { |
| 13480 | 14573 | "expression", |
| 13481 | 14574 | FreeExprInternalRep, |
| 13482 | 14575 | DupExprInternalRep, |
| 13483 | 14576 | NULL, |
| 13484 | | - JIM_TYPE_REFERENCES, |
| 14577 | + JIM_TYPE_NONE, |
| 13485 | 14578 | }; |
| 13486 | 14579 | |
| 13487 | 14580 | |
| 13488 | 14581 | struct ExprTree |
| 13489 | 14582 | { |
| | @@ -13571,12 +14664,11 @@ |
| 13571 | 14664 | |
| 13572 | 14665 | #define EXPR_UNTIL_CLOSE 0x0001 |
| 13573 | 14666 | #define EXPR_FUNC_ARGS 0x0002 |
| 13574 | 14667 | #define EXPR_TERNARY 0x0004 |
| 13575 | 14668 | |
| 13576 | | -static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) |
| 13577 | | -{ |
| 14669 | +static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) { |
| 13578 | 14670 | int rc; |
| 13579 | 14671 | struct JimExprNode *node; |
| 13580 | 14672 | |
| 13581 | 14673 | int exp_stacklen = builder->stack.len + exp_numterms; |
| 13582 | 14674 | |
| | @@ -13826,11 +14918,11 @@ |
| 13826 | 14918 | builder.level = 0; |
| 13827 | 14919 | builder.token = builder.first_token = tokenlist->list; |
| 13828 | 14920 | builder.exprObjPtr = exprObjPtr; |
| 13829 | 14921 | builder.fileNameObj = fileNameObj; |
| 13830 | 14922 | |
| 13831 | | - builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1)); |
| 14923 | + builder.nodes = Jim_Alloc(sizeof(struct JimExprNode) * (tokenlist->count - 1)); |
| 13832 | 14924 | memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1)); |
| 13833 | 14925 | builder.next = builder.nodes; |
| 13834 | 14926 | Jim_InitStack(&builder.stack); |
| 13835 | 14927 | |
| 13836 | 14928 | rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1); |
| | @@ -14004,17 +15096,23 @@ |
| 14004 | 15096 | return JIM_OK; |
| 14005 | 15097 | } |
| 14006 | 15098 | return JIM_ERR; |
| 14007 | 15099 | |
| 14008 | 15100 | case JIM_TT_ESC: |
| 15101 | + if (interp->safeexpr) { |
| 15102 | + return JIM_ERR; |
| 15103 | + } |
| 14009 | 15104 | if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) { |
| 14010 | 15105 | Jim_SetResult(interp, objPtr); |
| 14011 | 15106 | return JIM_OK; |
| 14012 | 15107 | } |
| 14013 | 15108 | return JIM_ERR; |
| 14014 | 15109 | |
| 14015 | 15110 | case JIM_TT_CMD: |
| 15111 | + if (interp->safeexpr) { |
| 15112 | + return JIM_ERR; |
| 15113 | + } |
| 14016 | 15114 | return Jim_EvalObj(interp, node->objPtr); |
| 14017 | 15115 | |
| 14018 | 15116 | default: |
| 14019 | 15117 | |
| 14020 | 15118 | return JIM_ERR; |
| | @@ -14043,36 +15141,38 @@ |
| 14043 | 15141 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr) |
| 14044 | 15142 | { |
| 14045 | 15143 | struct ExprTree *expr; |
| 14046 | 15144 | int retcode = JIM_OK; |
| 14047 | 15145 | |
| 15146 | + Jim_IncrRefCount(exprObjPtr); |
| 14048 | 15147 | expr = JimGetExpression(interp, exprObjPtr); |
| 14049 | 15148 | if (!expr) { |
| 14050 | | - return JIM_ERR; |
| 15149 | + retcode = JIM_ERR; |
| 15150 | + goto done; |
| 14051 | 15151 | } |
| 14052 | 15152 | |
| 14053 | 15153 | #ifdef JIM_OPTIMIZATION |
| 14054 | | - { |
| 15154 | + if (!interp->safeexpr) { |
| 14055 | 15155 | Jim_Obj *objPtr; |
| 14056 | 15156 | |
| 14057 | 15157 | |
| 14058 | 15158 | switch (expr->len) { |
| 14059 | 15159 | case 1: |
| 14060 | 15160 | objPtr = JimExprIntValOrVar(interp, expr->expr); |
| 14061 | 15161 | if (objPtr) { |
| 14062 | 15162 | Jim_SetResult(interp, objPtr); |
| 14063 | | - return JIM_OK; |
| 15163 | + goto done; |
| 14064 | 15164 | } |
| 14065 | 15165 | break; |
| 14066 | 15166 | |
| 14067 | 15167 | case 2: |
| 14068 | 15168 | if (expr->expr->type == JIM_EXPROP_NOT) { |
| 14069 | 15169 | objPtr = JimExprIntValOrVar(interp, expr->expr->left); |
| 14070 | 15170 | |
| 14071 | 15171 | if (objPtr && JimIsWide(objPtr)) { |
| 14072 | 15172 | Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj); |
| 14073 | | - return JIM_OK; |
| 15173 | + goto done; |
| 14074 | 15174 | } |
| 14075 | 15175 | } |
| 14076 | 15176 | break; |
| 14077 | 15177 | |
| 14078 | 15178 | case 3: |
| | @@ -14104,11 +15204,11 @@ |
| 14104 | 15204 | break; |
| 14105 | 15205 | default: |
| 14106 | 15206 | goto noopt; |
| 14107 | 15207 | } |
| 14108 | 15208 | Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj); |
| 14109 | | - return JIM_OK; |
| 15209 | + goto done; |
| 14110 | 15210 | } |
| 14111 | 15211 | } |
| 14112 | 15212 | break; |
| 14113 | 15213 | } |
| 14114 | 15214 | } |
| | @@ -14118,11 +15218,17 @@ |
| 14118 | 15218 | expr->inUse++; |
| 14119 | 15219 | |
| 14120 | 15220 | |
| 14121 | 15221 | retcode = JimExprEvalTermNode(interp, expr->expr); |
| 14122 | 15222 | |
| 14123 | | - expr->inUse--; |
| 15223 | + |
| 15224 | + Jim_FreeIntRep(interp, exprObjPtr); |
| 15225 | + exprObjPtr->typePtr = &exprObjType; |
| 15226 | + Jim_SetIntRepPtr(exprObjPtr, expr); |
| 15227 | + |
| 15228 | +done: |
| 15229 | + Jim_DecrRefCount(interp, exprObjPtr); |
| 14124 | 15230 | |
| 14125 | 15231 | return retcode; |
| 14126 | 15232 | } |
| 14127 | 15233 | |
| 14128 | 15234 | int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) |
| | @@ -14405,21 +15511,21 @@ |
| 14405 | 15511 | |
| 14406 | 15512 | if (!sdescr && isspace(UCHAR(*str))) |
| 14407 | 15513 | break; |
| 14408 | 15514 | |
| 14409 | 15515 | n = utf8_tounicode(str, &c); |
| 14410 | | - if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) |
| 15516 | + if (sdescr && !JimCharsetMatch(sdescr, strlen(sdescr), c, JIM_CHARSET_SCAN)) |
| 14411 | 15517 | break; |
| 14412 | 15518 | while (n--) |
| 14413 | 15519 | *p++ = *str++; |
| 14414 | 15520 | } |
| 14415 | 15521 | *p = 0; |
| 14416 | 15522 | return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer); |
| 14417 | 15523 | } |
| 14418 | 15524 | |
| 14419 | 15525 | |
| 14420 | | -static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen, |
| 15526 | +static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int str_bytelen, |
| 14421 | 15527 | ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr) |
| 14422 | 15528 | { |
| 14423 | 15529 | const char *tok; |
| 14424 | 15530 | const ScanFmtPartDescr *descr = &fmtObj->descr[idx]; |
| 14425 | 15531 | size_t scanned = 0; |
| | @@ -14428,52 +15534,53 @@ |
| 14428 | 15534 | Jim_Obj *tmpObj = NULL; |
| 14429 | 15535 | |
| 14430 | 15536 | |
| 14431 | 15537 | *valObjPtr = 0; |
| 14432 | 15538 | if (descr->prefix) { |
| 14433 | | - for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 15539 | + for (i = 0; pos < str_bytelen && descr->prefix[i]; ++i) { |
| 14434 | 15540 | |
| 14435 | 15541 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14436 | | - while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 15542 | + while (pos < str_bytelen && isspace(UCHAR(str[pos]))) |
| 14437 | 15543 | ++pos; |
| 14438 | 15544 | else if (descr->prefix[i] != str[pos]) |
| 14439 | 15545 | break; |
| 14440 | 15546 | else |
| 14441 | 15547 | ++pos; |
| 14442 | 15548 | } |
| 14443 | | - if (pos >= strLen) { |
| 15549 | + if (pos >= str_bytelen) { |
| 14444 | 15550 | return -1; |
| 14445 | 15551 | } |
| 14446 | 15552 | else if (descr->prefix[i] != 0) |
| 14447 | 15553 | return 0; |
| 14448 | 15554 | } |
| 14449 | 15555 | |
| 14450 | 15556 | if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') |
| 14451 | 15557 | while (isspace(UCHAR(str[pos]))) |
| 14452 | 15558 | ++pos; |
| 15559 | + |
| 14453 | 15560 | |
| 14454 | 15561 | scanned = pos - anchor; |
| 14455 | 15562 | |
| 14456 | 15563 | |
| 14457 | 15564 | if (descr->type == 'n') { |
| 14458 | 15565 | |
| 14459 | 15566 | *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); |
| 14460 | 15567 | } |
| 14461 | | - else if (pos >= strLen) { |
| 15568 | + else if (pos >= str_bytelen) { |
| 14462 | 15569 | |
| 14463 | 15570 | return -1; |
| 14464 | 15571 | } |
| 14465 | 15572 | else if (descr->type == 'c') { |
| 14466 | | - int c; |
| 14467 | | - scanned += utf8_tounicode(&str[pos], &c); |
| 14468 | | - *valObjPtr = Jim_NewIntObj(interp, c); |
| 14469 | | - return scanned; |
| 15573 | + int c; |
| 15574 | + scanned += utf8_tounicode(&str[pos], &c); |
| 15575 | + *valObjPtr = Jim_NewIntObj(interp, c); |
| 15576 | + return scanned; |
| 14470 | 15577 | } |
| 14471 | 15578 | else { |
| 14472 | 15579 | |
| 14473 | 15580 | if (descr->width > 0) { |
| 14474 | | - size_t sLen = utf8_strlen(&str[pos], strLen - pos); |
| 15581 | + size_t sLen = utf8_strlen(&str[pos], str_bytelen - pos); |
| 14475 | 15582 | size_t tLen = descr->width > sLen ? sLen : descr->width; |
| 14476 | 15583 | |
| 14477 | 15584 | tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); |
| 14478 | 15585 | tok = tmpObj->bytes; |
| 14479 | 15586 | } |
| | @@ -14548,11 +15655,11 @@ |
| 14548 | 15655 | Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags) |
| 14549 | 15656 | { |
| 14550 | 15657 | size_t i, pos; |
| 14551 | 15658 | int scanned = 1; |
| 14552 | 15659 | const char *str = Jim_String(strObjPtr); |
| 14553 | | - int strLen = Jim_Utf8Length(interp, strObjPtr); |
| 15660 | + int str_bytelen = Jim_Length(strObjPtr); |
| 14554 | 15661 | Jim_Obj *resultList = 0; |
| 14555 | 15662 | Jim_Obj **resultVec = 0; |
| 14556 | 15663 | int resultc; |
| 14557 | 15664 | Jim_Obj *emptyStr = 0; |
| 14558 | 15665 | ScanFmtStringObj *fmtObj; |
| | @@ -14585,11 +15692,11 @@ |
| 14585 | 15692 | |
| 14586 | 15693 | if (descr->type == 0) |
| 14587 | 15694 | continue; |
| 14588 | 15695 | |
| 14589 | 15696 | if (scanned > 0) |
| 14590 | | - scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); |
| 15697 | + scanned = ScanOneEntry(interp, str, pos, str_bytelen, fmtObj, i, &value); |
| 14591 | 15698 | |
| 14592 | 15699 | if (scanned == -1 && i == 0) |
| 14593 | 15700 | goto eof; |
| 14594 | 15701 | |
| 14595 | 15702 | pos += scanned; |
| | @@ -14707,11 +15814,11 @@ |
| 14707 | 15814 | if (argc != 2 && argc != 3) { |
| 14708 | 15815 | Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?"); |
| 14709 | 15816 | return JIM_ERR; |
| 14710 | 15817 | } |
| 14711 | 15818 | if (argc == 3) { |
| 14712 | | - if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) |
| 15819 | + if (Jim_GetWideExpr(interp, argv[2], &increment) != JIM_OK) |
| 14713 | 15820 | return JIM_ERR; |
| 14714 | 15821 | } |
| 14715 | 15822 | intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 14716 | 15823 | if (!intObjPtr) { |
| 14717 | 15824 | |
| | @@ -14743,10 +15850,49 @@ |
| 14743 | 15850 | |
| 14744 | 15851 | |
| 14745 | 15852 | #define JIM_EVAL_SARGV_LEN 8 |
| 14746 | 15853 | #define JIM_EVAL_SINTV_LEN 8 |
| 14747 | 15854 | |
| 15855 | +static int JimTraceCallback(Jim_Interp *interp, const char *type, int argc, Jim_Obj *const *argv) |
| 15856 | +{ |
| 15857 | + JimPanic((interp->traceCmdObj == NULL, "xtrace invoked with no object")); |
| 15858 | + |
| 15859 | + int ret; |
| 15860 | + Jim_Obj *nargv[7]; |
| 15861 | + Jim_Obj *traceCmdObj = interp->traceCmdObj; |
| 15862 | + Jim_Obj *resultObj = Jim_GetResult(interp); |
| 15863 | + |
| 15864 | + ScriptObj *script = JimGetScript(interp, interp->evalFrame->scriptObj); |
| 15865 | + |
| 15866 | + nargv[0] = traceCmdObj; |
| 15867 | + nargv[1] = Jim_NewStringObj(interp, type, -1); |
| 15868 | + nargv[2] = script->fileNameObj; |
| 15869 | + nargv[3] = Jim_NewIntObj(interp, script->linenr); |
| 15870 | + nargv[4] = resultObj; |
| 15871 | + nargv[5] = argv[0]; |
| 15872 | + nargv[6] = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 15873 | + |
| 15874 | + |
| 15875 | + interp->traceCmdObj = NULL; |
| 15876 | + |
| 15877 | + Jim_IncrRefCount(resultObj); |
| 15878 | + ret = Jim_EvalObjVector(interp, 7, nargv); |
| 15879 | + Jim_DecrRefCount(interp, resultObj); |
| 15880 | + |
| 15881 | + if (ret == JIM_OK || ret == JIM_RETURN) { |
| 15882 | + |
| 15883 | + interp->traceCmdObj = traceCmdObj; |
| 15884 | + Jim_SetEmptyResult(interp); |
| 15885 | + ret = JIM_OK; |
| 15886 | + } |
| 15887 | + else { |
| 15888 | + |
| 15889 | + Jim_DecrRefCount(interp, traceCmdObj); |
| 15890 | + } |
| 15891 | + return ret; |
| 15892 | +} |
| 15893 | + |
| 14748 | 15894 | |
| 14749 | 15895 | static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 14750 | 15896 | { |
| 14751 | 15897 | int retcode; |
| 14752 | 15898 | |
| | @@ -14764,16 +15910,44 @@ |
| 14764 | 15910 | retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); |
| 14765 | 15911 | interp->unknown_called--; |
| 14766 | 15912 | |
| 14767 | 15913 | return retcode; |
| 14768 | 15914 | } |
| 15915 | + |
| 15916 | +static void JimPushEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *scriptObj) |
| 15917 | +{ |
| 15918 | + memset(frame, 0, sizeof(*frame)); |
| 15919 | + frame->parent = interp->evalFrame; |
| 15920 | + frame->level = frame->parent->level + 1; |
| 15921 | + frame->procLevel = interp->procLevel; |
| 15922 | + frame->framePtr = interp->framePtr; |
| 15923 | + if (scriptObj) { |
| 15924 | + frame->scriptObj = scriptObj; |
| 15925 | + } |
| 15926 | + else { |
| 15927 | + frame->scriptObj = frame->parent->scriptObj; |
| 15928 | + } |
| 15929 | + interp->evalFrame = frame; |
| 15930 | +#if 0 |
| 15931 | + if (frame->scriptObj) { |
| 15932 | + printf("script: %.*s\n", 20, Jim_String(frame->scriptObj)); |
| 15933 | + } |
| 15934 | +#endif |
| 15935 | +} |
| 15936 | + |
| 15937 | +static void JimPopEvalFrame(Jim_Interp *interp) |
| 15938 | +{ |
| 15939 | + interp->evalFrame = interp->evalFrame->parent; |
| 15940 | +} |
| 15941 | + |
| 14769 | 15942 | |
| 14770 | 15943 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14771 | 15944 | { |
| 14772 | 15945 | int retcode; |
| 14773 | 15946 | Jim_Cmd *cmdPtr; |
| 14774 | 15947 | void *prevPrivData; |
| 15948 | + Jim_Obj *tailcallObj = NULL; |
| 14775 | 15949 | |
| 14776 | 15950 | #if 0 |
| 14777 | 15951 | printf("invoke"); |
| 14778 | 15952 | int j; |
| 14779 | 15953 | for (j = 0; j < objc; j++) { |
| | @@ -14780,58 +15954,104 @@ |
| 14780 | 15954 | printf(" '%s'", Jim_String(objv[j])); |
| 14781 | 15955 | } |
| 14782 | 15956 | printf("\n"); |
| 14783 | 15957 | #endif |
| 14784 | 15958 | |
| 14785 | | - if (interp->framePtr->tailcallCmd) { |
| 14786 | | - |
| 14787 | | - cmdPtr = interp->framePtr->tailcallCmd; |
| 14788 | | - interp->framePtr->tailcallCmd = NULL; |
| 14789 | | - } |
| 14790 | | - else { |
| 14791 | | - cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| 14792 | | - if (cmdPtr == NULL) { |
| 14793 | | - return JimUnknown(interp, objc, objv); |
| 14794 | | - } |
| 14795 | | - JimIncrCmdRefCount(cmdPtr); |
| 14796 | | - } |
| 15959 | + cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| 15960 | + if (cmdPtr == NULL) { |
| 15961 | + return JimUnknown(interp, objc, objv); |
| 15962 | + } |
| 15963 | + JimIncrCmdRefCount(cmdPtr); |
| 14797 | 15964 | |
| 14798 | 15965 | if (interp->evalDepth == interp->maxEvalDepth) { |
| 14799 | 15966 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14800 | 15967 | retcode = JIM_ERR; |
| 14801 | 15968 | goto out; |
| 14802 | 15969 | } |
| 14803 | 15970 | interp->evalDepth++; |
| 14804 | 15971 | prevPrivData = interp->cmdPrivData; |
| 14805 | 15972 | |
| 14806 | | - |
| 14807 | | - Jim_SetEmptyResult(interp); |
| 14808 | | - if (cmdPtr->isproc) { |
| 14809 | | - retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14810 | | - } |
| 14811 | | - else { |
| 14812 | | - interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14813 | | - retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14814 | | - } |
| 15973 | +tailcall: |
| 15974 | + |
| 15975 | + interp->evalFrame->argc = objc; |
| 15976 | + interp->evalFrame->argv = objv; |
| 15977 | + interp->evalFrame->cmd = cmdPtr; |
| 15978 | + |
| 15979 | + if (!interp->traceCmdObj || |
| 15980 | + (retcode = JimTraceCallback(interp, "cmd", objc, objv)) == JIM_OK) { |
| 15981 | + |
| 15982 | + Jim_SetEmptyResult(interp); |
| 15983 | + if (cmdPtr->isproc) { |
| 15984 | + retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 15985 | + } |
| 15986 | + else { |
| 15987 | + interp->cmdPrivData = cmdPtr->u.native.privData; |
| 15988 | + retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 15989 | + } |
| 15990 | + if (retcode == JIM_ERR) { |
| 15991 | + JimSetErrorStack(interp); |
| 15992 | + } |
| 15993 | + } |
| 15994 | + |
| 15995 | + if (tailcallObj) { |
| 15996 | + |
| 15997 | + Jim_DecrRefCount(interp, tailcallObj); |
| 15998 | + tailcallObj = NULL; |
| 15999 | + } |
| 16000 | + |
| 16001 | + |
| 16002 | + interp->evalFrame->argc = 0; |
| 16003 | + interp->evalFrame->argv = NULL; |
| 16004 | + |
| 16005 | + |
| 16006 | + if (retcode == JIM_EVAL && interp->framePtr->tailcallObj) { |
| 16007 | + JimDecrCmdRefCount(interp, cmdPtr); |
| 16008 | + |
| 16009 | + |
| 16010 | + cmdPtr = interp->framePtr->tailcallCmd; |
| 16011 | + interp->framePtr->tailcallCmd = NULL; |
| 16012 | + tailcallObj = interp->framePtr->tailcallObj; |
| 16013 | + interp->framePtr->tailcallObj = NULL; |
| 16014 | + objc = tailcallObj->internalRep.listValue.len; |
| 16015 | + objv = tailcallObj->internalRep.listValue.ele; |
| 16016 | + goto tailcall; |
| 16017 | + } |
| 16018 | + |
| 14815 | 16019 | interp->cmdPrivData = prevPrivData; |
| 14816 | 16020 | interp->evalDepth--; |
| 14817 | 16021 | |
| 14818 | 16022 | out: |
| 14819 | 16023 | JimDecrCmdRefCount(interp, cmdPtr); |
| 16024 | + |
| 16025 | + if (retcode == JIM_ERR) { |
| 16026 | + JimSetErrorStack(interp); |
| 16027 | + } |
| 16028 | + |
| 16029 | + if (interp->framePtr->tailcallObj) { |
| 16030 | + JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 16031 | + Jim_DecrRefCount(interp, interp->framePtr->tailcallObj); |
| 16032 | + interp->framePtr->tailcallCmd = NULL; |
| 16033 | + interp->framePtr->tailcallObj = NULL; |
| 16034 | + } |
| 14820 | 16035 | |
| 14821 | 16036 | return retcode; |
| 14822 | 16037 | } |
| 14823 | 16038 | |
| 14824 | 16039 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14825 | 16040 | { |
| 14826 | 16041 | int i, retcode; |
| 16042 | + Jim_EvalFrame frame; |
| 14827 | 16043 | |
| 14828 | 16044 | |
| 14829 | 16045 | for (i = 0; i < objc; i++) |
| 14830 | 16046 | Jim_IncrRefCount(objv[i]); |
| 16047 | + |
| 16048 | + JimPushEvalFrame(interp, &frame, NULL); |
| 14831 | 16049 | |
| 14832 | 16050 | retcode = JimInvokeCommand(interp, objc, objv); |
| 16051 | + |
| 16052 | + JimPopEvalFrame(interp); |
| 14833 | 16053 | |
| 14834 | 16054 | |
| 14835 | 16055 | for (i = 0; i < objc; i++) |
| 14836 | 16056 | Jim_DecrRefCount(interp, objv[i]); |
| 14837 | 16057 | |
| | @@ -14848,44 +16068,14 @@ |
| 14848 | 16068 | ret = Jim_EvalObjVector(interp, objc + 1, nargv); |
| 14849 | 16069 | Jim_Free(nargv); |
| 14850 | 16070 | return ret; |
| 14851 | 16071 | } |
| 14852 | 16072 | |
| 14853 | | -static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) |
| 14854 | | -{ |
| 14855 | | - if (!interp->errorFlag) { |
| 14856 | | - |
| 14857 | | - interp->errorFlag = 1; |
| 14858 | | - Jim_IncrRefCount(script->fileNameObj); |
| 14859 | | - Jim_DecrRefCount(interp, interp->errorFileNameObj); |
| 14860 | | - interp->errorFileNameObj = script->fileNameObj; |
| 14861 | | - interp->errorLine = script->linenr; |
| 14862 | | - |
| 14863 | | - JimResetStackTrace(interp); |
| 14864 | | - |
| 14865 | | - interp->addStackTrace++; |
| 14866 | | - } |
| 14867 | | - |
| 14868 | | - |
| 14869 | | - if (interp->addStackTrace > 0) { |
| 14870 | | - |
| 14871 | | - |
| 14872 | | - JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); |
| 14873 | | - |
| 14874 | | - if (Jim_Length(script->fileNameObj)) { |
| 14875 | | - interp->addStackTrace = 0; |
| 14876 | | - } |
| 14877 | | - |
| 14878 | | - Jim_DecrRefCount(interp, interp->errorProc); |
| 14879 | | - interp->errorProc = interp->emptyObj; |
| 14880 | | - Jim_IncrRefCount(interp->errorProc); |
| 14881 | | - } |
| 14882 | | -} |
| 14883 | | - |
| 14884 | 16073 | static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr) |
| 14885 | 16074 | { |
| 14886 | 16075 | Jim_Obj *objPtr; |
| 16076 | + int ret = JIM_ERR; |
| 14887 | 16077 | |
| 14888 | 16078 | switch (token->type) { |
| 14889 | 16079 | case JIM_TT_STR: |
| 14890 | 16080 | case JIM_TT_ESC: |
| 14891 | 16081 | objPtr = token->objPtr; |
| | @@ -14895,26 +16085,25 @@ |
| 14895 | 16085 | break; |
| 14896 | 16086 | case JIM_TT_DICTSUGAR: |
| 14897 | 16087 | objPtr = JimExpandDictSugar(interp, token->objPtr); |
| 14898 | 16088 | break; |
| 14899 | 16089 | case JIM_TT_EXPRSUGAR: |
| 14900 | | - objPtr = JimExpandExprSugar(interp, token->objPtr); |
| 16090 | + ret = Jim_EvalExpression(interp, token->objPtr); |
| 16091 | + if (ret == JIM_OK) { |
| 16092 | + objPtr = Jim_GetResult(interp); |
| 16093 | + } |
| 16094 | + else { |
| 16095 | + objPtr = NULL; |
| 16096 | + } |
| 14901 | 16097 | break; |
| 14902 | 16098 | case JIM_TT_CMD: |
| 14903 | | - switch (Jim_EvalObj(interp, token->objPtr)) { |
| 14904 | | - case JIM_OK: |
| 14905 | | - case JIM_RETURN: |
| 14906 | | - objPtr = interp->result; |
| 14907 | | - break; |
| 14908 | | - case JIM_BREAK: |
| 14909 | | - |
| 14910 | | - return JIM_BREAK; |
| 14911 | | - case JIM_CONTINUE: |
| 14912 | | - |
| 14913 | | - return JIM_CONTINUE; |
| 14914 | | - default: |
| 14915 | | - return JIM_ERR; |
| 16099 | + ret = Jim_EvalObj(interp, token->objPtr); |
| 16100 | + if (ret == JIM_OK || ret == JIM_RETURN) { |
| 16101 | + objPtr = interp->result; |
| 16102 | + } else { |
| 16103 | + |
| 16104 | + objPtr = NULL; |
| 14916 | 16105 | } |
| 14917 | 16106 | break; |
| 14918 | 16107 | default: |
| 14919 | 16108 | JimPanic((1, |
| 14920 | 16109 | "default token type (%d) reached " "in Jim_SubstObj().", token->type)); |
| | @@ -14923,11 +16112,11 @@ |
| 14923 | 16112 | } |
| 14924 | 16113 | if (objPtr) { |
| 14925 | 16114 | *objPtrPtr = objPtr; |
| 14926 | 16115 | return JIM_OK; |
| 14927 | 16116 | } |
| 14928 | | - return JIM_ERR; |
| 16117 | + return ret; |
| 14929 | 16118 | } |
| 14930 | 16119 | |
| 14931 | 16120 | static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags) |
| 14932 | 16121 | { |
| 14933 | 16122 | int totlen = 0, i; |
| | @@ -15018,20 +16207,26 @@ |
| 15018 | 16207 | |
| 15019 | 16208 | |
| 15020 | 16209 | static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) |
| 15021 | 16210 | { |
| 15022 | 16211 | int retcode = JIM_OK; |
| 16212 | + Jim_EvalFrame frame; |
| 15023 | 16213 | |
| 15024 | 16214 | JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list.")); |
| 16215 | + |
| 16216 | + JimPushEvalFrame(interp, &frame, NULL); |
| 15025 | 16217 | |
| 15026 | 16218 | if (listPtr->internalRep.listValue.len) { |
| 15027 | 16219 | Jim_IncrRefCount(listPtr); |
| 15028 | 16220 | retcode = JimInvokeCommand(interp, |
| 15029 | 16221 | listPtr->internalRep.listValue.len, |
| 15030 | 16222 | listPtr->internalRep.listValue.ele); |
| 15031 | 16223 | Jim_DecrRefCount(interp, listPtr); |
| 15032 | 16224 | } |
| 16225 | + |
| 16226 | + JimPopEvalFrame(interp); |
| 16227 | + |
| 15033 | 16228 | return retcode; |
| 15034 | 16229 | } |
| 15035 | 16230 | |
| 15036 | 16231 | int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) |
| 15037 | 16232 | { |
| | @@ -15044,19 +16239,20 @@ |
| 15044 | 16239 | int i; |
| 15045 | 16240 | ScriptObj *script; |
| 15046 | 16241 | ScriptToken *token; |
| 15047 | 16242 | int retcode = JIM_OK; |
| 15048 | 16243 | Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL; |
| 15049 | | - Jim_Obj *prevScriptObj; |
| 16244 | + Jim_EvalFrame frame; |
| 15050 | 16245 | |
| 15051 | 16246 | if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { |
| 15052 | 16247 | return JimEvalObjList(interp, scriptObjPtr); |
| 15053 | 16248 | } |
| 15054 | 16249 | |
| 15055 | 16250 | Jim_IncrRefCount(scriptObjPtr); |
| 15056 | 16251 | script = JimGetScript(interp, scriptObjPtr); |
| 15057 | | - if (!JimScriptValid(interp, script)) { |
| 16252 | + if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) { |
| 16253 | + JimSetErrorStack(interp); |
| 15058 | 16254 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15059 | 16255 | return JIM_ERR; |
| 15060 | 16256 | } |
| 15061 | 16257 | |
| 15062 | 16258 | Jim_SetEmptyResult(interp); |
| | @@ -15086,13 +16282,12 @@ |
| 15086 | 16282 | } |
| 15087 | 16283 | #endif |
| 15088 | 16284 | |
| 15089 | 16285 | script->inUse++; |
| 15090 | 16286 | |
| 16287 | + JimPushEvalFrame(interp, &frame, scriptObjPtr); |
| 15091 | 16288 | |
| 15092 | | - prevScriptObj = interp->currentScriptObj; |
| 15093 | | - interp->currentScriptObj = scriptObjPtr; |
| 15094 | 16289 | |
| 15095 | 16290 | interp->errorFlag = 0; |
| 15096 | 16291 | argv = sargv; |
| 15097 | 16292 | |
| 15098 | 16293 | for (i = 0; i < script->len && retcode == JIM_OK; ) { |
| | @@ -15132,11 +16327,17 @@ |
| 15132 | 16327 | break; |
| 15133 | 16328 | case JIM_TT_VAR: |
| 15134 | 16329 | wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG); |
| 15135 | 16330 | break; |
| 15136 | 16331 | case JIM_TT_EXPRSUGAR: |
| 15137 | | - wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr); |
| 16332 | + retcode = Jim_EvalExpression(interp, token[i].objPtr); |
| 16333 | + if (retcode == JIM_OK) { |
| 16334 | + wordObjPtr = Jim_GetResult(interp); |
| 16335 | + } |
| 16336 | + else { |
| 16337 | + wordObjPtr = NULL; |
| 16338 | + } |
| 15138 | 16339 | break; |
| 15139 | 16340 | case JIM_TT_DICTSUGAR: |
| 15140 | 16341 | wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr); |
| 15141 | 16342 | break; |
| 15142 | 16343 | case JIM_TT_CMD: |
| | @@ -15219,20 +16420,14 @@ |
| 15219 | 16420 | } |
| 15220 | 16421 | } |
| 15221 | 16422 | |
| 15222 | 16423 | |
| 15223 | 16424 | if (retcode == JIM_ERR) { |
| 15224 | | - JimAddErrorToStack(interp, script); |
| 16425 | + JimSetErrorStack(interp); |
| 15225 | 16426 | } |
| 15226 | 16427 | |
| 15227 | | - else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { |
| 15228 | | - |
| 15229 | | - interp->addStackTrace = 0; |
| 15230 | | - } |
| 15231 | | - |
| 15232 | | - |
| 15233 | | - interp->currentScriptObj = prevScriptObj; |
| 16428 | + JimPopEvalFrame(interp); |
| 15234 | 16429 | |
| 15235 | 16430 | Jim_FreeIntRep(interp, scriptObjPtr); |
| 15236 | 16431 | scriptObjPtr->typePtr = &scriptObjType; |
| 15237 | 16432 | Jim_SetIntRepPtr(scriptObjPtr, script); |
| 15238 | 16433 | Jim_DecrRefCount(interp, scriptObjPtr); |
| | @@ -15285,11 +16480,11 @@ |
| 15285 | 16480 | Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); |
| 15286 | 16481 | Jim_AppendString(interp, argmsg, " ...?", -1); |
| 15287 | 16482 | } |
| 15288 | 16483 | else { |
| 15289 | 16484 | |
| 15290 | | - Jim_AppendString(interp, argmsg, "?arg...?", -1); |
| 16485 | + Jim_AppendString(interp, argmsg, "?arg ...?", -1); |
| 15291 | 16486 | } |
| 15292 | 16487 | } |
| 15293 | 16488 | else { |
| 15294 | 16489 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| 15295 | 16490 | Jim_AppendString(interp, argmsg, "?", 1); |
| | @@ -15314,17 +16509,15 @@ |
| 15314 | 16509 | Jim_CallFrame *callFramePtr; |
| 15315 | 16510 | int retcode; |
| 15316 | 16511 | |
| 15317 | 16512 | |
| 15318 | 16513 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); |
| 15319 | | - callFramePtr->argv = &interp->emptyObj; |
| 15320 | | - callFramePtr->argc = 0; |
| 16514 | + callFramePtr->argv = interp->evalFrame->argv; |
| 16515 | + callFramePtr->argc = interp->evalFrame->argc; |
| 15321 | 16516 | callFramePtr->procArgsObjPtr = NULL; |
| 15322 | 16517 | callFramePtr->procBodyObjPtr = scriptObj; |
| 15323 | 16518 | callFramePtr->staticVars = NULL; |
| 15324 | | - callFramePtr->fileNameObj = interp->emptyObj; |
| 15325 | | - callFramePtr->line = 0; |
| 15326 | 16519 | Jim_IncrRefCount(scriptObj); |
| 15327 | 16520 | interp->framePtr = callFramePtr; |
| 15328 | 16521 | |
| 15329 | 16522 | |
| 15330 | 16523 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| | @@ -15346,11 +16539,10 @@ |
| 15346 | 16539 | |
| 15347 | 16540 | static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) |
| 15348 | 16541 | { |
| 15349 | 16542 | Jim_CallFrame *callFramePtr; |
| 15350 | 16543 | int i, d, retcode, optargs; |
| 15351 | | - ScriptObj *script; |
| 15352 | 16544 | |
| 15353 | 16545 | |
| 15354 | 16546 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15355 | 16547 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| 15356 | 16548 | JimSetProcWrongArgs(interp, argv[0], cmd); |
| | @@ -15374,14 +16566,11 @@ |
| 15374 | 16566 | callFramePtr->argc = argc; |
| 15375 | 16567 | callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; |
| 15376 | 16568 | callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; |
| 15377 | 16569 | callFramePtr->staticVars = cmd->u.proc.staticVars; |
| 15378 | 16570 | |
| 15379 | | - |
| 15380 | | - script = JimGetScript(interp, interp->currentScriptObj); |
| 15381 | | - callFramePtr->fileNameObj = script->fileNameObj; |
| 15382 | | - callFramePtr->line = script->linenr; |
| 16571 | + interp->procLevel++; |
| 15383 | 16572 | |
| 15384 | 16573 | Jim_IncrRefCount(cmd->u.proc.argListObjPtr); |
| 15385 | 16574 | Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); |
| 15386 | 16575 | interp->framePtr = callFramePtr; |
| 15387 | 16576 | |
| | @@ -15425,57 +16614,32 @@ |
| 15425 | 16614 | if (retcode != JIM_OK) { |
| 15426 | 16615 | goto badargset; |
| 15427 | 16616 | } |
| 15428 | 16617 | } |
| 15429 | 16618 | |
| 16619 | + if (interp->traceCmdObj == NULL || |
| 16620 | + (retcode = JimTraceCallback(interp, "proc", argc, argv)) == JIM_OK) { |
| 15430 | 16621 | |
| 15431 | | - retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 16622 | + retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 16623 | + } |
| 15432 | 16624 | |
| 15433 | 16625 | badargset: |
| 15434 | 16626 | |
| 15435 | 16627 | |
| 15436 | 16628 | retcode = JimInvokeDefer(interp, retcode); |
| 15437 | 16629 | interp->framePtr = interp->framePtr->parent; |
| 15438 | 16630 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15439 | 16631 | |
| 15440 | | - |
| 15441 | | - if (interp->framePtr->tailcallObj) { |
| 15442 | | - do { |
| 15443 | | - Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15444 | | - |
| 15445 | | - interp->framePtr->tailcallObj = NULL; |
| 15446 | | - |
| 15447 | | - if (retcode == JIM_EVAL) { |
| 15448 | | - retcode = Jim_EvalObjList(interp, tailcallObj); |
| 15449 | | - if (retcode == JIM_RETURN) { |
| 15450 | | - interp->returnLevel++; |
| 15451 | | - } |
| 15452 | | - } |
| 15453 | | - Jim_DecrRefCount(interp, tailcallObj); |
| 15454 | | - } while (interp->framePtr->tailcallObj); |
| 15455 | | - |
| 15456 | | - |
| 15457 | | - if (interp->framePtr->tailcallCmd) { |
| 15458 | | - JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15459 | | - interp->framePtr->tailcallCmd = NULL; |
| 15460 | | - } |
| 15461 | | - } |
| 15462 | | - |
| 15463 | 16632 | |
| 15464 | 16633 | if (retcode == JIM_RETURN) { |
| 15465 | 16634 | if (--interp->returnLevel <= 0) { |
| 15466 | 16635 | retcode = interp->returnCode; |
| 15467 | 16636 | interp->returnCode = JIM_OK; |
| 15468 | 16637 | interp->returnLevel = 0; |
| 15469 | 16638 | } |
| 15470 | 16639 | } |
| 15471 | | - else if (retcode == JIM_ERR) { |
| 15472 | | - interp->addStackTrace++; |
| 15473 | | - Jim_DecrRefCount(interp, interp->errorProc); |
| 15474 | | - interp->errorProc = argv[0]; |
| 15475 | | - Jim_IncrRefCount(interp->errorProc); |
| 15476 | | - } |
| 16640 | + interp->procLevel--; |
| 15477 | 16641 | |
| 15478 | 16642 | return retcode; |
| 15479 | 16643 | } |
| 15480 | 16644 | |
| 15481 | 16645 | int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) |
| | @@ -15483,26 +16647,14 @@ |
| 15483 | 16647 | int retval; |
| 15484 | 16648 | Jim_Obj *scriptObjPtr; |
| 15485 | 16649 | |
| 15486 | 16650 | scriptObjPtr = Jim_NewStringObj(interp, script, -1); |
| 15487 | 16651 | Jim_IncrRefCount(scriptObjPtr); |
| 15488 | | - |
| 15489 | 16652 | if (filename) { |
| 15490 | | - Jim_Obj *prevScriptObj; |
| 15491 | | - |
| 15492 | 16653 | JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); |
| 15493 | | - |
| 15494 | | - prevScriptObj = interp->currentScriptObj; |
| 15495 | | - interp->currentScriptObj = scriptObjPtr; |
| 15496 | | - |
| 15497 | | - retval = Jim_EvalObj(interp, scriptObjPtr); |
| 15498 | | - |
| 15499 | | - interp->currentScriptObj = prevScriptObj; |
| 15500 | | - } |
| 15501 | | - else { |
| 15502 | | - retval = Jim_EvalObj(interp, scriptObjPtr); |
| 15503 | | - } |
| 16654 | + } |
| 16655 | + retval = Jim_EvalObj(interp, scriptObjPtr); |
| 15504 | 16656 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15505 | 16657 | return retval; |
| 15506 | 16658 | } |
| 15507 | 16659 | |
| 15508 | 16660 | int Jim_Eval(Jim_Interp *interp, const char *script) |
| | @@ -15535,65 +16687,69 @@ |
| 15535 | 16687 | return retval; |
| 15536 | 16688 | } |
| 15537 | 16689 | |
| 15538 | 16690 | #include <sys/stat.h> |
| 15539 | 16691 | |
| 15540 | | -int Jim_EvalFile(Jim_Interp *interp, const char *filename) |
| 15541 | | -{ |
| 15542 | | - FILE *fp; |
| 15543 | | - char *buf; |
| 15544 | | - Jim_Obj *scriptObjPtr; |
| 15545 | | - Jim_Obj *prevScriptObj; |
| 15546 | | - struct stat sb; |
| 15547 | | - int retcode; |
| 16692 | +static Jim_Obj *JimReadTextFile(Jim_Interp *interp, const char *filename) |
| 16693 | +{ |
| 16694 | + jim_stat_t sb; |
| 16695 | + int fd; |
| 16696 | + char *buf; |
| 15548 | 16697 | int readlen; |
| 15549 | 16698 | |
| 15550 | | - if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { |
| 16699 | + if (Jim_Stat(filename, &sb) == -1 || (fd = open(filename, O_RDONLY | O_TEXT, 0666)) < 0) { |
| 15551 | 16700 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); |
| 15552 | | - return JIM_ERR; |
| 16701 | + return NULL; |
| 15553 | 16702 | } |
| 15554 | | - if (sb.st_size == 0) { |
| 15555 | | - fclose(fp); |
| 15556 | | - return JIM_OK; |
| 15557 | | - } |
| 15558 | | - |
| 15559 | 16703 | buf = Jim_Alloc(sb.st_size + 1); |
| 15560 | | - readlen = fread(buf, 1, sb.st_size, fp); |
| 15561 | | - if (ferror(fp)) { |
| 15562 | | - fclose(fp); |
| 16704 | + readlen = read(fd, buf, sb.st_size); |
| 16705 | + close(fd); |
| 16706 | + if (readlen < 0) { |
| 15563 | 16707 | Jim_Free(buf); |
| 15564 | 16708 | Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno)); |
| 16709 | + return NULL; |
| 16710 | + } |
| 16711 | + else { |
| 16712 | + Jim_Obj *objPtr; |
| 16713 | + buf[readlen] = 0; |
| 16714 | + |
| 16715 | + objPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 16716 | + |
| 16717 | + return objPtr; |
| 16718 | + } |
| 16719 | +} |
| 16720 | + |
| 16721 | + |
| 16722 | +int Jim_EvalFile(Jim_Interp *interp, const char *filename) |
| 16723 | +{ |
| 16724 | + Jim_Obj *filenameObj; |
| 16725 | + Jim_Obj *oldFilenameObj; |
| 16726 | + Jim_Obj *scriptObjPtr; |
| 16727 | + int retcode; |
| 16728 | + |
| 16729 | + scriptObjPtr = JimReadTextFile(interp, filename); |
| 16730 | + if (!scriptObjPtr) { |
| 15565 | 16731 | return JIM_ERR; |
| 15566 | 16732 | } |
| 15567 | | - fclose(fp); |
| 15568 | | - buf[readlen] = 0; |
| 15569 | | - |
| 15570 | | - scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); |
| 15571 | | - JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); |
| 15572 | | - Jim_IncrRefCount(scriptObjPtr); |
| 15573 | | - |
| 15574 | | - prevScriptObj = interp->currentScriptObj; |
| 15575 | | - interp->currentScriptObj = scriptObjPtr; |
| 16733 | + |
| 16734 | + filenameObj = Jim_NewStringObj(interp, filename, -1); |
| 16735 | + JimSetSourceInfo(interp, scriptObjPtr, filenameObj, 1); |
| 16736 | + |
| 16737 | + oldFilenameObj = JimPushInterpObj(interp->currentFilenameObj, filenameObj); |
| 15576 | 16738 | |
| 15577 | 16739 | retcode = Jim_EvalObj(interp, scriptObjPtr); |
| 16740 | + |
| 16741 | + JimPopInterpObj(interp, interp->currentFilenameObj, oldFilenameObj); |
| 15578 | 16742 | |
| 15579 | 16743 | |
| 15580 | 16744 | if (retcode == JIM_RETURN) { |
| 15581 | 16745 | if (--interp->returnLevel <= 0) { |
| 15582 | 16746 | retcode = interp->returnCode; |
| 15583 | 16747 | interp->returnCode = JIM_OK; |
| 15584 | 16748 | interp->returnLevel = 0; |
| 15585 | 16749 | } |
| 15586 | 16750 | } |
| 15587 | | - if (retcode == JIM_ERR) { |
| 15588 | | - |
| 15589 | | - interp->addStackTrace++; |
| 15590 | | - } |
| 15591 | | - |
| 15592 | | - interp->currentScriptObj = prevScriptObj; |
| 15593 | | - |
| 15594 | | - Jim_DecrRefCount(interp, scriptObjPtr); |
| 15595 | 16751 | |
| 15596 | 16752 | return retcode; |
| 15597 | 16753 | } |
| 15598 | 16754 | |
| 15599 | 16755 | static void JimParseSubst(struct JimParserCtx *pc, int flags) |
| | @@ -15696,11 +16852,15 @@ |
| 15696 | 16852 | return (ScriptObj *) Jim_GetIntRepPtr(objPtr); |
| 15697 | 16853 | } |
| 15698 | 16854 | |
| 15699 | 16855 | int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) |
| 15700 | 16856 | { |
| 15701 | | - ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); |
| 16857 | + ScriptObj *script; |
| 16858 | + |
| 16859 | + JimPanic((substObjPtr->refCount == 0, "Jim_SubstObj() called with zero refcount object")); |
| 16860 | + |
| 16861 | + script = Jim_GetSubst(interp, substObjPtr, flags); |
| 15702 | 16862 | |
| 15703 | 16863 | Jim_IncrRefCount(substObjPtr); |
| 15704 | 16864 | script->inUse++; |
| 15705 | 16865 | |
| 15706 | 16866 | *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); |
| | @@ -15731,11 +16891,11 @@ |
| 15731 | 16891 | |
| 15732 | 16892 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); |
| 15733 | 16893 | } |
| 15734 | 16894 | |
| 15735 | 16895 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15736 | | - Jim_HashEntry *he, int type); |
| 16896 | + Jim_Obj *keyObjPtr, void *value, Jim_Obj *patternObjPtr, int type); |
| 15737 | 16897 | |
| 15738 | 16898 | #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) |
| 15739 | 16899 | |
| 15740 | 16900 | static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 15741 | 16901 | JimHashtableIteratorCallbackType *callback, int type) |
| | @@ -15743,22 +16903,22 @@ |
| 15743 | 16903 | Jim_HashEntry *he; |
| 15744 | 16904 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 15745 | 16905 | |
| 15746 | 16906 | |
| 15747 | 16907 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { |
| 15748 | | - he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); |
| 16908 | + he = Jim_FindHashEntry(ht, patternObjPtr); |
| 15749 | 16909 | if (he) { |
| 15750 | | - callback(interp, listObjPtr, he, type); |
| 16910 | + callback(interp, listObjPtr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he), |
| 16911 | + patternObjPtr, type); |
| 15751 | 16912 | } |
| 15752 | 16913 | } |
| 15753 | 16914 | else { |
| 15754 | 16915 | Jim_HashTableIterator htiter; |
| 15755 | 16916 | JimInitHashTableIterator(ht, &htiter); |
| 15756 | 16917 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 15757 | | - if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) { |
| 15758 | | - callback(interp, listObjPtr, he, type); |
| 15759 | | - } |
| 16918 | + callback(interp, listObjPtr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he), |
| 16919 | + patternObjPtr, type); |
| 15760 | 16920 | } |
| 15761 | 16921 | } |
| 15762 | 16922 | return listObjPtr; |
| 15763 | 16923 | } |
| 15764 | 16924 | |
| | @@ -15766,29 +16926,40 @@ |
| 15766 | 16926 | #define JIM_CMDLIST_COMMANDS 0 |
| 15767 | 16927 | #define JIM_CMDLIST_PROCS 1 |
| 15768 | 16928 | #define JIM_CMDLIST_CHANNELS 2 |
| 15769 | 16929 | |
| 15770 | 16930 | static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15771 | | - Jim_HashEntry *he, int type) |
| 16931 | + Jim_Obj *keyObj, void *value, Jim_Obj *patternObj, int type) |
| 15772 | 16932 | { |
| 15773 | | - Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15774 | | - Jim_Obj *objPtr; |
| 16933 | + Jim_Cmd *cmdPtr = (Jim_Cmd *)value; |
| 15775 | 16934 | |
| 15776 | 16935 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15777 | 16936 | |
| 15778 | 16937 | return; |
| 15779 | 16938 | } |
| 15780 | 16939 | |
| 15781 | | - objPtr = Jim_NewStringObj(interp, he->key, -1); |
| 15782 | | - Jim_IncrRefCount(objPtr); |
| 15783 | | - |
| 15784 | | - if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) { |
| 15785 | | - Jim_ListAppendElement(interp, listObjPtr, objPtr); |
| 15786 | | - } |
| 15787 | | - Jim_DecrRefCount(interp, objPtr); |
| 15788 | | -} |
| 15789 | | - |
| 16940 | + Jim_IncrRefCount(keyObj); |
| 16941 | + |
| 16942 | + if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, keyObj) >= 0) { |
| 16943 | + int match = 1; |
| 16944 | + if (patternObj) { |
| 16945 | + int plen, slen; |
| 16946 | + const char *pattern = Jim_GetStringNoQualifier(patternObj, &plen); |
| 16947 | + const char *str = Jim_GetStringNoQualifier(keyObj, &slen); |
| 16948 | +#ifdef JIM_NO_INTROSPECTION |
| 16949 | + |
| 16950 | + match = (JimStringCompareUtf8(pattern, plen, str, slen, 0) == 0); |
| 16951 | +#else |
| 16952 | + match = JimGlobMatch(pattern, plen, str, slen, 0); |
| 16953 | +#endif |
| 16954 | + } |
| 16955 | + if (match) { |
| 16956 | + Jim_ListAppendElement(interp, listObjPtr, keyObj); |
| 16957 | + } |
| 16958 | + } |
| 16959 | + Jim_DecrRefCount(interp, keyObj); |
| 16960 | +} |
| 15790 | 16961 | |
| 15791 | 16962 | static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type) |
| 15792 | 16963 | { |
| 15793 | 16964 | return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type); |
| 15794 | 16965 | } |
| | @@ -15795,22 +16966,25 @@ |
| 15795 | 16966 | |
| 15796 | 16967 | |
| 15797 | 16968 | #define JIM_VARLIST_GLOBALS 0 |
| 15798 | 16969 | #define JIM_VARLIST_LOCALS 1 |
| 15799 | 16970 | #define JIM_VARLIST_VARS 2 |
| 16971 | +#define JIM_VARLIST_MASK 0x000f |
| 15800 | 16972 | |
| 15801 | 16973 | #define JIM_VARLIST_VALUES 0x1000 |
| 15802 | 16974 | |
| 15803 | 16975 | static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15804 | | - Jim_HashEntry *he, int type) |
| 15805 | | -{ |
| 15806 | | - Jim_Var *varPtr = Jim_GetHashEntryVal(he); |
| 15807 | | - |
| 15808 | | - if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { |
| 15809 | | - Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); |
| 15810 | | - if (type & JIM_VARLIST_VALUES) { |
| 15811 | | - Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); |
| 16976 | + Jim_Obj *keyObj, void *value, Jim_Obj *patternObj, int type) |
| 16977 | +{ |
| 16978 | + Jim_VarVal *vv = (Jim_VarVal *)value; |
| 16979 | + |
| 16980 | + if ((type & JIM_VARLIST_MASK) != JIM_VARLIST_LOCALS || vv->linkFramePtr == NULL) { |
| 16981 | + if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, keyObj, 0)) { |
| 16982 | + Jim_ListAppendElement(interp, listObjPtr, keyObj); |
| 16983 | + if (type & JIM_VARLIST_VALUES) { |
| 16984 | + Jim_ListAppendElement(interp, listObjPtr, vv->objPtr); |
| 16985 | + } |
| 15812 | 16986 | } |
| 15813 | 16987 | } |
| 15814 | 16988 | } |
| 15815 | 16989 | |
| 15816 | 16990 | |
| | @@ -15819,42 +16993,78 @@ |
| 15819 | 16993 | if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) { |
| 15820 | 16994 | return interp->emptyObj; |
| 15821 | 16995 | } |
| 15822 | 16996 | else { |
| 15823 | 16997 | Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr; |
| 15824 | | - return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode); |
| 15825 | | - } |
| 15826 | | -} |
| 15827 | | - |
| 15828 | | -static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, |
| 15829 | | - Jim_Obj **objPtrPtr, int info_level_cmd) |
| 15830 | | -{ |
| 15831 | | - Jim_CallFrame *targetCallFrame; |
| 15832 | | - |
| 15833 | | - targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); |
| 15834 | | - if (targetCallFrame == NULL) { |
| 15835 | | - return JIM_ERR; |
| 15836 | | - } |
| 15837 | | - |
| 15838 | | - if (targetCallFrame == interp->topFramePtr) { |
| 15839 | | - Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 15840 | | - return JIM_ERR; |
| 15841 | | - } |
| 15842 | | - if (info_level_cmd) { |
| 15843 | | - *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); |
| 15844 | | - } |
| 15845 | | - else { |
| 15846 | | - Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 15847 | | - |
| 15848 | | - Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); |
| 15849 | | - Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj); |
| 15850 | | - Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); |
| 15851 | | - *objPtrPtr = listObj; |
| 15852 | | - } |
| 15853 | | - return JIM_OK; |
| 15854 | | -} |
| 15855 | | - |
| 16998 | + return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, |
| 16999 | + mode); |
| 17000 | + } |
| 17001 | +} |
| 17002 | + |
| 17003 | +static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objPtrPtr) |
| 17004 | +{ |
| 17005 | + long level; |
| 17006 | + |
| 17007 | + if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 17008 | + Jim_CallFrame *targetCallFrame = JimGetCallFrameByInteger(interp, level); |
| 17009 | + if (targetCallFrame && targetCallFrame != interp->topFramePtr) { |
| 17010 | +#ifdef JIM_NO_INTROSPECTION |
| 17011 | + |
| 17012 | + *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, 1); |
| 17013 | +#else |
| 17014 | + *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); |
| 17015 | +#endif |
| 17016 | + return JIM_OK; |
| 17017 | + } |
| 17018 | + } |
| 17019 | + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 17020 | + return JIM_ERR; |
| 17021 | +} |
| 17022 | + |
| 17023 | +static int JimInfoFrame(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objPtrPtr) |
| 17024 | +{ |
| 17025 | + long level; |
| 17026 | + |
| 17027 | + if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 17028 | + Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, level); |
| 17029 | + if (frame) { |
| 17030 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 17031 | + |
| 17032 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 17033 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "source", -1)); |
| 17034 | + if (frame->scriptObj) { |
| 17035 | + ScriptObj *script = JimGetScript(interp, frame->scriptObj); |
| 17036 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "line", -1)); |
| 17037 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, script->linenr)); |
| 17038 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "file", -1)); |
| 17039 | + Jim_ListAppendElement(interp, listObj, script->fileNameObj); |
| 17040 | + } |
| 17041 | +#ifndef JIM_NO_INTROSPECTION |
| 17042 | + { |
| 17043 | + Jim_Obj *cmdObj = Jim_NewListObj(interp, frame->argv, frame->argc); |
| 17044 | + |
| 17045 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "cmd", -1)); |
| 17046 | + Jim_ListAppendElement(interp, listObj, cmdObj); |
| 17047 | + } |
| 17048 | +#endif |
| 17049 | + { |
| 17050 | + Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame); |
| 17051 | + if (procNameObj) { |
| 17052 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1)); |
| 17053 | + Jim_ListAppendElement(interp, listObj, procNameObj); |
| 17054 | + } |
| 17055 | + } |
| 17056 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "level", -1)); |
| 17057 | + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - frame->framePtr->level)); |
| 17058 | + |
| 17059 | + *objPtrPtr = listObj; |
| 17060 | + return JIM_OK; |
| 17061 | + } |
| 17062 | + } |
| 17063 | + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 17064 | + return JIM_ERR; |
| 17065 | +} |
| 15856 | 17066 | |
| 15857 | 17067 | |
| 15858 | 17068 | static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 15859 | 17069 | { |
| 15860 | 17070 | if (argc != 2 && argc != 3) { |
| | @@ -16056,12 +17266,24 @@ |
| 16056 | 17266 | && complain) { |
| 16057 | 17267 | return JIM_ERR; |
| 16058 | 17268 | } |
| 16059 | 17269 | i++; |
| 16060 | 17270 | } |
| 17271 | + |
| 17272 | + Jim_SetEmptyResult(interp); |
| 16061 | 17273 | return JIM_OK; |
| 16062 | 17274 | } |
| 17275 | + |
| 17276 | +static int JimCheckLoopRetcode(Jim_Interp *interp, int retval) |
| 17277 | +{ |
| 17278 | + if (retval == JIM_BREAK || retval == JIM_CONTINUE) { |
| 17279 | + if (--interp->returnLevel > 0) { |
| 17280 | + return 1; |
| 17281 | + } |
| 17282 | + } |
| 17283 | + return 0; |
| 17284 | +} |
| 16063 | 17285 | |
| 16064 | 17286 | |
| 16065 | 17287 | static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16066 | 17288 | { |
| 16067 | 17289 | if (argc != 3) { |
| | @@ -16069,25 +17291,26 @@ |
| 16069 | 17291 | return JIM_ERR; |
| 16070 | 17292 | } |
| 16071 | 17293 | |
| 16072 | 17294 | |
| 16073 | 17295 | while (1) { |
| 16074 | | - int boolean, retval; |
| 17296 | + int boolean = 0, retval; |
| 16075 | 17297 | |
| 16076 | 17298 | if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) |
| 16077 | 17299 | return retval; |
| 16078 | 17300 | if (!boolean) |
| 16079 | 17301 | break; |
| 16080 | 17302 | |
| 16081 | 17303 | if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) { |
| 17304 | + if (JimCheckLoopRetcode(interp, retval)) { |
| 17305 | + return retval; |
| 17306 | + } |
| 16082 | 17307 | switch (retval) { |
| 16083 | 17308 | case JIM_BREAK: |
| 16084 | 17309 | goto out; |
| 16085 | | - break; |
| 16086 | 17310 | case JIM_CONTINUE: |
| 16087 | 17311 | continue; |
| 16088 | | - break; |
| 16089 | 17312 | default: |
| 16090 | 17313 | return retval; |
| 16091 | 17314 | } |
| 16092 | 17315 | } |
| 16093 | 17316 | } |
| | @@ -16099,10 +17322,11 @@ |
| 16099 | 17322 | |
| 16100 | 17323 | static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16101 | 17324 | { |
| 16102 | 17325 | int retval; |
| 16103 | 17326 | int boolean = 1; |
| 17327 | + int immediate = 0; |
| 16104 | 17328 | Jim_Obj *varNamePtr = NULL; |
| 16105 | 17329 | Jim_Obj *stopVarNamePtr = NULL; |
| 16106 | 17330 | |
| 16107 | 17331 | if (argc != 5) { |
| 16108 | 17332 | Jim_WrongNumArgs(interp, 1, argv, "start test next body"); |
| | @@ -16166,11 +17390,11 @@ |
| 16166 | 17390 | goto evalstart; |
| 16167 | 17391 | } |
| 16168 | 17392 | |
| 16169 | 17393 | |
| 16170 | 17394 | if (expr->expr->right->type == JIM_TT_EXPR_INT) { |
| 16171 | | - if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) { |
| 17395 | + if (Jim_GetWideExpr(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) { |
| 16172 | 17396 | goto evalstart; |
| 16173 | 17397 | } |
| 16174 | 17398 | } |
| 16175 | 17399 | else { |
| 16176 | 17400 | stopVarNamePtr = expr->expr->right->objPtr; |
| | @@ -16205,10 +17429,14 @@ |
| 16205 | 17429 | break; |
| 16206 | 17430 | } |
| 16207 | 17431 | |
| 16208 | 17432 | |
| 16209 | 17433 | retval = Jim_EvalObj(interp, argv[4]); |
| 17434 | + if (JimCheckLoopRetcode(interp, retval)) { |
| 17435 | + immediate++; |
| 17436 | + goto out; |
| 17437 | + } |
| 16210 | 17438 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16211 | 17439 | retval = JIM_OK; |
| 16212 | 17440 | |
| 16213 | 17441 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); |
| 16214 | 17442 | |
| | @@ -16241,10 +17469,14 @@ |
| 16241 | 17469 | |
| 16242 | 17470 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16243 | 17471 | |
| 16244 | 17472 | JIM_IF_OPTIM(evalnext:) |
| 16245 | 17473 | retval = Jim_EvalObj(interp, argv[3]); |
| 17474 | + if (JimCheckLoopRetcode(interp, retval)) { |
| 17475 | + immediate++; |
| 17476 | + goto out; |
| 17477 | + } |
| 16246 | 17478 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16247 | 17479 | |
| 16248 | 17480 | JIM_IF_OPTIM(testcond:) |
| 16249 | 17481 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| 16250 | 17482 | } |
| | @@ -16256,13 +17488,15 @@ |
| 16256 | 17488 | } |
| 16257 | 17489 | if (varNamePtr) { |
| 16258 | 17490 | Jim_DecrRefCount(interp, varNamePtr); |
| 16259 | 17491 | } |
| 16260 | 17492 | |
| 16261 | | - if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { |
| 16262 | | - Jim_SetEmptyResult(interp); |
| 16263 | | - return JIM_OK; |
| 17493 | + if (!immediate) { |
| 17494 | + if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { |
| 17495 | + Jim_SetEmptyResult(interp); |
| 17496 | + return JIM_OK; |
| 17497 | + } |
| 16264 | 17498 | } |
| 16265 | 17499 | |
| 16266 | 17500 | return retval; |
| 16267 | 17501 | } |
| 16268 | 17502 | |
| | @@ -16273,26 +17507,38 @@ |
| 16273 | 17507 | jim_wide i; |
| 16274 | 17508 | jim_wide limit; |
| 16275 | 17509 | jim_wide incr = 1; |
| 16276 | 17510 | Jim_Obj *bodyObjPtr; |
| 16277 | 17511 | |
| 16278 | | - if (argc != 5 && argc != 6) { |
| 16279 | | - Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body"); |
| 17512 | + if (argc < 4 || argc > 6) { |
| 17513 | + Jim_WrongNumArgs(interp, 1, argv, "var ?first? limit ?incr? body"); |
| 16280 | 17514 | return JIM_ERR; |
| 16281 | 17515 | } |
| 16282 | 17516 | |
| 16283 | | - if (Jim_GetWide(interp, argv[2], &i) != JIM_OK || |
| 16284 | | - Jim_GetWide(interp, argv[3], &limit) != JIM_OK || |
| 16285 | | - (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) { |
| 16286 | | - return JIM_ERR; |
| 16287 | | - } |
| 16288 | | - bodyObjPtr = (argc == 5) ? argv[4] : argv[5]; |
| 16289 | | - |
| 16290 | | - retval = Jim_SetVariable(interp, argv[1], argv[2]); |
| 17517 | + retval = Jim_GetWideExpr(interp, argv[2], &i); |
| 17518 | + if (argc > 4 && retval == JIM_OK) { |
| 17519 | + retval = Jim_GetWideExpr(interp, argv[3], &limit); |
| 17520 | + } |
| 17521 | + if (argc > 5 && retval == JIM_OK) { |
| 17522 | + Jim_GetWideExpr(interp, argv[4], &incr); |
| 17523 | + } |
| 17524 | + if (retval != JIM_OK) { |
| 17525 | + return retval; |
| 17526 | + } |
| 17527 | + if (argc == 4) { |
| 17528 | + limit = i; |
| 17529 | + i = 0; |
| 17530 | + } |
| 17531 | + bodyObjPtr = argv[argc - 1]; |
| 17532 | + |
| 17533 | + retval = Jim_SetVariable(interp, argv[1], Jim_NewIntObj(interp, i)); |
| 16291 | 17534 | |
| 16292 | 17535 | while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) { |
| 16293 | 17536 | retval = Jim_EvalObj(interp, bodyObjPtr); |
| 17537 | + if (JimCheckLoopRetcode(interp, retval)) { |
| 17538 | + return retval; |
| 17539 | + } |
| 16294 | 17540 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16295 | 17541 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); |
| 16296 | 17542 | |
| 16297 | 17543 | retval = JIM_OK; |
| 16298 | 17544 | |
| | @@ -16429,11 +17675,15 @@ |
| 16429 | 17675 | if (result != JIM_OK) { |
| 16430 | 17676 | goto err; |
| 16431 | 17677 | } |
| 16432 | 17678 | } |
| 16433 | 17679 | } |
| 16434 | | - switch (result = Jim_EvalObj(interp, script)) { |
| 17680 | + result = Jim_EvalObj(interp, script); |
| 17681 | + if (JimCheckLoopRetcode(interp, result)) { |
| 17682 | + goto err; |
| 17683 | + } |
| 17684 | + switch (result) { |
| 16435 | 17685 | case JIM_OK: |
| 16436 | 17686 | if (doMap) { |
| 16437 | 17687 | Jim_ListAppendElement(interp, resultObj, interp->result); |
| 16438 | 17688 | } |
| 16439 | 17689 | break; |
| | @@ -16550,23 +17800,25 @@ |
| 16550 | 17800 | Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody"); |
| 16551 | 17801 | return JIM_ERR; |
| 16552 | 17802 | } |
| 16553 | 17803 | |
| 16554 | 17804 | |
| 16555 | | - |
| 16556 | 17805 | int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, |
| 16557 | | - Jim_Obj *stringObj, int nocase) |
| 17806 | + Jim_Obj *stringObj, int flags) |
| 16558 | 17807 | { |
| 16559 | | - Jim_Obj *parms[4]; |
| 17808 | + Jim_Obj *parms[5]; |
| 16560 | 17809 | int argc = 0; |
| 16561 | 17810 | long eq; |
| 16562 | 17811 | int rc; |
| 16563 | 17812 | |
| 16564 | 17813 | parms[argc++] = commandObj; |
| 16565 | | - if (nocase) { |
| 17814 | + if (flags & JIM_NOCASE) { |
| 16566 | 17815 | parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); |
| 16567 | 17816 | } |
| 17817 | + if (flags & JIM_OPT_END) { |
| 17818 | + parms[argc++] = Jim_NewStringObj(interp, "--", -1); |
| 17819 | + } |
| 16568 | 17820 | parms[argc++] = patternObj; |
| 16569 | 17821 | parms[argc++] = stringObj; |
| 16570 | 17822 | |
| 16571 | 17823 | rc = Jim_EvalObjVector(interp, argc, parms); |
| 16572 | 17824 | |
| | @@ -16580,10 +17832,11 @@ |
| 16580 | 17832 | |
| 16581 | 17833 | static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16582 | 17834 | { |
| 16583 | 17835 | enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; |
| 16584 | 17836 | int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; |
| 17837 | + int match_flags = 0; |
| 16585 | 17838 | Jim_Obj *command = NULL, *scriptObj = NULL, *strObj; |
| 16586 | 17839 | Jim_Obj **caseList; |
| 16587 | 17840 | |
| 16588 | 17841 | if (argc < 3) { |
| 16589 | 17842 | wrongnumargs: |
| | @@ -16602,12 +17855,14 @@ |
| 16602 | 17855 | } |
| 16603 | 17856 | else if (strncmp(option, "-exact", 2) == 0) |
| 16604 | 17857 | matchOpt = SWITCH_EXACT; |
| 16605 | 17858 | else if (strncmp(option, "-glob", 2) == 0) |
| 16606 | 17859 | matchOpt = SWITCH_GLOB; |
| 16607 | | - else if (strncmp(option, "-regexp", 2) == 0) |
| 17860 | + else if (strncmp(option, "-regexp", 2) == 0) { |
| 16608 | 17861 | matchOpt = SWITCH_RE; |
| 17862 | + match_flags |= JIM_OPT_END; |
| 17863 | + } |
| 16609 | 17864 | else if (strncmp(option, "-command", 2) == 0) { |
| 16610 | 17865 | matchOpt = SWITCH_CMD; |
| 16611 | 17866 | if ((argc - opt) < 2) |
| 16612 | 17867 | goto wrongnumargs; |
| 16613 | 17868 | command = argv[++opt]; |
| | @@ -16646,11 +17901,11 @@ |
| 16646 | 17901 | break; |
| 16647 | 17902 | case SWITCH_RE: |
| 16648 | 17903 | command = Jim_NewStringObj(interp, "regexp", -1); |
| 16649 | 17904 | |
| 16650 | 17905 | case SWITCH_CMD:{ |
| 16651 | | - int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); |
| 17906 | + int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, match_flags); |
| 16652 | 17907 | |
| 16653 | 17908 | if (argc - opt == 1) { |
| 16654 | 17909 | JimListGetElements(interp, argv[opt], &patCount, &caseList); |
| 16655 | 17910 | } |
| 16656 | 17911 | |
| | @@ -16691,37 +17946,26 @@ |
| 16691 | 17946 | } |
| 16692 | 17947 | |
| 16693 | 17948 | |
| 16694 | 17949 | static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16695 | 17950 | { |
| 16696 | | - Jim_Obj *objPtr, *listObjPtr; |
| 16697 | | - int i; |
| 16698 | | - int idx; |
| 17951 | + Jim_Obj *objPtr; |
| 17952 | + int ret; |
| 16699 | 17953 | |
| 16700 | 17954 | if (argc < 2) { |
| 16701 | 17955 | Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); |
| 16702 | 17956 | return JIM_ERR; |
| 16703 | 17957 | } |
| 16704 | | - objPtr = argv[1]; |
| 16705 | | - Jim_IncrRefCount(objPtr); |
| 16706 | | - for (i = 2; i < argc; i++) { |
| 16707 | | - listObjPtr = objPtr; |
| 16708 | | - if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) { |
| 16709 | | - Jim_DecrRefCount(interp, listObjPtr); |
| 16710 | | - return JIM_ERR; |
| 16711 | | - } |
| 16712 | | - if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) { |
| 16713 | | - Jim_DecrRefCount(interp, listObjPtr); |
| 16714 | | - Jim_SetEmptyResult(interp); |
| 16715 | | - return JIM_OK; |
| 16716 | | - } |
| 16717 | | - Jim_IncrRefCount(objPtr); |
| 16718 | | - Jim_DecrRefCount(interp, listObjPtr); |
| 16719 | | - } |
| 16720 | | - Jim_SetResult(interp, objPtr); |
| 16721 | | - Jim_DecrRefCount(interp, objPtr); |
| 16722 | | - return JIM_OK; |
| 17958 | + ret = Jim_ListIndices(interp, argv[1], argv + 2, argc - 2, &objPtr, JIM_NONE); |
| 17959 | + if (ret < 0) { |
| 17960 | + ret = JIM_OK; |
| 17961 | + Jim_SetEmptyResult(interp); |
| 17962 | + } |
| 17963 | + else if (ret == JIM_OK) { |
| 17964 | + Jim_SetResult(interp, objPtr); |
| 17965 | + } |
| 17966 | + return ret; |
| 16723 | 17967 | } |
| 16724 | 17968 | |
| 16725 | 17969 | |
| 16726 | 17970 | static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16727 | 17971 | { |
| | @@ -16736,31 +17980,33 @@ |
| 16736 | 17980 | |
| 16737 | 17981 | static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16738 | 17982 | { |
| 16739 | 17983 | static const char * const options[] = { |
| 16740 | 17984 | "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command", |
| 16741 | | - NULL |
| 17985 | + "-stride", "-index", NULL |
| 16742 | 17986 | }; |
| 16743 | 17987 | enum |
| 16744 | 17988 | { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE, |
| 16745 | | - OPT_COMMAND }; |
| 17989 | + OPT_COMMAND, OPT_STRIDE, OPT_INDEX }; |
| 16746 | 17990 | int i; |
| 16747 | 17991 | int opt_bool = 0; |
| 16748 | 17992 | int opt_not = 0; |
| 16749 | | - int opt_nocase = 0; |
| 16750 | 17993 | int opt_all = 0; |
| 16751 | 17994 | int opt_inline = 0; |
| 16752 | 17995 | int opt_match = OPT_EXACT; |
| 16753 | 17996 | int listlen; |
| 16754 | 17997 | int rc = JIM_OK; |
| 16755 | 17998 | Jim_Obj *listObjPtr = NULL; |
| 16756 | 17999 | Jim_Obj *commandObj = NULL; |
| 18000 | + Jim_Obj *indexObj = NULL; |
| 18001 | + int match_flags = 0; |
| 18002 | + long stride = 1; |
| 16757 | 18003 | |
| 16758 | 18004 | if (argc < 3) { |
| 16759 | 18005 | wrongargs: |
| 16760 | 18006 | Jim_WrongNumArgs(interp, 1, argv, |
| 16761 | | - "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value"); |
| 18007 | + "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? ?-stride len? ?-index val? list value"); |
| 16762 | 18008 | return JIM_ERR; |
| 16763 | 18009 | } |
| 16764 | 18010 | |
| 16765 | 18011 | for (i = 1; i < argc - 2; i++) { |
| 16766 | 18012 | int option; |
| | @@ -16775,34 +18021,65 @@ |
| 16775 | 18021 | break; |
| 16776 | 18022 | case OPT_NOT: |
| 16777 | 18023 | opt_not = 1; |
| 16778 | 18024 | break; |
| 16779 | 18025 | case OPT_NOCASE: |
| 16780 | | - opt_nocase = 1; |
| 18026 | + match_flags |= JIM_NOCASE; |
| 16781 | 18027 | break; |
| 16782 | 18028 | case OPT_INLINE: |
| 16783 | 18029 | opt_inline = 1; |
| 16784 | 18030 | opt_bool = 0; |
| 16785 | 18031 | break; |
| 16786 | 18032 | case OPT_ALL: |
| 16787 | 18033 | opt_all = 1; |
| 16788 | 18034 | break; |
| 18035 | + case OPT_REGEXP: |
| 18036 | + opt_match = option; |
| 18037 | + match_flags |= JIM_OPT_END; |
| 18038 | + break; |
| 16789 | 18039 | case OPT_COMMAND: |
| 16790 | 18040 | if (i >= argc - 2) { |
| 16791 | 18041 | goto wrongargs; |
| 16792 | 18042 | } |
| 16793 | 18043 | commandObj = argv[++i]; |
| 16794 | 18044 | |
| 16795 | 18045 | case OPT_EXACT: |
| 16796 | 18046 | case OPT_GLOB: |
| 16797 | | - case OPT_REGEXP: |
| 16798 | 18047 | opt_match = option; |
| 16799 | 18048 | break; |
| 18049 | + case OPT_INDEX: |
| 18050 | + if (i >= argc - 2) { |
| 18051 | + goto wrongargs; |
| 18052 | + } |
| 18053 | + indexObj = argv[++i]; |
| 18054 | + break; |
| 18055 | + case OPT_STRIDE: |
| 18056 | + if (i >= argc - 2) { |
| 18057 | + goto wrongargs; |
| 18058 | + } |
| 18059 | + if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) { |
| 18060 | + return JIM_ERR; |
| 18061 | + } |
| 18062 | + if (stride < 1) { |
| 18063 | + Jim_SetResultString(interp, "stride length must be at least 1", -1); |
| 18064 | + return JIM_ERR; |
| 18065 | + } |
| 18066 | + break; |
| 16800 | 18067 | } |
| 16801 | 18068 | } |
| 16802 | 18069 | |
| 18070 | + argc -= i; |
| 18071 | + if (argc < 2) { |
| 18072 | + goto wrongargs; |
| 18073 | + } |
| 16803 | 18074 | argv += i; |
| 18075 | + |
| 18076 | + listlen = Jim_ListLength(interp, argv[0]); |
| 18077 | + if (listlen % stride) { |
| 18078 | + Jim_SetResultString(interp, "list size must be a multiple of the stride length", -1); |
| 18079 | + return JIM_ERR; |
| 18080 | + } |
| 16804 | 18081 | |
| 16805 | 18082 | if (opt_all) { |
| 16806 | 18083 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 16807 | 18084 | } |
| 16808 | 18085 | if (opt_match == OPT_REGEXP) { |
| | @@ -16810,68 +18087,104 @@ |
| 16810 | 18087 | } |
| 16811 | 18088 | if (commandObj) { |
| 16812 | 18089 | Jim_IncrRefCount(commandObj); |
| 16813 | 18090 | } |
| 16814 | 18091 | |
| 16815 | | - listlen = Jim_ListLength(interp, argv[0]); |
| 16816 | | - for (i = 0; i < listlen; i++) { |
| 18092 | + for (i = 0; i < listlen; i += stride) { |
| 16817 | 18093 | int eq = 0; |
| 16818 | | - Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); |
| 18094 | + Jim_Obj *searchListObj; |
| 18095 | + Jim_Obj *objPtr; |
| 18096 | + int offset; |
| 18097 | + |
| 18098 | + if (indexObj) { |
| 18099 | + int indexlen = Jim_ListLength(interp, indexObj); |
| 18100 | + if (stride == 1) { |
| 18101 | + searchListObj = Jim_ListGetIndex(interp, argv[0], i); |
| 18102 | + } |
| 18103 | + else { |
| 18104 | + searchListObj = Jim_NewListObj(interp, argv[0]->internalRep.listValue.ele + i, stride); |
| 18105 | + } |
| 18106 | + Jim_IncrRefCount(searchListObj); |
| 18107 | + rc = Jim_ListIndices(interp, searchListObj, indexObj->internalRep.listValue.ele, indexlen, &objPtr, JIM_ERRMSG); |
| 18108 | + if (rc != JIM_OK) { |
| 18109 | + Jim_DecrRefCount(interp, searchListObj); |
| 18110 | + rc = JIM_ERR; |
| 18111 | + goto done; |
| 18112 | + } |
| 18113 | + |
| 18114 | + offset = 0; |
| 18115 | + } |
| 18116 | + else { |
| 18117 | + |
| 18118 | + searchListObj = argv[0]; |
| 18119 | + offset = i; |
| 18120 | + objPtr = Jim_ListGetIndex(interp, searchListObj, i); |
| 18121 | + Jim_IncrRefCount(searchListObj); |
| 18122 | + } |
| 16819 | 18123 | |
| 16820 | 18124 | switch (opt_match) { |
| 16821 | 18125 | case OPT_EXACT: |
| 16822 | | - eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; |
| 18126 | + eq = Jim_StringCompareObj(interp, argv[1], objPtr, match_flags) == 0; |
| 16823 | 18127 | break; |
| 16824 | 18128 | |
| 16825 | 18129 | case OPT_GLOB: |
| 16826 | | - eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); |
| 18130 | + eq = Jim_StringMatchObj(interp, argv[1], objPtr, match_flags); |
| 16827 | 18131 | break; |
| 16828 | 18132 | |
| 16829 | 18133 | case OPT_REGEXP: |
| 16830 | 18134 | case OPT_COMMAND: |
| 16831 | | - eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); |
| 18135 | + eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, match_flags); |
| 16832 | 18136 | if (eq < 0) { |
| 16833 | | - if (listObjPtr) { |
| 16834 | | - Jim_FreeNewObj(interp, listObjPtr); |
| 16835 | | - } |
| 18137 | + Jim_DecrRefCount(interp, searchListObj); |
| 16836 | 18138 | rc = JIM_ERR; |
| 16837 | 18139 | goto done; |
| 16838 | 18140 | } |
| 16839 | 18141 | break; |
| 16840 | 18142 | } |
| 16841 | 18143 | |
| 16842 | 18144 | |
| 16843 | | - if (!eq && opt_bool && opt_not && !opt_all) { |
| 16844 | | - continue; |
| 16845 | | - } |
| 16846 | | - |
| 16847 | 18145 | if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { |
| 16848 | | - |
| 16849 | 18146 | Jim_Obj *resultObj; |
| 16850 | 18147 | |
| 16851 | 18148 | if (opt_bool) { |
| 16852 | 18149 | resultObj = Jim_NewIntObj(interp, eq ^ opt_not); |
| 16853 | 18150 | } |
| 16854 | 18151 | else if (!opt_inline) { |
| 16855 | 18152 | resultObj = Jim_NewIntObj(interp, i); |
| 16856 | 18153 | } |
| 16857 | | - else { |
| 18154 | + else if (stride == 1) { |
| 16858 | 18155 | resultObj = objPtr; |
| 16859 | 18156 | } |
| 18157 | + else if (opt_all) { |
| 18158 | + |
| 18159 | + ListInsertElements(listObjPtr, -1, stride, |
| 18160 | + searchListObj->internalRep.listValue.ele + offset); |
| 18161 | + |
| 18162 | + resultObj = NULL; |
| 18163 | + } |
| 18164 | + else { |
| 18165 | + resultObj = Jim_NewListObj(interp, searchListObj->internalRep.listValue.ele + offset, stride); |
| 18166 | + } |
| 16860 | 18167 | |
| 16861 | 18168 | if (opt_all) { |
| 16862 | | - Jim_ListAppendElement(interp, listObjPtr, resultObj); |
| 18169 | + |
| 18170 | + if (stride == 1) { |
| 18171 | + Jim_ListAppendElement(interp, listObjPtr, resultObj); |
| 18172 | + } |
| 16863 | 18173 | } |
| 16864 | 18174 | else { |
| 16865 | 18175 | Jim_SetResult(interp, resultObj); |
| 18176 | + Jim_DecrRefCount(interp, searchListObj); |
| 16866 | 18177 | goto done; |
| 16867 | 18178 | } |
| 16868 | 18179 | } |
| 18180 | + Jim_DecrRefCount(interp, searchListObj); |
| 16869 | 18181 | } |
| 16870 | 18182 | |
| 16871 | 18183 | if (opt_all) { |
| 16872 | 18184 | Jim_SetResult(interp, listObjPtr); |
| 18185 | + listObjPtr = NULL; |
| 16873 | 18186 | } |
| 16874 | 18187 | else { |
| 16875 | 18188 | |
| 16876 | 18189 | if (opt_bool) { |
| 16877 | 18190 | Jim_SetResultBool(interp, opt_not); |
| | @@ -16880,10 +18193,13 @@ |
| 16880 | 18193 | Jim_SetResultInt(interp, -1); |
| 16881 | 18194 | } |
| 16882 | 18195 | } |
| 16883 | 18196 | |
| 16884 | 18197 | done: |
| 18198 | + if (listObjPtr) { |
| 18199 | + Jim_FreeNewObj(interp, listObjPtr); |
| 18200 | + } |
| 16885 | 18201 | if (commandObj) { |
| 16886 | 18202 | Jim_DecrRefCount(interp, commandObj); |
| 16887 | 18203 | } |
| 16888 | 18204 | return rc; |
| 16889 | 18205 | } |
| | @@ -16993,11 +18309,11 @@ |
| 16993 | 18309 | |
| 16994 | 18310 | |
| 16995 | 18311 | static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16996 | 18312 | { |
| 16997 | 18313 | if (argc < 3) { |
| 16998 | | - Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 18314 | + Jim_WrongNumArgs(interp, 1, argv, "listVar ?index ...? value"); |
| 16999 | 18315 | return JIM_ERR; |
| 17000 | 18316 | } |
| 17001 | 18317 | else if (argc == 3) { |
| 17002 | 18318 | |
| 17003 | 18319 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| | @@ -17010,29 +18326,34 @@ |
| 17010 | 18326 | |
| 17011 | 18327 | |
| 17012 | 18328 | static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) |
| 17013 | 18329 | { |
| 17014 | 18330 | static const char * const options[] = { |
| 17015 | | - "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL |
| 18331 | + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", |
| 18332 | + "-stride", NULL |
| 17016 | 18333 | }; |
| 17017 | | - enum |
| 17018 | | - { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 18334 | + enum { |
| 18335 | + OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE, |
| 18336 | + OPT_STRIDE |
| 18337 | + }; |
| 17019 | 18338 | Jim_Obj *resObj; |
| 17020 | 18339 | int i; |
| 17021 | 18340 | int retCode; |
| 17022 | 18341 | int shared; |
| 18342 | + long stride = 1; |
| 17023 | 18343 | |
| 17024 | 18344 | struct lsort_info info; |
| 17025 | 18345 | |
| 17026 | 18346 | if (argc < 2) { |
| 18347 | +wrongargs: |
| 17027 | 18348 | Jim_WrongNumArgs(interp, 1, argv, "?options? list"); |
| 17028 | 18349 | return JIM_ERR; |
| 17029 | 18350 | } |
| 17030 | 18351 | |
| 17031 | 18352 | info.type = JIM_LSORT_ASCII; |
| 17032 | 18353 | info.order = 1; |
| 17033 | | - info.indexed = 0; |
| 18354 | + info.indexc = 0; |
| 17034 | 18355 | info.unique = 0; |
| 17035 | 18356 | info.command = NULL; |
| 17036 | 18357 | info.interp = interp; |
| 17037 | 18358 | |
| 17038 | 18359 | for (i = 1; i < (argc - 1); i++) { |
| | @@ -17069,33 +18390,77 @@ |
| 17069 | 18390 | return JIM_ERR; |
| 17070 | 18391 | } |
| 17071 | 18392 | info.type = JIM_LSORT_COMMAND; |
| 17072 | 18393 | info.command = argv[i + 1]; |
| 17073 | 18394 | i++; |
| 18395 | + break; |
| 18396 | + case OPT_STRIDE: |
| 18397 | + if (i >= argc - 2) { |
| 18398 | + goto wrongargs; |
| 18399 | + } |
| 18400 | + if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) { |
| 18401 | + return JIM_ERR; |
| 18402 | + } |
| 18403 | + if (stride < 2) { |
| 18404 | + Jim_SetResultString(interp, "stride length must be at least 2", -1); |
| 18405 | + return JIM_ERR; |
| 18406 | + } |
| 17074 | 18407 | break; |
| 17075 | 18408 | case OPT_INDEX: |
| 17076 | 18409 | if (i >= (argc - 2)) { |
| 18410 | +badindex: |
| 17077 | 18411 | Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1); |
| 17078 | 18412 | return JIM_ERR; |
| 17079 | 18413 | } |
| 17080 | | - if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) { |
| 17081 | | - return JIM_ERR; |
| 18414 | + JimListGetElements(interp, argv[i + 1], &info.indexc, &info.indexv); |
| 18415 | + if (info.indexc == 0) { |
| 18416 | + goto badindex; |
| 17082 | 18417 | } |
| 17083 | | - info.indexed = 1; |
| 17084 | 18418 | i++; |
| 17085 | 18419 | break; |
| 17086 | 18420 | } |
| 17087 | 18421 | } |
| 17088 | 18422 | resObj = argv[argc - 1]; |
| 17089 | | - if ((shared = Jim_IsShared(resObj))) |
| 17090 | | - resObj = Jim_DuplicateObj(interp, resObj); |
| 17091 | | - retCode = ListSortElements(interp, resObj, &info); |
| 17092 | | - if (retCode == JIM_OK) { |
| 17093 | | - Jim_SetResult(interp, resObj); |
| 17094 | | - } |
| 17095 | | - else if (shared) { |
| 17096 | | - Jim_FreeNewObj(interp, resObj); |
| 18423 | + if (stride > 1) { |
| 18424 | + Jim_Obj *tmpListObj; |
| 18425 | + Jim_Obj **elements; |
| 18426 | + int listlen; |
| 18427 | + int i; |
| 18428 | + |
| 18429 | + JimListGetElements(interp, resObj, &listlen, &elements); |
| 18430 | + if (listlen % stride) { |
| 18431 | + Jim_SetResultString(interp, "list size must be a multiple of the stride length", -1); |
| 18432 | + return JIM_ERR; |
| 18433 | + } |
| 18434 | + |
| 18435 | + tmpListObj = Jim_NewListObj(interp, NULL, 0); |
| 18436 | + Jim_IncrRefCount(tmpListObj); |
| 18437 | + for (i = 0; i < listlen; i += stride) { |
| 18438 | + Jim_ListAppendElement(interp, tmpListObj, Jim_NewListObj(interp, elements + i, stride)); |
| 18439 | + } |
| 18440 | + retCode = ListSortElements(interp, tmpListObj, &info); |
| 18441 | + if (retCode == JIM_OK) { |
| 18442 | + resObj = Jim_NewListObj(interp, NULL, 0); |
| 18443 | + |
| 18444 | + for (i = 0; i < listlen; i += stride) { |
| 18445 | + Jim_ListAppendList(interp, resObj, Jim_ListGetIndex(interp, tmpListObj, i / stride)); |
| 18446 | + } |
| 18447 | + Jim_SetResult(interp, resObj); |
| 18448 | + } |
| 18449 | + Jim_DecrRefCount(interp, tmpListObj); |
| 18450 | + } |
| 18451 | + else { |
| 18452 | + if ((shared = Jim_IsShared(resObj))) { |
| 18453 | + resObj = Jim_DuplicateObj(interp, resObj); |
| 18454 | + } |
| 18455 | + retCode = ListSortElements(interp, resObj, &info); |
| 18456 | + if (retCode == JIM_OK) { |
| 18457 | + Jim_SetResult(interp, resObj); |
| 18458 | + } |
| 18459 | + else if (shared) { |
| 18460 | + Jim_FreeNewObj(interp, resObj); |
| 18461 | + } |
| 17097 | 18462 | } |
| 17098 | 18463 | return retCode; |
| 17099 | 18464 | } |
| 17100 | 18465 | |
| 17101 | 18466 | |
| | @@ -17139,17 +18504,10 @@ |
| 17139 | 18504 | return JIM_OK; |
| 17140 | 18505 | } |
| 17141 | 18506 | |
| 17142 | 18507 | |
| 17143 | 18508 | |
| 17144 | | -static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17145 | | -{ |
| 17146 | | -#if !defined(JIM_DEBUG_COMMAND) |
| 17147 | | - Jim_SetResultString(interp, "unsupported", -1); |
| 17148 | | - return JIM_ERR; |
| 17149 | | -#endif |
| 17150 | | -} |
| 17151 | 18509 | |
| 17152 | 18510 | |
| 17153 | 18511 | static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17154 | 18512 | { |
| 17155 | 18513 | int rc; |
| | @@ -17164,14 +18522,10 @@ |
| 17164 | 18522 | } |
| 17165 | 18523 | else { |
| 17166 | 18524 | rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 17167 | 18525 | } |
| 17168 | 18526 | |
| 17169 | | - if (rc == JIM_ERR) { |
| 17170 | | - |
| 17171 | | - interp->addStackTrace++; |
| 17172 | | - } |
| 17173 | 18527 | return rc; |
| 17174 | 18528 | } |
| 17175 | 18529 | |
| 17176 | 18530 | |
| 17177 | 18531 | static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -17224,10 +18578,16 @@ |
| 17224 | 18578 | int retcode; |
| 17225 | 18579 | |
| 17226 | 18580 | if (argc == 2) { |
| 17227 | 18581 | retcode = Jim_EvalExpression(interp, argv[1]); |
| 17228 | 18582 | } |
| 18583 | +#ifndef JIM_COMPAT |
| 18584 | + else { |
| 18585 | + Jim_WrongNumArgs(interp, 1, argv, "expression"); |
| 18586 | + retcode = JIM_ERR; |
| 18587 | + } |
| 18588 | +#else |
| 17229 | 18589 | else if (argc > 2) { |
| 17230 | 18590 | Jim_Obj *objPtr; |
| 17231 | 18591 | |
| 17232 | 18592 | objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 17233 | 18593 | Jim_IncrRefCount(objPtr); |
| | @@ -17236,33 +18596,72 @@ |
| 17236 | 18596 | } |
| 17237 | 18597 | else { |
| 17238 | 18598 | Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); |
| 17239 | 18599 | return JIM_ERR; |
| 17240 | 18600 | } |
| 17241 | | - if (retcode != JIM_OK) |
| 17242 | | - return retcode; |
| 17243 | | - return JIM_OK; |
| 18601 | +#endif |
| 18602 | + return retcode; |
| 18603 | +} |
| 18604 | + |
| 18605 | +static int JimBreakContinueHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int retcode) |
| 18606 | +{ |
| 18607 | + if (argc != 1 && argc != 2) { |
| 18608 | + Jim_WrongNumArgs(interp, 1, argv, "?level?"); |
| 18609 | + return JIM_ERR; |
| 18610 | + } |
| 18611 | + if (argc == 2) { |
| 18612 | + long level; |
| 18613 | + int ret = Jim_GetLong(interp, argv[1], &level); |
| 18614 | + if (ret != JIM_OK) { |
| 18615 | + return ret; |
| 18616 | + } |
| 18617 | + interp->returnLevel = level; |
| 18618 | + } |
| 18619 | + return retcode; |
| 17244 | 18620 | } |
| 17245 | 18621 | |
| 17246 | 18622 | |
| 17247 | 18623 | static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17248 | 18624 | { |
| 17249 | | - if (argc != 1) { |
| 17250 | | - Jim_WrongNumArgs(interp, 1, argv, ""); |
| 17251 | | - return JIM_ERR; |
| 17252 | | - } |
| 17253 | | - return JIM_BREAK; |
| 18625 | + return JimBreakContinueHelper(interp, argc, argv, JIM_BREAK); |
| 17254 | 18626 | } |
| 17255 | 18627 | |
| 17256 | 18628 | |
| 17257 | 18629 | static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17258 | 18630 | { |
| 17259 | | - if (argc != 1) { |
| 17260 | | - Jim_WrongNumArgs(interp, 1, argv, ""); |
| 17261 | | - return JIM_ERR; |
| 18631 | + return JimBreakContinueHelper(interp, argc, argv, JIM_CONTINUE); |
| 18632 | +} |
| 18633 | + |
| 18634 | + |
| 18635 | +static int Jim_StacktraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18636 | +{ |
| 18637 | + Jim_Obj *listObj; |
| 18638 | + int i; |
| 18639 | + jim_wide skip = 0; |
| 18640 | + jim_wide last = 0; |
| 18641 | + |
| 18642 | + if (argc > 1) { |
| 18643 | + if (Jim_GetWideExpr(interp, argv[1], &skip) != JIM_OK) { |
| 18644 | + return JIM_ERR; |
| 18645 | + } |
| 17262 | 18646 | } |
| 17263 | | - return JIM_CONTINUE; |
| 18647 | + if (argc > 2) { |
| 18648 | + if (Jim_GetWideExpr(interp, argv[2], &last) != JIM_OK) { |
| 18649 | + return JIM_ERR; |
| 18650 | + } |
| 18651 | + } |
| 18652 | + |
| 18653 | + listObj = Jim_NewListObj(interp, NULL, 0); |
| 18654 | + for (i = skip; i <= interp->procLevel; i++) { |
| 18655 | + Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i); |
| 18656 | + if (frame->procLevel < last) { |
| 18657 | + break; |
| 18658 | + } |
| 18659 | + JimAddStackFrame(interp, frame, listObj); |
| 18660 | + } |
| 18661 | + Jim_SetResult(interp, listObj); |
| 18662 | + return JIM_OK; |
| 17264 | 18663 | } |
| 17265 | 18664 | |
| 17266 | 18665 | |
| 17267 | 18666 | static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17268 | 18667 | { |
| | @@ -17312,11 +18711,11 @@ |
| 17312 | 18711 | interp->returnLevel = level; |
| 17313 | 18712 | |
| 17314 | 18713 | if (i == argc - 1) { |
| 17315 | 18714 | Jim_SetResult(interp, argv[i]); |
| 17316 | 18715 | } |
| 17317 | | - return JIM_RETURN; |
| 18716 | + return level == 0 ? returnCode : JIM_RETURN; |
| 17318 | 18717 | } |
| 17319 | 18718 | |
| 17320 | 18719 | |
| 17321 | 18720 | static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17322 | 18721 | { |
| | @@ -17370,28 +18769,21 @@ |
| 17370 | 18769 | } |
| 17371 | 18770 | |
| 17372 | 18771 | static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17373 | 18772 | { |
| 17374 | 18773 | Jim_Obj *prefixListObj; |
| 17375 | | - const char *newname; |
| 17376 | 18774 | |
| 17377 | 18775 | if (argc < 3) { |
| 17378 | 18776 | Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?"); |
| 17379 | 18777 | return JIM_ERR; |
| 17380 | 18778 | } |
| 17381 | 18779 | |
| 17382 | 18780 | prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2); |
| 17383 | 18781 | Jim_IncrRefCount(prefixListObj); |
| 17384 | | - newname = Jim_String(argv[1]); |
| 17385 | | - if (newname[0] == ':' && newname[1] == ':') { |
| 17386 | | - while (*++newname == ':') { |
| 17387 | | - } |
| 17388 | | - } |
| 17389 | | - |
| 17390 | 18782 | Jim_SetResult(interp, argv[1]); |
| 17391 | 18783 | |
| 17392 | | - return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete); |
| 18784 | + return Jim_CreateCommandObj(interp, argv[1], JimAliasCmd, prefixListObj, JimAliasCmdDelete); |
| 17393 | 18785 | } |
| 17394 | 18786 | |
| 17395 | 18787 | |
| 17396 | 18788 | static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17397 | 18789 | { |
| | @@ -17400,40 +18792,54 @@ |
| 17400 | 18792 | if (argc != 4 && argc != 5) { |
| 17401 | 18793 | Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body"); |
| 17402 | 18794 | return JIM_ERR; |
| 17403 | 18795 | } |
| 17404 | 18796 | |
| 17405 | | - if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) { |
| 17406 | | - return JIM_ERR; |
| 17407 | | - } |
| 17408 | | - |
| 17409 | 18797 | if (argc == 4) { |
| 17410 | 18798 | cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL); |
| 17411 | 18799 | } |
| 17412 | 18800 | else { |
| 17413 | 18801 | cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); |
| 17414 | 18802 | } |
| 17415 | 18803 | |
| 17416 | 18804 | if (cmd) { |
| 17417 | 18805 | |
| 17418 | | - Jim_Obj *qualifiedCmdNameObj; |
| 17419 | | - const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); |
| 17420 | | - |
| 17421 | | - JimCreateCommand(interp, cmdname, cmd); |
| 18806 | + Jim_Obj *nameObjPtr = JimQualifyName(interp, argv[1]); |
| 18807 | + JimCreateCommand(interp, nameObjPtr, cmd); |
| 17422 | 18808 | |
| 17423 | 18809 | |
| 17424 | | - JimUpdateProcNamespace(interp, cmd, cmdname); |
| 17425 | | - |
| 17426 | | - JimFreeQualifiedName(interp, qualifiedCmdNameObj); |
| 18810 | + JimUpdateProcNamespace(interp, cmd, nameObjPtr); |
| 18811 | + Jim_DecrRefCount(interp, nameObjPtr); |
| 17427 | 18812 | |
| 17428 | 18813 | |
| 17429 | 18814 | Jim_SetResult(interp, argv[1]); |
| 17430 | 18815 | return JIM_OK; |
| 17431 | 18816 | } |
| 17432 | 18817 | return JIM_ERR; |
| 17433 | 18818 | } |
| 17434 | 18819 | |
| 18820 | + |
| 18821 | +static int Jim_XtraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18822 | +{ |
| 18823 | + if (argc != 2) { |
| 18824 | + Jim_WrongNumArgs(interp, 1, argv, "callback"); |
| 18825 | + return JIM_ERR; |
| 18826 | + } |
| 18827 | + |
| 18828 | + if (interp->traceCmdObj) { |
| 18829 | + Jim_DecrRefCount(interp, interp->traceCmdObj); |
| 18830 | + interp->traceCmdObj = NULL; |
| 18831 | + } |
| 18832 | + |
| 18833 | + if (Jim_Length(argv[1])) { |
| 18834 | + |
| 18835 | + interp->traceCmdObj = argv[1]; |
| 18836 | + Jim_IncrRefCount(interp->traceCmdObj); |
| 18837 | + } |
| 18838 | + return JIM_OK; |
| 18839 | +} |
| 18840 | + |
| 17435 | 18841 | |
| 17436 | 18842 | static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17437 | 18843 | { |
| 17438 | 18844 | int retcode; |
| 17439 | 18845 | |
| | @@ -17518,11 +18924,11 @@ |
| 17518 | 18924 | } |
| 17519 | 18925 | |
| 17520 | 18926 | if (len == 3) { |
| 17521 | 18927 | #ifdef jim_ext_namespace |
| 17522 | 18928 | |
| 17523 | | - nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); |
| 18929 | + nsObj = Jim_ListGetIndex(interp, argv[1], 2); |
| 17524 | 18930 | #else |
| 17525 | 18931 | Jim_SetResultString(interp, "namespaces not enabled", -1); |
| 17526 | 18932 | return JIM_ERR; |
| 17527 | 18933 | #endif |
| 17528 | 18934 | } |
| | @@ -17641,11 +19047,11 @@ |
| 17641 | 19047 | k = Jim_String(eachObjPtr); |
| 17642 | 19048 | kl = Jim_Utf8Length(interp, eachObjPtr); |
| 17643 | 19049 | |
| 17644 | 19050 | if (strLen >= kl && kl) { |
| 17645 | 19051 | int rc; |
| 17646 | | - rc = JimStringCompareLen(str, k, kl, nocase); |
| 19052 | + rc = JimStringCompareUtf8(str, kl, k, kl, nocase); |
| 17647 | 19053 | if (rc == 0) { |
| 17648 | 19054 | if (noMatchStart) { |
| 17649 | 19055 | Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); |
| 17650 | 19056 | noMatchStart = NULL; |
| 17651 | 19057 | } |
| | @@ -17674,50 +19080,85 @@ |
| 17674 | 19080 | static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17675 | 19081 | { |
| 17676 | 19082 | int len; |
| 17677 | 19083 | int opt_case = 1; |
| 17678 | 19084 | int option; |
| 17679 | | - static const char * const options[] = { |
| 17680 | | - "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace", |
| 17681 | | - "map", "repeat", "reverse", "index", "first", "last", "cat", |
| 17682 | | - "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL |
| 17683 | | - }; |
| 17684 | | - enum |
| 17685 | | - { |
| 17686 | | - OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE, |
| 17687 | | - OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, OPT_CAT, |
| 17688 | | - OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE |
| 17689 | | - }; |
| 17690 | 19085 | static const char * const nocase_options[] = { |
| 17691 | 19086 | "-nocase", NULL |
| 17692 | 19087 | }; |
| 17693 | 19088 | static const char * const nocase_length_options[] = { |
| 17694 | 19089 | "-nocase", "-length", NULL |
| 17695 | 19090 | }; |
| 17696 | 19091 | |
| 17697 | | - if (argc < 2) { |
| 17698 | | - Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); |
| 19092 | + enum { |
| 19093 | + OPT_BYTELENGTH, |
| 19094 | + OPT_BYTERANGE, |
| 19095 | + OPT_CAT, |
| 19096 | + OPT_COMPARE, |
| 19097 | + OPT_EQUAL, |
| 19098 | + OPT_FIRST, |
| 19099 | + OPT_INDEX, |
| 19100 | + OPT_IS, |
| 19101 | + OPT_LAST, |
| 19102 | + OPT_LENGTH, |
| 19103 | + OPT_MAP, |
| 19104 | + OPT_MATCH, |
| 19105 | + OPT_RANGE, |
| 19106 | + OPT_REPEAT, |
| 19107 | + OPT_REPLACE, |
| 19108 | + OPT_REVERSE, |
| 19109 | + OPT_TOLOWER, |
| 19110 | + OPT_TOTITLE, |
| 19111 | + OPT_TOUPPER, |
| 19112 | + OPT_TRIM, |
| 19113 | + OPT_TRIMLEFT, |
| 19114 | + OPT_TRIMRIGHT, |
| 19115 | + OPT_COUNT |
| 19116 | + }; |
| 19117 | + static const jim_subcmd_type cmds[OPT_COUNT + 1] = { |
| 19118 | + JIM_DEF_SUBCMD("bytelength", "string", 1, 1), |
| 19119 | + JIM_DEF_SUBCMD("byterange", "string first last", 3, 3), |
| 19120 | + JIM_DEF_SUBCMD("cat", "?...?", 0, -1), |
| 19121 | + JIM_DEF_SUBCMD("compare", "?-nocase? ?-length int? string1 string2", 2, 5), |
| 19122 | + JIM_DEF_SUBCMD("equal", "?-nocase? ?-length int? string1 string2", 2, 5), |
| 19123 | + JIM_DEF_SUBCMD("first", "subString string ?index?", 2, 3), |
| 19124 | + JIM_DEF_SUBCMD("index", "string index", 2, 2), |
| 19125 | + JIM_DEF_SUBCMD("is", "class ?-strict? str", 2, 3), |
| 19126 | + JIM_DEF_SUBCMD("last", "subString string ?index?", 2, 3), |
| 19127 | + JIM_DEF_SUBCMD("length","string", 1, 1), |
| 19128 | + JIM_DEF_SUBCMD("map", "?-nocase? mapList string", 2, 3), |
| 19129 | + JIM_DEF_SUBCMD("match", "?-nocase? pattern string", 2, 3), |
| 19130 | + JIM_DEF_SUBCMD("range", "string first last", 3, 3), |
| 19131 | + JIM_DEF_SUBCMD("repeat", "string count", 2, 2), |
| 19132 | + JIM_DEF_SUBCMD("replace", "string first last ?string?", 3, 4), |
| 19133 | + JIM_DEF_SUBCMD("reverse", "string", 1, 1), |
| 19134 | + JIM_DEF_SUBCMD("tolower", "string", 1, 1), |
| 19135 | + JIM_DEF_SUBCMD("totitle", "string", 1, 1), |
| 19136 | + JIM_DEF_SUBCMD("toupper", "string", 1, 1), |
| 19137 | + JIM_DEF_SUBCMD("trim", "string ?trimchars?", 1, 2), |
| 19138 | + JIM_DEF_SUBCMD("trimleft", "string ?trimchars?", 1, 2), |
| 19139 | + JIM_DEF_SUBCMD("trimright", "string ?trimchars?", 1, 2), |
| 19140 | + { } |
| 19141 | + }; |
| 19142 | + const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv); |
| 19143 | + if (!ct) { |
| 17699 | 19144 | return JIM_ERR; |
| 17700 | 19145 | } |
| 17701 | | - if (Jim_GetEnum(interp, argv[1], options, &option, NULL, |
| 17702 | | - JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) |
| 17703 | | - return Jim_CheckShowCommands(interp, argv[1], options); |
| 19146 | + if (ct->function) { |
| 19147 | + |
| 19148 | + return ct->function(interp, argc, argv); |
| 19149 | + } |
| 19150 | + |
| 19151 | + option = ct - cmds; |
| 17704 | 19152 | |
| 17705 | 19153 | switch (option) { |
| 17706 | 19154 | case OPT_LENGTH: |
| 19155 | + Jim_SetResultInt(interp, Jim_Utf8Length(interp, argv[2])); |
| 19156 | + return JIM_OK; |
| 19157 | + |
| 17707 | 19158 | case OPT_BYTELENGTH: |
| 17708 | | - if (argc != 3) { |
| 17709 | | - Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 17710 | | - return JIM_ERR; |
| 17711 | | - } |
| 17712 | | - if (option == OPT_LENGTH) { |
| 17713 | | - len = Jim_Utf8Length(interp, argv[2]); |
| 17714 | | - } |
| 17715 | | - else { |
| 17716 | | - len = Jim_Length(argv[2]); |
| 17717 | | - } |
| 17718 | | - Jim_SetResultInt(interp, len); |
| 19159 | + Jim_SetResultInt(interp, Jim_Length(argv[2])); |
| 17719 | 19160 | return JIM_OK; |
| 17720 | 19161 | |
| 17721 | 19162 | case OPT_CAT:{ |
| 17722 | 19163 | Jim_Obj *objPtr; |
| 17723 | 19164 | if (argc == 3) { |
| | @@ -17747,11 +19188,11 @@ |
| 17747 | 19188 | while (n > 0) { |
| 17748 | 19189 | int subopt; |
| 17749 | 19190 | if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL, |
| 17750 | 19191 | JIM_ENUM_ABBREV) != JIM_OK) { |
| 17751 | 19192 | badcompareargs: |
| 17752 | | - Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); |
| 19193 | + Jim_SubCmdArgError(interp, ct, argv[0]); |
| 17753 | 19194 | return JIM_ERR; |
| 17754 | 19195 | } |
| 17755 | 19196 | if (subopt == 0) { |
| 17756 | 19197 | |
| 17757 | 19198 | opt_case = 0; |
| | @@ -17775,16 +19216,23 @@ |
| 17775 | 19216 | if (opt_length < 0 && option != OPT_COMPARE && opt_case) { |
| 17776 | 19217 | |
| 17777 | 19218 | Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); |
| 17778 | 19219 | } |
| 17779 | 19220 | else { |
| 19221 | + const char *s1 = Jim_String(argv[0]); |
| 19222 | + int l1 = Jim_Utf8Length(interp, argv[0]); |
| 19223 | + const char *s2 = Jim_String(argv[1]); |
| 19224 | + int l2 = Jim_Utf8Length(interp, argv[1]); |
| 17780 | 19225 | if (opt_length >= 0) { |
| 17781 | | - n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); |
| 17782 | | - } |
| 17783 | | - else { |
| 17784 | | - n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case); |
| 19226 | + if (l1 > opt_length) { |
| 19227 | + l1 = opt_length; |
| 19228 | + } |
| 19229 | + if (l2 > opt_length) { |
| 19230 | + l2 = opt_length; |
| 19231 | + } |
| 17785 | 19232 | } |
| 19233 | + n = JimStringCompareUtf8(s1, l1, s2, l2, !opt_case); |
| 17786 | 19234 | Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0); |
| 17787 | 19235 | } |
| 17788 | 19236 | return JIM_OK; |
| 17789 | 19237 | } |
| 17790 | 19238 | |
| | @@ -17822,41 +19270,30 @@ |
| 17822 | 19270 | } |
| 17823 | 19271 | Jim_SetResult(interp, objPtr); |
| 17824 | 19272 | return JIM_OK; |
| 17825 | 19273 | } |
| 17826 | 19274 | |
| 17827 | | - case OPT_RANGE: |
| 19275 | + case OPT_RANGE:{ |
| 19276 | + Jim_Obj *objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); |
| 19277 | + if (objPtr == NULL) { |
| 19278 | + return JIM_ERR; |
| 19279 | + } |
| 19280 | + Jim_SetResult(interp, objPtr); |
| 19281 | + return JIM_OK; |
| 19282 | + } |
| 19283 | + |
| 17828 | 19284 | case OPT_BYTERANGE:{ |
| 17829 | | - Jim_Obj *objPtr; |
| 17830 | | - |
| 17831 | | - if (argc != 5) { |
| 17832 | | - Jim_WrongNumArgs(interp, 2, argv, "string first last"); |
| 17833 | | - return JIM_ERR; |
| 17834 | | - } |
| 17835 | | - if (option == OPT_RANGE) { |
| 17836 | | - objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); |
| 17837 | | - } |
| 17838 | | - else |
| 17839 | | - { |
| 17840 | | - objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); |
| 17841 | | - } |
| 17842 | | - |
| 19285 | + Jim_Obj *objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); |
| 17843 | 19286 | if (objPtr == NULL) { |
| 17844 | 19287 | return JIM_ERR; |
| 17845 | 19288 | } |
| 17846 | 19289 | Jim_SetResult(interp, objPtr); |
| 17847 | 19290 | return JIM_OK; |
| 17848 | 19291 | } |
| 17849 | 19292 | |
| 17850 | 19293 | case OPT_REPLACE:{ |
| 17851 | | - Jim_Obj *objPtr; |
| 17852 | | - |
| 17853 | | - if (argc != 5 && argc != 6) { |
| 17854 | | - Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?"); |
| 17855 | | - return JIM_ERR; |
| 17856 | | - } |
| 17857 | | - objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL); |
| 19294 | + Jim_Obj *objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL); |
| 17858 | 19295 | if (objPtr == NULL) { |
| 17859 | 19296 | return JIM_ERR; |
| 17860 | 19297 | } |
| 17861 | 19298 | Jim_SetResult(interp, objPtr); |
| 17862 | 19299 | return JIM_OK; |
| | @@ -17865,15 +19302,11 @@ |
| 17865 | 19302 | |
| 17866 | 19303 | case OPT_REPEAT:{ |
| 17867 | 19304 | Jim_Obj *objPtr; |
| 17868 | 19305 | jim_wide count; |
| 17869 | 19306 | |
| 17870 | | - if (argc != 4) { |
| 17871 | | - Jim_WrongNumArgs(interp, 2, argv, "string count"); |
| 17872 | | - return JIM_ERR; |
| 17873 | | - } |
| 17874 | | - if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) { |
| 19307 | + if (Jim_GetWideExpr(interp, argv[3], &count) != JIM_OK) { |
| 17875 | 19308 | return JIM_ERR; |
| 17876 | 19309 | } |
| 17877 | 19310 | objPtr = Jim_NewStringObj(interp, "", 0); |
| 17878 | 19311 | if (count > 0) { |
| 17879 | 19312 | while (count--) { |
| | @@ -17887,17 +19320,13 @@ |
| 17887 | 19320 | case OPT_REVERSE:{ |
| 17888 | 19321 | char *buf, *p; |
| 17889 | 19322 | const char *str; |
| 17890 | 19323 | int i; |
| 17891 | 19324 | |
| 17892 | | - if (argc != 3) { |
| 17893 | | - Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 17894 | | - return JIM_ERR; |
| 17895 | | - } |
| 17896 | | - |
| 17897 | 19325 | str = Jim_GetString(argv[2], &len); |
| 17898 | 19326 | buf = Jim_Alloc(len + 1); |
| 19327 | + assert(buf); |
| 17899 | 19328 | p = buf + len; |
| 17900 | 19329 | *p = 0; |
| 17901 | 19330 | for (i = 0; i < len; ) { |
| 17902 | 19331 | int c; |
| 17903 | 19332 | int l = utf8_tounicode(str, &c); |
| | @@ -17912,22 +19341,16 @@ |
| 17912 | 19341 | |
| 17913 | 19342 | case OPT_INDEX:{ |
| 17914 | 19343 | int idx; |
| 17915 | 19344 | const char *str; |
| 17916 | 19345 | |
| 17917 | | - if (argc != 4) { |
| 17918 | | - Jim_WrongNumArgs(interp, 2, argv, "string index"); |
| 17919 | | - return JIM_ERR; |
| 17920 | | - } |
| 17921 | 19346 | if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) { |
| 17922 | 19347 | return JIM_ERR; |
| 17923 | 19348 | } |
| 17924 | 19349 | str = Jim_String(argv[2]); |
| 17925 | 19350 | len = Jim_Utf8Length(interp, argv[2]); |
| 17926 | | - if (idx != INT_MIN && idx != INT_MAX) { |
| 17927 | | - idx = JimRelToAbsIndex(len, idx); |
| 17928 | | - } |
| 19351 | + idx = JimRelToAbsIndex(len, idx); |
| 17929 | 19352 | if (idx < 0 || idx >= len || str == NULL) { |
| 17930 | 19353 | Jim_SetResultString(interp, "", 0); |
| 17931 | 19354 | } |
| 17932 | 19355 | else if (len == Jim_Length(argv[2])) { |
| 17933 | 19356 | |
| | @@ -17944,23 +19367,22 @@ |
| 17944 | 19367 | case OPT_FIRST: |
| 17945 | 19368 | case OPT_LAST:{ |
| 17946 | 19369 | int idx = 0, l1, l2; |
| 17947 | 19370 | const char *s1, *s2; |
| 17948 | 19371 | |
| 17949 | | - if (argc != 4 && argc != 5) { |
| 17950 | | - Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?"); |
| 17951 | | - return JIM_ERR; |
| 17952 | | - } |
| 17953 | 19372 | s1 = Jim_String(argv[2]); |
| 17954 | 19373 | s2 = Jim_String(argv[3]); |
| 17955 | 19374 | l1 = Jim_Utf8Length(interp, argv[2]); |
| 17956 | 19375 | l2 = Jim_Utf8Length(interp, argv[3]); |
| 17957 | 19376 | if (argc == 5) { |
| 17958 | 19377 | if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) { |
| 17959 | 19378 | return JIM_ERR; |
| 17960 | 19379 | } |
| 17961 | 19380 | idx = JimRelToAbsIndex(l2, idx); |
| 19381 | + if (idx < 0) { |
| 19382 | + idx = 0; |
| 19383 | + } |
| 17962 | 19384 | } |
| 17963 | 19385 | else if (option == OPT_LAST) { |
| 17964 | 19386 | idx = l2; |
| 17965 | 19387 | } |
| 17966 | 19388 | if (option == OPT_FIRST) { |
| | @@ -17975,66 +19397,45 @@ |
| 17975 | 19397 | } |
| 17976 | 19398 | return JIM_OK; |
| 17977 | 19399 | } |
| 17978 | 19400 | |
| 17979 | 19401 | case OPT_TRIM: |
| 19402 | + Jim_SetResult(interp, JimStringTrim(interp, argv[2], argc == 4 ? argv[3] : NULL)); |
| 19403 | + return JIM_OK; |
| 17980 | 19404 | case OPT_TRIMLEFT: |
| 19405 | + Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], argc == 4 ? argv[3] : NULL)); |
| 19406 | + return JIM_OK; |
| 17981 | 19407 | case OPT_TRIMRIGHT:{ |
| 17982 | | - Jim_Obj *trimchars; |
| 17983 | | - |
| 17984 | | - if (argc != 3 && argc != 4) { |
| 17985 | | - Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?"); |
| 17986 | | - return JIM_ERR; |
| 17987 | | - } |
| 17988 | | - trimchars = (argc == 4 ? argv[3] : NULL); |
| 17989 | | - if (option == OPT_TRIM) { |
| 17990 | | - Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars)); |
| 17991 | | - } |
| 17992 | | - else if (option == OPT_TRIMLEFT) { |
| 17993 | | - Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars)); |
| 17994 | | - } |
| 17995 | | - else if (option == OPT_TRIMRIGHT) { |
| 17996 | | - Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars)); |
| 17997 | | - } |
| 19408 | + Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], argc == 4 ? argv[3] : NULL)); |
| 17998 | 19409 | return JIM_OK; |
| 17999 | | - } |
| 19410 | + } |
| 18000 | 19411 | |
| 18001 | 19412 | case OPT_TOLOWER: |
| 18002 | | - case OPT_TOUPPER: |
| 18003 | | - case OPT_TOTITLE: |
| 18004 | | - if (argc != 3) { |
| 18005 | | - Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 18006 | | - return JIM_ERR; |
| 18007 | | - } |
| 18008 | | - if (option == OPT_TOLOWER) { |
| 18009 | 19413 | Jim_SetResult(interp, JimStringToLower(interp, argv[2])); |
| 18010 | | - } |
| 18011 | | - else if (option == OPT_TOUPPER) { |
| 19414 | + return JIM_OK; |
| 19415 | + case OPT_TOUPPER: |
| 18012 | 19416 | Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); |
| 18013 | | - } |
| 18014 | | - else { |
| 19417 | + return JIM_OK; |
| 19418 | + case OPT_TOTITLE: |
| 18015 | 19419 | Jim_SetResult(interp, JimStringToTitle(interp, argv[2])); |
| 18016 | | - } |
| 18017 | | - return JIM_OK; |
| 19420 | + return JIM_OK; |
| 18018 | 19421 | |
| 18019 | 19422 | case OPT_IS: |
| 18020 | | - if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { |
| 18021 | | - return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); |
| 19423 | + if (argc == 5 && !Jim_CompareStringImmediate(interp, argv[3], "-strict")) { |
| 19424 | + Jim_SubCmdArgError(interp, ct, argv[0]); |
| 19425 | + return JIM_ERR; |
| 18022 | 19426 | } |
| 18023 | | - Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); |
| 18024 | | - return JIM_ERR; |
| 19427 | + return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); |
| 18025 | 19428 | } |
| 18026 | 19429 | return JIM_OK; |
| 18027 | 19430 | } |
| 18028 | 19431 | |
| 18029 | 19432 | |
| 18030 | 19433 | static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18031 | 19434 | { |
| 18032 | 19435 | long i, count = 1; |
| 18033 | 19436 | jim_wide start, elapsed; |
| 18034 | | - char buf[60]; |
| 18035 | | - const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration"; |
| 18036 | 19437 | |
| 18037 | 19438 | if (argc < 2) { |
| 18038 | 19439 | Jim_WrongNumArgs(interp, 1, argv, "script ?count?"); |
| 18039 | 19440 | return JIM_ERR; |
| 18040 | 19441 | } |
| | @@ -18043,22 +19444,92 @@ |
| 18043 | 19444 | return JIM_ERR; |
| 18044 | 19445 | } |
| 18045 | 19446 | if (count < 0) |
| 18046 | 19447 | return JIM_OK; |
| 18047 | 19448 | i = count; |
| 18048 | | - start = JimClock(); |
| 19449 | + start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW); |
| 18049 | 19450 | while (i-- > 0) { |
| 18050 | 19451 | int retval; |
| 18051 | 19452 | |
| 18052 | 19453 | retval = Jim_EvalObj(interp, argv[1]); |
| 18053 | 19454 | if (retval != JIM_OK) { |
| 18054 | 19455 | return retval; |
| 18055 | 19456 | } |
| 18056 | 19457 | } |
| 18057 | | - elapsed = JimClock() - start; |
| 18058 | | - sprintf(buf, fmt, count == 0 ? 0 : elapsed / count); |
| 18059 | | - Jim_SetResultString(interp, buf, -1); |
| 19458 | + elapsed = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start; |
| 19459 | + if (elapsed < count * 10) { |
| 19460 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, elapsed * 1.0 / count)); |
| 19461 | + } |
| 19462 | + else { |
| 19463 | + Jim_SetResultInt(interp, count == 0 ? 0 : elapsed / count); |
| 19464 | + } |
| 19465 | + Jim_AppendString(interp, Jim_GetResult(interp)," microseconds per iteration", -1); |
| 19466 | + return JIM_OK; |
| 19467 | +} |
| 19468 | + |
| 19469 | + |
| 19470 | +static int Jim_TimeRateCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19471 | +{ |
| 19472 | + long us = 0; |
| 19473 | + jim_wide start, delta, overhead; |
| 19474 | + Jim_Obj *objPtr; |
| 19475 | + double us_per_iter; |
| 19476 | + int count; |
| 19477 | + int n; |
| 19478 | + |
| 19479 | + if (argc < 2) { |
| 19480 | + Jim_WrongNumArgs(interp, 1, argv, "script ?milliseconds?"); |
| 19481 | + return JIM_ERR; |
| 19482 | + } |
| 19483 | + if (argc == 3) { |
| 19484 | + if (Jim_GetLong(interp, argv[2], &us) != JIM_OK) |
| 19485 | + return JIM_ERR; |
| 19486 | + us *= 1000; |
| 19487 | + } |
| 19488 | + if (us < 1) { |
| 19489 | + |
| 19490 | + us = 1000 * 1000; |
| 19491 | + } |
| 19492 | + |
| 19493 | + |
| 19494 | + start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW); |
| 19495 | + count = 0; |
| 19496 | + do { |
| 19497 | + int retval = Jim_EvalObj(interp, argv[1]); |
| 19498 | + delta = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start; |
| 19499 | + if (retval != JIM_OK) { |
| 19500 | + return retval; |
| 19501 | + } |
| 19502 | + count++; |
| 19503 | + } while (delta < us); |
| 19504 | + |
| 19505 | + |
| 19506 | + start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW); |
| 19507 | + n = 0; |
| 19508 | + do { |
| 19509 | + int retval = Jim_EvalObj(interp, interp->nullScriptObj); |
| 19510 | + overhead = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start; |
| 19511 | + if (retval != JIM_OK) { |
| 19512 | + return retval; |
| 19513 | + } |
| 19514 | + n++; |
| 19515 | + } while (n < count); |
| 19516 | + |
| 19517 | + delta -= overhead; |
| 19518 | + |
| 19519 | + us_per_iter = (double)delta / count; |
| 19520 | + objPtr = Jim_NewListObj(interp, NULL, 0); |
| 19521 | + |
| 19522 | + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "us_per_iter", -1)); |
| 19523 | + Jim_ListAppendElement(interp, objPtr, Jim_NewDoubleObj(interp, us_per_iter)); |
| 19524 | + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "iters_per_sec", -1)); |
| 19525 | + Jim_ListAppendElement(interp, objPtr, Jim_NewDoubleObj(interp, 1e6 / us_per_iter)); |
| 19526 | + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "count", -1)); |
| 19527 | + Jim_ListAppendElement(interp, objPtr, Jim_NewIntObj(interp, count)); |
| 19528 | + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "elapsed_us", -1)); |
| 19529 | + Jim_ListAppendElement(interp, objPtr, Jim_NewIntObj(interp, delta)); |
| 19530 | + Jim_SetResult(interp, objPtr); |
| 18060 | 19531 | return JIM_OK; |
| 18061 | 19532 | } |
| 18062 | 19533 | |
| 18063 | 19534 | |
| 18064 | 19535 | static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -18070,25 +19541,55 @@ |
| 18070 | 19541 | return JIM_ERR; |
| 18071 | 19542 | } |
| 18072 | 19543 | if (argc == 2) { |
| 18073 | 19544 | if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK) |
| 18074 | 19545 | return JIM_ERR; |
| 19546 | + Jim_SetResult(interp, argv[1]); |
| 18075 | 19547 | } |
| 18076 | 19548 | interp->exitCode = exitCode; |
| 18077 | 19549 | return JIM_EXIT; |
| 18078 | 19550 | } |
| 18079 | 19551 | |
| 19552 | +static int JimMatchReturnCodes(Jim_Interp *interp, Jim_Obj *retcodeListObj, int rc) |
| 19553 | +{ |
| 19554 | + int len = Jim_ListLength(interp, retcodeListObj); |
| 19555 | + int i; |
| 19556 | + for (i = 0; i < len; i++) { |
| 19557 | + int returncode; |
| 19558 | + if (Jim_GetReturnCode(interp, Jim_ListGetIndex(interp, retcodeListObj, i), &returncode) != JIM_OK) { |
| 19559 | + return JIM_ERR; |
| 19560 | + } |
| 19561 | + if (rc == returncode) { |
| 19562 | + return JIM_OK; |
| 19563 | + } |
| 19564 | + } |
| 19565 | + return -1; |
| 19566 | +} |
| 18080 | 19567 | |
| 18081 | | -static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19568 | + |
| 19569 | +static int JimCatchTryHelper(Jim_Interp *interp, int istry, int argc, Jim_Obj *const *argv) |
| 18082 | 19570 | { |
| 19571 | + static const char * const wrongargs_catchtry[2] = { |
| 19572 | + "?-?no?code ... --? script ?resultVarName? ?optionVarName?", |
| 19573 | + "?-?no?code ... --? script ?on|trap codes vars script? ... ?finally script?" |
| 19574 | + }; |
| 18083 | 19575 | int exitCode = 0; |
| 18084 | 19576 | int i; |
| 18085 | 19577 | int sig = 0; |
| 19578 | + int ok; |
| 19579 | + Jim_Obj *finallyScriptObj = NULL; |
| 19580 | + Jim_Obj *msgVarObj = NULL; |
| 19581 | + Jim_Obj *optsVarObj = NULL; |
| 19582 | + Jim_Obj *handlerScriptObj = NULL; |
| 19583 | + Jim_Obj *errorCodeObj; |
| 19584 | + int idx; |
| 18086 | 19585 | |
| 18087 | 19586 | |
| 18088 | 19587 | jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); |
| 18089 | 19588 | static const int max_ignore_code = sizeof(ignore_mask) * 8; |
| 19589 | + |
| 19590 | + JimPanic((istry != 0 && istry != 1, "wrong args to JimCatchTryHelper")); |
| 18090 | 19591 | |
| 18091 | 19592 | Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); |
| 18092 | 19593 | |
| 18093 | 19594 | for (i = 1; i < argc - 1; i++) { |
| 18094 | 19595 | const char *arg = Jim_String(argv[i]); |
| | @@ -18129,18 +19630,17 @@ |
| 18129 | 19630 | else { |
| 18130 | 19631 | ignore_mask &= (~((jim_wide)1 << option)); |
| 18131 | 19632 | } |
| 18132 | 19633 | } |
| 18133 | 19634 | |
| 18134 | | - argc -= i; |
| 18135 | | - if (argc < 1 || argc > 3) { |
| 18136 | | - wrongargs: |
| 18137 | | - Jim_WrongNumArgs(interp, 1, argv, |
| 18138 | | - "?-?no?code ... --? script ?resultVarName? ?optionVarName?"); |
| 19635 | + idx = i; |
| 19636 | + |
| 19637 | + if (argc - idx < 1) { |
| 19638 | +wrongargs: |
| 19639 | + Jim_WrongNumArgs(interp, 1, argv, wrongargs_catchtry[istry]); |
| 18139 | 19640 | return JIM_ERR; |
| 18140 | 19641 | } |
| 18141 | | - argv += i; |
| 18142 | 19642 | |
| 18143 | 19643 | if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { |
| 18144 | 19644 | sig++; |
| 18145 | 19645 | } |
| 18146 | 19646 | |
| | @@ -18148,64 +19648,172 @@ |
| 18148 | 19648 | if (Jim_CheckSignal(interp)) { |
| 18149 | 19649 | |
| 18150 | 19650 | exitCode = JIM_SIGNAL; |
| 18151 | 19651 | } |
| 18152 | 19652 | else { |
| 18153 | | - exitCode = Jim_EvalObj(interp, argv[0]); |
| 19653 | + exitCode = Jim_EvalObj(interp, argv[idx]); |
| 18154 | 19654 | |
| 18155 | 19655 | interp->errorFlag = 0; |
| 18156 | 19656 | } |
| 18157 | 19657 | interp->signal_level -= sig; |
| 18158 | 19658 | |
| 19659 | + errorCodeObj = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); |
| 19660 | + |
| 19661 | + idx++; |
| 19662 | + if (istry) { |
| 19663 | + while (idx < argc) { |
| 19664 | + int option; |
| 19665 | + int ret; |
| 19666 | + static const char * const try_options[] = { "on", "trap", "finally", NULL }; |
| 19667 | + enum { TRY_ON, TRY_TRAP, TRY_FINALLY, }; |
| 19668 | + |
| 19669 | + if (Jim_GetEnum(interp, argv[idx], try_options, &option, "handler", JIM_ERRMSG) != JIM_OK) { |
| 19670 | + return JIM_ERR; |
| 19671 | + } |
| 19672 | + switch (option) { |
| 19673 | + case TRY_ON: |
| 19674 | + case TRY_TRAP: |
| 19675 | + if (idx + 4 > argc) { |
| 19676 | + goto wrongargs; |
| 19677 | + } |
| 19678 | + if (option == TRY_ON) { |
| 19679 | + ret = JimMatchReturnCodes(interp, argv[idx + 1], exitCode); |
| 19680 | + if (ret > JIM_OK) { |
| 19681 | + goto wrongargs; |
| 19682 | + } |
| 19683 | + } |
| 19684 | + else if (errorCodeObj) { |
| 19685 | + int len = Jim_ListLength(interp, argv[idx + 1]); |
| 19686 | + int i; |
| 19687 | + |
| 19688 | + ret = JIM_OK; |
| 19689 | + |
| 19690 | + for (i = 0; i < len; i++) { |
| 19691 | + Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i); |
| 19692 | + Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i); |
| 19693 | + if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) { |
| 19694 | + ret = -1; |
| 19695 | + break; |
| 19696 | + } |
| 19697 | + } |
| 19698 | + } |
| 19699 | + else { |
| 19700 | + |
| 19701 | + ret = -1; |
| 19702 | + } |
| 19703 | + |
| 19704 | + if (ret == JIM_OK && handlerScriptObj == NULL) { |
| 19705 | + msgVarObj = Jim_ListGetIndex(interp, argv[idx + 2], 0); |
| 19706 | + optsVarObj = Jim_ListGetIndex(interp, argv[idx + 2], 1); |
| 19707 | + handlerScriptObj = argv[idx + 3]; |
| 19708 | + } |
| 19709 | + idx += 4; |
| 19710 | + break; |
| 19711 | + case TRY_FINALLY: |
| 19712 | + if (idx + 2 != argc) { |
| 19713 | + goto wrongargs; |
| 19714 | + } |
| 19715 | + finallyScriptObj = argv[idx + 1]; |
| 19716 | + idx += 2; |
| 19717 | + break; |
| 19718 | + } |
| 19719 | + } |
| 19720 | + } |
| 19721 | + else { |
| 19722 | + if (argc - idx >= 1) { |
| 19723 | + msgVarObj = argv[idx]; |
| 19724 | + idx++; |
| 19725 | + if (argc - idx >= 1) { |
| 19726 | + optsVarObj = argv[idx]; |
| 19727 | + idx++; |
| 19728 | + } |
| 19729 | + } |
| 19730 | + } |
| 19731 | + |
| 18159 | 19732 | |
| 18160 | 19733 | if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 18161 | 19734 | |
| 19735 | + if (finallyScriptObj) { |
| 19736 | + Jim_EvalObj(interp, finallyScriptObj); |
| 19737 | + } |
| 18162 | 19738 | return exitCode; |
| 18163 | 19739 | } |
| 18164 | 19740 | |
| 18165 | 19741 | if (sig && exitCode == JIM_SIGNAL) { |
| 18166 | 19742 | |
| 18167 | 19743 | if (interp->signal_set_result) { |
| 18168 | 19744 | interp->signal_set_result(interp, interp->sigmask); |
| 18169 | 19745 | } |
| 18170 | | - else { |
| 19746 | + else if (!istry) { |
| 18171 | 19747 | Jim_SetResultInt(interp, interp->sigmask); |
| 18172 | 19748 | } |
| 18173 | 19749 | interp->sigmask = 0; |
| 18174 | 19750 | } |
| 18175 | 19751 | |
| 18176 | | - if (argc >= 2) { |
| 18177 | | - if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) { |
| 18178 | | - return JIM_ERR; |
| 18179 | | - } |
| 18180 | | - if (argc == 3) { |
| 18181 | | - Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); |
| 18182 | | - |
| 18183 | | - Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); |
| 18184 | | - Jim_ListAppendElement(interp, optListObj, |
| 18185 | | - Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); |
| 18186 | | - Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); |
| 18187 | | - Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); |
| 18188 | | - if (exitCode == JIM_ERR) { |
| 18189 | | - Jim_Obj *errorCode; |
| 18190 | | - Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", |
| 18191 | | - -1)); |
| 18192 | | - Jim_ListAppendElement(interp, optListObj, interp->stackTrace); |
| 18193 | | - |
| 18194 | | - errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); |
| 18195 | | - if (errorCode) { |
| 18196 | | - Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); |
| 18197 | | - Jim_ListAppendElement(interp, optListObj, errorCode); |
| 18198 | | - } |
| 18199 | | - } |
| 18200 | | - if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) { |
| 18201 | | - return JIM_ERR; |
| 18202 | | - } |
| 18203 | | - } |
| 18204 | | - } |
| 18205 | | - Jim_SetResultInt(interp, exitCode); |
| 18206 | | - return JIM_OK; |
| 19752 | + ok = 1; |
| 19753 | + if (msgVarObj && Jim_Length(msgVarObj)) { |
| 19754 | + if (Jim_SetVariable(interp, msgVarObj, Jim_GetResult(interp)) != JIM_OK) { |
| 19755 | + ok = 0; |
| 19756 | + } |
| 19757 | + } |
| 19758 | + if (ok && optsVarObj && Jim_Length(optsVarObj)) { |
| 19759 | + Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); |
| 19760 | + |
| 19761 | + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); |
| 19762 | + Jim_ListAppendElement(interp, optListObj, |
| 19763 | + Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); |
| 19764 | + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); |
| 19765 | + Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); |
| 19766 | + if (exitCode == JIM_ERR) { |
| 19767 | + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", |
| 19768 | + -1)); |
| 19769 | + Jim_ListAppendElement(interp, optListObj, interp->stackTrace); |
| 19770 | + |
| 19771 | + if (errorCodeObj) { |
| 19772 | + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); |
| 19773 | + Jim_ListAppendElement(interp, optListObj, errorCodeObj); |
| 19774 | + } |
| 19775 | + } |
| 19776 | + if (Jim_SetVariable(interp, optsVarObj, optListObj) != JIM_OK) { |
| 19777 | + ok = 0; |
| 19778 | + } |
| 19779 | + } |
| 19780 | + if (ok && handlerScriptObj) { |
| 19781 | + |
| 19782 | + exitCode = Jim_EvalObj(interp, handlerScriptObj); |
| 19783 | + } |
| 19784 | + |
| 19785 | + if (finallyScriptObj) { |
| 19786 | + |
| 19787 | + Jim_Obj *prevResultObj = Jim_GetResult(interp); |
| 19788 | + Jim_IncrRefCount(prevResultObj); |
| 19789 | + int ret = Jim_EvalObj(interp, finallyScriptObj); |
| 19790 | + if (ret == JIM_OK) { |
| 19791 | + Jim_SetResult(interp, prevResultObj); |
| 19792 | + } |
| 19793 | + else { |
| 19794 | + exitCode = ret; |
| 19795 | + } |
| 19796 | + Jim_DecrRefCount(interp, prevResultObj); |
| 19797 | + } |
| 19798 | + if (!istry) { |
| 19799 | + Jim_SetResultInt(interp, exitCode); |
| 19800 | + exitCode = JIM_OK; |
| 19801 | + } |
| 19802 | + return exitCode; |
| 19803 | +} |
| 19804 | + |
| 19805 | + |
| 19806 | +static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19807 | +{ |
| 19808 | + return JimCatchTryHelper(interp, 0, argc, argv); |
| 19809 | +} |
| 19810 | + |
| 19811 | + |
| 19812 | +static int Jim_TryCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19813 | +{ |
| 19814 | + return JimCatchTryHelper(interp, 1, argc, argv); |
| 18207 | 19815 | } |
| 18208 | 19816 | |
| 18209 | 19817 | |
| 18210 | 19818 | |
| 18211 | 19819 | static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -18213,46 +19821,44 @@ |
| 18213 | 19821 | if (argc != 3) { |
| 18214 | 19822 | Jim_WrongNumArgs(interp, 1, argv, "oldName newName"); |
| 18215 | 19823 | return JIM_ERR; |
| 18216 | 19824 | } |
| 18217 | 19825 | |
| 18218 | | - if (JimValidName(interp, "new procedure", argv[2])) { |
| 18219 | | - return JIM_ERR; |
| 18220 | | - } |
| 18221 | | - |
| 18222 | | - return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); |
| 19826 | + return Jim_RenameCommand(interp, argv[1], argv[2]); |
| 18223 | 19827 | } |
| 18224 | 19828 | |
| 18225 | 19829 | #define JIM_DICTMATCH_KEYS 0x0001 |
| 18226 | 19830 | #define JIM_DICTMATCH_VALUES 0x002 |
| 18227 | 19831 | |
| 18228 | 19832 | int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types) |
| 18229 | 19833 | { |
| 18230 | | - Jim_HashEntry *he; |
| 18231 | 19834 | Jim_Obj *listObjPtr; |
| 18232 | | - Jim_HashTableIterator htiter; |
| 19835 | + Jim_Dict *dict; |
| 19836 | + int i; |
| 18233 | 19837 | |
| 18234 | 19838 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18235 | 19839 | return JIM_ERR; |
| 18236 | 19840 | } |
| 19841 | + dict = objPtr->internalRep.dictValue; |
| 18237 | 19842 | |
| 18238 | 19843 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18239 | 19844 | |
| 18240 | | - JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter); |
| 18241 | | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 19845 | + for (i = 0; i < dict->len; i += 2 ) { |
| 19846 | + Jim_Obj *keyObj = dict->table[i]; |
| 19847 | + Jim_Obj *valObj = dict->table[i + 1]; |
| 18242 | 19848 | if (patternObj) { |
| 18243 | | - Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he); |
| 18244 | | - if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) { |
| 19849 | + Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? keyObj : valObj; |
| 19850 | + if (!Jim_StringMatchObj(interp, patternObj, matchObj, 0)) { |
| 18245 | 19851 | |
| 18246 | 19852 | continue; |
| 18247 | 19853 | } |
| 18248 | 19854 | } |
| 18249 | 19855 | if (return_types & JIM_DICTMATCH_KEYS) { |
| 18250 | | - Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 19856 | + Jim_ListAppendElement(interp, listObjPtr, keyObj); |
| 18251 | 19857 | } |
| 18252 | 19858 | if (return_types & JIM_DICTMATCH_VALUES) { |
| 18253 | | - Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); |
| 19859 | + Jim_ListAppendElement(interp, listObjPtr, valObj); |
| 18254 | 19860 | } |
| 18255 | 19861 | } |
| 18256 | 19862 | |
| 18257 | 19863 | Jim_SetResult(interp, listObjPtr); |
| 18258 | 19864 | return JIM_OK; |
| | @@ -18261,11 +19867,11 @@ |
| 18261 | 19867 | int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18262 | 19868 | { |
| 18263 | 19869 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18264 | 19870 | return -1; |
| 18265 | 19871 | } |
| 18266 | | - return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 19872 | + return objPtr->internalRep.dictValue->len / 2; |
| 18267 | 19873 | } |
| 18268 | 19874 | |
| 18269 | 19875 | Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 18270 | 19876 | { |
| 18271 | 19877 | Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0); |
| | @@ -18274,73 +19880,41 @@ |
| 18274 | 19880 | JimPanic((objc == 0, "Jim_DictMerge called with objc=0")); |
| 18275 | 19881 | |
| 18276 | 19882 | |
| 18277 | 19883 | |
| 18278 | 19884 | for (i = 0; i < objc; i++) { |
| 18279 | | - Jim_HashTable *ht; |
| 18280 | | - Jim_HashTableIterator htiter; |
| 18281 | | - Jim_HashEntry *he; |
| 19885 | + Jim_Obj **table; |
| 19886 | + int tablelen; |
| 19887 | + int j; |
| 18282 | 19888 | |
| 18283 | | - if (SetDictFromAny(interp, objv[i]) != JIM_OK) { |
| 19889 | + table = Jim_DictPairs(interp, objv[i], &tablelen); |
| 19890 | + if (tablelen && !table) { |
| 18284 | 19891 | Jim_FreeNewObj(interp, objPtr); |
| 18285 | 19892 | return NULL; |
| 18286 | 19893 | } |
| 18287 | | - ht = objv[i]->internalRep.ptr; |
| 18288 | | - JimInitHashTableIterator(ht, &htiter); |
| 18289 | | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18290 | | - Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he)); |
| 19894 | + for (j = 0; j < tablelen; j += 2) { |
| 19895 | + DictAddElement(interp, objPtr, table[j], table[j + 1]); |
| 18291 | 19896 | } |
| 18292 | 19897 | } |
| 18293 | 19898 | return objPtr; |
| 18294 | 19899 | } |
| 18295 | 19900 | |
| 18296 | 19901 | int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18297 | 19902 | { |
| 18298 | | - Jim_HashTable *ht; |
| 18299 | | - unsigned int i; |
| 18300 | 19903 | char buffer[100]; |
| 18301 | | - int sum = 0; |
| 18302 | | - int nonzero_count = 0; |
| 18303 | 19904 | Jim_Obj *output; |
| 18304 | | - int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 19905 | + Jim_Dict *dict; |
| 18305 | 19906 | |
| 18306 | 19907 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18307 | 19908 | return JIM_ERR; |
| 18308 | 19909 | } |
| 18309 | 19910 | |
| 18310 | | - ht = (Jim_HashTable *)objPtr->internalRep.ptr; |
| 18311 | | - |
| 18312 | | - |
| 18313 | | - snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size); |
| 18314 | | - output = Jim_NewStringObj(interp, buffer, -1); |
| 18315 | | - |
| 18316 | | - for (i = 0; i < ht->size; i++) { |
| 18317 | | - Jim_HashEntry *he = ht->table[i]; |
| 18318 | | - int entries = 0; |
| 18319 | | - while (he) { |
| 18320 | | - entries++; |
| 18321 | | - he = he->next; |
| 18322 | | - } |
| 18323 | | - if (entries > 9) { |
| 18324 | | - bucket_counts[10]++; |
| 18325 | | - } |
| 18326 | | - else { |
| 18327 | | - bucket_counts[entries]++; |
| 18328 | | - } |
| 18329 | | - if (entries) { |
| 18330 | | - sum += entries; |
| 18331 | | - nonzero_count++; |
| 18332 | | - } |
| 18333 | | - } |
| 18334 | | - for (i = 0; i < 10; i++) { |
| 18335 | | - snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]); |
| 18336 | | - Jim_AppendString(interp, output, buffer, -1); |
| 18337 | | - } |
| 18338 | | - snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]); |
| 18339 | | - Jim_AppendString(interp, output, buffer, -1); |
| 18340 | | - snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0); |
| 18341 | | - Jim_AppendString(interp, output, buffer, -1); |
| 19911 | + dict = objPtr->internalRep.dictValue; |
| 19912 | + |
| 19913 | + |
| 19914 | + snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets", dict->len, dict->size); |
| 19915 | + output = Jim_NewStringObj(interp, buffer, -1); |
| 18342 | 19916 | Jim_SetResult(interp, output); |
| 18343 | 19917 | return JIM_OK; |
| 18344 | 19918 | } |
| 18345 | 19919 | |
| 18346 | 19920 | static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) |
| | @@ -18366,16 +19940,16 @@ |
| 18366 | 19940 | dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG); |
| 18367 | 19941 | if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) { |
| 18368 | 19942 | return JIM_ERR; |
| 18369 | 19943 | } |
| 18370 | 19944 | |
| 18371 | | - if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) { |
| 19945 | + dictValues = Jim_DictPairs(interp, objPtr, &len); |
| 19946 | + if (len && dictValues == NULL) { |
| 18372 | 19947 | return JIM_ERR; |
| 18373 | 19948 | } |
| 18374 | 19949 | for (i = 0; i < len; i += 2) { |
| 18375 | 19950 | if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) { |
| 18376 | | - Jim_Free(dictValues); |
| 18377 | 19951 | return JIM_ERR; |
| 18378 | 19952 | } |
| 18379 | 19953 | } |
| 18380 | 19954 | |
| 18381 | 19955 | |
| | @@ -18390,110 +19964,137 @@ |
| 18390 | 19964 | newkeyv[i] = keyv[i]; |
| 18391 | 19965 | } |
| 18392 | 19966 | |
| 18393 | 19967 | for (i = 0; i < len; i += 2) { |
| 18394 | 19968 | |
| 18395 | | - objPtr = Jim_GetVariable(interp, dictValues[i], 0); |
| 18396 | | - newkeyv[keyc] = dictValues[i]; |
| 18397 | | - Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0); |
| 19969 | + if (Jim_StringCompareObj(interp, dictVarName, dictValues[i], 0) != 0) { |
| 19970 | + |
| 19971 | + objPtr = Jim_GetVariable(interp, dictValues[i], 0); |
| 19972 | + newkeyv[keyc] = dictValues[i]; |
| 19973 | + Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, JIM_NORESULT); |
| 19974 | + } |
| 18398 | 19975 | } |
| 18399 | 19976 | Jim_Free(newkeyv); |
| 18400 | 19977 | } |
| 18401 | 19978 | } |
| 18402 | 19979 | |
| 18403 | | - Jim_Free(dictValues); |
| 18404 | | - |
| 18405 | 19980 | return ret; |
| 18406 | 19981 | } |
| 18407 | 19982 | |
| 18408 | 19983 | |
| 18409 | 19984 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18410 | 19985 | { |
| 18411 | 19986 | Jim_Obj *objPtr; |
| 18412 | 19987 | int types = JIM_DICTMATCH_KEYS; |
| 18413 | | - int option; |
| 18414 | | - static const char * const options[] = { |
| 18415 | | - "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18416 | | - "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18417 | | - "replace", "update", NULL |
| 18418 | | - }; |
| 18419 | | - enum |
| 18420 | | - { |
| 18421 | | - OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, |
| 18422 | | - OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, |
| 18423 | | - OPT_REPLACE, OPT_UPDATE, |
| 18424 | | - }; |
| 18425 | | - |
| 18426 | | - if (argc < 2) { |
| 18427 | | - Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18428 | | - return JIM_ERR; |
| 18429 | | - } |
| 18430 | | - |
| 18431 | | - if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { |
| 18432 | | - return Jim_CheckShowCommands(interp, argv[1], options); |
| 18433 | | - } |
| 18434 | | - |
| 18435 | | - switch (option) { |
| 18436 | | - case OPT_GET: |
| 18437 | | - if (argc < 3) { |
| 18438 | | - Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); |
| 18439 | | - return JIM_ERR; |
| 18440 | | - } |
| 19988 | + |
| 19989 | + enum { |
| 19990 | + OPT_CREATE, |
| 19991 | + OPT_GET, |
| 19992 | + OPT_GETDEF, |
| 19993 | + OPT_GETWITHDEFAULT, |
| 19994 | + OPT_SET, |
| 19995 | + OPT_UNSET, |
| 19996 | + OPT_EXISTS, |
| 19997 | + OPT_KEYS, |
| 19998 | + OPT_SIZE, |
| 19999 | + OPT_INFO, |
| 20000 | + OPT_MERGE, |
| 20001 | + OPT_WITH, |
| 20002 | + OPT_APPEND, |
| 20003 | + OPT_LAPPEND, |
| 20004 | + OPT_INCR, |
| 20005 | + OPT_REMOVE, |
| 20006 | + OPT_VALUES, |
| 20007 | + OPT_FOR, |
| 20008 | + OPT_REPLACE, |
| 20009 | + OPT_UPDATE, |
| 20010 | + OPT_COUNT |
| 20011 | + }; |
| 20012 | + static const jim_subcmd_type cmds[OPT_COUNT + 1] = { |
| 20013 | + JIM_DEF_SUBCMD("create", "?key value ...?", 0, -2), |
| 20014 | + JIM_DEF_SUBCMD("get", "dictionary ?key ...?", 1, -1), |
| 20015 | + JIM_DEF_SUBCMD_HIDDEN("getdef", "dictionary ?key ...? key default", 3, -1), |
| 20016 | + JIM_DEF_SUBCMD("getwithdefault", "dictionary ?key ...? key default", 3, -1), |
| 20017 | + JIM_DEF_SUBCMD("set", "varName key ?key ...? value", 3, -1), |
| 20018 | + JIM_DEF_SUBCMD("unset", "varName key ?key ...?", 2, -1), |
| 20019 | + JIM_DEF_SUBCMD("exists", "dictionary key ?key ...?", 2, -1), |
| 20020 | + JIM_DEF_SUBCMD("keys", "dictionary ?pattern?", 1, 2), |
| 20021 | + JIM_DEF_SUBCMD("size", "dictionary", 1, 1), |
| 20022 | + JIM_DEF_SUBCMD("info", "dictionary", 1, 1), |
| 20023 | + JIM_DEF_SUBCMD("merge", "?...?", 0, -1), |
| 20024 | + JIM_DEF_SUBCMD("with", "dictVar ?key ...? script", 2, -1), |
| 20025 | + JIM_DEF_SUBCMD("append", "varName key ?value ...?", 2, -1), |
| 20026 | + JIM_DEF_SUBCMD("lappend", "varName key ?value ...?", 2, -1), |
| 20027 | + JIM_DEF_SUBCMD("incr", "varName key ?increment?", 2, 3), |
| 20028 | + JIM_DEF_SUBCMD("remove", "dictionary ?key ...?", 1, -1), |
| 20029 | + JIM_DEF_SUBCMD("values", "dictionary ?pattern?", 1, 2), |
| 20030 | + JIM_DEF_SUBCMD("for", "vars dictionary script", 3, 3), |
| 20031 | + JIM_DEF_SUBCMD("replace", "dictionary ?key value ...?", 1, -1), |
| 20032 | + JIM_DEF_SUBCMD("update", "varName ?arg ...? script", 2, -1), |
| 20033 | + { } |
| 20034 | + }; |
| 20035 | + const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv); |
| 20036 | + if (!ct) { |
| 20037 | + return JIM_ERR; |
| 20038 | + } |
| 20039 | + if (ct->function) { |
| 20040 | + |
| 20041 | + return ct->function(interp, argc, argv); |
| 20042 | + } |
| 20043 | + |
| 20044 | + |
| 20045 | + switch (ct - cmds) { |
| 20046 | + case OPT_GET: |
| 18441 | 20047 | if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, |
| 18442 | 20048 | JIM_ERRMSG) != JIM_OK) { |
| 18443 | 20049 | return JIM_ERR; |
| 18444 | 20050 | } |
| 18445 | 20051 | Jim_SetResult(interp, objPtr); |
| 18446 | 20052 | return JIM_OK; |
| 18447 | 20053 | |
| 18448 | | - case OPT_SET: |
| 18449 | | - if (argc < 5) { |
| 18450 | | - Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); |
| 20054 | + case OPT_GETDEF: |
| 20055 | + case OPT_GETWITHDEFAULT:{ |
| 20056 | + int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 4, &objPtr, JIM_ERRMSG); |
| 20057 | + if (rc == -1) { |
| 20058 | + |
| 18451 | 20059 | return JIM_ERR; |
| 18452 | 20060 | } |
| 20061 | + if (rc == JIM_ERR) { |
| 20062 | + Jim_SetResult(interp, argv[argc - 1]); |
| 20063 | + } |
| 20064 | + else { |
| 20065 | + Jim_SetResult(interp, objPtr); |
| 20066 | + } |
| 20067 | + return JIM_OK; |
| 20068 | + } |
| 20069 | + |
| 20070 | + case OPT_SET: |
| 18453 | 20071 | return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); |
| 18454 | 20072 | |
| 18455 | | - case OPT_EXISTS: |
| 18456 | | - if (argc < 4) { |
| 18457 | | - Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); |
| 18458 | | - return JIM_ERR; |
| 18459 | | - } |
| 18460 | | - else { |
| 18461 | | - int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); |
| 20073 | + case OPT_EXISTS:{ |
| 20074 | + int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_NONE); |
| 18462 | 20075 | if (rc < 0) { |
| 18463 | 20076 | return JIM_ERR; |
| 18464 | 20077 | } |
| 18465 | 20078 | Jim_SetResultBool(interp, rc == JIM_OK); |
| 18466 | 20079 | return JIM_OK; |
| 18467 | 20080 | } |
| 18468 | 20081 | |
| 18469 | 20082 | case OPT_UNSET: |
| 18470 | | - if (argc < 4) { |
| 18471 | | - Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); |
| 18472 | | - return JIM_ERR; |
| 18473 | | - } |
| 18474 | | - if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 20083 | + if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE) != JIM_OK) { |
| 18475 | 20084 | return JIM_ERR; |
| 18476 | 20085 | } |
| 18477 | 20086 | return JIM_OK; |
| 18478 | 20087 | |
| 18479 | 20088 | case OPT_VALUES: |
| 18480 | 20089 | types = JIM_DICTMATCH_VALUES; |
| 18481 | 20090 | |
| 18482 | 20091 | case OPT_KEYS: |
| 18483 | | - if (argc != 3 && argc != 4) { |
| 18484 | | - Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18485 | | - return JIM_ERR; |
| 18486 | | - } |
| 18487 | 20092 | return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types); |
| 18488 | 20093 | |
| 18489 | 20094 | case OPT_SIZE: |
| 18490 | | - if (argc != 3) { |
| 18491 | | - Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18492 | | - return JIM_ERR; |
| 18493 | | - } |
| 18494 | | - else if (Jim_DictSize(interp, argv[2]) < 0) { |
| 20095 | + if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18495 | 20096 | return JIM_ERR; |
| 18496 | 20097 | } |
| 18497 | 20098 | Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); |
| 18498 | 20099 | return JIM_OK; |
| 18499 | 20100 | |
| | @@ -18506,42 +20107,30 @@ |
| 18506 | 20107 | return JIM_ERR; |
| 18507 | 20108 | } |
| 18508 | 20109 | Jim_SetResult(interp, objPtr); |
| 18509 | 20110 | return JIM_OK; |
| 18510 | 20111 | |
| 18511 | | - case OPT_UPDATE: |
| 18512 | | - if (argc < 6 || argc % 2) { |
| 18513 | | - |
| 18514 | | - argc = 2; |
| 18515 | | - } |
| 18516 | | - break; |
| 18517 | | - |
| 18518 | 20112 | case OPT_CREATE: |
| 18519 | | - if (argc % 2) { |
| 18520 | | - Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); |
| 18521 | | - return JIM_ERR; |
| 18522 | | - } |
| 18523 | 20113 | objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); |
| 18524 | 20114 | Jim_SetResult(interp, objPtr); |
| 18525 | 20115 | return JIM_OK; |
| 18526 | 20116 | |
| 18527 | 20117 | case OPT_INFO: |
| 18528 | | - if (argc != 3) { |
| 18529 | | - Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18530 | | - return JIM_ERR; |
| 18531 | | - } |
| 18532 | 20118 | return Jim_DictInfo(interp, argv[2]); |
| 18533 | 20119 | |
| 18534 | 20120 | case OPT_WITH: |
| 18535 | | - if (argc < 4) { |
| 18536 | | - Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); |
| 18537 | | - return JIM_ERR; |
| 18538 | | - } |
| 18539 | 20121 | return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]); |
| 20122 | + |
| 20123 | + case OPT_UPDATE: |
| 20124 | + if (argc < 6 || argc % 2) { |
| 20125 | + |
| 20126 | + argc = 2; |
| 20127 | + } |
| 20128 | + |
| 20129 | + default: |
| 20130 | + return Jim_EvalEnsemble(interp, "dict", Jim_String(argv[1]), argc - 2, argv + 2); |
| 18540 | 20131 | } |
| 18541 | | - |
| 18542 | | - return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18543 | 20132 | } |
| 18544 | 20133 | |
| 18545 | 20134 | |
| 18546 | 20135 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18547 | 20136 | { |
| | @@ -18582,30 +20171,79 @@ |
| 18582 | 20171 | } |
| 18583 | 20172 | Jim_SetResult(interp, objPtr); |
| 18584 | 20173 | return JIM_OK; |
| 18585 | 20174 | } |
| 18586 | 20175 | |
| 20176 | +#ifdef jim_ext_namespace |
| 20177 | +static int JimIsGlobalNamespace(Jim_Obj *objPtr) |
| 20178 | +{ |
| 20179 | + int len; |
| 20180 | + const char *str = Jim_GetString(objPtr, &len); |
| 20181 | + return len >= 2 && str[0] == ':' && str[1] == ':'; |
| 20182 | +} |
| 20183 | +#endif |
| 20184 | + |
| 18587 | 20185 | |
| 18588 | 20186 | static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18589 | 20187 | { |
| 18590 | | - int cmd; |
| 18591 | 20188 | Jim_Obj *objPtr; |
| 18592 | 20189 | int mode = 0; |
| 18593 | 20190 | |
| 18594 | | - static const char * const commands[] = { |
| 18595 | | - "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals", |
| 18596 | | - "vars", "version", "patchlevel", "complete", "args", "hostname", |
| 18597 | | - "script", "source", "stacktrace", "nameofexecutable", "returncodes", |
| 18598 | | - "references", "alias", NULL |
| 18599 | | - }; |
| 18600 | | - enum |
| 18601 | | - { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, |
| 18602 | | - INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, |
| 18603 | | - INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, |
| 18604 | | - INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, |
| 18605 | | - }; |
| 18606 | | - |
| 20191 | + |
| 20192 | + enum { |
| 20193 | + INFO_ALIAS, |
| 20194 | + INFO_ARGS, |
| 20195 | + INFO_BODY, |
| 20196 | + INFO_CHANNELS, |
| 20197 | + INFO_COMMANDS, |
| 20198 | + INFO_COMPLETE, |
| 20199 | + INFO_EXISTS, |
| 20200 | + INFO_FRAME, |
| 20201 | + INFO_GLOBALS, |
| 20202 | + INFO_HOSTNAME, |
| 20203 | + INFO_LEVEL, |
| 20204 | + INFO_LOCALS, |
| 20205 | + INFO_NAMEOFEXECUTABLE, |
| 20206 | + INFO_PATCHLEVEL, |
| 20207 | + INFO_PROCS, |
| 20208 | + INFO_REFERENCES, |
| 20209 | + INFO_RETURNCODES, |
| 20210 | + INFO_SCRIPT, |
| 20211 | + INFO_SOURCE, |
| 20212 | + INFO_STACKTRACE, |
| 20213 | + INFO_STATICS, |
| 20214 | + INFO_VARS, |
| 20215 | + INFO_VERSION, |
| 20216 | + INFO_COUNT |
| 20217 | + }; |
| 20218 | + static const jim_subcmd_type cmds[INFO_COUNT + 1] = { |
| 20219 | + JIM_DEF_SUBCMD("alias", "command", 1, 1), |
| 20220 | + JIM_DEF_SUBCMD("args", "procname", 1, 1), |
| 20221 | + JIM_DEF_SUBCMD("body", "procname", 1, 1), |
| 20222 | + JIM_DEF_SUBCMD("channels", "?pattern?", 0, 1), |
| 20223 | + JIM_DEF_SUBCMD("commands", "?pattern?", 0, 1), |
| 20224 | + JIM_DEF_SUBCMD("complete", "script ?missing?", 1, 2), |
| 20225 | + JIM_DEF_SUBCMD("exists", "varName", 1, 1), |
| 20226 | + JIM_DEF_SUBCMD("frame", "?levelNum?", 0, 1), |
| 20227 | + JIM_DEF_SUBCMD("globals", "?pattern?", 0, 1), |
| 20228 | + JIM_DEF_SUBCMD("hostname", NULL, 0, 0), |
| 20229 | + JIM_DEF_SUBCMD("level", "?levelNum?", 0, 1), |
| 20230 | + JIM_DEF_SUBCMD("locals", "?pattern?", 0, 1), |
| 20231 | + JIM_DEF_SUBCMD("nameofexecutable", NULL, 0, 0), |
| 20232 | + JIM_DEF_SUBCMD("patchlevel", NULL, 0, 0), |
| 20233 | + JIM_DEF_SUBCMD("procs", "?pattern?", 0, 1), |
| 20234 | + JIM_DEF_SUBCMD("references", NULL, 0, 0), |
| 20235 | + JIM_DEF_SUBCMD("returncodes", "?code?", 0, 1), |
| 20236 | + JIM_DEF_SUBCMD("script", "?filename?", 0, 1), |
| 20237 | + JIM_DEF_SUBCMD("source", "source ?filename line?", 1, 3), |
| 20238 | + JIM_DEF_SUBCMD("stacktrace", NULL, 0, 0), |
| 20239 | + JIM_DEF_SUBCMD("statics", "procname", 1, 1), |
| 20240 | + JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1), |
| 20241 | + JIM_DEF_SUBCMD("version", NULL, 0, 0), |
| 20242 | + { } |
| 20243 | + }; |
| 20244 | + const jim_subcmd_type *ct; |
| 18607 | 20245 | #ifdef jim_ext_namespace |
| 18608 | 20246 | int nons = 0; |
| 18609 | 20247 | |
| 18610 | 20248 | if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { |
| 18611 | 20249 | |
| | @@ -18612,36 +20250,29 @@ |
| 18612 | 20250 | argc--; |
| 18613 | 20251 | argv++; |
| 18614 | 20252 | nons = 1; |
| 18615 | 20253 | } |
| 18616 | 20254 | #endif |
| 18617 | | - |
| 18618 | | - if (argc < 2) { |
| 18619 | | - Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); |
| 20255 | + ct = Jim_ParseSubCmd(interp, cmds, argc, argv); |
| 20256 | + if (!ct) { |
| 18620 | 20257 | return JIM_ERR; |
| 18621 | 20258 | } |
| 18622 | | - if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { |
| 18623 | | - return Jim_CheckShowCommands(interp, argv[1], commands); |
| 20259 | + if (ct->function) { |
| 20260 | + |
| 20261 | + return ct->function(interp, argc, argv); |
| 18624 | 20262 | } |
| 18625 | 20263 | |
| 20264 | + int option = ct - cmds; |
| 18626 | 20265 | |
| 18627 | | - switch (cmd) { |
| 20266 | + switch (option) { |
| 18628 | 20267 | case INFO_EXISTS: |
| 18629 | | - if (argc != 3) { |
| 18630 | | - Jim_WrongNumArgs(interp, 2, argv, "varName"); |
| 18631 | | - return JIM_ERR; |
| 18632 | | - } |
| 18633 | 20268 | Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL); |
| 18634 | | - break; |
| 20269 | + return JIM_OK; |
| 18635 | 20270 | |
| 18636 | 20271 | case INFO_ALIAS:{ |
| 18637 | 20272 | Jim_Cmd *cmdPtr; |
| 18638 | 20273 | |
| 18639 | | - if (argc != 3) { |
| 18640 | | - Jim_WrongNumArgs(interp, 2, argv, "command"); |
| 18641 | | - return JIM_ERR; |
| 18642 | | - } |
| 18643 | 20274 | if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { |
| 18644 | 20275 | return JIM_ERR; |
| 18645 | 20276 | } |
| 18646 | 20277 | if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) { |
| 18647 | 20278 | Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]); |
| | @@ -18661,61 +20292,54 @@ |
| 18661 | 20292 | case INFO_PROCS: |
| 18662 | 20293 | mode++; |
| 18663 | 20294 | |
| 18664 | 20295 | case INFO_COMMANDS: |
| 18665 | 20296 | |
| 18666 | | - if (argc != 2 && argc != 3) { |
| 18667 | | - Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18668 | | - return JIM_ERR; |
| 18669 | | - } |
| 18670 | 20297 | #ifdef jim_ext_namespace |
| 18671 | 20298 | if (!nons) { |
| 18672 | | - if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { |
| 20299 | + if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) { |
| 18673 | 20300 | return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); |
| 18674 | 20301 | } |
| 18675 | 20302 | } |
| 18676 | 20303 | #endif |
| 18677 | 20304 | Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); |
| 18678 | | - break; |
| 20305 | + return JIM_OK; |
| 18679 | 20306 | |
| 18680 | 20307 | case INFO_VARS: |
| 18681 | 20308 | mode++; |
| 18682 | 20309 | |
| 18683 | 20310 | case INFO_LOCALS: |
| 18684 | 20311 | mode++; |
| 18685 | 20312 | |
| 18686 | 20313 | case INFO_GLOBALS: |
| 18687 | 20314 | |
| 18688 | | - if (argc != 2 && argc != 3) { |
| 18689 | | - Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18690 | | - return JIM_ERR; |
| 18691 | | - } |
| 18692 | 20315 | #ifdef jim_ext_namespace |
| 18693 | 20316 | if (!nons) { |
| 18694 | | - if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { |
| 20317 | + if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) { |
| 18695 | 20318 | return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); |
| 18696 | 20319 | } |
| 18697 | 20320 | } |
| 18698 | 20321 | #endif |
| 18699 | 20322 | Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode)); |
| 18700 | | - break; |
| 20323 | + return JIM_OK; |
| 18701 | 20324 | |
| 18702 | 20325 | case INFO_SCRIPT: |
| 18703 | | - if (argc != 2) { |
| 18704 | | - Jim_WrongNumArgs(interp, 2, argv, ""); |
| 18705 | | - return JIM_ERR; |
| 20326 | + if (argc == 3) { |
| 20327 | + Jim_IncrRefCount(argv[2]); |
| 20328 | + Jim_DecrRefCount(interp, interp->currentFilenameObj); |
| 20329 | + interp->currentFilenameObj = argv[2]; |
| 18706 | 20330 | } |
| 18707 | | - Jim_SetResult(interp, JimGetScript(interp, interp->currentScriptObj)->fileNameObj); |
| 18708 | | - break; |
| 20331 | + Jim_SetResult(interp, interp->currentFilenameObj); |
| 20332 | + return JIM_OK; |
| 18709 | 20333 | |
| 18710 | 20334 | case INFO_SOURCE:{ |
| 18711 | 20335 | jim_wide line; |
| 18712 | 20336 | Jim_Obj *resObjPtr; |
| 18713 | 20337 | Jim_Obj *fileNameObj; |
| 18714 | 20338 | |
| 18715 | | - if (argc != 3 && argc != 5) { |
| 18716 | | - Jim_WrongNumArgs(interp, 2, argv, "source ?filename line?"); |
| 20339 | + if (argc == 4) { |
| 20340 | + Jim_SubCmdArgError(interp, ct, argv[0]); |
| 18717 | 20341 | return JIM_ERR; |
| 18718 | 20342 | } |
| 18719 | 20343 | if (argc == 5) { |
| 18720 | 20344 | if (Jim_GetWide(interp, argv[4], &line) != JIM_OK) { |
| 18721 | 20345 | return JIM_ERR; |
| | @@ -18740,93 +20364,94 @@ |
| 18740 | 20364 | resObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18741 | 20365 | Jim_ListAppendElement(interp, resObjPtr, fileNameObj); |
| 18742 | 20366 | Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); |
| 18743 | 20367 | } |
| 18744 | 20368 | Jim_SetResult(interp, resObjPtr); |
| 18745 | | - break; |
| 20369 | + return JIM_OK; |
| 18746 | 20370 | } |
| 18747 | 20371 | |
| 18748 | 20372 | case INFO_STACKTRACE: |
| 18749 | 20373 | Jim_SetResult(interp, interp->stackTrace); |
| 18750 | | - break; |
| 20374 | + return JIM_OK; |
| 18751 | 20375 | |
| 18752 | 20376 | case INFO_LEVEL: |
| 18753 | | - case INFO_FRAME: |
| 18754 | | - switch (argc) { |
| 18755 | | - case 2: |
| 18756 | | - Jim_SetResultInt(interp, interp->framePtr->level); |
| 18757 | | - break; |
| 18758 | | - |
| 18759 | | - case 3: |
| 18760 | | - if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { |
| 18761 | | - return JIM_ERR; |
| 18762 | | - } |
| 18763 | | - Jim_SetResult(interp, objPtr); |
| 18764 | | - break; |
| 18765 | | - |
| 18766 | | - default: |
| 18767 | | - Jim_WrongNumArgs(interp, 2, argv, "?levelNum?"); |
| 18768 | | - return JIM_ERR; |
| 18769 | | - } |
| 18770 | | - break; |
| 20377 | + if (argc == 2) { |
| 20378 | + Jim_SetResultInt(interp, interp->framePtr->level); |
| 20379 | + } |
| 20380 | + else { |
| 20381 | + if (JimInfoLevel(interp, argv[2], &objPtr) != JIM_OK) { |
| 20382 | + return JIM_ERR; |
| 20383 | + } |
| 20384 | + Jim_SetResult(interp, objPtr); |
| 20385 | + } |
| 20386 | + return JIM_OK; |
| 20387 | + |
| 20388 | + case INFO_FRAME: |
| 20389 | + if (argc == 2) { |
| 20390 | + Jim_SetResultInt(interp, interp->procLevel + 1); |
| 20391 | + } |
| 20392 | + else { |
| 20393 | + if (JimInfoFrame(interp, argv[2], &objPtr) != JIM_OK) { |
| 20394 | + return JIM_ERR; |
| 20395 | + } |
| 20396 | + Jim_SetResult(interp, objPtr); |
| 20397 | + } |
| 20398 | + return JIM_OK; |
| 18771 | 20399 | |
| 18772 | 20400 | case INFO_BODY: |
| 18773 | 20401 | case INFO_STATICS: |
| 18774 | 20402 | case INFO_ARGS:{ |
| 18775 | 20403 | Jim_Cmd *cmdPtr; |
| 18776 | 20404 | |
| 18777 | | - if (argc != 3) { |
| 18778 | | - Jim_WrongNumArgs(interp, 2, argv, "procname"); |
| 18779 | | - return JIM_ERR; |
| 18780 | | - } |
| 18781 | 20405 | if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { |
| 18782 | 20406 | return JIM_ERR; |
| 18783 | 20407 | } |
| 18784 | 20408 | if (!cmdPtr->isproc) { |
| 18785 | 20409 | Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]); |
| 18786 | 20410 | return JIM_ERR; |
| 18787 | 20411 | } |
| 18788 | | - switch (cmd) { |
| 20412 | + switch (option) { |
| 20413 | +#ifdef JIM_NO_INTROSPECTION |
| 20414 | + default: |
| 20415 | + Jim_SetResultString(interp, "unsupported", -1); |
| 20416 | + return JIM_ERR; |
| 20417 | +#else |
| 18789 | 20418 | case INFO_BODY: |
| 18790 | 20419 | Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr); |
| 18791 | 20420 | break; |
| 18792 | 20421 | case INFO_ARGS: |
| 18793 | 20422 | Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); |
| 18794 | 20423 | break; |
| 20424 | +#endif |
| 18795 | 20425 | case INFO_STATICS: |
| 18796 | 20426 | if (cmdPtr->u.proc.staticVars) { |
| 18797 | 20427 | Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, |
| 18798 | 20428 | NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES)); |
| 18799 | 20429 | } |
| 18800 | 20430 | break; |
| 18801 | 20431 | } |
| 18802 | | - break; |
| 20432 | + return JIM_OK; |
| 18803 | 20433 | } |
| 18804 | 20434 | |
| 18805 | 20435 | case INFO_VERSION: |
| 18806 | 20436 | case INFO_PATCHLEVEL:{ |
| 18807 | 20437 | char buf[(JIM_INTEGER_SPACE * 2) + 1]; |
| 18808 | 20438 | |
| 18809 | 20439 | sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100); |
| 18810 | 20440 | Jim_SetResultString(interp, buf, -1); |
| 18811 | | - break; |
| 20441 | + return JIM_OK; |
| 18812 | 20442 | } |
| 18813 | 20443 | |
| 18814 | | - case INFO_COMPLETE: |
| 18815 | | - if (argc != 3 && argc != 4) { |
| 18816 | | - Jim_WrongNumArgs(interp, 2, argv, "script ?missing?"); |
| 18817 | | - return JIM_ERR; |
| 18818 | | - } |
| 18819 | | - else { |
| 20444 | + case INFO_COMPLETE: { |
| 18820 | 20445 | char missing; |
| 18821 | 20446 | |
| 18822 | 20447 | Jim_SetResultBool(interp, Jim_ScriptIsComplete(interp, argv[2], &missing)); |
| 18823 | 20448 | if (missing != ' ' && argc == 4) { |
| 18824 | 20449 | Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1)); |
| 18825 | 20450 | } |
| 20451 | + return JIM_OK; |
| 18826 | 20452 | } |
| 18827 | | - break; |
| 18828 | 20453 | |
| 18829 | 20454 | case INFO_HOSTNAME: |
| 18830 | 20455 | |
| 18831 | 20456 | return Jim_Eval(interp, "os.gethostname"); |
| 18832 | 20457 | |
| | @@ -18860,24 +20485,21 @@ |
| 18860 | 20485 | } |
| 18861 | 20486 | else { |
| 18862 | 20487 | Jim_SetResultString(interp, name, -1); |
| 18863 | 20488 | } |
| 18864 | 20489 | } |
| 18865 | | - else { |
| 18866 | | - Jim_WrongNumArgs(interp, 2, argv, "?code?"); |
| 18867 | | - return JIM_ERR; |
| 18868 | | - } |
| 18869 | | - break; |
| 20490 | + return JIM_OK; |
| 18870 | 20491 | case INFO_REFERENCES: |
| 18871 | 20492 | #ifdef JIM_REFERENCES |
| 18872 | 20493 | return JimInfoReferences(interp, argc, argv); |
| 18873 | 20494 | #else |
| 18874 | 20495 | Jim_SetResultString(interp, "not supported", -1); |
| 18875 | 20496 | return JIM_ERR; |
| 18876 | 20497 | #endif |
| 20498 | + default: |
| 20499 | + abort(); |
| 18877 | 20500 | } |
| 18878 | | - return JIM_OK; |
| 18879 | 20501 | } |
| 18880 | 20502 | |
| 18881 | 20503 | |
| 18882 | 20504 | static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18883 | 20505 | { |
| | @@ -19145,11 +20767,10 @@ |
| 19145 | 20767 | Jim_SetResult(interp, argv[1]); |
| 19146 | 20768 | if (argc == 3) { |
| 19147 | 20769 | JimSetStackTrace(interp, argv[2]); |
| 19148 | 20770 | return JIM_ERR; |
| 19149 | 20771 | } |
| 19150 | | - interp->addStackTrace++; |
| 19151 | 20772 | return JIM_ERR; |
| 19152 | 20773 | } |
| 19153 | 20774 | |
| 19154 | 20775 | |
| 19155 | 20776 | static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| | @@ -19168,26 +20789,27 @@ |
| 19168 | 20789 | |
| 19169 | 20790 | |
| 19170 | 20791 | static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19171 | 20792 | { |
| 19172 | 20793 | Jim_Obj *objPtr; |
| 19173 | | - long count; |
| 20794 | + jim_wide count; |
| 19174 | 20795 | |
| 19175 | | - if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) { |
| 20796 | + if (argc < 2 || Jim_GetWideExpr(interp, argv[1], &count) != JIM_OK || count < 0) { |
| 19176 | 20797 | Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?"); |
| 19177 | 20798 | return JIM_ERR; |
| 19178 | 20799 | } |
| 19179 | | - |
| 19180 | 20800 | if (count == 0 || argc == 2) { |
| 20801 | + Jim_SetEmptyResult(interp); |
| 19181 | 20802 | return JIM_OK; |
| 19182 | 20803 | } |
| 19183 | 20804 | |
| 19184 | 20805 | argc -= 2; |
| 19185 | 20806 | argv += 2; |
| 19186 | 20807 | |
| 19187 | | - objPtr = Jim_NewListObj(interp, argv, argc); |
| 19188 | | - while (--count) { |
| 20808 | + objPtr = Jim_NewListObj(interp, NULL, 0); |
| 20809 | + ListEnsureLength(objPtr, argc * count); |
| 20810 | + while (count--) { |
| 19189 | 20811 | ListInsertElements(objPtr, -1, argc, argv); |
| 19190 | 20812 | } |
| 19191 | 20813 | |
| 19192 | 20814 | Jim_SetResult(interp, objPtr); |
| 19193 | 20815 | return JIM_OK; |
| | @@ -19243,11 +20865,11 @@ |
| 19243 | 20865 | |
| 19244 | 20866 | Jim_SetResult(interp, listObjPtr); |
| 19245 | 20867 | return JIM_OK; |
| 19246 | 20868 | } |
| 19247 | 20869 | |
| 19248 | | - if (argc < 2) { |
| 20870 | + if (argc > 3) { |
| 19249 | 20871 | Jim_WrongNumArgs(interp, 1, argv, "varName ?default?"); |
| 19250 | 20872 | return JIM_ERR; |
| 19251 | 20873 | } |
| 19252 | 20874 | key = Jim_String(argv[1]); |
| 19253 | 20875 | val = getenv(key); |
| | @@ -19286,12 +20908,13 @@ |
| 19286 | 20908 | if (argc != 2) { |
| 19287 | 20909 | Jim_WrongNumArgs(interp, 1, argv, "list"); |
| 19288 | 20910 | return JIM_ERR; |
| 19289 | 20911 | } |
| 19290 | 20912 | JimListGetElements(interp, argv[1], &len, &ele); |
| 19291 | | - len--; |
| 19292 | 20913 | revObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 20914 | + ListEnsureLength(revObjPtr, len); |
| 20915 | + len--; |
| 19293 | 20916 | while (len >= 0) |
| 19294 | 20917 | ListAppendElement(revObjPtr, ele[len--]); |
| 19295 | 20918 | Jim_SetResult(interp, revObjPtr); |
| 19296 | 20919 | return JIM_OK; |
| 19297 | 20920 | } |
| | @@ -19329,25 +20952,26 @@ |
| 19329 | 20952 | if (argc < 2 || argc > 4) { |
| 19330 | 20953 | Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?"); |
| 19331 | 20954 | return JIM_ERR; |
| 19332 | 20955 | } |
| 19333 | 20956 | if (argc == 2) { |
| 19334 | | - if (Jim_GetWide(interp, argv[1], &end) != JIM_OK) |
| 19335 | | - return JIM_ERR; |
| 19336 | | - } |
| 19337 | | - else { |
| 19338 | | - if (Jim_GetWide(interp, argv[1], &start) != JIM_OK || |
| 19339 | | - Jim_GetWide(interp, argv[2], &end) != JIM_OK) |
| 19340 | | - return JIM_ERR; |
| 19341 | | - if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK) |
| 20957 | + if (Jim_GetWideExpr(interp, argv[1], &end) != JIM_OK) |
| 20958 | + return JIM_ERR; |
| 20959 | + } |
| 20960 | + else { |
| 20961 | + if (Jim_GetWideExpr(interp, argv[1], &start) != JIM_OK || |
| 20962 | + Jim_GetWideExpr(interp, argv[2], &end) != JIM_OK) |
| 20963 | + return JIM_ERR; |
| 20964 | + if (argc == 4 && Jim_GetWideExpr(interp, argv[3], &step) != JIM_OK) |
| 19342 | 20965 | return JIM_ERR; |
| 19343 | 20966 | } |
| 19344 | 20967 | if ((len = JimRangeLen(start, end, step)) == -1) { |
| 19345 | 20968 | Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1); |
| 19346 | 20969 | return JIM_ERR; |
| 19347 | 20970 | } |
| 19348 | 20971 | objPtr = Jim_NewListObj(interp, NULL, 0); |
| 20972 | + ListEnsureLength(objPtr, len); |
| 19349 | 20973 | for (i = 0; i < len; i++) |
| 19350 | 20974 | ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step)); |
| 19351 | 20975 | Jim_SetResult(interp, objPtr); |
| 19352 | 20976 | return JIM_OK; |
| 19353 | 20977 | } |
| | @@ -19362,15 +20986,15 @@ |
| 19362 | 20986 | return JIM_ERR; |
| 19363 | 20987 | } |
| 19364 | 20988 | if (argc == 1) { |
| 19365 | 20989 | max = JIM_WIDE_MAX; |
| 19366 | 20990 | } else if (argc == 2) { |
| 19367 | | - if (Jim_GetWide(interp, argv[1], &max) != JIM_OK) |
| 20991 | + if (Jim_GetWideExpr(interp, argv[1], &max) != JIM_OK) |
| 19368 | 20992 | return JIM_ERR; |
| 19369 | 20993 | } else if (argc == 3) { |
| 19370 | | - if (Jim_GetWide(interp, argv[1], &min) != JIM_OK || |
| 19371 | | - Jim_GetWide(interp, argv[2], &max) != JIM_OK) |
| 20994 | + if (Jim_GetWideExpr(interp, argv[1], &min) != JIM_OK || |
| 20995 | + Jim_GetWideExpr(interp, argv[2], &max) != JIM_OK) |
| 19372 | 20996 | return JIM_ERR; |
| 19373 | 20997 | } |
| 19374 | 20998 | len = max-min; |
| 19375 | 20999 | if (len < 0) { |
| 19376 | 21000 | Jim_SetResultString(interp, "Invalid arguments (max < min)", -1); |
| | @@ -19417,25 +21041,27 @@ |
| 19417 | 21041 | {"lappend", Jim_LappendCoreCommand}, |
| 19418 | 21042 | {"linsert", Jim_LinsertCoreCommand}, |
| 19419 | 21043 | {"lreplace", Jim_LreplaceCoreCommand}, |
| 19420 | 21044 | {"lsort", Jim_LsortCoreCommand}, |
| 19421 | 21045 | {"append", Jim_AppendCoreCommand}, |
| 19422 | | - {"debug", Jim_DebugCoreCommand}, |
| 19423 | 21046 | {"eval", Jim_EvalCoreCommand}, |
| 19424 | 21047 | {"uplevel", Jim_UplevelCoreCommand}, |
| 19425 | 21048 | {"expr", Jim_ExprCoreCommand}, |
| 19426 | 21049 | {"break", Jim_BreakCoreCommand}, |
| 19427 | 21050 | {"continue", Jim_ContinueCoreCommand}, |
| 19428 | 21051 | {"proc", Jim_ProcCoreCommand}, |
| 21052 | + {"xtrace", Jim_XtraceCoreCommand}, |
| 19429 | 21053 | {"concat", Jim_ConcatCoreCommand}, |
| 19430 | 21054 | {"return", Jim_ReturnCoreCommand}, |
| 19431 | 21055 | {"upvar", Jim_UpvarCoreCommand}, |
| 19432 | 21056 | {"global", Jim_GlobalCoreCommand}, |
| 19433 | 21057 | {"string", Jim_StringCoreCommand}, |
| 19434 | 21058 | {"time", Jim_TimeCoreCommand}, |
| 21059 | + {"timerate", Jim_TimeRateCoreCommand}, |
| 19435 | 21060 | {"exit", Jim_ExitCoreCommand}, |
| 19436 | 21061 | {"catch", Jim_CatchCoreCommand}, |
| 21062 | + {"try", Jim_TryCoreCommand}, |
| 19437 | 21063 | #ifdef JIM_REFERENCES |
| 19438 | 21064 | {"ref", Jim_RefCoreCommand}, |
| 19439 | 21065 | {"getref", Jim_GetrefCoreCommand}, |
| 19440 | 21066 | {"setref", Jim_SetrefCoreCommand}, |
| 19441 | 21067 | {"finalize", Jim_FinalizeCoreCommand}, |
| | @@ -19460,10 +21086,11 @@ |
| 19460 | 21086 | {"rand", Jim_RandCoreCommand}, |
| 19461 | 21087 | {"tailcall", Jim_TailcallCoreCommand}, |
| 19462 | 21088 | {"local", Jim_LocalCoreCommand}, |
| 19463 | 21089 | {"upcall", Jim_UpcallCoreCommand}, |
| 19464 | 21090 | {"apply", Jim_ApplyCoreCommand}, |
| 21091 | + {"stacktrace", Jim_StacktraceCoreCommand}, |
| 19465 | 21092 | {NULL, NULL}, |
| 19466 | 21093 | }; |
| 19467 | 21094 | |
| 19468 | 21095 | void Jim_RegisterCoreCommands(Jim_Interp *interp) |
| 19469 | 21096 | { |
| | @@ -19687,22 +21314,30 @@ |
| 19687 | 21314 | for (i = 0; i < nobjparam; i++) { |
| 19688 | 21315 | Jim_DecrRefCount(interp, objparam[i]); |
| 19689 | 21316 | } |
| 19690 | 21317 | } |
| 19691 | 21318 | |
| 21319 | +int Jim_CheckAbiVersion(Jim_Interp *interp, int abi_version) |
| 21320 | +{ |
| 21321 | + if (abi_version != JIM_ABI_VERSION) { |
| 21322 | + Jim_SetResultString(interp, "ABI version mismatch", -1); |
| 21323 | + return JIM_ERR; |
| 21324 | + } |
| 21325 | + return JIM_OK; |
| 21326 | +} |
| 21327 | + |
| 19692 | 21328 | |
| 19693 | 21329 | #ifndef jim_ext_package |
| 19694 | 21330 | int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) |
| 19695 | 21331 | { |
| 19696 | 21332 | return JIM_OK; |
| 19697 | 21333 | } |
| 19698 | 21334 | #endif |
| 19699 | 21335 | #ifndef jim_ext_aio |
| 19700 | | -FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) |
| 21336 | +int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) |
| 19701 | 21337 | { |
| 19702 | | - Jim_SetResultString(interp, "aio not enabled", -1); |
| 19703 | | - return NULL; |
| 21338 | + return -1; |
| 19704 | 21339 | } |
| 19705 | 21340 | #endif |
| 19706 | 21341 | |
| 19707 | 21342 | |
| 19708 | 21343 | #include <stdio.h> |
| | @@ -19717,34 +21352,45 @@ |
| 19717 | 21352 | |
| 19718 | 21353 | static const jim_subcmd_type dummy_subcmd = { |
| 19719 | 21354 | "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN |
| 19720 | 21355 | }; |
| 19721 | 21356 | |
| 19722 | | -static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep) |
| 21357 | +static Jim_Obj *subcmd_cmd_list(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep) |
| 19723 | 21358 | { |
| 19724 | | - const char *s = ""; |
| 21359 | + |
| 21360 | + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 21361 | + Jim_Obj *sortCmd[2]; |
| 19725 | 21362 | |
| 19726 | 21363 | for (; ct->cmd; ct++) { |
| 19727 | 21364 | if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { |
| 19728 | | - Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL); |
| 19729 | | - s = sep; |
| 21365 | + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, ct->cmd, -1)); |
| 19730 | 21366 | } |
| 19731 | 21367 | } |
| 21368 | + |
| 21369 | + |
| 21370 | + sortCmd[0] = Jim_NewStringObj(interp, "lsort", -1); |
| 21371 | + sortCmd[1] = listObj; |
| 21372 | + |
| 21373 | + if (Jim_EvalObjVector(interp, 2, sortCmd) == JIM_OK) { |
| 21374 | + return Jim_ListJoin(interp, Jim_GetResult(interp), sep, strlen(sep)); |
| 21375 | + } |
| 21376 | + |
| 21377 | + return Jim_GetResult(interp); |
| 19732 | 21378 | } |
| 19733 | 21379 | |
| 19734 | 21380 | static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, |
| 19735 | 21381 | Jim_Obj *cmd, Jim_Obj *subcmd) |
| 19736 | 21382 | { |
| 19737 | | - Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd); |
| 19738 | | - add_commands(interp, command_table, ", "); |
| 21383 | + Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be %#s", cmd, type, |
| 21384 | + subcmd, subcmd_cmd_list(interp, command_table, ", ")); |
| 19739 | 21385 | } |
| 19740 | 21386 | |
| 19741 | 21387 | static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, |
| 19742 | 21388 | Jim_Obj *const *argv) |
| 19743 | 21389 | { |
| 19744 | | - Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]); |
| 19745 | | - add_commands(interp, command_table, ", "); |
| 21390 | + Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: %#s", |
| 21391 | + argv[0], subcmd_cmd_list(interp, command_table, ", ")); |
| 19746 | 21392 | } |
| 19747 | 21393 | |
| 19748 | 21394 | static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) |
| 19749 | 21395 | { |
| 19750 | 21396 | if (cmd) { |
| | @@ -19754,14 +21400,14 @@ |
| 19754 | 21400 | if (ct->args && *ct->args) { |
| 19755 | 21401 | Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL); |
| 19756 | 21402 | } |
| 19757 | 21403 | } |
| 19758 | 21404 | |
| 19759 | | -static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) |
| 21405 | +void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *subcmd) |
| 19760 | 21406 | { |
| 19761 | 21407 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19762 | | - add_cmd_usage(interp, command_table, subcmd); |
| 21408 | + add_cmd_usage(interp, ct, subcmd); |
| 19763 | 21409 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19764 | 21410 | } |
| 19765 | 21411 | |
| 19766 | 21412 | static const Jim_ObjType subcmdLookupObjType = { |
| 19767 | 21413 | "subcmd-lookup", |
| | @@ -19778,10 +21424,11 @@ |
| 19778 | 21424 | const jim_subcmd_type *partial = 0; |
| 19779 | 21425 | int cmdlen; |
| 19780 | 21426 | Jim_Obj *cmd; |
| 19781 | 21427 | const char *cmdstr; |
| 19782 | 21428 | int help = 0; |
| 21429 | + int argsok = 1; |
| 19783 | 21430 | |
| 19784 | 21431 | if (argc < 2) { |
| 19785 | 21432 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n" |
| 19786 | 21433 | "Use \"%#s -help ?command?\" for help", argv[0], argv[0]); |
| 19787 | 21434 | return 0; |
| | @@ -19810,13 +21457,11 @@ |
| 19810 | 21457 | cmd = argv[2]; |
| 19811 | 21458 | } |
| 19812 | 21459 | |
| 19813 | 21460 | |
| 19814 | 21461 | if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { |
| 19815 | | - |
| 19816 | | - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19817 | | - add_commands(interp, command_table, " "); |
| 21462 | + Jim_SetResult(interp, subcmd_cmd_list(interp, command_table, " ")); |
| 19818 | 21463 | return &dummy_subcmd; |
| 19819 | 21464 | } |
| 19820 | 21465 | |
| 19821 | 21466 | cmdstr = Jim_GetString(cmd, &cmdlen); |
| 19822 | 21467 | |
| | @@ -19870,11 +21515,22 @@ |
| 19870 | 21515 | cmd->internalRep.ptrIntValue.ptr = (void *)command_table; |
| 19871 | 21516 | cmd->internalRep.ptrIntValue.int1 = ct - command_table; |
| 19872 | 21517 | |
| 19873 | 21518 | found: |
| 19874 | 21519 | |
| 19875 | | - if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { |
| 21520 | + |
| 21521 | + if (argc - 2 < ct->minargs) { |
| 21522 | + argsok = 0; |
| 21523 | + } |
| 21524 | + else if (ct->maxargs >= 0 && argc - 2 > ct->maxargs) { |
| 21525 | + argsok = 0; |
| 21526 | + } |
| 21527 | + else if (ct->maxargs < -1 && (argc - 2) % -ct->maxargs != 0) { |
| 21528 | + |
| 21529 | + argsok = 0; |
| 21530 | + } |
| 21531 | + if (!argsok) { |
| 19876 | 21532 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19877 | 21533 | |
| 19878 | 21534 | add_cmd_usage(interp, ct, argv[0]); |
| 19879 | 21535 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19880 | 21536 | |
| | @@ -19895,11 +21551,11 @@ |
| 19895 | 21551 | } |
| 19896 | 21552 | else { |
| 19897 | 21553 | ret = ct->function(interp, argc - 2, argv + 2); |
| 19898 | 21554 | } |
| 19899 | 21555 | if (ret < 0) { |
| 19900 | | - set_wrong_args(interp, ct, argv[0]); |
| 21556 | + Jim_SubCmdArgError(interp, ct, argv[0]); |
| 19901 | 21557 | ret = JIM_ERR; |
| 19902 | 21558 | } |
| 19903 | 21559 | } |
| 19904 | 21560 | return ret; |
| 19905 | 21561 | } |
| | @@ -19946,10 +21602,11 @@ |
| 19946 | 21602 | } |
| 19947 | 21603 | } |
| 19948 | 21604 | |
| 19949 | 21605 | #include <ctype.h> |
| 19950 | 21606 | #include <string.h> |
| 21607 | +#include <stdio.h> |
| 19951 | 21608 | |
| 19952 | 21609 | |
| 19953 | 21610 | #define JIM_INTEGER_SPACE 24 |
| 19954 | 21611 | #define MAX_FLOAT_WIDTH 320 |
| 19955 | 21612 | |
| | @@ -20192,11 +21849,11 @@ |
| 20192 | 21849 | } |
| 20193 | 21850 | |
| 20194 | 21851 | j = 0; |
| 20195 | 21852 | for (i = length; i > 0; ) { |
| 20196 | 21853 | i--; |
| 20197 | | - if (w & ((unsigned jim_wide)1 << i)) { |
| 21854 | + if (w & ((unsigned jim_wide)1 << i)) { |
| 20198 | 21855 | num_buffer[j++] = '1'; |
| 20199 | 21856 | } |
| 20200 | 21857 | else if (j || i == 0) { |
| 20201 | 21858 | num_buffer[j++] = '0'; |
| 20202 | 21859 | } |
| | @@ -20428,11 +22085,11 @@ |
| 20428 | 22085 | n++; |
| 20429 | 22086 | } |
| 20430 | 22087 | return n; |
| 20431 | 22088 | } |
| 20432 | 22089 | |
| 20433 | | -int regcomp(regex_t *preg, const char *exp, int cflags) |
| 22090 | +int jim_regcomp(regex_t *preg, const char *exp, int cflags) |
| 20434 | 22091 | { |
| 20435 | 22092 | int scan; |
| 20436 | 22093 | int longest; |
| 20437 | 22094 | unsigned len; |
| 20438 | 22095 | int flags; |
| | @@ -20843,11 +22500,11 @@ |
| 20843 | 22500 | if (*pattern == ']' || *pattern == '-') { |
| 20844 | 22501 | reg_addrange(preg, *pattern, *pattern); |
| 20845 | 22502 | pattern++; |
| 20846 | 22503 | } |
| 20847 | 22504 | |
| 20848 | | - while (*pattern && *pattern != ']') { |
| 22505 | + while (*pattern != ']') { |
| 20849 | 22506 | |
| 20850 | 22507 | int start; |
| 20851 | 22508 | int end; |
| 20852 | 22509 | |
| 20853 | 22510 | enum { |
| | @@ -20854,10 +22511,15 @@ |
| 20854 | 22511 | CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, |
| 20855 | 22512 | CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, |
| 20856 | 22513 | CC_NUM |
| 20857 | 22514 | }; |
| 20858 | 22515 | int cc; |
| 22516 | + |
| 22517 | + if (!*pattern) { |
| 22518 | + preg->err = REG_ERR_UNMATCHED_BRACKET; |
| 22519 | + return 0; |
| 22520 | + } |
| 20859 | 22521 | |
| 20860 | 22522 | pattern += reg_utf8_tounicode_case(pattern, &start, nocase); |
| 20861 | 22523 | if (start == '\\') { |
| 20862 | 22524 | |
| 20863 | 22525 | switch (*pattern) { |
| | @@ -20878,10 +22540,14 @@ |
| 20878 | 22540 | pattern += reg_decode_escape(pattern, &start); |
| 20879 | 22541 | if (start == 0) { |
| 20880 | 22542 | preg->err = REG_ERR_NULL_CHAR; |
| 20881 | 22543 | return 0; |
| 20882 | 22544 | } |
| 22545 | + if (start == '\\' && *pattern == 0) { |
| 22546 | + preg->err = REG_ERR_INVALID_ESCAPE; |
| 22547 | + return 0; |
| 22548 | + } |
| 20883 | 22549 | } |
| 20884 | 22550 | if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { |
| 20885 | 22551 | |
| 20886 | 22552 | pattern += utf8_tounicode(pattern, &end); |
| 20887 | 22553 | pattern += reg_utf8_tounicode_case(pattern, &end, nocase); |
| | @@ -20888,10 +22554,14 @@ |
| 20888 | 22554 | if (end == '\\') { |
| 20889 | 22555 | pattern += reg_decode_escape(pattern, &end); |
| 20890 | 22556 | if (end == 0) { |
| 20891 | 22557 | preg->err = REG_ERR_NULL_CHAR; |
| 20892 | 22558 | return 0; |
| 22559 | + } |
| 22560 | + if (end == '\\' && *pattern == 0) { |
| 22561 | + preg->err = REG_ERR_INVALID_ESCAPE; |
| 22562 | + return 0; |
| 20893 | 22563 | } |
| 20894 | 22564 | } |
| 20895 | 22565 | |
| 20896 | 22566 | reg_addrange(preg, start, end); |
| 20897 | 22567 | continue; |
| | @@ -20903,10 +22573,14 @@ |
| 20903 | 22573 | }; |
| 20904 | 22574 | |
| 20905 | 22575 | for (cc = 0; cc < CC_NUM; cc++) { |
| 20906 | 22576 | n = strlen(character_class[cc]); |
| 20907 | 22577 | if (strncmp(pattern, character_class[cc], n) == 0) { |
| 22578 | + if (pattern[n] != ']') { |
| 22579 | + preg->err = REG_ERR_UNMATCHED_BRACKET; |
| 22580 | + return 0; |
| 22581 | + } |
| 20908 | 22582 | |
| 20909 | 22583 | pattern += n + 1; |
| 20910 | 22584 | break; |
| 20911 | 22585 | } |
| 20912 | 22586 | } |
| | @@ -20993,11 +22667,11 @@ |
| 20993 | 22667 | return 0; |
| 20994 | 22668 | case '\\': |
| 20995 | 22669 | ch = *preg->regparse++; |
| 20996 | 22670 | switch (ch) { |
| 20997 | 22671 | case '\0': |
| 20998 | | - preg->err = REG_ERR_TRAILING_BACKSLASH; |
| 22672 | + preg->err = REG_ERR_INVALID_ESCAPE; |
| 20999 | 22673 | return 0; |
| 21000 | 22674 | case 'A': |
| 21001 | 22675 | ret = regnode(preg, BOLX); |
| 21002 | 22676 | break; |
| 21003 | 22677 | case 'Z': |
| | @@ -21180,11 +22854,11 @@ |
| 21180 | 22854 | |
| 21181 | 22855 | static int regtry(regex_t *preg, const char *string ); |
| 21182 | 22856 | static int regmatch(regex_t *preg, int prog); |
| 21183 | 22857 | static int regrepeat(regex_t *preg, int p, int max); |
| 21184 | 22858 | |
| 21185 | | -int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) |
| 22859 | +int jim_regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) |
| 21186 | 22860 | { |
| 21187 | 22861 | const char *s; |
| 21188 | 22862 | int scan; |
| 21189 | 22863 | |
| 21190 | 22864 | |
| | @@ -21521,11 +23195,11 @@ |
| 21521 | 23195 | break; |
| 21522 | 23196 | case WORDZ: |
| 21523 | 23197 | |
| 21524 | 23198 | if (preg->reginput > preg->regbol) { |
| 21525 | 23199 | |
| 21526 | | - if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { |
| 23200 | + if (reg_iseol(preg, c) || !(isalnum(UCHAR(c)) || c == '_')) { |
| 21527 | 23201 | c = preg->reginput[-1]; |
| 21528 | 23202 | |
| 21529 | 23203 | if (isalnum(UCHAR(c)) || c == '_') { |
| 21530 | 23204 | break; |
| 21531 | 23205 | } |
| | @@ -21617,10 +23291,12 @@ |
| 21617 | 23291 | preg->pmatch[no].rm_eo = save - preg->start; |
| 21618 | 23292 | } |
| 21619 | 23293 | } |
| 21620 | 23294 | return(1); |
| 21621 | 23295 | } |
| 23296 | + |
| 23297 | + preg->reginput = save; |
| 21622 | 23298 | return(0); |
| 21623 | 23299 | } |
| 21624 | 23300 | return REG_ERR_INTERNAL; |
| 21625 | 23301 | } |
| 21626 | 23302 | |
| | @@ -21640,14 +23316,13 @@ |
| 21640 | 23316 | |
| 21641 | 23317 | scan = preg->reginput; |
| 21642 | 23318 | opnd = OPERAND(p); |
| 21643 | 23319 | switch (OP(preg, p)) { |
| 21644 | 23320 | case ANY: |
| 21645 | | - |
| 21646 | 23321 | while (!reg_iseol(preg, *scan) && count < max) { |
| 21647 | 23322 | count++; |
| 21648 | | - scan++; |
| 23323 | + scan += utf8_charlen(*scan); |
| 21649 | 23324 | } |
| 21650 | 23325 | break; |
| 21651 | 23326 | case EXACTLY: |
| 21652 | 23327 | while (count < max) { |
| 21653 | 23328 | n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); |
| | @@ -21724,11 +23399,11 @@ |
| 21724 | 23399 | } |
| 21725 | 23400 | return 2; |
| 21726 | 23401 | } |
| 21727 | 23402 | |
| 21728 | 23403 | |
| 21729 | | -size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 23404 | +size_t jim_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) |
| 21730 | 23405 | { |
| 21731 | 23406 | static const char *error_strings[] = { |
| 21732 | 23407 | "success", |
| 21733 | 23408 | "no match", |
| 21734 | 23409 | "bad pattern", |
| | @@ -21743,13 +23418,14 @@ |
| 21743 | 23418 | "extra characters", |
| 21744 | 23419 | "*+ of empty atom", |
| 21745 | 23420 | "nested count", |
| 21746 | 23421 | "internal error", |
| 21747 | 23422 | "count follows nothing", |
| 21748 | | - "trailing backslash", |
| 23423 | + "invalid escape \\ sequence", |
| 21749 | 23424 | "corrupted program", |
| 21750 | 23425 | "contains null char", |
| 23426 | + "brackets [] not balanced", |
| 21751 | 23427 | }; |
| 21752 | 23428 | const char *err; |
| 21753 | 23429 | |
| 21754 | 23430 | if (errcode < 0 || errcode >= REG_ERR_NUM) { |
| 21755 | 23431 | err = "Bad error code"; |
| | @@ -21759,11 +23435,11 @@ |
| 21759 | 23435 | } |
| 21760 | 23436 | |
| 21761 | 23437 | return snprintf(errbuf, errbuf_size, "%s", err); |
| 21762 | 23438 | } |
| 21763 | 23439 | |
| 21764 | | -void regfree(regex_t *preg) |
| 23440 | +void jim_regfree(regex_t *preg) |
| 21765 | 23441 | { |
| 21766 | 23442 | free(preg->program); |
| 21767 | 23443 | } |
| 21768 | 23444 | |
| 21769 | 23445 | #endif |
| | @@ -21856,20 +23532,46 @@ |
| 21856 | 23532 | case ERROR_DIRECTORY: return ENOTDIR; |
| 21857 | 23533 | } |
| 21858 | 23534 | return EINVAL; |
| 21859 | 23535 | } |
| 21860 | 23536 | |
| 21861 | | -pidtype waitpid(pidtype pid, int *status, int nohang) |
| 23537 | +long JimProcessPid(phandle_t pid) |
| 23538 | +{ |
| 23539 | + if (pid == INVALID_HANDLE_VALUE) { |
| 23540 | + return -1; |
| 23541 | + } |
| 23542 | + return GetProcessId(pid); |
| 23543 | +} |
| 23544 | + |
| 23545 | +phandle_t JimWaitPid(long pid, int *status, int nohang) |
| 23546 | +{ |
| 23547 | + if (pid > 0) { |
| 23548 | + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid); |
| 23549 | + if (h) { |
| 23550 | + long pid = waitpid(h, status, nohang); |
| 23551 | + CloseHandle(h); |
| 23552 | + if (pid > 0) { |
| 23553 | + return h; |
| 23554 | + } |
| 23555 | + } |
| 23556 | + } |
| 23557 | + return JIM_BAD_PHANDLE; |
| 23558 | +} |
| 23559 | + |
| 23560 | +long waitpid(phandle_t phandle, int *status, int nohang) |
| 21862 | 23561 | { |
| 21863 | | - DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); |
| 23562 | + long pid; |
| 23563 | + DWORD ret = WaitForSingleObject(phandle, nohang ? 0 : INFINITE); |
| 21864 | 23564 | if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { |
| 21865 | 23565 | |
| 21866 | | - return JIM_BAD_PID; |
| 23566 | + return -1; |
| 21867 | 23567 | } |
| 21868 | | - GetExitCodeProcess(pid, &ret); |
| 23568 | + GetExitCodeProcess(phandle, &ret); |
| 21869 | 23569 | *status = ret; |
| 21870 | | - CloseHandle(pid); |
| 23570 | + |
| 23571 | + pid = GetProcessId(phandle); |
| 23572 | + CloseHandle(phandle); |
| 21871 | 23573 | return pid; |
| 21872 | 23574 | } |
| 21873 | 23575 | |
| 21874 | 23576 | int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) |
| 21875 | 23577 | { |
| | @@ -21887,11 +23589,11 @@ |
| 21887 | 23589 | if (handle == INVALID_HANDLE_VALUE) { |
| 21888 | 23590 | goto error; |
| 21889 | 23591 | } |
| 21890 | 23592 | |
| 21891 | 23593 | Jim_SetResultString(interp, name, -1); |
| 21892 | | - return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT); |
| 23594 | + return _open_osfhandle((intptr_t)handle, _O_RDWR | _O_TEXT); |
| 21893 | 23595 | |
| 21894 | 23596 | error: |
| 21895 | 23597 | Jim_SetResultErrno(interp, name); |
| 21896 | 23598 | DeleteFile(name); |
| 21897 | 23599 | return -1; |
| | @@ -22125,10 +23827,11 @@ |
| 22125 | 23827 | return buf; |
| 22126 | 23828 | } |
| 22127 | 23829 | #ifndef JIM_BOOTSTRAP_LIB_ONLY |
| 22128 | 23830 | #include <errno.h> |
| 22129 | 23831 | #include <string.h> |
| 23832 | +#include <stdio.h> |
| 22130 | 23833 | |
| 22131 | 23834 | |
| 22132 | 23835 | #ifdef USE_LINENOISE |
| 22133 | 23836 | #ifdef HAVE_UNISTD_H |
| 22134 | 23837 | #include <unistd.h> |
| | @@ -22140,42 +23843,58 @@ |
| 22140 | 23843 | #else |
| 22141 | 23844 | #define MAX_LINE_LEN 512 |
| 22142 | 23845 | #endif |
| 22143 | 23846 | |
| 22144 | 23847 | #ifdef USE_LINENOISE |
| 23848 | +struct JimCompletionInfo { |
| 23849 | + Jim_Interp *interp; |
| 23850 | + Jim_Obj *completion_command; |
| 23851 | + Jim_Obj *hints_command; |
| 23852 | + |
| 23853 | +}; |
| 23854 | + |
| 23855 | +static struct JimCompletionInfo *JimGetCompletionInfo(Jim_Interp *interp); |
| 22145 | 23856 | static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata); |
| 22146 | 23857 | static const char completion_callback_assoc_key[] = "interactive-completion"; |
| 23858 | +static char *JimHintsCallback(const char *prefix, int *color, int *bold, void *userdata); |
| 23859 | +static void JimFreeHintsCallback(void *hint, void *userdata); |
| 22147 | 23860 | #endif |
| 22148 | 23861 | |
| 22149 | 23862 | char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt) |
| 22150 | 23863 | { |
| 22151 | 23864 | #ifdef USE_LINENOISE |
| 22152 | | - struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key); |
| 23865 | + struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp); |
| 22153 | 23866 | char *result; |
| 22154 | 23867 | Jim_Obj *objPtr; |
| 22155 | 23868 | long mlmode = 0; |
| 22156 | | - if (compinfo) { |
| 23869 | + if (compinfo->completion_command) { |
| 22157 | 23870 | linenoiseSetCompletionCallback(JimCompletionCallback, compinfo); |
| 22158 | 23871 | } |
| 23872 | + if (compinfo->hints_command) { |
| 23873 | + linenoiseSetHintsCallback(JimHintsCallback, compinfo); |
| 23874 | + linenoiseSetFreeHintsCallback(JimFreeHintsCallback); |
| 23875 | + } |
| 22159 | 23876 | objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE); |
| 22160 | 23877 | if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) { |
| 22161 | 23878 | linenoiseSetMultiLine(mlmode); |
| 22162 | 23879 | } |
| 22163 | 23880 | |
| 22164 | 23881 | result = linenoise(prompt); |
| 22165 | 23882 | |
| 22166 | 23883 | linenoiseSetCompletionCallback(NULL, NULL); |
| 23884 | + linenoiseSetHintsCallback(NULL, NULL); |
| 23885 | + linenoiseSetFreeHintsCallback(NULL); |
| 22167 | 23886 | return result; |
| 22168 | 23887 | #else |
| 22169 | 23888 | int len; |
| 22170 | | - char *line = malloc(MAX_LINE_LEN); |
| 23889 | + char *line = Jim_Alloc(MAX_LINE_LEN); |
| 22171 | 23890 | |
| 22172 | 23891 | fputs(prompt, stdout); |
| 22173 | 23892 | fflush(stdout); |
| 22174 | 23893 | |
| 22175 | 23894 | if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { |
| 22176 | | - free(line); |
| 23895 | + Jim_Free(line); |
| 22177 | 23896 | return NULL; |
| 22178 | 23897 | } |
| 22179 | 23898 | len = strlen(line); |
| 22180 | 23899 | if (len && line[len - 1] == '\n') { |
| 22181 | 23900 | line[len - 1] = '\0'; |
| | @@ -22224,23 +23943,33 @@ |
| 22224 | 23943 | printf("%4d %s\n", i + 1, history[i]); |
| 22225 | 23944 | } |
| 22226 | 23945 | #endif |
| 22227 | 23946 | } |
| 22228 | 23947 | |
| 23948 | +void Jim_HistorySetMaxLen(int length) |
| 23949 | +{ |
| 23950 | +#ifdef USE_LINENOISE |
| 23951 | + linenoiseHistorySetMaxLen(length); |
| 23952 | +#endif |
| 23953 | +} |
| 23954 | + |
| 23955 | +int Jim_HistoryGetMaxLen(void) |
| 23956 | +{ |
| 22229 | 23957 | #ifdef USE_LINENOISE |
| 22230 | | -struct JimCompletionInfo { |
| 22231 | | - Jim_Interp *interp; |
| 22232 | | - Jim_Obj *command; |
| 22233 | | -}; |
| 23958 | + return linenoiseHistoryGetMaxLen(); |
| 23959 | +#endif |
| 23960 | + return 0; |
| 23961 | +} |
| 22234 | 23962 | |
| 23963 | +#ifdef USE_LINENOISE |
| 22235 | 23964 | static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata) |
| 22236 | 23965 | { |
| 22237 | 23966 | struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata; |
| 22238 | 23967 | Jim_Obj *objv[2]; |
| 22239 | 23968 | int ret; |
| 22240 | 23969 | |
| 22241 | | - objv[0] = info->command; |
| 23970 | + objv[0] = info->completion_command; |
| 22242 | 23971 | objv[1] = Jim_NewStringObj(info->interp, prefix, -1); |
| 22243 | 23972 | |
| 22244 | 23973 | ret = Jim_EvalObjVector(info->interp, 2, objv); |
| 22245 | 23974 | |
| 22246 | 23975 | |
| | @@ -22251,38 +23980,106 @@ |
| 22251 | 23980 | for (i = 0; i < len; i++) { |
| 22252 | 23981 | linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i))); |
| 22253 | 23982 | } |
| 22254 | 23983 | } |
| 22255 | 23984 | } |
| 23985 | + |
| 23986 | +static char *JimHintsCallback(const char *prefix, int *color, int *bold, void *userdata) |
| 23987 | +{ |
| 23988 | + struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata; |
| 23989 | + Jim_Obj *objv[2]; |
| 23990 | + int ret; |
| 23991 | + char *result = NULL; |
| 23992 | + |
| 23993 | + objv[0] = info->hints_command; |
| 23994 | + objv[1] = Jim_NewStringObj(info->interp, prefix, -1); |
| 23995 | + |
| 23996 | + ret = Jim_EvalObjVector(info->interp, 2, objv); |
| 23997 | + |
| 23998 | + |
| 23999 | + if (ret == JIM_OK) { |
| 24000 | + Jim_Obj *listObj = Jim_GetResult(info->interp); |
| 24001 | + Jim_IncrRefCount(listObj); |
| 24002 | + |
| 24003 | + int len = Jim_ListLength(info->interp, listObj); |
| 24004 | + if (len >= 1) { |
| 24005 | + long x; |
| 24006 | + result = Jim_StrDup(Jim_String(Jim_ListGetIndex(info->interp, listObj, 0))); |
| 24007 | + if (len >= 2 && Jim_GetLong(info->interp, Jim_ListGetIndex(info->interp, listObj, 1), &x) == JIM_OK) { |
| 24008 | + *color = x; |
| 24009 | + } |
| 24010 | + if (len >= 3 && Jim_GetLong(info->interp, Jim_ListGetIndex(info->interp, listObj, 2), &x) == JIM_OK) { |
| 24011 | + *bold = x; |
| 24012 | + } |
| 24013 | + } |
| 24014 | + Jim_DecrRefCount(info->interp, listObj); |
| 24015 | + } |
| 24016 | + return result; |
| 24017 | +} |
| 24018 | + |
| 24019 | +static void JimFreeHintsCallback(void *hint, void *userdata) |
| 24020 | +{ |
| 24021 | + Jim_Free(hint); |
| 24022 | +} |
| 22256 | 24023 | |
| 22257 | 24024 | static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data) |
| 22258 | 24025 | { |
| 22259 | 24026 | struct JimCompletionInfo *compinfo = data; |
| 22260 | 24027 | |
| 22261 | | - Jim_DecrRefCount(interp, compinfo->command); |
| 24028 | + if (compinfo->completion_command) { |
| 24029 | + Jim_DecrRefCount(interp, compinfo->completion_command); |
| 24030 | + } |
| 24031 | + if (compinfo->hints_command) { |
| 24032 | + Jim_DecrRefCount(interp, compinfo->hints_command); |
| 24033 | + } |
| 22262 | 24034 | |
| 22263 | 24035 | Jim_Free(compinfo); |
| 22264 | 24036 | } |
| 22265 | | -#endif |
| 22266 | | - |
| 22267 | | -void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj) |
| 22268 | | -{ |
| 22269 | | -#ifdef USE_LINENOISE |
| 22270 | | - if (commandObj) { |
| 22271 | | - |
| 22272 | | - Jim_IncrRefCount(commandObj); |
| 22273 | | - } |
| 22274 | | - |
| 22275 | | - Jim_DeleteAssocData(interp, completion_callback_assoc_key); |
| 22276 | | - |
| 22277 | | - if (commandObj) { |
| 22278 | | - struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo)); |
| 24037 | + |
| 24038 | +static struct JimCompletionInfo *JimGetCompletionInfo(Jim_Interp *interp) |
| 24039 | +{ |
| 24040 | + struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key); |
| 24041 | + if (compinfo == NULL) { |
| 24042 | + compinfo = Jim_Alloc(sizeof(*compinfo)); |
| 22279 | 24043 | compinfo->interp = interp; |
| 22280 | | - compinfo->command = commandObj; |
| 22281 | | - |
| 24044 | + compinfo->completion_command = NULL; |
| 24045 | + compinfo->hints_command = NULL; |
| 22282 | 24046 | Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo); |
| 22283 | 24047 | } |
| 24048 | + return compinfo; |
| 24049 | +} |
| 24050 | +#endif |
| 24051 | + |
| 24052 | +void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *completionCommandObj) |
| 24053 | +{ |
| 24054 | +#ifdef USE_LINENOISE |
| 24055 | + struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp); |
| 24056 | + |
| 24057 | + if (completionCommandObj) { |
| 24058 | + |
| 24059 | + Jim_IncrRefCount(completionCommandObj); |
| 24060 | + } |
| 24061 | + if (compinfo->completion_command) { |
| 24062 | + Jim_DecrRefCount(interp, compinfo->completion_command); |
| 24063 | + } |
| 24064 | + compinfo->completion_command = completionCommandObj; |
| 24065 | +#endif |
| 24066 | +} |
| 24067 | + |
| 24068 | +void Jim_HistorySetHints(Jim_Interp *interp, Jim_Obj *hintsCommandObj) |
| 24069 | +{ |
| 24070 | +#ifdef USE_LINENOISE |
| 24071 | + struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp); |
| 24072 | + |
| 24073 | + if (hintsCommandObj) { |
| 24074 | + |
| 24075 | + Jim_IncrRefCount(hintsCommandObj); |
| 24076 | + } |
| 24077 | + if (compinfo->hints_command) { |
| 24078 | + Jim_DecrRefCount(interp, compinfo->hints_command); |
| 24079 | + } |
| 24080 | + compinfo->hints_command = hintsCommandObj; |
| 22284 | 24081 | #endif |
| 22285 | 24082 | } |
| 22286 | 24083 | |
| 22287 | 24084 | int Jim_InteractivePrompt(Jim_Interp *interp) |
| 22288 | 24085 | { |
| | @@ -22298,10 +24095,11 @@ |
| 22298 | 24095 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 22299 | 24096 | Jim_HistoryLoad(history_file); |
| 22300 | 24097 | } |
| 22301 | 24098 | |
| 22302 | 24099 | Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1)); |
| 24100 | + Jim_HistorySetHints(interp, Jim_NewStringObj(interp, "tcl::stdhint", -1)); |
| 22303 | 24101 | #endif |
| 22304 | 24102 | |
| 22305 | 24103 | printf("Welcome to Jim version %d.%d\n", |
| 22306 | 24104 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 22307 | 24105 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| | @@ -22344,11 +24142,11 @@ |
| 22344 | 24142 | if (Jim_Length(scriptObjPtr) != 0) { |
| 22345 | 24143 | |
| 22346 | 24144 | Jim_AppendString(interp, scriptObjPtr, "\n", 1); |
| 22347 | 24145 | } |
| 22348 | 24146 | Jim_AppendString(interp, scriptObjPtr, line, -1); |
| 22349 | | - free(line); |
| 24147 | + Jim_Free(line); |
| 22350 | 24148 | if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state)) |
| 22351 | 24149 | break; |
| 22352 | 24150 | |
| 22353 | 24151 | snprintf(prompt, sizeof(prompt), "%c> ", state); |
| 22354 | 24152 | } |
| | @@ -22374,11 +24172,14 @@ |
| 22374 | 24172 | if (retcode == JIM_ERR) { |
| 22375 | 24173 | Jim_MakeErrorMessage(interp); |
| 22376 | 24174 | } |
| 22377 | 24175 | result = Jim_GetString(Jim_GetResult(interp), &reslen); |
| 22378 | 24176 | if (reslen) { |
| 22379 | | - printf("%s\n", result); |
| 24177 | + if (fwrite(result, reslen, 1, stdout) == 0) { |
| 24178 | + |
| 24179 | + } |
| 24180 | + putchar('\n'); |
| 22380 | 24181 | } |
| 22381 | 24182 | } |
| 22382 | 24183 | out: |
| 22383 | 24184 | Jim_Free(history_file); |
| 22384 | 24185 | |
| | @@ -22476,11 +24277,16 @@ |
| 22476 | 24277 | if (argc > 2 && strcmp(argv[1], "-e") == 0) { |
| 22477 | 24278 | |
| 22478 | 24279 | JimSetArgv(interp, argc - 3, argv + 3); |
| 22479 | 24280 | retcode = Jim_Eval(interp, argv[2]); |
| 22480 | 24281 | if (retcode != JIM_ERR) { |
| 22481 | | - printf("%s\n", Jim_String(Jim_GetResult(interp))); |
| 24282 | + int len; |
| 24283 | + const char *msg = Jim_GetString(Jim_GetResult(interp), &len); |
| 24284 | + if (fwrite(msg, len, 1, stdout) == 0) { |
| 24285 | + |
| 24286 | + } |
| 24287 | + putchar('\n'); |
| 22482 | 24288 | } |
| 22483 | 24289 | } |
| 22484 | 24290 | else { |
| 22485 | 24291 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 22486 | 24292 | JimSetArgv(interp, argc - 2, argv + 2); |
| 22487 | 24293 | |