aboutsummaryrefslogtreecommitdiff
path: root/jim.c
AgeCommit message (Collapse)AuthorFilesLines
2021-01-02build: Fix bootstrap buildSteve Bennett1-2/+2
In order for make-bootstrap-jim to reliably match #ifndef...JIM_BOOTSTRAP with the corresponding #endif, a corresponding comment needs to be added after the #endif Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-27core: combine JimParseBoolean() and JimParseExprBoolean()Steve Bennett1-29/+34
Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26try: reimplement in CSteve Bennett1-36/+150
For speed and size, since it shares a lot of the same code with catch Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26loop: Allow start value to be omittedSteve Bennett1-7/+16
It is convenient to be able to do just: loop i 5 { body } Where the start value is 0. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26core: commands that take an index now use integer expressionsSteve Bennett1-25/+27
This means that instead of just [list index 2+1], we can now do [list index end-$n*2+1] This applies to: lindex, linsert, lreplace, lset, lrange, lsort, regexp, regsub string index,first,last,range Also add tests for both direct integer expressions and indexes. Still needs doc update. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26Jim_GetWideExpr() now evaluates "safe" expressionsSteve Bennett1-3/+22
This means that $variable references and [commands] are not expanded. This should mitigate security concerns when using the 'integer expression' feature. It means that you must do: string repeat a $i*4 Not: string repeat a {$i*4} Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26core: support integer expressions in various commandsSteve Bennett1-16/+38
For convenience, many commands now accept integer expressions rather than only simple integers. These are: loop, range, incr, string repeat, lrepeat, pack, unpack, rand This simplifies many cases where previously expr {} or $() was required. e.g. foreach i [range 4+1 2*$b] { ... } string repeat 2**$n a Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-26Revert "core: remove procargs and procbody from callframe"Steve Bennett1-0/+10
This reverts commit 6b287b9c6b6ec8fbc62f1cbaad48547cf5a4b65c. These are needed for reference counting. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-14core: remove procargs and procbody from callframeSteve Bennett1-10/+0
These stored the currently executing proc args and body (the same as are available via info args and info body), but were never used anywhere. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-12-11list, string: support any number of +/-n for indexSteve Bennett1-3/+4
It is especially convenient to add -1 for something like: lindex $list end-$BACK-1 or: string range $str $p $p+$len-1 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-11-16expr: TIP 582 - comments in expressionsSteve Bennett1-6/+15
Add support for comments in expressions Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-11-16core: fix minor compiler warningSteve Bennett1-1/+1
Fixes #183 Reported-by: Stuart Cassoff <stwo@bell.net> Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-11-14core: parser: fix for script with missing end quoteSteve Bennett1-0/+3
Ensure that 'info complete' returns 0 for a script is missing the end quote such as "abc$def Fixes #181 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-10-31core: change "newVal" to "value" in [lset] usageD. Bohdan1-1/+1
2020-10-31core: put space before "..." in "wrong # args" msgD. Bohdan1-2/+2
Resolves #173.
2020-10-05build: some systems have backtrace but not execinfo.hSteve Bennett1-2/+2
Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-09-27core: make unary "!" work with non-int booleansD. Bohdan1-1/+10
2020-09-23dict: add support for getwithdefault/getdefSteve Bennett1-3/+26
TIP 342 (https://core.tcl-lang.org/tips/doc/trunk/tip/342.md) Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-09-23core: implement string comparison operatorsD. Bohdan1-4/+30
TIP 461
2020-09-23core: implement 0d radix prefix for decimalD. Bohdan1-7/+10
TIP 472
2020-07-12string last: fix segfault with invalid indexSteve Bennett1-4/+5
[string last foo bar -1] gave segfault due to missing check for invalid index. Fixes #161 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-25core: dicts (and arrays) now preserve insertion orderSteve Bennett1-173/+406
Although the documentation has always stated that, like Tcl, insertion order of dictionaries was preserved, this has never been the case. Instead, dictionaries were implemented as simple hash tables that did not preserve order. Now, a new implementation of dictionaries preserves insertion order and has a number of other benefits. Instead of hashing keys and storing keys and values in the hash table, the keys and values are not stored in a separate table, exactly as lists are stored, with alternating key, value pairs. Iterating over the dictionary is exactly like iterating over a list, where the order is consistent. The hash table uses closed hashing rather than open hashing to avoid allocatation of hash entry structures. Instead a fixed (but expandable) hash table maps the key hash to the offset in the key/value table. This use of offsets means that if the key/value table grows, the offsets remain valid. Likewise, if the hash table needs to grow, the key, value table remains unchanged. In addition to the offset (which indexes to the value, and 0 means the hash table entry is unused), the original hash is stored in the hash table. This reduces the need for object comparisons on hash entry collisions. The collision resolution algorithm is the same as that used by Python: peturb >>= 5; idx = (5 * idx + 1 + peturb) & dict->sizemask; In order to reduce collisions, the hash table is expanded once it reaches half full. This is more conservative that Python where the table is expanded when it is two thirds full. Note that if a hash collision occurs and then the original entry that cased the hash collision is removed, we still need to continue iterating when searching for the new key. Don't stop at the now-empty slot. So these entries are marked with offset=-1 to indicate that they need to be skipped. In addition, the new faster hashing algorithm from Tcl 8.7 is used. This the hash for integers to be calculated efficiently without requiring them to be converted to string form first. This implementation is modelled largely on the Python dict implementation. Overall the performance should be an improvement over the current implementation, whilst preserving order. Dictionary creating and insertion should be faster as hash entries do not need to be allocated and resizing should be slightly faster. Entry lookup should be about the same, except may be faster for pure integer keys. Below are some indicative benchmarks. OLD NEW dict-create-1.1 Create empty dict 97.2ns . dict-create-1.2 Create small dict 440ns -27% dict-create-1.3 Create medium dict 1.54us -57% dict-create-1.4 Create large dict (int keys) 130us -80% dict-create-1.5 Create large dict (string keys) 143us -75% dict-set-1.1 Replace existing item 258ns -34% dict-set-1.2 Replace nonexistent item 365ns -49% dict-exists-1.1 Find existing item 55.7ns -5% dict-exists-1.2 Find nonexistent item 55.0ns -5% Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-13core: info commands failed to match under some conditionsSteve Bennett1-18/+27
Now that proc names are stored as-is in the commands table, info commands needs to take into account matching both foo::test and ::foo::test against the pattern ::foo::* Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-12core: tidy up command creation/replacementSteve Bennett1-50/+43
We can simply use Jim_ReplaceHashEntry() when replacing a command in non-local mode now that the proc epoch doesn't need to be incremented. And JimRemoveHashEntry() only has one caller, so fold it into Jim_DeleteHashEntry() Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-11core: improvements to garbage collectionSteve Bennett1-23/+18
Don't look up every object in the command table, since it can be slow to do that. Only lookup if the object looks like a reference. Also, script and expression objects can't contain references that aren't already contained in sub-objects, so there is no need to scan them for references. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-11time: show results less than 1us per iterationSteve Bennett1-4/+7
In this case, show the result as a decimal value Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-11core: improve the performance of listsSteve Bennett1-14/+25
Under some circumstances, such as lrepeat and lreverse we know the length of the final list, so allocate the final size immediately rather than growing the table in multiple steps. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-11dict exists: Improve performance when when key not foundSteve Bennett1-2/+2
Pass JIM_NONE to prevent an error message being generated which is subsequently thrown away. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-10core: fix regtest TEST 35Steve Bennett1-10/+8
The changes in cdfa4637afe broke TEST 35 because the cmd pointer is dereferenced before checking the procEpoch instead of afterwards. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-05core: improve performance through negative command cachingSteve Bennett1-13/+46
Instead of incrementing the proc epoch on every command removal and some command creation, cache previous deleted commands (empty structure only). Periodically increment the proc epoch and invalide all cached commands. This is especially a win when creating short lived commands. e.g. proc a {} { local proc b {} { # do something } # now b is removed } Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-05core: command (proc) names may now contained embedded nullsSteve Bennett1-183/+162
The hash table used to store commands now uses Jim_Obj keys rather than allocated char *, so embedded nulls are supported. This means that some API function such as Jim_RenameCommand() now take Jim_Obj * rather than const char *, however Jim_CreateCommand() is retained with const char * for convenience and the new Jim_CreateCommandObj() is added. This is generally a performance win as the existing Jim_Obj can be used as the key. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-05core: string match and other glob matching support embedded nullsSteve Bennett1-27/+58
string match, switch -glob, info commands, etc. all now support patterns and strings with embedded nulls. Fixes #143 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-06-05core: variable names may now contain embedded nullsSteve Bennett1-104/+149
Hash tables used to store variables are now use Jim_Obj keys rather than allocated char *, so embedded nulls are supported. This is generally a performance win as the existing Jim_Obj can be used as the key. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-30apply: handle the JIM_RETURN return codeSteve Bennett1-15/+15
The fix for tailcall in 0d5a208e92 meant that a JIM_RETURN return code from apply was no longer being converted to the appropriate return code.o Fixes: #157 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-27lsearch: handle too few args with -commandSteve Bennett1-0/+4
Fixes #155 Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-07lsearch, switch: fix -regexp case with option-like patternSteve Bennett1-12/+23
If the pattern begins with -, the internal invocation of regexp will treat the pattern as an option. Fix this by adding -- to the internal invocation of regexp. Fixes #154 Reported-by: Barry Arthur <barry.arthur@gmail.com> Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-06exit: Set the exit code as the interp resultSteve Bennett1-0/+1
If exit is caught with catch -exit, it is currently not possible to retrieve the exit value. If an exit code is provided, set it as the interp result. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-04jim.c: Fix UpdateStringOfIndex()Steve Bennett1-1/+1
In case the index is invalid, the string should contain -MAX_INT Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-05-04scan: Fix a utf-8 bug for string lengthSteve Bennett1-12/+13
The string length was being checked in chars instead of bytes Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-28tests: debug.testEvan Hunter1-12/+19
Also requires fixing 'debug' command so that the interpreter & tcltest.tcl can tell it is not supported. And the result of 'debug show' is now returned as the interpreter result rather than being printed.
2020-04-28jim.c: Fix malloc -> Jim_AllocSteve Bennett1-1/+1
The expression tree nodes are freed with Jim_Free and should be allocated with Jim_Alloc Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-17local, rename: don't allow renaming a local proc with upcallSteve Bennett1-9/+17
If an existing command was replaced when using local proc ..., then renaming the command will break upcall from within the proc because the command no longer exists in the namespace. To prevent this case, disallow rename of such a command. It is still OK to delete with rename <cmd> "" Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-17parsing: Fix error with missing quoteSteve Bennett1-0/+3
If a quote is missing inside a command, e.g.["command here] the error should indicate that a quote is missing, not a bracket. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-17env: Fix error in case of too many argumentsSteve Bennett1-1/+1
Should produce an error, but did not previously Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-17apply: ignore the current namespaceSteve Bennett1-24/+9
If a namespace is given, it is relative to the global namespace not the current namespace. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-17expr: avoid memory leak due to shimmeringSteve Bennett1-7/+16
Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-04-02tailcall: Fix to avoid tailcalls consuming C stack framesSteve Bennett1-52/+56
The purpose of a tailcall is to avoid using additional stack frames, however although were were not creating an extra Tcl callframe we were using C stack frames through the call sequence: JimCallProcedure -> Jim_EvalObjList -> JimInvokeCommand -> JimCallProcedure This meant that a large number of tailcalls would overflow the stack. Instead we need to have JimCallProcedure return to JimInvokeCommand where the tailcall can be handled by a subsequent call to JimCallProcedure. Signed-off-by: Steve Bennett <steveb@workware.net.au>
2020-03-05jim.h: Change type of interp->lastCollectTimeSteve Bennett1-6/+6
Previously we stored lastCollectTime as time_t, but to support more easily enabling 64 bit vs 32 bit time_t, convert this to be JimClock() compatible (64 bit milliseconds). Signed-off-by: Steve Bennett <steveb@workware.net.au>
2019-12-13return: fix -level 0 -code xxxSteve Bennett1-1/+1
Should return the given return code, not JIM_RETURN (2) Reported-by: dbohdan <dbohdan@dbohdan.com> Signed-off-by: Steve Bennett <steveb@workware.net.au>
2019-11-30string map and string compare now support embedded nullsSteve Bennett1-60/+27
Reported-by: dbohdan <dbohdan@dbohdan.com> Signed-off-by: Steve Bennett <steveb@workware.net.au>