Fossil SCM

Update autosetup to 0.6.8 (v0.6.7-11-g3eb780c)

steveb 2017-10-13 08:43 trunk
Commit 2ed09fb8a3ec546524f8ecb4d5a8bb4a72308d829c198c91fe79d814e3e11c5d
--- autosetup/README.autosetup
+++ autosetup/README.autosetup
@@ -1,1 +1,11 @@
1
-This is autosetup v0.6.6. See http://msteveb.github.com/autosetup/
1
+README.autosetup created by autosetup v0.6.8
2
+
3
+This is the autosetup directory for a local install of autosetup.
4
+It contains autosetup, support files and loadable modules.
5
+
6
+*.tcl files in this directory are optional modules which
7
+can be loaded with the 'use' directive.
8
+
9
+*.auto files in this directory are auto-loaded.
10
+
11
+For more information, see http://msteveb.github.com/autosetup/
212
--- autosetup/README.autosetup
+++ autosetup/README.autosetup
@@ -1,1 +1,11 @@
1 This is autosetup v0.6.6. See http://msteveb.github.com/autosetup/
 
 
 
 
 
 
 
 
 
 
2
--- autosetup/README.autosetup
+++ autosetup/README.autosetup
@@ -1,1 +1,11 @@
1 README.autosetup created by autosetup v0.6.8
2
3 This is the autosetup directory for a local install of autosetup.
4 It contains autosetup, support files and loadable modules.
5
6 *.tcl files in this directory are optional modules which
7 can be loaded with the 'use' directive.
8
9 *.auto files in this directory are auto-loaded.
10
11 For more information, see http://msteveb.github.com/autosetup/
12
+551 -223
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,16 +1,16 @@
11
#!/bin/sh
22
# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
33
# All rights reserved
44
# vim:se syntax=tcl:
55
# \
6
-dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"
6
+dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
77
8
-set autosetup(version) 0.6.6
8
+set autosetup(version) 0.6.8
99
1010
# Can be set to 1 to debug early-init problems
11
-set autosetup(debug) 0
11
+set autosetup(debug) [expr {"--debug" in $argv}]
1212
1313
##################################################################
1414
#
1515
# Main flow of control, option handling
1616
#
@@ -87,15 +87,28 @@
8787
set autosetup(getopt) [getopt argv]
8888
8989
#"=Core Options:"
9090
options-add {
9191
help:=local => "display help and options. Optionally specify a module name, such as --help=system"
92
+ licence license => "display the autosetup license"
9293
version => "display the version of autosetup"
9394
ref:=text manual:=text
9495
reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
9596
debug => "display debugging output as autosetup runs"
96
- install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
97
+ install:=. => "install autosetup to the current or given directory"
98
+ }
99
+ if {$autosetup(installed)} {
100
+ # hidden options so we can produce a nice error
101
+ options-add {
102
+ sysinstall:path
103
+ }
104
+ } else {
105
+ options-add {
106
+ sysinstall:path => "install standalone autosetup to the given directory (e.g.: /usr/local)"
107
+ }
108
+ }
109
+ options-add {
97110
force init:=help => "create initial auto.def, etc. Use --init=help for known types"
98111
# Undocumented options
99112
option-checking=1
100113
nopager
101114
quiet
@@ -108,11 +121,11 @@
108121
exit 0
109122
}
110123
111124
# autosetup --conf=alternate-auto.def
112125
if {[opt-val conf] ne ""} {
113
- set autosetup(autodef) [opt-val conf]
126
+ set autosetup(autodef) [lindex [opt-val conf] end]
114127
}
115128
116129
# Debugging output (set this early)
117130
incr autosetup(debug) [opt-bool debug]
118131
incr autosetup(force) [opt-bool force]
@@ -124,41 +137,50 @@
124137
if {[file exists $autosetup(libdir)/local.tcl]} {
125138
use local
126139
}
127140
128141
# Now any auto-load modules
129
- foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
130
- automf_load source $file
131
- }
142
+ autosetup_load_auto_modules
132143
133144
if {[opt-val help] ne ""} {
134145
incr autosetup(showhelp)
135146
use help
136
- autosetup_help [opt-val help]
147
+ autosetup_help [lindex [opt-val help] end]
148
+ }
149
+
150
+ if {[opt-bool licence license]} {
151
+ use help
152
+ autosetup_show_license
153
+ exit 0
137154
}
138155
139156
if {[opt-val {manual ref reference}] ne ""} {
140157
use help
141
- autosetup_reference [opt-val {manual ref reference}]
158
+ autosetup_reference [lindex [opt-val {manual ref reference}] end]
142159
}
143160
144161
# Allow combining --install and --init
145162
set earlyexit 0
146163
if {[opt-val install] ne ""} {
147164
use install
148
- autosetup_install [opt-val install]
165
+ autosetup_install [lindex [opt-val install] end]
149166
incr earlyexit
150167
}
151168
152169
if {[opt-val init] ne ""} {
153170
use init
154
- autosetup_init [opt-val init]
171
+ autosetup_init [lindex [opt-val init] end]
155172
incr earlyexit
156173
}
157174
158175
if {$earlyexit} {
159176
exit 0
177
+ }
178
+ if {[opt-val sysinstall] ne ""} {
179
+ use install
180
+ autosetup_install [lindex [opt-val sysinstall] end] 1
181
+ exit 0
160182
}
161183
162184
if {![file exists $autosetup(autodef)]} {
163185
# Check for invalid option first
164186
options {}
@@ -210,14 +232,14 @@
210232
#
211233
# Check each of the named, boolean options and if any have been explicitly enabled
212234
# or disabled by the user, return 1 or 0 accordingly.
213235
#
214236
# If the option was specified more than once, the last value wins.
215
-# e.g. With --enable-foo --disable-foo, [opt-bool foo] will return 0
237
+# e.g. With '--enable-foo --disable-foo', '[opt-bool foo]' will return 0
216238
#
217239
# If no value was specified by the user, returns the default value for the
218
-# first option. If -nodefault is given, this behaviour changes and
240
+# first option. If '-nodefault' is given, this behaviour changes and
219241
# -1 is returned instead.
220242
#
221243
proc opt-bool {args} {
222244
set nodefault 0
223245
if {[lindex $args 0] eq "-nodefault"} {
@@ -237,20 +259,20 @@
237259
}
238260
# Default value is the default for the first option
239261
return [dict get $::autosetup(optdefault) [lindex $args 0]]
240262
}
241263
242
-# @opt-val option-list ?default=""?
264
+# @opt-val optionlist ?default=""?
243265
#
244
-# Returns a list containing all the values given for the non-boolean options in 'option-list'.
266
+# Returns a list containing all the values given for the non-boolean options in '$optionlist'.
245267
# There will be one entry in the list for each option given by the user, including if the
246268
# same option was used multiple times.
247269
# If only a single value is required, use something like:
248270
#
249271
## lindex [opt-val $names] end
250272
#
251
-# If no options were set, $default is returned (exactly, not as a list).
273
+# If no options were set, '$default' is returned (exactly, not as a list).
252274
#
253275
proc opt-val {names {default ""}} {
254276
option-check-names {*}$names
255277
256278
foreach opt $names {
@@ -463,35 +485,36 @@
463485
options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2]
464486
}
465487
}
466488
}
467489
468
-# @options options-spec
490
+# @options optionspec
469491
#
470492
# Specifies configuration-time options which may be selected by the user
471
-# and checked with opt-val and opt-bool. The format of options-spec follows.
493
+# and checked with 'opt-val' and 'opt-bool'. '$optionspec' contains a series
494
+# of options specifications separated by newlines, as follows:
472495
#
473496
# A boolean option is of the form:
474497
#
475498
## name[=0|1] => "Description of this boolean option"
476499
#
477
-# The default is name=0, meaning that the option is disabled by default.
478
-# If name=1 is used to make the option enabled by default, the description should reflect
500
+# The default is 'name=0', meaning that the option is disabled by default.
501
+# If 'name=1' is used to make the option enabled by default, the description should reflect
479502
# that with text like "Disable support for ...".
480503
#
481504
# An argument option (one which takes a parameter) is of the form:
482505
#
483506
## name:[=]value => "Description of this option"
484507
#
485
-# If the name:value form is used, the value must be provided with the option (as --name=myvalue).
486
-# If the name:=value form is used, the value is optional and the given value is used as the default
508
+# If the 'name:value' form is used, the value must be provided with the option (as '--name=myvalue').
509
+# If the 'name:=value' form is used, the value is optional and the given value is used as the default
487510
# if it is not provided.
488511
#
489
-# Undocumented options are also supported by omitting the "=> description.
490
-# These options are not displayed with --help and can be useful for internal options or as aliases.
512
+# Undocumented options are also supported by omitting the '=> description'.
513
+# These options are not displayed with '--help' and can be useful for internal options or as aliases.
491514
#
492
-# For example, --disable-lfs is an alias for --disable=largefile:
515
+# For example, '--disable-lfs' is an alias for '--disable=largefile':
493516
#
494517
## lfs=1 largefile=1 => "Disable large file support"
495518
#
496519
proc options {optlist} {
497520
# Allow options as a list or args
@@ -511,25 +534,24 @@
511534
}
512535
}
513536
}
514537
515538
proc config_guess {} {
516
- if {[file-isexec $::autosetup(dir)/config.guess]} {
517
- exec-with-stderr sh $::autosetup(dir)/config.guess
518
- if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} {
539
+ if {[file-isexec $::autosetup(dir)/autosetup-config.guess]} {
540
+ if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.guess} alias]} {
519541
user-error $alias
520542
}
521543
return $alias
522544
} else {
523
- configlog "No config.guess, so using uname"
545
+ configlog "No autosetup-config.guess, so using uname"
524546
string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
525547
}
526548
}
527549
528550
proc config_sub {alias} {
529
- if {[file-isexec $::autosetup(dir)/config.sub]} {
530
- if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} {
551
+ if {[file-isexec $::autosetup(dir)/autosetup-config.sub]} {
552
+ if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.sub $alias} alias]} {
531553
user-error $alias
532554
}
533555
}
534556
return $alias
535557
}
@@ -536,39 +558,45 @@
536558
537559
# @define name ?value=1?
538560
#
539561
# Defines the named variable to the given value.
540562
# These (name, value) pairs represent the results of the configuration check
541
-# and are available to be checked, modified and substituted.
563
+# and are available to be subsequently checked, modified and substituted.
542564
#
543565
proc define {name {value 1}} {
544566
set ::define($name) $value
545567
#dputs "$name <= $value"
546568
}
547569
548570
# @undefine name
549571
#
550
-# Undefine the named variable
572
+# Undefine the named variable.
551573
#
552574
proc undefine {name} {
553575
unset -nocomplain ::define($name)
554576
#dputs "$name <= <undef>"
555577
}
556578
557579
# @define-append name value ...
558580
#
559
-# Appends the given value(s) to the given 'defined' variable.
560
-# If the variable is not defined or empty, it is set to $value.
581
+# Appends the given value(s) to the given "defined" variable.
582
+# If the variable is not defined or empty, it is set to '$value'.
561583
# Otherwise the value is appended, separated by a space.
562584
# Any extra values are similarly appended.
563585
# If any value is already contained in the variable (as a substring) it is omitted.
564586
#
565587
proc define-append {name args} {
566588
if {[get-define $name ""] ne ""} {
567
- # Make a token attempt to avoid duplicates
589
+ # Avoid duplicates
568590
foreach arg $args {
569
- if {[string first $arg $::define($name)] == -1} {
591
+ set found 0
592
+ foreach str [split $::define($name) " "] {
593
+ if {$str eq $arg} {
594
+ incr found
595
+ }
596
+ }
597
+ if {!$found} {
570598
append ::define($name) " " $arg
571599
}
572600
}
573601
} else {
574602
set ::define($name) [join $args]
@@ -576,11 +604,11 @@
576604
#dputs "$name += [join $args] => $::define($name)"
577605
}
578606
579607
# @get-define name ?default=0?
580608
#
581
-# Returns the current value of the 'defined' variable, or $default
609
+# Returns the current value of the "defined" variable, or '$default'
582610
# if not set.
583611
#
584612
proc get-define {name {default 0}} {
585613
if {[info exists ::define($name)]} {
586614
#dputs "$name => $::define($name)"
@@ -598,11 +626,11 @@
598626
info exists ::define($name)
599627
}
600628
601629
# @all-defines
602630
#
603
-# Returns a dictionary (name value list) of all defined variables.
631
+# Returns a dictionary (name, value list) of all defined variables.
604632
#
605633
# This is suitable for use with 'dict', 'array set' or 'foreach'
606634
# and allows for arbitrary processing of the defined variables.
607635
#
608636
proc all-defines {} {
@@ -610,13 +638,13 @@
610638
}
611639
612640
613641
# @get-env name default
614642
#
615
-# If $name was specified on the command line, return it.
616
-# If $name was set in the environment, return it.
617
-# Otherwise return $default.
643
+# If '$name' was specified on the command line, return it.
644
+# Otherwise if '$name' was set in the environment, return it.
645
+# Otherwise return '$default'.
618646
#
619647
proc get-env {name default} {
620648
if {[dict exists $::autosetup(cmdline) $name]} {
621649
return [dict get $::autosetup(cmdline) $name]
622650
}
@@ -623,11 +651,11 @@
623651
getenv $name $default
624652
}
625653
626654
# @env-is-set name
627655
#
628
-# Returns 1 if the $name was specified on the command line or in the environment.
656
+# Returns 1 if '$name' was specified on the command line or in the environment.
629657
# Note that an empty environment variable is not considered to be set.
630658
#
631659
proc env-is-set {name} {
632660
if {[dict exists $::autosetup(cmdline) $name]} {
633661
return 1
@@ -639,11 +667,11 @@
639667
}
640668
641669
# @readfile filename ?default=""?
642670
#
643671
# Return the contents of the file, without the trailing newline.
644
-# If the file doesn't exist or can't be read, returns $default.
672
+# If the file doesn't exist or can't be read, returns '$default'.
645673
#
646674
proc readfile {filename {default_value ""}} {
647675
set result $default_value
648676
catch {
649677
set f [open $filename]
@@ -653,11 +681,11 @@
653681
return $result
654682
}
655683
656684
# @writefile filename value
657685
#
658
-# Creates the given file containing $value.
686
+# Creates the given file containing '$value'.
659687
# Does not add an extra newline.
660688
#
661689
proc writefile {filename value} {
662690
set f [open $filename w]
663691
puts -nonewline $f $value
@@ -677,63 +705,60 @@
677705
lappend args [quote-if-needed $arg]
678706
}
679707
join $args
680708
}
681709
682
-# @suffix suf list
683
-#
684
-# Takes a list and returns a new list with $suf appended
685
-# to each element
686
-#
687
-## suffix .c {a b c} => {a.c b.c c.c}
688
-#
689
-proc suffix {suf list} {
710
+# @list-non-empty list
711
+#
712
+# Returns a copy of the given list with empty elements removed
713
+proc list-non-empty {list} {
690714
set result {}
691715
foreach p $list {
692
- lappend result $p$suf
716
+ if {$p ne ""} {
717
+ lappend result $p
718
+ }
693719
}
694720
return $result
695721
}
696722
697
-# @prefix pre list
698
-#
699
-# Takes a list and returns a new list with $pre prepended
700
-# to each element
701
-#
702
-## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
703
-#
704
-proc prefix {pre list} {
705
- set result {}
706
- foreach p $list {
707
- lappend result $pre$p
708
- }
709
- return $result
723
+# @find-executable-path name
724
+#
725
+# Searches the path for an executable with the given name.
726
+# Note that the name may include some parameters, e.g. 'cc -mbig-endian',
727
+# in which case the parameters are ignored.
728
+# The full path to the executable if found, or "" if not found.
729
+# Returns 1 if found, or 0 if not.
730
+#
731
+proc find-executable-path {name} {
732
+ # Ignore any parameters
733
+ set name [lindex $name 0]
734
+ # The empty string is never a valid executable
735
+ if {$name ne ""} {
736
+ foreach p [split-path] {
737
+ dputs "Looking for $name in $p"
738
+ set exec [file join $p $name]
739
+ if {[file-isexec $exec]} {
740
+ dputs "Found $name -> $exec"
741
+ return $exec
742
+ }
743
+ }
744
+ }
745
+ return {}
710746
}
711747
712748
# @find-executable name
713749
#
714750
# Searches the path for an executable with the given name.
715
-# Note that the name may include some parameters, e.g. "cc -mbig-endian",
751
+# Note that the name may include some parameters, e.g. 'cc -mbig-endian',
716752
# in which case the parameters are ignored.
717753
# Returns 1 if found, or 0 if not.
718754
#
719755
proc find-executable {name} {
720
- # Ignore any parameters
721
- set name [lindex $name 0]
722
- if {$name eq ""} {
723
- # The empty string is never a valid executable
724
- return 0
725
- }
726
- foreach p [split-path] {
727
- dputs "Looking for $name in $p"
728
- set exec [file join $p $name]
729
- if {[file-isexec $exec]} {
730
- dputs "Found $name -> $exec"
731
- return 1
732
- }
733
- }
734
- return 0
756
+ if {[find-executable-path $name] eq {}} {
757
+ return 0
758
+ }
759
+ return 1
735760
}
736761
737762
# @find-an-executable ?-required? name ...
738763
#
739764
# Given a list of possible executable names,
@@ -764,11 +789,11 @@
764789
return ""
765790
}
766791
767792
# @configlog msg
768793
#
769
-# Writes the given message to the configuration log, config.log
794
+# Writes the given message to the configuration log, 'config.log'.
770795
#
771796
proc configlog {msg} {
772797
if {![info exists ::autosetup(logfh)]} {
773798
set ::autosetup(logfh) [open config.log w]
774799
}
@@ -800,12 +825,12 @@
800825
}
801826
}
802827
803828
# @msg-quiet command ...
804829
#
805
-# msg-quiet evaluates it's arguments as a command with output
806
-# from msg-checking and msg-result suppressed.
830
+# 'msg-quiet' evaluates it's arguments as a command with output
831
+# from 'msg-checking' and 'msg-result' suppressed.
807832
#
808833
# This is useful if a check needs to run a subcheck which isn't
809834
# of interest to the user.
810835
proc msg-quiet {args} {
811836
incr ::autosetup(msg-quiet)
@@ -841,11 +866,11 @@
841866
842867
# @user-error msg
843868
#
844869
# Indicate incorrect usage to the user, including if required components
845870
# or features are not found.
846
-# autosetup exits with a non-zero return code.
871
+# 'autosetup' exits with a non-zero return code.
847872
#
848873
proc user-error {msg} {
849874
show-notices
850875
puts stderr "Error: $msg"
851876
puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options"
@@ -887,10 +912,22 @@
887912
proc maybe-show-timestamp {} {
888913
if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} {
889914
puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]]
890915
}
891916
}
917
+
918
+# @autosetup-require-version required
919
+#
920
+# Checks the current version of 'autosetup' against '$required'.
921
+# A fatal error is generated if the current version is less than that required.
922
+#
923
+proc autosetup-require-version {required} {
924
+ use util
925
+ if {[compare-versions $::autosetup(version) $required] < 0} {
926
+ user-error "autosetup version $required is required, but this is $::autosetup(version)"
927
+ }
928
+}
892929
893930
proc autosetup_version {} {
894931
return "autosetup v$::autosetup(version)"
895932
}
896933
@@ -986,23 +1023,35 @@
9861023
# The latter form is useful for a complex module which requires additional
9871024
# support file. In this form, '$::usedir' is set to the module directory
9881025
# when it is loaded.
9891026
#
9901027
proc use {args} {
1028
+ global autosetup libmodule modsource
1029
+
1030
+ set dirs [list $autosetup(libdir)]
1031
+ if {[info exists autosetup(srcdir)]} {
1032
+ lappend dirs $autosetup(srcdir)/autosetup
1033
+ }
9911034
foreach m $args {
992
- if {[info exists ::libmodule($m)]} {
1035
+ if {[info exists libmodule($m)]} {
9931036
continue
9941037
}
995
- set ::libmodule($m) 1
996
- if {[info exists ::modsource($m)]} {
997
- automf_load eval $::modsource($m)
1038
+ set libmodule($m) 1
1039
+ if {[info exists modsource(${m}.tcl)]} {
1040
+ automf_load eval $modsource(${m}.tcl)
9981041
} else {
999
- set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl]
1042
+ set locs [list ${m}.tcl ${m}/init.tcl]
10001043
set found 0
1001
- foreach source $sources {
1002
- if {[file exists $source]} {
1003
- incr found
1044
+ foreach dir $dirs {
1045
+ foreach loc $locs {
1046
+ set source $dir/$loc
1047
+ if {[file exists $source]} {
1048
+ incr found
1049
+ break
1050
+ }
1051
+ }
1052
+ if {$found} {
10041053
break
10051054
}
10061055
}
10071056
if {$found} {
10081057
# For the convenience of the "use" source, point to the directory
@@ -1014,10 +1063,22 @@
10141063
autosetup-error "use: No such module: $m"
10151064
}
10161065
}
10171066
}
10181067
}
1068
+
1069
+proc autosetup_load_auto_modules {} {
1070
+ global autosetup modsource
1071
+ # First load any embedded auto modules
1072
+ foreach mod [array names modsource *.auto] {
1073
+ automf_load eval $modsource($mod)
1074
+ }
1075
+ # Now any external auto modules
1076
+ foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
1077
+ automf_load source $file
1078
+ }
1079
+}
10191080
10201081
# Load module source in the global scope by executing the given command
10211082
proc automf_load {args} {
10221083
if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
10231084
autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
@@ -1027,18 +1088,21 @@
10271088
# Initial settings
10281089
set autosetup(exe) $::argv0
10291090
set autosetup(istcl) 1
10301091
set autosetup(start) [clock millis]
10311092
set autosetup(installed) 0
1093
+set autosetup(sysinstall) 0
10321094
set autosetup(msg-checking) 0
10331095
set autosetup(msg-quiet) 0
1096
+set autosetup(inittypes) {}
10341097
10351098
# Embedded modules are inserted below here
10361099
set autosetup(installed) 1
1037
-# ----- module asciidoc-formatting -----
1100
+set autosetup(sysinstall) 0
1101
+# ----- @module asciidoc-formatting.tcl -----
10381102
1039
-set modsource(asciidoc-formatting) {
1103
+set modsource(asciidoc-formatting.tcl) {
10401104
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
10411105
# All rights reserved
10421106
10431107
# Module which provides text formatting
10441108
# asciidoc format
@@ -1102,13 +1166,13 @@
11021166
regsub -all "\n\n" $defn "\n ::\n" defn
11031167
puts $defn
11041168
}
11051169
}
11061170
1107
-# ----- module formatting -----
1171
+# ----- @module formatting.tcl -----
11081172
1109
-set modsource(formatting) {
1173
+set modsource(formatting.tcl) {
11101174
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
11111175
# All rights reserved
11121176
11131177
# Module which provides common text formatting
11141178
@@ -1159,13 +1223,13 @@
11591223
# Return the result
11601224
return $lines
11611225
}
11621226
}
11631227
1164
-# ----- module getopt -----
1228
+# ----- @module getopt.tcl -----
11651229
1166
-set modsource(getopt) {
1230
+set modsource(getopt.tcl) {
11671231
# Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/
11681232
# All rights reserved
11691233
11701234
# Simple getopt module
11711235
@@ -1197,11 +1261,11 @@
11971261
11981262
if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} {
11991263
# --name=value
12001264
dict lappend opts $name [list str $value]
12011265
} elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} {
1202
- if {$prefix in {enable- with- ""}} {
1266
+ if {$prefix in {enable- ""}} {
12031267
set value 1
12041268
} else {
12051269
set value 0
12061270
}
12071271
dict lappend opts $name [list bool $value]
@@ -1218,13 +1282,13 @@
12181282
12191283
return $opts
12201284
}
12211285
}
12221286
1223
-# ----- module help -----
1287
+# ----- @module help.tcl -----
12241288
1225
-set modsource(help) {
1289
+set modsource(help.tcl) {
12261290
# Copyright (c) 2010 WorkWare Systems http://workware.net.au/
12271291
# All rights reserved
12281292
12291293
# Module which provides usage, help and the command reference
12301294
@@ -1251,10 +1315,28 @@
12511315
options-show
12521316
}
12531317
}
12541318
exit 0
12551319
}
1320
+
1321
+proc autosetup_show_license {} {
1322
+ global modsource autosetup
1323
+ use_pager
1324
+
1325
+ if {[info exists modsource(LICENSE)]} {
1326
+ puts $modsource(LICENSE)
1327
+ return
1328
+ }
1329
+ foreach dir [list $autosetup(libdir) $autosetup(srcdir)] {
1330
+ set path [file join $dir LICENSE]
1331
+ if {[file exists $path]} {
1332
+ puts [readfile $path]
1333
+ return
1334
+ }
1335
+ }
1336
+ puts "LICENSE not found"
1337
+}
12561338
12571339
# If not already paged and stdout is a tty, pipe the output through the pager
12581340
# This is done by reinvoking autosetup with --nopager added
12591341
proc use_pager {} {
12601342
if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} {
@@ -1304,10 +1386,16 @@
13041386
}
13051387
13061388
proc autosetup_output_block {type lines} {
13071389
if {[llength $lines]} {
13081390
switch $type {
1391
+ section {
1392
+ section $lines
1393
+ }
1394
+ subsection {
1395
+ subsection $lines
1396
+ }
13091397
code {
13101398
codelines $lines
13111399
}
13121400
p {
13131401
p [join $lines]
@@ -1325,30 +1413,45 @@
13251413
# Generate a command reference from inline documentation
13261414
proc automf_command_reference {} {
13271415
lappend files $::autosetup(prog)
13281416
lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
13291417
1330
- section "Core Commands"
1331
- set type p
1332
- set lines {}
1333
- set cmd {}
1418
+ # We want to process all non-module files before module files
1419
+ # and then modules in alphabetical order.
1420
+ # So examine all files and extract docs into doc($modulename) and doc(_core_)
1421
+ #
1422
+ # Each entry is a list of {type data} where $type is one of: section, subsection, code, list, p
1423
+ # and $data is a string for section, subsection or a list of text lines for other types.
1424
+
1425
+ # XXX: Should commands be in alphabetical order too? Currently they are in file order.
1426
+
1427
+ set doc(_core_) {}
1428
+ lappend doc(_core_) [list section "Core Commands"]
13341429
13351430
foreach file $files {
1431
+ set modulename [file rootname [file tail $file]]
1432
+ set current _core_
13361433
set f [open $file]
13371434
while {![eof $f]} {
13381435
set line [gets $f]
1436
+
1437
+ # Find embedded module names
1438
+ if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
1439
+ continue
1440
+ }
13391441
13401442
# Find lines starting with "# @*" and continuing through the remaining comment lines
13411443
if {![regexp {^# @(.*)} $line -> cmd]} {
13421444
continue
13431445
}
13441446
13451447
# Synopsis or command?
13461448
if {$cmd eq "synopsis:"} {
1347
- section "Module: [file rootname [file tail $file]]"
1449
+ set current $modulename
1450
+ lappend doc($current) [list section "Module: $modulename"]
13481451
} else {
1349
- subsection $cmd
1452
+ lappend doc($current) [list subsection $cmd]
13501453
}
13511454
13521455
set lines {}
13531456
set type p
13541457
@@ -1369,29 +1472,38 @@
13691472
13701473
#puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd"
13711474
13721475
if {$t ne $type || $cmd eq ""} {
13731476
# Finish the current block
1374
- autosetup_output_block $type $lines
1477
+ lappend doc($current) [list $type $lines]
13751478
set lines {}
13761479
set type $t
13771480
}
13781481
if {$cmd ne ""} {
13791482
lappend lines $cmd
13801483
}
13811484
}
13821485
1383
- autosetup_output_block $type $lines
1486
+ lappend doc($current) [list $type $lines]
13841487
}
13851488
close $f
13861489
}
1490
+
1491
+ # Now format and output the results
1492
+
1493
+ # _core_ will sort first
1494
+ foreach module [lsort [array names doc]] {
1495
+ foreach item $doc($module) {
1496
+ autosetup_output_block {*}$item
1497
+ }
1498
+ }
13871499
}
13881500
}
13891501
1390
-# ----- module init -----
1502
+# ----- @module init.tcl -----
13911503
1392
-set modsource(init) {
1504
+set modsource(init.tcl) {
13931505
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
13941506
# All rights reserved
13951507
13961508
# Module to help create auto.def and configure
13971509
@@ -1444,79 +1556,157 @@
14441556
}
14451557
writefile $filename $contents
14461558
}
14471559
}
14481560
1449
-# ----- module install -----
1561
+# ----- @module install.tcl -----
14501562
1451
-set modsource(install) {
1563
+set modsource(install.tcl) {
14521564
# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
14531565
# All rights reserved
14541566
14551567
# Module which can install autosetup
14561568
1457
-proc autosetup_install {dir} {
1458
- if {[catch {
1569
+# autosetup(installed)=1 means that autosetup is not running from source
1570
+# autosetup(sysinstall)=1 means that autosetup is running from a sysinstall verion
1571
+# shared=1 means that we are trying to do a sysinstall. This is only possible from the development source.
1572
+
1573
+proc autosetup_install {dir {shared 0}} {
1574
+ global autosetup
1575
+ if {$shared} {
1576
+ if {$autosetup(installed) || $autosetup(sysinstall)} {
1577
+ user-error "Can only --sysinstall from development sources"
1578
+ }
1579
+ } elseif {$autosetup(installed)} {
1580
+ user-error "Can't --install from project install"
1581
+ }
1582
+
1583
+ if {$autosetup(sysinstall)} {
1584
+ # This is the sysinstall version, so install just uses references
14591585
cd $dir
1586
+
1587
+ puts "[autosetup_version] creating configure to use system-installed autosetup"
1588
+ autosetup_create_configure 1
1589
+ puts "Creating autosetup/README.autosetup"
14601590
file mkdir autosetup
1591
+ autosetup_install_readme autosetup/README.autosetup 1
1592
+ return
1593
+ }
1594
+
1595
+ if {[catch {
1596
+ if {$shared} {
1597
+ set target $dir/bin/autosetup
1598
+ set installedas $target
1599
+ } else {
1600
+ if {$dir eq "."} {
1601
+ set installedas autosetup
1602
+ } else {
1603
+ set installedas $dir/autosetup
1604
+ }
1605
+ cd $dir
1606
+ file mkdir autosetup
1607
+ set target autosetup/autosetup
1608
+ }
1609
+ set targetdir [file dirname $target]
1610
+ file mkdir $targetdir
14611611
1462
- set f [open autosetup/autosetup w]
1612
+ set f [open $target w]
14631613
1464
- set publicmodules [glob $::autosetup(libdir)/*.auto]
1614
+ set publicmodules {}
14651615
14661616
# First the main script, but only up until "CUT HERE"
1467
- set in [open $::autosetup(dir)/autosetup]
1617
+ set in [open $autosetup(dir)/autosetup]
14681618
while {[gets $in buf] >= 0} {
14691619
if {$buf ne "##-- CUT HERE --##"} {
14701620
puts $f $buf
14711621
continue
14721622
}
14731623
14741624
# Insert the static modules here
14751625
# i.e. those which don't contain @synopsis:
1626
+ # All modules are inserted if $shared is set
14761627
puts $f "set autosetup(installed) 1"
1477
- foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] {
1628
+ puts $f "set autosetup(sysinstall) $shared"
1629
+ foreach file [lsort [glob $autosetup(libdir)/*.{tcl,auto}]] {
1630
+ set modname [file tail $file]
1631
+ set ext [file ext $modname]
14781632
set buf [readfile $file]
1479
- if {[string match "*\n# @synopsis:*" $buf]} {
1480
- lappend publicmodules $file
1481
- continue
1633
+ if {!$shared} {
1634
+ if {$ext eq ".auto" || [string match "*\n# @synopsis:*" $buf]} {
1635
+ lappend publicmodules $file
1636
+ continue
1637
+ }
14821638
}
1483
- set modname [file rootname [file tail $file]]
1484
- puts $f "# ----- module $modname -----"
1639
+ dputs "install: importing lib/[file tail $file]"
1640
+ puts $f "# ----- @module $modname -----"
14851641
puts $f "\nset modsource($modname) \{"
14861642
puts $f $buf
14871643
puts $f "\}\n"
14881644
}
1645
+ if {$shared} {
1646
+ foreach {srcname destname} [list $autosetup(libdir)/README.autosetup-lib README.autosetup \
1647
+ $autosetup(srcdir)/LICENSE LICENSE] {
1648
+ dputs "install: importing $srcname as $destname"
1649
+ puts $f "\nset modsource($destname) \\\n[list [readfile $srcname]\n]\n"
1650
+ }
1651
+ }
14891652
}
14901653
close $in
14911654
close $f
1492
- exec chmod 755 autosetup/autosetup
1655
+ catch {exec chmod 755 $target}
1656
+
1657
+ set installfiles {autosetup-config.guess autosetup-config.sub autosetup-test-tclsh}
1658
+ set removefiles {}
1659
+
1660
+ if {!$shared} {
1661
+ autosetup_install_readme $targetdir/README.autosetup 0
14931662
1494
- # Install public modules
1495
- foreach file $publicmodules {
1496
- autosetup_install_file $file autosetup
1663
+ # Install public modules
1664
+ foreach file $publicmodules {
1665
+ set tail [file tail $file]
1666
+ autosetup_install_file $file $targetdir/$tail
1667
+ }
1668
+ lappend installfiles jimsh0.c autosetup-find-tclsh LICENSE
1669
+ lappend removefiles config.guess config.sub test-tclsh find-tclsh
1670
+ } else {
1671
+ lappend installfiles {sys-find-tclsh autosetup-find-tclsh}
14971672
}
14981673
14991674
# Install support files
1500
- foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} {
1501
- autosetup_install_file $::autosetup(dir)/$file autosetup
1502
- }
1503
- exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh
1504
-
1505
- writefile autosetup/README.autosetup \
1506
- "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n"
1507
-
1675
+ foreach fileinfo $installfiles {
1676
+ if {[llength $fileinfo] == 2} {
1677
+ lassign $fileinfo source dest
1678
+ } else {
1679
+ lassign $fileinfo source
1680
+ set dest $source
1681
+ }
1682
+ autosetup_install_file $autosetup(dir)/$source $targetdir/$dest
1683
+ }
1684
+
1685
+ # Remove obsolete files
1686
+ foreach file $removefiles {
1687
+ if {[file exists $targetdir/$file]} {
1688
+ file delete $targetdir/$file
1689
+ }
1690
+ }
15081691
} error]} {
15091692
user-error "Failed to install autosetup: $error"
15101693
}
1511
- puts "Installed [autosetup_version] to autosetup/"
1694
+ if {$shared} {
1695
+ set type "system"
1696
+ } else {
1697
+ set type "local"
1698
+ }
1699
+ puts "Installed $type [autosetup_version] to $installedas"
15121700
1513
- # Now create 'configure' if necessary
1514
- autosetup_create_configure
1701
+ if {!$shared} {
1702
+ # Now create 'configure' if necessary
1703
+ autosetup_create_configure 0
1704
+ }
15151705
}
15161706
1517
-proc autosetup_create_configure {} {
1707
+proc autosetup_create_configure {shared} {
15181708
if {[file exists configure]} {
15191709
if {!$::autosetup(force)} {
15201710
# Could this be an autosetup configure?
15211711
if {![string match "*\nWRAPPER=*" [readfile configure]]} {
15221712
puts "I see configure, but not created by autosetup, so I won't overwrite it."
@@ -1527,40 +1717,76 @@
15271717
puts "I will overwrite the existing configure because you used --force."
15281718
}
15291719
} else {
15301720
puts "I don't see configure, so I will create it."
15311721
}
1532
- writefile configure \
1722
+ if {$shared} {
1723
+ writefile configure \
1724
+{#!/bin/sh
1725
+# Note that WRAPPER is set here purely to detect an autosetup-created script
1726
+WRAPPER="-"; "autosetup" "$@"
1727
+}
1728
+ } else {
1729
+ writefile configure \
15331730
{#!/bin/sh
15341731
dir="`dirname "$0"`/autosetup"
1535
-WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
1732
+WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
15361733
}
1734
+ }
15371735
catch {exec chmod 755 configure}
15381736
}
15391737
15401738
# Append the contents of $file to filehandle $f
15411739
proc autosetup_install_append {f file} {
1740
+ dputs "install: include $file"
15421741
set in [open $file]
15431742
puts $f [read $in]
15441743
close $in
15451744
}
15461745
1547
-proc autosetup_install_file {file dir} {
1548
- if {![file exists $file]} {
1549
- error "Missing installation file '$file'"
1550
- }
1551
- writefile [file join $dir [file tail $file]] [readfile $file]\n
1552
-}
1553
-
1554
-if {$::autosetup(installed)} {
1555
- user-error "autosetup can only be installed from development source, not from installed copy"
1746
+proc autosetup_install_file {source target} {
1747
+ dputs "install: $source => $target"
1748
+ if {![file exists $source]} {
1749
+ error "Missing installation file '$source'"
1750
+ }
1751
+ writefile $target [readfile $source]\n
1752
+ # If possible, copy the file mode
1753
+ file stat $source stat
1754
+ set mode [format %o [expr {$stat(mode) & 0x1ff}]]
1755
+ catch {exec chmod $mode $target}
1756
+}
1757
+
1758
+proc autosetup_install_readme {target sysinstall} {
1759
+ set readme "README.autosetup created by [autosetup_version]\n\n"
1760
+ if {$sysinstall} {
1761
+ append readme \
1762
+{This is the autosetup directory for a system install of autosetup.
1763
+Loadable modules can be added here.
1764
+}
1765
+ } else {
1766
+ append readme \
1767
+{This is the autosetup directory for a local install of autosetup.
1768
+It contains autosetup, support files and loadable modules.
1769
+}
1770
+}
1771
+
1772
+ append readme {
1773
+*.tcl files in this directory are optional modules which
1774
+can be loaded with the 'use' directive.
1775
+
1776
+*.auto files in this directory are auto-loaded.
1777
+
1778
+For more information, see http://msteveb.github.com/autosetup/
1779
+}
1780
+ dputs "install: autosetup/README.autosetup"
1781
+ writefile $target $readme
15561782
}
15571783
}
15581784
1559
-# ----- module markdown-formatting -----
1785
+# ----- @module markdown-formatting.tcl -----
15601786
1561
-set modsource(markdown-formatting) {
1787
+set modsource(markdown-formatting.tcl) {
15621788
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
15631789
# All rights reserved
15641790
15651791
# Module which provides text formatting
15661792
# markdown format (kramdown syntax)
@@ -1627,13 +1853,13 @@
16271853
}
16281854
puts "$defn"
16291855
}
16301856
}
16311857
1632
-# ----- module misc -----
1858
+# ----- @module misc.tcl -----
16331859
1634
-set modsource(misc) {
1860
+set modsource(misc.tcl) {
16351861
# Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/
16361862
# All rights reserved
16371863
16381864
# Module containing misc procs useful to modules
16391865
# Largely for platform compatibility
@@ -1805,106 +2031,208 @@
18052031
string trim $result
18062032
}
18072033
}
18082034
}
18092035
1810
-# ----- module text-formatting -----
2036
+# ----- @module text-formatting.tcl -----
18112037
1812
-set modsource(text-formatting) {
2038
+set modsource(text-formatting.tcl) {
18132039
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
18142040
# All rights reserved
18152041
18162042
# Module which provides text formatting
18172043
18182044
use formatting
18192045
18202046
proc wordwrap {text length {firstprefix ""} {nextprefix ""}} {
1821
- set len 0
1822
- set space $firstprefix
1823
- foreach word [split $text] {
1824
- set word [string trim $word]
1825
- if {$word == ""} {
1826
- continue
1827
- }
1828
- if {$len && [string length $space$word] + $len >= $length} {
1829
- puts ""
1830
- set len 0
1831
- set space $nextprefix
1832
- }
1833
- incr len [string length $space$word]
1834
-
1835
- # Use man-page conventions for highlighting 'quoted' and *quoted*
1836
- # single words.
1837
- # Use x^Hx for *bold* and _^Hx for 'underline'.
1838
- #
1839
- # less and more will both understand this.
1840
- # Pipe through 'col -b' to remove them.
1841
- if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1842
- regsub -all . $bareword "_\b&" word
1843
- append word $dot
1844
- } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1845
- regsub -all . $bareword "&\b&" word
1846
- append word $dot
1847
- }
1848
- puts -nonewline $space$word
1849
- set space " "
1850
- }
1851
- if {$len} {
1852
- puts ""
1853
- }
2047
+ set len 0
2048
+ set space $firstprefix
2049
+
2050
+ foreach word [split $text] {
2051
+ set word [string trim $word]
2052
+ if {$word eq ""} {
2053
+ continue
2054
+ }
2055
+ if {[info exists partial]} {
2056
+ append partial " " $word
2057
+ if {[string first $quote $word] < 0} {
2058
+ # Haven't found end of quoted word
2059
+ continue
2060
+ }
2061
+ # Finished quoted word
2062
+ set word $partial
2063
+ unset partial
2064
+ unset quote
2065
+ } else {
2066
+ set quote [string index $word 0]
2067
+ if {$quote in {' *}} {
2068
+ if {[string first $quote $word 1] < 0} {
2069
+ # Haven't found end of quoted word
2070
+ # Not a whole word.
2071
+ set first [string index $word 0]
2072
+ # Start of quoted word
2073
+ set partial $word
2074
+ continue
2075
+ }
2076
+ }
2077
+ }
2078
+
2079
+ if {$len && [string length $space$word] + $len >= $length} {
2080
+ puts ""
2081
+ set len 0
2082
+ set space $nextprefix
2083
+ }
2084
+ incr len [string length $space$word]
2085
+
2086
+ # Use man-page conventions for highlighting 'quoted' and *quoted*
2087
+ # single words.
2088
+ # Use x^Hx for *bold* and _^Hx for 'underline'.
2089
+ #
2090
+ # less and more will both understand this.
2091
+ # Pipe through 'col -b' to remove them.
2092
+ if {[regexp {^'(.*)'(.*)} $word -> quoted after]} {
2093
+ set quoted [string map {~ " "} $quoted]
2094
+ regsub -all . $quoted "&\b&" quoted
2095
+ set word $quoted$after
2096
+ } elseif {[regexp {^[*](.*)[*](.*)} $word -> quoted after]} {
2097
+ set quoted [string map {~ " "} $quoted]
2098
+ regsub -all . $quoted "_\b&" quoted
2099
+ set word $quoted$after
2100
+ }
2101
+ puts -nonewline $space$word
2102
+ set space " "
2103
+ }
2104
+ if {[info exists partial]} {
2105
+ # Missing end of quote
2106
+ puts -nonewline $space$partial
2107
+ }
2108
+ if {$len} {
2109
+ puts ""
2110
+ }
18542111
}
18552112
proc title {text} {
1856
- underline [string trim $text] =
1857
- nl
2113
+ underline [string trim $text] =
2114
+ nl
18582115
}
18592116
proc p {text} {
1860
- wordwrap $text 80
1861
- nl
2117
+ wordwrap $text 80
2118
+ nl
18622119
}
18632120
proc codelines {lines} {
1864
- foreach line $lines {
1865
- puts " $line"
1866
- }
1867
- nl
2121
+ foreach line $lines {
2122
+ puts " $line"
2123
+ }
2124
+ nl
18682125
}
18692126
proc nl {} {
1870
- puts ""
2127
+ puts ""
18712128
}
18722129
proc underline {text char} {
1873
- regexp "^(\[ \t\]*)(.*)" $text -> indent words
1874
- puts $text
1875
- puts $indent[string repeat $char [string length $words]]
2130
+ regexp "^(\[ \t\]*)(.*)" $text -> indent words
2131
+ puts $text
2132
+ puts $indent[string repeat $char [string length $words]]
18762133
}
18772134
proc section {text} {
1878
- underline "[string trim $text]" -
1879
- nl
2135
+ underline "[string trim $text]" -
2136
+ nl
18802137
}
18812138
proc subsection {text} {
1882
- underline "$text" ~
1883
- nl
2139
+ underline "$text" ~
2140
+ nl
18842141
}
18852142
proc bullet {text} {
1886
- wordwrap $text 76 " * " " "
2143
+ wordwrap $text 76 " * " " "
18872144
}
18882145
proc indent {text} {
1889
- wordwrap $text 76 " " " "
2146
+ wordwrap $text 76 " " " "
18902147
}
18912148
proc defn {first args} {
1892
- if {$first ne ""} {
1893
- underline " $first" ~
1894
- }
1895
- foreach p $args {
1896
- if {$p ne ""} {
1897
- indent $p
1898
- }
1899
- }
2149
+ if {$first ne ""} {
2150
+ underline " $first" ~
2151
+ }
2152
+ foreach p $args {
2153
+ if {$p ne ""} {
2154
+ indent $p
2155
+ }
2156
+ }
2157
+}
2158
+}
2159
+
2160
+# ----- @module util.tcl -----
2161
+
2162
+set modsource(util.tcl) {
2163
+# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/
2164
+# All rights reserved
2165
+
2166
+# Module which contains miscellaneous utility functions
2167
+
2168
+# @compare-versions version1 version2
2169
+#
2170
+# Versions are of the form 'a.b.c' (may be any number of numeric components)
2171
+#
2172
+# Compares the two versions and returns:
2173
+## -1 if v1 < v2
2174
+## 0 if v1 == v2
2175
+## 1 if v1 > v2
2176
+#
2177
+# If one version has fewer components than the other, 0 is substituted to the right. e.g.
2178
+## 0.2 < 0.3
2179
+## 0.2.5 > 0.2
2180
+## 1.1 == 1.1.0
2181
+#
2182
+proc compare-versions {v1 v2} {
2183
+ foreach c1 [split $v1 .] c2 [split $v2 .] {
2184
+ if {$c1 eq ""} {
2185
+ set c1 0
2186
+ }
2187
+ if {$c2 eq ""} {
2188
+ set c2 0
2189
+ }
2190
+ if {$c1 < $c2} {
2191
+ return -1
2192
+ }
2193
+ if {$c1 > $c2} {
2194
+ return 1
2195
+ }
2196
+ }
2197
+ return 0
2198
+}
2199
+
2200
+# @suffix suf list
2201
+#
2202
+# Takes a list and returns a new list with '$suf' appended
2203
+# to each element
2204
+#
2205
+## suffix .c {a b c} => {a.c b.c c.c}
2206
+#
2207
+proc suffix {suf list} {
2208
+ set result {}
2209
+ foreach p $list {
2210
+ lappend result $p$suf
2211
+ }
2212
+ return $result
2213
+}
2214
+
2215
+# @prefix pre list
2216
+#
2217
+# Takes a list and returns a new list with '$pre' prepended
2218
+# to each element
2219
+#
2220
+## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
2221
+#
2222
+proc prefix {pre list} {
2223
+ set result {}
2224
+ foreach p $list {
2225
+ lappend result $pre$p
2226
+ }
2227
+ return $result
19002228
}
19012229
}
19022230
1903
-# ----- module wiki-formatting -----
2231
+# ----- @module wiki-formatting.tcl -----
19042232
1905
-set modsource(wiki-formatting) {
2233
+set modsource(wiki-formatting.tcl) {
19062234
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
19072235
# All rights reserved
19082236
19092237
# Module which provides text formatting
19102238
# wiki.tcl.tk format output
@@ -1975,11 +2303,11 @@
19752303
if {$autosetup(debug)} {
19762304
main $argv
19772305
}
19782306
if {[catch {main $argv} msg opts] == 1} {
19792307
show-notices
1980
- autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
2308
+ autosetup-full-error [error-dump $msg $opts $autosetup(debug)]
19812309
if {!$autosetup(debug)} {
19822310
puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
19832311
}
19842312
exit 1
19852313
}
19862314
19872315
ADDED autosetup/autosetup-config.guess
19882316
ADDED autosetup/autosetup-config.sub
19892317
ADDED autosetup/autosetup-find-tclsh
19902318
ADDED autosetup/autosetup-test-tclsh
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,16 +1,16 @@
1 #!/bin/sh
2 # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
3 # All rights reserved
4 # vim:se syntax=tcl:
5 # \
6 dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"
7
8 set autosetup(version) 0.6.6
9
10 # Can be set to 1 to debug early-init problems
11 set autosetup(debug) 0
12
13 ##################################################################
14 #
15 # Main flow of control, option handling
16 #
@@ -87,15 +87,28 @@
87 set autosetup(getopt) [getopt argv]
88
89 #"=Core Options:"
90 options-add {
91 help:=local => "display help and options. Optionally specify a module name, such as --help=system"
 
92 version => "display the version of autosetup"
93 ref:=text manual:=text
94 reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
95 debug => "display debugging output as autosetup runs"
96 install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
 
 
 
 
 
 
 
 
 
 
 
 
97 force init:=help => "create initial auto.def, etc. Use --init=help for known types"
98 # Undocumented options
99 option-checking=1
100 nopager
101 quiet
@@ -108,11 +121,11 @@
108 exit 0
109 }
110
111 # autosetup --conf=alternate-auto.def
112 if {[opt-val conf] ne ""} {
113 set autosetup(autodef) [opt-val conf]
114 }
115
116 # Debugging output (set this early)
117 incr autosetup(debug) [opt-bool debug]
118 incr autosetup(force) [opt-bool force]
@@ -124,41 +137,50 @@
124 if {[file exists $autosetup(libdir)/local.tcl]} {
125 use local
126 }
127
128 # Now any auto-load modules
129 foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
130 automf_load source $file
131 }
132
133 if {[opt-val help] ne ""} {
134 incr autosetup(showhelp)
135 use help
136 autosetup_help [opt-val help]
 
 
 
 
 
 
137 }
138
139 if {[opt-val {manual ref reference}] ne ""} {
140 use help
141 autosetup_reference [opt-val {manual ref reference}]
142 }
143
144 # Allow combining --install and --init
145 set earlyexit 0
146 if {[opt-val install] ne ""} {
147 use install
148 autosetup_install [opt-val install]
149 incr earlyexit
150 }
151
152 if {[opt-val init] ne ""} {
153 use init
154 autosetup_init [opt-val init]
155 incr earlyexit
156 }
157
158 if {$earlyexit} {
159 exit 0
 
 
 
 
 
160 }
161
162 if {![file exists $autosetup(autodef)]} {
163 # Check for invalid option first
164 options {}
@@ -210,14 +232,14 @@
210 #
211 # Check each of the named, boolean options and if any have been explicitly enabled
212 # or disabled by the user, return 1 or 0 accordingly.
213 #
214 # If the option was specified more than once, the last value wins.
215 # e.g. With --enable-foo --disable-foo, [opt-bool foo] will return 0
216 #
217 # If no value was specified by the user, returns the default value for the
218 # first option. If -nodefault is given, this behaviour changes and
219 # -1 is returned instead.
220 #
221 proc opt-bool {args} {
222 set nodefault 0
223 if {[lindex $args 0] eq "-nodefault"} {
@@ -237,20 +259,20 @@
237 }
238 # Default value is the default for the first option
239 return [dict get $::autosetup(optdefault) [lindex $args 0]]
240 }
241
242 # @opt-val option-list ?default=""?
243 #
244 # Returns a list containing all the values given for the non-boolean options in 'option-list'.
245 # There will be one entry in the list for each option given by the user, including if the
246 # same option was used multiple times.
247 # If only a single value is required, use something like:
248 #
249 ## lindex [opt-val $names] end
250 #
251 # If no options were set, $default is returned (exactly, not as a list).
252 #
253 proc opt-val {names {default ""}} {
254 option-check-names {*}$names
255
256 foreach opt $names {
@@ -463,35 +485,36 @@
463 options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2]
464 }
465 }
466 }
467
468 # @options options-spec
469 #
470 # Specifies configuration-time options which may be selected by the user
471 # and checked with opt-val and opt-bool. The format of options-spec follows.
 
472 #
473 # A boolean option is of the form:
474 #
475 ## name[=0|1] => "Description of this boolean option"
476 #
477 # The default is name=0, meaning that the option is disabled by default.
478 # If name=1 is used to make the option enabled by default, the description should reflect
479 # that with text like "Disable support for ...".
480 #
481 # An argument option (one which takes a parameter) is of the form:
482 #
483 ## name:[=]value => "Description of this option"
484 #
485 # If the name:value form is used, the value must be provided with the option (as --name=myvalue).
486 # If the name:=value form is used, the value is optional and the given value is used as the default
487 # if it is not provided.
488 #
489 # Undocumented options are also supported by omitting the "=> description.
490 # These options are not displayed with --help and can be useful for internal options or as aliases.
491 #
492 # For example, --disable-lfs is an alias for --disable=largefile:
493 #
494 ## lfs=1 largefile=1 => "Disable large file support"
495 #
496 proc options {optlist} {
497 # Allow options as a list or args
@@ -511,25 +534,24 @@
511 }
512 }
513 }
514
515 proc config_guess {} {
516 if {[file-isexec $::autosetup(dir)/config.guess]} {
517 exec-with-stderr sh $::autosetup(dir)/config.guess
518 if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} {
519 user-error $alias
520 }
521 return $alias
522 } else {
523 configlog "No config.guess, so using uname"
524 string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
525 }
526 }
527
528 proc config_sub {alias} {
529 if {[file-isexec $::autosetup(dir)/config.sub]} {
530 if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} {
531 user-error $alias
532 }
533 }
534 return $alias
535 }
@@ -536,39 +558,45 @@
536
537 # @define name ?value=1?
538 #
539 # Defines the named variable to the given value.
540 # These (name, value) pairs represent the results of the configuration check
541 # and are available to be checked, modified and substituted.
542 #
543 proc define {name {value 1}} {
544 set ::define($name) $value
545 #dputs "$name <= $value"
546 }
547
548 # @undefine name
549 #
550 # Undefine the named variable
551 #
552 proc undefine {name} {
553 unset -nocomplain ::define($name)
554 #dputs "$name <= <undef>"
555 }
556
557 # @define-append name value ...
558 #
559 # Appends the given value(s) to the given 'defined' variable.
560 # If the variable is not defined or empty, it is set to $value.
561 # Otherwise the value is appended, separated by a space.
562 # Any extra values are similarly appended.
563 # If any value is already contained in the variable (as a substring) it is omitted.
564 #
565 proc define-append {name args} {
566 if {[get-define $name ""] ne ""} {
567 # Make a token attempt to avoid duplicates
568 foreach arg $args {
569 if {[string first $arg $::define($name)] == -1} {
 
 
 
 
 
 
570 append ::define($name) " " $arg
571 }
572 }
573 } else {
574 set ::define($name) [join $args]
@@ -576,11 +604,11 @@
576 #dputs "$name += [join $args] => $::define($name)"
577 }
578
579 # @get-define name ?default=0?
580 #
581 # Returns the current value of the 'defined' variable, or $default
582 # if not set.
583 #
584 proc get-define {name {default 0}} {
585 if {[info exists ::define($name)]} {
586 #dputs "$name => $::define($name)"
@@ -598,11 +626,11 @@
598 info exists ::define($name)
599 }
600
601 # @all-defines
602 #
603 # Returns a dictionary (name value list) of all defined variables.
604 #
605 # This is suitable for use with 'dict', 'array set' or 'foreach'
606 # and allows for arbitrary processing of the defined variables.
607 #
608 proc all-defines {} {
@@ -610,13 +638,13 @@
610 }
611
612
613 # @get-env name default
614 #
615 # If $name was specified on the command line, return it.
616 # If $name was set in the environment, return it.
617 # Otherwise return $default.
618 #
619 proc get-env {name default} {
620 if {[dict exists $::autosetup(cmdline) $name]} {
621 return [dict get $::autosetup(cmdline) $name]
622 }
@@ -623,11 +651,11 @@
623 getenv $name $default
624 }
625
626 # @env-is-set name
627 #
628 # Returns 1 if the $name was specified on the command line or in the environment.
629 # Note that an empty environment variable is not considered to be set.
630 #
631 proc env-is-set {name} {
632 if {[dict exists $::autosetup(cmdline) $name]} {
633 return 1
@@ -639,11 +667,11 @@
639 }
640
641 # @readfile filename ?default=""?
642 #
643 # Return the contents of the file, without the trailing newline.
644 # If the file doesn't exist or can't be read, returns $default.
645 #
646 proc readfile {filename {default_value ""}} {
647 set result $default_value
648 catch {
649 set f [open $filename]
@@ -653,11 +681,11 @@
653 return $result
654 }
655
656 # @writefile filename value
657 #
658 # Creates the given file containing $value.
659 # Does not add an extra newline.
660 #
661 proc writefile {filename value} {
662 set f [open $filename w]
663 puts -nonewline $f $value
@@ -677,63 +705,60 @@
677 lappend args [quote-if-needed $arg]
678 }
679 join $args
680 }
681
682 # @suffix suf list
683 #
684 # Takes a list and returns a new list with $suf appended
685 # to each element
686 #
687 ## suffix .c {a b c} => {a.c b.c c.c}
688 #
689 proc suffix {suf list} {
690 set result {}
691 foreach p $list {
692 lappend result $p$suf
 
 
693 }
694 return $result
695 }
696
697 # @prefix pre list
698 #
699 # Takes a list and returns a new list with $pre prepended
700 # to each element
701 #
702 ## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
703 #
704 proc prefix {pre list} {
705 set result {}
706 foreach p $list {
707 lappend result $pre$p
708 }
709 return $result
 
 
 
 
 
 
 
 
 
 
710 }
711
712 # @find-executable name
713 #
714 # Searches the path for an executable with the given name.
715 # Note that the name may include some parameters, e.g. "cc -mbig-endian",
716 # in which case the parameters are ignored.
717 # Returns 1 if found, or 0 if not.
718 #
719 proc find-executable {name} {
720 # Ignore any parameters
721 set name [lindex $name 0]
722 if {$name eq ""} {
723 # The empty string is never a valid executable
724 return 0
725 }
726 foreach p [split-path] {
727 dputs "Looking for $name in $p"
728 set exec [file join $p $name]
729 if {[file-isexec $exec]} {
730 dputs "Found $name -> $exec"
731 return 1
732 }
733 }
734 return 0
735 }
736
737 # @find-an-executable ?-required? name ...
738 #
739 # Given a list of possible executable names,
@@ -764,11 +789,11 @@
764 return ""
765 }
766
767 # @configlog msg
768 #
769 # Writes the given message to the configuration log, config.log
770 #
771 proc configlog {msg} {
772 if {![info exists ::autosetup(logfh)]} {
773 set ::autosetup(logfh) [open config.log w]
774 }
@@ -800,12 +825,12 @@
800 }
801 }
802
803 # @msg-quiet command ...
804 #
805 # msg-quiet evaluates it's arguments as a command with output
806 # from msg-checking and msg-result suppressed.
807 #
808 # This is useful if a check needs to run a subcheck which isn't
809 # of interest to the user.
810 proc msg-quiet {args} {
811 incr ::autosetup(msg-quiet)
@@ -841,11 +866,11 @@
841
842 # @user-error msg
843 #
844 # Indicate incorrect usage to the user, including if required components
845 # or features are not found.
846 # autosetup exits with a non-zero return code.
847 #
848 proc user-error {msg} {
849 show-notices
850 puts stderr "Error: $msg"
851 puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options"
@@ -887,10 +912,22 @@
887 proc maybe-show-timestamp {} {
888 if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} {
889 puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]]
890 }
891 }
 
 
 
 
 
 
 
 
 
 
 
 
892
893 proc autosetup_version {} {
894 return "autosetup v$::autosetup(version)"
895 }
896
@@ -986,23 +1023,35 @@
986 # The latter form is useful for a complex module which requires additional
987 # support file. In this form, '$::usedir' is set to the module directory
988 # when it is loaded.
989 #
990 proc use {args} {
 
 
 
 
 
 
991 foreach m $args {
992 if {[info exists ::libmodule($m)]} {
993 continue
994 }
995 set ::libmodule($m) 1
996 if {[info exists ::modsource($m)]} {
997 automf_load eval $::modsource($m)
998 } else {
999 set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl]
1000 set found 0
1001 foreach source $sources {
1002 if {[file exists $source]} {
1003 incr found
 
 
 
 
 
 
1004 break
1005 }
1006 }
1007 if {$found} {
1008 # For the convenience of the "use" source, point to the directory
@@ -1014,10 +1063,22 @@
1014 autosetup-error "use: No such module: $m"
1015 }
1016 }
1017 }
1018 }
 
 
 
 
 
 
 
 
 
 
 
 
1019
1020 # Load module source in the global scope by executing the given command
1021 proc automf_load {args} {
1022 if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
1023 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
@@ -1027,18 +1088,21 @@
1027 # Initial settings
1028 set autosetup(exe) $::argv0
1029 set autosetup(istcl) 1
1030 set autosetup(start) [clock millis]
1031 set autosetup(installed) 0
 
1032 set autosetup(msg-checking) 0
1033 set autosetup(msg-quiet) 0
 
1034
1035 # Embedded modules are inserted below here
1036 set autosetup(installed) 1
1037 # ----- module asciidoc-formatting -----
 
1038
1039 set modsource(asciidoc-formatting) {
1040 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1041 # All rights reserved
1042
1043 # Module which provides text formatting
1044 # asciidoc format
@@ -1102,13 +1166,13 @@
1102 regsub -all "\n\n" $defn "\n ::\n" defn
1103 puts $defn
1104 }
1105 }
1106
1107 # ----- module formatting -----
1108
1109 set modsource(formatting) {
1110 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1111 # All rights reserved
1112
1113 # Module which provides common text formatting
1114
@@ -1159,13 +1223,13 @@
1159 # Return the result
1160 return $lines
1161 }
1162 }
1163
1164 # ----- module getopt -----
1165
1166 set modsource(getopt) {
1167 # Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/
1168 # All rights reserved
1169
1170 # Simple getopt module
1171
@@ -1197,11 +1261,11 @@
1197
1198 if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} {
1199 # --name=value
1200 dict lappend opts $name [list str $value]
1201 } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} {
1202 if {$prefix in {enable- with- ""}} {
1203 set value 1
1204 } else {
1205 set value 0
1206 }
1207 dict lappend opts $name [list bool $value]
@@ -1218,13 +1282,13 @@
1218
1219 return $opts
1220 }
1221 }
1222
1223 # ----- module help -----
1224
1225 set modsource(help) {
1226 # Copyright (c) 2010 WorkWare Systems http://workware.net.au/
1227 # All rights reserved
1228
1229 # Module which provides usage, help and the command reference
1230
@@ -1251,10 +1315,28 @@
1251 options-show
1252 }
1253 }
1254 exit 0
1255 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1256
1257 # If not already paged and stdout is a tty, pipe the output through the pager
1258 # This is done by reinvoking autosetup with --nopager added
1259 proc use_pager {} {
1260 if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} {
@@ -1304,10 +1386,16 @@
1304 }
1305
1306 proc autosetup_output_block {type lines} {
1307 if {[llength $lines]} {
1308 switch $type {
 
 
 
 
 
 
1309 code {
1310 codelines $lines
1311 }
1312 p {
1313 p [join $lines]
@@ -1325,30 +1413,45 @@
1325 # Generate a command reference from inline documentation
1326 proc automf_command_reference {} {
1327 lappend files $::autosetup(prog)
1328 lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
1329
1330 section "Core Commands"
1331 set type p
1332 set lines {}
1333 set cmd {}
 
 
 
 
 
 
 
1334
1335 foreach file $files {
 
 
1336 set f [open $file]
1337 while {![eof $f]} {
1338 set line [gets $f]
 
 
 
 
 
1339
1340 # Find lines starting with "# @*" and continuing through the remaining comment lines
1341 if {![regexp {^# @(.*)} $line -> cmd]} {
1342 continue
1343 }
1344
1345 # Synopsis or command?
1346 if {$cmd eq "synopsis:"} {
1347 section "Module: [file rootname [file tail $file]]"
 
1348 } else {
1349 subsection $cmd
1350 }
1351
1352 set lines {}
1353 set type p
1354
@@ -1369,29 +1472,38 @@
1369
1370 #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd"
1371
1372 if {$t ne $type || $cmd eq ""} {
1373 # Finish the current block
1374 autosetup_output_block $type $lines
1375 set lines {}
1376 set type $t
1377 }
1378 if {$cmd ne ""} {
1379 lappend lines $cmd
1380 }
1381 }
1382
1383 autosetup_output_block $type $lines
1384 }
1385 close $f
1386 }
 
 
 
 
 
 
 
 
 
1387 }
1388 }
1389
1390 # ----- module init -----
1391
1392 set modsource(init) {
1393 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1394 # All rights reserved
1395
1396 # Module to help create auto.def and configure
1397
@@ -1444,79 +1556,157 @@
1444 }
1445 writefile $filename $contents
1446 }
1447 }
1448
1449 # ----- module install -----
1450
1451 set modsource(install) {
1452 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
1453 # All rights reserved
1454
1455 # Module which can install autosetup
1456
1457 proc autosetup_install {dir} {
1458 if {[catch {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1459 cd $dir
 
 
 
 
1460 file mkdir autosetup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1461
1462 set f [open autosetup/autosetup w]
1463
1464 set publicmodules [glob $::autosetup(libdir)/*.auto]
1465
1466 # First the main script, but only up until "CUT HERE"
1467 set in [open $::autosetup(dir)/autosetup]
1468 while {[gets $in buf] >= 0} {
1469 if {$buf ne "##-- CUT HERE --##"} {
1470 puts $f $buf
1471 continue
1472 }
1473
1474 # Insert the static modules here
1475 # i.e. those which don't contain @synopsis:
 
1476 puts $f "set autosetup(installed) 1"
1477 foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] {
 
 
 
1478 set buf [readfile $file]
1479 if {[string match "*\n# @synopsis:*" $buf]} {
1480 lappend publicmodules $file
1481 continue
 
 
1482 }
1483 set modname [file rootname [file tail $file]]
1484 puts $f "# ----- module $modname -----"
1485 puts $f "\nset modsource($modname) \{"
1486 puts $f $buf
1487 puts $f "\}\n"
1488 }
 
 
 
 
 
 
 
1489 }
1490 close $in
1491 close $f
1492 exec chmod 755 autosetup/autosetup
 
 
 
 
 
 
1493
1494 # Install public modules
1495 foreach file $publicmodules {
1496 autosetup_install_file $file autosetup
 
 
 
 
 
 
1497 }
1498
1499 # Install support files
1500 foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} {
1501 autosetup_install_file $::autosetup(dir)/$file autosetup
1502 }
1503 exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh
1504
1505 writefile autosetup/README.autosetup \
1506 "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n"
1507
 
 
 
 
 
 
 
 
1508 } error]} {
1509 user-error "Failed to install autosetup: $error"
1510 }
1511 puts "Installed [autosetup_version] to autosetup/"
 
 
 
 
 
1512
1513 # Now create 'configure' if necessary
1514 autosetup_create_configure
 
 
1515 }
1516
1517 proc autosetup_create_configure {} {
1518 if {[file exists configure]} {
1519 if {!$::autosetup(force)} {
1520 # Could this be an autosetup configure?
1521 if {![string match "*\nWRAPPER=*" [readfile configure]]} {
1522 puts "I see configure, but not created by autosetup, so I won't overwrite it."
@@ -1527,40 +1717,76 @@
1527 puts "I will overwrite the existing configure because you used --force."
1528 }
1529 } else {
1530 puts "I don't see configure, so I will create it."
1531 }
1532 writefile configure \
 
 
 
 
 
 
 
1533 {#!/bin/sh
1534 dir="`dirname "$0"`/autosetup"
1535 WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
1536 }
 
1537 catch {exec chmod 755 configure}
1538 }
1539
1540 # Append the contents of $file to filehandle $f
1541 proc autosetup_install_append {f file} {
 
1542 set in [open $file]
1543 puts $f [read $in]
1544 close $in
1545 }
1546
1547 proc autosetup_install_file {file dir} {
1548 if {![file exists $file]} {
1549 error "Missing installation file '$file'"
1550 }
1551 writefile [file join $dir [file tail $file]] [readfile $file]\n
1552 }
1553
1554 if {$::autosetup(installed)} {
1555 user-error "autosetup can only be installed from development source, not from installed copy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1556 }
1557 }
1558
1559 # ----- module markdown-formatting -----
1560
1561 set modsource(markdown-formatting) {
1562 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1563 # All rights reserved
1564
1565 # Module which provides text formatting
1566 # markdown format (kramdown syntax)
@@ -1627,13 +1853,13 @@
1627 }
1628 puts "$defn"
1629 }
1630 }
1631
1632 # ----- module misc -----
1633
1634 set modsource(misc) {
1635 # Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/
1636 # All rights reserved
1637
1638 # Module containing misc procs useful to modules
1639 # Largely for platform compatibility
@@ -1805,106 +2031,208 @@
1805 string trim $result
1806 }
1807 }
1808 }
1809
1810 # ----- module text-formatting -----
1811
1812 set modsource(text-formatting) {
1813 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1814 # All rights reserved
1815
1816 # Module which provides text formatting
1817
1818 use formatting
1819
1820 proc wordwrap {text length {firstprefix ""} {nextprefix ""}} {
1821 set len 0
1822 set space $firstprefix
1823 foreach word [split $text] {
1824 set word [string trim $word]
1825 if {$word == ""} {
1826 continue
1827 }
1828 if {$len && [string length $space$word] + $len >= $length} {
1829 puts ""
1830 set len 0
1831 set space $nextprefix
1832 }
1833 incr len [string length $space$word]
1834
1835 # Use man-page conventions for highlighting 'quoted' and *quoted*
1836 # single words.
1837 # Use x^Hx for *bold* and _^Hx for 'underline'.
1838 #
1839 # less and more will both understand this.
1840 # Pipe through 'col -b' to remove them.
1841 if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1842 regsub -all . $bareword "_\b&" word
1843 append word $dot
1844 } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1845 regsub -all . $bareword "&\b&" word
1846 append word $dot
1847 }
1848 puts -nonewline $space$word
1849 set space " "
1850 }
1851 if {$len} {
1852 puts ""
1853 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1854 }
1855 proc title {text} {
1856 underline [string trim $text] =
1857 nl
1858 }
1859 proc p {text} {
1860 wordwrap $text 80
1861 nl
1862 }
1863 proc codelines {lines} {
1864 foreach line $lines {
1865 puts " $line"
1866 }
1867 nl
1868 }
1869 proc nl {} {
1870 puts ""
1871 }
1872 proc underline {text char} {
1873 regexp "^(\[ \t\]*)(.*)" $text -> indent words
1874 puts $text
1875 puts $indent[string repeat $char [string length $words]]
1876 }
1877 proc section {text} {
1878 underline "[string trim $text]" -
1879 nl
1880 }
1881 proc subsection {text} {
1882 underline "$text" ~
1883 nl
1884 }
1885 proc bullet {text} {
1886 wordwrap $text 76 " * " " "
1887 }
1888 proc indent {text} {
1889 wordwrap $text 76 " " " "
1890 }
1891 proc defn {first args} {
1892 if {$first ne ""} {
1893 underline " $first" ~
1894 }
1895 foreach p $args {
1896 if {$p ne ""} {
1897 indent $p
1898 }
1899 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1900 }
1901 }
1902
1903 # ----- module wiki-formatting -----
1904
1905 set modsource(wiki-formatting) {
1906 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1907 # All rights reserved
1908
1909 # Module which provides text formatting
1910 # wiki.tcl.tk format output
@@ -1975,11 +2303,11 @@
1975 if {$autosetup(debug)} {
1976 main $argv
1977 }
1978 if {[catch {main $argv} msg opts] == 1} {
1979 show-notices
1980 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
1981 if {!$autosetup(debug)} {
1982 puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
1983 }
1984 exit 1
1985 }
1986
1987 DDED autosetup/autosetup-config.guess
1988 DDED autosetup/autosetup-config.sub
1989 DDED autosetup/autosetup-find-tclsh
1990 DDED autosetup/autosetup-test-tclsh
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,16 +1,16 @@
1 #!/bin/sh
2 # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
3 # All rights reserved
4 # vim:se syntax=tcl:
5 # \
6 dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
7
8 set autosetup(version) 0.6.8
9
10 # Can be set to 1 to debug early-init problems
11 set autosetup(debug) [expr {"--debug" in $argv}]
12
13 ##################################################################
14 #
15 # Main flow of control, option handling
16 #
@@ -87,15 +87,28 @@
87 set autosetup(getopt) [getopt argv]
88
89 #"=Core Options:"
90 options-add {
91 help:=local => "display help and options. Optionally specify a module name, such as --help=system"
92 licence license => "display the autosetup license"
93 version => "display the version of autosetup"
94 ref:=text manual:=text
95 reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
96 debug => "display debugging output as autosetup runs"
97 install:=. => "install autosetup to the current or given directory"
98 }
99 if {$autosetup(installed)} {
100 # hidden options so we can produce a nice error
101 options-add {
102 sysinstall:path
103 }
104 } else {
105 options-add {
106 sysinstall:path => "install standalone autosetup to the given directory (e.g.: /usr/local)"
107 }
108 }
109 options-add {
110 force init:=help => "create initial auto.def, etc. Use --init=help for known types"
111 # Undocumented options
112 option-checking=1
113 nopager
114 quiet
@@ -108,11 +121,11 @@
121 exit 0
122 }
123
124 # autosetup --conf=alternate-auto.def
125 if {[opt-val conf] ne ""} {
126 set autosetup(autodef) [lindex [opt-val conf] end]
127 }
128
129 # Debugging output (set this early)
130 incr autosetup(debug) [opt-bool debug]
131 incr autosetup(force) [opt-bool force]
@@ -124,41 +137,50 @@
137 if {[file exists $autosetup(libdir)/local.tcl]} {
138 use local
139 }
140
141 # Now any auto-load modules
142 autosetup_load_auto_modules
 
 
143
144 if {[opt-val help] ne ""} {
145 incr autosetup(showhelp)
146 use help
147 autosetup_help [lindex [opt-val help] end]
148 }
149
150 if {[opt-bool licence license]} {
151 use help
152 autosetup_show_license
153 exit 0
154 }
155
156 if {[opt-val {manual ref reference}] ne ""} {
157 use help
158 autosetup_reference [lindex [opt-val {manual ref reference}] end]
159 }
160
161 # Allow combining --install and --init
162 set earlyexit 0
163 if {[opt-val install] ne ""} {
164 use install
165 autosetup_install [lindex [opt-val install] end]
166 incr earlyexit
167 }
168
169 if {[opt-val init] ne ""} {
170 use init
171 autosetup_init [lindex [opt-val init] end]
172 incr earlyexit
173 }
174
175 if {$earlyexit} {
176 exit 0
177 }
178 if {[opt-val sysinstall] ne ""} {
179 use install
180 autosetup_install [lindex [opt-val sysinstall] end] 1
181 exit 0
182 }
183
184 if {![file exists $autosetup(autodef)]} {
185 # Check for invalid option first
186 options {}
@@ -210,14 +232,14 @@
232 #
233 # Check each of the named, boolean options and if any have been explicitly enabled
234 # or disabled by the user, return 1 or 0 accordingly.
235 #
236 # If the option was specified more than once, the last value wins.
237 # e.g. With '--enable-foo --disable-foo', '[opt-bool foo]' will return 0
238 #
239 # If no value was specified by the user, returns the default value for the
240 # first option. If '-nodefault' is given, this behaviour changes and
241 # -1 is returned instead.
242 #
243 proc opt-bool {args} {
244 set nodefault 0
245 if {[lindex $args 0] eq "-nodefault"} {
@@ -237,20 +259,20 @@
259 }
260 # Default value is the default for the first option
261 return [dict get $::autosetup(optdefault) [lindex $args 0]]
262 }
263
264 # @opt-val optionlist ?default=""?
265 #
266 # Returns a list containing all the values given for the non-boolean options in '$optionlist'.
267 # There will be one entry in the list for each option given by the user, including if the
268 # same option was used multiple times.
269 # If only a single value is required, use something like:
270 #
271 ## lindex [opt-val $names] end
272 #
273 # If no options were set, '$default' is returned (exactly, not as a list).
274 #
275 proc opt-val {names {default ""}} {
276 option-check-names {*}$names
277
278 foreach opt $names {
@@ -463,35 +485,36 @@
485 options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2]
486 }
487 }
488 }
489
490 # @options optionspec
491 #
492 # Specifies configuration-time options which may be selected by the user
493 # and checked with 'opt-val' and 'opt-bool'. '$optionspec' contains a series
494 # of options specifications separated by newlines, as follows:
495 #
496 # A boolean option is of the form:
497 #
498 ## name[=0|1] => "Description of this boolean option"
499 #
500 # The default is 'name=0', meaning that the option is disabled by default.
501 # If 'name=1' is used to make the option enabled by default, the description should reflect
502 # that with text like "Disable support for ...".
503 #
504 # An argument option (one which takes a parameter) is of the form:
505 #
506 ## name:[=]value => "Description of this option"
507 #
508 # If the 'name:value' form is used, the value must be provided with the option (as '--name=myvalue').
509 # If the 'name:=value' form is used, the value is optional and the given value is used as the default
510 # if it is not provided.
511 #
512 # Undocumented options are also supported by omitting the '=> description'.
513 # These options are not displayed with '--help' and can be useful for internal options or as aliases.
514 #
515 # For example, '--disable-lfs' is an alias for '--disable=largefile':
516 #
517 ## lfs=1 largefile=1 => "Disable large file support"
518 #
519 proc options {optlist} {
520 # Allow options as a list or args
@@ -511,25 +534,24 @@
534 }
535 }
536 }
537
538 proc config_guess {} {
539 if {[file-isexec $::autosetup(dir)/autosetup-config.guess]} {
540 if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.guess} alias]} {
 
541 user-error $alias
542 }
543 return $alias
544 } else {
545 configlog "No autosetup-config.guess, so using uname"
546 string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
547 }
548 }
549
550 proc config_sub {alias} {
551 if {[file-isexec $::autosetup(dir)/autosetup-config.sub]} {
552 if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.sub $alias} alias]} {
553 user-error $alias
554 }
555 }
556 return $alias
557 }
@@ -536,39 +558,45 @@
558
559 # @define name ?value=1?
560 #
561 # Defines the named variable to the given value.
562 # These (name, value) pairs represent the results of the configuration check
563 # and are available to be subsequently checked, modified and substituted.
564 #
565 proc define {name {value 1}} {
566 set ::define($name) $value
567 #dputs "$name <= $value"
568 }
569
570 # @undefine name
571 #
572 # Undefine the named variable.
573 #
574 proc undefine {name} {
575 unset -nocomplain ::define($name)
576 #dputs "$name <= <undef>"
577 }
578
579 # @define-append name value ...
580 #
581 # Appends the given value(s) to the given "defined" variable.
582 # If the variable is not defined or empty, it is set to '$value'.
583 # Otherwise the value is appended, separated by a space.
584 # Any extra values are similarly appended.
585 # If any value is already contained in the variable (as a substring) it is omitted.
586 #
587 proc define-append {name args} {
588 if {[get-define $name ""] ne ""} {
589 # Avoid duplicates
590 foreach arg $args {
591 set found 0
592 foreach str [split $::define($name) " "] {
593 if {$str eq $arg} {
594 incr found
595 }
596 }
597 if {!$found} {
598 append ::define($name) " " $arg
599 }
600 }
601 } else {
602 set ::define($name) [join $args]
@@ -576,11 +604,11 @@
604 #dputs "$name += [join $args] => $::define($name)"
605 }
606
607 # @get-define name ?default=0?
608 #
609 # Returns the current value of the "defined" variable, or '$default'
610 # if not set.
611 #
612 proc get-define {name {default 0}} {
613 if {[info exists ::define($name)]} {
614 #dputs "$name => $::define($name)"
@@ -598,11 +626,11 @@
626 info exists ::define($name)
627 }
628
629 # @all-defines
630 #
631 # Returns a dictionary (name, value list) of all defined variables.
632 #
633 # This is suitable for use with 'dict', 'array set' or 'foreach'
634 # and allows for arbitrary processing of the defined variables.
635 #
636 proc all-defines {} {
@@ -610,13 +638,13 @@
638 }
639
640
641 # @get-env name default
642 #
643 # If '$name' was specified on the command line, return it.
644 # Otherwise if '$name' was set in the environment, return it.
645 # Otherwise return '$default'.
646 #
647 proc get-env {name default} {
648 if {[dict exists $::autosetup(cmdline) $name]} {
649 return [dict get $::autosetup(cmdline) $name]
650 }
@@ -623,11 +651,11 @@
651 getenv $name $default
652 }
653
654 # @env-is-set name
655 #
656 # Returns 1 if '$name' was specified on the command line or in the environment.
657 # Note that an empty environment variable is not considered to be set.
658 #
659 proc env-is-set {name} {
660 if {[dict exists $::autosetup(cmdline) $name]} {
661 return 1
@@ -639,11 +667,11 @@
667 }
668
669 # @readfile filename ?default=""?
670 #
671 # Return the contents of the file, without the trailing newline.
672 # If the file doesn't exist or can't be read, returns '$default'.
673 #
674 proc readfile {filename {default_value ""}} {
675 set result $default_value
676 catch {
677 set f [open $filename]
@@ -653,11 +681,11 @@
681 return $result
682 }
683
684 # @writefile filename value
685 #
686 # Creates the given file containing '$value'.
687 # Does not add an extra newline.
688 #
689 proc writefile {filename value} {
690 set f [open $filename w]
691 puts -nonewline $f $value
@@ -677,63 +705,60 @@
705 lappend args [quote-if-needed $arg]
706 }
707 join $args
708 }
709
710 # @list-non-empty list
711 #
712 # Returns a copy of the given list with empty elements removed
713 proc list-non-empty {list} {
 
 
 
 
714 set result {}
715 foreach p $list {
716 if {$p ne ""} {
717 lappend result $p
718 }
719 }
720 return $result
721 }
722
723 # @find-executable-path name
724 #
725 # Searches the path for an executable with the given name.
726 # Note that the name may include some parameters, e.g. 'cc -mbig-endian',
727 # in which case the parameters are ignored.
728 # The full path to the executable if found, or "" if not found.
729 # Returns 1 if found, or 0 if not.
730 #
731 proc find-executable-path {name} {
732 # Ignore any parameters
733 set name [lindex $name 0]
734 # The empty string is never a valid executable
735 if {$name ne ""} {
736 foreach p [split-path] {
737 dputs "Looking for $name in $p"
738 set exec [file join $p $name]
739 if {[file-isexec $exec]} {
740 dputs "Found $name -> $exec"
741 return $exec
742 }
743 }
744 }
745 return {}
746 }
747
748 # @find-executable name
749 #
750 # Searches the path for an executable with the given name.
751 # Note that the name may include some parameters, e.g. 'cc -mbig-endian',
752 # in which case the parameters are ignored.
753 # Returns 1 if found, or 0 if not.
754 #
755 proc find-executable {name} {
756 if {[find-executable-path $name] eq {}} {
757 return 0
758 }
759 return 1
 
 
 
 
 
 
 
 
 
 
 
760 }
761
762 # @find-an-executable ?-required? name ...
763 #
764 # Given a list of possible executable names,
@@ -764,11 +789,11 @@
789 return ""
790 }
791
792 # @configlog msg
793 #
794 # Writes the given message to the configuration log, 'config.log'.
795 #
796 proc configlog {msg} {
797 if {![info exists ::autosetup(logfh)]} {
798 set ::autosetup(logfh) [open config.log w]
799 }
@@ -800,12 +825,12 @@
825 }
826 }
827
828 # @msg-quiet command ...
829 #
830 # 'msg-quiet' evaluates it's arguments as a command with output
831 # from 'msg-checking' and 'msg-result' suppressed.
832 #
833 # This is useful if a check needs to run a subcheck which isn't
834 # of interest to the user.
835 proc msg-quiet {args} {
836 incr ::autosetup(msg-quiet)
@@ -841,11 +866,11 @@
866
867 # @user-error msg
868 #
869 # Indicate incorrect usage to the user, including if required components
870 # or features are not found.
871 # 'autosetup' exits with a non-zero return code.
872 #
873 proc user-error {msg} {
874 show-notices
875 puts stderr "Error: $msg"
876 puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options"
@@ -887,10 +912,22 @@
912 proc maybe-show-timestamp {} {
913 if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} {
914 puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]]
915 }
916 }
917
918 # @autosetup-require-version required
919 #
920 # Checks the current version of 'autosetup' against '$required'.
921 # A fatal error is generated if the current version is less than that required.
922 #
923 proc autosetup-require-version {required} {
924 use util
925 if {[compare-versions $::autosetup(version) $required] < 0} {
926 user-error "autosetup version $required is required, but this is $::autosetup(version)"
927 }
928 }
929
930 proc autosetup_version {} {
931 return "autosetup v$::autosetup(version)"
932 }
933
@@ -986,23 +1023,35 @@
1023 # The latter form is useful for a complex module which requires additional
1024 # support file. In this form, '$::usedir' is set to the module directory
1025 # when it is loaded.
1026 #
1027 proc use {args} {
1028 global autosetup libmodule modsource
1029
1030 set dirs [list $autosetup(libdir)]
1031 if {[info exists autosetup(srcdir)]} {
1032 lappend dirs $autosetup(srcdir)/autosetup
1033 }
1034 foreach m $args {
1035 if {[info exists libmodule($m)]} {
1036 continue
1037 }
1038 set libmodule($m) 1
1039 if {[info exists modsource(${m}.tcl)]} {
1040 automf_load eval $modsource(${m}.tcl)
1041 } else {
1042 set locs [list ${m}.tcl ${m}/init.tcl]
1043 set found 0
1044 foreach dir $dirs {
1045 foreach loc $locs {
1046 set source $dir/$loc
1047 if {[file exists $source]} {
1048 incr found
1049 break
1050 }
1051 }
1052 if {$found} {
1053 break
1054 }
1055 }
1056 if {$found} {
1057 # For the convenience of the "use" source, point to the directory
@@ -1014,10 +1063,22 @@
1063 autosetup-error "use: No such module: $m"
1064 }
1065 }
1066 }
1067 }
1068
1069 proc autosetup_load_auto_modules {} {
1070 global autosetup modsource
1071 # First load any embedded auto modules
1072 foreach mod [array names modsource *.auto] {
1073 automf_load eval $modsource($mod)
1074 }
1075 # Now any external auto modules
1076 foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
1077 automf_load source $file
1078 }
1079 }
1080
1081 # Load module source in the global scope by executing the given command
1082 proc automf_load {args} {
1083 if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
1084 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
@@ -1027,18 +1088,21 @@
1088 # Initial settings
1089 set autosetup(exe) $::argv0
1090 set autosetup(istcl) 1
1091 set autosetup(start) [clock millis]
1092 set autosetup(installed) 0
1093 set autosetup(sysinstall) 0
1094 set autosetup(msg-checking) 0
1095 set autosetup(msg-quiet) 0
1096 set autosetup(inittypes) {}
1097
1098 # Embedded modules are inserted below here
1099 set autosetup(installed) 1
1100 set autosetup(sysinstall) 0
1101 # ----- @module asciidoc-formatting.tcl -----
1102
1103 set modsource(asciidoc-formatting.tcl) {
1104 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1105 # All rights reserved
1106
1107 # Module which provides text formatting
1108 # asciidoc format
@@ -1102,13 +1166,13 @@
1166 regsub -all "\n\n" $defn "\n ::\n" defn
1167 puts $defn
1168 }
1169 }
1170
1171 # ----- @module formatting.tcl -----
1172
1173 set modsource(formatting.tcl) {
1174 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1175 # All rights reserved
1176
1177 # Module which provides common text formatting
1178
@@ -1159,13 +1223,13 @@
1223 # Return the result
1224 return $lines
1225 }
1226 }
1227
1228 # ----- @module getopt.tcl -----
1229
1230 set modsource(getopt.tcl) {
1231 # Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/
1232 # All rights reserved
1233
1234 # Simple getopt module
1235
@@ -1197,11 +1261,11 @@
1261
1262 if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} {
1263 # --name=value
1264 dict lappend opts $name [list str $value]
1265 } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} {
1266 if {$prefix in {enable- ""}} {
1267 set value 1
1268 } else {
1269 set value 0
1270 }
1271 dict lappend opts $name [list bool $value]
@@ -1218,13 +1282,13 @@
1282
1283 return $opts
1284 }
1285 }
1286
1287 # ----- @module help.tcl -----
1288
1289 set modsource(help.tcl) {
1290 # Copyright (c) 2010 WorkWare Systems http://workware.net.au/
1291 # All rights reserved
1292
1293 # Module which provides usage, help and the command reference
1294
@@ -1251,10 +1315,28 @@
1315 options-show
1316 }
1317 }
1318 exit 0
1319 }
1320
1321 proc autosetup_show_license {} {
1322 global modsource autosetup
1323 use_pager
1324
1325 if {[info exists modsource(LICENSE)]} {
1326 puts $modsource(LICENSE)
1327 return
1328 }
1329 foreach dir [list $autosetup(libdir) $autosetup(srcdir)] {
1330 set path [file join $dir LICENSE]
1331 if {[file exists $path]} {
1332 puts [readfile $path]
1333 return
1334 }
1335 }
1336 puts "LICENSE not found"
1337 }
1338
1339 # If not already paged and stdout is a tty, pipe the output through the pager
1340 # This is done by reinvoking autosetup with --nopager added
1341 proc use_pager {} {
1342 if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} {
@@ -1304,10 +1386,16 @@
1386 }
1387
1388 proc autosetup_output_block {type lines} {
1389 if {[llength $lines]} {
1390 switch $type {
1391 section {
1392 section $lines
1393 }
1394 subsection {
1395 subsection $lines
1396 }
1397 code {
1398 codelines $lines
1399 }
1400 p {
1401 p [join $lines]
@@ -1325,30 +1413,45 @@
1413 # Generate a command reference from inline documentation
1414 proc automf_command_reference {} {
1415 lappend files $::autosetup(prog)
1416 lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
1417
1418 # We want to process all non-module files before module files
1419 # and then modules in alphabetical order.
1420 # So examine all files and extract docs into doc($modulename) and doc(_core_)
1421 #
1422 # Each entry is a list of {type data} where $type is one of: section, subsection, code, list, p
1423 # and $data is a string for section, subsection or a list of text lines for other types.
1424
1425 # XXX: Should commands be in alphabetical order too? Currently they are in file order.
1426
1427 set doc(_core_) {}
1428 lappend doc(_core_) [list section "Core Commands"]
1429
1430 foreach file $files {
1431 set modulename [file rootname [file tail $file]]
1432 set current _core_
1433 set f [open $file]
1434 while {![eof $f]} {
1435 set line [gets $f]
1436
1437 # Find embedded module names
1438 if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
1439 continue
1440 }
1441
1442 # Find lines starting with "# @*" and continuing through the remaining comment lines
1443 if {![regexp {^# @(.*)} $line -> cmd]} {
1444 continue
1445 }
1446
1447 # Synopsis or command?
1448 if {$cmd eq "synopsis:"} {
1449 set current $modulename
1450 lappend doc($current) [list section "Module: $modulename"]
1451 } else {
1452 lappend doc($current) [list subsection $cmd]
1453 }
1454
1455 set lines {}
1456 set type p
1457
@@ -1369,29 +1472,38 @@
1472
1473 #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd"
1474
1475 if {$t ne $type || $cmd eq ""} {
1476 # Finish the current block
1477 lappend doc($current) [list $type $lines]
1478 set lines {}
1479 set type $t
1480 }
1481 if {$cmd ne ""} {
1482 lappend lines $cmd
1483 }
1484 }
1485
1486 lappend doc($current) [list $type $lines]
1487 }
1488 close $f
1489 }
1490
1491 # Now format and output the results
1492
1493 # _core_ will sort first
1494 foreach module [lsort [array names doc]] {
1495 foreach item $doc($module) {
1496 autosetup_output_block {*}$item
1497 }
1498 }
1499 }
1500 }
1501
1502 # ----- @module init.tcl -----
1503
1504 set modsource(init.tcl) {
1505 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1506 # All rights reserved
1507
1508 # Module to help create auto.def and configure
1509
@@ -1444,79 +1556,157 @@
1556 }
1557 writefile $filename $contents
1558 }
1559 }
1560
1561 # ----- @module install.tcl -----
1562
1563 set modsource(install.tcl) {
1564 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
1565 # All rights reserved
1566
1567 # Module which can install autosetup
1568
1569 # autosetup(installed)=1 means that autosetup is not running from source
1570 # autosetup(sysinstall)=1 means that autosetup is running from a sysinstall verion
1571 # shared=1 means that we are trying to do a sysinstall. This is only possible from the development source.
1572
1573 proc autosetup_install {dir {shared 0}} {
1574 global autosetup
1575 if {$shared} {
1576 if {$autosetup(installed) || $autosetup(sysinstall)} {
1577 user-error "Can only --sysinstall from development sources"
1578 }
1579 } elseif {$autosetup(installed)} {
1580 user-error "Can't --install from project install"
1581 }
1582
1583 if {$autosetup(sysinstall)} {
1584 # This is the sysinstall version, so install just uses references
1585 cd $dir
1586
1587 puts "[autosetup_version] creating configure to use system-installed autosetup"
1588 autosetup_create_configure 1
1589 puts "Creating autosetup/README.autosetup"
1590 file mkdir autosetup
1591 autosetup_install_readme autosetup/README.autosetup 1
1592 return
1593 }
1594
1595 if {[catch {
1596 if {$shared} {
1597 set target $dir/bin/autosetup
1598 set installedas $target
1599 } else {
1600 if {$dir eq "."} {
1601 set installedas autosetup
1602 } else {
1603 set installedas $dir/autosetup
1604 }
1605 cd $dir
1606 file mkdir autosetup
1607 set target autosetup/autosetup
1608 }
1609 set targetdir [file dirname $target]
1610 file mkdir $targetdir
1611
1612 set f [open $target w]
1613
1614 set publicmodules {}
1615
1616 # First the main script, but only up until "CUT HERE"
1617 set in [open $autosetup(dir)/autosetup]
1618 while {[gets $in buf] >= 0} {
1619 if {$buf ne "##-- CUT HERE --##"} {
1620 puts $f $buf
1621 continue
1622 }
1623
1624 # Insert the static modules here
1625 # i.e. those which don't contain @synopsis:
1626 # All modules are inserted if $shared is set
1627 puts $f "set autosetup(installed) 1"
1628 puts $f "set autosetup(sysinstall) $shared"
1629 foreach file [lsort [glob $autosetup(libdir)/*.{tcl,auto}]] {
1630 set modname [file tail $file]
1631 set ext [file ext $modname]
1632 set buf [readfile $file]
1633 if {!$shared} {
1634 if {$ext eq ".auto" || [string match "*\n# @synopsis:*" $buf]} {
1635 lappend publicmodules $file
1636 continue
1637 }
1638 }
1639 dputs "install: importing lib/[file tail $file]"
1640 puts $f "# ----- @module $modname -----"
1641 puts $f "\nset modsource($modname) \{"
1642 puts $f $buf
1643 puts $f "\}\n"
1644 }
1645 if {$shared} {
1646 foreach {srcname destname} [list $autosetup(libdir)/README.autosetup-lib README.autosetup \
1647 $autosetup(srcdir)/LICENSE LICENSE] {
1648 dputs "install: importing $srcname as $destname"
1649 puts $f "\nset modsource($destname) \\\n[list [readfile $srcname]\n]\n"
1650 }
1651 }
1652 }
1653 close $in
1654 close $f
1655 catch {exec chmod 755 $target}
1656
1657 set installfiles {autosetup-config.guess autosetup-config.sub autosetup-test-tclsh}
1658 set removefiles {}
1659
1660 if {!$shared} {
1661 autosetup_install_readme $targetdir/README.autosetup 0
1662
1663 # Install public modules
1664 foreach file $publicmodules {
1665 set tail [file tail $file]
1666 autosetup_install_file $file $targetdir/$tail
1667 }
1668 lappend installfiles jimsh0.c autosetup-find-tclsh LICENSE
1669 lappend removefiles config.guess config.sub test-tclsh find-tclsh
1670 } else {
1671 lappend installfiles {sys-find-tclsh autosetup-find-tclsh}
1672 }
1673
1674 # Install support files
1675 foreach fileinfo $installfiles {
1676 if {[llength $fileinfo] == 2} {
1677 lassign $fileinfo source dest
1678 } else {
1679 lassign $fileinfo source
1680 set dest $source
1681 }
1682 autosetup_install_file $autosetup(dir)/$source $targetdir/$dest
1683 }
1684
1685 # Remove obsolete files
1686 foreach file $removefiles {
1687 if {[file exists $targetdir/$file]} {
1688 file delete $targetdir/$file
1689 }
1690 }
1691 } error]} {
1692 user-error "Failed to install autosetup: $error"
1693 }
1694 if {$shared} {
1695 set type "system"
1696 } else {
1697 set type "local"
1698 }
1699 puts "Installed $type [autosetup_version] to $installedas"
1700
1701 if {!$shared} {
1702 # Now create 'configure' if necessary
1703 autosetup_create_configure 0
1704 }
1705 }
1706
1707 proc autosetup_create_configure {shared} {
1708 if {[file exists configure]} {
1709 if {!$::autosetup(force)} {
1710 # Could this be an autosetup configure?
1711 if {![string match "*\nWRAPPER=*" [readfile configure]]} {
1712 puts "I see configure, but not created by autosetup, so I won't overwrite it."
@@ -1527,40 +1717,76 @@
1717 puts "I will overwrite the existing configure because you used --force."
1718 }
1719 } else {
1720 puts "I don't see configure, so I will create it."
1721 }
1722 if {$shared} {
1723 writefile configure \
1724 {#!/bin/sh
1725 # Note that WRAPPER is set here purely to detect an autosetup-created script
1726 WRAPPER="-"; "autosetup" "$@"
1727 }
1728 } else {
1729 writefile configure \
1730 {#!/bin/sh
1731 dir="`dirname "$0"`/autosetup"
1732 WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
1733 }
1734 }
1735 catch {exec chmod 755 configure}
1736 }
1737
1738 # Append the contents of $file to filehandle $f
1739 proc autosetup_install_append {f file} {
1740 dputs "install: include $file"
1741 set in [open $file]
1742 puts $f [read $in]
1743 close $in
1744 }
1745
1746 proc autosetup_install_file {source target} {
1747 dputs "install: $source => $target"
1748 if {![file exists $source]} {
1749 error "Missing installation file '$source'"
1750 }
1751 writefile $target [readfile $source]\n
1752 # If possible, copy the file mode
1753 file stat $source stat
1754 set mode [format %o [expr {$stat(mode) & 0x1ff}]]
1755 catch {exec chmod $mode $target}
1756 }
1757
1758 proc autosetup_install_readme {target sysinstall} {
1759 set readme "README.autosetup created by [autosetup_version]\n\n"
1760 if {$sysinstall} {
1761 append readme \
1762 {This is the autosetup directory for a system install of autosetup.
1763 Loadable modules can be added here.
1764 }
1765 } else {
1766 append readme \
1767 {This is the autosetup directory for a local install of autosetup.
1768 It contains autosetup, support files and loadable modules.
1769 }
1770 }
1771
1772 append readme {
1773 *.tcl files in this directory are optional modules which
1774 can be loaded with the 'use' directive.
1775
1776 *.auto files in this directory are auto-loaded.
1777
1778 For more information, see http://msteveb.github.com/autosetup/
1779 }
1780 dputs "install: autosetup/README.autosetup"
1781 writefile $target $readme
1782 }
1783 }
1784
1785 # ----- @module markdown-formatting.tcl -----
1786
1787 set modsource(markdown-formatting.tcl) {
1788 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1789 # All rights reserved
1790
1791 # Module which provides text formatting
1792 # markdown format (kramdown syntax)
@@ -1627,13 +1853,13 @@
1853 }
1854 puts "$defn"
1855 }
1856 }
1857
1858 # ----- @module misc.tcl -----
1859
1860 set modsource(misc.tcl) {
1861 # Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/
1862 # All rights reserved
1863
1864 # Module containing misc procs useful to modules
1865 # Largely for platform compatibility
@@ -1805,106 +2031,208 @@
2031 string trim $result
2032 }
2033 }
2034 }
2035
2036 # ----- @module text-formatting.tcl -----
2037
2038 set modsource(text-formatting.tcl) {
2039 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2040 # All rights reserved
2041
2042 # Module which provides text formatting
2043
2044 use formatting
2045
2046 proc wordwrap {text length {firstprefix ""} {nextprefix ""}} {
2047 set len 0
2048 set space $firstprefix
2049
2050 foreach word [split $text] {
2051 set word [string trim $word]
2052 if {$word eq ""} {
2053 continue
2054 }
2055 if {[info exists partial]} {
2056 append partial " " $word
2057 if {[string first $quote $word] < 0} {
2058 # Haven't found end of quoted word
2059 continue
2060 }
2061 # Finished quoted word
2062 set word $partial
2063 unset partial
2064 unset quote
2065 } else {
2066 set quote [string index $word 0]
2067 if {$quote in {' *}} {
2068 if {[string first $quote $word 1] < 0} {
2069 # Haven't found end of quoted word
2070 # Not a whole word.
2071 set first [string index $word 0]
2072 # Start of quoted word
2073 set partial $word
2074 continue
2075 }
2076 }
2077 }
2078
2079 if {$len && [string length $space$word] + $len >= $length} {
2080 puts ""
2081 set len 0
2082 set space $nextprefix
2083 }
2084 incr len [string length $space$word]
2085
2086 # Use man-page conventions for highlighting 'quoted' and *quoted*
2087 # single words.
2088 # Use x^Hx for *bold* and _^Hx for 'underline'.
2089 #
2090 # less and more will both understand this.
2091 # Pipe through 'col -b' to remove them.
2092 if {[regexp {^'(.*)'(.*)} $word -> quoted after]} {
2093 set quoted [string map {~ " "} $quoted]
2094 regsub -all . $quoted "&\b&" quoted
2095 set word $quoted$after
2096 } elseif {[regexp {^[*](.*)[*](.*)} $word -> quoted after]} {
2097 set quoted [string map {~ " "} $quoted]
2098 regsub -all . $quoted "_\b&" quoted
2099 set word $quoted$after
2100 }
2101 puts -nonewline $space$word
2102 set space " "
2103 }
2104 if {[info exists partial]} {
2105 # Missing end of quote
2106 puts -nonewline $space$partial
2107 }
2108 if {$len} {
2109 puts ""
2110 }
2111 }
2112 proc title {text} {
2113 underline [string trim $text] =
2114 nl
2115 }
2116 proc p {text} {
2117 wordwrap $text 80
2118 nl
2119 }
2120 proc codelines {lines} {
2121 foreach line $lines {
2122 puts " $line"
2123 }
2124 nl
2125 }
2126 proc nl {} {
2127 puts ""
2128 }
2129 proc underline {text char} {
2130 regexp "^(\[ \t\]*)(.*)" $text -> indent words
2131 puts $text
2132 puts $indent[string repeat $char [string length $words]]
2133 }
2134 proc section {text} {
2135 underline "[string trim $text]" -
2136 nl
2137 }
2138 proc subsection {text} {
2139 underline "$text" ~
2140 nl
2141 }
2142 proc bullet {text} {
2143 wordwrap $text 76 " * " " "
2144 }
2145 proc indent {text} {
2146 wordwrap $text 76 " " " "
2147 }
2148 proc defn {first args} {
2149 if {$first ne ""} {
2150 underline " $first" ~
2151 }
2152 foreach p $args {
2153 if {$p ne ""} {
2154 indent $p
2155 }
2156 }
2157 }
2158 }
2159
2160 # ----- @module util.tcl -----
2161
2162 set modsource(util.tcl) {
2163 # Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/
2164 # All rights reserved
2165
2166 # Module which contains miscellaneous utility functions
2167
2168 # @compare-versions version1 version2
2169 #
2170 # Versions are of the form 'a.b.c' (may be any number of numeric components)
2171 #
2172 # Compares the two versions and returns:
2173 ## -1 if v1 < v2
2174 ## 0 if v1 == v2
2175 ## 1 if v1 > v2
2176 #
2177 # If one version has fewer components than the other, 0 is substituted to the right. e.g.
2178 ## 0.2 < 0.3
2179 ## 0.2.5 > 0.2
2180 ## 1.1 == 1.1.0
2181 #
2182 proc compare-versions {v1 v2} {
2183 foreach c1 [split $v1 .] c2 [split $v2 .] {
2184 if {$c1 eq ""} {
2185 set c1 0
2186 }
2187 if {$c2 eq ""} {
2188 set c2 0
2189 }
2190 if {$c1 < $c2} {
2191 return -1
2192 }
2193 if {$c1 > $c2} {
2194 return 1
2195 }
2196 }
2197 return 0
2198 }
2199
2200 # @suffix suf list
2201 #
2202 # Takes a list and returns a new list with '$suf' appended
2203 # to each element
2204 #
2205 ## suffix .c {a b c} => {a.c b.c c.c}
2206 #
2207 proc suffix {suf list} {
2208 set result {}
2209 foreach p $list {
2210 lappend result $p$suf
2211 }
2212 return $result
2213 }
2214
2215 # @prefix pre list
2216 #
2217 # Takes a list and returns a new list with '$pre' prepended
2218 # to each element
2219 #
2220 ## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
2221 #
2222 proc prefix {pre list} {
2223 set result {}
2224 foreach p $list {
2225 lappend result $pre$p
2226 }
2227 return $result
2228 }
2229 }
2230
2231 # ----- @module wiki-formatting.tcl -----
2232
2233 set modsource(wiki-formatting.tcl) {
2234 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2235 # All rights reserved
2236
2237 # Module which provides text formatting
2238 # wiki.tcl.tk format output
@@ -1975,11 +2303,11 @@
2303 if {$autosetup(debug)} {
2304 main $argv
2305 }
2306 if {[catch {main $argv} msg opts] == 1} {
2307 show-notices
2308 autosetup-full-error [error-dump $msg $opts $autosetup(debug)]
2309 if {!$autosetup(debug)} {
2310 puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
2311 }
2312 exit 1
2313 }
2314
2315 DDED autosetup/autosetup-config.guess
2316 DDED autosetup/autosetup-config.sub
2317 DDED autosetup/autosetup-find-tclsh
2318 DDED autosetup/autosetup-test-tclsh
--- a/autosetup/autosetup-config.guess
+++ b/autosetup/autosetup-config.guess
@@ -0,0 +1,50 @@
1
+#! /bin/sh
2
+# Attempt to guess a canonical system name.
3
+# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
4
+# under the terms of the GNU General Public License as published by
5
+# t;e Free Software Foundation, either version 3 of the L;cense, or
6
+# (at your option) any later version.
7
+#
8
+# This program is distributed in the hope that it will be useful, but
9
+# WITHOUT ANY WARRANTY; without even the implied warranty of
10
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+# General Public License for more details.
12
+#
13
+# You should have received a copy of the GNU General Public License
14
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
15
+#
16
+# As a special exceptionto the GNU General Public License, if you
17
+# distribute this file as part of a program that contains a
18
+# configuration script generated by Autoconf, you may include it under
19
+# the same distribution terms that you use for the rest of that
20
+# program. This Exception is an additional permission under section 7
21
+# of the GNU General Public License, version 3 ("GPLv3").
22
+#
23
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
24
+#
25
+# You can get the latest version of this script from:
26
+# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
27
+
28
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
29
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
30
+# Attempt to guess a canoniAttempt to g! /bin/sh
31
+# Attemp#*) machine=${! /bin/sh
32
+# Attemp#! /bin/sh
33
+# Attempt to guess a canonical system name.
34
+# Copyright 1992-2018canonical system name.
35
+# Copyrig! /bin/sh
36
+# Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
37
+# Attemp#! /bin/sh
38
+# Attempt to guess a ${! /bin/sh
39
+# Attemp#! /bin/sh
40
+# Attempt to guess a cekkoBSD:*:*)
41
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
42
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
43
+# Attempt to guess a canonical system name.
44
+# Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
45
+# Copyright 1992-2018 Free Software Foundation, Inc.
46
+
47
+timestamp='2018-03-08it and/or modify it
48
+# under the terms of the GNU General Public License as published by
49
+# t;e Free Software Foundation, either version 3 of the L;cense, or
50
+# (at your o
--- a/autosetup/autosetup-config.guess
+++ b/autosetup/autosetup-config.guess
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/autosetup-config.guess
+++ b/autosetup/autosetup-config.guess
@@ -0,0 +1,50 @@
1 #! /bin/sh
2 # Attempt to guess a canonical system name.
3 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
4 # under the terms of the GNU General Public License as published by
5 # t;e Free Software Foundation, either version 3 of the L;cense, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <https://www.gnu.org/licenses/>.
15 #
16 # As a special exceptionto the GNU General Public License, if you
17 # distribute this file as part of a program that contains a
18 # configuration script generated by Autoconf, you may include it under
19 # the same distribution terms that you use for the rest of that
20 # program. This Exception is an additional permission under section 7
21 # of the GNU General Public License, version 3 ("GPLv3").
22 #
23 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
24 #
25 # You can get the latest version of this script from:
26 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
27
28 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
29 cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
30 # Attempt to guess a canoniAttempt to g! /bin/sh
31 # Attemp#*) machine=${! /bin/sh
32 # Attemp#! /bin/sh
33 # Attempt to guess a canonical system name.
34 # Copyright 1992-2018canonical system name.
35 # Copyrig! /bin/sh
36 # Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
37 # Attemp#! /bin/sh
38 # Attempt to guess a ${! /bin/sh
39 # Attemp#! /bin/sh
40 # Attempt to guess a cekkoBSD:*:*)
41 echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
42 echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
43 # Attempt to guess a canonical system name.
44 # Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
45 # Copyright 1992-2018 Free Software Foundation, Inc.
46
47 timestamp='2018-03-08it and/or modify it
48 # under the terms of the GNU General Public License as published by
49 # t;e Free Software Foundation, either version 3 of the L;cense, or
50 # (at your o
--- a/autosetup/autosetup-config.sub
+++ b/autosetup/autosetup-config.sub
@@ -0,0 +1,75 @@
1
+#! /bin/sh
2
+# Configuration validation subroutine script.
3
+# Copyright 1992-2014 Free Software Found4-12-03it and/or modify it
4
+# under the terms of the GNU General Public License as published by
5
+# t;e Free Software Foundation, either version 3 of the L;cense, or
6
+# (at your option) any later version.
7
+#
8
+# This program is distributed in the hope that it will be useful, but
9
+# WITHOUT ANY WARRANTY; without even the implied warranty of
10
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+# General Public License for more details.
12
+#
13
+# You should have received a copy of the GNU General Public License
14
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
15
+#
16
+# As a special exception#
17
+# As a special exception to the GNU General Public License, if you
18
+# distribute this file as part of a program that contains a
19
+# configuration script generated by Autoconf, you may include it under
20
+# the same distribution terms that you use for the rest of that
21
+# program. This Exception is an additional permission under section 7
22
+# of the GNU General Public License, version 3 ("GPLv3").
23
+
24
+
25
+# Please send patches to <[email protected]>.
26
+#
27
+# Configuration subroutine to validate and canonicalize a configuration type.
28
+# Supply the specified configuration type as an argument.
29
+# If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
30
+
31
+'orting which valid configurations
32
+# it does not support. The user should be able to distinguish
33
+# a failure to support;hb=HEAD
34
+ $0 [OPTION]f not, see <https:/eration mode a special exception to the GNU General Public License, if you
35
+# distribute this file as part of a program that contains a
36
+# configuration script generated by Autoconf, you may include it under
37
+# the same distribution terms that you use for the rest of that
38
+# program. This Excepti4 Free Software Foundation, Inc.
39
+
40
+er section 7
41
+# of the GNU General Public License, version 3 ("GPLv3").
42
+
43
+
44
+# Please send patches to <[email protected]>.
45
+#
46
+# Configuration subroutine to validate and canonicalize a configuration type.
47
+# Supply the specified configuration type as an argument.
48
+# If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
49
+
50
+'orting which valid configurations
51
+# it does not support. The user should be able to distinguish
52
+# a failure to support a valid configuration from a meaningless
53
+# configur$1$1$1$1$1$basic_machine !$1$1$1$1$15v6$1$1udk$1! /bin/sh
54
+# Cio$1$1windowsnt/windowsnt/windp11e32k | z8k)
55
+ ;;
56
+ msbut
57
+# WITHOUT ANY W#! /bin/sh
58
+# Configuration validation subroutine script.
59
+# Copyright 1992-2018 Free Software Foundation, Inc.
60
+
61
+timestamp='2018-03-08it and/or modify it
62
+# under the terms of the GNU General Public License as published by
63
+# t;e Free Software Foundation, either version 3 of the L;cense, or
64
+# (at your option) any later version.
65
+#
66
+# This program is distributed in the hope that it will be useful, but
67
+# WITHOUT ANY WARRANTY; without even the implied warranty of
68
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the $1\': machine \`$basic_machineyramid?unknown$basic_machineu$basic_machine$basic_machine$basic_machine$basic_machinec9c | dpx2*-bull-next)
69
+ os=-nextstep3$1$1$1$1i386-vsta | vstabin/sh
70
+# Configuration validation subroutine script.
71
+# Copyright 1992-2018 Free Software Foundation, Inc.
72
+
73
+timestamp='2018-03-08it and/or modify it
74
+# under the terms of the GNU General Public License as published bon subroutine $basic_machine-linuxomron$basic_machine$basic_machine$basic_machine ext$basic_machine$basic_machine$basic_machine$basic_machine$basic_machinepentium4i786-`echo $basic_machinepn$basic_machineppcle | ppc-le | powerpc-littlele$basic_machine$basic_machine | ppc64-le | powerpc64-little64le$basic_machinepsshsh5elh6h64-unknown
75
+ ;
--- a/autosetup/autosetup-config.sub
+++ b/autosetup/autosetup-config.sub
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/autosetup-config.sub
+++ b/autosetup/autosetup-config.sub
@@ -0,0 +1,75 @@
1 #! /bin/sh
2 # Configuration validation subroutine script.
3 # Copyright 1992-2014 Free Software Found4-12-03it and/or modify it
4 # under the terms of the GNU General Public License as published by
5 # t;e Free Software Foundation, either version 3 of the L;cense, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <https://www.gnu.org/licenses/>.
15 #
16 # As a special exception#
17 # As a special exception to the GNU General Public License, if you
18 # distribute this file as part of a program that contains a
19 # configuration script generated by Autoconf, you may include it under
20 # the same distribution terms that you use for the rest of that
21 # program. This Exception is an additional permission under section 7
22 # of the GNU General Public License, version 3 ("GPLv3").
23
24
25 # Please send patches to <[email protected]>.
26 #
27 # Configuration subroutine to validate and canonicalize a configuration type.
28 # Supply the specified configuration type as an argument.
29 # If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
30
31 'orting which valid configurations
32 # it does not support. The user should be able to distinguish
33 # a failure to support;hb=HEAD
34 $0 [OPTION]f not, see <https:/eration mode a special exception to the GNU General Public License, if you
35 # distribute this file as part of a program that contains a
36 # configuration script generated by Autoconf, you may include it under
37 # the same distribution terms that you use for the rest of that
38 # program. This Excepti4 Free Software Foundation, Inc.
39
40 er section 7
41 # of the GNU General Public License, version 3 ("GPLv3").
42
43
44 # Please send patches to <[email protected]>.
45 #
46 # Configuration subroutine to validate and canonicalize a configuration type.
47 # Supply the specified configuration type as an argument.
48 # If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
49
50 'orting which valid configurations
51 # it does not support. The user should be able to distinguish
52 # a failure to support a valid configuration from a meaningless
53 # configur$1$1$1$1$1$basic_machine !$1$1$1$1$15v6$1$1udk$1! /bin/sh
54 # Cio$1$1windowsnt/windowsnt/windp11e32k | z8k)
55 ;;
56 msbut
57 # WITHOUT ANY W#! /bin/sh
58 # Configuration validation subroutine script.
59 # Copyright 1992-2018 Free Software Foundation, Inc.
60
61 timestamp='2018-03-08it and/or modify it
62 # under the terms of the GNU General Public License as published by
63 # t;e Free Software Foundation, either version 3 of the L;cense, or
64 # (at your option) any later version.
65 #
66 # This program is distributed in the hope that it will be useful, but
67 # WITHOUT ANY WARRANTY; without even the implied warranty of
68 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the $1\': machine \`$basic_machineyramid?unknown$basic_machineu$basic_machine$basic_machine$basic_machine$basic_machinec9c | dpx2*-bull-next)
69 os=-nextstep3$1$1$1$1i386-vsta | vstabin/sh
70 # Configuration validation subroutine script.
71 # Copyright 1992-2018 Free Software Foundation, Inc.
72
73 timestamp='2018-03-08it and/or modify it
74 # under the terms of the GNU General Public License as published bon subroutine $basic_machine-linuxomron$basic_machine$basic_machine$basic_machine ext$basic_machine$basic_machine$basic_machine$basic_machine$basic_machinepentium4i786-`echo $basic_machinepn$basic_machineppcle | ppc-le | powerpc-littlele$basic_machine$basic_machine | ppc64-le | powerpc64-little64le$basic_machinepsshsh5elh6h64-unknown
75 ;
--- a/autosetup/autosetup-find-tclsh
+++ b/autosetup/autosetup-find-tclsh
@@ -0,0 +1,12 @@
1
+#!/bin/sh
2
+# Looks for a suitable tclsh or jimsh in the PATH
3
+# If not foundstrap jimsh in current dir from source
4
+# Prefer $autosetup_tclsh i
5
+d=`dirname "$0"`
6
+{ "$d/jimshd/${1-autosetup-test-tclsh}"; } 2>/dev/null && exit 0
7
+done
8
+echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
9
+for cc in $ { $cc -o jimsh0 "$d/jimsh0.c"; } 2>&1 >/dev "$d/${1-autosetup--tclsh}"; } 2>/dev/null && exit 0
10
+done
11
+echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
12
+for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/autosetup-find-tclsh
+++ b/autosetup/autosetup-find-tclsh
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/autosetup-find-tclsh
+++ b/autosetup/autosetup-find-tclsh
@@ -0,0 +1,12 @@
1 #!/bin/sh
2 # Looks for a suitable tclsh or jimsh in the PATH
3 # If not foundstrap jimsh in current dir from source
4 # Prefer $autosetup_tclsh i
5 d=`dirname "$0"`
6 { "$d/jimshd/${1-autosetup-test-tclsh}"; } 2>/dev/null && exit 0
7 done
8 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
9 for cc in $ { $cc -o jimsh0 "$d/jimsh0.c"; } 2>&1 >/dev "$d/${1-autosetup--tclsh}"; } 2>/dev/null && exit 0
10 done
11 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
12 for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/autosetup-test-tclsh
+++ b/autosetup/autosetup-test-tclsh
@@ -0,0 +1,20 @@
1
+# A small Tcl script to verify that the chosen
2
+# interpreter works. Sometimes we might e.g. pick up
3
+# an interpreter for a different arch.
4
+# Outputs the full path to the interpreter
5
+
6
+if {[catch {info version} version] == 0} {
7
+ # This is Jim Tcl
8
+ if {$version >= 0.72} {
9
+ # Ensure that regexp works
10
+ regexp (a.*?) a
11
+ puts [info nameofexecutable]
12
+ exit 0
13
+ }
14
+} elseif {[catch {info tclversion} version] == 0} {
15
+ if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
16
+ puts [info nameofexecutable]
17
+ exit 0
18
+ }
19
+}
20
+exit 1
--- a/autosetup/autosetup-test-tclsh
+++ b/autosetup/autosetup-test-tclsh
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/autosetup-test-tclsh
+++ b/autosetup/autosetup-test-tclsh
@@ -0,0 +1,20 @@
1 # A small Tcl script to verify that the chosen
2 # interpreter works. Sometimes we might e.g. pick up
3 # an interpreter for a different arch.
4 # Outputs the full path to the interpreter
5
6 if {[catch {info version} version] == 0} {
7 # This is Jim Tcl
8 if {$version >= 0.72} {
9 # Ensure that regexp works
10 regexp (a.*?) a
11 puts [info nameofexecutable]
12 exit 0
13 }
14 } elseif {[catch {info tclversion} version] == 0} {
15 if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
16 puts [info nameofexecutable]
17 exit 0
18 }
19 }
20 exit 1
--- autosetup/cc-db.tcl
+++ autosetup/cc-db.tcl
@@ -1,12 +1,12 @@
11
# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
22
# All rights reserved
33
44
# @synopsis:
55
#
6
-# The 'cc-db' module provides a knowledge based of system idiosyncrasies
7
-# In general, this module can always be included
6
+# The 'cc-db' module provides a knowledge-base of system idiosyncrasies.
7
+# In general, this module can always be included.
88
99
use cc
1010
1111
module-options {}
1212
1313
--- autosetup/cc-db.tcl
+++ autosetup/cc-db.tcl
@@ -1,12 +1,12 @@
1 # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc-db' module provides a knowledge based of system idiosyncrasies
7 # In general, this module can always be included
8
9 use cc
10
11 module-options {}
12
13
--- autosetup/cc-db.tcl
+++ autosetup/cc-db.tcl
@@ -1,12 +1,12 @@
1 # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc-db' module provides a knowledge-base of system idiosyncrasies.
7 # In general, this module can always be included.
8
9 use cc
10
11 module-options {}
12
13
--- autosetup/cc-lib.tcl
+++ autosetup/cc-lib.tcl
@@ -9,11 +9,11 @@
99
1010
module-options {}
1111
1212
# @cc-check-lfs
1313
#
14
-# The equivalent of the AC_SYS_LARGEFILE macro
14
+# The equivalent of the 'AC_SYS_LARGEFILE' macro.
1515
#
1616
# defines 'HAVE_LFS' if LFS is available,
1717
# and defines '_FILE_OFFSET_BITS=64' if necessary
1818
#
1919
# Returns 1 if 'LFS' is available or 0 otherwise
@@ -35,11 +35,11 @@
3535
return $lfs
3636
}
3737
3838
# @cc-check-endian
3939
#
40
-# The equivalent of the AC_C_BIGENDIAN macro
40
+# The equivalent of the 'AC_C_BIGENDIAN' macro.
4141
#
4242
# defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
4343
# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
4444
#
4545
# Returns 1 if determined, or 0 if not.
@@ -80,112 +80,110 @@
8080
#
8181
# Checks whether the given C/C++ compiler flags can be used. Defines feature
8282
# names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and
8383
# appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'.
8484
proc cc-check-flags {args} {
85
- set result 1
86
- array set opts [cc-get-settings]
87
- switch -exact -- $opts(-lang) {
88
- c++ {
89
- set lang C++
90
- set prefix CXXFLAG
91
- }
92
- c {
93
- set lang C
94
- set prefix CFLAG
95
- }
96
- default {
97
- autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
98
- }
99
- }
100
- foreach flag $args {
101
- msg-checking "Checking whether the $lang compiler accepts $flag..."
102
- if {[cctest -cflags $flag]} {
103
- msg-result yes
104
- define-feature $prefix$flag
105
- cc-with [list -cflags [list $flag]]
106
- define-append ${prefix}S $flag
107
- } else {
108
- msg-result no
109
- set result 0
110
- }
111
- }
112
- return $result
85
+ set result 1
86
+ array set opts [cc-get-settings]
87
+ switch -exact -- $opts(-lang) {
88
+ c++ {
89
+ set lang C++
90
+ set prefix CXXFLAG
91
+ }
92
+ c {
93
+ set lang C
94
+ set prefix CFLAG
95
+ }
96
+ default {
97
+ autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
98
+ }
99
+ }
100
+ foreach flag $args {
101
+ msg-checking "Checking whether the $lang compiler accepts $flag..."
102
+ if {[cctest -cflags $flag]} {
103
+ msg-result yes
104
+ define-feature $prefix$flag
105
+ cc-with [list -cflags [list $flag]]
106
+ define-append ${prefix}S $flag
107
+ } else {
108
+ msg-result no
109
+ set result 0
110
+ }
111
+ }
112
+ return $result
113113
}
114114
115115
# @cc-check-standards ver ?...?
116116
#
117117
# Checks whether the C/C++ compiler accepts one of the specified '-std=$ver'
118118
# options, and appends the first working one to '-cflags' and 'CFLAGS' or
119119
# 'CXXFLAGS'.
120120
proc cc-check-standards {args} {
121
- array set opts [cc-get-settings]
122
- foreach std $args {
123
- if {[cc-check-flags -std=$std]} {
124
- return $std
125
- }
126
- }
127
- return ""
121
+ array set opts [cc-get-settings]
122
+ foreach std $args {
123
+ if {[cc-check-flags -std=$std]} {
124
+ return $std
125
+ }
126
+ }
127
+ return ""
128128
}
129129
130130
# Checks whether $keyword is usable as alignof
131131
proc cctest_alignof {keyword} {
132
- msg-checking "Checking for $keyword..."
133
- if {[cctest -code [subst -nobackslashes {
134
- printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x'));
135
- }]]} then {
136
- msg-result ok
137
- define-feature $keyword
138
- } else {
139
- msg-result "not found"
140
- }
132
+ msg-checking "Checking for $keyword..."
133
+ if {[cctest -code "int x = ${keyword}(char), y = ${keyword}('x');"]} then {
134
+ msg-result ok
135
+ define-feature $keyword
136
+ } else {
137
+ msg-result "not found"
138
+ }
141139
}
142140
143141
# @cc-check-c11
144142
#
145143
# Checks for several C11/C++11 extensions and their alternatives. Currently
146144
# checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'.
147145
proc cc-check-c11 {} {
148
- msg-checking "Checking for _Static_assert..."
149
- if {[cctest -code {
150
- _Static_assert(1, "static assertions are available");
151
- }]} then {
152
- msg-result ok
153
- define-feature _Static_assert
154
- } else {
155
- msg-result "not found"
156
- }
157
-
158
- cctest_alignof _Alignof
159
- cctest_alignof __alignof__
160
- cctest_alignof __alignof
146
+ msg-checking "Checking for _Static_assert..."
147
+ if {[cctest -code {
148
+ _Static_assert(1, "static assertions are available");
149
+ }]} then {
150
+ msg-result ok
151
+ define-feature _Static_assert
152
+ } else {
153
+ msg-result "not found"
154
+ }
155
+
156
+ cctest_alignof _Alignof
157
+ cctest_alignof __alignof__
158
+ cctest_alignof __alignof
161159
}
162160
163161
# @cc-check-alloca
164162
#
165
-# The equivalent of the AC_FUNC_ALLOCA macro
163
+# The equivalent of the 'AC_FUNC_ALLOCA' macro.
166164
#
167
-# Checks for the existence of alloca
168
-# defines HAVE_ALLOCA and returns 1 if it exists
165
+# Checks for the existence of 'alloca'
166
+# defines 'HAVE_ALLOCA' and returns 1 if it exists.
169167
proc cc-check-alloca {} {
170
- cc-check-some-feature alloca {
171
- cctest -includes alloca.h -code { alloca (2 * sizeof (int)); }
172
- }
168
+ cc-check-some-feature alloca {
169
+ cctest -includes alloca.h -code { alloca (2 * sizeof (int)); }
170
+ }
173171
}
174172
175173
# @cc-signal-return-type
176174
#
177
-# The equivalent of the AC_TYPE_SIGNAL macro
175
+# The equivalent of the 'AC_TYPE_SIGNAL' macro.
178176
#
179
-# defines RETSIGTYPE to int or void
177
+# defines 'RETSIGTYPE' to 'int' or 'void'.
180178
proc cc-signal-return-type {} {
181
- msg-checking "Checking return type of signal handlers..."
182
- cc-with {-includes {sys/types.h signal.h}} {
183
- if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} {
184
- set type int
185
- } else {
186
- set type void
187
- }
188
- define RETSIGTYPE $type
189
- msg-result $type
190
- }
179
+ msg-checking "Checking return type of signal handlers..."
180
+ cc-with {-includes {sys/types.h signal.h}} {
181
+ if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} {
182
+ set type int
183
+ } else {
184
+ set type void
185
+ }
186
+ define RETSIGTYPE $type
187
+ msg-result $type
188
+ }
191189
}
192190
--- autosetup/cc-lib.tcl
+++ autosetup/cc-lib.tcl
@@ -9,11 +9,11 @@
9
10 module-options {}
11
12 # @cc-check-lfs
13 #
14 # The equivalent of the AC_SYS_LARGEFILE macro
15 #
16 # defines 'HAVE_LFS' if LFS is available,
17 # and defines '_FILE_OFFSET_BITS=64' if necessary
18 #
19 # Returns 1 if 'LFS' is available or 0 otherwise
@@ -35,11 +35,11 @@
35 return $lfs
36 }
37
38 # @cc-check-endian
39 #
40 # The equivalent of the AC_C_BIGENDIAN macro
41 #
42 # defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
43 # or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
44 #
45 # Returns 1 if determined, or 0 if not.
@@ -80,112 +80,110 @@
80 #
81 # Checks whether the given C/C++ compiler flags can be used. Defines feature
82 # names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and
83 # appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'.
84 proc cc-check-flags {args} {
85 set result 1
86 array set opts [cc-get-settings]
87 switch -exact -- $opts(-lang) {
88 c++ {
89 set lang C++
90 set prefix CXXFLAG
91 }
92 c {
93 set lang C
94 set prefix CFLAG
95 }
96 default {
97 autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
98 }
99 }
100 foreach flag $args {
101 msg-checking "Checking whether the $lang compiler accepts $flag..."
102 if {[cctest -cflags $flag]} {
103 msg-result yes
104 define-feature $prefix$flag
105 cc-with [list -cflags [list $flag]]
106 define-append ${prefix}S $flag
107 } else {
108 msg-result no
109 set result 0
110 }
111 }
112 return $result
113 }
114
115 # @cc-check-standards ver ?...?
116 #
117 # Checks whether the C/C++ compiler accepts one of the specified '-std=$ver'
118 # options, and appends the first working one to '-cflags' and 'CFLAGS' or
119 # 'CXXFLAGS'.
120 proc cc-check-standards {args} {
121 array set opts [cc-get-settings]
122 foreach std $args {
123 if {[cc-check-flags -std=$std]} {
124 return $std
125 }
126 }
127 return ""
128 }
129
130 # Checks whether $keyword is usable as alignof
131 proc cctest_alignof {keyword} {
132 msg-checking "Checking for $keyword..."
133 if {[cctest -code [subst -nobackslashes {
134 printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x'));
135 }]]} then {
136 msg-result ok
137 define-feature $keyword
138 } else {
139 msg-result "not found"
140 }
141 }
142
143 # @cc-check-c11
144 #
145 # Checks for several C11/C++11 extensions and their alternatives. Currently
146 # checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'.
147 proc cc-check-c11 {} {
148 msg-checking "Checking for _Static_assert..."
149 if {[cctest -code {
150 _Static_assert(1, "static assertions are available");
151 }]} then {
152 msg-result ok
153 define-feature _Static_assert
154 } else {
155 msg-result "not found"
156 }
157
158 cctest_alignof _Alignof
159 cctest_alignof __alignof__
160 cctest_alignof __alignof
161 }
162
163 # @cc-check-alloca
164 #
165 # The equivalent of the AC_FUNC_ALLOCA macro
166 #
167 # Checks for the existence of alloca
168 # defines HAVE_ALLOCA and returns 1 if it exists
169 proc cc-check-alloca {} {
170 cc-check-some-feature alloca {
171 cctest -includes alloca.h -code { alloca (2 * sizeof (int)); }
172 }
173 }
174
175 # @cc-signal-return-type
176 #
177 # The equivalent of the AC_TYPE_SIGNAL macro
178 #
179 # defines RETSIGTYPE to int or void
180 proc cc-signal-return-type {} {
181 msg-checking "Checking return type of signal handlers..."
182 cc-with {-includes {sys/types.h signal.h}} {
183 if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} {
184 set type int
185 } else {
186 set type void
187 }
188 define RETSIGTYPE $type
189 msg-result $type
190 }
191 }
192
--- autosetup/cc-lib.tcl
+++ autosetup/cc-lib.tcl
@@ -9,11 +9,11 @@
9
10 module-options {}
11
12 # @cc-check-lfs
13 #
14 # The equivalent of the 'AC_SYS_LARGEFILE' macro.
15 #
16 # defines 'HAVE_LFS' if LFS is available,
17 # and defines '_FILE_OFFSET_BITS=64' if necessary
18 #
19 # Returns 1 if 'LFS' is available or 0 otherwise
@@ -35,11 +35,11 @@
35 return $lfs
36 }
37
38 # @cc-check-endian
39 #
40 # The equivalent of the 'AC_C_BIGENDIAN' macro.
41 #
42 # defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
43 # or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
44 #
45 # Returns 1 if determined, or 0 if not.
@@ -80,112 +80,110 @@
80 #
81 # Checks whether the given C/C++ compiler flags can be used. Defines feature
82 # names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and
83 # appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'.
84 proc cc-check-flags {args} {
85 set result 1
86 array set opts [cc-get-settings]
87 switch -exact -- $opts(-lang) {
88 c++ {
89 set lang C++
90 set prefix CXXFLAG
91 }
92 c {
93 set lang C
94 set prefix CFLAG
95 }
96 default {
97 autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
98 }
99 }
100 foreach flag $args {
101 msg-checking "Checking whether the $lang compiler accepts $flag..."
102 if {[cctest -cflags $flag]} {
103 msg-result yes
104 define-feature $prefix$flag
105 cc-with [list -cflags [list $flag]]
106 define-append ${prefix}S $flag
107 } else {
108 msg-result no
109 set result 0
110 }
111 }
112 return $result
113 }
114
115 # @cc-check-standards ver ?...?
116 #
117 # Checks whether the C/C++ compiler accepts one of the specified '-std=$ver'
118 # options, and appends the first working one to '-cflags' and 'CFLAGS' or
119 # 'CXXFLAGS'.
120 proc cc-check-standards {args} {
121 array set opts [cc-get-settings]
122 foreach std $args {
123 if {[cc-check-flags -std=$std]} {
124 return $std
125 }
126 }
127 return ""
128 }
129
130 # Checks whether $keyword is usable as alignof
131 proc cctest_alignof {keyword} {
132 msg-checking "Checking for $keyword..."
133 if {[cctest -code "int x = ${keyword}(char), y = ${keyword}('x');"]} then {
134 msg-result ok
135 define-feature $keyword
136 } else {
137 msg-result "not found"
138 }
 
 
139 }
140
141 # @cc-check-c11
142 #
143 # Checks for several C11/C++11 extensions and their alternatives. Currently
144 # checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'.
145 proc cc-check-c11 {} {
146 msg-checking "Checking for _Static_assert..."
147 if {[cctest -code {
148 _Static_assert(1, "static assertions are available");
149 }]} then {
150 msg-result ok
151 define-feature _Static_assert
152 } else {
153 msg-result "not found"
154 }
155
156 cctest_alignof _Alignof
157 cctest_alignof __alignof__
158 cctest_alignof __alignof
159 }
160
161 # @cc-check-alloca
162 #
163 # The equivalent of the 'AC_FUNC_ALLOCA' macro.
164 #
165 # Checks for the existence of 'alloca'
166 # defines 'HAVE_ALLOCA' and returns 1 if it exists.
167 proc cc-check-alloca {} {
168 cc-check-some-feature alloca {
169 cctest -includes alloca.h -code { alloca (2 * sizeof (int)); }
170 }
171 }
172
173 # @cc-signal-return-type
174 #
175 # The equivalent of the 'AC_TYPE_SIGNAL' macro.
176 #
177 # defines 'RETSIGTYPE' to 'int' or 'void'.
178 proc cc-signal-return-type {} {
179 msg-checking "Checking return type of signal handlers..."
180 cc-with {-includes {sys/types.h signal.h}} {
181 if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} {
182 set type int
183 } else {
184 set type void
185 }
186 define RETSIGTYPE $type
187 msg-result $type
188 }
189 }
190
+66 -49
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -2,12 +2,12 @@
22
# All rights reserved
33
44
# @synopsis:
55
#
66
# The 'cc' module supports checking various 'features' of the C or C++
7
-# compiler/linker environment. Common commands are cc-check-includes,
8
-# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template.
7
+# compiler/linker environment. Common commands are 'cc-check-includes',
8
+# 'cc-check-types', 'cc-check-functions', 'cc-with', 'make-config-header' and 'make-template'.
99
#
1010
# The following environment variables are used if set:
1111
#
1212
## CC - C compiler
1313
## CXX - C++ compiler
@@ -28,15 +28,10 @@
2828
2929
use system
3030
3131
module-options {}
3232
33
-# Note that the return code is not meaningful
34
-proc cc-check-something {name code} {
35
- uplevel 1 $code
36
-}
37
-
3833
# Checks for the existence of the given function by linking
3934
#
4035
proc cctest_function {function} {
4136
cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
4237
}
@@ -68,12 +63,12 @@
6863
}
6964
7065
# @cc-check-sizeof type ...
7166
#
7267
# Checks the size of the given types (between 1 and 32, inclusive).
73
-# Defines a variable with the size determined, or "unknown" otherwise.
74
-# e.g. for type 'long long', defines SIZEOF_LONG_LONG.
68
+# Defines a variable with the size determined, or 'unknown' otherwise.
69
+# e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
7570
# Returns the size of the last type.
7671
#
7772
proc cc-check-sizeof {args} {
7873
foreach type $args {
7974
msg-checking "Checking for sizeof $type..."
@@ -109,11 +104,11 @@
109104
return $ret
110105
}
111106
112107
# @cc-check-includes includes ...
113108
#
114
-# Checks that the given include files can be used
109
+# Checks that the given include files can be used.
115110
proc cc-check-includes {args} {
116111
cc-check-some-feature $args {
117112
set with {}
118113
if {[dict exists $::autosetup(cc-include-deps) $each]} {
119114
set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
@@ -134,12 +129,12 @@
134129
}
135130
}
136131
137132
# @cc-include-needs include required ...
138133
#
139
-# Ensures that when checking for 'include', a check is first
140
-# made for each 'required' file, and if found, it is #included
134
+# Ensures that when checking for '$include', a check is first
135
+# made for each '$required' file, and if found, it is included with '#include'.
141136
proc cc-include-needs {file args} {
142137
foreach depfile $args {
143138
dict set ::autosetup(cc-include-deps) $file $depfile 1
144139
}
145140
}
@@ -153,22 +148,22 @@
153148
}
154149
}
155150
156151
# @cc-check-defines define ...
157152
#
158
-# Checks that the given preprocessor symbol is defined
153
+# Checks that the given preprocessor symbols are defined.
159154
proc cc-check-defines {args} {
160155
cc-check-some-feature $args {
161156
cctest_define $each
162157
}
163158
}
164159
165160
# @cc-check-decls name ...
166161
#
167162
# Checks that each given name is either a preprocessor symbol or rvalue
168
-# such as an enum. Note that the define used is HAVE_DECL_xxx
169
-# rather than HAVE_xxx
163
+# such as an enum. Note that the define used is 'HAVE_DECL_xxx'
164
+# rather than 'HAVE_xxx'.
170165
proc cc-check-decls {args} {
171166
set ret 1
172167
foreach name $args {
173168
msg-checking "Checking for $name..."
174169
set r [cctest_decl $name]
@@ -183,21 +178,21 @@
183178
return $ret
184179
}
185180
186181
# @cc-check-functions function ...
187182
#
188
-# Checks that the given functions exist (can be linked)
183
+# Checks that the given functions exist (can be linked).
189184
proc cc-check-functions {args} {
190185
cc-check-some-feature $args {
191186
cctest_function $each
192187
}
193188
}
194189
195190
# @cc-check-members type.member ...
196191
#
197192
# Checks that the given type/structure members exist.
198
-# A structure member is of the form "struct stat.st_mtime"
193
+# A structure member is of the form 'struct stat.st_mtime'.
199194
proc cc-check-members {args} {
200195
cc-check-some-feature $args {
201196
cctest_member $each
202197
}
203198
}
@@ -207,17 +202,17 @@
207202
# Checks that the given function can be found in one of the libs.
208203
#
209204
# First checks for no library required, then checks each of the libraries
210205
# in turn.
211206
#
212
-# If the function is found, the feature is defined and lib_$function is defined
213
-# to -l$lib where the function was found, or "" if no library required.
214
-# In addition, -l$lib is prepended to the LIBS define.
207
+# If the function is found, the feature is defined and 'lib_$function' is defined
208
+# to '-l$lib' where the function was found, or "" if no library required.
209
+# In addition, '-l$lib' is prepended to the 'LIBS' define.
215210
#
216211
# If additional libraries may be needed for linking, they should be specified
217
-# as $extralibs as "-lotherlib1 -lotherlib2".
218
-# These libraries are not automatically added to LIBS.
212
+# with '$extralibs' as '-lotherlib1 -lotherlib2'.
213
+# These libraries are not automatically added to 'LIBS'.
219214
#
220215
# Returns 1 if found or 0 if not.
221216
#
222217
proc cc-check-function-in-lib {function libs {otherlibs {}}} {
223218
msg-checking "Checking libs for $function..."
@@ -240,13 +235,12 @@
240235
}
241236
}
242237
}
243238
}
244239
}
245
- if {$found} {
246
- define [feature-define-name $function]
247
- } else {
240
+ define-feature $function $found
241
+ if {!$found} {
248242
msg-result "no"
249243
}
250244
return $found
251245
}
252246
@@ -253,16 +247,16 @@
253247
# @cc-check-tools tool ...
254248
#
255249
# Checks for existence of the given compiler tools, taking
256250
# into account any cross compilation prefix.
257251
#
258
-# For example, when checking for "ar", first AR is checked on the command
259
-# line and then in the environment. If not found, "${host}-ar" or
260
-# simply "ar" is assumed depending upon whether cross compiling.
261
-# The path is searched for this executable, and if found AR is defined
252
+# For example, when checking for 'ar', first 'AR' is checked on the command
253
+# line and then in the environment. If not found, '${host}-ar' or
254
+# simply 'ar' is assumed depending upon whether cross compiling.
255
+# The path is searched for this executable, and if found 'AR' is defined
262256
# to the executable name.
263
-# Note that even when cross compiling, the simple "ar" is used as a fallback,
257
+# Note that even when cross compiling, the simple 'ar' is used as a fallback,
264258
# but a warning is generated. This is necessary for some toolchains.
265259
#
266260
# It is an error if the executable is not found.
267261
#
268262
proc cc-check-tools {args} {
@@ -284,14 +278,14 @@
284278
285279
# @cc-check-progs prog ...
286280
#
287281
# Checks for existence of the given executables on the path.
288282
#
289
-# For example, when checking for "grep", the path is searched for
290
-# the executable, 'grep', and if found GREP is defined as "grep".
283
+# For example, when checking for 'grep', the path is searched for
284
+# the executable, 'grep', and if found 'GREP' is defined as 'grep'.
291285
#
292
-# If the executable is not found, the variable is defined as false.
286
+# If the executable is not found, the variable is defined as 'false'.
293287
# Returns 1 if all programs were found, or 0 otherwise.
294288
#
295289
proc cc-check-progs {args} {
296290
set failed 0
297291
foreach prog $args {
@@ -303,10 +297,33 @@
303297
incr failed
304298
} else {
305299
msg-result ok
306300
define $PROG $prog
307301
}
302
+ }
303
+ expr {!$failed}
304
+}
305
+
306
+# @cc-path-progs prog ...
307
+#
308
+# Like cc-check-progs, but sets the define to the full path rather
309
+# than just the program name.
310
+#
311
+proc cc-path-progs {args} {
312
+ set failed 0
313
+ foreach prog $args {
314
+ set PROG [string toupper $prog]
315
+ msg-checking "Checking for $prog..."
316
+ set path [find-executable-path $prog]
317
+ if {$path eq ""} {
318
+ msg-result no
319
+ define $PROG false
320
+ incr failed
321
+ } else {
322
+ msg-result $path
323
+ define $PROG $path
324
+ }
308325
}
309326
expr {!$failed}
310327
}
311328
312329
# Adds the given settings to $::autosetup(ccsettings) and
@@ -326,18 +343,18 @@
326343
327344
foreach {name value} $settings {
328345
switch -exact -- $name {
329346
-cflags - -includes {
330347
# These are given as lists
331
- lappend new($name) {*}$value
348
+ lappend new($name) {*}[list-non-empty $value]
332349
}
333350
-declare {
334351
lappend new($name) $value
335352
}
336353
-libs {
337354
# Note that new libraries are added before previous libraries
338
- set new($name) [list {*}$value {*}$new($name)]
355
+ set new($name) [list {*}[list-non-empty $value] {*}$new($name)]
339356
}
340357
-link - -lang - -nooutput {
341358
set new($name) $value
342359
}
343360
-source - -sourcefile - -code {
@@ -373,16 +390,16 @@
373390
return $prev
374391
}
375392
376393
# @cc-with settings ?{ script }?
377394
#
378
-# Sets the given 'cctest' settings and then runs the tests in 'script'.
379
-# Note that settings such as -lang replace the current setting, while
380
-# those such as -includes are appended to the existing setting.
395
+# Sets the given 'cctest' settings and then runs the tests in '$script'.
396
+# Note that settings such as '-lang' replace the current setting, while
397
+# those such as '-includes' are appended to the existing setting.
381398
#
382399
# If no script is given, the settings become the default for the remainder
383
-# of the auto.def file.
400
+# of the 'auto.def' file.
384401
#
385402
## cc-with {-lang c++} {
386403
## # This will check with the C++ compiler
387404
## cc-check-types bool
388405
## cc-with {-includes signal.h} {
@@ -390,11 +407,11 @@
390407
## ...
391408
## }
392409
## # back to just the C++ compiler
393410
## }
394411
#
395
-# The -libs setting is special in that newer values are added *before* earlier ones.
412
+# The '-libs' setting is special in that newer values are added *before* earlier ones.
396413
#
397414
## cc-with {-libs {-lc -lm}} {
398415
## cc-with {-libs -ldl} {
399416
## cctest -libs -lsocket ...
400417
## # libs will be in this order: -lsocket -ldl -lc -lm
@@ -416,11 +433,11 @@
416433
}
417434
}
418435
419436
# @cctest ?settings?
420437
#
421
-# Low level C compiler checker. Compiles and or links a small C program
438
+# Low level C/C++ compiler checker. Compiles and or links a small C program
422439
# according to the arguments and returns 1 if OK, or 0 if not.
423440
#
424441
# Supported settings are:
425442
#
426443
## -cflags cflags A list of flags to pass to the compiler
@@ -432,11 +449,11 @@
432449
## -code code Code to compile in the body of main()
433450
## -source code Compile a complete program. Ignore -includes, -declare and -code
434451
## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
435452
## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
436453
#
437
-# Unless -source or -sourcefile is specified, the C program looks like:
454
+# Unless '-source' or '-sourcefile' is specified, the C program looks like:
438455
#
439456
## #include <firstinclude> /* same for remaining includes in the list */
440457
##
441458
## declare-code /* any code in -declare, verbatim */
442459
##
@@ -554,32 +571,32 @@
554571
return $ok
555572
}
556573
557574
# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
558575
#
559
-# Deprecated - see make-config-header
576
+# Deprecated - see 'make-config-header'
560577
proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
561578
user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
562579
make-config-header $file -auto $autopatterns -bare $barepatterns
563580
}
564581
565582
# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
566583
#
567584
# Examines all defined variables which match the given patterns
568
-# and writes an include file, $file, which defines each of these.
585
+# and writes an include file, '$file', which defines each of these.
569586
# Variables which match '-auto' are output as follows:
570
-# - defines which have the value "0" are ignored.
587
+# - defines which have the value '0' are ignored.
571588
# - defines which have integer values are defined as the integer value.
572
-# - any other value is defined as a string, e.g. "value"
589
+# - any other value is defined as a string, e.g. '"value"'
573590
# Variables which match '-bare' are defined as-is.
574
-# Variables which match '-str' are defined as a string, e.g. "value"
591
+# Variables which match '-str' are defined as a string, e.g. '"value"'
575592
# Variables which match '-none' are omitted.
576593
#
577
-# Note that order is important. The first pattern which matches is selected
594
+# Note that order is important. The first pattern that matches is selected.
578595
# Default behaviour is:
579596
#
580
-# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
597
+## -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
581598
#
582599
# If the file would be unchanged, it is not written.
583600
proc make-config-header {file args} {
584601
set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
585602
file mkdir [file dirname $file]
586603
587604
DELETED autosetup/config.guess
588605
DELETED autosetup/config.sub
589606
DELETED autosetup/find-tclsh
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -2,12 +2,12 @@
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc' module supports checking various 'features' of the C or C++
7 # compiler/linker environment. Common commands are cc-check-includes,
8 # cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template.
9 #
10 # The following environment variables are used if set:
11 #
12 ## CC - C compiler
13 ## CXX - C++ compiler
@@ -28,15 +28,10 @@
28
29 use system
30
31 module-options {}
32
33 # Note that the return code is not meaningful
34 proc cc-check-something {name code} {
35 uplevel 1 $code
36 }
37
38 # Checks for the existence of the given function by linking
39 #
40 proc cctest_function {function} {
41 cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
42 }
@@ -68,12 +63,12 @@
68 }
69
70 # @cc-check-sizeof type ...
71 #
72 # Checks the size of the given types (between 1 and 32, inclusive).
73 # Defines a variable with the size determined, or "unknown" otherwise.
74 # e.g. for type 'long long', defines SIZEOF_LONG_LONG.
75 # Returns the size of the last type.
76 #
77 proc cc-check-sizeof {args} {
78 foreach type $args {
79 msg-checking "Checking for sizeof $type..."
@@ -109,11 +104,11 @@
109 return $ret
110 }
111
112 # @cc-check-includes includes ...
113 #
114 # Checks that the given include files can be used
115 proc cc-check-includes {args} {
116 cc-check-some-feature $args {
117 set with {}
118 if {[dict exists $::autosetup(cc-include-deps) $each]} {
119 set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
@@ -134,12 +129,12 @@
134 }
135 }
136
137 # @cc-include-needs include required ...
138 #
139 # Ensures that when checking for 'include', a check is first
140 # made for each 'required' file, and if found, it is #included
141 proc cc-include-needs {file args} {
142 foreach depfile $args {
143 dict set ::autosetup(cc-include-deps) $file $depfile 1
144 }
145 }
@@ -153,22 +148,22 @@
153 }
154 }
155
156 # @cc-check-defines define ...
157 #
158 # Checks that the given preprocessor symbol is defined
159 proc cc-check-defines {args} {
160 cc-check-some-feature $args {
161 cctest_define $each
162 }
163 }
164
165 # @cc-check-decls name ...
166 #
167 # Checks that each given name is either a preprocessor symbol or rvalue
168 # such as an enum. Note that the define used is HAVE_DECL_xxx
169 # rather than HAVE_xxx
170 proc cc-check-decls {args} {
171 set ret 1
172 foreach name $args {
173 msg-checking "Checking for $name..."
174 set r [cctest_decl $name]
@@ -183,21 +178,21 @@
183 return $ret
184 }
185
186 # @cc-check-functions function ...
187 #
188 # Checks that the given functions exist (can be linked)
189 proc cc-check-functions {args} {
190 cc-check-some-feature $args {
191 cctest_function $each
192 }
193 }
194
195 # @cc-check-members type.member ...
196 #
197 # Checks that the given type/structure members exist.
198 # A structure member is of the form "struct stat.st_mtime"
199 proc cc-check-members {args} {
200 cc-check-some-feature $args {
201 cctest_member $each
202 }
203 }
@@ -207,17 +202,17 @@
207 # Checks that the given function can be found in one of the libs.
208 #
209 # First checks for no library required, then checks each of the libraries
210 # in turn.
211 #
212 # If the function is found, the feature is defined and lib_$function is defined
213 # to -l$lib where the function was found, or "" if no library required.
214 # In addition, -l$lib is prepended to the LIBS define.
215 #
216 # If additional libraries may be needed for linking, they should be specified
217 # as $extralibs as "-lotherlib1 -lotherlib2".
218 # These libraries are not automatically added to LIBS.
219 #
220 # Returns 1 if found or 0 if not.
221 #
222 proc cc-check-function-in-lib {function libs {otherlibs {}}} {
223 msg-checking "Checking libs for $function..."
@@ -240,13 +235,12 @@
240 }
241 }
242 }
243 }
244 }
245 if {$found} {
246 define [feature-define-name $function]
247 } else {
248 msg-result "no"
249 }
250 return $found
251 }
252
@@ -253,16 +247,16 @@
253 # @cc-check-tools tool ...
254 #
255 # Checks for existence of the given compiler tools, taking
256 # into account any cross compilation prefix.
257 #
258 # For example, when checking for "ar", first AR is checked on the command
259 # line and then in the environment. If not found, "${host}-ar" or
260 # simply "ar" is assumed depending upon whether cross compiling.
261 # The path is searched for this executable, and if found AR is defined
262 # to the executable name.
263 # Note that even when cross compiling, the simple "ar" is used as a fallback,
264 # but a warning is generated. This is necessary for some toolchains.
265 #
266 # It is an error if the executable is not found.
267 #
268 proc cc-check-tools {args} {
@@ -284,14 +278,14 @@
284
285 # @cc-check-progs prog ...
286 #
287 # Checks for existence of the given executables on the path.
288 #
289 # For example, when checking for "grep", the path is searched for
290 # the executable, 'grep', and if found GREP is defined as "grep".
291 #
292 # If the executable is not found, the variable is defined as false.
293 # Returns 1 if all programs were found, or 0 otherwise.
294 #
295 proc cc-check-progs {args} {
296 set failed 0
297 foreach prog $args {
@@ -303,10 +297,33 @@
303 incr failed
304 } else {
305 msg-result ok
306 define $PROG $prog
307 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308 }
309 expr {!$failed}
310 }
311
312 # Adds the given settings to $::autosetup(ccsettings) and
@@ -326,18 +343,18 @@
326
327 foreach {name value} $settings {
328 switch -exact -- $name {
329 -cflags - -includes {
330 # These are given as lists
331 lappend new($name) {*}$value
332 }
333 -declare {
334 lappend new($name) $value
335 }
336 -libs {
337 # Note that new libraries are added before previous libraries
338 set new($name) [list {*}$value {*}$new($name)]
339 }
340 -link - -lang - -nooutput {
341 set new($name) $value
342 }
343 -source - -sourcefile - -code {
@@ -373,16 +390,16 @@
373 return $prev
374 }
375
376 # @cc-with settings ?{ script }?
377 #
378 # Sets the given 'cctest' settings and then runs the tests in 'script'.
379 # Note that settings such as -lang replace the current setting, while
380 # those such as -includes are appended to the existing setting.
381 #
382 # If no script is given, the settings become the default for the remainder
383 # of the auto.def file.
384 #
385 ## cc-with {-lang c++} {
386 ## # This will check with the C++ compiler
387 ## cc-check-types bool
388 ## cc-with {-includes signal.h} {
@@ -390,11 +407,11 @@
390 ## ...
391 ## }
392 ## # back to just the C++ compiler
393 ## }
394 #
395 # The -libs setting is special in that newer values are added *before* earlier ones.
396 #
397 ## cc-with {-libs {-lc -lm}} {
398 ## cc-with {-libs -ldl} {
399 ## cctest -libs -lsocket ...
400 ## # libs will be in this order: -lsocket -ldl -lc -lm
@@ -416,11 +433,11 @@
416 }
417 }
418
419 # @cctest ?settings?
420 #
421 # Low level C compiler checker. Compiles and or links a small C program
422 # according to the arguments and returns 1 if OK, or 0 if not.
423 #
424 # Supported settings are:
425 #
426 ## -cflags cflags A list of flags to pass to the compiler
@@ -432,11 +449,11 @@
432 ## -code code Code to compile in the body of main()
433 ## -source code Compile a complete program. Ignore -includes, -declare and -code
434 ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
435 ## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
436 #
437 # Unless -source or -sourcefile is specified, the C program looks like:
438 #
439 ## #include <firstinclude> /* same for remaining includes in the list */
440 ##
441 ## declare-code /* any code in -declare, verbatim */
442 ##
@@ -554,32 +571,32 @@
554 return $ok
555 }
556
557 # @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
558 #
559 # Deprecated - see make-config-header
560 proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
561 user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
562 make-config-header $file -auto $autopatterns -bare $barepatterns
563 }
564
565 # @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
566 #
567 # Examines all defined variables which match the given patterns
568 # and writes an include file, $file, which defines each of these.
569 # Variables which match '-auto' are output as follows:
570 # - defines which have the value "0" are ignored.
571 # - defines which have integer values are defined as the integer value.
572 # - any other value is defined as a string, e.g. "value"
573 # Variables which match '-bare' are defined as-is.
574 # Variables which match '-str' are defined as a string, e.g. "value"
575 # Variables which match '-none' are omitted.
576 #
577 # Note that order is important. The first pattern which matches is selected
578 # Default behaviour is:
579 #
580 # -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
581 #
582 # If the file would be unchanged, it is not written.
583 proc make-config-header {file args} {
584 set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
585 file mkdir [file dirname $file]
586
587 ELETED autosetup/config.guess
588 ELETED autosetup/config.sub
589 ELETED autosetup/find-tclsh
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -2,12 +2,12 @@
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc' module supports checking various 'features' of the C or C++
7 # compiler/linker environment. Common commands are 'cc-check-includes',
8 # 'cc-check-types', 'cc-check-functions', 'cc-with', 'make-config-header' and 'make-template'.
9 #
10 # The following environment variables are used if set:
11 #
12 ## CC - C compiler
13 ## CXX - C++ compiler
@@ -28,15 +28,10 @@
28
29 use system
30
31 module-options {}
32
 
 
 
 
 
33 # Checks for the existence of the given function by linking
34 #
35 proc cctest_function {function} {
36 cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
37 }
@@ -68,12 +63,12 @@
63 }
64
65 # @cc-check-sizeof type ...
66 #
67 # Checks the size of the given types (between 1 and 32, inclusive).
68 # Defines a variable with the size determined, or 'unknown' otherwise.
69 # e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
70 # Returns the size of the last type.
71 #
72 proc cc-check-sizeof {args} {
73 foreach type $args {
74 msg-checking "Checking for sizeof $type..."
@@ -109,11 +104,11 @@
104 return $ret
105 }
106
107 # @cc-check-includes includes ...
108 #
109 # Checks that the given include files can be used.
110 proc cc-check-includes {args} {
111 cc-check-some-feature $args {
112 set with {}
113 if {[dict exists $::autosetup(cc-include-deps) $each]} {
114 set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
@@ -134,12 +129,12 @@
129 }
130 }
131
132 # @cc-include-needs include required ...
133 #
134 # Ensures that when checking for '$include', a check is first
135 # made for each '$required' file, and if found, it is included with '#include'.
136 proc cc-include-needs {file args} {
137 foreach depfile $args {
138 dict set ::autosetup(cc-include-deps) $file $depfile 1
139 }
140 }
@@ -153,22 +148,22 @@
148 }
149 }
150
151 # @cc-check-defines define ...
152 #
153 # Checks that the given preprocessor symbols are defined.
154 proc cc-check-defines {args} {
155 cc-check-some-feature $args {
156 cctest_define $each
157 }
158 }
159
160 # @cc-check-decls name ...
161 #
162 # Checks that each given name is either a preprocessor symbol or rvalue
163 # such as an enum. Note that the define used is 'HAVE_DECL_xxx'
164 # rather than 'HAVE_xxx'.
165 proc cc-check-decls {args} {
166 set ret 1
167 foreach name $args {
168 msg-checking "Checking for $name..."
169 set r [cctest_decl $name]
@@ -183,21 +178,21 @@
178 return $ret
179 }
180
181 # @cc-check-functions function ...
182 #
183 # Checks that the given functions exist (can be linked).
184 proc cc-check-functions {args} {
185 cc-check-some-feature $args {
186 cctest_function $each
187 }
188 }
189
190 # @cc-check-members type.member ...
191 #
192 # Checks that the given type/structure members exist.
193 # A structure member is of the form 'struct stat.st_mtime'.
194 proc cc-check-members {args} {
195 cc-check-some-feature $args {
196 cctest_member $each
197 }
198 }
@@ -207,17 +202,17 @@
202 # Checks that the given function can be found in one of the libs.
203 #
204 # First checks for no library required, then checks each of the libraries
205 # in turn.
206 #
207 # If the function is found, the feature is defined and 'lib_$function' is defined
208 # to '-l$lib' where the function was found, or "" if no library required.
209 # In addition, '-l$lib' is prepended to the 'LIBS' define.
210 #
211 # If additional libraries may be needed for linking, they should be specified
212 # with '$extralibs' as '-lotherlib1 -lotherlib2'.
213 # These libraries are not automatically added to 'LIBS'.
214 #
215 # Returns 1 if found or 0 if not.
216 #
217 proc cc-check-function-in-lib {function libs {otherlibs {}}} {
218 msg-checking "Checking libs for $function..."
@@ -240,13 +235,12 @@
235 }
236 }
237 }
238 }
239 }
240 define-feature $function $found
241 if {!$found} {
 
242 msg-result "no"
243 }
244 return $found
245 }
246
@@ -253,16 +247,16 @@
247 # @cc-check-tools tool ...
248 #
249 # Checks for existence of the given compiler tools, taking
250 # into account any cross compilation prefix.
251 #
252 # For example, when checking for 'ar', first 'AR' is checked on the command
253 # line and then in the environment. If not found, '${host}-ar' or
254 # simply 'ar' is assumed depending upon whether cross compiling.
255 # The path is searched for this executable, and if found 'AR' is defined
256 # to the executable name.
257 # Note that even when cross compiling, the simple 'ar' is used as a fallback,
258 # but a warning is generated. This is necessary for some toolchains.
259 #
260 # It is an error if the executable is not found.
261 #
262 proc cc-check-tools {args} {
@@ -284,14 +278,14 @@
278
279 # @cc-check-progs prog ...
280 #
281 # Checks for existence of the given executables on the path.
282 #
283 # For example, when checking for 'grep', the path is searched for
284 # the executable, 'grep', and if found 'GREP' is defined as 'grep'.
285 #
286 # If the executable is not found, the variable is defined as 'false'.
287 # Returns 1 if all programs were found, or 0 otherwise.
288 #
289 proc cc-check-progs {args} {
290 set failed 0
291 foreach prog $args {
@@ -303,10 +297,33 @@
297 incr failed
298 } else {
299 msg-result ok
300 define $PROG $prog
301 }
302 }
303 expr {!$failed}
304 }
305
306 # @cc-path-progs prog ...
307 #
308 # Like cc-check-progs, but sets the define to the full path rather
309 # than just the program name.
310 #
311 proc cc-path-progs {args} {
312 set failed 0
313 foreach prog $args {
314 set PROG [string toupper $prog]
315 msg-checking "Checking for $prog..."
316 set path [find-executable-path $prog]
317 if {$path eq ""} {
318 msg-result no
319 define $PROG false
320 incr failed
321 } else {
322 msg-result $path
323 define $PROG $path
324 }
325 }
326 expr {!$failed}
327 }
328
329 # Adds the given settings to $::autosetup(ccsettings) and
@@ -326,18 +343,18 @@
343
344 foreach {name value} $settings {
345 switch -exact -- $name {
346 -cflags - -includes {
347 # These are given as lists
348 lappend new($name) {*}[list-non-empty $value]
349 }
350 -declare {
351 lappend new($name) $value
352 }
353 -libs {
354 # Note that new libraries are added before previous libraries
355 set new($name) [list {*}[list-non-empty $value] {*}$new($name)]
356 }
357 -link - -lang - -nooutput {
358 set new($name) $value
359 }
360 -source - -sourcefile - -code {
@@ -373,16 +390,16 @@
390 return $prev
391 }
392
393 # @cc-with settings ?{ script }?
394 #
395 # Sets the given 'cctest' settings and then runs the tests in '$script'.
396 # Note that settings such as '-lang' replace the current setting, while
397 # those such as '-includes' are appended to the existing setting.
398 #
399 # If no script is given, the settings become the default for the remainder
400 # of the 'auto.def' file.
401 #
402 ## cc-with {-lang c++} {
403 ## # This will check with the C++ compiler
404 ## cc-check-types bool
405 ## cc-with {-includes signal.h} {
@@ -390,11 +407,11 @@
407 ## ...
408 ## }
409 ## # back to just the C++ compiler
410 ## }
411 #
412 # The '-libs' setting is special in that newer values are added *before* earlier ones.
413 #
414 ## cc-with {-libs {-lc -lm}} {
415 ## cc-with {-libs -ldl} {
416 ## cctest -libs -lsocket ...
417 ## # libs will be in this order: -lsocket -ldl -lc -lm
@@ -416,11 +433,11 @@
433 }
434 }
435
436 # @cctest ?settings?
437 #
438 # Low level C/C++ compiler checker. Compiles and or links a small C program
439 # according to the arguments and returns 1 if OK, or 0 if not.
440 #
441 # Supported settings are:
442 #
443 ## -cflags cflags A list of flags to pass to the compiler
@@ -432,11 +449,11 @@
449 ## -code code Code to compile in the body of main()
450 ## -source code Compile a complete program. Ignore -includes, -declare and -code
451 ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
452 ## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
453 #
454 # Unless '-source' or '-sourcefile' is specified, the C program looks like:
455 #
456 ## #include <firstinclude> /* same for remaining includes in the list */
457 ##
458 ## declare-code /* any code in -declare, verbatim */
459 ##
@@ -554,32 +571,32 @@
571 return $ok
572 }
573
574 # @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
575 #
576 # Deprecated - see 'make-config-header'
577 proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
578 user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
579 make-config-header $file -auto $autopatterns -bare $barepatterns
580 }
581
582 # @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
583 #
584 # Examines all defined variables which match the given patterns
585 # and writes an include file, '$file', which defines each of these.
586 # Variables which match '-auto' are output as follows:
587 # - defines which have the value '0' are ignored.
588 # - defines which have integer values are defined as the integer value.
589 # - any other value is defined as a string, e.g. '"value"'
590 # Variables which match '-bare' are defined as-is.
591 # Variables which match '-str' are defined as a string, e.g. '"value"'
592 # Variables which match '-none' are omitted.
593 #
594 # Note that order is important. The first pattern that matches is selected.
595 # Default behaviour is:
596 #
597 ## -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
598 #
599 # If the file would be unchanged, it is not written.
600 proc make-config-header {file args} {
601 set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
602 file mkdir [file dirname $file]
603
604 ELETED autosetup/config.guess
605 ELETED autosetup/config.sub
606 ELETED autosetup/find-tclsh
D autosetup/config.guess
-50
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -1,50 +0,0 @@
1
-#! /bin/sh
2
-# Attempt to guess a canonical system name.
3
-# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
4
-# under the terms of the GNU General Public License as published by
5
-# t;e Free Software Foundation, either version 3 of the L;cense, or
6
-# (at your option) any later version.
7
-#
8
-# This program is distributed in the hope that it will be useful, but
9
-# WITHOUT ANY WARRANTY; without even the implied warranty of
10
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
-# General Public License for more details.
12
-#
13
-# You should have received a copy of the GNU General Public License
14
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
15
-#
16
-# As a special exceptionto the GNU General Public License, if you
17
-# distribute this file as part of a program that contains a
18
-# configuration script generated by Autoconf, you may include it under
19
-# the same distribution terms that you use for the rest of that
20
-# program. This Exception is an additional permission under section 7
21
-# of the GNU General Public License, version 3 ("GPLv3").
22
-#
23
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
24
-#
25
-# You can get the latest version of this script from:
26
-# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
27
-
28
-$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
29
- cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
30
-# Attempt to guess a canoniAttempt to g! /bin/sh
31
-# Attemp#*) machine=${! /bin/sh
32
-# Attemp#! /bin/sh
33
-# Attempt to guess a canonical system name.
34
-# Copyright 1992-2018canonical system name.
35
-# Copyrig! /bin/sh
36
-# Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
37
-# Attemp#! /bin/sh
38
-# Attempt to guess a ${! /bin/sh
39
-# Attemp#! /bin/sh
40
-# Attempt to guess a cekkoBSD:*:*)
41
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
42
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
43
-# Attempt to guess a canonical system name.
44
-# Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
45
-# Copyright 1992-2018 Free Software Foundation, Inc.
46
-
47
-timestamp='2018-03-08it and/or modify it
48
-# under the terms of the GNU General Public License as published by
49
-# t;e Free Software Foundation, either version 3 of the L;cense, or
50
-# (at your o
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -1,50 +0,0 @@
1 #! /bin/sh
2 # Attempt to guess a canonical system name.
3 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
4 # under the terms of the GNU General Public License as published by
5 # t;e Free Software Foundation, either version 3 of the L;cense, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <https://www.gnu.org/licenses/>.
15 #
16 # As a special exceptionto the GNU General Public License, if you
17 # distribute this file as part of a program that contains a
18 # configuration script generated by Autoconf, you may include it under
19 # the same distribution terms that you use for the rest of that
20 # program. This Exception is an additional permission under section 7
21 # of the GNU General Public License, version 3 ("GPLv3").
22 #
23 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
24 #
25 # You can get the latest version of this script from:
26 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
27
28 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
29 cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
30 # Attempt to guess a canoniAttempt to g! /bin/sh
31 # Attemp#*) machine=${! /bin/sh
32 # Attemp#! /bin/sh
33 # Attempt to guess a canonical system name.
34 # Copyright 1992-2018canonical system name.
35 # Copyrig! /bin/sh
36 # Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
37 # Attemp#! /bin/sh
38 # Attempt to guess a ${! /bin/sh
39 # Attemp#! /bin/sh
40 # Attempt to guess a cekkoBSD:*:*)
41 echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
42 echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
43 # Attempt to guess a canonical system name.
44 # Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
45 # Copyright 1992-2018 Free Software Foundation, Inc.
46
47 timestamp='2018-03-08it and/or modify it
48 # under the terms of the GNU General Public License as published by
49 # t;e Free Software Foundation, either version 3 of the L;cense, or
50 # (at your o
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -1,50 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D autosetup/config.sub
-75
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -1,75 +0,0 @@
1
-#! /bin/sh
2
-# Configuration validation subroutine script.
3
-# Copyright 1992-2014 Free Software Found4-12-03it and/or modify it
4
-# under the terms of the GNU General Public License as published by
5
-# t;e Free Software Foundation, either version 3 of the L;cense, or
6
-# (at your option) any later version.
7
-#
8
-# This program is distributed in the hope that it will be useful, but
9
-# WITHOUT ANY WARRANTY; without even the implied warranty of
10
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
-# General Public License for more details.
12
-#
13
-# You should have received a copy of the GNU General Public License
14
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
15
-#
16
-# As a special exception#
17
-# As a special exception to the GNU General Public License, if you
18
-# distribute this file as part of a program that contains a
19
-# configuration script generated by Autoconf, you may include it under
20
-# the same distribution terms that you use for the rest of that
21
-# program. This Exception is an additional permission under section 7
22
-# of the GNU General Public License, version 3 ("GPLv3").
23
-
24
-
25
-# Please send patches to <[email protected]>.
26
-#
27
-# Configuration subroutine to validate and canonicalize a configuration type.
28
-# Supply the specified configuration type as an argument.
29
-# If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
30
-
31
-'orting which valid configurations
32
-# it does not support. The user should be able to distinguish
33
-# a failure to support;hb=HEAD
34
- $0 [OPTION]f not, see <https:/eration mode a special exception to the GNU General Public License, if you
35
-# distribute this file as part of a program that contains a
36
-# configuration script generated by Autoconf, you may include it under
37
-# the same distribution terms that you use for the rest of that
38
-# program. This Excepti4 Free Software Foundation, Inc.
39
-
40
-er section 7
41
-# of the GNU General Public License, version 3 ("GPLv3").
42
-
43
-
44
-# Please send patches to <[email protected]>.
45
-#
46
-# Configuration subroutine to validate and canonicalize a configuration type.
47
-# Supply the specified configuration type as an argument.
48
-# If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
49
-
50
-'orting which valid configurations
51
-# it does not support. The user should be able to distinguish
52
-# a failure to support a valid configuration from a meaningless
53
-# configur$1$1$1$1$1$basic_machine !$1$1$1$1$15v6$1$1udk$1! /bin/sh
54
-# Cio$1$1windowsnt/windowsnt/windp11e32k | z8k)
55
- ;;
56
- msbut
57
-# WITHOUT ANY W#! /bin/sh
58
-# Configuration validation subroutine script.
59
-# Copyright 1992-2018 Free Software Foundation, Inc.
60
-
61
-timestamp='2018-03-08it and/or modify it
62
-# under the terms of the GNU General Public License as published by
63
-# t;e Free Software Foundation, either version 3 of the L;cense, or
64
-# (at your option) any later version.
65
-#
66
-# This program is distributed in the hope that it will be useful, but
67
-# WITHOUT ANY WARRANTY; without even the implied warranty of
68
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the $1\': machine \`$basic_machineyramid?unknown$basic_machineu$basic_machine$basic_machine$basic_machine$basic_machinec9c | dpx2*-bull-next)
69
- os=-nextstep3$1$1$1$1i386-vsta | vstabin/sh
70
-# Configuration validation subroutine script.
71
-# Copyright 1992-2018 Free Software Foundation, Inc.
72
-
73
-timestamp='2018-03-08it and/or modify it
74
-# under the terms of the GNU General Public License as published bon subroutine $basic_machine-linuxomron$basic_machine$basic_machine$basic_machine ext$basic_machine$basic_machine$basic_machine$basic_machine$basic_machinepentium4i786-`echo $basic_machinepn$basic_machineppcle | ppc-le | powerpc-littlele$basic_machine$basic_machine | ppc64-le | powerpc64-little64le$basic_machinepsshsh5elh6h64-unknown
75
- ;
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -1,75 +0,0 @@
1 #! /bin/sh
2 # Configuration validation subroutine script.
3 # Copyright 1992-2014 Free Software Found4-12-03it and/or modify it
4 # under the terms of the GNU General Public License as published by
5 # t;e Free Software Foundation, either version 3 of the L;cense, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <https://www.gnu.org/licenses/>.
15 #
16 # As a special exception#
17 # As a special exception to the GNU General Public License, if you
18 # distribute this file as part of a program that contains a
19 # configuration script generated by Autoconf, you may include it under
20 # the same distribution terms that you use for the rest of that
21 # program. This Exception is an additional permission under section 7
22 # of the GNU General Public License, version 3 ("GPLv3").
23
24
25 # Please send patches to <[email protected]>.
26 #
27 # Configuration subroutine to validate and canonicalize a configuration type.
28 # Supply the specified configuration type as an argument.
29 # If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
30
31 'orting which valid configurations
32 # it does not support. The user should be able to distinguish
33 # a failure to support;hb=HEAD
34 $0 [OPTION]f not, see <https:/eration mode a special exception to the GNU General Public License, if you
35 # distribute this file as part of a program that contains a
36 # configuration script generated by Autoconf, you may include it under
37 # the same distribution terms that you use for the rest of that
38 # program. This Excepti4 Free Software Foundation, Inc.
39
40 er section 7
41 # of the GNU General Public License, version 3 ("GPLv3").
42
43
44 # Please send patches to <[email protected]>.
45 #
46 # Configuration subroutine to validate and canonicalize a configuration type.
47 # Supply the specified configuration type as an argument.
48 # If it is invalid, we print 1 Free Software Foundation,3 Free Software Foundation, Inc.
49
50 'orting which valid configurations
51 # it does not support. The user should be able to distinguish
52 # a failure to support a valid configuration from a meaningless
53 # configur$1$1$1$1$1$basic_machine !$1$1$1$1$15v6$1$1udk$1! /bin/sh
54 # Cio$1$1windowsnt/windowsnt/windp11e32k | z8k)
55 ;;
56 msbut
57 # WITHOUT ANY W#! /bin/sh
58 # Configuration validation subroutine script.
59 # Copyright 1992-2018 Free Software Foundation, Inc.
60
61 timestamp='2018-03-08it and/or modify it
62 # under the terms of the GNU General Public License as published by
63 # t;e Free Software Foundation, either version 3 of the L;cense, or
64 # (at your option) any later version.
65 #
66 # This program is distributed in the hope that it will be useful, but
67 # WITHOUT ANY WARRANTY; without even the implied warranty of
68 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the $1\': machine \`$basic_machineyramid?unknown$basic_machineu$basic_machine$basic_machine$basic_machine$basic_machinec9c | dpx2*-bull-next)
69 os=-nextstep3$1$1$1$1i386-vsta | vstabin/sh
70 # Configuration validation subroutine script.
71 # Copyright 1992-2018 Free Software Foundation, Inc.
72
73 timestamp='2018-03-08it and/or modify it
74 # under the terms of the GNU General Public License as published bon subroutine $basic_machine-linuxomron$basic_machine$basic_machine$basic_machine ext$basic_machine$basic_machine$basic_machine$basic_machine$basic_machinepentium4i786-`echo $basic_machinepn$basic_machineppcle | ppc-le | powerpc-littlele$basic_machine$basic_machine | ppc64-le | powerpc64-little64le$basic_machinepsshsh5elh6h64-unknown
75 ;
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -1,75 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D autosetup/find-tclsh
-10
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -1,10 +0,0 @@
1
-#!/bin/sh
2
-# Looks for a suitable tclsh or jimsh in the PATH
3
-# If not foundstrap jimsh d=`dirname "$0"`
4
-{ "$d/jimshd/${1-ac"; } 2>&1done
5
-echo 1>&2 bootstrap jimsh0"
6
-for cc in tclsh8.7; do
7
- { $tclsh "$d/c"; } 2>&1 >/dev "$d/${1-autosetup--tclsh}"; } 2>/devexit 0
8
-done
9
-echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
10
-for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -1,10 +0,0 @@
1 #!/bin/sh
2 # Looks for a suitable tclsh or jimsh in the PATH
3 # If not foundstrap jimsh d=`dirname "$0"`
4 { "$d/jimshd/${1-ac"; } 2>&1done
5 echo 1>&2 bootstrap jimsh0"
6 for cc in tclsh8.7; do
7 { $tclsh "$d/c"; } 2>&1 >/dev "$d/${1-autosetup--tclsh}"; } 2>/devexit 0
8 done
9 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
10 for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -1,10 +0,0 @@
 
 
 
 
 
 
 
 
 
 
+2033 -1988
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
11
/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
2
-#define _GNU_SOURCE
32
#define JIM_TCL_COMPAT
4
-#define JIM_REFERENCES
53
#define JIM_ANSIC
64
#define JIM_REGEXP
75
#define HAVE_NO_AUTOCONF
86
#define _JIMAUTOCONF_H
97
#define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
3129
#define HAVE_MKDIR_ONE_ARG
3230
#define HAVE_SYSTEM
3331
#define HAVE_SYS_TIME_H
3432
#define HAVE_DIRENT_H
3533
#define HAVE_UNISTD_H
34
+#define HAVE_UMASK
35
+#include <sys/stat.h>
36
+#ifndef S_IRWXG
37
+#define S_IRWXG 0
38
+#endif
39
+#ifndef S_IRWXO
40
+#define S_IRWXO 0
41
+#endif
3642
#else
3743
#define TCL_PLATFORM_OS "unknown"
3844
#define TCL_PLATFORM_PLATFORM "unix"
3945
#define TCL_PLATFORM_PATH_SEPARATOR ":"
46
+#ifdef _MINIX
47
+#define vfork fork
48
+#define _POSIX_SOURCE
49
+#else
50
+#define _GNU_SOURCE
51
+#endif
4052
#define HAVE_VFORK
4153
#define HAVE_WAITPID
4254
#define HAVE_ISATTY
4355
#define HAVE_MKSTEMP
4456
#define HAVE_LINK
4557
#define HAVE_SYS_TIME_H
4658
#define HAVE_DIRENT_H
4759
#define HAVE_UNISTD_H
60
+#define HAVE_UMASK
4861
#endif
49
-#define JIM_VERSION 76
62
+#define JIM_VERSION 77
5063
#ifndef JIM_WIN32COMPAT_H
5164
#define JIM_WIN32COMPAT_H
5265
5366
5467
@@ -88,11 +101,10 @@
88101
#define JIM_WIDE_MIN LLONG_MIN
89102
#define JIM_WIDE_MAX LLONG_MAX
90103
#define JIM_WIDE_MODIFIER "I64d"
91104
#define strcasecmp _stricmp
92105
#define strtoull _strtoui64
93
-#define snprintf _snprintf
94106
95107
#include <io.h>
96108
97109
struct timeval {
98110
long tv_sec;
@@ -105,14 +117,14 @@
105117
struct dirent {
106118
char *d_name;
107119
};
108120
109121
typedef struct DIR {
110
- long handle;
122
+ long handle;
111123
struct _finddata_t info;
112
- struct dirent result;
113
- char *name;
124
+ struct dirent result;
125
+ char *name;
114126
} DIR;
115127
116128
DIR *opendir(const char *name);
117129
int closedir(DIR *dir);
118130
struct dirent *readdir(DIR *dir);
@@ -122,11 +134,11 @@
122134
#include <stdlib.h>
123135
#define strtod __strtod
124136
125137
#endif
126138
127
-#endif
139
+#endif
128140
129141
#ifdef __cplusplus
130142
}
131143
#endif
132144
@@ -146,19 +158,21 @@
146158
147159
#ifndef JIM_UTF8
148160
#include <ctype.h>
149161
150162
151
-#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
163
+#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
164
+#define utf8_strwidth(S, B) utf8_strlen((S), (B))
152165
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
153166
#define utf8_getchars(CP, C) (*(CP) = (C), 1)
154167
#define utf8_upper(C) toupper(C)
155168
#define utf8_title(C) toupper(C)
156169
#define utf8_lower(C) tolower(C)
157170
#define utf8_index(C, I) (I)
158171
#define utf8_charlen(C) 1
159172
#define utf8_prev_len(S, L) 1
173
+#define utf8_width(C) 1
160174
161175
#else
162176
163177
#endif
164178
@@ -175,13 +189,13 @@
175189
extern "C" {
176190
#endif
177191
178192
#include <time.h>
179193
#include <limits.h>
180
-#include <stdio.h>
181
-#include <stdlib.h>
182
-#include <stdarg.h>
194
+#include <stdio.h>
195
+#include <stdlib.h>
196
+#include <stdarg.h>
183197
184198
185199
#ifndef HAVE_NO_AUTOCONF
186200
#endif
187201
@@ -224,31 +238,31 @@
224238
#define JIM_SIGNAL 5
225239
#define JIM_EXIT 6
226240
227241
#define JIM_EVAL 7
228242
229
-#define JIM_MAX_CALLFRAME_DEPTH 1000
230
-#define JIM_MAX_EVAL_DEPTH 2000
243
+#define JIM_MAX_CALLFRAME_DEPTH 1000
244
+#define JIM_MAX_EVAL_DEPTH 2000
231245
232246
233247
#define JIM_PRIV_FLAG_SHIFT 20
234248
235
-#define JIM_NONE 0
236
-#define JIM_ERRMSG 1
237
-#define JIM_ENUM_ABBREV 2
238
-#define JIM_UNSHARED 4
239
-#define JIM_MUSTEXIST 8
240
-
241
-
242
-#define JIM_SUBST_NOVAR 1
243
-#define JIM_SUBST_NOCMD 2
244
-#define JIM_SUBST_NOESC 4
245
-#define JIM_SUBST_FLAG 128
246
-
247
-
248
-#define JIM_CASESENS 0
249
-#define JIM_NOCASE 1
249
+#define JIM_NONE 0
250
+#define JIM_ERRMSG 1
251
+#define JIM_ENUM_ABBREV 2
252
+#define JIM_UNSHARED 4
253
+#define JIM_MUSTEXIST 8
254
+
255
+
256
+#define JIM_SUBST_NOVAR 1
257
+#define JIM_SUBST_NOCMD 2
258
+#define JIM_SUBST_NOESC 4
259
+#define JIM_SUBST_FLAG 128
260
+
261
+
262
+#define JIM_CASESENS 0
263
+#define JIM_NOCASE 1
250264
251265
252266
#define JIM_PATH_LEN 1024
253267
254268
@@ -339,79 +353,79 @@
339353
#define Jim_GetHashTableSize(ht) ((ht)->size)
340354
#define Jim_GetHashTableUsed(ht) ((ht)->used)
341355
342356
343357
typedef struct Jim_Obj {
344
- char *bytes;
345
- const struct Jim_ObjType *typePtr;
346
- int refCount;
347
- int length;
348
-
358
+ char *bytes;
359
+ const struct Jim_ObjType *typePtr;
360
+ int refCount;
361
+ int length;
362
+
349363
union {
350
-
364
+
351365
jim_wide wideValue;
352
-
366
+
353367
int intValue;
354
-
368
+
355369
double doubleValue;
356
-
370
+
357371
void *ptr;
358
-
372
+
359373
struct {
360374
void *ptr1;
361375
void *ptr2;
362376
} twoPtrValue;
363
-
377
+
364378
struct {
365379
struct Jim_Var *varPtr;
366
- unsigned long callFrameId;
367
- int global;
380
+ unsigned long callFrameId;
381
+ int global;
368382
} varValue;
369
-
383
+
370384
struct {
371385
struct Jim_Obj *nsObj;
372386
struct Jim_Cmd *cmdPtr;
373
- unsigned long procEpoch;
387
+ unsigned long procEpoch;
374388
} cmdValue;
375
-
389
+
376390
struct {
377
- struct Jim_Obj **ele;
378
- int len;
379
- int maxLen;
391
+ struct Jim_Obj **ele;
392
+ int len;
393
+ int maxLen;
380394
} listValue;
381
-
395
+
382396
struct {
383397
int maxLength;
384
- int charLength;
398
+ int charLength;
385399
} strValue;
386
-
400
+
387401
struct {
388402
unsigned long id;
389403
struct Jim_Reference *refPtr;
390404
} refValue;
391
-
405
+
392406
struct {
393407
struct Jim_Obj *fileNameObj;
394408
int lineNumber;
395409
} sourceValue;
396
-
410
+
397411
struct {
398412
struct Jim_Obj *varNameObjPtr;
399413
struct Jim_Obj *indexObjPtr;
400414
} dictSubstValue;
401
-
415
+
402416
struct {
403
- void *compre;
417
+ void *compre;
404418
unsigned flags;
405419
} regexpValue;
406420
struct {
407421
int line;
408422
int argc;
409423
} scriptLineValue;
410424
} internalRep;
411
- struct Jim_Obj *prevObjPtr;
412
- struct Jim_Obj *nextObjPtr;
425
+ struct Jim_Obj *prevObjPtr;
426
+ struct Jim_Obj *nextObjPtr;
413427
} Jim_Obj;
414428
415429
416430
#define Jim_IncrRefCount(objPtr) \
417431
++(objPtr)->refCount
@@ -442,40 +456,40 @@
442456
typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
443457
struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
444458
typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
445459
446460
typedef struct Jim_ObjType {
447
- const char *name;
461
+ const char *name;
448462
Jim_FreeInternalRepProc *freeIntRepProc;
449463
Jim_DupInternalRepProc *dupIntRepProc;
450464
Jim_UpdateStringProc *updateStringProc;
451465
int flags;
452466
} Jim_ObjType;
453467
454468
455
-#define JIM_TYPE_NONE 0
456
-#define JIM_TYPE_REFERENCES 1
469
+#define JIM_TYPE_NONE 0
470
+#define JIM_TYPE_REFERENCES 1
457471
458472
459473
460474
typedef struct Jim_CallFrame {
461
- unsigned long id;
462
- int level;
463
- struct Jim_HashTable vars;
464
- struct Jim_HashTable *staticVars;
465
- struct Jim_CallFrame *parent;
466
- Jim_Obj *const *argv;
467
- int argc;
468
- Jim_Obj *procArgsObjPtr;
469
- Jim_Obj *procBodyObjPtr;
470
- struct Jim_CallFrame *next;
471
- Jim_Obj *nsObj;
472
- Jim_Obj *fileNameObj;
475
+ unsigned long id;
476
+ int level;
477
+ struct Jim_HashTable vars;
478
+ struct Jim_HashTable *staticVars;
479
+ struct Jim_CallFrame *parent;
480
+ Jim_Obj *const *argv;
481
+ int argc;
482
+ Jim_Obj *procArgsObjPtr;
483
+ Jim_Obj *procBodyObjPtr;
484
+ struct Jim_CallFrame *next;
485
+ Jim_Obj *nsObj;
486
+ Jim_Obj *fileNameObj;
473487
int line;
474
- Jim_Stack *localCommands;
475
- struct Jim_Obj *tailcallObj;
476
- struct Jim_Cmd *tailcallCmd;
488
+ Jim_Stack *localCommands;
489
+ struct Jim_Obj *tailcallObj;
490
+ struct Jim_Cmd *tailcallCmd;
477491
} Jim_CallFrame;
478492
479493
typedef struct Jim_Var {
480494
Jim_Obj *objPtr;
481495
struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +501,35 @@
487501
typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
488502
489503
490504
491505
typedef struct Jim_Cmd {
492
- int inUse;
493
- int isproc;
494
- struct Jim_Cmd *prevCmd;
506
+ int inUse;
507
+ int isproc;
508
+ struct Jim_Cmd *prevCmd;
495509
union {
496510
struct {
497
-
498
- Jim_CmdProc *cmdProc;
499
- Jim_DelCmdProc *delProc;
500
- void *privData;
511
+
512
+ Jim_CmdProc *cmdProc;
513
+ Jim_DelCmdProc *delProc;
514
+ void *privData;
501515
} native;
502516
struct {
503
-
517
+
504518
Jim_Obj *argListObjPtr;
505519
Jim_Obj *bodyObjPtr;
506
- Jim_HashTable *staticVars;
507
- int argListLen;
508
- int reqArity;
509
- int optArity;
510
- int argsPos;
511
- int upcall;
520
+ Jim_HashTable *staticVars;
521
+ int argListLen;
522
+ int reqArity;
523
+ int optArity;
524
+ int argsPos;
525
+ int upcall;
512526
struct Jim_ProcArg {
513
- Jim_Obj *nameObjPtr;
514
- Jim_Obj *defaultObjPtr;
527
+ Jim_Obj *nameObjPtr;
528
+ Jim_Obj *defaultObjPtr;
515529
} *arglist;
516
- Jim_Obj *nsObj;
530
+ Jim_Obj *nsObj;
517531
} proc;
518532
} u;
519533
} Jim_Cmd;
520534
521535
@@ -523,64 +537,64 @@
523537
unsigned char sbox[256];
524538
unsigned int i, j;
525539
} Jim_PrngState;
526540
527541
typedef struct Jim_Interp {
528
- Jim_Obj *result;
529
- int errorLine;
530
- Jim_Obj *errorFileNameObj;
531
- int addStackTrace;
532
- int maxCallFrameDepth;
533
- int maxEvalDepth;
534
- int evalDepth;
535
- int returnCode;
536
- int returnLevel;
537
- int exitCode;
538
- long id;
539
- int signal_level;
540
- jim_wide sigmask;
541
- int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
542
- Jim_CallFrame *framePtr;
543
- Jim_CallFrame *topFramePtr;
544
- struct Jim_HashTable commands;
542
+ Jim_Obj *result;
543
+ int errorLine;
544
+ Jim_Obj *errorFileNameObj;
545
+ int addStackTrace;
546
+ int maxCallFrameDepth;
547
+ int maxEvalDepth;
548
+ int evalDepth;
549
+ int returnCode;
550
+ int returnLevel;
551
+ int exitCode;
552
+ long id;
553
+ int signal_level;
554
+ jim_wide sigmask;
555
+ int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
556
+ Jim_CallFrame *framePtr;
557
+ Jim_CallFrame *topFramePtr;
558
+ struct Jim_HashTable commands;
545559
unsigned long procEpoch; /* Incremented every time the result
546560
of procedures names lookup caching
547561
may no longer be valid. */
548562
unsigned long callFrameEpoch; /* Incremented every time a new
549563
callframe is created. This id is used for the
550564
'ID' field contained in the Jim_CallFrame
551565
structure. */
552
- int local;
553
- Jim_Obj *liveList;
554
- Jim_Obj *freeList;
555
- Jim_Obj *currentScriptObj;
556
- Jim_Obj *nullScriptObj;
557
- Jim_Obj *emptyObj;
558
- Jim_Obj *trueObj;
559
- Jim_Obj *falseObj;
560
- unsigned long referenceNextId;
561
- struct Jim_HashTable references;
566
+ int local;
567
+ Jim_Obj *liveList;
568
+ Jim_Obj *freeList;
569
+ Jim_Obj *currentScriptObj;
570
+ Jim_Obj *nullScriptObj;
571
+ Jim_Obj *emptyObj;
572
+ Jim_Obj *trueObj;
573
+ Jim_Obj *falseObj;
574
+ unsigned long referenceNextId;
575
+ struct Jim_HashTable references;
562576
unsigned long lastCollectId; /* reference max Id of the last GC
563577
execution. It's set to -1 while the collection
564578
is running as sentinel to avoid to recursive
565579
calls via the [collect] command inside
566580
finalizers. */
567
- time_t lastCollectTime;
568
- Jim_Obj *stackTrace;
569
- Jim_Obj *errorProc;
570
- Jim_Obj *unknown;
571
- int unknown_called;
572
- int errorFlag;
581
+ time_t lastCollectTime;
582
+ Jim_Obj *stackTrace;
583
+ Jim_Obj *errorProc;
584
+ Jim_Obj *unknown;
585
+ int unknown_called;
586
+ int errorFlag;
573587
void *cmdPrivData; /* Used to pass the private data pointer to
574588
a command. It is set to what the user specified
575589
via Jim_CreateCommand(). */
576590
577
- struct Jim_CallFrame *freeFramesList;
578
- struct Jim_HashTable assocData;
579
- Jim_PrngState *prngState;
580
- struct Jim_HashTable packages;
581
- Jim_Stack *loadHandles;
591
+ struct Jim_CallFrame *freeFramesList;
592
+ struct Jim_HashTable assocData;
593
+ Jim_PrngState *prngState;
594
+ struct Jim_HashTable packages;
595
+ Jim_Stack *loadHandles;
582596
} Jim_Interp;
583597
584598
#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
585599
#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
586600
#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +637,11 @@
623637
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
624638
625639
626640
JIM_EXPORT char **Jim_GetEnviron(void);
627641
JIM_EXPORT void Jim_SetEnviron(char **env);
628
-JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
642
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template);
629643
630644
631645
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
632646
633647
@@ -816,14 +830,18 @@
816830
Jim_Obj *newObjPtr, int flags);
817831
JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
818832
Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
819833
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
820834
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
821
-JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
822
-JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
835
+
836
+#define JIM_DICTMATCH_KEYS 0x0001
837
+#define JIM_DICTMATCH_VALUES 0x002
838
+
839
+JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types);
823840
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
824841
JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
842
+JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv);
825843
826844
827845
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
828846
int *intPtr);
829847
@@ -831,10 +849,14 @@
831849
JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
832850
Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
833851
JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
834852
Jim_Obj *exprObjPtr, int *boolPtr);
835853
854
+
855
+JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr,
856
+ int *booleanPtr);
857
+
836858
837859
JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
838860
jim_wide *widePtr);
839861
JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
840862
long *longPtr);
@@ -852,10 +874,12 @@
852874
853875
JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
854876
Jim_Obj *const *argv, const char *msg);
855877
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
856878
const char * const *tablePtr, int *indexPtr, const char *name, int flags);
879
+JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr,
880
+ const char *const *tablePtr);
857881
JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
858882
Jim_Obj *scriptObj, char *stateCharPtr);
859883
860884
JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
861885
@@ -904,11 +928,11 @@
904928
905929
#ifdef __cplusplus
906930
}
907931
#endif
908932
909
-#endif
933
+#endif
910934
911935
#ifndef JIM_SUBCMD_H
912936
#define JIM_SUBCMD_H
913937
914938
@@ -915,24 +939,24 @@
915939
#ifdef __cplusplus
916940
extern "C" {
917941
#endif
918942
919943
920
-#define JIM_MODFLAG_HIDDEN 0x0001
921
-#define JIM_MODFLAG_FULLARGV 0x0002
944
+#define JIM_MODFLAG_HIDDEN 0x0001
945
+#define JIM_MODFLAG_FULLARGV 0x0002
922946
923947
924948
925949
typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
926950
927951
typedef struct {
928
- const char *cmd;
929
- const char *args;
930
- jim_subcmd_function *function;
931
- short minargs;
932
- short maxargs;
933
- unsigned short flags;
952
+ const char *cmd;
953
+ const char *args;
954
+ jim_subcmd_function *function;
955
+ short minargs;
956
+ short maxargs;
957
+ unsigned short flags;
934958
} jim_subcmd_type;
935959
936960
const jim_subcmd_type *
937961
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
938962
@@ -960,36 +984,36 @@
960984
int rm_eo;
961985
} regmatch_t;
962986
963987
964988
typedef struct regexp {
965
-
966
- int re_nsub;
967
-
968
-
969
- int cflags;
970
- int err;
971
- int regstart;
972
- int reganch;
973
- int regmust;
974
- int regmlen;
975
- int *program;
976
-
977
-
978
- const char *regparse;
979
- int p;
980
- int proglen;
981
-
982
-
983
- int eflags;
984
- const char *start;
985
- const char *reginput;
986
- const char *regbol;
987
-
988
-
989
- regmatch_t *pmatch;
990
- int nmatch;
989
+
990
+ int re_nsub;
991
+
992
+
993
+ int cflags;
994
+ int err;
995
+ int regstart;
996
+ int reganch;
997
+ int regmust;
998
+ int regmlen;
999
+ int *program;
1000
+
1001
+
1002
+ const char *regparse;
1003
+ int p;
1004
+ int proglen;
1005
+
1006
+
1007
+ int eflags;
1008
+ const char *start;
1009
+ const char *reginput;
1010
+ const char *regbol;
1011
+
1012
+
1013
+ regmatch_t *pmatch;
1014
+ int nmatch;
9911015
} regexp;
9921016
9931017
typedef regexp regex_t;
9941018
9951019
#define REG_EXTENDED 0
@@ -997,13 +1021,13 @@
9971021
#define REG_ICASE 2
9981022
9991023
#define REG_NOTBOL 16
10001024
10011025
enum {
1002
- REG_NOERROR,
1003
- REG_NOMATCH,
1004
- REG_BADPAT,
1026
+ REG_NOERROR,
1027
+ REG_NOMATCH,
1028
+ REG_BADPAT,
10051029
REG_ERR_NULL_ARGUMENT,
10061030
REG_ERR_UNKNOWN,
10071031
REG_ERR_TOO_BIG,
10081032
REG_ERR_NOMEM,
10091033
REG_ERR_TOO_MANY_PAREN,
@@ -1100,10 +1124,43 @@
11001124
"\n"
11011125
"if {$tcl_platform(platform) eq \"windows\"} {\n"
11021126
" set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
11031127
"}\n"
11041128
"\n"
1129
+"\n"
1130
+"set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n"
1131
+"\n"
1132
+"\n"
1133
+"\n"
1134
+"proc tcl::autocomplete {prefix} {\n"
1135
+" if {[set space [string first \" \" $prefix]] != -1} {\n"
1136
+" set cmd [string range $prefix 0 $space-1]\n"
1137
+" if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n"
1138
+" set arg [string range $prefix $space+1 end]\n"
1139
+"\n"
1140
+" return [lmap p [$cmd -commands] {\n"
1141
+" if {![string match \"${arg}*\" $p]} continue\n"
1142
+" function \"$cmd $p\"\n"
1143
+" }]\n"
1144
+" }\n"
1145
+" }\n"
1146
+"\n"
1147
+" if {[string match \"source *\" $prefix]} {\n"
1148
+" set path [string range $prefix 7 end]\n"
1149
+" return [lmap p [glob -nocomplain \"${path}*\"] {\n"
1150
+" function \"source $p\"\n"
1151
+" }]\n"
1152
+" }\n"
1153
+"\n"
1154
+" return [lmap p [lsort [info commands $prefix*]] {\n"
1155
+" if {[string match \"* *\" $p]} {\n"
1156
+" continue\n"
1157
+" }\n"
1158
+" function $p\n"
1159
+" }]\n"
1160
+"}\n"
1161
+"\n"
11051162
"_jimsh_init\n"
11061163
);
11071164
}
11081165
int Jim_globInit(Jim_Interp *interp)
11091166
{
@@ -1402,31 +1459,10 @@
14021459
" if {[exists ::jim::exe]} {\n"
14031460
" return $::jim::exe\n"
14041461
" }\n"
14051462
"}\n"
14061463
"\n"
1407
-"\n"
1408
-"proc {dict with} {&dictVar {args key} script} {\n"
1409
-" set keys {}\n"
1410
-" foreach {n v} [dict get $dictVar {*}$key] {\n"
1411
-" upvar $n var_$n\n"
1412
-" set var_$n $v\n"
1413
-" lappend keys $n\n"
1414
-" }\n"
1415
-" catch {uplevel 1 $script} msg opts\n"
1416
-" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1417
-" foreach n $keys {\n"
1418
-" if {[info exists var_$n]} {\n"
1419
-" dict set dictVar {*}$key $n [set var_$n]\n"
1420
-" } else {\n"
1421
-" dict unset dictVar {*}$key $n\n"
1422
-" }\n"
1423
-" }\n"
1424
-" }\n"
1425
-" return {*}$opts $msg\n"
1426
-"}\n"
1427
-"\n"
14281464
"\n"
14291465
"proc {dict update} {&varName args script} {\n"
14301466
" set keys {}\n"
14311467
" foreach {n v} $args {\n"
14321468
" upvar $v var_$v\n"
@@ -1445,23 +1481,10 @@
14451481
" }\n"
14461482
" }\n"
14471483
" return {*}$opts $msg\n"
14481484
"}\n"
14491485
"\n"
1450
-"\n"
1451
-"\n"
1452
-"proc {dict merge} {dict args} {\n"
1453
-" foreach d $args {\n"
1454
-"\n"
1455
-" dict size $d\n"
1456
-" foreach {k v} $d {\n"
1457
-" dict set dict $k $v\n"
1458
-" }\n"
1459
-" }\n"
1460
-" return $dict\n"
1461
-"}\n"
1462
-"\n"
14631486
"proc {dict replace} {dictionary {args {key value}}} {\n"
14641487
" if {[llength ${key value}] % 2} {\n"
14651488
" tailcall {dict replace}\n"
14661489
" }\n"
14671490
" tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1526,10 @@
15031526
" dict unset dictionary $k\n"
15041527
" }\n"
15051528
" return $dictionary\n"
15061529
"}\n"
15071530
"\n"
1508
-"\n"
1509
-"proc {dict values} {dictionary {pattern *}} {\n"
1510
-" dict keys [lreverse $dictionary] $pattern\n"
1511
-"}\n"
1512
-"\n"
15131531
"\n"
15141532
"proc {dict for} {vars dictionary script} {\n"
15151533
" if {[llength $vars] != 2} {\n"
15161534
" return -code error \"must have exactly two variable names\"\n"
15171535
" }\n"
@@ -1588,11 +1606,10 @@
15881606
"\n"
15891607
"\n"
15901608
"proc fileevent {args} {\n"
15911609
" tailcall {*}$args\n"
15921610
"}\n"
1593
-"\n"
15941611
"\n"
15951612
"\n"
15961613
"\n"
15971614
"proc parray {arrayname {pattern *} {puts puts}} {\n"
15981615
" upvar $arrayname a\n"
@@ -1701,15 +1718,10 @@
17011718
"\n"
17021719
"\n"
17031720
"\n"
17041721
"\n"
17051722
"\n"
1706
-"\n"
1707
-"\n"
1708
-"\n"
1709
-"\n"
1710
-"\n"
17111723
"proc try {args} {\n"
17121724
" set catchopts {}\n"
17131725
" while {[string match -* [lindex $args 0]]} {\n"
17141726
" set args [lassign $args opt]\n"
17151727
" if {$opt eq \"--\"} {\n"
@@ -1780,10 +1792,13 @@
17801792
"}\n"
17811793
);
17821794
}
17831795
17841796
1797
+#ifndef _GNU_SOURCE
1798
+#define _GNU_SOURCE
1799
+#endif
17851800
#include <stdio.h>
17861801
#include <string.h>
17871802
#include <errno.h>
17881803
#include <fcntl.h>
17891804
#ifdef HAVE_UNISTD_H
@@ -1807,13 +1822,16 @@
18071822
#if defined(JIM_SSL)
18081823
#include <openssl/ssl.h>
18091824
#include <openssl/err.h>
18101825
#endif
18111826
1827
+#ifdef HAVE_TERMIOS_H
1828
+#endif
18121829
1813
-#define AIO_CMD_LEN 32
1814
-#define AIO_BUF_LEN 256
1830
+
1831
+#define AIO_CMD_LEN 32
1832
+#define AIO_BUF_LEN 256
18151833
18161834
#ifndef HAVE_FTELLO
18171835
#define ftello ftell
18181836
#endif
18191837
#ifndef HAVE_FSEEKO
@@ -1848,11 +1866,11 @@
18481866
typedef struct AioFile
18491867
{
18501868
FILE *fp;
18511869
Jim_Obj *filename;
18521870
int type;
1853
- int openFlags;
1871
+ int openFlags;
18541872
int fd;
18551873
Jim_Obj *rEvent;
18561874
Jim_Obj *wEvent;
18571875
Jim_Obj *eEvent;
18581876
int addr_family;
@@ -1879,21 +1897,21 @@
18791897
{
18801898
if (!ferror(af->fp)) {
18811899
return JIM_OK;
18821900
}
18831901
clearerr(af->fp);
1884
-
1902
+
18851903
if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
18861904
return JIM_OK;
18871905
}
18881906
#ifdef ECONNRESET
18891907
if (errno == ECONNRESET) {
18901908
return JIM_OK;
18911909
}
18921910
#endif
18931911
#ifdef ECONNABORTED
1894
- if (errno != ECONNABORTED) {
1912
+ if (errno == ECONNABORTED) {
18951913
return JIM_OK;
18961914
}
18971915
#endif
18981916
return JIM_ERR;
18991917
}
@@ -1945,20 +1963,19 @@
19451963
JIM_NOTUSED(interp);
19461964
19471965
Jim_DecrRefCount(interp, af->filename);
19481966
19491967
#ifdef jim_ext_eventloop
1950
-
1951
- Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1968
+
1969
+ Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
19521970
#endif
19531971
19541972
#if defined(JIM_SSL)
19551973
if (af->ssl != NULL) {
19561974
SSL_free(af->ssl);
19571975
}
19581976
#endif
1959
-
19601977
if (!(af->openFlags & AIO_KEEPOPEN)) {
19611978
fclose(af->fp);
19621979
}
19631980
19641981
Jim_Free(af);
@@ -1968,11 +1985,11 @@
19681985
{
19691986
AioFile *af = Jim_CmdPrivData(interp);
19701987
char buf[AIO_BUF_LEN];
19711988
Jim_Obj *objPtr;
19721989
int nonewline = 0;
1973
- jim_wide neededLen = -1;
1990
+ jim_wide neededLen = -1;
19741991
19751992
if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
19761993
nonewline = 1;
19771994
argv++;
19781995
argc--;
@@ -2007,11 +2024,11 @@
20072024
}
20082025
}
20092026
if (retval != readlen)
20102027
break;
20112028
}
2012
-
2029
+
20132030
if (JimCheckStreamError(interp, af)) {
20142031
Jim_FreeNewObj(interp, objPtr);
20152032
return JIM_ERR;
20162033
}
20172034
if (nonewline) {
@@ -2029,11 +2046,11 @@
20292046
20302047
AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
20312048
{
20322049
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
20332050
2034
-
2051
+
20352052
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
20362053
return (AioFile *) cmdPtr->u.native.privData;
20372054
}
20382055
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
20392056
return NULL;
@@ -2110,21 +2127,21 @@
21102127
}
21112128
else {
21122129
len = strlen(buf);
21132130
21142131
if (len && (buf[len - 1] == '\n')) {
2115
-
2132
+
21162133
len--;
21172134
}
21182135
21192136
Jim_AppendString(interp, objPtr, buf, len);
21202137
break;
21212138
}
21222139
}
21232140
21242141
if (JimCheckStreamError(interp, af)) {
2125
-
2142
+
21262143
Jim_FreeNewObj(interp, objPtr);
21272144
return JIM_ERR;
21282145
}
21292146
21302147
if (argc) {
@@ -2134,11 +2151,11 @@
21342151
}
21352152
21362153
len = Jim_Length(objPtr);
21372154
21382155
if (len == 0 && feof(af->fp)) {
2139
-
2156
+
21402157
len = -1;
21412158
}
21422159
Jim_SetResultInt(interp, len);
21432160
}
21442161
else {
@@ -2364,33 +2381,33 @@
23642381
23652382
static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
23662383
int argc, Jim_Obj * const *argv)
23672384
{
23682385
if (argc == 0) {
2369
-
2386
+
23702387
if (*scriptHandlerObj) {
23712388
Jim_SetResult(interp, *scriptHandlerObj);
23722389
}
23732390
return JIM_OK;
23742391
}
23752392
23762393
if (*scriptHandlerObj) {
2377
-
2378
- Jim_DeleteFileHandler(interp, af->fp, mask);
2394
+
2395
+ Jim_DeleteFileHandler(interp, af->fd, mask);
23792396
}
23802397
2381
-
2398
+
23822399
if (Jim_Length(argv[0]) == 0) {
2383
-
2400
+
23842401
return JIM_OK;
23852402
}
23862403
2387
-
2404
+
23882405
Jim_IncrRefCount(argv[0]);
23892406
*scriptHandlerObj = argv[0];
23902407
2391
- Jim_CreateFileHandler(interp, af->fp, mask,
2408
+ Jim_CreateFileHandler(interp, af->fd, mask,
23922409
JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
23932410
23942411
return JIM_OK;
23952412
}
23962413
@@ -2414,136 +2431,138 @@
24142431
24152432
return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
24162433
}
24172434
#endif
24182435
2436
+
2437
+
24192438
24202439
static const jim_subcmd_type aio_command_table[] = {
24212440
{ "read",
24222441
"?-nonewline? ?len?",
24232442
aio_cmd_read,
24242443
0,
24252444
2,
2426
-
2445
+
24272446
},
24282447
{ "copyto",
24292448
"handle ?size?",
24302449
aio_cmd_copy,
24312450
1,
24322451
2,
2433
-
2452
+
24342453
},
24352454
{ "gets",
24362455
"?var?",
24372456
aio_cmd_gets,
24382457
0,
24392458
1,
2440
-
2459
+
24412460
},
24422461
{ "puts",
24432462
"?-nonewline? str",
24442463
aio_cmd_puts,
24452464
1,
24462465
2,
2447
-
2466
+
24482467
},
24492468
{ "isatty",
24502469
NULL,
24512470
aio_cmd_isatty,
24522471
0,
24532472
0,
2454
-
2473
+
24552474
},
24562475
{ "flush",
24572476
NULL,
24582477
aio_cmd_flush,
24592478
0,
24602479
0,
2461
-
2480
+
24622481
},
24632482
{ "eof",
24642483
NULL,
24652484
aio_cmd_eof,
24662485
0,
24672486
0,
2468
-
2487
+
24692488
},
24702489
{ "close",
24712490
"?r(ead)|w(rite)?",
24722491
aio_cmd_close,
24732492
0,
24742493
1,
24752494
JIM_MODFLAG_FULLARGV,
2476
-
2495
+
24772496
},
24782497
{ "seek",
24792498
"offset ?start|current|end",
24802499
aio_cmd_seek,
24812500
1,
24822501
2,
2483
-
2502
+
24842503
},
24852504
{ "tell",
24862505
NULL,
24872506
aio_cmd_tell,
24882507
0,
24892508
0,
2490
-
2509
+
24912510
},
24922511
{ "filename",
24932512
NULL,
24942513
aio_cmd_filename,
24952514
0,
24962515
0,
2497
-
2516
+
24982517
},
24992518
#ifdef O_NDELAY
25002519
{ "ndelay",
25012520
"?0|1?",
25022521
aio_cmd_ndelay,
25032522
0,
25042523
1,
2505
-
2524
+
25062525
},
25072526
#endif
25082527
#ifdef HAVE_FSYNC
25092528
{ "sync",
25102529
NULL,
25112530
aio_cmd_sync,
25122531
0,
25132532
0,
2514
-
2533
+
25152534
},
25162535
#endif
25172536
{ "buffering",
25182537
"none|line|full",
25192538
aio_cmd_buffering,
25202539
1,
25212540
1,
2522
-
2541
+
25232542
},
25242543
#ifdef jim_ext_eventloop
25252544
{ "readable",
25262545
"?readable-script?",
25272546
aio_cmd_readable,
25282547
0,
25292548
1,
2530
-
2549
+
25312550
},
25322551
{ "writable",
25332552
"?writable-script?",
25342553
aio_cmd_writable,
25352554
0,
25362555
1,
2537
-
2556
+
25382557
},
25392558
{ "onexception",
25402559
"?exception-script?",
25412560
aio_cmd_onexception,
25422561
0,
25432562
1,
2544
-
2563
+
25452564
},
25462565
#endif
25472566
{ NULL }
25482567
};
25492568
@@ -2566,11 +2585,11 @@
25662585
25672586
#ifdef jim_ext_tclcompat
25682587
{
25692588
const char *filename = Jim_String(argv[1]);
25702589
2571
-
2590
+
25722591
if (*filename == '|') {
25732592
Jim_Obj *evalObj[3];
25742593
25752594
evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
25762595
evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2623,11 +2642,11 @@
26232642
Jim_DecrRefCount(interp, filename);
26242643
return NULL;
26252644
}
26262645
}
26272646
2628
-
2647
+
26292648
af = Jim_Alloc(sizeof(*af));
26302649
memset(af, 0, sizeof(*af));
26312650
af->fp = fh;
26322651
af->fd = fileno(fh);
26332652
af->filename = filename;
@@ -2661,27 +2680,27 @@
26612680
Jim_SetResult(interp, objPtr);
26622681
return JIM_OK;
26632682
}
26642683
}
26652684
2666
-
2685
+
26672686
close(p[0]);
26682687
close(p[1]);
26692688
JimAioSetError(interp, NULL);
26702689
return JIM_ERR;
26712690
}
26722691
#endif
26732692
26742693
2675
-int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2694
+int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template)
26762695
{
26772696
#ifdef HAVE_MKSTEMP
26782697
int fd;
26792698
mode_t mask;
26802699
Jim_Obj *filenameObj;
26812700
2682
- if (template == NULL) {
2701
+ if (filename_template == NULL) {
26832702
const char *tmpdir = getenv("TMPDIR");
26842703
if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
26852704
tmpdir = "/tmp/";
26862705
}
26872706
filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
@@ -2689,21 +2708,15 @@
26892708
Jim_AppendString(interp, filenameObj, "/", 1);
26902709
}
26912710
Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
26922711
}
26932712
else {
2694
- filenameObj = Jim_NewStringObj(interp, template, -1);
2713
+ filenameObj = Jim_NewStringObj(interp, filename_template, -1);
26952714
}
26962715
2697
-#if defined(S_IRWXG) && defined(S_IRWXO)
2716
+
26982717
mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2699
-#else
2700
-
2701
- mask = umask(S_IXUSR);
2702
-#endif
2703
-
2704
-
27052718
fd = mkstemp(filenameObj->bytes);
27062719
umask(mask);
27072720
if (fd < 0) {
27082721
JimAioSetError(interp, filenameObj);
27092722
Jim_FreeNewObj(interp, filenameObj);
@@ -2731,11 +2744,11 @@
27312744
Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
27322745
#ifndef JIM_ANSIC
27332746
Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
27342747
#endif
27352748
2736
-
2749
+
27372750
JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
27382751
JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
27392752
JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
27402753
27412754
return JIM_OK;
@@ -2831,20 +2844,20 @@
28312844
{
28322845
regex_t *compre;
28332846
const char *pattern;
28342847
int ret;
28352848
2836
-
2849
+
28372850
if (objPtr->typePtr == &regexpObjType &&
28382851
objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
2839
-
2852
+
28402853
return objPtr->internalRep.regexpValue.compre;
28412854
}
28422855
2843
-
28442856
2845
-
2857
+
2858
+
28462859
pattern = Jim_String(objPtr);
28472860
compre = Jim_Alloc(sizeof(regex_t));
28482861
28492862
if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
28502863
char buf[100];
@@ -3001,11 +3014,11 @@
30013014
}
30023015
30033016
num_matches++;
30043017
30053018
if (opt_all && !opt_inline) {
3006
-
3019
+
30073020
goto try_next_match;
30083021
}
30093022
30103023
30113024
j = 0;
@@ -3041,11 +3054,11 @@
30413054
30423055
if (opt_inline) {
30433056
Jim_ListAppendElement(interp, resultListObj, resultObj);
30443057
}
30453058
else {
3046
-
3059
+
30473060
result = Jim_SetVariable(interp, argv[i], resultObj);
30483061
30493062
if (result != JIM_OK) {
30503063
Jim_FreeObj(interp, resultObj);
30513064
break;
@@ -3168,11 +3181,11 @@
31683181
31693182
source_str = Jim_GetString(argv[i + 1], &source_len);
31703183
replace_str = Jim_GetString(argv[i + 2], &replace_len);
31713184
varname = argv[i + 3];
31723185
3173
-
3186
+
31743187
resultObj = Jim_NewStringObj(interp, "", 0);
31753188
31763189
if (offset) {
31773190
if (offset < 0) {
31783191
offset += source_len + 1;
@@ -3183,11 +3196,11 @@
31833196
else if (offset < 0) {
31843197
offset = 0;
31853198
}
31863199
}
31873200
3188
-
3201
+
31893202
Jim_AppendString(interp, resultObj, source_str, offset);
31903203
31913204
31923205
n = source_len - offset;
31933206
p = source_str + offset;
@@ -3242,23 +3255,23 @@
32423255
}
32433256
32443257
p += pmatch[0].rm_eo;
32453258
n -= pmatch[0].rm_eo;
32463259
3247
-
3260
+
32483261
if (!opt_all || n == 0) {
32493262
break;
32503263
}
32513264
3252
-
3265
+
32533266
if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
32543267
break;
32553268
}
32563269
3257
-
3270
+
32583271
if (pattern[0] == '\0' && n) {
3259
-
3272
+
32603273
Jim_AppendString(interp, resultObj, p, 1);
32613274
p++;
32623275
n--;
32633276
}
32643277
@@ -3265,11 +3278,11 @@
32653278
regexec_flags |= REG_NOTBOL;
32663279
} while (n);
32673280
32683281
Jim_AppendString(interp, resultObj, p, -1);
32693282
3270
-
3283
+
32713284
if (argc - i == 4) {
32723285
result = Jim_SetVariable(interp, varname, resultObj);
32733286
32743287
if (result == JIM_OK) {
32753288
Jim_SetResultInt(interp, num_matches);
@@ -3371,11 +3384,11 @@
33713384
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
33723385
}
33733386
33743387
static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
33753388
{
3376
-
3389
+
33773390
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
33783391
33793392
AppendStatElement(interp, listObj, "dev", sb->st_dev);
33803393
AppendStatElement(interp, listObj, "ino", sb->st_ino);
33813394
AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3400,38 @@
33873400
AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
33883401
AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
33893402
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
33903403
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
33913404
3392
-
3405
+
33933406
if (varName) {
3394
- Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3407
+ Jim_Obj *objPtr;
3408
+ objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3409
+
33953410
if (objPtr) {
3396
- if (Jim_DictSize(interp, objPtr) < 0) {
3397
-
3411
+ Jim_Obj *objv[2];
3412
+
3413
+ objv[0] = objPtr;
3414
+ objv[1] = listObj;
3415
+
3416
+ objPtr = Jim_DictMerge(interp, 2, objv);
3417
+ if (objPtr == NULL) {
3418
+
33983419
Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
33993420
Jim_FreeNewObj(interp, listObj);
34003421
return JIM_ERR;
34013422
}
34023423
3403
- if (Jim_IsShared(objPtr))
3404
- objPtr = Jim_DuplicateObj(interp, objPtr);
3405
-
3406
-
3407
- Jim_ListAppendList(interp, objPtr, listObj);
3408
- Jim_DictSize(interp, objPtr);
34093424
Jim_InvalidateStringRep(objPtr);
34103425
34113426
Jim_FreeNewObj(interp, listObj);
34123427
listObj = objPtr;
34133428
}
34143429
Jim_SetVariable(interp, varName, listObj);
34153430
}
34163431
3417
-
3432
+
34183433
Jim_SetResult(interp, listObj);
34193434
34203435
return JIM_OK;
34213436
}
34223437
@@ -3432,11 +3447,11 @@
34323447
}
34333448
else if (p == path) {
34343449
Jim_SetResultString(interp, "/", -1);
34353450
}
34363451
else if (ISWINDOWS && p[-1] == ':') {
3437
-
3452
+
34383453
Jim_SetResultString(interp, path, p - path + 1);
34393454
}
34403455
else {
34413456
Jim_SetResultString(interp, path, p - path);
34423457
}
@@ -3512,35 +3527,35 @@
35123527
char *newname = Jim_Alloc(MAXPATHLEN + 1);
35133528
char *last = newname;
35143529
35153530
*newname = 0;
35163531
3517
-
3532
+
35183533
for (i = 0; i < argc; i++) {
35193534
int len;
35203535
const char *part = Jim_GetString(argv[i], &len);
35213536
35223537
if (*part == '/') {
3523
-
3538
+
35243539
last = newname;
35253540
}
35263541
else if (ISWINDOWS && strchr(part, ':')) {
3527
-
3542
+
35283543
last = newname;
35293544
}
35303545
else if (part[0] == '.') {
35313546
if (part[1] == '/') {
35323547
part += 2;
35333548
len -= 2;
35343549
}
35353550
else if (part[1] == 0 && last != newname) {
3536
-
3551
+
35373552
continue;
35383553
}
35393554
}
35403555
3541
-
3556
+
35423557
if (last != newname && last[-1] != '/') {
35433558
*last++ = '/';
35443559
}
35453560
35463561
if (len) {
@@ -3551,22 +3566,22 @@
35513566
}
35523567
memcpy(last, part, len);
35533568
last += len;
35543569
}
35553570
3556
-
3571
+
35573572
if (last > newname + 1 && last[-1] == '/') {
3558
-
3573
+
35593574
if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
35603575
*--last = 0;
35613576
}
35623577
}
35633578
}
35643579
35653580
*last = 0;
35663581
3567
-
3582
+
35683583
35693584
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
35703585
35713586
return JIM_OK;
35723587
}
@@ -3591,11 +3606,11 @@
35913606
static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
35923607
{
35933608
#ifdef X_OK
35943609
return file_access(interp, argv[0], X_OK);
35953610
#else
3596
-
3611
+
35973612
Jim_SetResultBool(interp, 1);
35983613
return JIM_OK;
35993614
#endif
36003615
}
36013616
@@ -3616,11 +3631,11 @@
36163631
while (argc--) {
36173632
const char *path = Jim_String(argv[0]);
36183633
36193634
if (unlink(path) == -1 && errno != ENOENT) {
36203635
if (rmdir(path) == -1) {
3621
-
3636
+
36223637
if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
36233638
Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
36243639
strerror(errno));
36253640
return JIM_ERR;
36263641
}
@@ -3639,15 +3654,15 @@
36393654
36403655
static int mkdir_all(char *path)
36413656
{
36423657
int ok = 1;
36433658
3644
-
3659
+
36453660
goto first;
36463661
36473662
while (ok--) {
3648
-
3663
+
36493664
{
36503665
char *slash = strrchr(path, '/');
36513666
36523667
if (slash && slash != path) {
36533668
*slash = 0;
@@ -3660,24 +3675,24 @@
36603675
first:
36613676
if (MKDIR_DEFAULT(path) == 0) {
36623677
return 0;
36633678
}
36643679
if (errno == ENOENT) {
3665
-
3680
+
36663681
continue;
36673682
}
3668
-
3683
+
36693684
if (errno == EEXIST) {
36703685
struct stat sb;
36713686
36723687
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
36733688
return 0;
36743689
}
3675
-
3690
+
36763691
errno = EEXIST;
36773692
}
3678
-
3693
+
36793694
break;
36803695
}
36813696
return -1;
36823697
}
36833698
@@ -3962,192 +3977,192 @@
39623977
{ "atime",
39633978
"name",
39643979
file_cmd_atime,
39653980
1,
39663981
1,
3967
-
3982
+
39683983
},
39693984
{ "mtime",
39703985
"name ?time?",
39713986
file_cmd_mtime,
39723987
1,
39733988
2,
3974
-
3989
+
39753990
},
39763991
{ "copy",
39773992
"?-force? source dest",
39783993
file_cmd_copy,
39793994
2,
39803995
3,
3981
-
3996
+
39823997
},
39833998
{ "dirname",
39843999
"name",
39854000
file_cmd_dirname,
39864001
1,
39874002
1,
3988
-
4003
+
39894004
},
39904005
{ "rootname",
39914006
"name",
39924007
file_cmd_rootname,
39934008
1,
39944009
1,
3995
-
4010
+
39964011
},
39974012
{ "extension",
39984013
"name",
39994014
file_cmd_extension,
40004015
1,
40014016
1,
4002
-
4017
+
40034018
},
40044019
{ "tail",
40054020
"name",
40064021
file_cmd_tail,
40074022
1,
40084023
1,
4009
-
4024
+
40104025
},
40114026
{ "normalize",
40124027
"name",
40134028
file_cmd_normalize,
40144029
1,
40154030
1,
4016
-
4031
+
40174032
},
40184033
{ "join",
40194034
"name ?name ...?",
40204035
file_cmd_join,
40214036
1,
40224037
-1,
4023
-
4038
+
40244039
},
40254040
{ "readable",
40264041
"name",
40274042
file_cmd_readable,
40284043
1,
40294044
1,
4030
-
4045
+
40314046
},
40324047
{ "writable",
40334048
"name",
40344049
file_cmd_writable,
40354050
1,
40364051
1,
4037
-
4052
+
40384053
},
40394054
{ "executable",
40404055
"name",
40414056
file_cmd_executable,
40424057
1,
40434058
1,
4044
-
4059
+
40454060
},
40464061
{ "exists",
40474062
"name",
40484063
file_cmd_exists,
40494064
1,
40504065
1,
4051
-
4066
+
40524067
},
40534068
{ "delete",
40544069
"?-force|--? name ...",
40554070
file_cmd_delete,
40564071
1,
40574072
-1,
4058
-
4073
+
40594074
},
40604075
{ "mkdir",
40614076
"dir ...",
40624077
file_cmd_mkdir,
40634078
1,
40644079
-1,
4065
-
4080
+
40664081
},
40674082
{ "tempfile",
40684083
"?template?",
40694084
file_cmd_tempfile,
40704085
0,
40714086
1,
4072
-
4087
+
40734088
},
40744089
{ "rename",
40754090
"?-force? source dest",
40764091
file_cmd_rename,
40774092
2,
40784093
3,
4079
-
4094
+
40804095
},
40814096
#if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
40824097
{ "link",
40834098
"?-symbolic|-hard? newname target",
40844099
file_cmd_link,
40854100
2,
40864101
3,
4087
-
4102
+
40884103
},
40894104
#endif
40904105
#if defined(HAVE_READLINK)
40914106
{ "readlink",
40924107
"name",
40934108
file_cmd_readlink,
40944109
1,
40954110
1,
4096
-
4111
+
40974112
},
40984113
#endif
40994114
{ "size",
41004115
"name",
41014116
file_cmd_size,
41024117
1,
41034118
1,
4104
-
4119
+
41054120
},
41064121
{ "stat",
41074122
"name ?var?",
41084123
file_cmd_stat,
41094124
1,
41104125
2,
4111
-
4126
+
41124127
},
41134128
{ "lstat",
41144129
"name ?var?",
41154130
file_cmd_lstat,
41164131
1,
41174132
2,
4118
-
4133
+
41194134
},
41204135
{ "type",
41214136
"name",
41224137
file_cmd_type,
41234138
1,
41244139
1,
4125
-
4140
+
41264141
},
41274142
#ifdef HAVE_GETEUID
41284143
{ "owned",
41294144
"name",
41304145
file_cmd_owned,
41314146
1,
41324147
1,
4133
-
4148
+
41344149
},
41354150
#endif
41364151
{ "isdirectory",
41374152
"name",
41384153
file_cmd_isdirectory,
41394154
1,
41404155
1,
4141
-
4156
+
41424157
},
41434158
{ "isfile",
41444159
"name",
41454160
file_cmd_isfile,
41464161
1,
41474162
1,
4148
-
4163
+
41494164
},
41504165
{
41514166
NULL
41524167
}
41534168
};
@@ -4179,11 +4194,11 @@
41794194
Jim_SetResultString(interp, "Failed to get pwd", -1);
41804195
Jim_Free(cwd);
41814196
return JIM_ERR;
41824197
}
41834198
else if (ISWINDOWS) {
4184
-
4199
+
41854200
char *p = cwd;
41864201
while ((p = strchr(p, '\\')) != NULL) {
41874202
*p++ = '/';
41884203
}
41894204
}
@@ -4203,10 +4218,13 @@
42034218
Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
42044219
Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
42054220
return JIM_OK;
42064221
}
42074222
4223
+#ifndef _GNU_SOURCE
4224
+#define _GNU_SOURCE
4225
+#endif
42084226
#include <string.h>
42094227
#include <ctype.h>
42104228
42114229
42124230
#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4232,20 @@
42144232
{
42154233
Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
42164234
int i, j;
42174235
int rc;
42184236
4219
-
4237
+
42204238
for (i = 1; i < argc; i++) {
42214239
int len;
42224240
const char *arg = Jim_GetString(argv[i], &len);
42234241
42244242
if (i > 1) {
42254243
Jim_AppendString(interp, cmdlineObj, " ", 1);
42264244
}
42274245
if (strpbrk(arg, "\\\" ") == NULL) {
4228
-
4246
+
42294247
Jim_AppendString(interp, cmdlineObj, arg, len);
42304248
continue;
42314249
}
42324250
42334251
Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4268,11 +4286,11 @@
42684286
42694287
#include <errno.h>
42704288
#include <signal.h>
42714289
42724290
#if defined(__MINGW32__)
4273
-
4291
+
42744292
#ifndef STRICT
42754293
#define STRICT
42764294
#endif
42774295
#define WIN32_LEAN_AND_MEAN
42784296
#include <windows.h>
@@ -4294,11 +4312,11 @@
42944312
static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
42954313
static fdtype JimDupFd(fdtype infd);
42964314
static fdtype JimOpenForRead(const char *filename);
42974315
static FILE *JimFdOpenForRead(fdtype fd);
42984316
static int JimPipe(fdtype pipefd[2]);
4299
- static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
4317
+ static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env,
43004318
fdtype inputId, fdtype outputId, fdtype errorId);
43014319
static int JimErrno(void);
43024320
#else
43034321
#include <unistd.h>
43044322
#include <fcntl.h>
@@ -4323,10 +4341,11 @@
43234341
#define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
43244342
#endif
43254343
#endif
43264344
43274345
static const char *JimStrError(void);
4346
+static char **JimOriginalEnviron(void);
43284347
static char **JimSaveEnv(char **env);
43294348
static void JimRestoreEnv(char **env);
43304349
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
43314350
pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
43324351
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
@@ -4390,18 +4409,18 @@
43904409
char *envdata;
43914410
43924411
Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
43934412
43944413
if (!objPtr) {
4395
- return Jim_GetEnviron();
4414
+ return JimOriginalEnviron();
43964415
}
43974416
43984417
4399
-
4418
+
44004419
num = Jim_ListLength(interp, objPtr);
44014420
if (num % 2) {
4402
-
4421
+
44034422
num--;
44044423
}
44054424
size = Jim_Length(objPtr) + 2;
44064425
44074426
envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4493,19 +4512,19 @@
44934512
}
44944513
44954514
44964515
struct WaitInfo
44974516
{
4498
- pidtype pid;
4499
- int status;
4500
- int flags;
4517
+ pidtype pid;
4518
+ int status;
4519
+ int flags;
45014520
};
45024521
45034522
struct WaitInfoTable {
4504
- struct WaitInfo *info;
4505
- int size;
4506
- int used;
4523
+ struct WaitInfo *info;
4524
+ int size;
4525
+ int used;
45074526
};
45084527
45094528
45104529
#define WI_DETACHED 2
45114530
@@ -4528,12 +4547,12 @@
45284547
return table;
45294548
}
45304549
45314550
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
45324551
{
4533
- fdtype outputId;
4534
- fdtype errorId;
4552
+ fdtype outputId;
4553
+ fdtype errorId;
45354554
pidtype *pidPtr;
45364555
int numPids, result;
45374556
int child_siginfo = 1;
45384557
Jim_Obj *childErrObj;
45394558
Jim_Obj *errStrObj;
@@ -4545,11 +4564,11 @@
45454564
argc--;
45464565
numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
45474566
if (numPids < 0) {
45484567
return JIM_ERR;
45494568
}
4550
-
4569
+
45514570
listObj = Jim_NewListObj(interp, NULL, 0);
45524571
for (i = 0; i < numPids; i++) {
45534572
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
45544573
}
45554574
Jim_SetResult(interp, listObj);
@@ -4567,19 +4586,19 @@
45674586
45684587
result = JIM_OK;
45694588
45704589
errStrObj = Jim_NewStringObj(interp, "", 0);
45714590
4572
-
4591
+
45734592
if (outputId != JIM_BAD_FD) {
45744593
if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
45754594
result = JIM_ERR;
45764595
Jim_SetResultErrno(interp, "error reading from output pipe");
45774596
}
45784597
}
45794598
4580
-
4599
+
45814600
childErrObj = Jim_NewStringObj(interp, "", 0);
45824601
Jim_IncrRefCount(childErrObj);
45834602
45844603
if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
45854604
result = JIM_ERR;
@@ -4592,25 +4611,25 @@
45924611
if (ret < 0) {
45934612
Jim_SetResultErrno(interp, "error reading from error pipe");
45944613
result = JIM_ERR;
45954614
}
45964615
else if (ret > 0) {
4597
-
4616
+
45984617
child_siginfo = 0;
45994618
}
46004619
}
46014620
46024621
if (child_siginfo) {
4603
-
4622
+
46044623
Jim_AppendObj(interp, errStrObj, childErrObj);
46054624
}
46064625
Jim_DecrRefCount(interp, childErrObj);
46074626
4608
-
4627
+
46094628
Jim_RemoveTrailingNewline(errStrObj);
46104629
4611
-
4630
+
46124631
Jim_SetResult(interp, errStrObj);
46134632
46144633
return result;
46154634
}
46164635
@@ -4629,11 +4648,11 @@
46294648
for (count = table->used; count > 0; waitPtr++, count--) {
46304649
if (waitPtr->flags & WI_DETACHED) {
46314650
int status;
46324651
pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
46334652
if (pid == waitPtr->pid) {
4634
-
4653
+
46354654
table->used--;
46364655
continue;
46374656
}
46384657
}
46394658
if (waitPtr != &table->info[dest]) {
@@ -4645,36 +4664,36 @@
46454664
46464665
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
46474666
{
46484667
int i;
46494668
4650
-
4669
+
46514670
for (i = 0; i < table->used; i++) {
46524671
if (pid == table->info[i].pid) {
4653
-
4672
+
46544673
JimWaitPid(pid, statusPtr, 0);
46554674
4656
-
4675
+
46574676
if (i != table->used - 1) {
46584677
table->info[i] = table->info[table->used - 1];
46594678
}
46604679
table->used--;
46614680
return pid;
46624681
}
46634682
}
46644683
4665
-
4684
+
46664685
return JIM_BAD_PID;
46674686
}
46684687
46694688
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
46704689
{
46714690
int j;
46724691
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
46734692
46744693
for (j = 0; j < numPids; j++) {
4675
-
4694
+
46764695
int i;
46774696
for (i = 0; i < table->used; i++) {
46784697
if (pidPtr[j] == table->info[i].pid) {
46794698
table->info[i].flags |= WI_DETACHED;
46804699
break;
@@ -4707,16 +4726,16 @@
47074726
int cmdCount; /* Count of number of distinct commands
47084727
* found in argc/argv. */
47094728
const char *input = NULL; /* Describes input for pipeline, depending
47104729
* on "inputFile". NULL means take input
47114730
* from stdin/pipe. */
4712
- int input_len = 0;
4731
+ int input_len = 0;
47134732
4714
-#define FILE_NAME 0
4715
-#define FILE_APPEND 1
4716
-#define FILE_HANDLE 2
4717
-#define FILE_TEXT 3
4733
+#define FILE_NAME 0
4734
+#define FILE_APPEND 1
4735
+#define FILE_HANDLE 2
4736
+#define FILE_TEXT 3
47184737
47194738
int inputFile = FILE_NAME; /* 1 means input is name of input file.
47204739
* 2 means input is filehandle name.
47214740
* 0 means input holds actual
47224741
* text to be input to command. */
@@ -4737,20 +4756,20 @@
47374756
* or NULL if stderr goes to stderr/pipe. */
47384757
fdtype inputId = JIM_BAD_FD;
47394758
fdtype outputId = JIM_BAD_FD;
47404759
fdtype errorId = JIM_BAD_FD;
47414760
fdtype lastOutputId = JIM_BAD_FD;
4742
- fdtype pipeIds[2];
4761
+ fdtype pipeIds[2];
47434762
int firstArg, lastArg; /* Indexes of first and last arguments in
47444763
* current command. */
47454764
int lastBar;
47464765
int i;
47474766
pidtype pid;
47484767
char **save_environ;
47494768
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
47504769
4751
-
4770
+
47524771
char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
47534772
int arg_count = 0;
47544773
47554774
JimReapDetachedPids(table);
47564775
@@ -4796,11 +4815,11 @@
47964815
if (*output == '>') {
47974816
outputFile = FILE_APPEND;
47984817
output++;
47994818
}
48004819
if (*output == '&') {
4801
-
4820
+
48024821
output++;
48034822
dup_error = 1;
48044823
}
48054824
if (*output == '@') {
48064825
outputFile = FILE_HANDLE;
@@ -4837,11 +4856,11 @@
48374856
goto badargs;
48384857
}
48394858
lastBar = i;
48404859
cmdCount++;
48414860
}
4842
-
4861
+
48434862
arg_array[arg_count++] = (char *)arg;
48444863
continue;
48454864
}
48464865
48474866
if (i >= argc) {
@@ -4855,11 +4874,11 @@
48554874
badargs:
48564875
Jim_Free(arg_array);
48574876
return -1;
48584877
}
48594878
4860
-
4879
+
48614880
save_environ = JimSaveEnv(JimBuildEnv(interp));
48624881
48634882
if (input != NULL) {
48644883
if (inputFile == FILE_TEXT) {
48654884
inputId = JimCreateTemp(interp, input, input_len);
@@ -4866,11 +4885,11 @@
48664885
if (inputId == JIM_BAD_FD) {
48674886
goto error;
48684887
}
48694888
}
48704889
else if (inputFile == FILE_HANDLE) {
4871
-
4890
+
48724891
FILE *fh = JimGetAioFilehandle(interp, input);
48734892
48744893
if (fh == NULL) {
48754894
goto error;
48764895
}
@@ -4918,20 +4937,20 @@
49184937
}
49194938
lastOutputId = pipeIds[1];
49204939
*outPipePtr = pipeIds[0];
49214940
pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
49224941
}
4923
-
4942
+
49244943
if (error != NULL) {
49254944
if (errorFile == FILE_HANDLE) {
49264945
if (strcmp(error, "1") == 0) {
4927
-
4946
+
49284947
if (lastOutputId != JIM_BAD_FD) {
49294948
errorId = JimDupFd(lastOutputId);
49304949
}
49314950
else {
4932
-
4951
+
49334952
error = "stdout";
49344953
}
49354954
}
49364955
if (errorId == JIM_BAD_FD) {
49374956
FILE *fh = JimGetAioFilehandle(interp, error);
@@ -4973,11 +4992,11 @@
49734992
pipe_dup_err = 1;
49744993
}
49754994
break;
49764995
}
49774996
}
4978
-
4997
+
49794998
arg_array[lastArg] = NULL;
49804999
if (lastArg == arg_count) {
49815000
outputId = lastOutputId;
49825001
}
49835002
else {
@@ -4986,19 +5005,19 @@
49865005
goto error;
49875006
}
49885007
outputId = pipeIds[1];
49895008
}
49905009
4991
-
5010
+
49925011
if (pipe_dup_err) {
49935012
errorId = outputId;
49945013
}
49955014
4996
-
5015
+
49975016
49985017
#ifdef __MINGW32__
4999
- pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
5018
+ pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
50005019
if (pid == JIM_BAD_PID) {
50015020
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
50025021
goto error;
50035022
}
50045023
#else
@@ -5006,32 +5025,39 @@
50065025
if (pid < 0) {
50075026
Jim_SetResultErrno(interp, "couldn't fork child process");
50085027
goto error;
50095028
}
50105029
if (pid == 0) {
5011
-
5030
+
50125031
50135032
if (inputId != -1) dup2(inputId, 0);
50145033
if (outputId != -1) dup2(outputId, 1);
50155034
if (errorId != -1) dup2(errorId, 2);
50165035
50175036
for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
50185037
close(i);
50195038
}
50205039
5021
-
5040
+
50225041
(void)signal(SIGPIPE, SIG_DFL);
50235042
50245043
execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
50255044
5026
-
5045
+
50275046
fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
5047
+#ifdef JIM_MAINTAINER
5048
+ {
5049
+
5050
+ static char *const false_argv[2] = {"false", NULL};
5051
+ execvp(false_argv[0],false_argv);
5052
+ }
5053
+#endif
50285054
_exit(127);
50295055
}
50305056
#endif
50315057
5032
-
5058
+
50335059
50345060
if (table->used == table->size) {
50355061
table->size += WAIT_TABLE_GROW_BY;
50365062
table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
50375063
}
@@ -5040,19 +5066,20 @@
50405066
table->info[table->used].flags = 0;
50415067
table->used++;
50425068
50435069
pidPtr[numPids] = pid;
50445070
5045
-
5071
+
50465072
errorId = origErrorId;
50475073
50485074
50495075
if (inputId != JIM_BAD_FD) {
50505076
JimCloseFd(inputId);
50515077
}
50525078
if (outputId != JIM_BAD_FD) {
50535079
JimCloseFd(outputId);
5080
+ outputId = JIM_BAD_FD;
50545081
}
50555082
inputId = pipeIds[0];
50565083
pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
50575084
}
50585085
*pidArrayPtr = pidPtr;
@@ -5111,11 +5138,11 @@
51115138
{
51125139
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
51135140
int result = JIM_OK;
51145141
int i;
51155142
5116
-
5143
+
51175144
for (i = 0; i < numPids; i++) {
51185145
int waitStatus = 0;
51195146
if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
51205147
if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
51215148
result = JIM_ERR;
@@ -5284,17 +5311,21 @@
52845311
}
52855312
52865313
static fdtype JimOpenForRead(const char *filename)
52875314
{
52885315
return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
5289
- JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
5316
+ JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
52905317
}
52915318
52925319
static fdtype JimOpenForWrite(const char *filename, int append)
52935320
{
5294
- return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5295
- JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
5321
+ fdtype fd = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5322
+ JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
5323
+ if (append && fd != JIM_BAD_FD) {
5324
+ SetFilePointer(fd, 0, NULL, FILE_END);
5325
+ }
5326
+ return fd;
52965327
}
52975328
52985329
static FILE *JimFdOpenForWrite(fdtype fd)
52995330
{
53005331
return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
@@ -5302,11 +5333,11 @@
53025333
53035334
static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
53045335
{
53055336
DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
53065337
if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
5307
-
5338
+
53085339
return JIM_BAD_PID;
53095340
}
53105341
GetExitCodeProcess(pid, &ret);
53115342
*status = ret;
53125343
CloseHandle(pid);
@@ -5329,11 +5360,11 @@
53295360
if (handle == INVALID_HANDLE_VALUE) {
53305361
goto error;
53315362
}
53325363
53335364
if (contents != NULL) {
5334
-
5365
+
53355366
FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
53365367
if (fh == NULL) {
53375368
goto error;
53385369
}
53395370
@@ -5381,10 +5412,15 @@
53815412
53825413
static void JimRestoreEnv(char **env)
53835414
{
53845415
JimFreeEnv(env, Jim_GetEnviron());
53855416
}
5417
+
5418
+static char **JimOriginalEnviron(void)
5419
+{
5420
+ return NULL;
5421
+}
53865422
53875423
static Jim_Obj *
53885424
JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
53895425
{
53905426
char *start, *special;
@@ -5455,18 +5491,19 @@
54555491
}
54565492
return strObj;
54575493
}
54585494
54595495
static pidtype
5460
-JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
5496
+JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, fdtype inputId, fdtype outputId, fdtype errorId)
54615497
{
54625498
STARTUPINFO startInfo;
54635499
PROCESS_INFORMATION procInfo;
54645500
HANDLE hProcess, h;
54655501
char execPath[MAX_PATH];
54665502
pidtype pid = JIM_BAD_PID;
54675503
Jim_Obj *cmdLineObj;
5504
+ char *winenv;
54685505
54695506
if (JimWinFindExecutable(argv[0], execPath) < 0) {
54705507
return JIM_BAD_PID;
54715508
}
54725509
argv[0] = execPath;
@@ -5514,13 +5551,24 @@
55145551
0, TRUE, DUPLICATE_SAME_ACCESS);
55155552
}
55165553
if (startInfo.hStdError == JIM_BAD_FD) {
55175554
goto end;
55185555
}
5556
+
5557
+ if (env == NULL) {
5558
+
5559
+ winenv = NULL;
5560
+ }
5561
+ else if (env[0] == NULL) {
5562
+ winenv = (char *)"\0";
5563
+ }
5564
+ else {
5565
+ winenv = env[0];
5566
+ }
55195567
55205568
if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5521
- 0, env, NULL, &startInfo, &procInfo)) {
5569
+ 0, winenv, NULL, &startInfo, &procInfo)) {
55225570
goto end;
55235571
}
55245572
55255573
55265574
WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5568,10 +5616,15 @@
55685616
lseek(fd, 0L, SEEK_SET);
55695617
}
55705618
}
55715619
return fd;
55725620
}
5621
+
5622
+static char **JimOriginalEnviron(void)
5623
+{
5624
+ return Jim_GetEnviron();
5625
+}
55735626
55745627
static char **JimSaveEnv(char **env)
55755628
{
55765629
char **saveenv = Jim_GetEnviron();
55775630
Jim_SetEnviron(env);
@@ -5601,11 +5654,11 @@
56015654
#include <sys/time.h>
56025655
#endif
56035656
56045657
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
56055658
{
5606
-
5659
+
56075660
char buf[100];
56085661
time_t t;
56095662
long seconds;
56105663
56115664
const char *format = "%a %b %d %H:%M:%S %Z %Y";
@@ -5642,20 +5695,20 @@
56425695
56435696
if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
56445697
return -1;
56455698
}
56465699
5647
-
5700
+
56485701
localtime_r(&now, &tm);
56495702
56505703
pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
56515704
if (pt == 0 || *pt != 0) {
56525705
Jim_SetResultString(interp, "Failed to parse time according to format", -1);
56535706
return JIM_ERR;
56545707
}
56555708
5656
-
5709
+
56575710
Jim_SetResultInt(interp, mktime(&tm));
56585711
56595712
return JIM_OK;
56605713
}
56615714
#endif
@@ -5693,47 +5746,47 @@
56935746
{ "seconds",
56945747
NULL,
56955748
clock_cmd_seconds,
56965749
0,
56975750
0,
5698
-
5751
+
56995752
},
57005753
{ "clicks",
57015754
NULL,
57025755
clock_cmd_micros,
57035756
0,
57045757
0,
5705
-
5758
+
57065759
},
57075760
{ "microseconds",
57085761
NULL,
57095762
clock_cmd_micros,
57105763
0,
57115764
0,
5712
-
5765
+
57135766
},
57145767
{ "milliseconds",
57155768
NULL,
57165769
clock_cmd_millis,
57175770
0,
57185771
0,
5719
-
5772
+
57205773
},
57215774
{ "format",
57225775
"seconds ?-format format?",
57235776
clock_cmd_format,
57245777
1,
57255778
3,
5726
-
5779
+
57275780
},
57285781
#ifdef HAVE_STRPTIME
57295782
{ "scan",
57305783
"str -format format",
57315784
clock_cmd_scan,
57325785
3,
57335786
3,
5734
-
5787
+
57355788
},
57365789
#endif
57375790
{ NULL }
57385791
};
57395792
@@ -5753,12 +5806,13 @@
57535806
#include <errno.h>
57545807
57555808
57565809
static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57575810
{
5758
-
5759
- Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
5811
+
5812
+ Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5813
+ Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
57605814
return JIM_OK;
57615815
}
57625816
57635817
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57645818
{
@@ -5769,21 +5823,20 @@
57695823
return JIM_OK;
57705824
}
57715825
57725826
patternObj = (argc == 1) ? NULL : argv[1];
57735827
5774
-
5828
+
57755829
if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
57765830
if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5777
-
5831
+
57785832
Jim_SetResult(interp, objPtr);
57795833
return JIM_OK;
57805834
}
57815835
}
57825836
5783
-
5784
- return Jim_DictValues(interp, objPtr, patternObj);
5837
+ return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES);
57855838
}
57865839
57875840
static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57885841
{
57895842
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5843,11 @@
57905843
57915844
if (!objPtr) {
57925845
return JIM_OK;
57935846
}
57945847
5795
- return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
5848
+ return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS);
57965849
}
57975850
57985851
static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
57995852
{
58005853
int i;
@@ -5802,27 +5855,29 @@
58025855
Jim_Obj *resultObj;
58035856
Jim_Obj *objPtr;
58045857
Jim_Obj **dictValuesObj;
58055858
58065859
if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5807
-
5860
+
58085861
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
58095862
return JIM_OK;
58105863
}
58115864
58125865
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
58135866
58145867
if (objPtr == NULL) {
5815
-
5868
+
58165869
return JIM_OK;
58175870
}
58185871
58195872
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5820
- return JIM_ERR;
5873
+
5874
+ Jim_SetResultString(interp, "", -1);
5875
+ return JIM_OK;
58215876
}
58225877
5823
-
5878
+
58245879
resultObj = Jim_NewDictObj(interp, NULL, 0);
58255880
58265881
for (i = 0; i < len; i += 2) {
58275882
if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
58285883
Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5892,18 @@
58375892
static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
58385893
{
58395894
Jim_Obj *objPtr;
58405895
int len = 0;
58415896
5842
-
5897
+
58435898
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
58445899
if (objPtr) {
58455900
len = Jim_DictSize(interp, objPtr);
58465901
if (len < 0) {
5847
- return JIM_ERR;
5902
+
5903
+ Jim_SetResultInt(interp, 0);
5904
+ return JIM_OK;
58485905
}
58495906
}
58505907
58515908
Jim_SetResultInt(interp, len);
58525909
@@ -5876,11 +5933,11 @@
58765933
return JIM_ERR;
58775934
}
58785935
58795936
dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
58805937
if (!dictObj) {
5881
-
5938
+
58825939
return Jim_SetVariable(interp, argv[0], listObj);
58835940
}
58845941
else if (Jim_DictSize(interp, dictObj) < 0) {
58855942
return JIM_ERR;
58865943
}
@@ -5905,53 +5962,53 @@
59055962
{ "exists",
59065963
"arrayName",
59075964
array_cmd_exists,
59085965
1,
59095966
1,
5910
-
5967
+
59115968
},
59125969
{ "get",
59135970
"arrayName ?pattern?",
59145971
array_cmd_get,
59155972
1,
59165973
2,
5917
-
5974
+
59185975
},
59195976
{ "names",
59205977
"arrayName ?pattern?",
59215978
array_cmd_names,
59225979
1,
59235980
2,
5924
-
5981
+
59255982
},
59265983
{ "set",
59275984
"arrayName list",
59285985
array_cmd_set,
59295986
2,
59305987
2,
5931
-
5988
+
59325989
},
59335990
{ "size",
59345991
"arrayName",
59355992
array_cmd_size,
59365993
1,
59375994
1,
5938
-
5995
+
59395996
},
59405997
{ "stat",
59415998
"arrayName",
59425999
array_cmd_stat,
59436000
1,
59446001
1,
5945
-
6002
+
59466003
},
59476004
{ "unset",
59486005
"arrayName ?pattern?",
59496006
array_cmd_unset,
59506007
1,
59516008
2,
5952
-
6009
+
59536010
},
59546011
{ NULL
59556012
}
59566013
};
59576014
@@ -5987,11 +6044,14 @@
59876044
Jim_arrayInit(interp);
59886045
Jim_stdlibInit(interp);
59896046
Jim_tclcompatInit(interp);
59906047
return JIM_OK;
59916048
}
5992
-#define JIM_OPTIMIZATION
6049
+#define JIM_OPTIMIZATION
6050
+#ifndef _GNU_SOURCE
6051
+#define _GNU_SOURCE
6052
+#endif
59936053
59946054
#include <stdio.h>
59956055
#include <stdlib.h>
59966056
59976057
#include <string.h>
@@ -6056,10 +6116,16 @@
60566116
#define JimPanic(X) JimPanicDump X
60576117
#else
60586118
#define JimPanic(X)
60596119
#endif
60606120
6121
+#ifdef JIM_OPTIMIZATION
6122
+#define JIM_IF_OPTIM(X) X
6123
+#else
6124
+#define JIM_IF_OPTIM(X)
6125
+#endif
6126
+
60616127
60626128
static char JimEmptyStringRep[] = "";
60636129
60646130
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
60656131
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6178,34 @@
61126178
if (*pattern == '^') {
61136179
not++;
61146180
pattern++;
61156181
}
61166182
6117
-
6183
+
61186184
if (*pattern == ']') {
61196185
goto first;
61206186
}
61216187
}
61226188
61236189
while (*pattern && *pattern != ']') {
6124
-
6190
+
61256191
if (pattern[0] == '\\') {
61266192
first:
61276193
pattern += utf8_tounicode_case(pattern, &pchar, nocase);
61286194
}
61296195
else {
6130
-
6196
+
61316197
int start;
61326198
int end;
61336199
61346200
pattern += utf8_tounicode_case(pattern, &start, nocase);
61356201
if (pattern[0] == '-' && pattern[1]) {
6136
-
6202
+
61376203
pattern += utf8_tounicode(pattern, &pchar);
61386204
pattern += utf8_tounicode_case(pattern, &end, nocase);
61396205
6140
-
6206
+
61416207
if ((c >= start && c <= end) || (c >= end && c <= start)) {
61426208
match = 1;
61436209
}
61446210
continue;
61456211
}
@@ -6169,19 +6235,19 @@
61696235
while (pattern[1] == '*') {
61706236
pattern++;
61716237
}
61726238
pattern++;
61736239
if (!pattern[0]) {
6174
- return 1;
6240
+ return 1;
61756241
}
61766242
while (*string) {
6177
-
6243
+
61786244
if (JimGlobMatch(pattern, string, nocase))
6179
- return 1;
6245
+ return 1;
61806246
string += utf8_tounicode(string, &c);
61816247
}
6182
- return 0;
6248
+ return 0;
61836249
61846250
case '?':
61856251
string += utf8_tounicode(string, &c);
61866252
break;
61876253
@@ -6190,20 +6256,20 @@
61906256
pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
61916257
if (!pattern) {
61926258
return 0;
61936259
}
61946260
if (!*pattern) {
6195
-
6261
+
61966262
continue;
61976263
}
61986264
break;
61996265
}
62006266
case '\\':
62016267
if (pattern[1]) {
62026268
pattern++;
62036269
}
6204
-
6270
+
62056271
default:
62066272
string += utf8_tounicode_case(string, &c, nocase);
62076273
utf8_tounicode_case(pattern, &pchar, nocase);
62086274
if (pchar != c) {
62096275
return 0;
@@ -6249,11 +6315,11 @@
62496315
maxchars--;
62506316
}
62516317
if (!maxchars) {
62526318
return 0;
62536319
}
6254
-
6320
+
62556321
if (*s1) {
62566322
return 1;
62576323
}
62586324
if (*s2) {
62596325
return -1;
@@ -6290,11 +6356,11 @@
62906356
const char *p;
62916357
62926358
if (!l1 || !l2 || l1 > l2)
62936359
return -1;
62946360
6295
-
6361
+
62966362
for (p = s2 + l2 - 1; p != s2 - 1; p--) {
62976363
if (*p == *s1 && memcmp(s1, p, l1) == 0) {
62986364
return p - s2;
62996365
}
63006366
}
@@ -6349,28 +6415,28 @@
63496415
}
63506416
*sign = 1;
63516417
}
63526418
63536419
if (str[i] != '0') {
6354
-
6420
+
63556421
return 0;
63566422
}
63576423
6358
-
6424
+
63596425
switch (str[i + 1]) {
63606426
case 'x': case 'X': *base = 16; break;
63616427
case 'o': case 'O': *base = 8; break;
63626428
case 'b': case 'B': *base = 2; break;
63636429
default: return 0;
63646430
}
63656431
i += 2;
6366
-
6432
+
63676433
if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6368
-
6434
+
63696435
return i;
63706436
}
6371
-
6437
+
63726438
*base = 10;
63736439
return 0;
63746440
}
63756441
63766442
static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6450,11 @@
63846450
if (endptr == NULL || *endptr != str + i) {
63856451
return value * sign;
63866452
}
63876453
}
63886454
6389
-
6455
+
63906456
return strtol(str, endptr, 10);
63916457
}
63926458
63936459
63946460
static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6469,11 @@
64036469
if (endptr == NULL || *endptr != str + i) {
64046470
return value * sign;
64056471
}
64066472
}
64076473
6408
-
6474
+
64096475
return strtoull(str, endptr, 10);
64106476
#else
64116477
return (unsigned long)jim_strtol(str, endptr);
64126478
#endif
64136479
}
@@ -6428,26 +6494,40 @@
64286494
64296495
int Jim_StringToDouble(const char *str, double *doublePtr)
64306496
{
64316497
char *endptr;
64326498
6433
-
6499
+
64346500
errno = 0;
64356501
64366502
*doublePtr = strtod(str, &endptr);
64376503
64386504
return JimCheckConversion(str, endptr);
64396505
}
64406506
64416507
static jim_wide JimPowWide(jim_wide b, jim_wide e)
64426508
{
6443
- jim_wide i, res = 1;
6509
+ jim_wide res = 1;
64446510
6445
- if ((b == 0 && e != 0) || (e < 0))
6446
- return 0;
6447
- for (i = 0; i < e; i++) {
6448
- res *= b;
6511
+
6512
+ if (b == 1) {
6513
+
6514
+ return 1;
6515
+ }
6516
+ if (e < 0) {
6517
+ if (b != -1) {
6518
+ return 0;
6519
+ }
6520
+ e = -e;
6521
+ }
6522
+ while (e)
6523
+ {
6524
+ if (e & 1) {
6525
+ res *= b;
6526
+ }
6527
+ e >>= 1;
6528
+ b *= b;
64496529
}
64506530
return res;
64516531
}
64526532
64536533
#ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6589,11 @@
65096589
char *Jim_StrDupLen(const char *s, int l)
65106590
{
65116591
char *copy = Jim_Alloc(l + 1);
65126592
65136593
memcpy(copy, s, l + 1);
6514
- copy[l] = 0;
6594
+ copy[l] = 0;
65156595
return copy;
65166596
}
65176597
65186598
65196599
@@ -6598,52 +6678,52 @@
65986678
}
65996679
66006680
66016681
void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
66026682
{
6603
- Jim_HashTable n;
6683
+ Jim_HashTable n;
66046684
unsigned int realsize = JimHashTableNextPower(size), i;
66056685
66066686
if (size <= ht->used)
66076687
return;
66086688
66096689
Jim_InitHashTable(&n, ht->type, ht->privdata);
66106690
n.size = realsize;
66116691
n.sizemask = realsize - 1;
66126692
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6613
-
6693
+
66146694
n.uniq = ht->uniq;
66156695
6616
-
6696
+
66176697
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
66186698
66196699
n.used = ht->used;
66206700
for (i = 0; ht->used > 0; i++) {
66216701
Jim_HashEntry *he, *nextHe;
66226702
66236703
if (ht->table[i] == NULL)
66246704
continue;
66256705
6626
-
6706
+
66276707
he = ht->table[i];
66286708
while (he) {
66296709
unsigned int h;
66306710
66316711
nextHe = he->next;
6632
-
6712
+
66336713
h = Jim_HashKey(ht, he->key) & n.sizemask;
66346714
he->next = n.table[h];
66356715
n.table[h] = he;
66366716
ht->used--;
6637
-
6717
+
66386718
he = nextHe;
66396719
}
66406720
}
66416721
assert(ht->used == 0);
66426722
Jim_Free(ht->table);
66436723
6644
-
6724
+
66456725
*ht = n;
66466726
}
66476727
66486728
66496729
int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6732,11 @@
66526732
66536733
entry = JimInsertHashEntry(ht, key, 0);
66546734
if (entry == NULL)
66556735
return JIM_ERR;
66566736
6657
-
6737
+
66586738
Jim_SetHashKey(ht, entry, key);
66596739
Jim_SetHashVal(ht, entry, val);
66606740
return JIM_OK;
66616741
}
66626742
@@ -6678,11 +6758,11 @@
66786758
Jim_SetHashVal(ht, entry, val);
66796759
}
66806760
existed = 1;
66816761
}
66826762
else {
6683
-
6763
+
66846764
Jim_SetHashKey(ht, entry, key);
66856765
Jim_SetHashVal(ht, entry, val);
66866766
existed = 0;
66876767
}
66886768
@@ -6701,11 +6781,11 @@
67016781
he = ht->table[h];
67026782
67036783
prevHe = NULL;
67046784
while (he) {
67056785
if (Jim_CompareHashKeys(ht, key, he->key)) {
6706
-
6786
+
67076787
if (prevHe)
67086788
prevHe->next = he->next;
67096789
else
67106790
ht->table[h] = he->next;
67116791
Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6795,19 @@
67156795
return JIM_OK;
67166796
}
67176797
prevHe = he;
67186798
he = he->next;
67196799
}
6720
- return JIM_ERR;
6800
+ return JIM_ERR;
67216801
}
67226802
67236803
67246804
int Jim_FreeHashTable(Jim_HashTable *ht)
67256805
{
67266806
unsigned int i;
67276807
6728
-
6808
+
67296809
for (i = 0; ht->used > 0; i++) {
67306810
Jim_HashEntry *he, *nextHe;
67316811
67326812
if ((he = ht->table[i]) == NULL)
67336813
continue;
@@ -6738,15 +6818,15 @@
67386818
Jim_Free(he);
67396819
ht->used--;
67406820
he = nextHe;
67416821
}
67426822
}
6743
-
6823
+
67446824
Jim_Free(ht->table);
6745
-
6825
+
67466826
JimResetHashTable(ht);
6747
- return JIM_OK;
6827
+ return JIM_OK;
67486828
}
67496829
67506830
Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
67516831
{
67526832
Jim_HashEntry *he;
@@ -6819,24 +6899,24 @@
68196899
static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
68206900
{
68216901
unsigned int h;
68226902
Jim_HashEntry *he;
68236903
6824
-
6904
+
68256905
JimExpandHashTableIfNeeded(ht);
68266906
6827
-
6907
+
68286908
h = Jim_HashKey(ht, key) & ht->sizemask;
6829
-
6909
+
68306910
he = ht->table[h];
68316911
while (he) {
68326912
if (Jim_CompareHashKeys(ht, key, he->key))
68336913
return replace ? he : NULL;
68346914
he = he->next;
68356915
}
68366916
6837
-
6917
+
68386918
he = Jim_Alloc(sizeof(*he));
68396919
he->next = ht->table[h];
68406920
ht->table[h] = he;
68416921
ht->used++;
68426922
he->key = NULL;
@@ -6865,16 +6945,16 @@
68656945
{
68666946
Jim_Free(key);
68676947
}
68686948
68696949
static const Jim_HashTableType JimPackageHashTableType = {
6870
- JimStringCopyHTHashFunction,
6871
- JimStringCopyHTDup,
6872
- NULL,
6873
- JimStringCopyHTKeyCompare,
6874
- JimStringCopyHTKeyDestructor,
6875
- NULL
6950
+ JimStringCopyHTHashFunction,
6951
+ JimStringCopyHTDup,
6952
+ NULL,
6953
+ JimStringCopyHTKeyCompare,
6954
+ JimStringCopyHTKeyDestructor,
6955
+ NULL
68766956
};
68776957
68786958
typedef struct AssocDataValue
68796959
{
68806960
Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6969,16 @@
68896969
assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
68906970
Jim_Free(data);
68916971
}
68926972
68936973
static const Jim_HashTableType JimAssocDataHashTableType = {
6894
- JimStringCopyHTHashFunction,
6895
- JimStringCopyHTDup,
6896
- NULL,
6897
- JimStringCopyHTKeyCompare,
6898
- JimStringCopyHTKeyDestructor,
6899
- JimAssocDataHashTableValueDestructor
6974
+ JimStringCopyHTHashFunction,
6975
+ JimStringCopyHTDup,
6976
+ NULL,
6977
+ JimStringCopyHTKeyCompare,
6978
+ JimStringCopyHTKeyDestructor,
6979
+ JimAssocDataHashTableValueDestructor
69006980
};
69016981
69026982
void Jim_InitStack(Jim_Stack *stack)
69036983
{
69046984
stack->len = 0;
@@ -6951,56 +7031,61 @@
69517031
freeFunc(stack->vector[i]);
69527032
}
69537033
69547034
69557035
6956
-#define JIM_TT_NONE 0
6957
-#define JIM_TT_STR 1
6958
-#define JIM_TT_ESC 2
6959
-#define JIM_TT_VAR 3
6960
-#define JIM_TT_DICTSUGAR 4
6961
-#define JIM_TT_CMD 5
6962
-
6963
-#define JIM_TT_SEP 6
6964
-#define JIM_TT_EOL 7
6965
-#define JIM_TT_EOF 8
6966
-
6967
-#define JIM_TT_LINE 9
6968
-#define JIM_TT_WORD 10
7036
+#define JIM_TT_NONE 0
7037
+#define JIM_TT_STR 1
7038
+#define JIM_TT_ESC 2
7039
+#define JIM_TT_VAR 3
7040
+#define JIM_TT_DICTSUGAR 4
7041
+#define JIM_TT_CMD 5
7042
+
7043
+#define JIM_TT_SEP 6
7044
+#define JIM_TT_EOL 7
7045
+#define JIM_TT_EOF 8
7046
+
7047
+#define JIM_TT_LINE 9
7048
+#define JIM_TT_WORD 10
69697049
69707050
69717051
#define JIM_TT_SUBEXPR_START 11
69727052
#define JIM_TT_SUBEXPR_END 12
69737053
#define JIM_TT_SUBEXPR_COMMA 13
69747054
#define JIM_TT_EXPR_INT 14
69757055
#define JIM_TT_EXPR_DOUBLE 15
7056
+#define JIM_TT_EXPR_BOOLEAN 16
69767057
6977
-#define JIM_TT_EXPRSUGAR 16
7058
+#define JIM_TT_EXPRSUGAR 17
69787059
69797060
69807061
#define JIM_TT_EXPR_OP 20
69817062
69827063
#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
69837064
7065
+#define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA)
7066
+
7067
+#define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP)
7068
+
69847069
struct JimParseMissing {
6985
- int ch;
6986
- int line;
7070
+ int ch;
7071
+ int line;
69877072
};
69887073
69897074
struct JimParserCtx
69907075
{
6991
- const char *p;
6992
- int len;
6993
- int linenr;
7076
+ const char *p;
7077
+ int len;
7078
+ int linenr;
69947079
const char *tstart;
6995
- const char *tend;
6996
- int tline;
6997
- int tt;
6998
- int eof;
6999
- int inquote;
7000
- int comment;
7001
- struct JimParseMissing missing;
7080
+ const char *tend;
7081
+ int tline;
7082
+ int tt;
7083
+ int eof;
7084
+ int inquote;
7085
+ int comment;
7086
+ struct JimParseMissing missing;
70027087
};
70037088
70047089
static int JimParseScript(struct JimParserCtx *pc);
70057090
static int JimParseSep(struct JimParserCtx *pc);
70067091
static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7115,11 @@
70307115
pc->missing.line = linenr;
70317116
}
70327117
70337118
static int JimParseScript(struct JimParserCtx *pc)
70347119
{
7035
- while (1) {
7120
+ while (1) {
70367121
if (!pc->len) {
70377122
pc->tstart = pc->p;
70387123
pc->tend = pc->p - 1;
70397124
pc->tline = pc->linenr;
70407125
pc->tt = JIM_TT_EOL;
@@ -7066,11 +7151,11 @@
70667151
pc->comment = 0;
70677152
return JimParseCmd(pc);
70687153
case '$':
70697154
pc->comment = 0;
70707155
if (JimParseVar(pc) == JIM_ERR) {
7071
-
7156
+
70727157
pc->tstart = pc->tend = pc->p++;
70737158
pc->len--;
70747159
pc->tt = JIM_TT_ESC;
70757160
}
70767161
return JIM_OK;
@@ -7127,11 +7212,11 @@
71277212
71287213
static void JimParseSubBrace(struct JimParserCtx *pc)
71297214
{
71307215
int level = 1;
71317216
7132
-
7217
+
71337218
pc->p++;
71347219
pc->len--;
71357220
while (pc->len) {
71367221
switch (*pc->p) {
71377222
case '\\':
@@ -7171,11 +7256,11 @@
71717256
static int JimParseSubQuote(struct JimParserCtx *pc)
71727257
{
71737258
int tt = JIM_TT_STR;
71747259
int line = pc->tline;
71757260
7176
-
7261
+
71777262
pc->p++;
71787263
pc->len--;
71797264
while (pc->len) {
71807265
switch (*pc->p) {
71817266
case '\\':
@@ -7220,11 +7305,11 @@
72207305
{
72217306
int level = 1;
72227307
int startofword = 1;
72237308
int line = pc->tline;
72247309
7225
-
7310
+
72267311
pc->p++;
72277312
pc->len--;
72287313
while (pc->len) {
72297314
switch (*pc->p) {
72307315
case '\\':
@@ -7300,17 +7385,17 @@
73007385
return JIM_OK;
73017386
}
73027387
73037388
static int JimParseVar(struct JimParserCtx *pc)
73047389
{
7305
-
7390
+
73067391
pc->p++;
73077392
pc->len--;
73087393
73097394
#ifdef EXPRSUGAR_BRACKET
73107395
if (*pc->p == '[') {
7311
-
7396
+
73127397
JimParseCmd(pc);
73137398
pc->tt = JIM_TT_EXPRSUGAR;
73147399
return JIM_OK;
73157400
}
73167401
#endif
@@ -7336,11 +7421,11 @@
73367421
pc->len--;
73377422
}
73387423
}
73397424
else {
73407425
while (1) {
7341
-
7426
+
73427427
if (pc->p[0] == ':' && pc->p[1] == ':') {
73437428
while (*pc->p == ':') {
73447429
pc->p++;
73457430
pc->len--;
73467431
}
@@ -7351,11 +7436,11 @@
73517436
pc->len--;
73527437
continue;
73537438
}
73547439
break;
73557440
}
7356
-
7441
+
73577442
if (*pc->p == '(') {
73587443
int count = 1;
73597444
const char *paren = NULL;
73607445
73617446
pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7463,11 @@
73787463
if (count == 0) {
73797464
pc->p++;
73807465
pc->len--;
73817466
}
73827467
else if (paren) {
7383
-
7468
+
73847469
paren++;
73857470
pc->len += (pc->p - paren);
73867471
pc->p = paren;
73877472
}
73887473
#ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7488,19 @@
74037488
74047489
static int JimParseStr(struct JimParserCtx *pc)
74057490
{
74067491
if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
74077492
pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7408
-
7493
+
74097494
if (*pc->p == '{') {
74107495
return JimParseBrace(pc);
74117496
}
74127497
if (*pc->p == '"') {
74137498
pc->inquote = 1;
74147499
pc->p++;
74157500
pc->len--;
7416
-
7501
+
74177502
pc->missing.line = pc->tline;
74187503
}
74197504
}
74207505
pc->tstart = pc->p;
74217506
pc->tline = pc->linenr;
@@ -7441,25 +7526,25 @@
74417526
}
74427527
pc->p++;
74437528
pc->len--;
74447529
}
74457530
else if (pc->len == 1) {
7446
-
7531
+
74477532
pc->missing.ch = '\\';
74487533
}
74497534
break;
74507535
case '(':
7451
-
7536
+
74527537
if (pc->len > 1 && pc->p[1] != '$') {
74537538
break;
74547539
}
7455
-
7540
+
74567541
case ')':
7457
-
7542
+
74587543
if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
74597544
if (pc->p == pc->tstart) {
7460
-
7545
+
74617546
pc->p++;
74627547
pc->len--;
74637548
}
74647549
pc->tend = pc->p - 1;
74657550
pc->tt = JIM_TT_ESC;
@@ -7499,11 +7584,11 @@
74997584
break;
75007585
}
75017586
pc->p++;
75027587
pc->len--;
75037588
}
7504
- return JIM_OK;
7589
+ return JIM_OK;
75057590
}
75067591
75077592
static int JimParseComment(struct JimParserCtx *pc)
75087593
{
75097594
while (*pc->p) {
@@ -7610,34 +7695,34 @@
76107695
if (c == -1) {
76117696
break;
76127697
}
76137698
val = (val << 4) | c;
76147699
}
7615
-
7700
+
76167701
if (s[i] == '{') {
76177702
if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7618
-
7703
+
76197704
i--;
76207705
k = 0;
76217706
}
76227707
else {
7623
-
7708
+
76247709
k++;
76257710
}
76267711
}
76277712
if (k) {
7628
-
7713
+
76297714
if (s[i] == 'x') {
76307715
*p++ = val;
76317716
}
76327717
else {
76337718
p += utf8_fromunicode(p, val);
76347719
}
76357720
i += k;
76367721
break;
76377722
}
7638
-
7723
+
76397724
*p++ = s[i];
76407725
}
76417726
break;
76427727
case 'v':
76437728
*p++ = 0xb;
@@ -7646,11 +7731,11 @@
76467731
case '\0':
76477732
*p++ = '\\';
76487733
i++;
76497734
break;
76507735
case '\n':
7651
-
7736
+
76527737
*p++ = ' ';
76537738
do {
76547739
i++;
76557740
} while (s[i + 1] == ' ' || s[i + 1] == '\t');
76567741
break;
@@ -7660,11 +7745,11 @@
76607745
case '3':
76617746
case '4':
76627747
case '5':
76637748
case '6':
76647749
case '7':
7665
-
7750
+
76667751
{
76677752
int val = 0;
76687753
int c = odigitval(s[i + 1]);
76697754
76707755
val = c;
@@ -7717,16 +7802,16 @@
77177802
}
77187803
else {
77197804
len = (end - start) + 1;
77207805
token = Jim_Alloc(len + 1);
77217806
if (pc->tt != JIM_TT_ESC) {
7722
-
7807
+
77237808
memcpy(token, start, len);
77247809
token[len] = '\0';
77257810
}
77267811
else {
7727
-
7812
+
77287813
len = JimEscape(token, start, len);
77297814
}
77307815
}
77317816
77327817
return Jim_NewStringObjNoAlloc(interp, token, len);
@@ -7790,11 +7875,11 @@
77907875
while (pc->len) {
77917876
switch (*pc->p) {
77927877
case '\\':
77937878
pc->tt = JIM_TT_ESC;
77947879
if (--pc->len == 0) {
7795
-
7880
+
77967881
pc->tend = pc->p;
77977882
return JIM_OK;
77987883
}
77997884
pc->p++;
78007885
break;
@@ -7826,11 +7911,11 @@
78267911
pc->tend = pc->p - 1;
78277912
return JIM_OK;
78287913
}
78297914
if (*pc->p == '\\') {
78307915
if (--pc->len == 0) {
7831
-
7916
+
78327917
pc->tend = pc->p;
78337918
return JIM_OK;
78347919
}
78357920
pc->tt = JIM_TT_ESC;
78367921
pc->p++;
@@ -7846,24 +7931,24 @@
78467931
78477932
Jim_Obj *Jim_NewObj(Jim_Interp *interp)
78487933
{
78497934
Jim_Obj *objPtr;
78507935
7851
-
7936
+
78527937
if (interp->freeList != NULL) {
7853
-
7938
+
78547939
objPtr = interp->freeList;
78557940
interp->freeList = objPtr->nextObjPtr;
78567941
}
78577942
else {
7858
-
7943
+
78597944
objPtr = Jim_Alloc(sizeof(*objPtr));
78607945
}
78617946
78627947
objPtr->refCount = 0;
78637948
7864
-
7949
+
78657950
objPtr->prevObjPtr = NULL;
78667951
objPtr->nextObjPtr = interp->liveList;
78677952
if (interp->liveList)
78687953
interp->liveList->prevObjPtr = objPtr;
78697954
interp->liveList = objPtr;
@@ -7871,32 +7956,32 @@
78717956
return objPtr;
78727957
}
78737958
78747959
void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
78757960
{
7876
-
7961
+
78777962
JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
78787963
objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
78797964
7880
-
7965
+
78817966
Jim_FreeIntRep(interp, objPtr);
7882
-
7967
+
78837968
if (objPtr->bytes != NULL) {
78847969
if (objPtr->bytes != JimEmptyStringRep)
78857970
Jim_Free(objPtr->bytes);
78867971
}
7887
-
7972
+
78887973
if (objPtr->prevObjPtr)
78897974
objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
78907975
if (objPtr->nextObjPtr)
78917976
objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
78927977
if (interp->liveList == objPtr)
78937978
interp->liveList = objPtr->nextObjPtr;
78947979
#ifdef JIM_DISABLE_OBJECT_POOL
78957980
Jim_Free(objPtr);
78967981
#else
7897
-
7982
+
78987983
objPtr->prevObjPtr = NULL;
78997984
objPtr->nextObjPtr = interp->freeList;
79007985
if (interp->freeList)
79017986
interp->freeList->prevObjPtr = objPtr;
79027987
interp->freeList = objPtr;
@@ -7919,45 +8004,45 @@
79198004
{
79208005
Jim_Obj *dupPtr;
79218006
79228007
dupPtr = Jim_NewObj(interp);
79238008
if (objPtr->bytes == NULL) {
7924
-
8009
+
79258010
dupPtr->bytes = NULL;
79268011
}
79278012
else if (objPtr->length == 0) {
7928
-
8013
+
79298014
dupPtr->bytes = JimEmptyStringRep;
79308015
dupPtr->length = 0;
79318016
dupPtr->typePtr = NULL;
79328017
return dupPtr;
79338018
}
79348019
else {
79358020
dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
79368021
dupPtr->length = objPtr->length;
7937
-
8022
+
79388023
memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
79398024
}
79408025
7941
-
8026
+
79428027
dupPtr->typePtr = objPtr->typePtr;
79438028
if (objPtr->typePtr != NULL) {
79448029
if (objPtr->typePtr->dupIntRepProc == NULL) {
79458030
dupPtr->internalRep = objPtr->internalRep;
79468031
}
79478032
else {
7948
-
8033
+
79498034
objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
79508035
}
79518036
}
79528037
return dupPtr;
79538038
}
79548039
79558040
const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
79568041
{
79578042
if (objPtr->bytes == NULL) {
7958
-
8043
+
79598044
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
79608045
objPtr->typePtr->updateStringProc(objPtr);
79618046
}
79628047
if (lenPtr)
79638048
*lenPtr = objPtr->length;
@@ -7966,11 +8051,11 @@
79668051
79678052
79688053
int Jim_Length(Jim_Obj *objPtr)
79698054
{
79708055
if (objPtr->bytes == NULL) {
7971
-
8056
+
79728057
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
79738058
objPtr->typePtr->updateStringProc(objPtr);
79748059
}
79758060
return objPtr->length;
79768061
}
@@ -7977,11 +8062,11 @@
79778062
79788063
79798064
const char *Jim_String(Jim_Obj *objPtr)
79808065
{
79818066
if (objPtr->bytes == NULL) {
7982
-
8067
+
79838068
JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
79848069
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
79858070
objPtr->typePtr->updateStringProc(objPtr);
79868071
}
79878072
return objPtr->bytes;
@@ -8037,22 +8122,22 @@
80378122
}
80388123
80398124
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
80408125
{
80418126
if (objPtr->typePtr != &stringObjType) {
8042
-
8127
+
80438128
if (objPtr->bytes == NULL) {
8044
-
8129
+
80458130
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
80468131
objPtr->typePtr->updateStringProc(objPtr);
80478132
}
8048
-
8133
+
80498134
Jim_FreeIntRep(interp, objPtr);
8050
-
8135
+
80518136
objPtr->typePtr = &stringObjType;
80528137
objPtr->internalRep.strValue.maxLength = objPtr->length;
8053
-
8138
+
80548139
objPtr->internalRep.strValue.charLength = -1;
80558140
}
80568141
return JIM_OK;
80578142
}
80588143
@@ -8073,14 +8158,14 @@
80738158
80748159
Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
80758160
{
80768161
Jim_Obj *objPtr = Jim_NewObj(interp);
80778162
8078
-
8163
+
80798164
if (len == -1)
80808165
len = strlen(s);
8081
-
8166
+
80828167
if (len == 0) {
80838168
objPtr->bytes = JimEmptyStringRep;
80848169
}
80858170
else {
80868171
objPtr->bytes = Jim_Alloc(len + 1);
@@ -8087,25 +8172,25 @@
80878172
memcpy(objPtr->bytes, s, len);
80888173
objPtr->bytes[len] = '\0';
80898174
}
80908175
objPtr->length = len;
80918176
8092
-
8177
+
80938178
objPtr->typePtr = NULL;
80948179
return objPtr;
80958180
}
80968181
80978182
80988183
Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
80998184
{
81008185
#ifdef JIM_UTF8
8101
-
8186
+
81028187
int bytelen = utf8_index(s, charlen);
81038188
81048189
Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
81058190
8106
-
8191
+
81078192
objPtr->typePtr = &stringObjType;
81088193
objPtr->internalRep.strValue.maxLength = bytelen;
81098194
objPtr->internalRep.strValue.charLength = charlen;
81108195
81118196
return objPtr;
@@ -8132,11 +8217,11 @@
81328217
len = strlen(str);
81338218
needlen = objPtr->length + len;
81348219
if (objPtr->internalRep.strValue.maxLength < needlen ||
81358220
objPtr->internalRep.strValue.maxLength == 0) {
81368221
needlen *= 2;
8137
-
8222
+
81388223
if (needlen < 7) {
81398224
needlen = 7;
81408225
}
81418226
if (objPtr->bytes == JimEmptyStringRep) {
81428227
objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8233,11 @@
81488233
}
81498234
memcpy(objPtr->bytes + objPtr->length, str, len);
81508235
objPtr->bytes[objPtr->length + len] = '\0';
81518236
81528237
if (objPtr->internalRep.strValue.charLength >= 0) {
8153
-
8238
+
81548239
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
81558240
}
81568241
objPtr->length += len;
81578242
}
81588243
@@ -8210,11 +8295,11 @@
82108295
int l1, l2;
82118296
const char *s1 = Jim_GetString(firstObjPtr, &l1);
82128297
const char *s2 = Jim_GetString(secondObjPtr, &l2);
82138298
82148299
if (nocase) {
8215
-
8300
+
82168301
return JimStringCompareLen(s1, s2, -1, nocase);
82178302
}
82188303
return JimStringCompare(s1, l1, s2, l2);
82198304
}
82208305
@@ -8312,11 +8397,11 @@
83128397
83138398
if (first == 0 && rangeLen == len) {
83148399
return strObjPtr;
83158400
}
83168401
if (len == bytelen) {
8317
-
8402
+
83188403
return Jim_NewStringObj(interp, str + first, rangeLen);
83198404
}
83208405
return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
83218406
#else
83228407
return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8426,19 @@
83418426
return strObjPtr;
83428427
}
83438428
83448429
str = Jim_String(strObjPtr);
83458430
8346
-
8431
+
83478432
objPtr = Jim_NewStringObjUtf8(interp, str, first);
83488433
8349
-
8434
+
83508435
if (newStrObj) {
83518436
Jim_AppendObj(interp, objPtr, newStrObj);
83528437
}
83538438
8354
-
8439
+
83558440
Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
83568441
83578442
return objPtr;
83588443
}
83598444
@@ -8452,11 +8537,11 @@
84528537
while (len) {
84538538
int c;
84548539
int n = utf8_tounicode(str, &c);
84558540
84568541
if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8457
-
8542
+
84588543
break;
84598544
}
84608545
str += n;
84618546
len -= n;
84628547
}
@@ -8523,41 +8608,41 @@
85238608
85248609
len = Jim_Length(strObjPtr);
85258610
nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
85268611
85278612
if (nontrim == NULL) {
8528
-
8613
+
85298614
return Jim_NewEmptyStringObj(interp);
85308615
}
85318616
if (nontrim == strObjPtr->bytes + len) {
8532
-
8617
+
85338618
return strObjPtr;
85348619
}
85358620
85368621
if (Jim_IsShared(strObjPtr)) {
85378622
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
85388623
}
85398624
else {
8540
-
8625
+
85418626
strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
85428627
strObjPtr->length = (nontrim - strObjPtr->bytes);
85438628
}
85448629
85458630
return strObjPtr;
85468631
}
85478632
85488633
static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
85498634
{
8550
-
8635
+
85518636
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
85528637
8553
-
8638
+
85548639
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
85558640
8556
-
8641
+
85578642
if (objPtr != strObjPtr && objPtr->refCount == 0) {
8558
-
8643
+
85598644
Jim_FreeNewObj(interp, objPtr);
85608645
}
85618646
85628647
return strObjPtr;
85638648
}
@@ -8575,17 +8660,17 @@
85758660
static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
85768661
{
85778662
static const char * const strclassnames[] = {
85788663
"integer", "alpha", "alnum", "ascii", "digit",
85798664
"double", "lower", "upper", "space", "xdigit",
8580
- "control", "print", "graph", "punct",
8665
+ "control", "print", "graph", "punct", "boolean",
85818666
NULL
85828667
};
85838668
enum {
85848669
STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
85858670
STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8586
- STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT
8671
+ STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN,
85878672
};
85888673
int strclass;
85898674
int len;
85908675
int i;
85918676
const char *str;
@@ -8613,10 +8698,17 @@
86138698
{
86148699
double d;
86158700
Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
86168701
return JIM_OK;
86178702
}
8703
+
8704
+ case STR_IS_BOOLEAN:
8705
+ {
8706
+ int b;
8707
+ Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK);
8708
+ return JIM_OK;
8709
+ }
86188710
86198711
case STR_IS_ALPHA: isclassfunc = isalpha; break;
86208712
case STR_IS_ALNUM: isclassfunc = isalnum; break;
86218713
case STR_IS_ASCII: isclassfunc = jim_isascii; break;
86228714
case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8723,11 @@
86318723
default:
86328724
return JIM_ERR;
86338725
}
86348726
86358727
for (i = 0; i < len; i++) {
8636
- if (!isclassfunc(str[i])) {
8728
+ if (!isclassfunc(UCHAR(str[i]))) {
86378729
Jim_SetResultBool(interp, 0);
86388730
return JIM_OK;
86398731
}
86408732
}
86418733
Jim_SetResultBool(interp, 1);
@@ -8665,11 +8757,11 @@
86658757
86668758
if (objPtr->typePtr != &comparedStringObjType) {
86678759
Jim_FreeIntRep(interp, objPtr);
86688760
objPtr->typePtr = &comparedStringObjType;
86698761
}
8670
- objPtr->internalRep.ptr = (char *)str;
8762
+ objPtr->internalRep.ptr = (char *)str;
86718763
return 1;
86728764
}
86738765
}
86748766
86758767
static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8850,20 @@
87588850
int type;
87598851
} ScriptToken;
87608852
87618853
typedef struct ScriptObj
87628854
{
8763
- ScriptToken *token;
8764
- Jim_Obj *fileNameObj;
8765
- int len;
8766
- int substFlags;
8855
+ ScriptToken *token;
8856
+ Jim_Obj *fileNameObj;
8857
+ int len;
8858
+ int substFlags;
87678859
int inUse; /* Used to share a ScriptObj. Currently
87688860
only used by Jim_EvalObj() as protection against
87698861
shimmering of the currently evaluated object. */
8770
- int firstline;
8771
- int linenr;
8772
- int missing;
8862
+ int firstline;
8863
+ int linenr;
8864
+ int missing;
87738865
} ScriptObj;
87748866
87758867
static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
87768868
static int JimParseCheckMissing(Jim_Interp *interp, int ch);
87778869
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8891,23 @@
87998891
dupPtr->typePtr = NULL;
88008892
}
88018893
88028894
typedef struct
88038895
{
8804
- const char *token;
8805
- int len;
8806
- int type;
8807
- int line;
8896
+ const char *token;
8897
+ int len;
8898
+ int type;
8899
+ int line;
88088900
} ParseToken;
88098901
88108902
typedef struct
88118903
{
8812
-
8813
- ParseToken *list;
8814
- int size;
8815
- int count;
8816
- ParseToken static_list[20];
8904
+
8905
+ ParseToken *list;
8906
+ int size;
8907
+ int count;
8908
+ ParseToken static_list[20];
88178909
} ParseTokenList;
88188910
88198911
static void ScriptTokenListInit(ParseTokenList *tokenlist)
88208912
{
88218913
tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8926,18 @@
88348926
int line)
88358927
{
88368928
ParseToken *t;
88378929
88388930
if (tokenlist->count == tokenlist->size) {
8839
-
8931
+
88408932
tokenlist->size *= 2;
88418933
if (tokenlist->list != tokenlist->static_list) {
88428934
tokenlist->list =
88438935
Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
88448936
}
88458937
else {
8846
-
8938
+
88478939
tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
88488940
memcpy(tokenlist->list, tokenlist->static_list,
88498941
tokenlist->count * sizeof(*tokenlist->list));
88508942
}
88518943
}
@@ -8859,20 +8951,20 @@
88598951
static int JimCountWordTokens(ParseToken *t)
88608952
{
88618953
int expand = 1;
88628954
int count = 0;
88638955
8864
-
8956
+
88658957
if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
88668958
if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8867
-
8959
+
88688960
expand = -1;
88698961
t++;
88708962
}
88718963
}
88728964
8873
-
8965
+
88748966
while (!TOKEN_IS_SEP(t->type)) {
88758967
t++;
88768968
count++;
88778969
}
88788970
@@ -8882,11 +8974,11 @@
88828974
static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
88838975
{
88848976
Jim_Obj *objPtr;
88858977
88868978
if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8887
-
8979
+
88888980
int len = t->len;
88898981
char *str = Jim_Alloc(len + 1);
88908982
len = JimEscape(str, t->token, len);
88918983
objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
88928984
}
@@ -8899,13 +8991,13 @@
88998991
static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
89008992
ParseTokenList *tokenlist)
89018993
{
89028994
int i;
89038995
struct ScriptToken *token;
8904
-
8996
+
89058997
int lineargs = 0;
8906
-
8998
+
89078999
ScriptToken *linefirst;
89089000
int count;
89099001
int linenr;
89109002
89119003
#ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +9006,11 @@
89149006
printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
89159007
tokenlist->list[i].len, tokenlist->list[i].token);
89169008
}
89179009
#endif
89189010
8919
-
9011
+
89209012
count = tokenlist->count;
89219013
for (i = 0; i < tokenlist->count; i++) {
89229014
if (tokenlist->list[i].type == JIM_TT_EOL) {
89239015
count++;
89249016
}
@@ -8925,59 +9017,59 @@
89259017
}
89269018
linenr = script->firstline = tokenlist->list[0].line;
89279019
89289020
token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
89299021
8930
-
9022
+
89319023
linefirst = token++;
89329024
89339025
for (i = 0; i < tokenlist->count; ) {
8934
-
9026
+
89359027
int wordtokens;
89369028
8937
-
9029
+
89389030
while (tokenlist->list[i].type == JIM_TT_SEP) {
89399031
i++;
89409032
}
89419033
89429034
wordtokens = JimCountWordTokens(tokenlist->list + i);
89439035
89449036
if (wordtokens == 0) {
8945
-
9037
+
89469038
if (lineargs) {
89479039
linefirst->type = JIM_TT_LINE;
89489040
linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
89499041
Jim_IncrRefCount(linefirst->objPtr);
89509042
8951
-
9043
+
89529044
lineargs = 0;
89539045
linefirst = token++;
89549046
}
89559047
i++;
89569048
continue;
89579049
}
89589050
else if (wordtokens != 1) {
8959
-
9051
+
89609052
token->type = JIM_TT_WORD;
89619053
token->objPtr = Jim_NewIntObj(interp, wordtokens);
89629054
Jim_IncrRefCount(token->objPtr);
89639055
token++;
89649056
if (wordtokens < 0) {
8965
-
9057
+
89669058
i++;
89679059
wordtokens = -wordtokens - 1;
89689060
lineargs--;
89699061
}
89709062
}
89719063
89729064
if (lineargs == 0) {
8973
-
9065
+
89749066
linenr = tokenlist->list[i].line;
89759067
}
89769068
lineargs++;
89779069
8978
-
9070
+
89799071
while (wordtokens--) {
89809072
const ParseToken *t = &tokenlist->list[i++];
89819073
89829074
token->type = t->type;
89839075
token->objPtr = JimMakeScriptObj(interp, t);
@@ -9049,11 +9141,11 @@
90499141
token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
90509142
90519143
for (i = 0; i < tokenlist->count; i++) {
90529144
const ParseToken *t = &tokenlist->list[i];
90539145
9054
-
9146
+
90559147
token->type = t->type;
90569148
token->objPtr = JimMakeScriptObj(interp, t);
90579149
Jim_IncrRefCount(token->objPtr);
90589150
token++;
90599151
}
@@ -9068,29 +9160,29 @@
90689160
struct JimParserCtx parser;
90699161
struct ScriptObj *script;
90709162
ParseTokenList tokenlist;
90719163
int line = 1;
90729164
9073
-
9165
+
90749166
if (objPtr->typePtr == &sourceObjType) {
90759167
line = objPtr->internalRep.sourceValue.lineNumber;
90769168
}
90779169
9078
-
9170
+
90799171
ScriptTokenListInit(&tokenlist);
90809172
90819173
JimParserInit(&parser, scriptText, scriptTextLen, line);
90829174
while (!parser.eof) {
90839175
JimParseScript(&parser);
90849176
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
90859177
parser.tline);
90869178
}
90879179
9088
-
9180
+
90899181
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
90909182
9091
-
9183
+
90929184
script = Jim_Alloc(sizeof(*script));
90939185
memset(script, 0, sizeof(*script));
90949186
script->inUse = 1;
90959187
if (objPtr->typePtr == &sourceObjType) {
90969188
script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9194,14 @@
91029194
script->missing = parser.missing.ch;
91039195
script->linenr = parser.missing.line;
91049196
91059197
ScriptObjAddTokens(interp, script, &tokenlist);
91069198
9107
-
9199
+
91089200
ScriptTokenListFree(&tokenlist);
91099201
9110
-
9202
+
91119203
Jim_FreeIntRep(interp, objPtr);
91129204
Jim_SetIntRepPtr(objPtr, script);
91139205
objPtr->typePtr = &scriptObjType;
91149206
}
91159207
@@ -9116,11 +9208,11 @@
91169208
static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
91179209
91189210
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
91199211
{
91209212
if (objPtr == interp->emptyObj) {
9121
-
9213
+
91229214
objPtr = interp->nullScriptObj;
91239215
}
91249216
91259217
if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
91269218
JimSetScriptFromAny(interp, objPtr);
@@ -9155,17 +9247,17 @@
91559247
Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
91569248
Jim_Free(cmdPtr->u.proc.staticVars);
91579249
}
91589250
}
91599251
else {
9160
-
9252
+
91619253
if (cmdPtr->u.native.delProc) {
91629254
cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
91639255
}
91649256
}
91659257
if (cmdPtr->prevCmd) {
9166
-
9258
+
91679259
JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
91689260
}
91699261
Jim_Free(cmdPtr);
91709262
}
91719263
}
@@ -9176,46 +9268,46 @@
91769268
Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
91779269
Jim_Free(val);
91789270
}
91799271
91809272
static const Jim_HashTableType JimVariablesHashTableType = {
9181
- JimStringCopyHTHashFunction,
9182
- JimStringCopyHTDup,
9183
- NULL,
9184
- JimStringCopyHTKeyCompare,
9185
- JimStringCopyHTKeyDestructor,
9186
- JimVariablesHTValDestructor
9273
+ JimStringCopyHTHashFunction,
9274
+ JimStringCopyHTDup,
9275
+ NULL,
9276
+ JimStringCopyHTKeyCompare,
9277
+ JimStringCopyHTKeyDestructor,
9278
+ JimVariablesHTValDestructor
91879279
};
91889280
91899281
static void JimCommandsHT_ValDestructor(void *interp, void *val)
91909282
{
91919283
JimDecrCmdRefCount(interp, val);
91929284
}
91939285
91949286
static const Jim_HashTableType JimCommandsHashTableType = {
9195
- JimStringCopyHTHashFunction,
9196
- JimStringCopyHTDup,
9197
- NULL,
9198
- JimStringCopyHTKeyCompare,
9199
- JimStringCopyHTKeyDestructor,
9200
- JimCommandsHT_ValDestructor
9287
+ JimStringCopyHTHashFunction,
9288
+ JimStringCopyHTDup,
9289
+ NULL,
9290
+ JimStringCopyHTKeyCompare,
9291
+ JimStringCopyHTKeyDestructor,
9292
+ JimCommandsHT_ValDestructor
92019293
};
92029294
92039295
92049296
92059297
#ifdef jim_ext_namespace
92069298
static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
92079299
{
92089300
const char *name = Jim_String(nsObj);
92099301
if (name[0] == ':' && name[1] == ':') {
9210
-
9302
+
92119303
while (*++name == ':') {
92129304
}
92139305
nsObj = Jim_NewStringObj(interp, name, -1);
92149306
}
92159307
else if (Jim_Length(interp->framePtr->nsObj)) {
9216
-
9308
+
92179309
nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
92189310
Jim_AppendStrings(interp, nsObj, "::", name, NULL);
92199311
}
92209312
return nsObj;
92219313
}
@@ -9239,16 +9331,16 @@
92399331
static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
92409332
{
92419333
Jim_Obj *objPtr = interp->emptyObj;
92429334
92439335
if (name[0] == ':' && name[1] == ':') {
9244
-
9336
+
92459337
while (*++name == ':') {
92469338
}
92479339
}
92489340
else if (Jim_Length(interp->framePtr->nsObj)) {
9249
-
9341
+
92509342
objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
92519343
Jim_AppendStrings(interp, objPtr, "::", name, NULL);
92529344
name = Jim_String(objPtr);
92539345
}
92549346
Jim_IncrRefCount(objPtr);
@@ -9257,11 +9349,11 @@
92579349
}
92589350
92599351
#define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
92609352
92619353
#else
9262
-
9354
+
92639355
#define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
92649356
#define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
92659357
92669358
Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
92679359
{
@@ -9276,17 +9368,17 @@
92769368
92779369
Jim_InterpIncrProcEpoch(interp);
92789370
}
92799371
92809372
if (he && interp->local) {
9281
-
9373
+
92829374
cmd->prevCmd = Jim_GetHashEntryVal(he);
92839375
Jim_SetHashVal(&interp->commands, he, cmd);
92849376
}
92859377
else {
92869378
if (he) {
9287
-
9379
+
92889380
Jim_DeleteHashEntry(&interp->commands, name);
92899381
}
92909382
92919383
Jim_AddHashEntry(&interp->commands, name, cmd);
92929384
}
@@ -9297,11 +9389,11 @@
92979389
int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
92989390
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
92999391
{
93009392
Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
93019393
9302
-
9394
+
93039395
memset(cmdPtr, 0, sizeof(*cmdPtr));
93049396
cmdPtr->inUse = 1;
93059397
cmdPtr->u.native.delProc = delProc;
93069398
cmdPtr->u.native.cmdProc = cmdProc;
93079399
cmdPtr->u.native.privData = privData;
@@ -9326,11 +9418,11 @@
93269418
Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
93279419
Jim_Var *varPtr;
93289420
int subLen;
93299421
93309422
objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9331
-
9423
+
93329424
subLen = Jim_ListLength(interp, objPtr);
93339425
if (subLen == 1 || subLen == 2) {
93349426
nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
93359427
if (subLen == 1) {
93369428
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9464,19 @@
93729464
93739465
static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
93749466
{
93759467
#ifdef jim_ext_namespace
93769468
if (cmdPtr->isproc) {
9377
-
9469
+
93789470
const char *pt = strrchr(cmdname, ':');
93799471
if (pt && pt != cmdname && pt[-1] == ':') {
93809472
Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
93819473
cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
93829474
Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
93839475
93849476
if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9385
-
9477
+
93869478
Jim_InterpIncrProcEpoch(interp);
93879479
}
93889480
}
93899481
}
93909482
#endif
@@ -9397,11 +9489,11 @@
93979489
int argListLen;
93989490
int i;
93999491
94009492
argListLen = Jim_ListLength(interp, argListObjPtr);
94019493
9402
-
9494
+
94039495
cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
94049496
memset(cmdPtr, 0, sizeof(*cmdPtr));
94059497
cmdPtr->inUse = 1;
94069498
cmdPtr->isproc = 1;
94079499
cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9504,24 @@
94129504
cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
94139505
Jim_IncrRefCount(argListObjPtr);
94149506
Jim_IncrRefCount(bodyObjPtr);
94159507
Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
94169508
9417
-
9509
+
94189510
if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
94199511
goto err;
94209512
}
94219513
9422
-
9423
-
9514
+
9515
+
94249516
for (i = 0; i < argListLen; i++) {
94259517
Jim_Obj *argPtr;
94269518
Jim_Obj *nameObjPtr;
94279519
Jim_Obj *defaultObjPtr;
94289520
int len;
94299521
9430
-
9522
+
94319523
argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
94329524
len = Jim_ListLength(interp, argPtr);
94339525
if (len == 0) {
94349526
Jim_SetResultString(interp, "argument with no name", -1);
94359527
err:
@@ -9440,16 +9532,16 @@
94409532
Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
94419533
goto err;
94429534
}
94439535
94449536
if (len == 2) {
9445
-
9537
+
94469538
nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
94479539
defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
94489540
}
94499541
else {
9450
-
9542
+
94519543
nameObjPtr = argPtr;
94529544
defaultObjPtr = NULL;
94539545
}
94549546
94559547
@@ -9510,29 +9602,29 @@
95109602
}
95119603
95129604
fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
95139605
fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
95149606
9515
-
9607
+
95169608
he = Jim_FindHashEntry(&interp->commands, fqold);
95179609
if (he == NULL) {
95189610
Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
95199611
}
95209612
else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
95219613
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
95229614
}
95239615
else {
9524
-
9616
+
95259617
cmdPtr = Jim_GetHashEntryVal(he);
95269618
JimIncrCmdRefCount(cmdPtr);
95279619
JimUpdateProcNamespace(interp, cmdPtr, fqnew);
95289620
Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
95299621
9530
-
9622
+
95319623
Jim_DeleteHashEntry(&interp->commands, fqold);
95329624
9533
-
9625
+
95349626
Jim_InterpIncrProcEpoch(interp);
95359627
95369628
ret = JIM_OK;
95379629
}
95389630
@@ -9571,23 +9663,23 @@
95719663
objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
95729664
#ifdef jim_ext_namespace
95739665
|| !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
95749666
#endif
95759667
) {
9576
-
95779668
9578
-
9669
+
9670
+
95799671
const char *name = Jim_String(objPtr);
95809672
Jim_HashEntry *he;
95819673
95829674
if (name[0] == ':' && name[1] == ':') {
95839675
while (*++name == ':') {
95849676
}
95859677
}
95869678
#ifdef jim_ext_namespace
95879679
else if (Jim_Length(interp->framePtr->nsObj)) {
9588
-
9680
+
95899681
Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
95909682
Jim_AppendStrings(interp, nameObj, "::", name, NULL);
95919683
he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
95929684
Jim_FreeNewObj(interp, nameObj);
95939685
if (he) {
@@ -9594,11 +9686,11 @@
95949686
goto found;
95959687
}
95969688
}
95979689
#endif
95989690
9599
-
9691
+
96009692
he = Jim_FindHashEntry(&interp->commands, name);
96019693
if (he == NULL) {
96029694
if (flags & JIM_ERRMSG) {
96039695
Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
96049696
}
@@ -9607,11 +9699,11 @@
96079699
#ifdef jim_ext_namespace
96089700
found:
96099701
#endif
96109702
cmd = Jim_GetHashEntryVal(he);
96119703
9612
-
9704
+
96139705
Jim_FreeIntRep(interp, objPtr);
96149706
objPtr->typePtr = &commandObjType;
96159707
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
96169708
objPtr->internalRep.cmdValue.cmdPtr = cmd;
96179709
objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9718,11 @@
96269718
return cmd;
96279719
}
96289720
96299721
96309722
9631
-#define JIM_DICT_SUGAR 100
9723
+#define JIM_DICT_SUGAR 100
96329724
96339725
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
96349726
96359727
static const Jim_ObjType variableObjType = {
96369728
"variable",
@@ -9640,11 +9732,11 @@
96409732
JIM_TYPE_REFERENCES,
96419733
};
96429734
96439735
static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
96449736
{
9645
-
9737
+
96469738
if (nameObjPtr->typePtr != &variableObjType) {
96479739
int len;
96489740
const char *str = Jim_GetString(nameObjPtr, &len);
96499741
if (memchr(str, '\0', len)) {
96509742
Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9752,18 @@
96609752
Jim_CallFrame *framePtr;
96619753
Jim_HashEntry *he;
96629754
int global;
96639755
int len;
96649756
9665
-
9757
+
96669758
if (objPtr->typePtr == &variableObjType) {
96679759
framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
96689760
if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9669
-
9761
+
96709762
return JIM_OK;
96719763
}
9672
-
9764
+
96739765
}
96749766
else if (objPtr->typePtr == &dictSubstObjType) {
96759767
return JIM_DICT_SUGAR;
96769768
}
96779769
else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9771,11 @@
96799771
}
96809772
96819773
96829774
varName = Jim_GetString(objPtr, &len);
96839775
9684
-
9776
+
96859777
if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
96869778
return JIM_DICT_SUGAR;
96879779
}
96889780
96899781
if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9787,23 @@
96959787
else {
96969788
global = 0;
96979789
framePtr = interp->framePtr;
96989790
}
96999791
9700
-
9792
+
97019793
he = Jim_FindHashEntry(&framePtr->vars, varName);
97029794
if (he == NULL) {
97039795
if (!global && framePtr->staticVars) {
9704
-
9796
+
97059797
he = Jim_FindHashEntry(framePtr->staticVars, varName);
97069798
}
97079799
if (he == NULL) {
97089800
return JIM_ERR;
97099801
}
97109802
}
97119803
9712
-
9804
+
97139805
Jim_FreeIntRep(interp, objPtr);
97149806
objPtr->typePtr = &variableObjType;
97159807
objPtr->internalRep.varValue.callFrameId = framePtr->id;
97169808
objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
97179809
objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9818,11 @@
97269818
{
97279819
const char *name;
97289820
Jim_CallFrame *framePtr;
97299821
int global;
97309822
9731
-
9823
+
97329824
Jim_Var *var = Jim_Alloc(sizeof(*var));
97339825
97349826
var->objPtr = valObjPtr;
97359827
Jim_IncrRefCount(valObjPtr);
97369828
var->linkFramePtr = NULL;
@@ -9745,14 +9837,14 @@
97459837
else {
97469838
framePtr = interp->framePtr;
97479839
global = 0;
97489840
}
97499841
9750
-
9842
+
97519843
Jim_AddHashEntry(&framePtr->vars, name, var);
97529844
9753
-
9845
+
97549846
Jim_FreeIntRep(interp, nameObjPtr);
97559847
nameObjPtr->typePtr = &variableObjType;
97569848
nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
97579849
nameObjPtr->internalRep.varValue.varPtr = var;
97589850
nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9874,11 @@
97829874
if (var->linkFramePtr == NULL) {
97839875
Jim_IncrRefCount(valObjPtr);
97849876
Jim_DecrRefCount(interp, var->objPtr);
97859877
var->objPtr = valObjPtr;
97869878
}
9787
- else {
9879
+ else {
97889880
Jim_CallFrame *savedCallFrame;
97899881
97909882
savedCallFrame = interp->framePtr;
97919883
interp->framePtr = var->linkFramePtr;
97929884
err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9843,14 +9935,14 @@
98439935
const char *varName;
98449936
const char *targetName;
98459937
Jim_CallFrame *framePtr;
98469938
Jim_Var *varPtr;
98479939
9848
-
9940
+
98499941
switch (SetVariableFromAny(interp, nameObjPtr)) {
98509942
case JIM_DICT_SUGAR:
9851
-
9943
+
98529944
Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
98539945
return JIM_ERR;
98549946
98559947
case JIM_OK:
98569948
varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9950,23 @@
98589950
if (varPtr->linkFramePtr == NULL) {
98599951
Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
98609952
return JIM_ERR;
98619953
}
98629954
9863
-
9955
+
98649956
varPtr->linkFramePtr = NULL;
98659957
break;
98669958
}
98679959
9868
-
9869
-
9960
+
9961
+
98709962
varName = Jim_String(nameObjPtr);
98719963
98729964
if (varName[0] == ':' && varName[1] == ':') {
98739965
while (*++varName == ':') {
98749966
}
9875
-
9967
+
98769968
framePtr = interp->topFramePtr;
98779969
}
98789970
else {
98799971
framePtr = interp->framePtr;
98809972
}
@@ -9894,15 +9986,15 @@
98949986
nameObjPtr);
98959987
Jim_DecrRefCount(interp, targetNameObjPtr);
98969988
return JIM_ERR;
98979989
}
98989990
9899
-
9991
+
99009992
if (framePtr == targetCallFrame) {
99019993
Jim_Obj *objPtr = targetNameObjPtr;
99029994
9903
-
9995
+
99049996
while (1) {
99059997
if (strcmp(Jim_String(objPtr), varName) == 0) {
99069998
Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
99079999
Jim_DecrRefCount(interp, targetNameObjPtr);
990810000
return JIM_ERR;
@@ -9914,13 +10006,13 @@
991410006
break;
991510007
objPtr = varPtr->objPtr;
991610008
}
991710009
}
991810010
9919
-
10011
+
992010012
Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
9921
-
10013
+
992210014
nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
992310015
Jim_DecrRefCount(interp, targetNameObjPtr);
992410016
return JIM_OK;
992510017
}
992610018
@@ -9934,26 +10026,26 @@
993410026
return varPtr->objPtr;
993510027
}
993610028
else {
993710029
Jim_Obj *objPtr;
993810030
9939
-
10031
+
994010032
Jim_CallFrame *savedCallFrame = interp->framePtr;
994110033
994210034
interp->framePtr = varPtr->linkFramePtr;
994310035
objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
994410036
interp->framePtr = savedCallFrame;
994510037
if (objPtr) {
994610038
return objPtr;
994710039
}
9948
-
10040
+
994910041
}
995010042
}
995110043
break;
995210044
995310045
case JIM_DICT_SUGAR:
9954
-
10046
+
995510047
return JimDictSugarGet(interp, nameObjPtr, flags);
995610048
}
995710049
if (flags & JIM_ERRMSG) {
995810050
Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
995910051
}
@@ -10003,17 +10095,17 @@
1000310095
int retval;
1000410096
Jim_CallFrame *framePtr;
1000510097
1000610098
retval = SetVariableFromAny(interp, nameObjPtr);
1000710099
if (retval == JIM_DICT_SUGAR) {
10008
-
10100
+
1000910101
return JimDictSugarSet(interp, nameObjPtr, NULL);
1001010102
}
1001110103
else if (retval == JIM_OK) {
1001210104
varPtr = nameObjPtr->internalRep.varValue.varPtr;
1001310105
10014
-
10106
+
1001510107
if (varPtr->linkFramePtr) {
1001610108
framePtr = interp->framePtr;
1001710109
interp->framePtr = varPtr->linkFramePtr;
1001810110
retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
1001910111
interp->framePtr = framePtr;
@@ -10028,11 +10120,11 @@
1002810120
framePtr = interp->framePtr;
1002910121
}
1003010122
1003110123
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
1003210124
if (retval == JIM_OK) {
10033
-
10125
+
1003410126
framePtr->id = interp->callFrameEpoch++;
1003510127
}
1003610128
}
1003710129
}
1003810130
if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10153,11 @@
1006110153
keyLen = (str + len) - p;
1006210154
if (str[len - 1] == ')') {
1006310155
keyLen--;
1006410156
}
1006510157
10066
-
10158
+
1006710159
keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
1006810160
1006910161
Jim_IncrRefCount(varObjPtr);
1007010162
Jim_IncrRefCount(keyObjPtr);
1007110163
*varPtrPtr = varObjPtr;
@@ -10080,23 +10172,23 @@
1008010172
1008110173
err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
1008210174
&objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
1008310175
1008410176
if (err == JIM_OK) {
10085
-
10177
+
1008610178
Jim_SetEmptyResult(interp);
1008710179
}
1008810180
else {
1008910181
if (!valObjPtr) {
10090
-
10182
+
1009110183
if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
1009210184
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
1009310185
objPtr);
1009410186
return err;
1009510187
}
1009610188
}
10097
-
10189
+
1009810190
Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
1009910191
(valObjPtr ? "set" : "unset"), objPtr);
1010010192
}
1010110193
return err;
1010210194
}
@@ -10118,11 +10210,11 @@
1011810210
Jim_SetResultFormatted(interp,
1011910211
"can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
1012010212
ret < 0 ? "variable isn't" : "no such element in");
1012110213
}
1012210214
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10123
-
10215
+
1012410216
Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
1012510217
}
1012610218
1012710219
return resObjPtr;
1012810220
}
@@ -10160,11 +10252,11 @@
1016010252
{
1016110253
if (objPtr->typePtr != &dictSubstObjType) {
1016210254
Jim_Obj *varObjPtr, *keyObjPtr;
1016310255
1016410256
if (objPtr->typePtr == &interpolatedObjType) {
10165
-
10257
+
1016610258
1016710259
varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
1016810260
keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
1016910261
1017010262
Jim_IncrRefCount(varObjPtr);
@@ -10205,11 +10297,11 @@
1020510297
static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
1020610298
{
1020710299
Jim_Obj *resultObjPtr;
1020810300
1020910301
if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
10210
-
10302
+
1021110303
resultObjPtr->refCount--;
1021210304
return resultObjPtr;
1021310305
}
1021410306
return NULL;
1021510307
}
@@ -10249,11 +10341,11 @@
1024910341
return cf;
1025010342
}
1025110343
1025210344
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
1025310345
{
10254
-
10346
+
1025510347
if (localCommands) {
1025610348
Jim_Obj *cmdNameObj;
1025710349
1025810350
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
1025910351
Jim_HashEntry *he;
@@ -10268,20 +10360,20 @@
1026810360
Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
1026910361
if (cmd->prevCmd) {
1027010362
Jim_Cmd *prevCmd = cmd->prevCmd;
1027110363
cmd->prevCmd = NULL;
1027210364
10273
-
10365
+
1027410366
JimDecrCmdRefCount(interp, cmd);
1027510367
10276
-
10368
+
1027710369
Jim_SetHashVal(ht, he, prevCmd);
1027810370
}
1027910371
else {
1028010372
Jim_DeleteHashEntry(ht, fqname);
10281
- Jim_InterpIncrProcEpoch(interp);
1028210373
}
10374
+ Jim_InterpIncrProcEpoch(interp);
1028310375
}
1028410376
Jim_DecrRefCount(interp, cmdNameObj);
1028510377
JimFreeQualifiedName(interp, fqObjName);
1028610378
}
1028710379
Jim_FreeStack(localCommands);
@@ -10289,12 +10381,12 @@
1028910381
}
1029010382
return JIM_OK;
1029110383
}
1029210384
1029310385
10294
-#define JIM_FCF_FULL 0
10295
-#define JIM_FCF_REUSE 1
10386
+#define JIM_FCF_FULL 0
10387
+#define JIM_FCF_REUSE 1
1029610388
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
1029710389
{
1029810390
JimDeleteLocalProcs(interp, cf->localCommands);
1029910391
1030010392
if (cf->procArgsObjPtr)
@@ -10327,263 +10419,10 @@
1032710419
cf->next = interp->freeFramesList;
1032810420
interp->freeFramesList = cf;
1032910421
}
1033010422
1033110423
10332
-#ifdef JIM_REFERENCES
10333
-
10334
-static void JimReferencesHTValDestructor(void *interp, void *val)
10335
-{
10336
- Jim_Reference *refPtr = (void *)val;
10337
-
10338
- Jim_DecrRefCount(interp, refPtr->objPtr);
10339
- if (refPtr->finalizerCmdNamePtr != NULL) {
10340
- Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10341
- }
10342
- Jim_Free(val);
10343
-}
10344
-
10345
-static unsigned int JimReferencesHTHashFunction(const void *key)
10346
-{
10347
-
10348
- const unsigned long *widePtr = key;
10349
- unsigned int intValue = (unsigned int)*widePtr;
10350
-
10351
- return Jim_IntHashFunction(intValue);
10352
-}
10353
-
10354
-static void *JimReferencesHTKeyDup(void *privdata, const void *key)
10355
-{
10356
- void *copy = Jim_Alloc(sizeof(unsigned long));
10357
-
10358
- JIM_NOTUSED(privdata);
10359
-
10360
- memcpy(copy, key, sizeof(unsigned long));
10361
- return copy;
10362
-}
10363
-
10364
-static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2)
10365
-{
10366
- JIM_NOTUSED(privdata);
10367
-
10368
- return memcmp(key1, key2, sizeof(unsigned long)) == 0;
10369
-}
10370
-
10371
-static void JimReferencesHTKeyDestructor(void *privdata, void *key)
10372
-{
10373
- JIM_NOTUSED(privdata);
10374
-
10375
- Jim_Free(key);
10376
-}
10377
-
10378
-static const Jim_HashTableType JimReferencesHashTableType = {
10379
- JimReferencesHTHashFunction,
10380
- JimReferencesHTKeyDup,
10381
- NULL,
10382
- JimReferencesHTKeyCompare,
10383
- JimReferencesHTKeyDestructor,
10384
- JimReferencesHTValDestructor
10385
-};
10386
-
10387
-
10388
-
10389
-#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
10390
-
10391
-static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
10392
-{
10393
- const char *fmt = "<reference.<%s>.%020lu>";
10394
-
10395
- sprintf(buf, fmt, refPtr->tag, id);
10396
- return JIM_REFERENCE_SPACE;
10397
-}
10398
-
10399
-static void UpdateStringOfReference(struct Jim_Obj *objPtr);
10400
-
10401
-static const Jim_ObjType referenceObjType = {
10402
- "reference",
10403
- NULL,
10404
- NULL,
10405
- UpdateStringOfReference,
10406
- JIM_TYPE_REFERENCES,
10407
-};
10408
-
10409
-static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10410
-{
10411
- char buf[JIM_REFERENCE_SPACE + 1];
10412
-
10413
- JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10414
- JimSetStringBytes(objPtr, buf);
10415
-}
10416
-
10417
-static int isrefchar(int c)
10418
-{
10419
- return (c == '_' || isalnum(c));
10420
-}
10421
-
10422
-static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10423
-{
10424
- unsigned long value;
10425
- int i, len;
10426
- const char *str, *start, *end;
10427
- char refId[21];
10428
- Jim_Reference *refPtr;
10429
- Jim_HashEntry *he;
10430
- char *endptr;
10431
-
10432
-
10433
- str = Jim_GetString(objPtr, &len);
10434
-
10435
- if (len < JIM_REFERENCE_SPACE)
10436
- goto badformat;
10437
-
10438
- start = str;
10439
- end = str + len - 1;
10440
- while (*start == ' ')
10441
- start++;
10442
- while (*end == ' ' && end > start)
10443
- end--;
10444
- if (end - start + 1 != JIM_REFERENCE_SPACE)
10445
- goto badformat;
10446
-
10447
- if (memcmp(start, "<reference.<", 12) != 0)
10448
- goto badformat;
10449
- if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
10450
- goto badformat;
10451
-
10452
- for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10453
- if (!isrefchar(start[12 + i]))
10454
- goto badformat;
10455
- }
10456
-
10457
- memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
10458
- refId[20] = '\0';
10459
-
10460
- value = strtoul(refId, &endptr, 10);
10461
- if (JimCheckConversion(refId, endptr) != JIM_OK)
10462
- goto badformat;
10463
-
10464
- he = Jim_FindHashEntry(&interp->references, &value);
10465
- if (he == NULL) {
10466
- Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10467
- return JIM_ERR;
10468
- }
10469
- refPtr = Jim_GetHashEntryVal(he);
10470
-
10471
- Jim_FreeIntRep(interp, objPtr);
10472
- objPtr->typePtr = &referenceObjType;
10473
- objPtr->internalRep.refValue.id = value;
10474
- objPtr->internalRep.refValue.refPtr = refPtr;
10475
- return JIM_OK;
10476
-
10477
- badformat:
10478
- Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr);
10479
- return JIM_ERR;
10480
-}
10481
-
10482
-Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
10483
-{
10484
- struct Jim_Reference *refPtr;
10485
- unsigned long id;
10486
- Jim_Obj *refObjPtr;
10487
- const char *tag;
10488
- int tagLen, i;
10489
-
10490
-
10491
- Jim_CollectIfNeeded(interp);
10492
-
10493
- refPtr = Jim_Alloc(sizeof(*refPtr));
10494
- refPtr->objPtr = objPtr;
10495
- Jim_IncrRefCount(objPtr);
10496
- refPtr->finalizerCmdNamePtr = cmdNamePtr;
10497
- if (cmdNamePtr)
10498
- Jim_IncrRefCount(cmdNamePtr);
10499
- id = interp->referenceNextId++;
10500
- Jim_AddHashEntry(&interp->references, &id, refPtr);
10501
- refObjPtr = Jim_NewObj(interp);
10502
- refObjPtr->typePtr = &referenceObjType;
10503
- refObjPtr->bytes = NULL;
10504
- refObjPtr->internalRep.refValue.id = id;
10505
- refObjPtr->internalRep.refValue.refPtr = refPtr;
10506
- interp->referenceNextId++;
10507
- tag = Jim_GetString(tagPtr, &tagLen);
10508
- if (tagLen > JIM_REFERENCE_TAGLEN)
10509
- tagLen = JIM_REFERENCE_TAGLEN;
10510
- for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10511
- if (i < tagLen && isrefchar(tag[i]))
10512
- refPtr->tag[i] = tag[i];
10513
- else
10514
- refPtr->tag[i] = '_';
10515
- }
10516
- refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0';
10517
- return refObjPtr;
10518
-}
10519
-
10520
-Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr)
10521
-{
10522
- if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR)
10523
- return NULL;
10524
- return objPtr->internalRep.refValue.refPtr;
10525
-}
10526
-
10527
-int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr)
10528
-{
10529
- Jim_Reference *refPtr;
10530
-
10531
- if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10532
- return JIM_ERR;
10533
- Jim_IncrRefCount(cmdNamePtr);
10534
- if (refPtr->finalizerCmdNamePtr)
10535
- Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10536
- refPtr->finalizerCmdNamePtr = cmdNamePtr;
10537
- return JIM_OK;
10538
-}
10539
-
10540
-int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr)
10541
-{
10542
- Jim_Reference *refPtr;
10543
-
10544
- if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10545
- return JIM_ERR;
10546
- *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr;
10547
- return JIM_OK;
10548
-}
10549
-
10550
-
10551
-
10552
-static const Jim_HashTableType JimRefMarkHashTableType = {
10553
- JimReferencesHTHashFunction,
10554
- JimReferencesHTKeyDup,
10555
- NULL,
10556
- JimReferencesHTKeyCompare,
10557
- JimReferencesHTKeyDestructor,
10558
- NULL
10559
-};
10560
-
10561
-
10562
-int Jim_Collect(Jim_Interp *interp)
10563
-{
10564
- int collected = 0;
10565
- return collected;
10566
-}
10567
-
10568
-#define JIM_COLLECT_ID_PERIOD 5000
10569
-#define JIM_COLLECT_TIME_PERIOD 300
10570
-
10571
-void Jim_CollectIfNeeded(Jim_Interp *interp)
10572
-{
10573
- unsigned long elapsedId;
10574
- int elapsedTime;
10575
-
10576
- elapsedId = interp->referenceNextId - interp->lastCollectId;
10577
- elapsedTime = time(NULL) - interp->lastCollectTime;
10578
-
10579
-
10580
- if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
10581
- Jim_Collect(interp);
10582
- }
10583
-}
10584
-#endif
1058510424
1058610425
int Jim_IsBigEndian(void)
1058710426
{
1058810427
union {
1058910428
unsigned short s;
@@ -10630,11 +10469,11 @@
1063010469
Jim_IncrRefCount(i->nullScriptObj);
1063110470
Jim_IncrRefCount(i->errorProc);
1063210471
Jim_IncrRefCount(i->trueObj);
1063310472
Jim_IncrRefCount(i->falseObj);
1063410473
10635
-
10474
+
1063610475
Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
1063710476
Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
1063810477
1063910478
Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
1064010479
Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,11 +10491,11 @@
1065210491
{
1065310492
Jim_CallFrame *cf, *cfx;
1065410493
1065510494
Jim_Obj *objPtr, *nextObjPtr;
1065610495
10657
-
10496
+
1065810497
for (cf = i->framePtr; cf; cf = cfx) {
1065910498
cfx = cf->parent;
1066010499
JimFreeCallFrame(i, cf, JIM_FCF_FULL);
1066110500
}
1066210501
@@ -10705,27 +10544,27 @@
1070510544
printf("-------------------------------------\n\n");
1070610545
JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
1070710546
}
1070810547
#endif
1070910548
10710
-
10549
+
1071110550
objPtr = i->freeList;
1071210551
while (objPtr) {
1071310552
nextObjPtr = objPtr->nextObjPtr;
1071410553
Jim_Free(objPtr);
1071510554
objPtr = nextObjPtr;
1071610555
}
1071710556
10718
-
10557
+
1071910558
for (cf = i->freeFramesList; cf; cf = cfx) {
1072010559
cfx = cf->next;
1072110560
if (cf->vars.table)
1072210561
Jim_FreeHashTable(&cf->vars);
1072310562
Jim_Free(cf);
1072410563
}
1072510564
10726
-
10565
+
1072710566
Jim_Free(i);
1072810567
}
1072910568
1073010569
Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
1073110570
{
@@ -10746,25 +10585,25 @@
1074610585
else {
1074710586
if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
1074810587
level = -1;
1074910588
}
1075010589
else {
10751
-
10590
+
1075210591
level = interp->framePtr->level - level;
1075310592
}
1075410593
}
1075510594
}
1075610595
else {
10757
- str = "1";
10596
+ str = "1";
1075810597
level = interp->framePtr->level - 1;
1075910598
}
1076010599
1076110600
if (level == 0) {
1076210601
return interp->topFramePtr;
1076310602
}
1076410603
if (level > 0) {
10765
-
10604
+
1076610605
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
1076710606
if (framePtr->level == level) {
1076810607
return framePtr;
1076910608
}
1077010609
}
@@ -10779,19 +10618,19 @@
1077910618
long level;
1078010619
Jim_CallFrame *framePtr;
1078110620
1078210621
if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
1078310622
if (level <= 0) {
10784
-
10623
+
1078510624
level = interp->framePtr->level + level;
1078610625
}
1078710626
1078810627
if (level == 0) {
1078910628
return interp->topFramePtr;
1079010629
}
1079110630
10792
-
10631
+
1079310632
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
1079410633
if (framePtr->level == level) {
1079510634
return framePtr;
1079610635
}
1079710636
}
@@ -10810,11 +10649,11 @@
1081010649
1081110650
static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
1081210651
{
1081310652
int len;
1081410653
10815
-
10654
+
1081610655
Jim_IncrRefCount(stackTraceObj);
1081710656
Jim_DecrRefCount(interp, interp->stackTrace);
1081810657
interp->stackTrace = stackTraceObj;
1081910658
interp->errorFlag = 1;
1082010659
@@ -10831,32 +10670,32 @@
1083110670
{
1083210671
if (strcmp(procname, "unknown") == 0) {
1083310672
procname = "";
1083410673
}
1083510674
if (!*procname && !Jim_Length(fileNameObj)) {
10836
-
10675
+
1083710676
return;
1083810677
}
1083910678
1084010679
if (Jim_IsShared(interp->stackTrace)) {
1084110680
Jim_DecrRefCount(interp, interp->stackTrace);
1084210681
interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
1084310682
Jim_IncrRefCount(interp->stackTrace);
1084410683
}
1084510684
10846
-
10685
+
1084710686
if (!*procname && Jim_Length(fileNameObj)) {
10848
-
10687
+
1084910688
int len = Jim_ListLength(interp, interp->stackTrace);
1085010689
1085110690
if (len >= 3) {
1085210691
Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
1085310692
if (Jim_Length(objPtr)) {
10854
-
10693
+
1085510694
objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
1085610695
if (Jim_Length(objPtr) == 0) {
10857
-
10696
+
1085810697
ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
1085910698
ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
1086010699
return;
1086110700
}
1086210701
}
@@ -10958,18 +10797,18 @@
1095810797
{
1095910798
jim_wide wideValue;
1096010799
const char *str;
1096110800
1096210801
if (objPtr->typePtr == &coercedDoubleObjType) {
10963
-
10802
+
1096410803
objPtr->typePtr = &intObjType;
1096510804
return JIM_OK;
1096610805
}
1096710806
10968
-
10807
+
1096910808
str = Jim_String(objPtr);
10970
-
10809
+
1097110810
if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
1097210811
if (flags & JIM_ERRMSG) {
1097310812
Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
1097410813
}
1097510814
return JIM_ERR;
@@ -10976,11 +10815,11 @@
1097610815
}
1097710816
if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
1097810817
Jim_SetResultString(interp, "Integer value too big to be represented", -1);
1097910818
return JIM_ERR;
1098010819
}
10981
-
10820
+
1098210821
Jim_FreeIntRep(interp, objPtr);
1098310822
objPtr->typePtr = &intObjType;
1098410823
objPtr->internalRep.wideValue = wideValue;
1098510824
return JIM_OK;
1098610825
}
@@ -11075,17 +10914,17 @@
1107510914
{
1107610915
char buf[JIM_DOUBLE_SPACE + 1];
1107710916
int i;
1107810917
int len = sprintf(buf, "%.12g", value);
1107910918
11080
-
10919
+
1108110920
for (i = 0; i < len; i++) {
1108210921
if (buf[i] == '.' || buf[i] == 'e') {
1108310922
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
1108410923
char *e = strchr(buf, 'e');
1108510924
if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
11086
-
10925
+
1108710926
e += 2;
1108810927
memmove(e, e + 1, len - (e - buf));
1108910928
}
1109010929
#endif
1109110930
break;
@@ -11107,38 +10946,38 @@
1110710946
const char *str;
1110810947
1110910948
str = Jim_String(objPtr);
1111010949
1111110950
#ifdef HAVE_LONG_LONG
11112
-
10951
+
1111310952
#define MIN_INT_IN_DOUBLE -(1LL << 53)
1111410953
#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
1111510954
1111610955
if (objPtr->typePtr == &intObjType
1111710956
&& JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
1111810957
&& JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
1111910958
11120
-
10959
+
1112110960
objPtr->typePtr = &coercedDoubleObjType;
1112210961
return JIM_OK;
1112310962
}
1112410963
else
1112510964
#endif
1112610965
if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
11127
-
10966
+
1112810967
Jim_FreeIntRep(interp, objPtr);
1112910968
objPtr->typePtr = &coercedDoubleObjType;
1113010969
objPtr->internalRep.wideValue = wideValue;
1113110970
return JIM_OK;
1113210971
}
1113310972
else {
11134
-
10973
+
1113510974
if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
1113610975
Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
1113710976
return JIM_ERR;
1113810977
}
11139
-
10978
+
1114010979
Jim_FreeIntRep(interp, objPtr);
1114110980
}
1114210981
objPtr->typePtr = &doubleObjType;
1114310982
objPtr->internalRep.doubleValue = doubleValue;
1114410983
return JIM_OK;
@@ -11170,10 +11009,50 @@
1117011009
objPtr->typePtr = &doubleObjType;
1117111010
objPtr->bytes = NULL;
1117211011
objPtr->internalRep.doubleValue = doubleValue;
1117311012
return objPtr;
1117411013
}
11014
+
11015
+static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
11016
+
11017
+int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr)
11018
+{
11019
+ if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR)
11020
+ return JIM_ERR;
11021
+ *booleanPtr = (int) JimWideValue(objPtr);
11022
+ return JIM_OK;
11023
+}
11024
+
11025
+static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
11026
+{
11027
+ static const char * const falses[] = {
11028
+ "0", "false", "no", "off", NULL
11029
+ };
11030
+ static const char * const trues[] = {
11031
+ "1", "true", "yes", "on", NULL
11032
+ };
11033
+
11034
+ int boolean;
11035
+
11036
+ int index;
11037
+ if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) {
11038
+ boolean = 0;
11039
+ } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) {
11040
+ boolean = 1;
11041
+ } else {
11042
+ if (flags & JIM_ERRMSG) {
11043
+ Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr);
11044
+ }
11045
+ return JIM_ERR;
11046
+ }
11047
+
11048
+
11049
+ Jim_FreeIntRep(interp, objPtr);
11050
+ objPtr->typePtr = &intObjType;
11051
+ objPtr->internalRep.wideValue = boolean;
11052
+ return JIM_OK;
11053
+}
1117511054
1117611055
static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
1117711056
static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
1117811057
static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
1117911058
static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11100,11 @@
1122111100
#define JIM_ELESTR_QUOTE 2
1122211101
static unsigned char ListElementQuotingType(const char *s, int len)
1122311102
{
1122411103
int i, level, blevel, trySimple = 1;
1122511104
11226
-
11105
+
1122711106
if (len == 0)
1122811107
return JIM_ELESTR_BRACE;
1122911108
if (s[0] == '"' || s[0] == '{') {
1123011109
trySimple = 0;
1123111110
goto testbrace;
@@ -11243,20 +11122,20 @@
1124311122
case '\n':
1124411123
case '\t':
1124511124
case '\f':
1124611125
case '\v':
1124711126
trySimple = 0;
11248
-
11127
+
1124911128
case '{':
1125011129
case '}':
1125111130
goto testbrace;
1125211131
}
1125311132
}
1125411133
return JIM_ELESTR_SIMPLE;
1125511134
1125611135
testbrace:
11257
-
11136
+
1125811137
if (s[len - 1] == '\\')
1125911138
return JIM_ELESTR_QUOTE;
1126011139
level = 0;
1126111140
blevel = 0;
1126211141
for (i = 0; i < len; i++) {
@@ -11372,11 +11251,11 @@
1137211251
int i, bufLen, realLength;
1137311252
const char *strRep;
1137411253
char *p;
1137511254
unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
1137611255
11377
-
11256
+
1137811257
if (objc > STATIC_QUOTING_LEN) {
1137911258
quotingType = Jim_Alloc(objc);
1138011259
}
1138111260
else {
1138211261
quotingType = staticQuoting;
@@ -11391,25 +11270,25 @@
1139111270
case JIM_ELESTR_SIMPLE:
1139211271
if (i != 0 || strRep[0] != '#') {
1139311272
bufLen += len;
1139411273
break;
1139511274
}
11396
-
11275
+
1139711276
quotingType[i] = JIM_ELESTR_BRACE;
11398
-
11277
+
1139911278
case JIM_ELESTR_BRACE:
1140011279
bufLen += len + 2;
1140111280
break;
1140211281
case JIM_ELESTR_QUOTE:
1140311282
bufLen += len * 2;
1140411283
break;
1140511284
}
11406
- bufLen++;
11285
+ bufLen++;
1140711286
}
1140811287
bufLen++;
1140911288
11410
-
11289
+
1141111290
p = objPtr->bytes = Jim_Alloc(bufLen + 1);
1141211291
realLength = 0;
1141311292
for (i = 0; i < objc; i++) {
1141411293
int len, qlen;
1141511294
@@ -11436,17 +11315,17 @@
1143611315
qlen = BackslashQuoteString(strRep, len, p);
1143711316
p += qlen;
1143811317
realLength += qlen;
1143911318
break;
1144011319
}
11441
-
11320
+
1144211321
if (i + 1 != objc) {
1144311322
*p++ = ' ';
1144411323
realLength++;
1144511324
}
1144611325
}
11447
- *p = '\0';
11326
+ *p = '\0';
1144811327
objPtr->length = realLength;
1144911328
1145011329
if (quotingType != staticQuoting) {
1145111330
Jim_Free(quotingType);
1145211331
}
@@ -11477,21 +11356,21 @@
1147711356
listObjPtrPtr = JimDictPairs(objPtr, &len);
1147811357
for (i = 0; i < len; i++) {
1147911358
Jim_IncrRefCount(listObjPtrPtr[i]);
1148011359
}
1148111360
11482
-
11361
+
1148311362
Jim_FreeIntRep(interp, objPtr);
1148411363
objPtr->typePtr = &listObjType;
1148511364
objPtr->internalRep.listValue.len = len;
1148611365
objPtr->internalRep.listValue.maxLen = len;
1148711366
objPtr->internalRep.listValue.ele = listObjPtrPtr;
1148811367
1148911368
return JIM_OK;
1149011369
}
1149111370
11492
-
11371
+
1149311372
if (objPtr->typePtr == &sourceObjType) {
1149411373
fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
1149511374
linenr = objPtr->internalRep.sourceValue.lineNumber;
1149611375
}
1149711376
else {
@@ -11498,20 +11377,20 @@
1149811377
fileNameObj = interp->emptyObj;
1149911378
linenr = 1;
1150011379
}
1150111380
Jim_IncrRefCount(fileNameObj);
1150211381
11503
-
11382
+
1150411383
str = Jim_GetString(objPtr, &strLen);
1150511384
1150611385
Jim_FreeIntRep(interp, objPtr);
1150711386
objPtr->typePtr = &listObjType;
1150811387
objPtr->internalRep.listValue.len = 0;
1150911388
objPtr->internalRep.listValue.maxLen = 0;
1151011389
objPtr->internalRep.listValue.ele = NULL;
1151111390
11512
-
11391
+
1151311392
if (strLen) {
1151411393
JimParserInit(&parser, str, strLen, linenr);
1151511394
while (!parser.eof) {
1151611395
Jim_Obj *elementPtr;
1151711396
@@ -11641,11 +11520,11 @@
1164111520
Jim_Obj *compare_script;
1164211521
int rc;
1164311522
1164411523
jim_wide ret = 0;
1164511524
11646
-
11525
+
1164711526
compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
1164811527
Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
1164911528
Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
1165011529
1165111530
rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11542,23 @@
1166311542
int dst = 0;
1166411543
Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
1166511544
1166611545
for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
1166711546
if (comp(&ele[dst], &ele[src]) == 0) {
11668
-
11547
+
1166911548
Jim_DecrRefCount(sort_info->interp, ele[dst]);
1167011549
}
1167111550
else {
11672
-
11551
+
1167311552
dst++;
1167411553
}
1167511554
ele[dst] = ele[src];
1167611555
}
11677
-
11556
+
1167811557
ele[++dst] = ele[src];
1167911558
11680
-
11559
+
1168111560
listObjPtr->internalRep.listValue.len = dst;
1168211561
}
1168311562
1168411563
1168511564
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11572,11 @@
1169311572
int rc;
1169411573
1169511574
JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
1169611575
SetListFromAny(interp, listObjPtr);
1169711576
11698
-
11577
+
1169911578
prev_info = sort_info;
1170011579
sort_info = info;
1170111580
1170211581
vector = listObjPtr->internalRep.listValue.ele;
1170311582
len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11595,17 @@
1171611595
break;
1171711596
case JIM_LSORT_COMMAND:
1171811597
fn = ListSortCommand;
1171911598
break;
1172011599
default:
11721
- fn = NULL;
11600
+ fn = NULL;
1172211601
JimPanic((1, "ListSort called with invalid sort type"));
11723
- return -1;
11602
+ return -1;
1172411603
}
1172511604
1172611605
if (info->indexed) {
11727
-
11606
+
1172811607
info->subfn = fn;
1172911608
fn = ListSortIndexHelper;
1173011609
}
1173111610
1173211611
if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11629,11 @@
1175011629
int i;
1175111630
Jim_Obj **point;
1175211631
1175311632
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
1175411633
if (requiredLen < 2) {
11755
-
11634
+
1175611635
requiredLen = 4;
1175711636
}
1175811637
else {
1175911638
requiredLen *= 2;
1176011639
}
@@ -11936,34 +11815,34 @@
1193611815
for (i = 0; i < objc; i++)
1193711816
ListAppendList(objPtr, objv[i]);
1193811817
return objPtr;
1193911818
}
1194011819
else {
11941
-
11820
+
1194211821
int len = 0, objLen;
1194311822
char *bytes, *p;
1194411823
11945
-
11824
+
1194611825
for (i = 0; i < objc; i++) {
1194711826
len += Jim_Length(objv[i]);
1194811827
}
1194911828
if (objc)
1195011829
len += objc - 1;
11951
-
11830
+
1195211831
p = bytes = Jim_Alloc(len + 1);
1195311832
for (i = 0; i < objc; i++) {
1195411833
const char *s = Jim_GetString(objv[i], &objLen);
1195511834
11956
-
11835
+
1195711836
while (objLen && isspace(UCHAR(*s))) {
1195811837
s++;
1195911838
objLen--;
1196011839
len--;
1196111840
}
11962
-
11841
+
1196311842
while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11964
-
11843
+
1196511844
if (objLen > 1 && s[objLen - 2] == '\\') {
1196611845
break;
1196711846
}
1196811847
objLen--;
1196911848
len--;
@@ -11990,11 +11869,11 @@
1199011869
int len, rangeLen;
1199111870
1199211871
if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
1199311872
Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
1199411873
return NULL;
11995
- len = Jim_ListLength(interp, listObjPtr);
11874
+ len = Jim_ListLength(interp, listObjPtr);
1199611875
first = JimRelToAbsIndex(len, first);
1199711876
last = JimRelToAbsIndex(len, last);
1199811877
JimRelToAbsRange(len, &first, &last, &rangeLen);
1199911878
if (first == 0 && last == len) {
1200011879
return listObjPtr;
@@ -12030,16 +11909,16 @@
1203011909
{
1203111910
Jim_DecrRefCount(interp, (Jim_Obj *)val);
1203211911
}
1203311912
1203411913
static const Jim_HashTableType JimDictHashTableType = {
12035
- JimObjectHTHashFunction,
12036
- JimObjectHTKeyValDup,
12037
- JimObjectHTKeyValDup,
12038
- JimObjectHTKeyCompare,
12039
- JimObjectHTKeyValDestructor,
12040
- JimObjectHTKeyValDestructor
11914
+ JimObjectHTHashFunction,
11915
+ JimObjectHTKeyValDup,
11916
+ JimObjectHTKeyValDup,
11917
+ JimObjectHTKeyCompare,
11918
+ JimObjectHTKeyValDestructor,
11919
+ JimObjectHTKeyValDestructor
1204111920
};
1204211921
1204311922
static const Jim_ObjType dictObjType = {
1204411923
"dict",
1204511924
FreeDictInternalRep,
@@ -12060,17 +11939,17 @@
1206011939
{
1206111940
Jim_HashTable *ht, *dupHt;
1206211941
Jim_HashTableIterator htiter;
1206311942
Jim_HashEntry *he;
1206411943
12065
-
11944
+
1206611945
ht = srcPtr->internalRep.ptr;
1206711946
dupHt = Jim_Alloc(sizeof(*dupHt));
1206811947
Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
1206911948
if (ht->size != 0)
1207011949
Jim_ExpandHashTable(dupHt, ht->size);
12071
-
11950
+
1207211951
JimInitHashTableIterator(ht, &htiter);
1207311952
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1207411953
Jim_AddHashEntry(dupHt, he->key, he->u.val);
1207511954
}
1207611955
@@ -12086,11 +11965,11 @@
1208611965
Jim_Obj **objv;
1208711966
int i;
1208811967
1208911968
ht = dictPtr->internalRep.ptr;
1209011969
12091
-
11970
+
1209211971
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
1209311972
JimInitHashTableIterator(ht, &htiter);
1209411973
i = 0;
1209511974
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1209611975
objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11979,15 @@
1210011979
return objv;
1210111980
}
1210211981
1210311982
static void UpdateStringOfDict(struct Jim_Obj *objPtr)
1210411983
{
12105
-
11984
+
1210611985
int len;
1210711986
Jim_Obj **objv = JimDictPairs(objPtr, &len);
1210811987
12109
-
11988
+
1211011989
JimMakeListStringRep(objPtr, objv, len);
1211111990
1211211991
Jim_Free(objv);
1211311992
}
1211411993
@@ -12122,18 +12001,18 @@
1212212001
1212312002
if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
1212412003
Jim_String(objPtr);
1212512004
}
1212612005
12127
-
12006
+
1212812007
listlen = Jim_ListLength(interp, objPtr);
1212912008
if (listlen % 2) {
1213012009
Jim_SetResultString(interp, "missing value to go with key", -1);
1213112010
return JIM_ERR;
1213212011
}
1213312012
else {
12134
-
12013
+
1213512014
Jim_HashTable *ht;
1213612015
int i;
1213712016
1213812017
ht = Jim_Alloc(sizeof(*ht));
1213912018
Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12037,11 @@
1215812037
static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
1215912038
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
1216012039
{
1216112040
Jim_HashTable *ht = objPtr->internalRep.ptr;
1216212041
12163
- if (valueObjPtr == NULL) {
12042
+ if (valueObjPtr == NULL) {
1216412043
return Jim_DeleteHashEntry(ht, keyObjPtr);
1216512044
}
1216612045
Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
1216712046
return JIM_OK;
1216812047
}
@@ -12209,12 +12088,14 @@
1220912088
if (flags & JIM_ERRMSG) {
1221012089
Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
1221112090
}
1221212091
return JIM_ERR;
1221312092
}
12214
- *objPtrPtr = he->u.val;
12215
- return JIM_OK;
12093
+ else {
12094
+ *objPtrPtr = Jim_GetHashEntryVal(he);
12095
+ return JIM_OK;
12096
+ }
1221612097
}
1221712098
1221812099
1221912100
int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
1222012101
{
@@ -12258,11 +12139,11 @@
1225812139
int shared, i;
1225912140
1226012141
varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
1226112142
if (objPtr == NULL) {
1226212143
if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12263
-
12144
+
1226412145
return JIM_ERR;
1226512146
}
1226612147
varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
1226712148
if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
1226812149
Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12153,26 @@
1227212153
if ((shared = Jim_IsShared(objPtr)))
1227312154
varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
1227412155
for (i = 0; i < keyc; i++) {
1227512156
dictObjPtr = objPtr;
1227612157
12277
-
12158
+
1227812159
if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
1227912160
goto err;
1228012161
}
1228112162
1228212163
if (i == keyc - 1) {
12283
-
12164
+
1228412165
if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
1228512166
if (newObjPtr || (flags & JIM_MUSTEXIST)) {
1228612167
goto err;
1228712168
}
1228812169
}
1228912170
break;
1229012171
}
1229112172
12292
-
12173
+
1229312174
Jim_InvalidateStringRep(dictObjPtr);
1229412175
if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
1229512176
newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
1229612177
if (Jim_IsShared(objPtr)) {
1229712178
objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12185,11 @@
1230412185
}
1230512186
objPtr = Jim_NewDictObj(interp, NULL, 0);
1230612187
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
1230712188
}
1230812189
}
12309
-
12190
+
1231012191
Jim_InvalidateStringRep(objPtr);
1231112192
Jim_InvalidateStringRep(varObjPtr);
1231212193
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
1231312194
goto err;
1231412195
}
@@ -12341,11 +12222,11 @@
1234112222
char buf[JIM_INTEGER_SPACE + 1];
1234212223
if (objPtr->internalRep.intValue >= 0) {
1234312224
sprintf(buf, "%d", objPtr->internalRep.intValue);
1234412225
}
1234512226
else {
12346
-
12227
+
1234712228
sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
1234812229
}
1234912230
JimSetStringBytes(objPtr, buf);
1235012231
}
1235112232
}
@@ -12354,14 +12235,14 @@
1235412235
{
1235512236
int idx, end = 0;
1235612237
const char *str;
1235712238
char *endptr;
1235812239
12359
-
12240
+
1236012241
str = Jim_String(objPtr);
1236112242
12362
-
12243
+
1236312244
if (strncmp(str, "end", 3) == 0) {
1236412245
end = 1;
1236512246
str += 3;
1236612247
idx = 0;
1236712248
}
@@ -12372,21 +12253,21 @@
1237212253
goto badindex;
1237312254
}
1237412255
str = endptr;
1237512256
}
1237612257
12377
-
12258
+
1237812259
if (*str == '+' || *str == '-') {
1237912260
int sign = (*str == '+' ? 1 : -1);
1238012261
1238112262
idx += sign * jim_strtol(++str, &endptr);
1238212263
if (str == endptr || *endptr) {
1238312264
goto badindex;
1238412265
}
1238512266
str = endptr;
1238612267
}
12387
-
12268
+
1238812269
while (isspace(UCHAR(*str))) {
1238912270
str++;
1239012271
}
1239112272
if (*str) {
1239212273
goto badindex;
@@ -12394,19 +12275,19 @@
1239412275
if (end) {
1239512276
if (idx > 0) {
1239612277
idx = INT_MAX;
1239712278
}
1239812279
else {
12399
-
12280
+
1240012281
idx--;
1240112282
}
1240212283
}
1240312284
else if (idx < 0) {
1240412285
idx = -INT_MAX;
1240512286
}
1240612287
12407
-
12288
+
1240812289
Jim_FreeIntRep(interp, objPtr);
1240912290
objPtr->typePtr = &indexObjType;
1241012291
objPtr->internalRep.intValue = idx;
1241112292
return JIM_OK;
1241212293
@@ -12416,11 +12297,11 @@
1241612297
return JIM_ERR;
1241712298
}
1241812299
1241912300
int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
1242012301
{
12421
-
12302
+
1242212303
if (objPtr->typePtr == &intObjType) {
1242312304
jim_wide val = JimWideValue(objPtr);
1242412305
1242512306
if (val < 0)
1242612307
*indexPtr = -INT_MAX;
@@ -12473,18 +12354,18 @@
1247312354
static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1247412355
{
1247512356
int returnCode;
1247612357
jim_wide wideValue;
1247712358
12478
-
12359
+
1247912360
if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
1248012361
returnCode = (int)wideValue;
1248112362
else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
1248212363
Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
1248312364
return JIM_ERR;
1248412365
}
12485
-
12366
+
1248612367
Jim_FreeIntRep(interp, objPtr);
1248712368
objPtr->typePtr = &returnCodeObjType;
1248812369
objPtr->internalRep.intValue = returnCode;
1248912370
return JIM_OK;
1249012371
}
@@ -12498,19 +12379,20 @@
1249812379
}
1249912380
1250012381
static int JimParseExprOperator(struct JimParserCtx *pc);
1250112382
static int JimParseExprNumber(struct JimParserCtx *pc);
1250212383
static int JimParseExprIrrational(struct JimParserCtx *pc);
12384
+static int JimParseExprBoolean(struct JimParserCtx *pc);
1250312385
1250412386
1250512387
1250612388
1250712389
enum
1250812390
{
12509
-
12510
-
12511
- JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
12391
+
12392
+
12393
+ JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
1251212394
JIM_EXPROP_DIV,
1251312395
JIM_EXPROP_MOD,
1251412396
JIM_EXPROP_SUB,
1251512397
JIM_EXPROP_ADD,
1251612398
JIM_EXPROP_LSHIFT,
@@ -12521,66 +12403,67 @@
1252112403
JIM_EXPROP_GT,
1252212404
JIM_EXPROP_LTE,
1252312405
JIM_EXPROP_GTE,
1252412406
JIM_EXPROP_NUMEQ,
1252512407
JIM_EXPROP_NUMNE,
12526
- JIM_EXPROP_BITAND,
12408
+ JIM_EXPROP_BITAND,
1252712409
JIM_EXPROP_BITXOR,
1252812410
JIM_EXPROP_BITOR,
1252912411
12530
-
12531
- JIM_EXPROP_LOGICAND,
12412
+
12413
+ JIM_EXPROP_LOGICAND,
1253212414
JIM_EXPROP_LOGICAND_LEFT,
1253312415
JIM_EXPROP_LOGICAND_RIGHT,
1253412416
12535
-
12536
- JIM_EXPROP_LOGICOR,
12417
+
12418
+ JIM_EXPROP_LOGICOR,
1253712419
JIM_EXPROP_LOGICOR_LEFT,
1253812420
JIM_EXPROP_LOGICOR_RIGHT,
1253912421
12540
-
12541
-
12542
- JIM_EXPROP_TERNARY,
12422
+
12423
+
12424
+ JIM_EXPROP_TERNARY,
1254312425
JIM_EXPROP_TERNARY_LEFT,
1254412426
JIM_EXPROP_TERNARY_RIGHT,
1254512427
12546
-
12547
- JIM_EXPROP_COLON,
12428
+
12429
+ JIM_EXPROP_COLON,
1254812430
JIM_EXPROP_COLON_LEFT,
1254912431
JIM_EXPROP_COLON_RIGHT,
1255012432
12551
- JIM_EXPROP_POW,
12433
+ JIM_EXPROP_POW,
1255212434
1255312435
12554
- JIM_EXPROP_STREQ,
12436
+ JIM_EXPROP_STREQ,
1255512437
JIM_EXPROP_STRNE,
1255612438
JIM_EXPROP_STRIN,
1255712439
JIM_EXPROP_STRNI,
1255812440
1255912441
12560
- JIM_EXPROP_NOT,
12442
+ JIM_EXPROP_NOT,
1256112443
JIM_EXPROP_BITNOT,
1256212444
JIM_EXPROP_UNARYMINUS,
1256312445
JIM_EXPROP_UNARYPLUS,
1256412446
12565
-
12566
- JIM_EXPROP_FUNC_FIRST,
12447
+
12448
+ JIM_EXPROP_FUNC_FIRST,
1256712449
JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
1256812450
JIM_EXPROP_FUNC_WIDE,
1256912451
JIM_EXPROP_FUNC_ABS,
1257012452
JIM_EXPROP_FUNC_DOUBLE,
1257112453
JIM_EXPROP_FUNC_ROUND,
1257212454
JIM_EXPROP_FUNC_RAND,
1257312455
JIM_EXPROP_FUNC_SRAND,
1257412456
12575
-
12576
- JIM_EXPROP_FUNC_SIN,
12457
+
12458
+ JIM_EXPROP_FUNC_SIN,
1257712459
JIM_EXPROP_FUNC_COS,
1257812460
JIM_EXPROP_FUNC_TAN,
1257912461
JIM_EXPROP_FUNC_ASIN,
1258012462
JIM_EXPROP_FUNC_ACOS,
1258112463
JIM_EXPROP_FUNC_ATAN,
12464
+ JIM_EXPROP_FUNC_ATAN2,
1258212465
JIM_EXPROP_FUNC_SINH,
1258312466
JIM_EXPROP_FUNC_COSH,
1258412467
JIM_EXPROP_FUNC_TANH,
1258512468
JIM_EXPROP_FUNC_CEIL,
1258612469
JIM_EXPROP_FUNC_FLOOR,
@@ -12587,10 +12470,12 @@
1258712470
JIM_EXPROP_FUNC_EXP,
1258812471
JIM_EXPROP_FUNC_LOG,
1258912472
JIM_EXPROP_FUNC_LOG10,
1259012473
JIM_EXPROP_FUNC_SQRT,
1259112474
JIM_EXPROP_FUNC_POW,
12475
+ JIM_EXPROP_FUNC_HYPOT,
12476
+ JIM_EXPROP_FUNC_FMOD,
1259212477
};
1259312478
1259412479
struct JimExprState
1259512480
{
1259612481
Jim_Obj **stack;
@@ -12667,11 +12552,15 @@
1266712552
case JIM_EXPROP_UNARYPLUS:
1266812553
dC = dA;
1266912554
intresult = 0;
1267012555
break;
1267112556
case JIM_EXPROP_FUNC_ABS:
12557
+#ifdef JIM_MATH_FUNCTIONS
12558
+ dC = fabs(dA);
12559
+#else
1267212560
dC = dA >= 0 ? dA : -dA;
12561
+#endif
1267312562
intresult = 0;
1267412563
break;
1267512564
case JIM_EXPROP_UNARYMINUS:
1267612565
dC = -dA;
1267712566
intresult = 0;
@@ -12859,16 +12748,16 @@
1285912748
}
1286012749
}
1286112750
break;
1286212751
case JIM_EXPROP_ROTL:
1286312752
case JIM_EXPROP_ROTR:{
12864
-
12753
+
1286512754
unsigned long uA = (unsigned long)wA;
1286612755
unsigned long uB = (unsigned long)wB;
1286712756
const unsigned int S = sizeof(unsigned long) * 8;
1286812757
12869
-
12758
+
1287012759
uB %= S;
1287112760
1287212761
if (e->opcode == JIM_EXPROP_ROTR) {
1287312762
uB = S - uB;
1287412763
}
@@ -12890,11 +12779,10 @@
1289012779
1289112780
1289212781
1289312782
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
1289412783
{
12895
- int intresult = 1;
1289612784
int rc = JIM_OK;
1289712785
double dA, dB, dC = 0;
1289812786
jim_wide wA, wB, wC = 0;
1289912787
1290012788
Jim_Obj *B = ExprPop(e);
@@ -12902,30 +12790,36 @@
1290212790
1290312791
if ((A->typePtr != &doubleObjType || A->bytes) &&
1290412792
(B->typePtr != &doubleObjType || B->bytes) &&
1290512793
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
1290612794
12907
-
12795
+
1290812796
1290912797
switch (e->opcode) {
1291012798
case JIM_EXPROP_POW:
1291112799
case JIM_EXPROP_FUNC_POW:
12800
+ if (wA == 0 && wB < 0) {
12801
+ Jim_SetResultString(interp, "exponentiation of zero by negative power", -1);
12802
+ rc = JIM_ERR;
12803
+ goto done;
12804
+ }
1291212805
wC = JimPowWide(wA, wB);
12913
- break;
12806
+ goto intresult;
1291412807
case JIM_EXPROP_ADD:
1291512808
wC = wA + wB;
12916
- break;
12809
+ goto intresult;
1291712810
case JIM_EXPROP_SUB:
1291812811
wC = wA - wB;
12919
- break;
12812
+ goto intresult;
1292012813
case JIM_EXPROP_MUL:
1292112814
wC = wA * wB;
12922
- break;
12815
+ goto intresult;
1292312816
case JIM_EXPROP_DIV:
1292412817
if (wB == 0) {
1292512818
Jim_SetResultString(interp, "Division by zero", -1);
1292612819
rc = JIM_ERR;
12820
+ goto done;
1292712821
}
1292812822
else {
1292912823
if (wB < 0) {
1293012824
wB = -wB;
1293112825
wA = -wA;
@@ -12932,55 +12826,67 @@
1293212826
}
1293312827
wC = wA / wB;
1293412828
if (wA % wB < 0) {
1293512829
wC--;
1293612830
}
12831
+ goto intresult;
1293712832
}
12938
- break;
1293912833
case JIM_EXPROP_LT:
1294012834
wC = wA < wB;
12941
- break;
12835
+ goto intresult;
1294212836
case JIM_EXPROP_GT:
1294312837
wC = wA > wB;
12944
- break;
12838
+ goto intresult;
1294512839
case JIM_EXPROP_LTE:
1294612840
wC = wA <= wB;
12947
- break;
12841
+ goto intresult;
1294812842
case JIM_EXPROP_GTE:
1294912843
wC = wA >= wB;
12950
- break;
12844
+ goto intresult;
1295112845
case JIM_EXPROP_NUMEQ:
1295212846
wC = wA == wB;
12953
- break;
12847
+ goto intresult;
1295412848
case JIM_EXPROP_NUMNE:
1295512849
wC = wA != wB;
12956
- break;
12957
- default:
12958
- abort();
12850
+ goto intresult;
1295912851
}
1296012852
}
12961
- else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12962
- intresult = 0;
12853
+ if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
1296312854
switch (e->opcode) {
12855
+#ifndef JIM_MATH_FUNCTIONS
1296412856
case JIM_EXPROP_POW:
1296512857
case JIM_EXPROP_FUNC_POW:
12966
-#ifdef JIM_MATH_FUNCTIONS
12967
- dC = pow(dA, dB);
12968
-#else
12858
+ case JIM_EXPROP_FUNC_ATAN2:
12859
+ case JIM_EXPROP_FUNC_HYPOT:
12860
+ case JIM_EXPROP_FUNC_FMOD:
1296912861
Jim_SetResultString(interp, "unsupported", -1);
1297012862
rc = JIM_ERR;
12863
+ goto done;
12864
+#else
12865
+ case JIM_EXPROP_POW:
12866
+ case JIM_EXPROP_FUNC_POW:
12867
+ dC = pow(dA, dB);
12868
+ goto doubleresult;
12869
+ case JIM_EXPROP_FUNC_ATAN2:
12870
+ dC = atan2(dA, dB);
12871
+ goto doubleresult;
12872
+ case JIM_EXPROP_FUNC_HYPOT:
12873
+ dC = hypot(dA, dB);
12874
+ goto doubleresult;
12875
+ case JIM_EXPROP_FUNC_FMOD:
12876
+ dC = fmod(dA, dB);
12877
+ goto doubleresult;
1297112878
#endif
12972
- break;
1297312879
case JIM_EXPROP_ADD:
1297412880
dC = dA + dB;
12975
- break;
12881
+ goto doubleresult;
1297612882
case JIM_EXPROP_SUB:
1297712883
dC = dA - dB;
12978
- break;
12884
+ goto doubleresult;
1297912885
case JIM_EXPROP_MUL:
1298012886
dC = dA * dB;
12981
- break;
12887
+ goto doubleresult;
1298212888
case JIM_EXPROP_DIV:
1298312889
if (dB == 0) {
1298412890
#ifdef INFINITY
1298512891
dC = dA < 0 ? -INFINITY : INFINITY;
1298612892
#else
@@ -12988,83 +12894,70 @@
1298812894
#endif
1298912895
}
1299012896
else {
1299112897
dC = dA / dB;
1299212898
}
12993
- break;
12899
+ goto doubleresult;
1299412900
case JIM_EXPROP_LT:
1299512901
wC = dA < dB;
12996
- intresult = 1;
12997
- break;
12902
+ goto intresult;
1299812903
case JIM_EXPROP_GT:
1299912904
wC = dA > dB;
13000
- intresult = 1;
13001
- break;
12905
+ goto intresult;
1300212906
case JIM_EXPROP_LTE:
1300312907
wC = dA <= dB;
13004
- intresult = 1;
13005
- break;
12908
+ goto intresult;
1300612909
case JIM_EXPROP_GTE:
1300712910
wC = dA >= dB;
13008
- intresult = 1;
13009
- break;
12911
+ goto intresult;
1301012912
case JIM_EXPROP_NUMEQ:
1301112913
wC = dA == dB;
13012
- intresult = 1;
13013
- break;
12914
+ goto intresult;
1301412915
case JIM_EXPROP_NUMNE:
1301512916
wC = dA != dB;
13016
- intresult = 1;
13017
- break;
13018
- default:
13019
- abort();
12917
+ goto intresult;
1302012918
}
1302112919
}
1302212920
else {
13023
-
1302412921
13025
-
12922
+
12923
+
1302612924
int i = Jim_StringCompareObj(interp, A, B, 0);
1302712925
1302812926
switch (e->opcode) {
1302912927
case JIM_EXPROP_LT:
1303012928
wC = i < 0;
13031
- break;
12929
+ goto intresult;
1303212930
case JIM_EXPROP_GT:
1303312931
wC = i > 0;
13034
- break;
12932
+ goto intresult;
1303512933
case JIM_EXPROP_LTE:
1303612934
wC = i <= 0;
13037
- break;
12935
+ goto intresult;
1303812936
case JIM_EXPROP_GTE:
1303912937
wC = i >= 0;
13040
- break;
12938
+ goto intresult;
1304112939
case JIM_EXPROP_NUMEQ:
1304212940
wC = i == 0;
13043
- break;
12941
+ goto intresult;
1304412942
case JIM_EXPROP_NUMNE:
1304512943
wC = i != 0;
13046
- break;
13047
- default:
13048
- rc = JIM_ERR;
13049
- break;
12944
+ goto intresult;
1305012945
}
1305112946
}
1305212947
13053
- if (rc == JIM_OK) {
13054
- if (intresult) {
13055
- ExprPush(e, Jim_NewIntObj(interp, wC));
13056
- }
13057
- else {
13058
- ExprPush(e, Jim_NewDoubleObj(interp, dC));
13059
- }
13060
- }
13061
-
12948
+ rc = JIM_ERR;
12949
+done:
1306212950
Jim_DecrRefCount(interp, A);
1306312951
Jim_DecrRefCount(interp, B);
13064
-
1306512952
return rc;
12953
+intresult:
12954
+ ExprPush(e, Jim_NewIntObj(interp, wC));
12955
+ goto done;
12956
+doubleresult:
12957
+ ExprPush(e, Jim_NewDoubleObj(interp, dC));
12958
+ goto done;
1306612959
}
1306712960
1306812961
static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
1306912962
{
1307012963
int listlen;
@@ -13113,16 +13006,20 @@
1311313006
1311413007
static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
1311513008
{
1311613009
long l;
1311713010
double d;
13011
+ int b;
1311813012
1311913013
if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
1312013014
return l != 0;
1312113015
}
1312213016
if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
1312313017
return d != 0;
13018
+ }
13019
+ if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
13020
+ return b != 0;
1312413021
}
1312513022
return -1;
1312613023
}
1312713024
1312813025
static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
@@ -13131,21 +13028,21 @@
1313113028
Jim_Obj *A = ExprPop(e);
1313213029
int rc = JIM_OK;
1313313030
1313413031
switch (ExprBool(interp, A)) {
1313513032
case 0:
13136
-
13033
+
1313713034
e->skip = JimWideValue(skip);
1313813035
ExprPush(e, Jim_NewIntObj(interp, 0));
1313913036
break;
1314013037
1314113038
case 1:
13142
-
13039
+
1314313040
break;
1314413041
1314513042
case -1:
13146
-
13043
+
1314713044
rc = JIM_ERR;
1314813045
}
1314913046
Jim_DecrRefCount(interp, A);
1315013047
Jim_DecrRefCount(interp, skip);
1315113048
@@ -13158,21 +13055,21 @@
1315813055
Jim_Obj *A = ExprPop(e);
1315913056
int rc = JIM_OK;
1316013057
1316113058
switch (ExprBool(interp, A)) {
1316213059
case 0:
13163
-
13060
+
1316413061
break;
1316513062
1316613063
case 1:
13167
-
13064
+
1316813065
e->skip = JimWideValue(skip);
1316913066
ExprPush(e, Jim_NewIntObj(interp, 1));
1317013067
break;
1317113068
1317213069
case -1:
13173
-
13070
+
1317413071
rc = JIM_ERR;
1317513072
break;
1317613073
}
1317713074
Jim_DecrRefCount(interp, A);
1317813075
Jim_DecrRefCount(interp, skip);
@@ -13193,11 +13090,11 @@
1319313090
case 1:
1319413091
ExprPush(e, Jim_NewIntObj(interp, 1));
1319513092
break;
1319613093
1319713094
case -1:
13198
-
13095
+
1319913096
rc = JIM_ERR;
1320013097
break;
1320113098
}
1320213099
Jim_DecrRefCount(interp, A);
1320313100
@@ -13208,27 +13105,27 @@
1320813105
{
1320913106
Jim_Obj *skip = ExprPop(e);
1321013107
Jim_Obj *A = ExprPop(e);
1321113108
int rc = JIM_OK;
1321213109
13213
-
13110
+
1321413111
ExprPush(e, A);
1321513112
1321613113
switch (ExprBool(interp, A)) {
1321713114
case 0:
13218
-
13115
+
1321913116
e->skip = JimWideValue(skip);
13220
-
13117
+
1322113118
ExprPush(e, Jim_NewIntObj(interp, 0));
1322213119
break;
1322313120
1322413121
case 1:
13225
-
13122
+
1322613123
break;
1322713124
1322813125
case -1:
13229
-
13126
+
1323013127
rc = JIM_ERR;
1323113128
break;
1323213129
}
1323313130
Jim_DecrRefCount(interp, A);
1323413131
Jim_DecrRefCount(interp, skip);
@@ -13240,15 +13137,15 @@
1324013137
{
1324113138
Jim_Obj *skip = ExprPop(e);
1324213139
Jim_Obj *B = ExprPop(e);
1324313140
Jim_Obj *A = ExprPop(e);
1324413141
13245
-
13142
+
1324613143
if (ExprBool(interp, A)) {
13247
-
13144
+
1324813145
e->skip = JimWideValue(skip);
13249
-
13146
+
1325013147
ExprPush(e, B);
1325113148
}
1325213149
1325313150
Jim_DecrRefCount(interp, skip);
1325413151
Jim_DecrRefCount(interp, A);
@@ -13264,15 +13161,16 @@
1326413161
enum
1326513162
{
1326613163
LAZY_NONE,
1326713164
LAZY_OP,
1326813165
LAZY_LEFT,
13269
- LAZY_RIGHT
13166
+ LAZY_RIGHT,
13167
+ RIGHT_ASSOC,
1327013168
};
1327113169
13272
-#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13273
-#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13170
+#define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1}
13171
+#define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, LAZY_NONE)
1327413172
1327513173
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
1327613174
OPRINIT("*", 110, 2, JimExprOpBin),
1327713175
OPRINIT("/", 110, 2, JimExprOpBin),
1327813176
OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,27 +13194,28 @@
1329613194
1329713195
OPRINIT("&", 50, 2, JimExprOpIntBin),
1329813196
OPRINIT("^", 49, 2, JimExprOpIntBin),
1329913197
OPRINIT("|", 48, 2, JimExprOpIntBin),
1330013198
13301
- OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13302
- OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13303
- OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13304
-
13305
- OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13306
- OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13307
- OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13308
-
13309
- OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13310
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13311
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13312
-
13313
- OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13314
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13315
- OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13316
-
13317
- OPRINIT("**", 250, 2, JimExprOpBin),
13199
+ OPRINIT_ATTR("&&", 10, 2, NULL, LAZY_OP),
13200
+ OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13201
+ OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13202
+
13203
+ OPRINIT_ATTR("||", 9, 2, NULL, LAZY_OP),
13204
+ OPRINIT_ATTR(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13205
+ OPRINIT_ATTR(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13206
+
13207
+ OPRINIT_ATTR("?", 5, 2, JimExprOpNull, LAZY_OP),
13208
+ OPRINIT_ATTR(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13209
+ OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13210
+
13211
+ OPRINIT_ATTR(":", 5, 2, JimExprOpNull, LAZY_OP),
13212
+ OPRINIT_ATTR(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13213
+ OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13214
+
13215
+
13216
+ OPRINIT_ATTR("**", 120, 2, JimExprOpBin, RIGHT_ASSOC),
1331813217
1331913218
OPRINIT("eq", 60, 2, JimExprOpStrBin),
1332013219
OPRINIT("ne", 60, 2, JimExprOpStrBin),
1332113220
1332213221
OPRINIT("in", 55, 2, JimExprOpStrBin),
@@ -13342,10 +13241,11 @@
1334213241
OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
1334313242
OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
1334413243
OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
1334513244
OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
1334613245
OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13246
+ OPRINIT("atan2", 200, 2, JimExprOpBin),
1334713247
OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
1334813248
OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
1334913249
OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
1335013250
OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
1335113251
OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
@@ -13352,10 +13252,12 @@
1335213252
OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
1335313253
OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
1335413254
OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
1335513255
OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
1335613256
OPRINIT("pow", 200, 2, JimExprOpBin),
13257
+ OPRINIT("hypot", 200, 2, JimExprOpBin),
13258
+ OPRINIT("fmod", 200, 2, JimExprOpBin),
1335713259
#endif
1335813260
};
1335913261
#undef OPRINIT
1336013262
#undef OPRINIT_LAZY
1336113263
@@ -13362,20 +13264,20 @@
1336213264
#define JIM_EXPR_OPERATORS_NUM \
1336313265
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1336413266
1336513267
static int JimParseExpression(struct JimParserCtx *pc)
1336613268
{
13367
-
13269
+
1336813270
while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
1336913271
if (*pc->p == '\n') {
1337013272
pc->linenr++;
1337113273
}
1337213274
pc->p++;
1337313275
pc->len--;
1337413276
}
1337513277
13376
-
13278
+
1337713279
pc->tline = pc->linenr;
1337813280
pc->tstart = pc->p;
1337913281
1338013282
if (pc->len == 0) {
1338113283
pc->tend = pc->p;
@@ -13401,11 +13303,11 @@
1340113303
return JimParseCmd(pc);
1340213304
case '$':
1340313305
if (JimParseVar(pc) == JIM_ERR)
1340413306
return JimParseExprOperator(pc);
1340513307
else {
13406
-
13308
+
1340713309
if (pc->tt == JIM_TT_EXPRSUGAR) {
1340813310
return JIM_ERR;
1340913311
}
1341013312
return JIM_OK;
1341113313
}
@@ -13430,10 +13332,18 @@
1343013332
case 'N':
1343113333
case 'I':
1343213334
case 'n':
1343313335
case 'i':
1343413336
if (JimParseExprIrrational(pc) == JIM_ERR)
13337
+ if (JimParseExprBoolean(pc) == JIM_ERR)
13338
+ return JimParseExprOperator(pc);
13339
+ break;
13340
+ case 't':
13341
+ case 'f':
13342
+ case 'o':
13343
+ case 'y':
13344
+ if (JimParseExprBoolean(pc) == JIM_ERR)
1343513345
return JimParseExprOperator(pc);
1343613346
break;
1343713347
default:
1343813348
return JimParseExprOperator(pc);
1343913349
break;
@@ -13443,21 +13353,21 @@
1344313353
1344413354
static int JimParseExprNumber(struct JimParserCtx *pc)
1344513355
{
1344613356
char *end;
1344713357
13448
-
13358
+
1344913359
pc->tt = JIM_TT_EXPR_INT;
1345013360
1345113361
jim_strtoull(pc->p, (char **)&pc->p);
13452
-
13362
+
1345313363
if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13454
- if (strtod(pc->tstart, &end)) { }
13364
+ if (strtod(pc->tstart, &end)) { }
1345513365
if (end == pc->tstart)
1345613366
return JIM_ERR;
1345713367
if (end > pc->p) {
13458
-
13368
+
1345913369
pc->tt = JIM_TT_EXPR_DOUBLE;
1346013370
pc->p = end;
1346113371
}
1346213372
}
1346313373
pc->tend = pc->p - 1;
@@ -13481,17 +13391,38 @@
1348113391
return JIM_OK;
1348213392
}
1348313393
}
1348413394
return JIM_ERR;
1348513395
}
13396
+
13397
+static int JimParseExprBoolean(struct JimParserCtx *pc)
13398
+{
13399
+ const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL };
13400
+ const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 };
13401
+ int i;
13402
+
13403
+ for (i = 0; booleans[i]; i++) {
13404
+ const char *boolean = booleans[i];
13405
+ int length = lengths[i];
13406
+
13407
+ if (strncmp(boolean, pc->p, length) == 0) {
13408
+ pc->p += length;
13409
+ pc->len -= length;
13410
+ pc->tend = pc->p - 1;
13411
+ pc->tt = JIM_TT_EXPR_BOOLEAN;
13412
+ return JIM_OK;
13413
+ }
13414
+ }
13415
+ return JIM_ERR;
13416
+}
1348613417
1348713418
static int JimParseExprOperator(struct JimParserCtx *pc)
1348813419
{
1348913420
int i;
1349013421
int bestIdx = -1, bestLen = 0;
1349113422
13492
-
13423
+
1349313424
for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
1349413425
const char * const opname = Jim_ExprOperators[i].name;
1349513426
const int oplen = Jim_ExprOperators[i].namelen;
1349613427
1349713428
if (opname == NULL || opname[0] != pc->p[0]) {
@@ -13505,11 +13436,11 @@
1350513436
}
1350613437
if (bestIdx == -1) {
1350713438
return JIM_ERR;
1350813439
}
1350913440
13510
-
13441
+
1351113442
if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
1351213443
const char *p = pc->p + bestLen;
1351313444
int len = pc->len - bestLen;
1351413445
1351513446
while (len && isspace(UCHAR(*p))) {
@@ -13539,13 +13470,19 @@
1353913470
1354013471
const char *jim_tt_name(int type)
1354113472
{
1354213473
static const char * const tt_names[JIM_TT_EXPR_OP] =
1354313474
{ "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13544
- "DBL", "$()" };
13475
+ "DBL", "BOO", "$()" };
1354513476
if (type < JIM_TT_EXPR_OP) {
1354613477
return tt_names[type];
13478
+ }
13479
+ else if (type == JIM_EXPROP_UNARYMINUS) {
13480
+ return "-VE";
13481
+ }
13482
+ else if (type == JIM_EXPROP_UNARYPLUS) {
13483
+ return "+VE";
1354713484
}
1354813485
else {
1354913486
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
1355013487
static char buf[20];
1355113488
@@ -13570,13 +13507,13 @@
1357013507
};
1357113508
1357213509
1357313510
typedef struct ExprByteCode
1357413511
{
13575
- ScriptToken *token;
13576
- int len;
13577
- int inUse;
13512
+ ScriptToken *token;
13513
+ int len;
13514
+ int inUse;
1357813515
} ExprByteCode;
1357913516
1358013517
static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
1358113518
{
1358213519
int i;
@@ -13604,26 +13541,29 @@
1360413541
static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
1360513542
{
1360613543
JIM_NOTUSED(interp);
1360713544
JIM_NOTUSED(srcPtr);
1360813545
13609
-
13546
+
1361013547
dupPtr->typePtr = NULL;
1361113548
}
1361213549
13613
-
13614
-static int ExprCheckCorrectness(ExprByteCode * expr)
13550
+static int ExprCheckCorrectness(Jim_Interp *interp, Jim_Obj *exprObjPtr, ExprByteCode * expr)
1361513551
{
1361613552
int i;
1361713553
int stacklen = 0;
1361813554
int ternary = 0;
13555
+ int lasttt = JIM_TT_NONE;
13556
+ const char *errmsg;
1361913557
1362013558
for (i = 0; i < expr->len; i++) {
1362113559
ScriptToken *t = &expr->token[i];
1362213560
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13561
+ lasttt = t->type;
1362313562
1362413563
stacklen -= op->arity;
13564
+
1362513565
if (stacklen < 0) {
1362613566
break;
1362713567
}
1362813568
if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
1362913569
ternary++;
@@ -13630,26 +13570,47 @@
1363013570
}
1363113571
else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
1363213572
ternary--;
1363313573
}
1363413574
13635
-
13575
+
1363613576
stacklen++;
1363713577
}
13638
- if (stacklen != 1 || ternary != 0) {
13639
- return JIM_ERR;
13578
+ if (stacklen == 1 && ternary == 0) {
13579
+ return JIM_OK;
1364013580
}
13641
- return JIM_OK;
13581
+
13582
+ if (stacklen <= 0) {
13583
+
13584
+ if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
13585
+ errmsg = "too few arguments for math function";
13586
+ Jim_SetResultString(interp, "too few arguments for math function", -1);
13587
+ } else {
13588
+ errmsg = "premature end of expression";
13589
+ }
13590
+ }
13591
+ else if (stacklen > 1) {
13592
+ if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
13593
+ errmsg = "too many arguments for math function";
13594
+ } else {
13595
+ errmsg = "extra tokens at end of expression";
13596
+ }
13597
+ }
13598
+ else {
13599
+ errmsg = "invalid ternary expression";
13600
+ }
13601
+ Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": %s", exprObjPtr, errmsg);
13602
+ return JIM_ERR;
1364213603
}
1364313604
1364413605
static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
1364513606
{
1364613607
int i;
1364713608
1364813609
int leftindex, arity, offset;
1364913610
13650
-
13611
+
1365113612
leftindex = expr->len - 1;
1365213613
1365313614
arity = 1;
1365413615
while (arity) {
1365513616
ScriptToken *tt = &expr->token[leftindex];
@@ -13662,11 +13623,11 @@
1366213623
return JIM_ERR;
1366313624
}
1366413625
}
1366513626
leftindex++;
1366613627
13667
-
13628
+
1366813629
memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
1366913630
sizeof(*expr->token) * (expr->len - leftindex));
1367013631
expr->len += 2;
1367113632
offset = (expr->len - leftindex) - 1;
1367213633
@@ -13674,16 +13635,16 @@
1367413635
expr->token[leftindex + 1].objPtr = interp->emptyObj;
1367513636
1367613637
expr->token[leftindex].type = JIM_TT_EXPR_INT;
1367713638
expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
1367813639
13679
-
13640
+
1368013641
expr->token[expr->len].objPtr = interp->emptyObj;
1368113642
expr->token[expr->len].type = t->type + 2;
1368213643
expr->len++;
1368313644
13684
-
13645
+
1368513646
for (i = leftindex - 1; i > 0; i--) {
1368613647
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
1368713648
if (op->lazy == LAZY_LEFT) {
1368813649
if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
1368913650
JimWideValue(expr->token[i - 1].objPtr) += 2;
@@ -13729,11 +13690,11 @@
1372913690
return right_index;
1373013691
}
1373113692
right_index--;
1373213693
}
1373313694
13734
-
13695
+
1373513696
return -1;
1373613697
}
1373713698
1373813699
static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
1373913700
{
@@ -13771,11 +13732,11 @@
1377113732
1377213733
if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
1377313734
continue;
1377413735
}
1377513736
13776
-
13737
+
1377713738
if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
1377813739
continue;
1377913740
}
1378013741
1378113742
tmp = expr->token[prev_right_index];
@@ -13784,25 +13745,25 @@
1378413745
}
1378513746
expr->token[i] = tmp;
1378613747
1378713748
JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
1378813749
13789
-
13750
+
1379013751
i++;
1379113752
}
1379213753
}
1379313754
13794
-static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
13755
+static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
1379513756
{
1379613757
Jim_Stack stack;
1379713758
ExprByteCode *expr;
1379813759
int ok = 1;
1379913760
int i;
1380013761
int prevtt = JIM_TT_NONE;
1380113762
int have_ternary = 0;
1380213763
13803
-
13764
+
1380413765
int count = tokenlist->count - 1;
1380513766
1380613767
expr = Jim_Alloc(sizeof(*expr));
1380713768
expr->inUse = 1;
1380813769
expr->len = 0;
@@ -13813,11 +13774,11 @@
1381313774
ParseToken *t = &tokenlist->list[i];
1381413775
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
1381513776
1381613777
if (op->lazy == LAZY_OP) {
1381713778
count += 2;
13818
-
13779
+
1381913780
if (t->type == JIM_EXPROP_TERNARY) {
1382013781
have_ternary = 1;
1382113782
}
1382213783
}
1382313784
}
@@ -13825,128 +13786,128 @@
1382513786
expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
1382613787
1382713788
for (i = 0; i < tokenlist->count && ok; i++) {
1382813789
ParseToken *t = &tokenlist->list[i];
1382913790
13830
-
13791
+
1383113792
struct ScriptToken *token = &expr->token[expr->len];
1383213793
1383313794
if (t->type == JIM_TT_EOL) {
1383413795
break;
1383513796
}
1383613797
13837
- switch (t->type) {
13838
- case JIM_TT_STR:
13839
- case JIM_TT_ESC:
13840
- case JIM_TT_VAR:
13841
- case JIM_TT_DICTSUGAR:
13842
- case JIM_TT_EXPRSUGAR:
13843
- case JIM_TT_CMD:
13844
- token->type = t->type;
13845
-strexpr:
13846
- token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13847
- if (t->type == JIM_TT_CMD) {
13848
-
13849
- JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13850
- }
13851
- expr->len++;
13852
- break;
13853
-
13854
- case JIM_TT_EXPR_INT:
13855
- case JIM_TT_EXPR_DOUBLE:
13856
- {
13857
- char *endptr;
13858
- if (t->type == JIM_TT_EXPR_INT) {
13859
- token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13860
- }
13861
- else {
13862
- token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13863
- }
13864
- if (endptr != t->token + t->len) {
13865
-
13866
- Jim_FreeNewObj(interp, token->objPtr);
13867
- token->type = JIM_TT_STR;
13868
- goto strexpr;
13869
- }
13870
- token->type = t->type;
13871
- expr->len++;
13872
- }
13873
- break;
13874
-
13875
- case JIM_TT_SUBEXPR_START:
13876
- Jim_StackPush(&stack, t);
13877
- prevtt = JIM_TT_NONE;
13878
- continue;
13879
-
13880
- case JIM_TT_SUBEXPR_COMMA:
13881
-
13882
- continue;
13883
-
13884
- case JIM_TT_SUBEXPR_END:
13885
- ok = 0;
13886
- while (Jim_StackLen(&stack)) {
13887
- ParseToken *tt = Jim_StackPop(&stack);
13888
-
13889
- if (tt->type == JIM_TT_SUBEXPR_START) {
13890
- ok = 1;
13891
- break;
13892
- }
13893
-
13894
- if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13895
- goto err;
13896
- }
13897
- }
13898
- if (!ok) {
13899
- Jim_SetResultString(interp, "Unexpected close parenthesis", -1);
13900
- goto err;
13901
- }
13902
- break;
13903
-
13904
-
13905
- default:{
13906
-
13907
- const struct Jim_ExprOperator *op;
13908
- ParseToken *tt;
13909
-
13910
-
13911
- if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
13912
- if (t->type == JIM_EXPROP_SUB) {
13913
- t->type = JIM_EXPROP_UNARYMINUS;
13914
- }
13915
- else if (t->type == JIM_EXPROP_ADD) {
13916
- t->type = JIM_EXPROP_UNARYPLUS;
13917
- }
13918
- }
13919
-
13920
- op = JimExprOperatorInfoByOpcode(t->type);
13921
-
13922
-
13923
- while ((tt = Jim_StackPeek(&stack)) != NULL) {
13924
- const struct Jim_ExprOperator *tt_op =
13925
- JimExprOperatorInfoByOpcode(tt->type);
13926
-
13927
-
13928
-
13929
- if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13930
- if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13931
- ok = 0;
13932
- goto err;
13933
- }
13934
- Jim_StackPop(&stack);
13935
- }
13936
- else {
13937
- break;
13938
- }
13939
- }
13940
- Jim_StackPush(&stack, t);
13941
- break;
13942
- }
13798
+ if (TOKEN_IS_EXPR_OP(t->type)) {
13799
+ const struct Jim_ExprOperator *op;
13800
+ ParseToken *tt;
13801
+
13802
+
13803
+ if (prevtt == JIM_TT_NONE || prevtt == JIM_TT_SUBEXPR_START || prevtt == JIM_TT_SUBEXPR_COMMA || prevtt >= JIM_TT_EXPR_OP) {
13804
+ if (t->type == JIM_EXPROP_SUB) {
13805
+ t->type = JIM_EXPROP_UNARYMINUS;
13806
+ }
13807
+ else if (t->type == JIM_EXPROP_ADD) {
13808
+ t->type = JIM_EXPROP_UNARYPLUS;
13809
+ }
13810
+ }
13811
+
13812
+ op = JimExprOperatorInfoByOpcode(t->type);
13813
+
13814
+
13815
+ while ((tt = Jim_StackPeek(&stack)) != NULL) {
13816
+ const struct Jim_ExprOperator *tt_op =
13817
+ JimExprOperatorInfoByOpcode(tt->type);
13818
+
13819
+
13820
+ if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13821
+
13822
+ if (tt_op->precedence == op->precedence && tt_op->lazy == RIGHT_ASSOC) {
13823
+ break;
13824
+ }
13825
+ if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13826
+ ok = 0;
13827
+ goto err;
13828
+ }
13829
+ Jim_StackPop(&stack);
13830
+ }
13831
+ else {
13832
+ break;
13833
+ }
13834
+ }
13835
+ Jim_StackPush(&stack, t);
13836
+ }
13837
+ else if (t->type == JIM_TT_SUBEXPR_START) {
13838
+ Jim_StackPush(&stack, t);
13839
+ }
13840
+ else if (t->type == JIM_TT_SUBEXPR_END || t->type == JIM_TT_SUBEXPR_COMMA) {
13841
+
13842
+ ok = 0;
13843
+ while (Jim_StackLen(&stack)) {
13844
+ ParseToken *tt = Jim_StackPop(&stack);
13845
+
13846
+ if (tt->type == JIM_TT_SUBEXPR_START || tt->type == JIM_TT_SUBEXPR_COMMA) {
13847
+ if (t->type == JIM_TT_SUBEXPR_COMMA) {
13848
+
13849
+ Jim_StackPush(&stack, tt);
13850
+ }
13851
+ ok = 1;
13852
+ break;
13853
+ }
13854
+ if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13855
+ goto err;
13856
+ }
13857
+ }
13858
+ if (!ok) {
13859
+ Jim_SetResultFormatted(interp, "Unexpected close parenthesis in expression: \"%#s\"", exprObjPtr);
13860
+ goto err;
13861
+ }
13862
+ }
13863
+ else {
13864
+ Jim_Obj *objPtr = NULL;
13865
+
13866
+
13867
+ token->type = t->type;
13868
+
13869
+
13870
+ if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) {
13871
+ Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", exprObjPtr);
13872
+ ok = 0;
13873
+ goto err;
13874
+ }
13875
+
13876
+
13877
+ if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) {
13878
+ char *endptr;
13879
+ if (t->type == JIM_TT_EXPR_INT) {
13880
+ objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13881
+ }
13882
+ else {
13883
+ objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13884
+ }
13885
+ if (endptr != t->token + t->len) {
13886
+
13887
+ Jim_FreeNewObj(interp, objPtr);
13888
+ objPtr = NULL;
13889
+ }
13890
+ }
13891
+
13892
+ if (objPtr) {
13893
+ token->objPtr = objPtr;
13894
+ }
13895
+ else {
13896
+
13897
+ token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13898
+ if (t->type == JIM_TT_CMD) {
13899
+
13900
+ JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13901
+ }
13902
+ }
13903
+ expr->len++;
1394313904
}
1394413905
prevtt = t->type;
1394513906
}
1394613907
13947
-
13908
+
1394813909
while (Jim_StackLen(&stack)) {
1394913910
ParseToken *tt = Jim_StackPop(&stack);
1395013911
1395113912
if (tt->type == JIM_TT_SUBEXPR_START) {
1395213913
ok = 0;
@@ -13962,11 +13923,11 @@
1396213923
if (have_ternary) {
1396313924
ExprTernaryReorderExpression(interp, expr);
1396413925
}
1396513926
1396613927
err:
13967
-
13928
+
1396813929
Jim_FreeStack(&stack);
1396913930
1397013931
for (i = 0; i < expr->len; i++) {
1397113932
Jim_IncrRefCount(expr->token[i].objPtr);
1397213933
}
@@ -13989,11 +13950,11 @@
1398913950
ParseTokenList tokenlist;
1399013951
int line;
1399113952
Jim_Obj *fileNameObj;
1399213953
int rc = JIM_ERR;
1399313954
13994
-
13955
+
1399513956
if (objPtr->typePtr == &sourceObjType) {
1399613957
fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
1399713958
line = objPtr->internalRep.sourceValue.lineNumber;
1399813959
}
1399913960
else {
@@ -14002,18 +13963,17 @@
1400213963
}
1400313964
Jim_IncrRefCount(fileNameObj);
1400413965
1400513966
exprText = Jim_GetString(objPtr, &exprTextLen);
1400613967
14007
-
13968
+
1400813969
ScriptTokenListInit(&tokenlist);
1400913970
1401013971
JimParserInit(&parser, exprText, exprTextLen, line);
1401113972
while (!parser.eof) {
1401213973
if (JimParseExpression(&parser) != JIM_OK) {
1401313974
ScriptTokenListFree(&tokenlist);
14014
- invalidexpr:
1401513975
Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
1401613976
expr = NULL;
1401713977
goto err;
1401813978
}
1401913979
@@ -14036,14 +13996,14 @@
1403613996
ScriptTokenListFree(&tokenlist);
1403713997
Jim_DecrRefCount(interp, fileNameObj);
1403813998
return JIM_ERR;
1403913999
}
1404014000
14041
-
14042
- expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
1404314001
14044
-
14002
+ expr = ExprCreateByteCode(interp, &tokenlist, objPtr, fileNameObj);
14003
+
14004
+
1404514005
ScriptTokenListFree(&tokenlist);
1404614006
1404714007
if (!expr) {
1404814008
goto err;
1404914009
}
@@ -14059,20 +14019,22 @@
1405914019
printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
1406014020
}
1406114021
}
1406214022
#endif
1406314023
14064
-
14065
- if (ExprCheckCorrectness(expr) != JIM_OK) {
14024
+
14025
+ if (ExprCheckCorrectness(interp, objPtr, expr) != JIM_OK) {
14026
+
1406614027
ExprFreeByteCode(interp, expr);
14067
- goto invalidexpr;
14028
+ expr = NULL;
14029
+ goto err;
1406814030
}
1406914031
1407014032
rc = JIM_OK;
1407114033
1407214034
err:
14073
-
14035
+
1407414036
Jim_DecrRefCount(interp, fileNameObj);
1407514037
Jim_FreeIntRep(interp, objPtr);
1407614038
Jim_SetIntRepPtr(objPtr, expr);
1407714039
objPtr->typePtr = &exprObjType;
1407814040
return rc;
@@ -14112,11 +14074,11 @@
1411214074
int retcode = JIM_OK;
1411314075
struct JimExprState e;
1411414076
1411514077
expr = JimGetExpression(interp, exprObjPtr);
1411614078
if (!expr) {
14117
- return JIM_ERR;
14079
+ return JIM_ERR;
1411814080
}
1411914081
1412014082
#ifdef JIM_OPTIMIZATION
1412114083
{
1412214084
Jim_Obj *objPtr;
@@ -14185,26 +14147,27 @@
1418514147
noopt:
1418614148
#endif
1418714149
1418814150
expr->inUse++;
1418914151
14190
-
14152
+
1419114153
1419214154
if (expr->len > JIM_EE_STATICSTACK_LEN)
1419314155
e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
1419414156
else
1419514157
e.stack = staticStack;
1419614158
1419714159
e.stacklen = 0;
1419814160
14199
-
14161
+
1420014162
for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
1420114163
Jim_Obj *objPtr;
1420214164
1420314165
switch (expr->token[i].type) {
1420414166
case JIM_TT_EXPR_INT:
1420514167
case JIM_TT_EXPR_DOUBLE:
14168
+ case JIM_TT_EXPR_BOOLEAN:
1420614169
case JIM_TT_STR:
1420714170
ExprPush(&e, expr->token[i].objPtr);
1420814171
break;
1420914172
1421014173
case JIM_TT_VAR:
@@ -14240,16 +14203,16 @@
1424014203
ExprPush(&e, Jim_GetResult(interp));
1424114204
}
1424214205
break;
1424314206
1424414207
default:{
14245
-
14208
+
1424614209
e.skip = 0;
1424714210
e.opcode = expr->token[i].type;
1424814211
1424914212
retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
14250
-
14213
+
1425114214
i += e.skip;
1425214215
continue;
1425314216
}
1425414217
}
1425514218
}
@@ -14273,20 +14236,27 @@
1427314236
int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
1427414237
{
1427514238
int retcode;
1427614239
jim_wide wideValue;
1427714240
double doubleValue;
14241
+ int booleanValue;
1427814242
Jim_Obj *exprResultPtr;
1427914243
1428014244
retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
1428114245
if (retcode != JIM_OK)
1428214246
return retcode;
1428314247
1428414248
if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
1428514249
if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
14286
- Jim_DecrRefCount(interp, exprResultPtr);
14287
- return JIM_ERR;
14250
+ if (Jim_GetBoolean(interp, exprResultPtr, &booleanValue) != JIM_OK) {
14251
+ Jim_DecrRefCount(interp, exprResultPtr);
14252
+ return JIM_ERR;
14253
+ } else {
14254
+ Jim_DecrRefCount(interp, exprResultPtr);
14255
+ *boolPtr = booleanValue;
14256
+ return JIM_OK;
14257
+ }
1428814258
}
1428914259
else {
1429014260
Jim_DecrRefCount(interp, exprResultPtr);
1429114261
*boolPtr = doubleValue != 0;
1429214262
return JIM_OK;
@@ -14301,29 +14271,29 @@
1430114271
1430214272
1430314273
1430414274
typedef struct ScanFmtPartDescr
1430514275
{
14306
- char *arg;
14307
- char *prefix;
14308
- size_t width;
14309
- int pos;
14310
- char type;
14311
- char modifier;
14276
+ char *arg;
14277
+ char *prefix;
14278
+ size_t width;
14279
+ int pos;
14280
+ char type;
14281
+ char modifier;
1431214282
} ScanFmtPartDescr;
1431314283
1431414284
1431514285
typedef struct ScanFmtStringObj
1431614286
{
14317
- jim_wide size;
14318
- char *stringRep;
14319
- size_t count;
14320
- size_t convCount;
14321
- size_t maxPos;
14322
- const char *error;
14323
- char *scratch;
14324
- ScanFmtPartDescr descr[1];
14287
+ jim_wide size;
14288
+ char *stringRep;
14289
+ size_t count;
14290
+ size_t convCount;
14291
+ size_t maxPos;
14292
+ const char *error;
14293
+ char *scratch;
14294
+ ScanFmtPartDescr descr[1];
1432514295
} ScanFmtStringObj;
1432614296
1432714297
1432814298
static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
1432914299
static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14370,22 +14340,22 @@
1437014340
int maxFmtLen = objPtr->length;
1437114341
const char *fmtEnd = fmt + maxFmtLen;
1437214342
int curr;
1437314343
1437414344
Jim_FreeIntRep(interp, objPtr);
14375
-
14345
+
1437614346
for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
1437714347
if (fmt[i] == '%')
1437814348
++maxCount;
14379
-
14380
- approxSize = sizeof(ScanFmtStringObj)
14381
- +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14382
- +maxFmtLen * sizeof(char) + 3 + 1
14383
- + maxFmtLen * sizeof(char) + 1
14384
- + maxFmtLen * sizeof(char)
14385
- +(maxCount + 1) * sizeof(char)
14386
- +1;
14349
+
14350
+ approxSize = sizeof(ScanFmtStringObj)
14351
+ +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14352
+ +maxFmtLen * sizeof(char) + 3 + 1
14353
+ + maxFmtLen * sizeof(char) + 1
14354
+ + maxFmtLen * sizeof(char)
14355
+ +(maxCount + 1) * sizeof(char)
14356
+ +1;
1438714357
fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
1438814358
memset(fmtObj, 0, approxSize);
1438914359
fmtObj->size = approxSize;
1439014360
fmtObj->maxPos = 0;
1439114361
fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14367,12 @@
1439714367
for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
1439814368
int width = 0, skip;
1439914369
ScanFmtPartDescr *descr = &fmtObj->descr[curr];
1440014370
1440114371
fmtObj->count++;
14402
- descr->width = 0;
14403
-
14372
+ descr->width = 0;
14373
+
1440414374
if (*fmt != '%' || fmt[1] == '%') {
1440514375
descr->type = 0;
1440614376
descr->prefix = &buffer[i];
1440714377
for (; fmt < fmtEnd; ++fmt) {
1440814378
if (*fmt == '%') {
@@ -14412,65 +14382,65 @@
1441214382
}
1441314383
buffer[i++] = *fmt;
1441414384
}
1441514385
buffer[i++] = 0;
1441614386
}
14417
-
14387
+
1441814388
++fmt;
14419
-
14389
+
1442014390
if (fmt >= fmtEnd)
1442114391
goto done;
14422
- descr->pos = 0;
14392
+ descr->pos = 0;
1442314393
if (*fmt == '*') {
14424
- descr->pos = -1;
14394
+ descr->pos = -1;
1442514395
++fmt;
1442614396
}
1442714397
else
14428
- fmtObj->convCount++;
14429
-
14398
+ fmtObj->convCount++;
14399
+
1443014400
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
1443114401
fmt += skip;
14432
-
14402
+
1443314403
if (descr->pos != -1 && *fmt == '$') {
1443414404
int prev;
1443514405
1443614406
++fmt;
1443714407
descr->pos = width;
1443814408
width = 0;
14439
-
14409
+
1444014410
if ((lastPos == 0 && descr->pos > 0)
1444114411
|| (lastPos > 0 && descr->pos == 0)) {
1444214412
fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
1444314413
return JIM_ERR;
1444414414
}
14445
-
14415
+
1444614416
for (prev = 0; prev < curr; ++prev) {
1444714417
if (fmtObj->descr[prev].pos == -1)
1444814418
continue;
1444914419
if (fmtObj->descr[prev].pos == descr->pos) {
1445014420
fmtObj->error =
1445114421
"variable is assigned by multiple \"%n$\" conversion specifiers";
1445214422
return JIM_ERR;
1445314423
}
1445414424
}
14455
-
14425
+
1445614426
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
1445714427
descr->width = width;
1445814428
fmt += skip;
1445914429
}
1446014430
if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
1446114431
fmtObj->maxPos = descr->pos;
1446214432
}
1446314433
else {
14464
-
14434
+
1446514435
descr->width = width;
1446614436
}
1446714437
}
14468
-
14438
+
1446914439
if (lastPos == -1)
1447014440
lastPos = descr->pos;
14471
-
14441
+
1447214442
if (*fmt == '[') {
1447314443
int swapped = 1, beg = i, end, j;
1447414444
1447514445
descr->type = '[';
1447614446
descr->arg = &buffer[i];
@@ -14485,11 +14455,11 @@
1448514455
fmtObj->error = "unmatched [ in format string";
1448614456
return JIM_ERR;
1448714457
}
1448814458
end = i;
1448914459
buffer[i++] = 0;
14490
-
14460
+
1449114461
while (swapped) {
1449214462
swapped = 0;
1449314463
for (j = beg + 1; j < end - 1; ++j) {
1449414464
if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
1449514465
char tmp = buffer[j - 1];
@@ -14500,11 +14470,11 @@
1450014470
}
1450114471
}
1450214472
}
1450314473
}
1450414474
else {
14505
-
14475
+
1450614476
if (strchr("hlL", *fmt) != 0)
1450714477
descr->modifier = tolower((int)*fmt++);
1450814478
1450914479
descr->type = *fmt;
1451014480
if (strchr("efgcsndoxui", *fmt) == 0) {
@@ -14543,11 +14513,11 @@
1454314513
while (*str) {
1454414514
int c;
1454514515
int n;
1454614516
1454714517
if (!sdescr && isspace(UCHAR(*str)))
14548
- break;
14518
+ break;
1454914519
1455014520
n = utf8_tounicode(str, &c);
1455114521
if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
1455214522
break;
1455314523
while (n--)
@@ -14566,89 +14536,89 @@
1456614536
size_t scanned = 0;
1456714537
size_t anchor = pos;
1456814538
int i;
1456914539
Jim_Obj *tmpObj = NULL;
1457014540
14571
-
14541
+
1457214542
*valObjPtr = 0;
1457314543
if (descr->prefix) {
1457414544
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14575
-
14545
+
1457614546
if (isspace(UCHAR(descr->prefix[i])))
1457714547
while (pos < strLen && isspace(UCHAR(str[pos])))
1457814548
++pos;
1457914549
else if (descr->prefix[i] != str[pos])
14580
- break;
14550
+ break;
1458114551
else
14582
- ++pos;
14552
+ ++pos;
1458314553
}
1458414554
if (pos >= strLen) {
14585
- return -1;
14555
+ return -1;
1458614556
}
1458714557
else if (descr->prefix[i] != 0)
14588
- return 0;
14558
+ return 0;
1458914559
}
14590
-
14560
+
1459114561
if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
1459214562
while (isspace(UCHAR(str[pos])))
1459314563
++pos;
14594
-
14564
+
1459514565
scanned = pos - anchor;
1459614566
14597
-
14567
+
1459814568
if (descr->type == 'n') {
14599
-
14569
+
1460014570
*valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
1460114571
}
1460214572
else if (pos >= strLen) {
14603
-
14573
+
1460414574
return -1;
1460514575
}
1460614576
else if (descr->type == 'c') {
1460714577
int c;
1460814578
scanned += utf8_tounicode(&str[pos], &c);
1460914579
*valObjPtr = Jim_NewIntObj(interp, c);
1461014580
return scanned;
1461114581
}
1461214582
else {
14613
-
14583
+
1461414584
if (descr->width > 0) {
1461514585
size_t sLen = utf8_strlen(&str[pos], strLen - pos);
1461614586
size_t tLen = descr->width > sLen ? sLen : descr->width;
1461714587
1461814588
tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
1461914589
tok = tmpObj->bytes;
1462014590
}
1462114591
else {
14622
-
14592
+
1462314593
tok = &str[pos];
1462414594
}
1462514595
switch (descr->type) {
1462614596
case 'd':
1462714597
case 'o':
1462814598
case 'x':
1462914599
case 'u':
1463014600
case 'i':{
14631
- char *endp;
14601
+ char *endp;
1463214602
jim_wide w;
1463314603
1463414604
int base = descr->type == 'o' ? 8
1463514605
: descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
1463614606
14637
-
14607
+
1463814608
if (base == 0) {
1463914609
w = jim_strtoull(tok, &endp);
1464014610
}
1464114611
else {
1464214612
w = strtoull(tok, &endp, base);
1464314613
}
1464414614
1464514615
if (endp != tok) {
14646
-
14616
+
1464714617
*valObjPtr = Jim_NewIntObj(interp, w);
1464814618
14649
-
14619
+
1465014620
scanned += endp - tok;
1465114621
}
1465214622
else {
1465314623
scanned = *tok ? 0 : -1;
1465414624
}
@@ -14665,13 +14635,13 @@
1466514635
case 'g':{
1466614636
char *endp;
1466714637
double value = strtod(tok, &endp);
1466814638
1466914639
if (endp != tok) {
14670
-
14640
+
1467114641
*valObjPtr = Jim_NewDoubleObj(interp, value);
14672
-
14642
+
1467314643
scanned += endp - tok;
1467414644
}
1467514645
else {
1467614646
scanned = *tok ? 0 : -1;
1467714647
}
@@ -14696,65 +14666,65 @@
1469614666
Jim_Obj **resultVec = 0;
1469714667
int resultc;
1469814668
Jim_Obj *emptyStr = 0;
1469914669
ScanFmtStringObj *fmtObj;
1470014670
14701
-
14671
+
1470214672
JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
1470314673
1470414674
fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14705
-
14675
+
1470614676
if (fmtObj->error != 0) {
1470714677
if (flags & JIM_ERRMSG)
1470814678
Jim_SetResultString(interp, fmtObj->error, -1);
1470914679
return 0;
1471014680
}
14711
-
14681
+
1471214682
emptyStr = Jim_NewEmptyStringObj(interp);
1471314683
Jim_IncrRefCount(emptyStr);
14714
-
14684
+
1471514685
resultList = Jim_NewListObj(interp, NULL, 0);
1471614686
if (fmtObj->maxPos > 0) {
1471714687
for (i = 0; i < fmtObj->maxPos; ++i)
1471814688
Jim_ListAppendElement(interp, resultList, emptyStr);
1471914689
JimListGetElements(interp, resultList, &resultc, &resultVec);
1472014690
}
14721
-
14691
+
1472214692
for (i = 0, pos = 0; i < fmtObj->count; ++i) {
1472314693
ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
1472414694
Jim_Obj *value = 0;
1472514695
14726
-
14696
+
1472714697
if (descr->type == 0)
1472814698
continue;
14729
-
14699
+
1473014700
if (scanned > 0)
1473114701
scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14732
-
14702
+
1473314703
if (scanned == -1 && i == 0)
1473414704
goto eof;
14735
-
14705
+
1473614706
pos += scanned;
1473714707
14738
-
14708
+
1473914709
if (value == 0)
1474014710
value = Jim_NewEmptyStringObj(interp);
14741
-
14711
+
1474214712
if (descr->pos == -1) {
1474314713
Jim_FreeNewObj(interp, value);
1474414714
}
1474514715
else if (descr->pos == 0)
14746
-
14716
+
1474714717
Jim_ListAppendElement(interp, resultList, value);
1474814718
else if (resultVec[descr->pos - 1] == emptyStr) {
14749
-
14719
+
1475014720
Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
1475114721
Jim_IncrRefCount(value);
1475214722
resultVec[descr->pos - 1] = value;
1475314723
}
1475414724
else {
14755
-
14725
+
1475614726
Jim_FreeNewObj(interp, value);
1475714727
goto err;
1475814728
}
1475914729
}
1476014730
Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14762,15 @@
1479214762
{
1479314763
Jim_PrngState *prng;
1479414764
unsigned char *destByte = (unsigned char *)dest;
1479514765
unsigned int si, sj, x;
1479614766
14797
-
14767
+
1479814768
if (interp->prngState == NULL)
1479914769
JimPrngInit(interp);
1480014770
prng = interp->prngState;
14801
-
14771
+
1480214772
for (x = 0; x < len; x++) {
1480314773
prng->i = (prng->i + 1) & 0xff;
1480414774
si = prng->sbox[prng->i];
1480514775
prng->j = (prng->j + si) & 0xff;
1480614776
sj = prng->sbox[prng->j];
@@ -14814,19 +14784,19 @@
1481414784
static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
1481514785
{
1481614786
int i;
1481714787
Jim_PrngState *prng;
1481814788
14819
-
14789
+
1482014790
if (interp->prngState == NULL)
1482114791
JimPrngInit(interp);
1482214792
prng = interp->prngState;
1482314793
14824
-
14794
+
1482514795
for (i = 0; i < 256; i++)
1482614796
prng->sbox[i] = i;
14827
-
14797
+
1482814798
for (i = 0; i < seedLen; i++) {
1482914799
unsigned char t;
1483014800
1483114801
t = prng->sbox[i & 0xFF];
1483214802
prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14823,11 @@
1485314823
if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
1485414824
return JIM_ERR;
1485514825
}
1485614826
intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1485714827
if (!intObjPtr) {
14858
-
14828
+
1485914829
wideValue = 0;
1486014830
}
1486114831
else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
1486214832
return JIM_ERR;
1486314833
}
@@ -14867,26 +14837,26 @@
1486714837
Jim_FreeNewObj(interp, intObjPtr);
1486814838
return JIM_ERR;
1486914839
}
1487014840
}
1487114841
else {
14872
-
14842
+
1487314843
Jim_InvalidateStringRep(intObjPtr);
1487414844
JimWideValue(intObjPtr) = wideValue + increment;
1487514845
1487614846
if (argv[1]->typePtr != &variableObjType) {
14877
-
14847
+
1487814848
Jim_SetVariable(interp, argv[1], intObjPtr);
1487914849
}
1488014850
}
1488114851
Jim_SetResult(interp, intObjPtr);
1488214852
return JIM_OK;
1488314853
}
1488414854
1488514855
14886
-#define JIM_EVAL_SARGV_LEN 8
14887
-#define JIM_EVAL_SINTV_LEN 8
14856
+#define JIM_EVAL_SARGV_LEN 8
14857
+#define JIM_EVAL_SINTV_LEN 8
1488814858
1488914859
1489014860
static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1489114861
{
1489214862
int retcode;
@@ -14894,16 +14864,16 @@
1489414864
if (interp->unknown_called > 50) {
1489514865
return JIM_ERR;
1489614866
}
1489714867
1489814868
14899
-
14869
+
1490014870
if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
1490114871
return JIM_ERR;
1490214872
1490314873
interp->unknown_called++;
14904
-
14874
+
1490514875
retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
1490614876
interp->unknown_called--;
1490714877
1490814878
return retcode;
1490914879
}
@@ -14921,11 +14891,11 @@
1492114891
}
1492214892
printf("\n");
1492314893
#endif
1492414894
1492514895
if (interp->framePtr->tailcallCmd) {
14926
-
14896
+
1492714897
cmdPtr = interp->framePtr->tailcallCmd;
1492814898
interp->framePtr->tailcallCmd = NULL;
1492914899
}
1493014900
else {
1493114901
cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14940,11 +14910,11 @@
1494014910
retcode = JIM_ERR;
1494114911
goto out;
1494214912
}
1494314913
interp->evalDepth++;
1494414914
14945
-
14915
+
1494614916
Jim_SetEmptyResult(interp);
1494714917
if (cmdPtr->isproc) {
1494814918
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
1494914919
}
1495014920
else {
@@ -14961,17 +14931,17 @@
1496114931
1496214932
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1496314933
{
1496414934
int i, retcode;
1496514935
14966
-
14936
+
1496714937
for (i = 0; i < objc; i++)
1496814938
Jim_IncrRefCount(objv[i]);
1496914939
1497014940
retcode = JimInvokeCommand(interp, objc, objv);
1497114941
14972
-
14942
+
1497314943
for (i = 0; i < objc; i++)
1497414944
Jim_DecrRefCount(interp, objv[i]);
1497514945
1497614946
return retcode;
1497714947
}
@@ -14989,25 +14959,25 @@
1498914959
}
1499014960
1499114961
static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
1499214962
{
1499314963
if (!interp->errorFlag) {
14994
-
14964
+
1499514965
interp->errorFlag = 1;
1499614966
Jim_IncrRefCount(script->fileNameObj);
1499714967
Jim_DecrRefCount(interp, interp->errorFileNameObj);
1499814968
interp->errorFileNameObj = script->fileNameObj;
1499914969
interp->errorLine = script->linenr;
1500014970
1500114971
JimResetStackTrace(interp);
15002
-
14972
+
1500314973
interp->addStackTrace++;
1500414974
}
1500514975
15006
-
14976
+
1500714977
if (interp->addStackTrace > 0) {
15008
-
14978
+
1500914979
1501014980
JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
1501114981
1501214982
if (Jim_Length(script->fileNameObj)) {
1501314983
interp->addStackTrace = 0;
@@ -15042,14 +15012,14 @@
1504215012
case JIM_OK:
1504315013
case JIM_RETURN:
1504415014
objPtr = interp->result;
1504515015
break;
1504615016
case JIM_BREAK:
15047
-
15017
+
1504815018
return JIM_BREAK;
1504915019
case JIM_CONTINUE:
15050
-
15020
+
1505115021
return JIM_CONTINUE;
1505215022
default:
1505315023
return JIM_ERR;
1505415024
}
1505515025
break;
@@ -15084,23 +15054,23 @@
1508415054
case JIM_OK:
1508515055
case JIM_RETURN:
1508615056
break;
1508715057
case JIM_BREAK:
1508815058
if (flags & JIM_SUBST_FLAG) {
15089
-
15059
+
1509015060
tokens = i;
1509115061
continue;
1509215062
}
15093
-
15094
-
15063
+
15064
+
1509515065
case JIM_CONTINUE:
1509615066
if (flags & JIM_SUBST_FLAG) {
1509715067
intv[i] = NULL;
1509815068
continue;
1509915069
}
15100
-
15101
-
15070
+
15071
+
1510215072
default:
1510315073
while (i--) {
1510415074
Jim_DecrRefCount(interp, intv[i]);
1510515075
}
1510615076
if (intv != sintv) {
@@ -15111,28 +15081,28 @@
1511115081
Jim_IncrRefCount(intv[i]);
1511215082
Jim_String(intv[i]);
1511315083
totlen += intv[i]->length;
1511415084
}
1511515085
15116
-
15086
+
1511715087
if (tokens == 1 && intv[0] && intv == sintv) {
1511815088
Jim_DecrRefCount(interp, intv[0]);
1511915089
return intv[0];
1512015090
}
1512115091
1512215092
objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
1512315093
1512415094
if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
1512515095
&& token[2].type == JIM_TT_VAR) {
15126
-
15096
+
1512715097
objPtr->typePtr = &interpolatedObjType;
1512815098
objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
1512915099
objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
1513015100
Jim_IncrRefCount(intv[2]);
1513115101
}
1513215102
else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
15133
-
15103
+
1513415104
JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
1513515105
}
1513615106
1513715107
1513815108
s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +15113,11 @@
1514315113
s += intv[i]->length;
1514415114
Jim_DecrRefCount(interp, intv[i]);
1514515115
}
1514615116
}
1514715117
objPtr->bytes[totlen] = '\0';
15148
-
15118
+
1514915119
if (intv != sintv) {
1515015120
Jim_Free(intv);
1515115121
}
1515215122
1515315123
return objPtr;
@@ -15187,11 +15157,11 @@
1518715157
1518815158
if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
1518915159
return JimEvalObjList(interp, scriptObjPtr);
1519015160
}
1519115161
15192
- Jim_IncrRefCount(scriptObjPtr);
15162
+ Jim_IncrRefCount(scriptObjPtr);
1519315163
script = JimGetScript(interp, scriptObjPtr);
1519415164
if (!JimScriptValid(interp, script)) {
1519515165
Jim_DecrRefCount(interp, scriptObjPtr);
1519615166
return JIM_ERR;
1519715167
}
@@ -15223,11 +15193,11 @@
1522315193
}
1522415194
#endif
1522515195
1522615196
script->inUse++;
1522715197
15228
-
15198
+
1522915199
prevScriptObj = interp->currentScriptObj;
1523015200
interp->currentScriptObj = scriptObjPtr;
1523115201
1523215202
interp->errorFlag = 0;
1523315203
argv = sargv;
@@ -15234,19 +15204,19 @@
1523415204
1523515205
for (i = 0; i < script->len && retcode == JIM_OK; ) {
1523615206
int argc;
1523715207
int j;
1523815208
15239
-
15209
+
1524015210
argc = token[i].objPtr->internalRep.scriptLineValue.argc;
1524115211
script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
1524215212
15243
-
15213
+
1524415214
if (argc > JIM_EVAL_SARGV_LEN)
1524515215
argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
1524615216
15247
-
15217
+
1524815218
i++;
1524915219
1525015220
for (j = 0; j < argc; j++) {
1525115221
long wordtokens = 1;
1525215222
int expand = 0;
@@ -15302,11 +15272,11 @@
1530215272
1530315273
if (!expand) {
1530415274
argv[j] = wordObjPtr;
1530515275
}
1530615276
else {
15307
-
15277
+
1530815278
int len = Jim_ListLength(interp, wordObjPtr);
1530915279
int newargc = argc + len - 1;
1531015280
int k;
1531115281
1531215282
if (len > 1) {
@@ -15315,39 +15285,39 @@
1531515285
argv = Jim_Alloc(sizeof(*argv) * newargc);
1531615286
memcpy(argv, sargv, sizeof(*argv) * j);
1531715287
}
1531815288
}
1531915289
else {
15320
-
15290
+
1532115291
argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
1532215292
}
1532315293
}
1532415294
15325
-
15295
+
1532615296
for (k = 0; k < len; k++) {
1532715297
argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
1532815298
Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
1532915299
}
1533015300
1533115301
Jim_DecrRefCount(interp, wordObjPtr);
1533215302
15333
-
15303
+
1533415304
j--;
1533515305
argc += len - 1;
1533615306
}
1533715307
}
1533815308
1533915309
if (retcode == JIM_OK && argc) {
15340
-
15310
+
1534115311
retcode = JimInvokeCommand(interp, argc, argv);
15342
-
15312
+
1534315313
if (Jim_CheckSignal(interp)) {
1534415314
retcode = JIM_SIGNAL;
1534515315
}
1534615316
}
1534715317
15348
-
15318
+
1534915319
while (j-- > 0) {
1535015320
Jim_DecrRefCount(interp, argv[j]);
1535115321
}
1535215322
1535315323
if (argv != sargv) {
@@ -15354,21 +15324,21 @@
1535415324
Jim_Free(argv);
1535515325
argv = sargv;
1535615326
}
1535715327
}
1535815328
15359
-
15329
+
1536015330
if (retcode == JIM_ERR) {
1536115331
JimAddErrorToStack(interp, script);
1536215332
}
15363
-
15333
+
1536415334
else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15365
-
15335
+
1536615336
interp->addStackTrace = 0;
1536715337
}
1536815338
15369
-
15339
+
1537015340
interp->currentScriptObj = prevScriptObj;
1537115341
1537215342
Jim_FreeIntRep(interp, scriptObjPtr);
1537315343
scriptObjPtr->typePtr = &scriptObjType;
1537415344
Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15348,14 @@
1537815348
}
1537915349
1538015350
static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
1538115351
{
1538215352
int retcode;
15383
-
15353
+
1538415354
const char *varname = Jim_String(argNameObj);
1538515355
if (*varname == '&') {
15386
-
15356
+
1538715357
Jim_Obj *objPtr;
1538815358
Jim_CallFrame *savedCallFrame = interp->framePtr;
1538915359
1539015360
interp->framePtr = interp->framePtr->parent;
1539115361
objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15362,11 @@
1539215362
interp->framePtr = savedCallFrame;
1539315363
if (!objPtr) {
1539415364
return JIM_ERR;
1539515365
}
1539615366
15397
-
15367
+
1539815368
objPtr = Jim_NewStringObj(interp, varname + 1, -1);
1539915369
Jim_IncrRefCount(objPtr);
1540015370
retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
1540115371
Jim_DecrRefCount(interp, objPtr);
1540215372
}
@@ -15406,26 +15376,26 @@
1540615376
return retcode;
1540715377
}
1540815378
1540915379
static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
1541015380
{
15411
-
15381
+
1541215382
Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
1541315383
int i;
1541415384
1541515385
for (i = 0; i < cmd->u.proc.argListLen; i++) {
1541615386
Jim_AppendString(interp, argmsg, " ", 1);
1541715387
1541815388
if (i == cmd->u.proc.argsPos) {
1541915389
if (cmd->u.proc.arglist[i].defaultObjPtr) {
15420
-
15390
+
1542115391
Jim_AppendString(interp, argmsg, "?", 1);
1542215392
Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
1542315393
Jim_AppendString(interp, argmsg, " ...?", -1);
1542415394
}
1542515395
else {
15426
-
15396
+
1542715397
Jim_AppendString(interp, argmsg, "?arg...?", -1);
1542815398
}
1542915399
}
1543015400
else {
1543115401
if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15411,19 @@
1544115411
Jim_AppendString(interp, argmsg, arg, -1);
1544215412
}
1544315413
}
1544415414
}
1544515415
Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
15446
- Jim_FreeNewObj(interp, argmsg);
1544715416
}
1544815417
1544915418
#ifdef jim_ext_namespace
1545015419
int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
1545115420
{
1545215421
Jim_CallFrame *callFramePtr;
1545315422
int retcode;
1545415423
15455
-
15424
+
1545615425
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
1545715426
callFramePtr->argv = &interp->emptyObj;
1545815427
callFramePtr->argc = 0;
1545915428
callFramePtr->procArgsObjPtr = NULL;
1546015429
callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15431,21 @@
1546215431
callFramePtr->fileNameObj = interp->emptyObj;
1546315432
callFramePtr->line = 0;
1546415433
Jim_IncrRefCount(scriptObj);
1546515434
interp->framePtr = callFramePtr;
1546615435
15467
-
15436
+
1546815437
if (interp->framePtr->level == interp->maxCallFrameDepth) {
1546915438
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
1547015439
retcode = JIM_ERR;
1547115440
}
1547215441
else {
15473
-
15442
+
1547415443
retcode = Jim_EvalObj(interp, scriptObj);
1547515444
}
1547615445
15477
-
15446
+
1547815447
interp->framePtr = interp->framePtr->parent;
1547915448
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1548015449
1548115450
return retcode;
1548215451
}
@@ -15486,62 +15455,62 @@
1548615455
{
1548715456
Jim_CallFrame *callFramePtr;
1548815457
int i, d, retcode, optargs;
1548915458
ScriptObj *script;
1549015459
15491
-
15460
+
1549215461
if (argc - 1 < cmd->u.proc.reqArity ||
1549315462
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
1549415463
JimSetProcWrongArgs(interp, argv[0], cmd);
1549515464
return JIM_ERR;
1549615465
}
1549715466
1549815467
if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15499
-
15468
+
1550015469
return JIM_OK;
1550115470
}
1550215471
15503
-
15472
+
1550415473
if (interp->framePtr->level == interp->maxCallFrameDepth) {
1550515474
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
1550615475
return JIM_ERR;
1550715476
}
1550815477
15509
-
15478
+
1551015479
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
1551115480
callFramePtr->argv = argv;
1551215481
callFramePtr->argc = argc;
1551315482
callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
1551415483
callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
1551515484
callFramePtr->staticVars = cmd->u.proc.staticVars;
1551615485
15517
-
15486
+
1551815487
script = JimGetScript(interp, interp->currentScriptObj);
1551915488
callFramePtr->fileNameObj = script->fileNameObj;
1552015489
callFramePtr->line = script->linenr;
1552115490
1552215491
Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
1552315492
Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
1552415493
interp->framePtr = callFramePtr;
1552515494
15526
-
15495
+
1552715496
optargs = (argc - 1 - cmd->u.proc.reqArity);
1552815497
15529
-
15498
+
1553015499
i = 1;
1553115500
for (d = 0; d < cmd->u.proc.argListLen; d++) {
1553215501
Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
1553315502
if (d == cmd->u.proc.argsPos) {
15534
-
15503
+
1553515504
Jim_Obj *listObjPtr;
1553615505
int argsLen = 0;
1553715506
if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
1553815507
argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
1553915508
}
1554015509
listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
1554115510
15542
-
15511
+
1554315512
if (cmd->u.proc.arglist[d].defaultObjPtr) {
1554415513
nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
1554515514
}
1554615515
retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
1554715516
if (retcode != JIM_OK) {
@@ -15550,33 +15519,33 @@
1555015519
1555115520
i += argsLen;
1555215521
continue;
1555315522
}
1555415523
15555
-
15524
+
1555615525
if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
1555715526
retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
1555815527
}
1555915528
else {
15560
-
15529
+
1556115530
retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
1556215531
}
1556315532
if (retcode != JIM_OK) {
1556415533
goto badargset;
1556515534
}
1556615535
}
1556715536
15568
-
15537
+
1556915538
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
1557015539
1557115540
badargset:
1557215541
15573
-
15542
+
1557415543
interp->framePtr = interp->framePtr->parent;
1557515544
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1557615545
15577
-
15546
+
1557815547
if (interp->framePtr->tailcallObj) {
1557915548
do {
1558015549
Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
1558115550
1558215551
interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15557,18 @@
1558815557
}
1558915558
}
1559015559
Jim_DecrRefCount(interp, tailcallObj);
1559115560
} while (interp->framePtr->tailcallObj);
1559215561
15593
-
15562
+
1559415563
if (interp->framePtr->tailcallCmd) {
1559515564
JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
1559615565
interp->framePtr->tailcallCmd = NULL;
1559715566
}
1559815567
}
1559915568
15600
-
15569
+
1560115570
if (retcode == JIM_RETURN) {
1560215571
if (--interp->returnLevel <= 0) {
1560315572
retcode = interp->returnCode;
1560415573
interp->returnCode = JIM_OK;
1560515574
interp->returnLevel = 0;
@@ -15711,20 +15680,20 @@
1571115680
prevScriptObj = interp->currentScriptObj;
1571215681
interp->currentScriptObj = scriptObjPtr;
1571315682
1571415683
retcode = Jim_EvalObj(interp, scriptObjPtr);
1571515684
15716
-
15685
+
1571715686
if (retcode == JIM_RETURN) {
1571815687
if (--interp->returnLevel <= 0) {
1571915688
retcode = interp->returnCode;
1572015689
interp->returnCode = JIM_OK;
1572115690
interp->returnLevel = 0;
1572215691
}
1572315692
}
1572415693
if (retcode == JIM_ERR) {
15725
-
15694
+
1572615695
interp->addStackTrace++;
1572715696
}
1572815697
1572915698
interp->currentScriptObj = prevScriptObj;
1573015699
@@ -15750,11 +15719,11 @@
1575015719
}
1575115720
if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
1575215721
if (JimParseVar(pc) == JIM_OK) {
1575315722
return;
1575415723
}
15755
-
15724
+
1575615725
pc->tstart = pc->p;
1575715726
flags |= JIM_SUBST_NOVAR;
1575815727
}
1575915728
while (pc->len) {
1576015729
if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15750,32 @@
1578115750
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
1578215751
struct JimParserCtx parser;
1578315752
struct ScriptObj *script = Jim_Alloc(sizeof(*script));
1578415753
ParseTokenList tokenlist;
1578515754
15786
-
15755
+
1578715756
ScriptTokenListInit(&tokenlist);
1578815757
1578915758
JimParserInit(&parser, scriptText, scriptTextLen, 1);
1579015759
while (1) {
1579115760
JimParseSubst(&parser, flags);
1579215761
if (parser.eof) {
15793
-
15762
+
1579415763
break;
1579515764
}
1579615765
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
1579715766
parser.tline);
1579815767
}
1579915768
15800
-
15769
+
1580115770
script->inUse = 1;
1580215771
script->substFlags = flags;
1580315772
script->fileNameObj = interp->emptyObj;
1580415773
Jim_IncrRefCount(script->fileNameObj);
1580515774
SubstObjAddTokens(interp, script, &tokenlist);
1580615775
15807
-
15776
+
1580815777
ScriptTokenListFree(&tokenlist);
1580915778
1581015779
#ifdef DEBUG_SHOW_SUBST
1581115780
{
1581215781
int i;
@@ -15817,11 +15786,11 @@
1581715786
Jim_String(script->token[i].objPtr));
1581815787
}
1581915788
}
1582015789
#endif
1582115790
15822
-
15791
+
1582315792
Jim_FreeIntRep(interp, objPtr);
1582415793
Jim_SetIntRepPtr(objPtr, script);
1582515794
objPtr->typePtr = &scriptObjType;
1582615795
return JIM_OK;
1582715796
}
@@ -15835,11 +15804,11 @@
1583515804
1583615805
int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
1583715806
{
1583815807
ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
1583915808
15840
- Jim_IncrRefCount(substObjPtr);
15809
+ Jim_IncrRefCount(substObjPtr);
1584115810
script->inUse++;
1584215811
1584315812
*resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
1584415813
1584515814
script->inUse--;
@@ -15851,22 +15820,24 @@
1585115820
}
1585215821
1585315822
void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
1585415823
{
1585515824
Jim_Obj *objPtr;
15856
- Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
15825
+ Jim_Obj *listObjPtr;
15826
+
15827
+ JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0"));
15828
+
15829
+ listObjPtr = Jim_NewListObj(interp, argv, argc);
1585715830
1585815831
if (*msg) {
1585915832
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
1586015833
}
1586115834
Jim_IncrRefCount(listObjPtr);
1586215835
objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
1586315836
Jim_DecrRefCount(interp, listObjPtr);
1586415837
15865
- Jim_IncrRefCount(objPtr);
1586615838
Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
15867
- Jim_DecrRefCount(interp, objPtr);
1586815839
}
1586915840
1587015841
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
1587115842
Jim_HashEntry *he, int type);
1587215843
@@ -15876,11 +15847,11 @@
1587615847
JimHashtableIteratorCallbackType *callback, int type)
1587715848
{
1587815849
Jim_HashEntry *he;
1587915850
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
1588015851
15881
-
15852
+
1588215853
if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
1588315854
he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
1588415855
if (he) {
1588515856
callback(interp, listObjPtr, he, type);
1588615857
}
@@ -15907,11 +15878,11 @@
1590715878
{
1590815879
Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
1590915880
Jim_Obj *objPtr;
1591015881
1591115882
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15912
-
15883
+
1591315884
return;
1591415885
}
1591515886
1591615887
objPtr = Jim_NewStringObj(interp, he->key, -1);
1591715888
Jim_IncrRefCount(objPtr);
@@ -15967,11 +15938,11 @@
1596715938
1596815939
targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
1596915940
if (targetCallFrame == NULL) {
1597015941
return JIM_ERR;
1597115942
}
15972
-
15943
+
1597315944
if (targetCallFrame == interp->topFramePtr) {
1597415945
Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
1597515946
return JIM_ERR;
1597615947
}
1597715948
if (info_level_cmd) {
@@ -16154,11 +16125,11 @@
1615416125
if (!objPtr)
1615516126
return JIM_ERR;
1615616127
Jim_SetResult(interp, objPtr);
1615716128
return JIM_OK;
1615816129
}
16159
-
16130
+
1616016131
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1616116132
return JIM_ERR;
1616216133
Jim_SetResult(interp, argv[2]);
1616316134
return JIM_OK;
1616416135
}
@@ -16197,11 +16168,11 @@
1619716168
if (argc != 3) {
1619816169
Jim_WrongNumArgs(interp, 1, argv, "condition body");
1619916170
return JIM_ERR;
1620016171
}
1620116172
16202
-
16173
+
1620316174
while (1) {
1620416175
int boolean, retval;
1620516176
1620616177
if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
1620716178
return retval;
@@ -16237,11 +16208,11 @@
1623716208
if (argc != 5) {
1623816209
Jim_WrongNumArgs(interp, 1, argv, "start test next body");
1623916210
return JIM_ERR;
1624016211
}
1624116212
16242
-
16213
+
1624316214
if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
1624416215
return retval;
1624516216
}
1624616217
1624716218
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16253,19 +16224,19 @@
1625316224
ExprByteCode *expr;
1625416225
jim_wide stop, currentVal;
1625516226
Jim_Obj *objPtr;
1625616227
int cmpOffset;
1625716228
16258
-
16229
+
1625916230
expr = JimGetExpression(interp, argv[2]);
1626016231
incrScript = JimGetScript(interp, argv[3]);
1626116232
16262
-
16233
+
1626316234
if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
1626416235
goto evalstart;
1626516236
}
16266
-
16237
+
1626716238
if (incrScript->token[1].type != JIM_TT_ESC ||
1626816239
expr->token[0].type != JIM_TT_VAR ||
1626916240
(expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
1627016241
goto evalstart;
1627116242
}
@@ -16278,48 +16249,48 @@
1627816249
}
1627916250
else {
1628016251
goto evalstart;
1628116252
}
1628216253
16283
-
16254
+
1628416255
if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
1628516256
goto evalstart;
1628616257
}
1628716258
16288
-
16259
+
1628916260
if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
1629016261
goto evalstart;
1629116262
}
1629216263
16293
-
16264
+
1629416265
if (expr->token[1].type == JIM_TT_EXPR_INT) {
1629516266
if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
1629616267
goto evalstart;
1629716268
}
1629816269
}
1629916270
else {
1630016271
stopVarNamePtr = expr->token[1].objPtr;
1630116272
Jim_IncrRefCount(stopVarNamePtr);
16302
-
16273
+
1630316274
stop = 0;
1630416275
}
1630516276
16306
-
16277
+
1630716278
varNamePtr = expr->token[0].objPtr;
1630816279
Jim_IncrRefCount(varNamePtr);
1630916280
1631016281
objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
1631116282
if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
1631216283
goto testcond;
1631316284
}
1631416285
16315
-
16286
+
1631616287
while (retval == JIM_OK) {
16317
-
16318
-
1631916288
16320
-
16289
+
16290
+
16291
+
1632116292
if (stopVarNamePtr) {
1632216293
objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
1632316294
if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
1632416295
goto testcond;
1632516296
}
@@ -16327,18 +16298,18 @@
1632716298
1632816299
if (currentVal >= stop + cmpOffset) {
1632916300
break;
1633016301
}
1633116302
16332
-
16303
+
1633316304
retval = Jim_EvalObj(interp, argv[4]);
1633416305
if (retval == JIM_OK || retval == JIM_CONTINUE) {
1633516306
retval = JIM_OK;
1633616307
1633716308
objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
1633816309
16339
-
16310
+
1634016311
if (objPtr == NULL) {
1634116312
retval = JIM_ERR;
1634216313
goto out;
1634316314
}
1634416315
if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16329,25 @@
1635816329
}
1635916330
evalstart:
1636016331
#endif
1636116332
1636216333
while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16363
-
16334
+
1636416335
retval = Jim_EvalObj(interp, argv[4]);
1636516336
1636616337
if (retval == JIM_OK || retval == JIM_CONTINUE) {
16367
-
16368
- evalnext:
16338
+
16339
+JIM_IF_OPTIM(evalnext:)
1636916340
retval = Jim_EvalObj(interp, argv[3]);
1637016341
if (retval == JIM_OK || retval == JIM_CONTINUE) {
16371
-
16372
- testcond:
16342
+
16343
+JIM_IF_OPTIM(testcond:)
1637316344
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
1637416345
}
1637516346
}
1637616347
}
16377
- out:
16348
+JIM_IF_OPTIM(out:)
1637816349
if (stopVarNamePtr) {
1637916350
Jim_DecrRefCount(interp, stopVarNamePtr);
1638016351
}
1638116352
if (varNamePtr) {
1638216353
Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16389,11 @@
1641816389
if (retval == JIM_OK || retval == JIM_CONTINUE) {
1641916390
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
1642016391
1642116392
retval = JIM_OK;
1642216393
16423
-
16394
+
1642416395
i += incr;
1642516396
1642616397
if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
1642716398
if (argv[1]->typePtr != &variableObjType) {
1642816399
if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16454,21 @@
1648316454
1648416455
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
1648516456
{
1648616457
int result = JIM_OK;
1648716458
int i, numargs;
16488
- Jim_ListIter twoiters[2];
16459
+ Jim_ListIter twoiters[2];
1648916460
Jim_ListIter *iters;
1649016461
Jim_Obj *script;
1649116462
Jim_Obj *resultObj;
1649216463
1649316464
if (argc < 4 || argc % 2 != 0) {
1649416465
Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
1649516466
return JIM_ERR;
1649616467
}
16497
- script = argv[argc - 1];
16498
- numargs = (argc - 1 - 1);
16468
+ script = argv[argc - 1];
16469
+ numargs = (argc - 1 - 1);
1649916470
1650016471
if (numargs == 2) {
1650116472
iters = twoiters;
1650216473
}
1650316474
else {
@@ -16521,34 +16492,34 @@
1652116492
resultObj = interp->emptyObj;
1652216493
}
1652316494
Jim_IncrRefCount(resultObj);
1652416495
1652516496
while (1) {
16526
-
16497
+
1652716498
for (i = 0; i < numargs; i += 2) {
1652816499
if (!JimListIterDone(interp, &iters[i + 1])) {
1652916500
break;
1653016501
}
1653116502
}
1653216503
if (i == numargs) {
16533
-
16504
+
1653416505
break;
1653516506
}
1653616507
16537
-
16508
+
1653816509
for (i = 0; i < numargs; i += 2) {
1653916510
Jim_Obj *varName;
1654016511
16541
-
16512
+
1654216513
JimListIterInit(&iters[i], argv[i + 1]);
1654316514
while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
1654416515
Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
1654516516
if (!valObj) {
16546
-
16517
+
1654716518
valObj = interp->emptyObj;
1654816519
}
16549
-
16520
+
1655016521
Jim_IncrRefCount(valObj);
1655116522
result = Jim_SetVariable(interp, varName, valObj);
1655216523
Jim_DecrRefCount(interp, valObj);
1655316524
if (result != JIM_OK) {
1655416525
goto err;
@@ -16630,41 +16601,41 @@
1663016601
{
1663116602
int boolean, retval, current = 1, falsebody = 0;
1663216603
1663316604
if (argc >= 3) {
1663416605
while (1) {
16635
-
16606
+
1663616607
if (current >= argc)
1663716608
goto err;
1663816609
if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
1663916610
!= JIM_OK)
1664016611
return retval;
16641
-
16612
+
1664216613
if (current >= argc)
1664316614
goto err;
1664416615
if (Jim_CompareStringImmediate(interp, argv[current], "then"))
1664516616
current++;
16646
-
16617
+
1664716618
if (current >= argc)
1664816619
goto err;
1664916620
if (boolean)
1665016621
return Jim_EvalObj(interp, argv[current]);
16651
-
16622
+
1665216623
if (++current >= argc) {
1665316624
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
1665416625
return JIM_OK;
1665516626
}
1665616627
falsebody = current++;
1665716628
if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16658
-
16629
+
1665916630
if (current != argc - 1)
1666016631
goto err;
1666116632
return Jim_EvalObj(interp, argv[current]);
1666216633
}
1666316634
else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
1666416635
continue;
16665
-
16636
+
1666616637
else if (falsebody != argc - 1)
1666716638
goto err;
1666816639
return Jim_EvalObj(interp, argv[falsebody]);
1666916640
}
1667016641
return JIM_OK;
@@ -16772,21 +16743,21 @@
1677216743
if (Jim_StringMatchObj(interp, patObj, strObj, 0))
1677316744
script = caseList[i + 1];
1677416745
break;
1677516746
case SWITCH_RE:
1677616747
command = Jim_NewStringObj(interp, "regexp", -1);
16777
-
16748
+
1677816749
case SWITCH_CMD:{
1677916750
int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
1678016751
1678116752
if (argc - opt == 1) {
1678216753
Jim_Obj **vector;
1678316754
1678416755
JimListGetElements(interp, argv[opt], &patCount, &vector);
1678516756
caseList = vector;
1678616757
}
16787
-
16758
+
1678816759
if (rc < 0) {
1678916760
return -rc;
1679016761
}
1679116762
if (rc)
1679216763
script = caseList[i + 1];
@@ -16920,11 +16891,11 @@
1692016891
case OPT_COMMAND:
1692116892
if (i >= argc - 2) {
1692216893
goto wrongargs;
1692316894
}
1692416895
commandObj = argv[++i];
16925
-
16896
+
1692616897
case OPT_EXACT:
1692716898
case OPT_GLOB:
1692816899
case OPT_REGEXP:
1692916900
opt_match = option;
1693016901
break;
@@ -16968,17 +16939,17 @@
1696816939
goto done;
1696916940
}
1697016941
break;
1697116942
}
1697216943
16973
-
16944
+
1697416945
if (!eq && opt_bool && opt_not && !opt_all) {
1697516946
continue;
1697616947
}
1697716948
1697816949
if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16979
-
16950
+
1698016951
Jim_Obj *resultObj;
1698116952
1698216953
if (opt_bool) {
1698316954
resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
1698416955
}
@@ -17001,11 +16972,11 @@
1700116972
1700216973
if (opt_all) {
1700316974
Jim_SetResult(interp, listObjPtr);
1700416975
}
1700516976
else {
17006
-
16977
+
1700716978
if (opt_bool) {
1700816979
Jim_SetResultBool(interp, opt_not);
1700916980
}
1701016981
else if (!opt_inline) {
1701116982
Jim_SetResultInt(interp, -1);
@@ -17030,11 +17001,11 @@
1703017001
Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
1703117002
return JIM_ERR;
1703217003
}
1703317004
listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1703417005
if (!listObjPtr) {
17035
-
17006
+
1703617007
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1703717008
new_obj = 1;
1703817009
}
1703917010
else if (Jim_IsShared(listObjPtr)) {
1704017011
listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +17074,31 @@
1710317074
first = JimRelToAbsIndex(len, first);
1710417075
last = JimRelToAbsIndex(len, last);
1710517076
JimRelToAbsRange(len, &first, &last, &rangeLen);
1710617077
1710717078
17108
-
17079
+
1710917080
if (first < len) {
17110
-
17081
+
1711117082
}
1711217083
else if (len == 0) {
17113
-
17084
+
1711417085
first = 0;
1711517086
}
1711617087
else {
1711717088
Jim_SetResultString(interp, "list doesn't contain element ", -1);
1711817089
Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
1711917090
return JIM_ERR;
1712017091
}
1712117092
17122
-
17093
+
1712317094
newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
1712417095
17125
-
17096
+
1712617097
ListInsertElements(newListObj, -1, argc - 4, argv + 4);
1712717098
17128
-
17099
+
1712917100
ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
1713017101
1713117102
Jim_SetResult(interp, newListObj);
1713217103
return JIM_OK;
1713317104
}
@@ -17138,11 +17109,11 @@
1713817109
if (argc < 3) {
1713917110
Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
1714017111
return JIM_ERR;
1714117112
}
1714217113
else if (argc == 3) {
17143
-
17114
+
1714417115
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1714517116
return JIM_ERR;
1714617117
Jim_SetResult(interp, argv[2]);
1714717118
return JIM_OK;
1714817119
}
@@ -17253,11 +17224,11 @@
1725317224
}
1725417225
else {
1725517226
int new_obj = 0;
1725617227
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
1725717228
if (!stringObjPtr) {
17258
-
17229
+
1725917230
stringObjPtr = Jim_NewEmptyStringObj(interp);
1726017231
new_obj = 1;
1726117232
}
1726217233
else if (Jim_IsShared(stringObjPtr)) {
1726317234
new_obj = 1;
@@ -17302,11 +17273,11 @@
1730217273
else {
1730317274
rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1730417275
}
1730517276
1730617277
if (rc == JIM_ERR) {
17307
-
17278
+
1730817279
interp->addStackTrace++;
1730917280
}
1731017281
return rc;
1731117282
}
1731217283
@@ -17316,14 +17287,14 @@
1731617287
if (argc >= 2) {
1731717288
int retcode;
1731817289
Jim_CallFrame *savedCallFrame, *targetCallFrame;
1731917290
const char *str;
1732017291
17321
-
17292
+
1732217293
savedCallFrame = interp->framePtr;
1732317294
17324
-
17295
+
1732517296
str = Jim_String(argv[1]);
1732617297
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
1732717298
targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1732817299
argc--;
1732917300
argv++;
@@ -17336,11 +17307,11 @@
1733617307
}
1733717308
if (argc < 2) {
1733817309
Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
1733917310
return JIM_ERR;
1734017311
}
17341
-
17312
+
1734217313
interp->framePtr = targetCallFrame;
1734317314
if (argc == 2) {
1734417315
retcode = Jim_EvalObj(interp, argv[1]);
1734517316
}
1734617317
else {
@@ -17438,15 +17409,15 @@
1743817409
if (i != argc - 1 && i != argc) {
1743917410
Jim_WrongNumArgs(interp, 1, argv,
1744017411
"?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
1744117412
}
1744217413
17443
-
17414
+
1744417415
if (stackTraceObj && returnCode == JIM_ERR) {
1744517416
JimSetStackTrace(interp, stackTraceObj);
1744617417
}
17447
-
17418
+
1744817419
if (errorCodeObj && returnCode == JIM_ERR) {
1744917420
Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
1745017421
}
1745117422
interp->returnCode = returnCode;
1745217423
interp->returnLevel = level;
@@ -17463,31 +17434,31 @@
1746317434
if (interp->framePtr->level == 0) {
1746417435
Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
1746517436
return JIM_ERR;
1746617437
}
1746717438
else if (argc >= 2) {
17468
-
17439
+
1746917440
Jim_CallFrame *cf = interp->framePtr->parent;
1747017441
1747117442
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
1747217443
if (cmdPtr == NULL) {
1747317444
return JIM_ERR;
1747417445
}
1747517446
1747617447
JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
1747717448
17478
-
17449
+
1747917450
JimIncrCmdRefCount(cmdPtr);
1748017451
cf->tailcallCmd = cmdPtr;
1748117452
17482
-
17453
+
1748317454
JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
1748417455
1748517456
cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
1748617457
Jim_IncrRefCount(cf->tailcallObj);
1748717458
17488
-
17459
+
1748917460
return JIM_EVAL;
1749017461
}
1749117462
return JIM_OK;
1749217463
}
1749317464
@@ -17494,11 +17465,11 @@
1749417465
static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1749517466
{
1749617467
Jim_Obj *cmdList;
1749717468
Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
1749817469
17499
-
17470
+
1750017471
cmdList = Jim_DuplicateObj(interp, prefixListObj);
1750117472
Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
1750217473
1750317474
return JimEvalObjList(interp, cmdList);
1750417475
}
@@ -17552,22 +17523,22 @@
1755217523
else {
1755317524
cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
1755417525
}
1755517526
1755617527
if (cmd) {
17557
-
17528
+
1755817529
Jim_Obj *qualifiedCmdNameObj;
1755917530
const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
1756017531
1756117532
JimCreateCommand(interp, cmdname, cmd);
1756217533
17563
-
17534
+
1756417535
JimUpdateProcNamespace(interp, cmd, cmdname);
1756517536
1756617537
JimFreeQualifiedName(interp, qualifiedCmdNameObj);
1756717538
17568
-
17539
+
1756917540
Jim_SetResult(interp, argv[1]);
1757017541
return JIM_OK;
1757117542
}
1757217543
return JIM_ERR;
1757317544
}
@@ -17580,17 +17551,17 @@
1758017551
if (argc < 2) {
1758117552
Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
1758217553
return JIM_ERR;
1758317554
}
1758417555
17585
-
17556
+
1758617557
interp->local++;
1758717558
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
1758817559
interp->local--;
1758917560
1759017561
17591
-
17562
+
1759217563
if (retcode == 0) {
1759317564
Jim_Obj *cmdNameObj = Jim_GetResult(interp);
1759417565
1759517566
if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
1759617567
return JIM_ERR;
@@ -17619,18 +17590,18 @@
1761917590
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
1762017591
if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
1762117592
Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
1762217593
return JIM_ERR;
1762317594
}
17624
-
17595
+
1762517596
cmdPtr->u.proc.upcall++;
1762617597
JimIncrCmdRefCount(cmdPtr);
1762717598
17628
-
17599
+
1762917600
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
1763017601
17631
-
17602
+
1763217603
cmdPtr->u.proc.upcall--;
1763317604
JimDecrCmdRefCount(interp, cmdPtr);
1763417605
1763517606
return retcode;
1763617607
}
@@ -17657,11 +17628,11 @@
1765717628
return JIM_ERR;
1765817629
}
1765917630
1766017631
if (len == 3) {
1766117632
#ifdef jim_ext_namespace
17662
-
17633
+
1766317634
nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
1766417635
#else
1766517636
Jim_SetResultString(interp, "namespaces not enabled", -1);
1766617637
return JIM_ERR;
1766717638
#endif
@@ -17670,11 +17641,11 @@
1767017641
bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
1767117642
1767217643
cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
1767317644
1767417645
if (cmd) {
17675
-
17646
+
1767617647
nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
1767717648
nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
1767817649
Jim_IncrRefCount(nargv[0]);
1767917650
memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
1768017651
ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17671,11 @@
1770017671
static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1770117672
{
1770217673
int i;
1770317674
Jim_CallFrame *targetCallFrame;
1770417675
17705
-
17676
+
1770617677
if (argc > 3 && (argc % 2 == 0)) {
1770717678
targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1770817679
argc--;
1770917680
argv++;
1771017681
}
@@ -17713,17 +17684,17 @@
1771317684
}
1771417685
if (targetCallFrame == NULL) {
1771517686
return JIM_ERR;
1771617687
}
1771717688
17718
-
17689
+
1771917690
if (argc < 3) {
1772017691
Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
1772117692
return JIM_ERR;
1772217693
}
1772317694
17724
-
17695
+
1772517696
for (i = 1; i < argc; i += 2) {
1772617697
if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
1772717698
return JIM_ERR;
1772817699
}
1772917700
return JIM_OK;
@@ -17736,15 +17707,15 @@
1773617707
1773717708
if (argc < 2) {
1773817709
Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
1773917710
return JIM_ERR;
1774017711
}
17741
-
17712
+
1774217713
if (interp->framePtr->level == 0)
17743
- return JIM_OK;
17714
+ return JIM_OK;
1774417715
for (i = 1; i < argc; i++) {
17745
-
17716
+
1774617717
const char *name = Jim_String(argv[i]);
1774717718
if (name[0] != ':' || name[1] != ':') {
1774817719
if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
1774917720
return JIM_ERR;
1775017721
}
@@ -17767,21 +17738,21 @@
1776717738
}
1776817739
1776917740
str = Jim_String(objPtr);
1777017741
strLen = Jim_Utf8Length(interp, objPtr);
1777117742
17772
-
17743
+
1777317744
resultObjPtr = Jim_NewStringObj(interp, "", 0);
1777417745
while (strLen) {
1777517746
for (i = 0; i < numMaps; i += 2) {
17776
- Jim_Obj *objPtr;
17747
+ Jim_Obj *eachObjPtr;
1777717748
const char *k;
1777817749
int kl;
1777917750
17780
- objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17781
- k = Jim_String(objPtr);
17782
- kl = Jim_Utf8Length(interp, objPtr);
17751
+ eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17752
+ k = Jim_String(eachObjPtr);
17753
+ kl = Jim_Utf8Length(interp, eachObjPtr);
1778317754
1778417755
if (strLen >= kl && kl) {
1778517756
int rc;
1778617757
rc = JimStringCompareLen(str, k, kl, nocase);
1778717758
if (rc == 0) {
@@ -17794,11 +17765,11 @@
1779417765
strLen -= kl;
1779517766
break;
1779617767
}
1779717768
}
1779817769
}
17799
- if (i == numMaps) {
17770
+ if (i == numMaps) {
1780017771
int c;
1780117772
if (noMatchStart == NULL)
1780217773
noMatchStart = str;
1780317774
str += utf8_tounicode(str, &c);
1780417775
strLen--;
@@ -17838,11 +17809,11 @@
1783817809
Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
1783917810
return JIM_ERR;
1784017811
}
1784117812
if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
1784217813
JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17843
- return JIM_ERR;
17814
+ return Jim_CheckShowCommands(interp, argv[1], options);
1784417815
1784517816
switch (option) {
1784617817
case OPT_LENGTH:
1784717818
case OPT_BYTELENGTH:
1784817819
if (argc != 3) {
@@ -17859,11 +17830,11 @@
1785917830
return JIM_OK;
1786017831
1786117832
case OPT_CAT:{
1786217833
Jim_Obj *objPtr;
1786317834
if (argc == 3) {
17864
-
17835
+
1786517836
objPtr = argv[2];
1786617837
}
1786717838
else {
1786817839
int i;
1786917840
@@ -17878,11 +17849,11 @@
1787817849
}
1787917850
1788017851
case OPT_COMPARE:
1788117852
case OPT_EQUAL:
1788217853
{
17883
-
17854
+
1788417855
long opt_length = -1;
1788517856
int n = argc - 4;
1788617857
int i = 2;
1788717858
while (n > 0) {
1788817859
int subopt;
@@ -17891,16 +17862,16 @@
1789117862
badcompareargs:
1789217863
Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
1789317864
return JIM_ERR;
1789417865
}
1789517866
if (subopt == 0) {
17896
-
17867
+
1789717868
opt_case = 0;
1789817869
n--;
1789917870
}
1790017871
else {
17901
-
17872
+
1790217873
if (n < 2) {
1790317874
goto badcompareargs;
1790417875
}
1790517876
if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
1790617877
return JIM_ERR;
@@ -17911,11 +17882,11 @@
1791117882
if (n) {
1791217883
goto badcompareargs;
1791317884
}
1791417885
argv += argc - 2;
1791517886
if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17916
-
17887
+
1791717888
Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
1791817889
}
1791917890
else {
1792017891
if (opt_length >= 0) {
1792117892
n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17996,10 @@
1802517996
}
1802617997
1802717998
case OPT_REVERSE:{
1802817999
char *buf, *p;
1802918000
const char *str;
18030
- int len;
1803118001
int i;
1803218002
1803318003
if (argc != 3) {
1803418004
Jim_WrongNumArgs(interp, 2, argv, "string");
1803518005
return JIM_ERR;
@@ -18069,11 +18039,11 @@
1806918039
}
1807018040
if (idx < 0 || idx >= len || str == NULL) {
1807118041
Jim_SetResultString(interp, "", 0);
1807218042
}
1807318043
else if (len == Jim_Length(argv[2])) {
18074
-
18044
+
1807518045
Jim_SetResultString(interp, str + idx, 1);
1807618046
}
1807718047
else {
1807818048
int c;
1807918049
int i = utf8_index(str, idx);
@@ -18223,11 +18193,11 @@
1822318193
{
1822418194
int exitCode = 0;
1822518195
int i;
1822618196
int sig = 0;
1822718197
18228
-
18198
+
1822918199
jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
1823018200
static const int max_ignore_code = sizeof(ignore_mask) * 8;
1823118201
1823218202
Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
1823318203
@@ -18234,11 +18204,11 @@
1823418204
for (i = 1; i < argc - 1; i++) {
1823518205
const char *arg = Jim_String(argv[i]);
1823618206
jim_wide option;
1823718207
int ignore;
1823818208
18239
-
18209
+
1824018210
if (strcmp(arg, "--") == 0) {
1824118211
i++;
1824218212
break;
1824318213
}
1824418214
if (*arg != '-') {
@@ -18285,28 +18255,28 @@
1828518255
sig++;
1828618256
}
1828718257
1828818258
interp->signal_level += sig;
1828918259
if (Jim_CheckSignal(interp)) {
18290
-
18260
+
1829118261
exitCode = JIM_SIGNAL;
1829218262
}
1829318263
else {
1829418264
exitCode = Jim_EvalObj(interp, argv[0]);
18295
-
18265
+
1829618266
interp->errorFlag = 0;
1829718267
}
1829818268
interp->signal_level -= sig;
1829918269
18300
-
18270
+
1830118271
if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18302
-
18272
+
1830318273
return exitCode;
1830418274
}
1830518275
1830618276
if (sig && exitCode == JIM_SIGNAL) {
18307
-
18277
+
1830818278
if (interp->signal_set_result) {
1830918279
interp->signal_set_result(interp, interp->sigmask);
1831018280
}
1831118281
else {
1831218282
Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18315,10 @@
1834518315
}
1834618316
Jim_SetResultInt(interp, exitCode);
1834718317
return JIM_OK;
1834818318
}
1834918319
18350
-#ifdef JIM_REFERENCES
18351
-
18352
-
18353
-static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18354
-{
18355
- if (argc != 3 && argc != 4) {
18356
- Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?");
18357
- return JIM_ERR;
18358
- }
18359
- if (argc == 3) {
18360
- Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL));
18361
- }
18362
- else {
18363
- Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3]));
18364
- }
18365
- return JIM_OK;
18366
-}
18367
-
18368
-
18369
-static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18370
-{
18371
- Jim_Reference *refPtr;
18372
-
18373
- if (argc != 2) {
18374
- Jim_WrongNumArgs(interp, 1, argv, "reference");
18375
- return JIM_ERR;
18376
- }
18377
- if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18378
- return JIM_ERR;
18379
- Jim_SetResult(interp, refPtr->objPtr);
18380
- return JIM_OK;
18381
-}
18382
-
18383
-
18384
-static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18385
-{
18386
- Jim_Reference *refPtr;
18387
-
18388
- if (argc != 3) {
18389
- Jim_WrongNumArgs(interp, 1, argv, "reference newValue");
18390
- return JIM_ERR;
18391
- }
18392
- if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18393
- return JIM_ERR;
18394
- Jim_IncrRefCount(argv[2]);
18395
- Jim_DecrRefCount(interp, refPtr->objPtr);
18396
- refPtr->objPtr = argv[2];
18397
- Jim_SetResult(interp, argv[2]);
18398
- return JIM_OK;
18399
-}
18400
-
18401
-
18402
-static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18403
-{
18404
- if (argc != 1) {
18405
- Jim_WrongNumArgs(interp, 1, argv, "");
18406
- return JIM_ERR;
18407
- }
18408
- Jim_SetResultInt(interp, Jim_Collect(interp));
18409
-
18410
-
18411
- while (interp->freeList) {
18412
- Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
18413
- Jim_Free(interp->freeList);
18414
- interp->freeList = nextObjPtr;
18415
- }
18416
-
18417
- return JIM_OK;
18418
-}
18419
-
18420
-
18421
-static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18422
-{
18423
- if (argc != 2 && argc != 3) {
18424
- Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?");
18425
- return JIM_ERR;
18426
- }
18427
- if (argc == 2) {
18428
- Jim_Obj *cmdNamePtr;
18429
-
18430
- if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
18431
- return JIM_ERR;
18432
- if (cmdNamePtr != NULL)
18433
- Jim_SetResult(interp, cmdNamePtr);
18434
- }
18435
- else {
18436
- if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK)
18437
- return JIM_ERR;
18438
- Jim_SetResult(interp, argv[2]);
18439
- }
18440
- return JIM_OK;
18441
-}
18442
-
18443
-
18444
-static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18445
-{
18446
- Jim_Obj *listObjPtr;
18447
- Jim_HashTableIterator htiter;
18448
- Jim_HashEntry *he;
18449
-
18450
- listObjPtr = Jim_NewListObj(interp, NULL, 0);
18451
-
18452
- JimInitHashTableIterator(&interp->references, &htiter);
18453
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18454
- char buf[JIM_REFERENCE_SPACE + 1];
18455
- Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18456
- const unsigned long *refId = he->key;
18457
-
18458
- JimFormatReference(buf, refPtr, *refId);
18459
- Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18460
- }
18461
- Jim_SetResult(interp, listObjPtr);
18462
- return JIM_OK;
18463
-}
18464
-#endif
1846518320
1846618321
1846718322
static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1846818323
{
1846918324
if (argc != 3) {
@@ -18476,56 +18331,43 @@
1847618331
}
1847718332
1847818333
return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
1847918334
}
1848018335
18481
-#define JIM_DICTMATCH_VALUES 0x0001
18482
-
18483
-typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
18484
-
18485
-static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18486
-{
18487
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18488
- if (type & JIM_DICTMATCH_VALUES) {
18489
- Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18490
- }
18491
-}
18492
-
18493
-static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18494
- JimDictMatchCallbackType *callback, int type)
18495
-{
18496
- Jim_HashEntry *he;
18497
- Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18498
-
18499
-
18500
- Jim_HashTableIterator htiter;
18501
- JimInitHashTableIterator(ht, &htiter);
18502
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18503
- if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18504
- callback(interp, listObjPtr, he, type);
18505
- }
18506
- }
18507
-
18508
- return listObjPtr;
18509
-}
18510
-
18511
-
18512
-int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18513
-{
18514
- if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18515
- return JIM_ERR;
18516
- }
18517
- Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
18518
- return JIM_OK;
18519
-}
18520
-
18521
-int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18522
-{
18523
- if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18524
- return JIM_ERR;
18525
- }
18526
- Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
18336
+#define JIM_DICTMATCH_KEYS 0x0001
18337
+#define JIM_DICTMATCH_VALUES 0x002
18338
+
18339
+int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types)
18340
+{
18341
+ Jim_HashEntry *he;
18342
+ Jim_Obj *listObjPtr;
18343
+ Jim_HashTableIterator htiter;
18344
+
18345
+ if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18346
+ return JIM_ERR;
18347
+ }
18348
+
18349
+ listObjPtr = Jim_NewListObj(interp, NULL, 0);
18350
+
18351
+ JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter);
18352
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18353
+ if (patternObj) {
18354
+ Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
18355
+ if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
18356
+
18357
+ continue;
18358
+ }
18359
+ }
18360
+ if (return_types & JIM_DICTMATCH_KEYS) {
18361
+ Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18362
+ }
18363
+ if (return_types & JIM_DICTMATCH_VALUES) {
18364
+ Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18365
+ }
18366
+ }
18367
+
18368
+ Jim_SetResult(interp, listObjPtr);
1852718369
return JIM_OK;
1852818370
}
1852918371
1853018372
int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
1853118373
{
@@ -18532,38 +18374,85 @@
1853218374
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1853318375
return -1;
1853418376
}
1853518377
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
1853618378
}
18379
+
18380
+Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
18381
+{
18382
+ Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0);
18383
+ int i;
18384
+
18385
+ JimPanic((objc == 0, "Jim_DictMerge called with objc=0"));
18386
+
18387
+
18388
+
18389
+ for (i = 0; i < objc; i++) {
18390
+ Jim_HashTable *ht;
18391
+ Jim_HashTableIterator htiter;
18392
+ Jim_HashEntry *he;
18393
+
18394
+ if (SetDictFromAny(interp, objv[i]) != JIM_OK) {
18395
+ Jim_FreeNewObj(interp, objPtr);
18396
+ return NULL;
18397
+ }
18398
+ ht = objv[i]->internalRep.ptr;
18399
+ JimInitHashTableIterator(ht, &htiter);
18400
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18401
+ Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he));
18402
+ }
18403
+ }
18404
+ return objPtr;
18405
+}
1853718406
1853818407
int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
1853918408
{
1854018409
Jim_HashTable *ht;
1854118410
unsigned int i;
18411
+ char buffer[100];
18412
+ int sum = 0;
18413
+ int nonzero_count = 0;
18414
+ Jim_Obj *output;
18415
+ int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1854218416
1854318417
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1854418418
return JIM_ERR;
1854518419
}
1854618420
1854718421
ht = (Jim_HashTable *)objPtr->internalRep.ptr;
1854818422
18549
-
18550
- printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18423
+
18424
+ snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
18425
+ output = Jim_NewStringObj(interp, buffer, -1);
1855118426
1855218427
for (i = 0; i < ht->size; i++) {
1855318428
Jim_HashEntry *he = ht->table[i];
18554
-
18555
- if (he) {
18556
- printf("%d: ", i);
18557
-
18558
- while (he) {
18559
- printf(" %s", Jim_String(he->key));
18560
- he = he->next;
18561
- }
18562
- printf("\n");
18429
+ int entries = 0;
18430
+ while (he) {
18431
+ entries++;
18432
+ he = he->next;
18433
+ }
18434
+ if (entries > 9) {
18435
+ bucket_counts[10]++;
18436
+ }
18437
+ else {
18438
+ bucket_counts[entries]++;
18439
+ }
18440
+ if (entries) {
18441
+ sum += entries;
18442
+ nonzero_count++;
1856318443
}
1856418444
}
18445
+ for (i = 0; i < 10; i++) {
18446
+ snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
18447
+ Jim_AppendString(interp, output, buffer, -1);
18448
+ }
18449
+ snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
18450
+ Jim_AppendString(interp, output, buffer, -1);
18451
+ snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
18452
+ Jim_AppendString(interp, output, buffer, -1);
18453
+ Jim_SetResult(interp, output);
1856518454
return JIM_OK;
1856618455
}
1856718456
1856818457
static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
1856918458
{
@@ -18573,14 +18462,67 @@
1857318462
Jim_AppendString(interp, prefixObj, subcmd, -1);
1857418463
1857518464
return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
1857618465
}
1857718466
18467
+static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj)
18468
+{
18469
+ int i;
18470
+ Jim_Obj *objPtr;
18471
+ Jim_Obj *dictObj;
18472
+ Jim_Obj **dictValues;
18473
+ int len;
18474
+ int ret = JIM_OK;
18475
+
18476
+
18477
+ dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG);
18478
+ if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) {
18479
+ return JIM_ERR;
18480
+ }
18481
+
18482
+ if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) {
18483
+ return JIM_ERR;
18484
+ }
18485
+ for (i = 0; i < len; i += 2) {
18486
+ if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) {
18487
+ Jim_Free(dictValues);
18488
+ return JIM_ERR;
18489
+ }
18490
+ }
18491
+
18492
+
18493
+ if (Jim_Length(scriptObj)) {
18494
+ ret = Jim_EvalObj(interp, scriptObj);
18495
+
18496
+
18497
+ if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) {
18498
+
18499
+ Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1));
18500
+ for (i = 0; i < keyc; i++) {
18501
+ newkeyv[i] = keyv[i];
18502
+ }
18503
+
18504
+ for (i = 0; i < len; i += 2) {
18505
+
18506
+ objPtr = Jim_GetVariable(interp, dictValues[i], 0);
18507
+ newkeyv[keyc] = dictValues[i];
18508
+ Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0);
18509
+ }
18510
+ Jim_Free(newkeyv);
18511
+ }
18512
+ }
18513
+
18514
+ Jim_Free(dictValues);
18515
+
18516
+ return ret;
18517
+}
18518
+
1857818519
1857918520
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1858018521
{
1858118522
Jim_Obj *objPtr;
18523
+ int types = JIM_DICTMATCH_KEYS;
1858218524
int option;
1858318525
static const char * const options[] = {
1858418526
"create", "get", "set", "unset", "exists", "keys", "size", "info",
1858518527
"merge", "with", "append", "lappend", "incr", "remove", "values", "for",
1858618528
"replace", "update", NULL
@@ -18596,11 +18538,11 @@
1859618538
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
1859718539
return JIM_ERR;
1859818540
}
1859918541
1860018542
if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18601
- return JIM_ERR;
18543
+ return Jim_CheckShowCommands(interp, argv[1], options);
1860218544
}
1860318545
1860418546
switch (option) {
1860518547
case OPT_GET:
1860618548
if (argc < 3) {
@@ -18643,16 +18585,19 @@
1864318585
if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
1864418586
return JIM_ERR;
1864518587
}
1864618588
return JIM_OK;
1864718589
18590
+ case OPT_VALUES:
18591
+ types = JIM_DICTMATCH_VALUES;
18592
+
1864818593
case OPT_KEYS:
1864918594
if (argc != 3 && argc != 4) {
1865018595
Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
1865118596
return JIM_ERR;
1865218597
}
18653
- return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18598
+ return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types);
1865418599
1865518600
case OPT_SIZE:
1865618601
if (argc != 3) {
1865718602
Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1865818603
return JIM_ERR;
@@ -18665,19 +18610,20 @@
1866518610
1866618611
case OPT_MERGE:
1866718612
if (argc == 2) {
1866818613
return JIM_OK;
1866918614
}
18670
- if (Jim_DictSize(interp, argv[2]) < 0) {
18615
+ objPtr = Jim_DictMerge(interp, argc - 2, argv + 2);
18616
+ if (objPtr == NULL) {
1867118617
return JIM_ERR;
1867218618
}
18673
-
18674
- break;
18619
+ Jim_SetResult(interp, objPtr);
18620
+ return JIM_OK;
1867518621
1867618622
case OPT_UPDATE:
1867718623
if (argc < 6 || argc % 2) {
18678
-
18624
+
1867918625
argc = 2;
1868018626
}
1868118627
break;
1868218628
1868318629
case OPT_CREATE:
@@ -18693,12 +18639,19 @@
1869318639
if (argc != 3) {
1869418640
Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1869518641
return JIM_ERR;
1869618642
}
1869718643
return Jim_DictInfo(interp, argv[2]);
18644
+
18645
+ case OPT_WITH:
18646
+ if (argc < 4) {
18647
+ Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18648
+ return JIM_ERR;
18649
+ }
18650
+ return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]);
1869818651
}
18699
-
18652
+
1870018653
return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
1870118654
}
1870218655
1870318656
1870418657
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18717,11 @@
1876418717
1876518718
#ifdef jim_ext_namespace
1876618719
int nons = 0;
1876718720
1876818721
if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18769
-
18722
+
1877018723
argc--;
1877118724
argv++;
1877218725
nons = 1;
1877318726
}
1877418727
#endif
@@ -18775,16 +18728,15 @@
1877518728
1877618729
if (argc < 2) {
1877718730
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
1877818731
return JIM_ERR;
1877918732
}
18780
- if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV)
18781
- != JIM_OK) {
18782
- return JIM_ERR;
18733
+ if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
18734
+ return Jim_CheckShowCommands(interp, argv[1], commands);
1878318735
}
1878418736
18785
-
18737
+
1878618738
switch (cmd) {
1878718739
case INFO_EXISTS:
1878818740
if (argc != 3) {
1878918741
Jim_WrongNumArgs(interp, 2, argv, "varName");
1879018742
return JIM_ERR;
@@ -18809,21 +18761,21 @@
1880918761
Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
1881018762
return JIM_OK;
1881118763
}
1881218764
1881318765
case INFO_CHANNELS:
18814
- mode++;
18766
+ mode++;
1881518767
#ifndef jim_ext_aio
1881618768
Jim_SetResultString(interp, "aio not enabled", -1);
1881718769
return JIM_ERR;
1881818770
#endif
18819
-
18771
+
1882018772
case INFO_PROCS:
18821
- mode++;
18822
-
18773
+ mode++;
18774
+
1882318775
case INFO_COMMANDS:
18824
-
18776
+
1882518777
if (argc != 2 && argc != 3) {
1882618778
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
1882718779
return JIM_ERR;
1882818780
}
1882918781
#ifdef jim_ext_namespace
@@ -18835,17 +18787,17 @@
1883518787
#endif
1883618788
Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
1883718789
break;
1883818790
1883918791
case INFO_VARS:
18840
- mode++;
18841
-
18792
+ mode++;
18793
+
1884218794
case INFO_LOCALS:
18843
- mode++;
18844
-
18795
+ mode++;
18796
+
1884518797
case INFO_GLOBALS:
18846
-
18798
+
1884718799
if (argc != 2 && argc != 3) {
1884818800
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
1884918801
return JIM_ERR;
1885018802
}
1885118803
#ifdef jim_ext_namespace
@@ -18951,13 +18903,12 @@
1895118903
case INFO_ARGS:
1895218904
Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
1895318905
break;
1895418906
case INFO_STATICS:
1895518907
if (cmdPtr->u.proc.staticVars) {
18956
- int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
1895718908
Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18958
- NULL, JimVariablesMatch, mode));
18909
+ NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES));
1895918910
}
1896018911
break;
1896118912
}
1896218913
break;
1896318914
}
@@ -18985,15 +18936,15 @@
1898518936
}
1898618937
}
1898718938
break;
1898818939
1898918940
case INFO_HOSTNAME:
18990
-
18941
+
1899118942
return Jim_Eval(interp, "os.gethostname");
1899218943
1899318944
case INFO_NAMEOFEXECUTABLE:
18994
-
18945
+
1899518946
return Jim_Eval(interp, "{info nameofexecutable}");
1899618947
1899718948
case INFO_RETURNCODES:
1899818949
if (argc == 2) {
1899918950
int i;
@@ -19070,11 +19021,11 @@
1907019021
1907119022
if (option == OPT_VAR) {
1907219023
result = Jim_GetVariable(interp, objPtr, 0) != NULL;
1907319024
}
1907419025
else {
19075
-
19026
+
1907619027
Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
1907719028
1907819029
if (cmd) {
1907919030
switch (option) {
1908019031
case OPT_COMMAND:
@@ -19113,11 +19064,11 @@
1911319064
if (len == 0) {
1911419065
return JIM_OK;
1911519066
}
1911619067
strLen = Jim_Utf8Length(interp, argv[1]);
1911719068
19118
-
19069
+
1911919070
if (argc == 2) {
1912019071
splitChars = " \n\t\r";
1912119072
splitLen = 4;
1912219073
}
1912319074
else {
@@ -19126,11 +19077,11 @@
1912619077
}
1912719078
1912819079
noMatchStart = str;
1912919080
resObjPtr = Jim_NewListObj(interp, NULL, 0);
1913019081
19131
-
19082
+
1913219083
if (splitLen) {
1913319084
Jim_Obj *objPtr;
1913419085
while (strLen--) {
1913519086
const char *sc = splitChars;
1913619087
int scLen = splitLen;
@@ -19155,11 +19106,11 @@
1915519106
#define NUM_COMMON (128 - 9)
1915619107
while (strLen--) {
1915719108
int n = utf8_tounicode(str, &c);
1915819109
#ifdef JIM_OPTIMIZATION
1915919110
if (c >= 9 && c < 128) {
19160
-
19111
+
1916119112
c -= 9;
1916219113
if (!commonObj) {
1916319114
commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
1916419115
memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
1916519116
}
@@ -19189,11 +19140,11 @@
1918919140
1919019141
if (argc != 2 && argc != 3) {
1919119142
Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
1919219143
return JIM_ERR;
1919319144
}
19194
-
19145
+
1919519146
if (argc == 2) {
1919619147
joinStr = " ";
1919719148
joinStrLen = 1;
1919819149
}
1919919150
else {
@@ -19468,13 +19419,13 @@
1946819419
return -1;
1946919420
else if (step < 0 && end > start)
1947019421
return -1;
1947119422
len = end - start;
1947219423
if (len < 0)
19473
- len = -len;
19424
+ len = -len;
1947419425
if (step < 0)
19475
- step = -step;
19426
+ step = -step;
1947619427
len = 1 + ((len - 1) / step);
1947719428
if (len > INT_MAX)
1947819429
len = INT_MAX;
1947919430
return (int)((len < 0) ? -1 : len);
1948019431
}
@@ -19644,40 +19595,68 @@
1964419595
argv[1] = interp->result;
1964519596
1964619597
Jim_EvalObjVector(interp, 2, argv);
1964719598
}
1964819599
19649
-static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19650
- const char *prefix, const char *const *tablePtr, const char *name)
19600
+static char **JimSortStringTable(const char *const *tablePtr)
1965119601
{
1965219602
int count;
1965319603
char **tablePtrSorted;
19654
- int i;
19604
+
1965519605
1965619606
for (count = 0; tablePtr[count]; count++) {
1965719607
}
1965819608
19609
+
19610
+ tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1));
19611
+ memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19612
+ qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19613
+ tablePtrSorted[count] = NULL;
19614
+
19615
+ return tablePtrSorted;
19616
+}
19617
+
19618
+static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19619
+ const char *prefix, const char *const *tablePtr, const char *name)
19620
+{
19621
+ char **tablePtrSorted;
19622
+ int i;
19623
+
1965919624
if (name == NULL) {
1966019625
name = "option";
1966119626
}
1966219627
1966319628
Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19664
- tablePtrSorted = Jim_Alloc(sizeof(char *) * count);
19665
- memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19666
- qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19667
- for (i = 0; i < count; i++) {
19668
- if (i + 1 == count && count > 1) {
19629
+ tablePtrSorted = JimSortStringTable(tablePtr);
19630
+ for (i = 0; tablePtrSorted[i]; i++) {
19631
+ if (tablePtrSorted[i + 1] == NULL && i > 0) {
1966919632
Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
1967019633
}
1967119634
Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19672
- if (i + 1 != count) {
19635
+ if (tablePtrSorted[i + 1]) {
1967319636
Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
1967419637
}
1967519638
}
1967619639
Jim_Free(tablePtrSorted);
1967719640
}
1967819641
19642
+
19643
+int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr)
19644
+{
19645
+ if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) {
19646
+ int i;
19647
+ char **tablePtrSorted = JimSortStringTable(tablePtr);
19648
+ Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
19649
+ for (i = 0; tablePtrSorted[i]; i++) {
19650
+ Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1));
19651
+ }
19652
+ Jim_Free(tablePtrSorted);
19653
+ return JIM_OK;
19654
+ }
19655
+ return JIM_ERR;
19656
+}
19657
+
1967919658
int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
1968019659
const char *const *tablePtr, int *indexPtr, const char *name, int flags)
1968119660
{
1968219661
const char *bad = "bad ";
1968319662
const char *const *entryPtr = NULL;
@@ -19688,11 +19667,11 @@
1968819667
1968919668
*indexPtr = -1;
1969019669
1969119670
for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
1969219671
if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19693
-
19672
+
1969419673
*indexPtr = i;
1969519674
return JIM_OK;
1969619675
}
1969719676
if (flags & JIM_ENUM_ABBREV) {
1969819677
if (strncmp(arg, *entryPtr, arglen) == 0) {
@@ -19706,11 +19685,11 @@
1970619685
match = i;
1970719686
}
1970819687
}
1970919688
}
1971019689
19711
-
19690
+
1971219691
if (match >= 0) {
1971319692
*indexPtr = match;
1971419693
return JIM_OK;
1971519694
}
1971619695
@@ -19743,15 +19722,17 @@
1974319722
return objPtr->typePtr == &listObjType;
1974419723
}
1974519724
1974619725
void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
1974719726
{
19748
-
19727
+
1974919728
int len = strlen(format);
1975019729
int extra = 0;
1975119730
int n = 0;
1975219731
const char *params[5];
19732
+ int nobjparam = 0;
19733
+ Jim_Obj *objparam[5];
1975319734
char *buf;
1975419735
va_list args;
1975519736
int i;
1975619737
1975719738
va_start(args, format);
@@ -19766,10 +19747,12 @@
1976619747
}
1976719748
else if (strncmp(format + i, "%#s", 3) == 0) {
1976819749
Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
1976919750
1977019751
params[n] = Jim_GetString(objPtr, &l);
19752
+ objparam[nobjparam++] = objPtr;
19753
+ Jim_IncrRefCount(objPtr);
1977119754
}
1977219755
else {
1977319756
if (format[i] == '%') {
1977419757
i++;
1977519758
}
@@ -19784,10 +19767,14 @@
1978419767
len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
1978519768
1978619769
va_end(args);
1978719770
1978819771
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19772
+
19773
+ for (i = 0; i < nobjparam; i++) {
19774
+ Jim_DecrRefCount(interp, objparam[i]);
19775
+ }
1978919776
}
1979019777
1979119778
1979219779
#ifndef jim_ext_package
1979319780
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19795,11 @@
1980819795
#include <string.h>
1980919796
1981019797
1981119798
static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1981219799
{
19813
-
19800
+
1981419801
return JIM_OK;
1981519802
}
1981619803
1981719804
static const jim_subcmd_type dummy_subcmd = {
1981819805
"dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19887,43 +19874,43 @@
1988719874
return 0;
1988819875
}
1988919876
1989019877
cmd = argv[1];
1989119878
19892
-
19879
+
1989319880
if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
1989419881
if (argc == 2) {
19895
-
19882
+
1989619883
show_cmd_usage(interp, command_table, argc, argv);
1989719884
return &dummy_subcmd;
1989819885
}
1989919886
help = 1;
1990019887
19901
-
19888
+
1990219889
cmd = argv[2];
1990319890
}
1990419891
19905
-
19892
+
1990619893
if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19907
-
19894
+
1990819895
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
1990919896
add_commands(interp, command_table, " ");
1991019897
return &dummy_subcmd;
1991119898
}
1991219899
1991319900
cmdstr = Jim_GetString(cmd, &cmdlen);
1991419901
1991519902
for (ct = command_table; ct->cmd; ct++) {
1991619903
if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19917
-
19904
+
1991819905
break;
1991919906
}
1992019907
if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
1992119908
if (partial) {
19922
-
19909
+
1992319910
if (help) {
19924
-
19911
+
1992519912
show_cmd_usage(interp, command_table, argc, argv);
1992619913
return &dummy_subcmd;
1992719914
}
1992819915
bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
1992919916
return 0;
@@ -19931,44 +19918,44 @@
1993119918
partial = ct;
1993219919
}
1993319920
continue;
1993419921
}
1993519922
19936
-
19923
+
1993719924
if (partial && !ct->cmd) {
1993819925
ct = partial;
1993919926
}
1994019927
1994119928
if (!ct->cmd) {
19942
-
19929
+
1994319930
if (help) {
19944
-
19931
+
1994519932
show_cmd_usage(interp, command_table, argc, argv);
1994619933
return &dummy_subcmd;
1994719934
}
1994819935
bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
1994919936
return 0;
1995019937
}
1995119938
1995219939
if (help) {
1995319940
Jim_SetResultString(interp, "Usage: ", -1);
19954
-
19941
+
1995519942
add_cmd_usage(interp, ct, argv[0]);
1995619943
return &dummy_subcmd;
1995719944
}
1995819945
19959
-
19946
+
1996019947
if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
1996119948
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19962
-
19949
+
1996319950
add_cmd_usage(interp, ct, argv[0]);
1996419951
Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
1996519952
1996619953
return 0;
1996719954
}
1996819955
19969
-
19956
+
1997019957
return ct;
1997119958
}
1997219959
1997319960
int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
1997419961
{
@@ -20019,11 +20006,11 @@
2001920006
*p++ = 0xe0 | ((uc & 0xf000) >> 12);
2002020007
*p++ = 0x80 | ((uc & 0xfc0) >> 6);
2002120008
*p = 0x80 | (uc & 0x3f);
2002220009
return 3;
2002320010
}
20024
-
20011
+
2002520012
else {
2002620013
*p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
2002720014
*p++ = 0x80 | ((uc & 0x3f000) >> 12);
2002820015
*p++ = 0x80 | ((uc & 0xfc0) >> 6);
2002920016
*p = 0x80 | (uc & 0x3f);
@@ -20210,11 +20197,11 @@
2021020197
if (ch == 'h') {
2021120198
useShort = 1;
2021220199
format += step;
2021320200
step = utf8_tounicode(format, &ch);
2021420201
} else if (ch == 'l') {
20215
-
20202
+
2021620203
format += step;
2021720204
step = utf8_tounicode(format, &ch);
2021820205
if (ch == 'l') {
2021920206
format += step;
2022020207
step = utf8_tounicode(format, &ch);
@@ -20237,11 +20224,11 @@
2023720224
goto errorMsg;
2023820225
case 's': {
2023920226
formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
2024020227
formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
2024120228
if (gotPrecision && (precision < formatted_chars)) {
20242
-
20229
+
2024320230
formatted_chars = precision;
2024420231
formatted_bytes = utf8_index(formatted_buf, precision);
2024520232
}
2024620233
break;
2024720234
}
@@ -20249,11 +20236,11 @@
2024920236
jim_wide code;
2025020237
2025120238
if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
2025220239
goto error;
2025320240
}
20254
-
20241
+
2025520242
formatted_bytes = utf8_getchars(spec, code);
2025620243
formatted_buf = spec;
2025720244
formatted_chars = 1;
2025820245
break;
2025920246
}
@@ -20267,11 +20254,11 @@
2026720254
goto error;
2026820255
}
2026920256
length = sizeof(w) * 8;
2027020257
2027120258
20272
-
20259
+
2027320260
if (num_buffer_size < length + 1) {
2027420261
num_buffer_size = length + 1;
2027520262
num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
2027620263
}
2027720264
@@ -20295,29 +20282,29 @@
2029520282
case 'E':
2029620283
case 'f':
2029720284
case 'g':
2029820285
case 'G':
2029920286
doubleType = 1;
20300
-
20287
+
2030120288
case 'd':
2030220289
case 'u':
2030320290
case 'o':
2030420291
case 'x':
2030520292
case 'X': {
2030620293
jim_wide w;
2030720294
double d;
2030820295
int length;
2030920296
20310
-
20297
+
2031120298
if (width) {
2031220299
p += sprintf(p, "%ld", width);
2031320300
}
2031420301
if (gotPrecision) {
2031520302
p += sprintf(p, ".%ld", precision);
2031620303
}
2031720304
20318
-
20305
+
2031920306
if (doubleType) {
2032020307
if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
2032120308
goto error;
2032220309
}
2032320310
length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20331,19 @@
2034420331
}
2034520332
2034620333
*p++ = (char) ch;
2034720334
*p = '\0';
2034820335
20349
-
20336
+
2035020337
if (width > length) {
2035120338
length = width;
2035220339
}
2035320340
if (gotPrecision) {
2035420341
length += precision;
2035520342
}
2035620343
20357
-
20344
+
2035820345
if (num_buffer_size < length + 1) {
2035920346
num_buffer_size = length + 1;
2036020347
num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
2036120348
}
2036220349
@@ -20370,11 +20357,11 @@
2037020357
formatted_buf = num_buffer;
2037120358
break;
2037220359
}
2037320360
2037420361
default: {
20375
-
20362
+
2037620363
spec[0] = ch;
2037720364
spec[1] = '\0';
2037820365
Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
2037920366
goto error;
2038020367
}
@@ -20422,37 +20409,37 @@
2042220409
2042320410
#define REG_MAX_PAREN 100
2042420411
2042520412
2042620413
20427
-#define END 0
20428
-#define BOL 1
20429
-#define EOL 2
20430
-#define ANY 3
20431
-#define ANYOF 4
20432
-#define ANYBUT 5
20433
-#define BRANCH 6
20434
-#define BACK 7
20435
-#define EXACTLY 8
20436
-#define NOTHING 9
20437
-#define REP 10
20438
-#define REPMIN 11
20439
-#define REPX 12
20440
-#define REPXMIN 13
20441
-#define BOLX 14
20442
-#define EOLX 15
20443
-#define WORDA 16
20444
-#define WORDZ 17
20445
-
20446
-#define OPENNC 1000
20447
-#define OPEN 1001
20448
-
20449
-
20450
-
20451
-
20452
-#define CLOSENC 2000
20453
-#define CLOSE 2001
20414
+#define END 0
20415
+#define BOL 1
20416
+#define EOL 2
20417
+#define ANY 3
20418
+#define ANYOF 4
20419
+#define ANYBUT 5
20420
+#define BRANCH 6
20421
+#define BACK 7
20422
+#define EXACTLY 8
20423
+#define NOTHING 9
20424
+#define REP 10
20425
+#define REPMIN 11
20426
+#define REPX 12
20427
+#define REPXMIN 13
20428
+#define BOLX 14
20429
+#define EOLX 15
20430
+#define WORDA 16
20431
+#define WORDZ 17
20432
+
20433
+#define OPENNC 1000
20434
+#define OPEN 1001
20435
+
20436
+
20437
+
20438
+
20439
+#define CLOSENC 2000
20440
+#define CLOSE 2001
2045420441
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
2045520442
2045620443
#define REG_MAGIC 0xFADED00D
2045720444
2045820445
@@ -20465,18 +20452,18 @@
2046520452
2046620453
#define FAIL(R,M) { (R)->err = (M); return (M); }
2046720454
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
2046820455
#define META "^$.[()|?{+*"
2046920456
20470
-#define HASWIDTH 1
20471
-#define SIMPLE 2
20472
-#define SPSTART 4
20473
-#define WORST 0
20457
+#define HASWIDTH 1
20458
+#define SIMPLE 2
20459
+#define SPSTART 4
20460
+#define WORST 0
2047420461
2047520462
#define MAX_REP_COUNT 1000000
2047620463
20477
-static int reg(regex_t *preg, int paren , int *flagp );
20464
+static int reg(regex_t *preg, int paren, int *flagp );
2047820465
static int regpiece(regex_t *preg, int *flagp );
2047920466
static int regbranch(regex_t *preg, int *flagp );
2048020467
static int regatom(regex_t *preg, int *flagp );
2048120468
static int regnode(regex_t *preg, int op );
2048220469
static int regnext(regex_t *preg, int p );
@@ -20520,15 +20507,15 @@
2052020507
memset(preg, 0, sizeof(*preg));
2052120508
2052220509
if (exp == NULL)
2052320510
FAIL(preg, REG_ERR_NULL_ARGUMENT);
2052420511
20525
-
20512
+
2052620513
preg->cflags = cflags;
2052720514
preg->regparse = exp;
2052820515
20529
-
20516
+
2053020517
preg->proglen = (strlen(exp) + 1) * 5;
2053120518
preg->program = malloc(preg->proglen * sizeof(int));
2053220519
if (preg->program == NULL)
2053320520
FAIL(preg, REG_ERR_NOMEM);
2053420521
@@ -20535,24 +20522,24 @@
2053520522
regc(preg, REG_MAGIC);
2053620523
if (reg(preg, 0, &flags) == 0) {
2053720524
return preg->err;
2053820525
}
2053920526
20540
-
20541
- if (preg->re_nsub >= REG_MAX_PAREN)
20527
+
20528
+ if (preg->re_nsub >= REG_MAX_PAREN)
2054220529
FAIL(preg,REG_ERR_TOO_BIG);
2054320530
20544
-
20545
- preg->regstart = 0;
20531
+
20532
+ preg->regstart = 0;
2054620533
preg->reganch = 0;
2054720534
preg->regmust = 0;
2054820535
preg->regmlen = 0;
20549
- scan = 1;
20550
- if (OP(preg, regnext(preg, scan)) == END) {
20536
+ scan = 1;
20537
+ if (OP(preg, regnext(preg, scan)) == END) {
2055120538
scan = OPERAND(scan);
2055220539
20553
-
20540
+
2055420541
if (OP(preg, scan) == EXACTLY) {
2055520542
preg->regstart = preg->program[OPERAND(scan)];
2055620543
}
2055720544
else if (OP(preg, scan) == BOL)
2055820545
preg->reganch++;
@@ -20579,24 +20566,24 @@
2057920566
#endif
2058020567
2058120568
return 0;
2058220569
}
2058320570
20584
-static int reg(regex_t *preg, int paren , int *flagp )
20571
+static int reg(regex_t *preg, int paren, int *flagp )
2058520572
{
2058620573
int ret;
2058720574
int br;
2058820575
int ender;
2058920576
int parno = 0;
2059020577
int flags;
2059120578
20592
- *flagp = HASWIDTH;
20579
+ *flagp = HASWIDTH;
2059320580
20594
-
20581
+
2059520582
if (paren) {
2059620583
if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20597
-
20584
+
2059820585
preg->regparse += 2;
2059920586
parno = -1;
2060020587
}
2060120588
else {
2060220589
parno = ++preg->re_nsub;
@@ -20603,16 +20590,16 @@
2060320590
}
2060420591
ret = regnode(preg, OPEN+parno);
2060520592
} else
2060620593
ret = 0;
2060720594
20608
-
20595
+
2060920596
br = regbranch(preg, &flags);
2061020597
if (br == 0)
2061120598
return 0;
2061220599
if (ret != 0)
20613
- regtail(preg, ret, br);
20600
+ regtail(preg, ret, br);
2061420601
else
2061520602
ret = br;
2061620603
if (!(flags&HASWIDTH))
2061720604
*flagp &= ~HASWIDTH;
2061820605
*flagp |= flags&SPSTART;
@@ -20619,25 +20606,25 @@
2061920606
while (*preg->regparse == '|') {
2062020607
preg->regparse++;
2062120608
br = regbranch(preg, &flags);
2062220609
if (br == 0)
2062320610
return 0;
20624
- regtail(preg, ret, br);
20611
+ regtail(preg, ret, br);
2062520612
if (!(flags&HASWIDTH))
2062620613
*flagp &= ~HASWIDTH;
2062720614
*flagp |= flags&SPSTART;
2062820615
}
2062920616
20630
-
20617
+
2063120618
ender = regnode(preg, (paren) ? CLOSE+parno : END);
2063220619
regtail(preg, ret, ender);
2063320620
20634
-
20621
+
2063520622
for (br = ret; br != 0; br = regnext(preg, br))
2063620623
regoptail(preg, br, ender);
2063720624
20638
-
20625
+
2063920626
if (paren && *preg->regparse++ != ')') {
2064020627
preg->err = REG_ERR_UNMATCHED_PAREN;
2064120628
return 0;
2064220629
} else if (!paren && *preg->regparse != '\0') {
2064320630
if (*preg->regparse == ')') {
@@ -20657,11 +20644,11 @@
2065720644
int ret;
2065820645
int chain;
2065920646
int latest;
2066020647
int flags;
2066120648
20662
- *flagp = WORST;
20649
+ *flagp = WORST;
2066320650
2066420651
ret = regnode(preg, BRANCH);
2066520652
chain = 0;
2066620653
while (*preg->regparse != '\0' && *preg->regparse != ')' &&
2066720654
*preg->regparse != '|') {
@@ -20675,11 +20662,11 @@
2067520662
else {
2067620663
regtail(preg, chain, latest);
2067720664
}
2067820665
chain = latest;
2067920666
}
20680
- if (chain == 0)
20667
+ if (chain == 0)
2068120668
(void) regnode(preg, NOTHING);
2068220669
2068320670
return(ret);
2068420671
}
2068520672
@@ -20705,11 +20692,11 @@
2070520692
if (!(flags&HASWIDTH) && op != '?') {
2070620693
preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
2070720694
return 0;
2070820695
}
2070920696
20710
-
20697
+
2071120698
if (op == '{') {
2071220699
char *end;
2071320700
2071420701
min = strtoul(preg->regparse + 1, &end, 10);
2071520702
if (end == preg->regparse + 1) {
@@ -20777,11 +20764,11 @@
2077720764
static void reg_addrange(regex_t *preg, int lower, int upper)
2077820765
{
2077920766
if (lower > upper) {
2078020767
reg_addrange(preg, upper, lower);
2078120768
}
20782
-
20769
+
2078320770
regc(preg, upper - lower + 1);
2078420771
regc(preg, lower);
2078520772
}
2078620773
2078720774
static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20832,17 @@
2084520832
case 'r': *ch = '\r'; break;
2084620833
case 't': *ch = '\t'; break;
2084720834
case 'v': *ch = '\v'; break;
2084820835
case 'u':
2084920836
if (*s == '{') {
20850
-
20837
+
2085120838
n = parse_hex(s + 1, 6, ch);
2085220839
if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
2085320840
s += n + 2;
2085420841
}
2085520842
else {
20856
-
20843
+
2085720844
*ch = 'u';
2085820845
}
2085920846
}
2086020847
else if ((n = parse_hex(s, 4, ch)) > 0) {
2086120848
s += n;
@@ -20886,15 +20873,15 @@
2088620873
int nocase = (preg->cflags & REG_ICASE);
2088720874
2088820875
int ch;
2088920876
int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
2089020877
20891
- *flagp = WORST;
20878
+ *flagp = WORST;
2089220879
2089320880
preg->regparse += n;
2089420881
switch (ch) {
20895
-
20882
+
2089620883
case '^':
2089720884
ret = regnode(preg, BOL);
2089820885
break;
2089920886
case '$':
2090020887
ret = regnode(preg, EOL);
@@ -20904,24 +20891,24 @@
2090420891
*flagp |= HASWIDTH|SIMPLE;
2090520892
break;
2090620893
case '[': {
2090720894
const char *pattern = preg->regparse;
2090820895
20909
- if (*pattern == '^') {
20896
+ if (*pattern == '^') {
2091020897
ret = regnode(preg, ANYBUT);
2091120898
pattern++;
2091220899
} else
2091320900
ret = regnode(preg, ANYOF);
2091420901
20915
-
20902
+
2091620903
if (*pattern == ']' || *pattern == '-') {
2091720904
reg_addrange(preg, *pattern, *pattern);
2091820905
pattern++;
2091920906
}
2092020907
2092120908
while (*pattern && *pattern != ']') {
20922
-
20909
+
2092320910
int start;
2092420911
int end;
2092520912
2092620913
pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
2092720914
if (start == '\\') {
@@ -20930,11 +20917,11 @@
2093020917
preg->err = REG_ERR_NULL_CHAR;
2093120918
return 0;
2093220919
}
2093320920
}
2093420921
if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20935
-
20922
+
2093620923
pattern += utf8_tounicode(pattern, &end);
2093720924
pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
2093820925
if (end == '\\') {
2093920926
pattern += reg_decode_escape(pattern, &end);
2094020927
if (end == 0) {
@@ -20957,22 +20944,22 @@
2095720944
CC_NUM
2095820945
};
2095920946
int i;
2096020947
2096120948
for (i = 0; i < CC_NUM; i++) {
20962
- int n = strlen(character_class[i]);
20949
+ n = strlen(character_class[i]);
2096320950
if (strncmp(pattern, character_class[i], n) == 0) {
20964
-
20951
+
2096520952
pattern += n + 1;
2096620953
break;
2096720954
}
2096820955
}
2096920956
if (i != CC_NUM) {
2097020957
switch (i) {
2097120958
case CC_ALNUM:
2097220959
reg_addrange(preg, '0', '9');
20973
-
20960
+
2097420961
case CC_ALPHA:
2097520962
if ((preg->cflags & REG_ICASE) == 0) {
2097620963
reg_addrange(preg, 'a', 'z');
2097720964
}
2097820965
reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20977,11 @@
2099020977
reg_addrange(preg, 'a', 'z');
2099120978
break;
2099220979
case CC_XDIGIT:
2099320980
reg_addrange(preg, 'a', 'f');
2099420981
reg_addrange(preg, 'A', 'F');
20995
-
20982
+
2099620983
case CC_DIGIT:
2099720984
reg_addrange(preg, '0', '9');
2099820985
break;
2099920986
case CC_CNTRL:
2100020987
reg_addrange(preg, 0, 31);
@@ -21014,11 +21001,11 @@
2101421001
break;
2101521002
}
2101621003
continue;
2101721004
}
2101821005
}
21019
-
21006
+
2102021007
reg_addrange(preg, start, start);
2102121008
}
2102221009
regc(preg, '\0');
2102321010
2102421011
if (*pattern) {
@@ -21037,11 +21024,11 @@
2103721024
break;
2103821025
case '\0':
2103921026
case '|':
2104021027
case ')':
2104121028
preg->err = REG_ERR_INTERNAL;
21042
- return 0;
21029
+ return 0;
2104321030
case '?':
2104421031
case '+':
2104521032
case '*':
2104621033
case '{':
2104721034
preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +21077,34 @@
2109021077
ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
2109121078
reg_addrange_str(preg," \t\r\n\f\v");
2109221079
regc(preg, '\0');
2109321080
*flagp |= HASWIDTH|SIMPLE;
2109421081
break;
21095
-
21082
+
2109621083
default:
21097
-
21098
-
21084
+
21085
+
2109921086
preg->regparse--;
2110021087
goto de_fault;
2110121088
}
2110221089
break;
2110321090
de_fault:
2110421091
default: {
2110521092
int added = 0;
2110621093
21107
-
21094
+
2110821095
preg->regparse -= n;
2110921096
2111021097
ret = regnode(preg, EXACTLY);
2111121098
2111221099
21113
-
21100
+
2111421101
while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
2111521102
n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
2111621103
if (ch == '\\' && preg->regparse[n]) {
2111721104
if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
21118
-
21105
+
2111921106
break;
2112021107
}
2112121108
n += reg_decode_escape(preg->regparse + n, &ch);
2112221109
if (ch == 0) {
2112321110
preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21112,23 @@
2112521112
}
2112621113
}
2112721114
2112821115
2112921116
if (ISMULT(preg->regparse[n])) {
21130
-
21117
+
2113121118
if (added) {
21132
-
21119
+
2113321120
break;
2113421121
}
21135
-
21122
+
2113621123
regc(preg, ch);
2113721124
added++;
2113821125
preg->regparse += n;
2113921126
break;
2114021127
}
2114121128
21142
-
21129
+
2114321130
regc(preg, ch);
2114421131
added++;
2114521132
preg->regparse += n;
2114621133
}
2114721134
regc(preg, '\0');
@@ -21168,15 +21155,15 @@
2116821155
2116921156
static int regnode(regex_t *preg, int op)
2117021157
{
2117121158
reg_grow(preg, 2);
2117221159
21173
-
21160
+
2117421161
preg->program[preg->p++] = op;
2117521162
preg->program[preg->p++] = 0;
2117621163
21177
-
21164
+
2117821165
return preg->p - 2;
2117921166
}
2118021167
2118121168
static void regc(regex_t *preg, int b )
2118221169
{
@@ -21186,13 +21173,13 @@
2118621173
2118721174
static int reginsert(regex_t *preg, int op, int size, int opnd )
2118821175
{
2118921176
reg_grow(preg, size);
2119021177
21191
-
21178
+
2119221179
memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21193
-
21180
+
2119421181
memset(preg->program + opnd, 0, sizeof(int) * size);
2119521182
2119621183
preg->program[opnd] = op;
2119721184
2119821185
preg->p += size;
@@ -21204,11 +21191,11 @@
2120421191
{
2120521192
int scan;
2120621193
int temp;
2120721194
int offset;
2120821195
21209
-
21196
+
2121021197
scan = p;
2121121198
for (;;) {
2121221199
temp = regnext(preg, scan);
2121321200
if (temp == 0)
2121421201
break;
@@ -21224,11 +21211,11 @@
2122421211
}
2122521212
2122621213
2122721214
static void regoptail(regex_t *preg, int p, int val )
2122821215
{
21229
-
21216
+
2123021217
if (p != 0 && OP(preg, p) == BRANCH) {
2123121218
regtail(preg, OPERAND(p), val);
2123221219
}
2123321220
}
2123421221
@@ -21240,16 +21227,16 @@
2124021227
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
2124121228
{
2124221229
const char *s;
2124321230
int scan;
2124421231
21245
-
21232
+
2124621233
if (preg == NULL || preg->program == NULL || string == NULL) {
2124721234
return REG_ERR_NULL_ARGUMENT;
2124821235
}
2124921236
21250
-
21237
+
2125121238
if (*preg->program != REG_MAGIC) {
2125221239
return REG_ERR_CORRUPTED;
2125321240
}
2125421241
2125521242
#ifdef DEBUG
@@ -21258,51 +21245,51 @@
2125821245
#endif
2125921246
2126021247
preg->eflags = eflags;
2126121248
preg->pmatch = pmatch;
2126221249
preg->nmatch = nmatch;
21263
- preg->start = string;
21250
+ preg->start = string;
2126421251
21265
-
21252
+
2126621253
for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
2126721254
int op = OP(preg, scan);
2126821255
if (op == END)
2126921256
break;
2127021257
if (op == REPX || op == REPXMIN)
2127121258
preg->program[scan + 4] = 0;
2127221259
}
2127321260
21274
-
21261
+
2127521262
if (preg->regmust != 0) {
2127621263
s = string;
2127721264
while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
2127821265
if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
2127921266
break;
2128021267
}
2128121268
s++;
2128221269
}
21283
- if (s == NULL)
21270
+ if (s == NULL)
2128421271
return REG_NOMATCH;
2128521272
}
2128621273
21287
-
21274
+
2128821275
preg->regbol = string;
2128921276
21290
-
21277
+
2129121278
if (preg->reganch) {
2129221279
if (eflags & REG_NOTBOL) {
21293
-
21280
+
2129421281
goto nextline;
2129521282
}
2129621283
while (1) {
2129721284
if (regtry(preg, string)) {
2129821285
return REG_NOERROR;
2129921286
}
2130021287
if (*string) {
2130121288
nextline:
2130221289
if (preg->cflags & REG_NEWLINE) {
21303
-
21290
+
2130421291
string = strchr(string, '\n');
2130521292
if (string) {
2130621293
preg->regbol = ++string;
2130721294
continue;
2130821295
}
@@ -21310,22 +21297,22 @@
2131021297
}
2131121298
return REG_NOMATCH;
2131221299
}
2131321300
}
2131421301
21315
-
21302
+
2131621303
s = string;
2131721304
if (preg->regstart != '\0') {
21318
-
21305
+
2131921306
while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
2132021307
if (regtry(preg, s))
2132121308
return REG_NOERROR;
2132221309
s++;
2132321310
}
2132421311
}
2132521312
else
21326
-
21313
+
2132721314
while (1) {
2132821315
if (regtry(preg, s))
2132921316
return REG_NOERROR;
2133021317
if (*s == '\0') {
2133121318
break;
@@ -21334,15 +21321,15 @@
2133421321
int c;
2133521322
s += utf8_tounicode(s, &c);
2133621323
}
2133721324
}
2133821325
21339
-
21326
+
2134021327
return REG_NOMATCH;
2134121328
}
2134221329
21343
-
21330
+
2134421331
static int regtry( regex_t *preg, const char *string )
2134521332
{
2134621333
int i;
2134721334
2134821335
preg->reginput = string;
@@ -21379,11 +21366,11 @@
2137921366
}
2138021367
2138121368
static int reg_range_find(const int *range, int c)
2138221369
{
2138321370
while (*range) {
21384
-
21371
+
2138521372
if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
2138621373
return 1;
2138721374
}
2138821375
range += 2;
2138921376
}
@@ -21391,11 +21378,11 @@
2139121378
}
2139221379
2139321380
static const char *str_find(const char *string, int c, int nocase)
2139421381
{
2139521382
if (nocase) {
21396
-
21383
+
2139721384
c = utf8_upper(c);
2139821385
}
2139921386
while (*string) {
2140021387
int ch;
2140121388
int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21422,15 @@
2143521422
no = regrepeat(preg, scan + 5, max);
2143621423
if (no < min) {
2143721424
return 0;
2143821425
}
2143921426
if (matchmin) {
21440
-
21427
+
2144121428
max = no;
2144221429
no = min;
2144321430
}
21444
-
21431
+
2144521432
while (1) {
2144621433
if (matchmin) {
2144721434
if (no > max) {
2144821435
break;
2144921436
}
@@ -21453,22 +21440,22 @@
2145321440
break;
2145421441
}
2145521442
}
2145621443
preg->reginput = save + utf8_index(save, no);
2145721444
reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21458
-
21445
+
2145921446
if (reg_iseol(preg, nextch) || c == nextch) {
2146021447
if (regmatch(preg, next)) {
2146121448
return(1);
2146221449
}
2146321450
}
2146421451
if (matchmin) {
21465
-
21452
+
2146621453
no++;
2146721454
}
2146821455
else {
21469
-
21456
+
2147021457
no--;
2147121458
}
2147221459
}
2147321460
return(0);
2147421461
}
@@ -21478,13 +21465,13 @@
2147821465
int *scanpt = preg->program + scan;
2147921466
2148021467
int max = scanpt[2];
2148121468
int min = scanpt[3];
2148221469
21483
-
21470
+
2148421471
if (scanpt[4] < min) {
21485
-
21472
+
2148621473
scanpt[4]++;
2148721474
if (regmatch(preg, scan + 5)) {
2148821475
return 1;
2148921476
}
2149021477
scanpt[4]--;
@@ -21493,39 +21480,39 @@
2149321480
if (scanpt[4] > max) {
2149421481
return 0;
2149521482
}
2149621483
2149721484
if (matchmin) {
21498
-
21485
+
2149921486
if (regmatch(preg, regnext(preg, scan))) {
2150021487
return 1;
2150121488
}
21502
-
21489
+
2150321490
scanpt[4]++;
2150421491
if (regmatch(preg, scan + 5)) {
2150521492
return 1;
2150621493
}
2150721494
scanpt[4]--;
2150821495
return 0;
2150921496
}
21510
-
21497
+
2151121498
if (scanpt[4] < max) {
2151221499
scanpt[4]++;
2151321500
if (regmatch(preg, scan + 5)) {
2151421501
return 1;
2151521502
}
2151621503
scanpt[4]--;
2151721504
}
21518
-
21505
+
2151921506
return regmatch(preg, regnext(preg, scan));
2152021507
}
2152121508
2152221509
2152321510
static int regmatch(regex_t *preg, int prog)
2152421511
{
21525
- int scan;
21526
- int next;
21512
+ int scan;
21513
+ int next;
2152721514
const char *save;
2152821515
2152921516
scan = prog;
2153021517
2153121518
#ifdef DEBUG
@@ -21535,11 +21522,11 @@
2153521522
while (scan != 0) {
2153621523
int n;
2153721524
int c;
2153821525
#ifdef DEBUG
2153921526
if (regnarrate) {
21540
- fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21527
+ fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
2154121528
}
2154221529
#endif
2154321530
next = regnext(preg, scan);
2154421531
n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
2154521532
@@ -21546,49 +21533,49 @@
2154621533
switch (OP(preg, scan)) {
2154721534
case BOLX:
2154821535
if ((preg->eflags & REG_NOTBOL)) {
2154921536
return(0);
2155021537
}
21551
-
21538
+
2155221539
case BOL:
2155321540
if (preg->reginput != preg->regbol) {
2155421541
return(0);
2155521542
}
2155621543
break;
2155721544
case EOLX:
2155821545
if (c != 0) {
21559
-
21546
+
2156021547
return 0;
2156121548
}
2156221549
break;
2156321550
case EOL:
2156421551
if (!reg_iseol(preg, c)) {
2156521552
return(0);
2156621553
}
2156721554
break;
2156821555
case WORDA:
21569
-
21556
+
2157021557
if ((!isalnum(UCHAR(c))) && c != '_')
2157121558
return(0);
21572
-
21559
+
2157321560
if (preg->reginput > preg->regbol &&
2157421561
(isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
2157521562
return(0);
2157621563
break;
2157721564
case WORDZ:
21578
-
21565
+
2157921566
if (preg->reginput > preg->regbol) {
21580
-
21567
+
2158121568
if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
2158221569
c = preg->reginput[-1];
21583
-
21570
+
2158421571
if (isalnum(UCHAR(c)) || c == '_') {
2158521572
break;
2158621573
}
2158721574
}
2158821575
}
21589
-
21576
+
2159021577
return(0);
2159121578
2159221579
case ANY:
2159321580
if (reg_iseol(preg, c))
2159421581
return 0;
@@ -21624,12 +21611,12 @@
2162421611
case NOTHING:
2162521612
break;
2162621613
case BACK:
2162721614
break;
2162821615
case BRANCH:
21629
- if (OP(preg, next) != BRANCH)
21630
- next = OPERAND(scan);
21616
+ if (OP(preg, next) != BRANCH)
21617
+ next = OPERAND(scan);
2163121618
else {
2163221619
do {
2163321620
save = preg->reginput;
2163421621
if (regmatch(preg, OPERAND(scan))) {
2163521622
return(1);
@@ -21636,11 +21623,11 @@
2163621623
}
2163721624
preg->reginput = save;
2163821625
scan = regnext(preg, scan);
2163921626
} while (scan != 0 && OP(preg, scan) == BRANCH);
2164021627
return(0);
21641
-
21628
+
2164221629
}
2164321630
break;
2164421631
case REP:
2164521632
case REPMIN:
2164621633
return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21635,11 @@
2164821635
case REPX:
2164921636
case REPXMIN:
2165021637
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
2165121638
2165221639
case END:
21653
- return 1;
21640
+ return 1;
2165421641
2165521642
case OPENNC:
2165621643
case CLOSENC:
2165721644
return regmatch(preg, next);
2165821645
@@ -21695,11 +21682,11 @@
2169521682
2169621683
scan = preg->reginput;
2169721684
opnd = OPERAND(p);
2169821685
switch (OP(preg, p)) {
2169921686
case ANY:
21700
-
21687
+
2170121688
while (!reg_iseol(preg, *scan) && count < max) {
2170221689
count++;
2170321690
scan++;
2170421691
}
2170521692
break;
@@ -21731,13 +21718,13 @@
2173121718
}
2173221719
count++;
2173321720
scan += n;
2173421721
}
2173521722
break;
21736
- default:
21723
+ default:
2173721724
preg->err = REG_ERR_INTERNAL;
21738
- count = 0;
21725
+ count = 0;
2173921726
break;
2174021727
}
2174121728
preg->reginput = scan;
2174221729
2174321730
return(count);
@@ -21758,11 +21745,11 @@
2175821745
return(p+offset);
2175921746
}
2176021747
2176121748
static int regopsize(regex_t *preg, int p )
2176221749
{
21763
-
21750
+
2176421751
switch (OP(preg, p)) {
2176521752
case REP:
2176621753
case REPMIN:
2176721754
case REPX:
2176821755
case REPXMIN:
@@ -21879,26 +21866,26 @@
2187921866
{
2188021867
DIR *dir = 0;
2188121868
2188221869
if (name && name[0]) {
2188321870
size_t base_length = strlen(name);
21884
- const char *all =
21871
+ const char *all =
2188521872
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
2188621873
2188721874
if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
2188821875
(dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
2188921876
strcat(strcpy(dir->name, name), all);
2189021877
2189121878
if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
2189221879
dir->result.d_name = 0;
21893
- else {
21880
+ else {
2189421881
Jim_Free(dir->name);
2189521882
Jim_Free(dir);
2189621883
dir = 0;
2189721884
}
2189821885
}
21899
- else {
21886
+ else {
2190021887
Jim_Free(dir);
2190121888
dir = 0;
2190221889
errno = ENOMEM;
2190321890
}
2190421891
}
@@ -21916,11 +21903,11 @@
2191621903
if (dir->handle != -1)
2191721904
result = _findclose(dir->handle);
2191821905
Jim_Free(dir->name);
2191921906
Jim_Free(dir);
2192021907
}
21921
- if (result == -1)
21908
+ if (result == -1)
2192221909
errno = EBADF;
2192321910
return result;
2192421911
}
2192521912
2192621913
struct dirent *readdir(DIR * dir)
@@ -21947,10 +21934,13 @@
2194721934
2194821935
#ifdef USE_LINENOISE
2194921936
#ifdef HAVE_UNISTD_H
2195021937
#include <unistd.h>
2195121938
#endif
21939
+#ifdef HAVE_SYS_STAT_H
21940
+ #include <sys/stat.h>
21941
+#endif
2195221942
#include "linenoise.h"
2195321943
#else
2195421944
#define MAX_LINE_LEN 512
2195521945
#endif
2195621946
@@ -21992,41 +21982,86 @@
2199221982
}
2199321983
2199421984
void Jim_HistorySave(const char *filename)
2199521985
{
2199621986
#ifdef USE_LINENOISE
21987
+#ifdef HAVE_UMASK
21988
+ mode_t mask;
21989
+
21990
+ mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
21991
+#endif
2199721992
linenoiseHistorySave(filename);
21993
+#ifdef HAVE_UMASK
21994
+ mask = umask(mask);
21995
+#endif
2199821996
#endif
2199921997
}
2200021998
2200121999
void Jim_HistoryShow(void)
2200222000
{
2200322001
#ifdef USE_LINENOISE
22004
-
22002
+
2200522003
int i;
2200622004
int len;
2200722005
char **history = linenoiseHistory(&len);
2200822006
for (i = 0; i < len; i++) {
2200922007
printf("%4d %s\n", i + 1, history[i]);
2201022008
}
2201122009
#endif
2201222010
}
22011
+
22012
+#ifdef USE_LINENOISE
22013
+struct JimCompletionInfo {
22014
+ Jim_Interp *interp;
22015
+ Jim_Obj *command;
22016
+};
22017
+
22018
+void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
22019
+{
22020
+ struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
22021
+ Jim_Obj *objv[2];
22022
+ int ret;
22023
+
22024
+ objv[0] = info->command;
22025
+ objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
22026
+
22027
+ ret = Jim_EvalObjVector(info->interp, 2, objv);
22028
+
22029
+
22030
+ if (ret == JIM_OK) {
22031
+ int i;
22032
+ Jim_Obj *listObj = Jim_GetResult(info->interp);
22033
+ int len = Jim_ListLength(info->interp, listObj);
22034
+ for (i = 0; i < len; i++) {
22035
+ linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i)));
22036
+ }
22037
+ }
22038
+}
22039
+#endif
2201322040
2201422041
int Jim_InteractivePrompt(Jim_Interp *interp)
2201522042
{
2201622043
int retcode = JIM_OK;
2201722044
char *history_file = NULL;
2201822045
#ifdef USE_LINENOISE
2201922046
const char *home;
22047
+ struct JimCompletionInfo compinfo;
2202022048
2202122049
home = getenv("HOME");
2202222050
if (home && isatty(STDIN_FILENO)) {
2202322051
int history_len = strlen(home) + sizeof("/.jim_history");
2202422052
history_file = Jim_Alloc(history_len);
2202522053
snprintf(history_file, history_len, "%s/.jim_history", home);
2202622054
Jim_HistoryLoad(history_file);
2202722055
}
22056
+
22057
+ compinfo.interp = interp;
22058
+ compinfo.command = Jim_NewStringObj(interp, "tcl::autocomplete", -1);
22059
+ Jim_IncrRefCount(compinfo.command);
22060
+
22061
+
22062
+ linenoiseSetCompletionCallback(JimCompletionCallback, &compinfo);
2202822063
#endif
2202922064
2203022065
printf("Welcome to Jim version %d.%d\n",
2203122066
JIM_VERSION / 100, JIM_VERSION % 100);
2203222067
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22065,11 +22100,11 @@
2206522100
Jim_DecrRefCount(interp, scriptObjPtr);
2206622101
retcode = JIM_OK;
2206722102
goto out;
2206822103
}
2206922104
if (Jim_Length(scriptObjPtr) != 0) {
22070
-
22105
+
2207122106
Jim_AppendString(interp, scriptObjPtr, "\n", 1);
2207222107
}
2207322108
Jim_AppendString(interp, scriptObjPtr, line, -1);
2207422109
free(line);
2207522110
if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22112,11 @@
2207722112
2207822113
snprintf(prompt, sizeof(prompt), "%c> ", state);
2207922114
}
2208022115
#ifdef USE_LINENOISE
2208122116
if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22082
-
22117
+
2208322118
Jim_HistoryShow();
2208422119
Jim_DecrRefCount(interp, scriptObjPtr);
2208522120
continue;
2208622121
}
2208722122
@@ -22104,10 +22139,16 @@
2210422139
printf("%s\n", result);
2210522140
}
2210622141
}
2210722142
out:
2210822143
Jim_Free(history_file);
22144
+
22145
+#ifdef USE_LINENOISE
22146
+ Jim_DecrRefCount(interp, compinfo.command);
22147
+ linenoiseSetCompletionCallback(NULL, NULL);
22148
+#endif
22149
+
2210922150
return retcode;
2211022151
}
2211122152
2211222153
#include <stdio.h>
2211322154
#include <stdlib.h>
@@ -22120,11 +22161,11 @@
2212022161
static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
2212122162
{
2212222163
int n;
2212322164
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2212422165
22125
-
22166
+
2212622167
for (n = 0; n < argc; n++) {
2212722168
Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
2212822169
2212922170
Jim_ListAppendElement(interp, listObj, obj);
2213022171
}
@@ -22146,71 +22187,75 @@
2214622187
printf("or : %s [options] [filename]\n", executable_name);
2214722188
printf("\n");
2214822189
printf("Without options: Interactive mode\n");
2214922190
printf("\n");
2215022191
printf("Options:\n");
22151
- printf(" --version : prints the version string\n");
22152
- printf(" --help : prints this text\n");
22153
- printf(" -e CMD : executes command CMD\n");
22154
- printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22155
- printf(" [filename] : executes the script contained in the named file\n");
22156
- printf(" NOTE: all subsequent options will be passed to the script\n\n");
22192
+ printf(" --version : prints the version string\n");
22193
+ printf(" --help : prints this text\n");
22194
+ printf(" -e CMD : executes command CMD\n");
22195
+ printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22196
+ printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n");
22197
+ printf(" NOTE: all subsequent options will be passed to the script\n\n");
2215722198
}
2215822199
2215922200
int main(int argc, char *const argv[])
2216022201
{
2216122202
int retcode;
2216222203
Jim_Interp *interp;
2216322204
char *const orig_argv0 = argv[0];
2216422205
22165
-
22206
+
2216622207
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
2216722208
printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
2216822209
return 0;
2216922210
}
2217022211
else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
2217122212
usage(argv[0]);
2217222213
return 0;
2217322214
}
2217422215
22175
-
22216
+
2217622217
interp = Jim_CreateInterp();
2217722218
Jim_RegisterCoreCommands(interp);
2217822219
22179
-
22220
+
2218022221
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
2218122222
JimPrintErrorMessage(interp);
2218222223
}
2218322224
2218422225
Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
2218522226
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
2218622227
retcode = Jim_initjimshInit(interp);
2218722228
2218822229
if (argc == 1) {
22189
-
22230
+
2219022231
if (retcode == JIM_ERR) {
2219122232
JimPrintErrorMessage(interp);
2219222233
}
2219322234
if (retcode != JIM_EXIT) {
2219422235
JimSetArgv(interp, 0, NULL);
2219522236
retcode = Jim_InteractivePrompt(interp);
2219622237
}
2219722238
}
2219822239
else {
22199
-
22240
+
2220022241
if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22201
-
22242
+
2220222243
JimSetArgv(interp, argc - 3, argv + 3);
2220322244
retcode = Jim_Eval(interp, argv[2]);
2220422245
if (retcode != JIM_ERR) {
2220522246
printf("%s\n", Jim_String(Jim_GetResult(interp)));
2220622247
}
2220722248
}
2220822249
else {
2220922250
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
2221022251
JimSetArgv(interp, argc - 2, argv + 2);
22211
- retcode = Jim_EvalFile(interp, argv[1]);
22252
+ if (strcmp(argv[1], "-") == 0) {
22253
+ retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
22254
+ } else {
22255
+ retcode = Jim_EvalFile(interp, argv[1]);
22256
+ }
2221222257
}
2221322258
if (retcode == JIM_ERR) {
2221422259
JimPrintErrorMessage(interp);
2221522260
}
2221622261
}
2221722262
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
2 #define _GNU_SOURCE
3 #define JIM_TCL_COMPAT
4 #define JIM_REFERENCES
5 #define JIM_ANSIC
6 #define JIM_REGEXP
7 #define HAVE_NO_AUTOCONF
8 #define _JIMAUTOCONF_H
9 #define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
31 #define HAVE_MKDIR_ONE_ARG
32 #define HAVE_SYSTEM
33 #define HAVE_SYS_TIME_H
34 #define HAVE_DIRENT_H
35 #define HAVE_UNISTD_H
 
 
 
 
 
 
 
 
36 #else
37 #define TCL_PLATFORM_OS "unknown"
38 #define TCL_PLATFORM_PLATFORM "unix"
39 #define TCL_PLATFORM_PATH_SEPARATOR ":"
 
 
 
 
 
 
40 #define HAVE_VFORK
41 #define HAVE_WAITPID
42 #define HAVE_ISATTY
43 #define HAVE_MKSTEMP
44 #define HAVE_LINK
45 #define HAVE_SYS_TIME_H
46 #define HAVE_DIRENT_H
47 #define HAVE_UNISTD_H
 
48 #endif
49 #define JIM_VERSION 76
50 #ifndef JIM_WIN32COMPAT_H
51 #define JIM_WIN32COMPAT_H
52
53
54
@@ -88,11 +101,10 @@
88 #define JIM_WIDE_MIN LLONG_MIN
89 #define JIM_WIDE_MAX LLONG_MAX
90 #define JIM_WIDE_MODIFIER "I64d"
91 #define strcasecmp _stricmp
92 #define strtoull _strtoui64
93 #define snprintf _snprintf
94
95 #include <io.h>
96
97 struct timeval {
98 long tv_sec;
@@ -105,14 +117,14 @@
105 struct dirent {
106 char *d_name;
107 };
108
109 typedef struct DIR {
110 long handle;
111 struct _finddata_t info;
112 struct dirent result;
113 char *name;
114 } DIR;
115
116 DIR *opendir(const char *name);
117 int closedir(DIR *dir);
118 struct dirent *readdir(DIR *dir);
@@ -122,11 +134,11 @@
122 #include <stdlib.h>
123 #define strtod __strtod
124
125 #endif
126
127 #endif
128
129 #ifdef __cplusplus
130 }
131 #endif
132
@@ -146,19 +158,21 @@
146
147 #ifndef JIM_UTF8
148 #include <ctype.h>
149
150
151 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
 
152 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
153 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
154 #define utf8_upper(C) toupper(C)
155 #define utf8_title(C) toupper(C)
156 #define utf8_lower(C) tolower(C)
157 #define utf8_index(C, I) (I)
158 #define utf8_charlen(C) 1
159 #define utf8_prev_len(S, L) 1
 
160
161 #else
162
163 #endif
164
@@ -175,13 +189,13 @@
175 extern "C" {
176 #endif
177
178 #include <time.h>
179 #include <limits.h>
180 #include <stdio.h>
181 #include <stdlib.h>
182 #include <stdarg.h>
183
184
185 #ifndef HAVE_NO_AUTOCONF
186 #endif
187
@@ -224,31 +238,31 @@
224 #define JIM_SIGNAL 5
225 #define JIM_EXIT 6
226
227 #define JIM_EVAL 7
228
229 #define JIM_MAX_CALLFRAME_DEPTH 1000
230 #define JIM_MAX_EVAL_DEPTH 2000
231
232
233 #define JIM_PRIV_FLAG_SHIFT 20
234
235 #define JIM_NONE 0
236 #define JIM_ERRMSG 1
237 #define JIM_ENUM_ABBREV 2
238 #define JIM_UNSHARED 4
239 #define JIM_MUSTEXIST 8
240
241
242 #define JIM_SUBST_NOVAR 1
243 #define JIM_SUBST_NOCMD 2
244 #define JIM_SUBST_NOESC 4
245 #define JIM_SUBST_FLAG 128
246
247
248 #define JIM_CASESENS 0
249 #define JIM_NOCASE 1
250
251
252 #define JIM_PATH_LEN 1024
253
254
@@ -339,79 +353,79 @@
339 #define Jim_GetHashTableSize(ht) ((ht)->size)
340 #define Jim_GetHashTableUsed(ht) ((ht)->used)
341
342
343 typedef struct Jim_Obj {
344 char *bytes;
345 const struct Jim_ObjType *typePtr;
346 int refCount;
347 int length;
348
349 union {
350
351 jim_wide wideValue;
352
353 int intValue;
354
355 double doubleValue;
356
357 void *ptr;
358
359 struct {
360 void *ptr1;
361 void *ptr2;
362 } twoPtrValue;
363
364 struct {
365 struct Jim_Var *varPtr;
366 unsigned long callFrameId;
367 int global;
368 } varValue;
369
370 struct {
371 struct Jim_Obj *nsObj;
372 struct Jim_Cmd *cmdPtr;
373 unsigned long procEpoch;
374 } cmdValue;
375
376 struct {
377 struct Jim_Obj **ele;
378 int len;
379 int maxLen;
380 } listValue;
381
382 struct {
383 int maxLength;
384 int charLength;
385 } strValue;
386
387 struct {
388 unsigned long id;
389 struct Jim_Reference *refPtr;
390 } refValue;
391
392 struct {
393 struct Jim_Obj *fileNameObj;
394 int lineNumber;
395 } sourceValue;
396
397 struct {
398 struct Jim_Obj *varNameObjPtr;
399 struct Jim_Obj *indexObjPtr;
400 } dictSubstValue;
401
402 struct {
403 void *compre;
404 unsigned flags;
405 } regexpValue;
406 struct {
407 int line;
408 int argc;
409 } scriptLineValue;
410 } internalRep;
411 struct Jim_Obj *prevObjPtr;
412 struct Jim_Obj *nextObjPtr;
413 } Jim_Obj;
414
415
416 #define Jim_IncrRefCount(objPtr) \
417 ++(objPtr)->refCount
@@ -442,40 +456,40 @@
442 typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
443 struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
444 typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
445
446 typedef struct Jim_ObjType {
447 const char *name;
448 Jim_FreeInternalRepProc *freeIntRepProc;
449 Jim_DupInternalRepProc *dupIntRepProc;
450 Jim_UpdateStringProc *updateStringProc;
451 int flags;
452 } Jim_ObjType;
453
454
455 #define JIM_TYPE_NONE 0
456 #define JIM_TYPE_REFERENCES 1
457
458
459
460 typedef struct Jim_CallFrame {
461 unsigned long id;
462 int level;
463 struct Jim_HashTable vars;
464 struct Jim_HashTable *staticVars;
465 struct Jim_CallFrame *parent;
466 Jim_Obj *const *argv;
467 int argc;
468 Jim_Obj *procArgsObjPtr;
469 Jim_Obj *procBodyObjPtr;
470 struct Jim_CallFrame *next;
471 Jim_Obj *nsObj;
472 Jim_Obj *fileNameObj;
473 int line;
474 Jim_Stack *localCommands;
475 struct Jim_Obj *tailcallObj;
476 struct Jim_Cmd *tailcallCmd;
477 } Jim_CallFrame;
478
479 typedef struct Jim_Var {
480 Jim_Obj *objPtr;
481 struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +501,35 @@
487 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
488
489
490
491 typedef struct Jim_Cmd {
492 int inUse;
493 int isproc;
494 struct Jim_Cmd *prevCmd;
495 union {
496 struct {
497
498 Jim_CmdProc *cmdProc;
499 Jim_DelCmdProc *delProc;
500 void *privData;
501 } native;
502 struct {
503
504 Jim_Obj *argListObjPtr;
505 Jim_Obj *bodyObjPtr;
506 Jim_HashTable *staticVars;
507 int argListLen;
508 int reqArity;
509 int optArity;
510 int argsPos;
511 int upcall;
512 struct Jim_ProcArg {
513 Jim_Obj *nameObjPtr;
514 Jim_Obj *defaultObjPtr;
515 } *arglist;
516 Jim_Obj *nsObj;
517 } proc;
518 } u;
519 } Jim_Cmd;
520
521
@@ -523,64 +537,64 @@
523 unsigned char sbox[256];
524 unsigned int i, j;
525 } Jim_PrngState;
526
527 typedef struct Jim_Interp {
528 Jim_Obj *result;
529 int errorLine;
530 Jim_Obj *errorFileNameObj;
531 int addStackTrace;
532 int maxCallFrameDepth;
533 int maxEvalDepth;
534 int evalDepth;
535 int returnCode;
536 int returnLevel;
537 int exitCode;
538 long id;
539 int signal_level;
540 jim_wide sigmask;
541 int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
542 Jim_CallFrame *framePtr;
543 Jim_CallFrame *topFramePtr;
544 struct Jim_HashTable commands;
545 unsigned long procEpoch; /* Incremented every time the result
546 of procedures names lookup caching
547 may no longer be valid. */
548 unsigned long callFrameEpoch; /* Incremented every time a new
549 callframe is created. This id is used for the
550 'ID' field contained in the Jim_CallFrame
551 structure. */
552 int local;
553 Jim_Obj *liveList;
554 Jim_Obj *freeList;
555 Jim_Obj *currentScriptObj;
556 Jim_Obj *nullScriptObj;
557 Jim_Obj *emptyObj;
558 Jim_Obj *trueObj;
559 Jim_Obj *falseObj;
560 unsigned long referenceNextId;
561 struct Jim_HashTable references;
562 unsigned long lastCollectId; /* reference max Id of the last GC
563 execution. It's set to -1 while the collection
564 is running as sentinel to avoid to recursive
565 calls via the [collect] command inside
566 finalizers. */
567 time_t lastCollectTime;
568 Jim_Obj *stackTrace;
569 Jim_Obj *errorProc;
570 Jim_Obj *unknown;
571 int unknown_called;
572 int errorFlag;
573 void *cmdPrivData; /* Used to pass the private data pointer to
574 a command. It is set to what the user specified
575 via Jim_CreateCommand(). */
576
577 struct Jim_CallFrame *freeFramesList;
578 struct Jim_HashTable assocData;
579 Jim_PrngState *prngState;
580 struct Jim_HashTable packages;
581 Jim_Stack *loadHandles;
582 } Jim_Interp;
583
584 #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
585 #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
586 #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +637,11 @@
623 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
624
625
626 JIM_EXPORT char **Jim_GetEnviron(void);
627 JIM_EXPORT void Jim_SetEnviron(char **env);
628 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
629
630
631 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
632
633
@@ -816,14 +830,18 @@
816 Jim_Obj *newObjPtr, int flags);
817 JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
818 Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
819 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
820 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
821 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
822 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
 
 
 
823 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
824 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
 
825
826
827 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
828 int *intPtr);
829
@@ -831,10 +849,14 @@
831 JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
832 Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
833 JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
834 Jim_Obj *exprObjPtr, int *boolPtr);
835
 
 
 
 
836
837 JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
838 jim_wide *widePtr);
839 JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
840 long *longPtr);
@@ -852,10 +874,12 @@
852
853 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
854 Jim_Obj *const *argv, const char *msg);
855 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
856 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
 
 
857 JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
858 Jim_Obj *scriptObj, char *stateCharPtr);
859
860 JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
861
@@ -904,11 +928,11 @@
904
905 #ifdef __cplusplus
906 }
907 #endif
908
909 #endif
910
911 #ifndef JIM_SUBCMD_H
912 #define JIM_SUBCMD_H
913
914
@@ -915,24 +939,24 @@
915 #ifdef __cplusplus
916 extern "C" {
917 #endif
918
919
920 #define JIM_MODFLAG_HIDDEN 0x0001
921 #define JIM_MODFLAG_FULLARGV 0x0002
922
923
924
925 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
926
927 typedef struct {
928 const char *cmd;
929 const char *args;
930 jim_subcmd_function *function;
931 short minargs;
932 short maxargs;
933 unsigned short flags;
934 } jim_subcmd_type;
935
936 const jim_subcmd_type *
937 Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
938
@@ -960,36 +984,36 @@
960 int rm_eo;
961 } regmatch_t;
962
963
964 typedef struct regexp {
965
966 int re_nsub;
967
968
969 int cflags;
970 int err;
971 int regstart;
972 int reganch;
973 int regmust;
974 int regmlen;
975 int *program;
976
977
978 const char *regparse;
979 int p;
980 int proglen;
981
982
983 int eflags;
984 const char *start;
985 const char *reginput;
986 const char *regbol;
987
988
989 regmatch_t *pmatch;
990 int nmatch;
991 } regexp;
992
993 typedef regexp regex_t;
994
995 #define REG_EXTENDED 0
@@ -997,13 +1021,13 @@
997 #define REG_ICASE 2
998
999 #define REG_NOTBOL 16
1000
1001 enum {
1002 REG_NOERROR,
1003 REG_NOMATCH,
1004 REG_BADPAT,
1005 REG_ERR_NULL_ARGUMENT,
1006 REG_ERR_UNKNOWN,
1007 REG_ERR_TOO_BIG,
1008 REG_ERR_NOMEM,
1009 REG_ERR_TOO_MANY_PAREN,
@@ -1100,10 +1124,43 @@
1100 "\n"
1101 "if {$tcl_platform(platform) eq \"windows\"} {\n"
1102 " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
1103 "}\n"
1104 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105 "_jimsh_init\n"
1106 );
1107 }
1108 int Jim_globInit(Jim_Interp *interp)
1109 {
@@ -1402,31 +1459,10 @@
1402 " if {[exists ::jim::exe]} {\n"
1403 " return $::jim::exe\n"
1404 " }\n"
1405 "}\n"
1406 "\n"
1407 "\n"
1408 "proc {dict with} {&dictVar {args key} script} {\n"
1409 " set keys {}\n"
1410 " foreach {n v} [dict get $dictVar {*}$key] {\n"
1411 " upvar $n var_$n\n"
1412 " set var_$n $v\n"
1413 " lappend keys $n\n"
1414 " }\n"
1415 " catch {uplevel 1 $script} msg opts\n"
1416 " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1417 " foreach n $keys {\n"
1418 " if {[info exists var_$n]} {\n"
1419 " dict set dictVar {*}$key $n [set var_$n]\n"
1420 " } else {\n"
1421 " dict unset dictVar {*}$key $n\n"
1422 " }\n"
1423 " }\n"
1424 " }\n"
1425 " return {*}$opts $msg\n"
1426 "}\n"
1427 "\n"
1428 "\n"
1429 "proc {dict update} {&varName args script} {\n"
1430 " set keys {}\n"
1431 " foreach {n v} $args {\n"
1432 " upvar $v var_$v\n"
@@ -1445,23 +1481,10 @@
1445 " }\n"
1446 " }\n"
1447 " return {*}$opts $msg\n"
1448 "}\n"
1449 "\n"
1450 "\n"
1451 "\n"
1452 "proc {dict merge} {dict args} {\n"
1453 " foreach d $args {\n"
1454 "\n"
1455 " dict size $d\n"
1456 " foreach {k v} $d {\n"
1457 " dict set dict $k $v\n"
1458 " }\n"
1459 " }\n"
1460 " return $dict\n"
1461 "}\n"
1462 "\n"
1463 "proc {dict replace} {dictionary {args {key value}}} {\n"
1464 " if {[llength ${key value}] % 2} {\n"
1465 " tailcall {dict replace}\n"
1466 " }\n"
1467 " tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1526,10 @@
1503 " dict unset dictionary $k\n"
1504 " }\n"
1505 " return $dictionary\n"
1506 "}\n"
1507 "\n"
1508 "\n"
1509 "proc {dict values} {dictionary {pattern *}} {\n"
1510 " dict keys [lreverse $dictionary] $pattern\n"
1511 "}\n"
1512 "\n"
1513 "\n"
1514 "proc {dict for} {vars dictionary script} {\n"
1515 " if {[llength $vars] != 2} {\n"
1516 " return -code error \"must have exactly two variable names\"\n"
1517 " }\n"
@@ -1588,11 +1606,10 @@
1588 "\n"
1589 "\n"
1590 "proc fileevent {args} {\n"
1591 " tailcall {*}$args\n"
1592 "}\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "proc parray {arrayname {pattern *} {puts puts}} {\n"
1598 " upvar $arrayname a\n"
@@ -1701,15 +1718,10 @@
1701 "\n"
1702 "\n"
1703 "\n"
1704 "\n"
1705 "\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "proc try {args} {\n"
1712 " set catchopts {}\n"
1713 " while {[string match -* [lindex $args 0]]} {\n"
1714 " set args [lassign $args opt]\n"
1715 " if {$opt eq \"--\"} {\n"
@@ -1780,10 +1792,13 @@
1780 "}\n"
1781 );
1782 }
1783
1784
 
 
 
1785 #include <stdio.h>
1786 #include <string.h>
1787 #include <errno.h>
1788 #include <fcntl.h>
1789 #ifdef HAVE_UNISTD_H
@@ -1807,13 +1822,16 @@
1807 #if defined(JIM_SSL)
1808 #include <openssl/ssl.h>
1809 #include <openssl/err.h>
1810 #endif
1811
 
 
1812
1813 #define AIO_CMD_LEN 32
1814 #define AIO_BUF_LEN 256
 
1815
1816 #ifndef HAVE_FTELLO
1817 #define ftello ftell
1818 #endif
1819 #ifndef HAVE_FSEEKO
@@ -1848,11 +1866,11 @@
1848 typedef struct AioFile
1849 {
1850 FILE *fp;
1851 Jim_Obj *filename;
1852 int type;
1853 int openFlags;
1854 int fd;
1855 Jim_Obj *rEvent;
1856 Jim_Obj *wEvent;
1857 Jim_Obj *eEvent;
1858 int addr_family;
@@ -1879,21 +1897,21 @@
1879 {
1880 if (!ferror(af->fp)) {
1881 return JIM_OK;
1882 }
1883 clearerr(af->fp);
1884
1885 if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
1886 return JIM_OK;
1887 }
1888 #ifdef ECONNRESET
1889 if (errno == ECONNRESET) {
1890 return JIM_OK;
1891 }
1892 #endif
1893 #ifdef ECONNABORTED
1894 if (errno != ECONNABORTED) {
1895 return JIM_OK;
1896 }
1897 #endif
1898 return JIM_ERR;
1899 }
@@ -1945,20 +1963,19 @@
1945 JIM_NOTUSED(interp);
1946
1947 Jim_DecrRefCount(interp, af->filename);
1948
1949 #ifdef jim_ext_eventloop
1950
1951 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1952 #endif
1953
1954 #if defined(JIM_SSL)
1955 if (af->ssl != NULL) {
1956 SSL_free(af->ssl);
1957 }
1958 #endif
1959
1960 if (!(af->openFlags & AIO_KEEPOPEN)) {
1961 fclose(af->fp);
1962 }
1963
1964 Jim_Free(af);
@@ -1968,11 +1985,11 @@
1968 {
1969 AioFile *af = Jim_CmdPrivData(interp);
1970 char buf[AIO_BUF_LEN];
1971 Jim_Obj *objPtr;
1972 int nonewline = 0;
1973 jim_wide neededLen = -1;
1974
1975 if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
1976 nonewline = 1;
1977 argv++;
1978 argc--;
@@ -2007,11 +2024,11 @@
2007 }
2008 }
2009 if (retval != readlen)
2010 break;
2011 }
2012
2013 if (JimCheckStreamError(interp, af)) {
2014 Jim_FreeNewObj(interp, objPtr);
2015 return JIM_ERR;
2016 }
2017 if (nonewline) {
@@ -2029,11 +2046,11 @@
2029
2030 AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
2031 {
2032 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2033
2034
2035 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2036 return (AioFile *) cmdPtr->u.native.privData;
2037 }
2038 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2039 return NULL;
@@ -2110,21 +2127,21 @@
2110 }
2111 else {
2112 len = strlen(buf);
2113
2114 if (len && (buf[len - 1] == '\n')) {
2115
2116 len--;
2117 }
2118
2119 Jim_AppendString(interp, objPtr, buf, len);
2120 break;
2121 }
2122 }
2123
2124 if (JimCheckStreamError(interp, af)) {
2125
2126 Jim_FreeNewObj(interp, objPtr);
2127 return JIM_ERR;
2128 }
2129
2130 if (argc) {
@@ -2134,11 +2151,11 @@
2134 }
2135
2136 len = Jim_Length(objPtr);
2137
2138 if (len == 0 && feof(af->fp)) {
2139
2140 len = -1;
2141 }
2142 Jim_SetResultInt(interp, len);
2143 }
2144 else {
@@ -2364,33 +2381,33 @@
2364
2365 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2366 int argc, Jim_Obj * const *argv)
2367 {
2368 if (argc == 0) {
2369
2370 if (*scriptHandlerObj) {
2371 Jim_SetResult(interp, *scriptHandlerObj);
2372 }
2373 return JIM_OK;
2374 }
2375
2376 if (*scriptHandlerObj) {
2377
2378 Jim_DeleteFileHandler(interp, af->fp, mask);
2379 }
2380
2381
2382 if (Jim_Length(argv[0]) == 0) {
2383
2384 return JIM_OK;
2385 }
2386
2387
2388 Jim_IncrRefCount(argv[0]);
2389 *scriptHandlerObj = argv[0];
2390
2391 Jim_CreateFileHandler(interp, af->fp, mask,
2392 JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
2393
2394 return JIM_OK;
2395 }
2396
@@ -2414,136 +2431,138 @@
2414
2415 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2416 }
2417 #endif
2418
 
 
2419
2420 static const jim_subcmd_type aio_command_table[] = {
2421 { "read",
2422 "?-nonewline? ?len?",
2423 aio_cmd_read,
2424 0,
2425 2,
2426
2427 },
2428 { "copyto",
2429 "handle ?size?",
2430 aio_cmd_copy,
2431 1,
2432 2,
2433
2434 },
2435 { "gets",
2436 "?var?",
2437 aio_cmd_gets,
2438 0,
2439 1,
2440
2441 },
2442 { "puts",
2443 "?-nonewline? str",
2444 aio_cmd_puts,
2445 1,
2446 2,
2447
2448 },
2449 { "isatty",
2450 NULL,
2451 aio_cmd_isatty,
2452 0,
2453 0,
2454
2455 },
2456 { "flush",
2457 NULL,
2458 aio_cmd_flush,
2459 0,
2460 0,
2461
2462 },
2463 { "eof",
2464 NULL,
2465 aio_cmd_eof,
2466 0,
2467 0,
2468
2469 },
2470 { "close",
2471 "?r(ead)|w(rite)?",
2472 aio_cmd_close,
2473 0,
2474 1,
2475 JIM_MODFLAG_FULLARGV,
2476
2477 },
2478 { "seek",
2479 "offset ?start|current|end",
2480 aio_cmd_seek,
2481 1,
2482 2,
2483
2484 },
2485 { "tell",
2486 NULL,
2487 aio_cmd_tell,
2488 0,
2489 0,
2490
2491 },
2492 { "filename",
2493 NULL,
2494 aio_cmd_filename,
2495 0,
2496 0,
2497
2498 },
2499 #ifdef O_NDELAY
2500 { "ndelay",
2501 "?0|1?",
2502 aio_cmd_ndelay,
2503 0,
2504 1,
2505
2506 },
2507 #endif
2508 #ifdef HAVE_FSYNC
2509 { "sync",
2510 NULL,
2511 aio_cmd_sync,
2512 0,
2513 0,
2514
2515 },
2516 #endif
2517 { "buffering",
2518 "none|line|full",
2519 aio_cmd_buffering,
2520 1,
2521 1,
2522
2523 },
2524 #ifdef jim_ext_eventloop
2525 { "readable",
2526 "?readable-script?",
2527 aio_cmd_readable,
2528 0,
2529 1,
2530
2531 },
2532 { "writable",
2533 "?writable-script?",
2534 aio_cmd_writable,
2535 0,
2536 1,
2537
2538 },
2539 { "onexception",
2540 "?exception-script?",
2541 aio_cmd_onexception,
2542 0,
2543 1,
2544
2545 },
2546 #endif
2547 { NULL }
2548 };
2549
@@ -2566,11 +2585,11 @@
2566
2567 #ifdef jim_ext_tclcompat
2568 {
2569 const char *filename = Jim_String(argv[1]);
2570
2571
2572 if (*filename == '|') {
2573 Jim_Obj *evalObj[3];
2574
2575 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2576 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2623,11 +2642,11 @@
2623 Jim_DecrRefCount(interp, filename);
2624 return NULL;
2625 }
2626 }
2627
2628
2629 af = Jim_Alloc(sizeof(*af));
2630 memset(af, 0, sizeof(*af));
2631 af->fp = fh;
2632 af->fd = fileno(fh);
2633 af->filename = filename;
@@ -2661,27 +2680,27 @@
2661 Jim_SetResult(interp, objPtr);
2662 return JIM_OK;
2663 }
2664 }
2665
2666
2667 close(p[0]);
2668 close(p[1]);
2669 JimAioSetError(interp, NULL);
2670 return JIM_ERR;
2671 }
2672 #endif
2673
2674
2675 int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2676 {
2677 #ifdef HAVE_MKSTEMP
2678 int fd;
2679 mode_t mask;
2680 Jim_Obj *filenameObj;
2681
2682 if (template == NULL) {
2683 const char *tmpdir = getenv("TMPDIR");
2684 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2685 tmpdir = "/tmp/";
2686 }
2687 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
@@ -2689,21 +2708,15 @@
2689 Jim_AppendString(interp, filenameObj, "/", 1);
2690 }
2691 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2692 }
2693 else {
2694 filenameObj = Jim_NewStringObj(interp, template, -1);
2695 }
2696
2697 #if defined(S_IRWXG) && defined(S_IRWXO)
2698 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2699 #else
2700
2701 mask = umask(S_IXUSR);
2702 #endif
2703
2704
2705 fd = mkstemp(filenameObj->bytes);
2706 umask(mask);
2707 if (fd < 0) {
2708 JimAioSetError(interp, filenameObj);
2709 Jim_FreeNewObj(interp, filenameObj);
@@ -2731,11 +2744,11 @@
2731 Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
2732 #ifndef JIM_ANSIC
2733 Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
2734 #endif
2735
2736
2737 JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
2738 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2739 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2740
2741 return JIM_OK;
@@ -2831,20 +2844,20 @@
2831 {
2832 regex_t *compre;
2833 const char *pattern;
2834 int ret;
2835
2836
2837 if (objPtr->typePtr == &regexpObjType &&
2838 objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
2839
2840 return objPtr->internalRep.regexpValue.compre;
2841 }
2842
2843
2844
2845
 
2846 pattern = Jim_String(objPtr);
2847 compre = Jim_Alloc(sizeof(regex_t));
2848
2849 if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
2850 char buf[100];
@@ -3001,11 +3014,11 @@
3001 }
3002
3003 num_matches++;
3004
3005 if (opt_all && !opt_inline) {
3006
3007 goto try_next_match;
3008 }
3009
3010
3011 j = 0;
@@ -3041,11 +3054,11 @@
3041
3042 if (opt_inline) {
3043 Jim_ListAppendElement(interp, resultListObj, resultObj);
3044 }
3045 else {
3046
3047 result = Jim_SetVariable(interp, argv[i], resultObj);
3048
3049 if (result != JIM_OK) {
3050 Jim_FreeObj(interp, resultObj);
3051 break;
@@ -3168,11 +3181,11 @@
3168
3169 source_str = Jim_GetString(argv[i + 1], &source_len);
3170 replace_str = Jim_GetString(argv[i + 2], &replace_len);
3171 varname = argv[i + 3];
3172
3173
3174 resultObj = Jim_NewStringObj(interp, "", 0);
3175
3176 if (offset) {
3177 if (offset < 0) {
3178 offset += source_len + 1;
@@ -3183,11 +3196,11 @@
3183 else if (offset < 0) {
3184 offset = 0;
3185 }
3186 }
3187
3188
3189 Jim_AppendString(interp, resultObj, source_str, offset);
3190
3191
3192 n = source_len - offset;
3193 p = source_str + offset;
@@ -3242,23 +3255,23 @@
3242 }
3243
3244 p += pmatch[0].rm_eo;
3245 n -= pmatch[0].rm_eo;
3246
3247
3248 if (!opt_all || n == 0) {
3249 break;
3250 }
3251
3252
3253 if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
3254 break;
3255 }
3256
3257
3258 if (pattern[0] == '\0' && n) {
3259
3260 Jim_AppendString(interp, resultObj, p, 1);
3261 p++;
3262 n--;
3263 }
3264
@@ -3265,11 +3278,11 @@
3265 regexec_flags |= REG_NOTBOL;
3266 } while (n);
3267
3268 Jim_AppendString(interp, resultObj, p, -1);
3269
3270
3271 if (argc - i == 4) {
3272 result = Jim_SetVariable(interp, varname, resultObj);
3273
3274 if (result == JIM_OK) {
3275 Jim_SetResultInt(interp, num_matches);
@@ -3371,11 +3384,11 @@
3371 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
3372 }
3373
3374 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3375 {
3376
3377 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3378
3379 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3380 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3381 AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3400,38 @@
3387 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3388 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3389 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3390 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3391
3392
3393 if (varName) {
3394 Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
 
 
3395 if (objPtr) {
3396 if (Jim_DictSize(interp, objPtr) < 0) {
3397
 
 
 
 
 
 
3398 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3399 Jim_FreeNewObj(interp, listObj);
3400 return JIM_ERR;
3401 }
3402
3403 if (Jim_IsShared(objPtr))
3404 objPtr = Jim_DuplicateObj(interp, objPtr);
3405
3406
3407 Jim_ListAppendList(interp, objPtr, listObj);
3408 Jim_DictSize(interp, objPtr);
3409 Jim_InvalidateStringRep(objPtr);
3410
3411 Jim_FreeNewObj(interp, listObj);
3412 listObj = objPtr;
3413 }
3414 Jim_SetVariable(interp, varName, listObj);
3415 }
3416
3417
3418 Jim_SetResult(interp, listObj);
3419
3420 return JIM_OK;
3421 }
3422
@@ -3432,11 +3447,11 @@
3432 }
3433 else if (p == path) {
3434 Jim_SetResultString(interp, "/", -1);
3435 }
3436 else if (ISWINDOWS && p[-1] == ':') {
3437
3438 Jim_SetResultString(interp, path, p - path + 1);
3439 }
3440 else {
3441 Jim_SetResultString(interp, path, p - path);
3442 }
@@ -3512,35 +3527,35 @@
3512 char *newname = Jim_Alloc(MAXPATHLEN + 1);
3513 char *last = newname;
3514
3515 *newname = 0;
3516
3517
3518 for (i = 0; i < argc; i++) {
3519 int len;
3520 const char *part = Jim_GetString(argv[i], &len);
3521
3522 if (*part == '/') {
3523
3524 last = newname;
3525 }
3526 else if (ISWINDOWS && strchr(part, ':')) {
3527
3528 last = newname;
3529 }
3530 else if (part[0] == '.') {
3531 if (part[1] == '/') {
3532 part += 2;
3533 len -= 2;
3534 }
3535 else if (part[1] == 0 && last != newname) {
3536
3537 continue;
3538 }
3539 }
3540
3541
3542 if (last != newname && last[-1] != '/') {
3543 *last++ = '/';
3544 }
3545
3546 if (len) {
@@ -3551,22 +3566,22 @@
3551 }
3552 memcpy(last, part, len);
3553 last += len;
3554 }
3555
3556
3557 if (last > newname + 1 && last[-1] == '/') {
3558
3559 if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
3560 *--last = 0;
3561 }
3562 }
3563 }
3564
3565 *last = 0;
3566
3567
3568
3569 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
3570
3571 return JIM_OK;
3572 }
@@ -3591,11 +3606,11 @@
3591 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3592 {
3593 #ifdef X_OK
3594 return file_access(interp, argv[0], X_OK);
3595 #else
3596
3597 Jim_SetResultBool(interp, 1);
3598 return JIM_OK;
3599 #endif
3600 }
3601
@@ -3616,11 +3631,11 @@
3616 while (argc--) {
3617 const char *path = Jim_String(argv[0]);
3618
3619 if (unlink(path) == -1 && errno != ENOENT) {
3620 if (rmdir(path) == -1) {
3621
3622 if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
3623 Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
3624 strerror(errno));
3625 return JIM_ERR;
3626 }
@@ -3639,15 +3654,15 @@
3639
3640 static int mkdir_all(char *path)
3641 {
3642 int ok = 1;
3643
3644
3645 goto first;
3646
3647 while (ok--) {
3648
3649 {
3650 char *slash = strrchr(path, '/');
3651
3652 if (slash && slash != path) {
3653 *slash = 0;
@@ -3660,24 +3675,24 @@
3660 first:
3661 if (MKDIR_DEFAULT(path) == 0) {
3662 return 0;
3663 }
3664 if (errno == ENOENT) {
3665
3666 continue;
3667 }
3668
3669 if (errno == EEXIST) {
3670 struct stat sb;
3671
3672 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
3673 return 0;
3674 }
3675
3676 errno = EEXIST;
3677 }
3678
3679 break;
3680 }
3681 return -1;
3682 }
3683
@@ -3962,192 +3977,192 @@
3962 { "atime",
3963 "name",
3964 file_cmd_atime,
3965 1,
3966 1,
3967
3968 },
3969 { "mtime",
3970 "name ?time?",
3971 file_cmd_mtime,
3972 1,
3973 2,
3974
3975 },
3976 { "copy",
3977 "?-force? source dest",
3978 file_cmd_copy,
3979 2,
3980 3,
3981
3982 },
3983 { "dirname",
3984 "name",
3985 file_cmd_dirname,
3986 1,
3987 1,
3988
3989 },
3990 { "rootname",
3991 "name",
3992 file_cmd_rootname,
3993 1,
3994 1,
3995
3996 },
3997 { "extension",
3998 "name",
3999 file_cmd_extension,
4000 1,
4001 1,
4002
4003 },
4004 { "tail",
4005 "name",
4006 file_cmd_tail,
4007 1,
4008 1,
4009
4010 },
4011 { "normalize",
4012 "name",
4013 file_cmd_normalize,
4014 1,
4015 1,
4016
4017 },
4018 { "join",
4019 "name ?name ...?",
4020 file_cmd_join,
4021 1,
4022 -1,
4023
4024 },
4025 { "readable",
4026 "name",
4027 file_cmd_readable,
4028 1,
4029 1,
4030
4031 },
4032 { "writable",
4033 "name",
4034 file_cmd_writable,
4035 1,
4036 1,
4037
4038 },
4039 { "executable",
4040 "name",
4041 file_cmd_executable,
4042 1,
4043 1,
4044
4045 },
4046 { "exists",
4047 "name",
4048 file_cmd_exists,
4049 1,
4050 1,
4051
4052 },
4053 { "delete",
4054 "?-force|--? name ...",
4055 file_cmd_delete,
4056 1,
4057 -1,
4058
4059 },
4060 { "mkdir",
4061 "dir ...",
4062 file_cmd_mkdir,
4063 1,
4064 -1,
4065
4066 },
4067 { "tempfile",
4068 "?template?",
4069 file_cmd_tempfile,
4070 0,
4071 1,
4072
4073 },
4074 { "rename",
4075 "?-force? source dest",
4076 file_cmd_rename,
4077 2,
4078 3,
4079
4080 },
4081 #if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
4082 { "link",
4083 "?-symbolic|-hard? newname target",
4084 file_cmd_link,
4085 2,
4086 3,
4087
4088 },
4089 #endif
4090 #if defined(HAVE_READLINK)
4091 { "readlink",
4092 "name",
4093 file_cmd_readlink,
4094 1,
4095 1,
4096
4097 },
4098 #endif
4099 { "size",
4100 "name",
4101 file_cmd_size,
4102 1,
4103 1,
4104
4105 },
4106 { "stat",
4107 "name ?var?",
4108 file_cmd_stat,
4109 1,
4110 2,
4111
4112 },
4113 { "lstat",
4114 "name ?var?",
4115 file_cmd_lstat,
4116 1,
4117 2,
4118
4119 },
4120 { "type",
4121 "name",
4122 file_cmd_type,
4123 1,
4124 1,
4125
4126 },
4127 #ifdef HAVE_GETEUID
4128 { "owned",
4129 "name",
4130 file_cmd_owned,
4131 1,
4132 1,
4133
4134 },
4135 #endif
4136 { "isdirectory",
4137 "name",
4138 file_cmd_isdirectory,
4139 1,
4140 1,
4141
4142 },
4143 { "isfile",
4144 "name",
4145 file_cmd_isfile,
4146 1,
4147 1,
4148
4149 },
4150 {
4151 NULL
4152 }
4153 };
@@ -4179,11 +4194,11 @@
4179 Jim_SetResultString(interp, "Failed to get pwd", -1);
4180 Jim_Free(cwd);
4181 return JIM_ERR;
4182 }
4183 else if (ISWINDOWS) {
4184
4185 char *p = cwd;
4186 while ((p = strchr(p, '\\')) != NULL) {
4187 *p++ = '/';
4188 }
4189 }
@@ -4203,10 +4218,13 @@
4203 Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
4204 Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
4205 return JIM_OK;
4206 }
4207
 
 
 
4208 #include <string.h>
4209 #include <ctype.h>
4210
4211
4212 #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4232,20 @@
4214 {
4215 Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
4216 int i, j;
4217 int rc;
4218
4219
4220 for (i = 1; i < argc; i++) {
4221 int len;
4222 const char *arg = Jim_GetString(argv[i], &len);
4223
4224 if (i > 1) {
4225 Jim_AppendString(interp, cmdlineObj, " ", 1);
4226 }
4227 if (strpbrk(arg, "\\\" ") == NULL) {
4228
4229 Jim_AppendString(interp, cmdlineObj, arg, len);
4230 continue;
4231 }
4232
4233 Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4268,11 +4286,11 @@
4268
4269 #include <errno.h>
4270 #include <signal.h>
4271
4272 #if defined(__MINGW32__)
4273
4274 #ifndef STRICT
4275 #define STRICT
4276 #endif
4277 #define WIN32_LEAN_AND_MEAN
4278 #include <windows.h>
@@ -4294,11 +4312,11 @@
4294 static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
4295 static fdtype JimDupFd(fdtype infd);
4296 static fdtype JimOpenForRead(const char *filename);
4297 static FILE *JimFdOpenForRead(fdtype fd);
4298 static int JimPipe(fdtype pipefd[2]);
4299 static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
4300 fdtype inputId, fdtype outputId, fdtype errorId);
4301 static int JimErrno(void);
4302 #else
4303 #include <unistd.h>
4304 #include <fcntl.h>
@@ -4323,10 +4341,11 @@
4323 #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
4324 #endif
4325 #endif
4326
4327 static const char *JimStrError(void);
 
4328 static char **JimSaveEnv(char **env);
4329 static void JimRestoreEnv(char **env);
4330 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4331 pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4332 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
@@ -4390,18 +4409,18 @@
4390 char *envdata;
4391
4392 Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
4393
4394 if (!objPtr) {
4395 return Jim_GetEnviron();
4396 }
4397
4398
4399
4400 num = Jim_ListLength(interp, objPtr);
4401 if (num % 2) {
4402
4403 num--;
4404 }
4405 size = Jim_Length(objPtr) + 2;
4406
4407 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4493,19 +4512,19 @@
4493 }
4494
4495
4496 struct WaitInfo
4497 {
4498 pidtype pid;
4499 int status;
4500 int flags;
4501 };
4502
4503 struct WaitInfoTable {
4504 struct WaitInfo *info;
4505 int size;
4506 int used;
4507 };
4508
4509
4510 #define WI_DETACHED 2
4511
@@ -4528,12 +4547,12 @@
4528 return table;
4529 }
4530
4531 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4532 {
4533 fdtype outputId;
4534 fdtype errorId;
4535 pidtype *pidPtr;
4536 int numPids, result;
4537 int child_siginfo = 1;
4538 Jim_Obj *childErrObj;
4539 Jim_Obj *errStrObj;
@@ -4545,11 +4564,11 @@
4545 argc--;
4546 numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
4547 if (numPids < 0) {
4548 return JIM_ERR;
4549 }
4550
4551 listObj = Jim_NewListObj(interp, NULL, 0);
4552 for (i = 0; i < numPids; i++) {
4553 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
4554 }
4555 Jim_SetResult(interp, listObj);
@@ -4567,19 +4586,19 @@
4567
4568 result = JIM_OK;
4569
4570 errStrObj = Jim_NewStringObj(interp, "", 0);
4571
4572
4573 if (outputId != JIM_BAD_FD) {
4574 if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
4575 result = JIM_ERR;
4576 Jim_SetResultErrno(interp, "error reading from output pipe");
4577 }
4578 }
4579
4580
4581 childErrObj = Jim_NewStringObj(interp, "", 0);
4582 Jim_IncrRefCount(childErrObj);
4583
4584 if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
4585 result = JIM_ERR;
@@ -4592,25 +4611,25 @@
4592 if (ret < 0) {
4593 Jim_SetResultErrno(interp, "error reading from error pipe");
4594 result = JIM_ERR;
4595 }
4596 else if (ret > 0) {
4597
4598 child_siginfo = 0;
4599 }
4600 }
4601
4602 if (child_siginfo) {
4603
4604 Jim_AppendObj(interp, errStrObj, childErrObj);
4605 }
4606 Jim_DecrRefCount(interp, childErrObj);
4607
4608
4609 Jim_RemoveTrailingNewline(errStrObj);
4610
4611
4612 Jim_SetResult(interp, errStrObj);
4613
4614 return result;
4615 }
4616
@@ -4629,11 +4648,11 @@
4629 for (count = table->used; count > 0; waitPtr++, count--) {
4630 if (waitPtr->flags & WI_DETACHED) {
4631 int status;
4632 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4633 if (pid == waitPtr->pid) {
4634
4635 table->used--;
4636 continue;
4637 }
4638 }
4639 if (waitPtr != &table->info[dest]) {
@@ -4645,36 +4664,36 @@
4645
4646 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4647 {
4648 int i;
4649
4650
4651 for (i = 0; i < table->used; i++) {
4652 if (pid == table->info[i].pid) {
4653
4654 JimWaitPid(pid, statusPtr, 0);
4655
4656
4657 if (i != table->used - 1) {
4658 table->info[i] = table->info[table->used - 1];
4659 }
4660 table->used--;
4661 return pid;
4662 }
4663 }
4664
4665
4666 return JIM_BAD_PID;
4667 }
4668
4669 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4670 {
4671 int j;
4672 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4673
4674 for (j = 0; j < numPids; j++) {
4675
4676 int i;
4677 for (i = 0; i < table->used; i++) {
4678 if (pidPtr[j] == table->info[i].pid) {
4679 table->info[i].flags |= WI_DETACHED;
4680 break;
@@ -4707,16 +4726,16 @@
4707 int cmdCount; /* Count of number of distinct commands
4708 * found in argc/argv. */
4709 const char *input = NULL; /* Describes input for pipeline, depending
4710 * on "inputFile". NULL means take input
4711 * from stdin/pipe. */
4712 int input_len = 0;
4713
4714 #define FILE_NAME 0
4715 #define FILE_APPEND 1
4716 #define FILE_HANDLE 2
4717 #define FILE_TEXT 3
4718
4719 int inputFile = FILE_NAME; /* 1 means input is name of input file.
4720 * 2 means input is filehandle name.
4721 * 0 means input holds actual
4722 * text to be input to command. */
@@ -4737,20 +4756,20 @@
4737 * or NULL if stderr goes to stderr/pipe. */
4738 fdtype inputId = JIM_BAD_FD;
4739 fdtype outputId = JIM_BAD_FD;
4740 fdtype errorId = JIM_BAD_FD;
4741 fdtype lastOutputId = JIM_BAD_FD;
4742 fdtype pipeIds[2];
4743 int firstArg, lastArg; /* Indexes of first and last arguments in
4744 * current command. */
4745 int lastBar;
4746 int i;
4747 pidtype pid;
4748 char **save_environ;
4749 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4750
4751
4752 char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
4753 int arg_count = 0;
4754
4755 JimReapDetachedPids(table);
4756
@@ -4796,11 +4815,11 @@
4796 if (*output == '>') {
4797 outputFile = FILE_APPEND;
4798 output++;
4799 }
4800 if (*output == '&') {
4801
4802 output++;
4803 dup_error = 1;
4804 }
4805 if (*output == '@') {
4806 outputFile = FILE_HANDLE;
@@ -4837,11 +4856,11 @@
4837 goto badargs;
4838 }
4839 lastBar = i;
4840 cmdCount++;
4841 }
4842
4843 arg_array[arg_count++] = (char *)arg;
4844 continue;
4845 }
4846
4847 if (i >= argc) {
@@ -4855,11 +4874,11 @@
4855 badargs:
4856 Jim_Free(arg_array);
4857 return -1;
4858 }
4859
4860
4861 save_environ = JimSaveEnv(JimBuildEnv(interp));
4862
4863 if (input != NULL) {
4864 if (inputFile == FILE_TEXT) {
4865 inputId = JimCreateTemp(interp, input, input_len);
@@ -4866,11 +4885,11 @@
4866 if (inputId == JIM_BAD_FD) {
4867 goto error;
4868 }
4869 }
4870 else if (inputFile == FILE_HANDLE) {
4871
4872 FILE *fh = JimGetAioFilehandle(interp, input);
4873
4874 if (fh == NULL) {
4875 goto error;
4876 }
@@ -4918,20 +4937,20 @@
4918 }
4919 lastOutputId = pipeIds[1];
4920 *outPipePtr = pipeIds[0];
4921 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4922 }
4923
4924 if (error != NULL) {
4925 if (errorFile == FILE_HANDLE) {
4926 if (strcmp(error, "1") == 0) {
4927
4928 if (lastOutputId != JIM_BAD_FD) {
4929 errorId = JimDupFd(lastOutputId);
4930 }
4931 else {
4932
4933 error = "stdout";
4934 }
4935 }
4936 if (errorId == JIM_BAD_FD) {
4937 FILE *fh = JimGetAioFilehandle(interp, error);
@@ -4973,11 +4992,11 @@
4973 pipe_dup_err = 1;
4974 }
4975 break;
4976 }
4977 }
4978
4979 arg_array[lastArg] = NULL;
4980 if (lastArg == arg_count) {
4981 outputId = lastOutputId;
4982 }
4983 else {
@@ -4986,19 +5005,19 @@
4986 goto error;
4987 }
4988 outputId = pipeIds[1];
4989 }
4990
4991
4992 if (pipe_dup_err) {
4993 errorId = outputId;
4994 }
4995
4996
4997
4998 #ifdef __MINGW32__
4999 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
5000 if (pid == JIM_BAD_PID) {
5001 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
5002 goto error;
5003 }
5004 #else
@@ -5006,32 +5025,39 @@
5006 if (pid < 0) {
5007 Jim_SetResultErrno(interp, "couldn't fork child process");
5008 goto error;
5009 }
5010 if (pid == 0) {
5011
5012
5013 if (inputId != -1) dup2(inputId, 0);
5014 if (outputId != -1) dup2(outputId, 1);
5015 if (errorId != -1) dup2(errorId, 2);
5016
5017 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
5018 close(i);
5019 }
5020
5021
5022 (void)signal(SIGPIPE, SIG_DFL);
5023
5024 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
5025
5026
5027 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
 
 
 
 
 
 
 
5028 _exit(127);
5029 }
5030 #endif
5031
5032
5033
5034 if (table->used == table->size) {
5035 table->size += WAIT_TABLE_GROW_BY;
5036 table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
5037 }
@@ -5040,19 +5066,20 @@
5040 table->info[table->used].flags = 0;
5041 table->used++;
5042
5043 pidPtr[numPids] = pid;
5044
5045
5046 errorId = origErrorId;
5047
5048
5049 if (inputId != JIM_BAD_FD) {
5050 JimCloseFd(inputId);
5051 }
5052 if (outputId != JIM_BAD_FD) {
5053 JimCloseFd(outputId);
 
5054 }
5055 inputId = pipeIds[0];
5056 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5057 }
5058 *pidArrayPtr = pidPtr;
@@ -5111,11 +5138,11 @@
5111 {
5112 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
5113 int result = JIM_OK;
5114 int i;
5115
5116
5117 for (i = 0; i < numPids; i++) {
5118 int waitStatus = 0;
5119 if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
5120 if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
5121 result = JIM_ERR;
@@ -5284,17 +5311,21 @@
5284 }
5285
5286 static fdtype JimOpenForRead(const char *filename)
5287 {
5288 return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
5289 JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
5290 }
5291
5292 static fdtype JimOpenForWrite(const char *filename, int append)
5293 {
5294 return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5295 JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
 
 
 
 
5296 }
5297
5298 static FILE *JimFdOpenForWrite(fdtype fd)
5299 {
5300 return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
@@ -5302,11 +5333,11 @@
5302
5303 static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
5304 {
5305 DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
5306 if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
5307
5308 return JIM_BAD_PID;
5309 }
5310 GetExitCodeProcess(pid, &ret);
5311 *status = ret;
5312 CloseHandle(pid);
@@ -5329,11 +5360,11 @@
5329 if (handle == INVALID_HANDLE_VALUE) {
5330 goto error;
5331 }
5332
5333 if (contents != NULL) {
5334
5335 FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
5336 if (fh == NULL) {
5337 goto error;
5338 }
5339
@@ -5381,10 +5412,15 @@
5381
5382 static void JimRestoreEnv(char **env)
5383 {
5384 JimFreeEnv(env, Jim_GetEnviron());
5385 }
 
 
 
 
 
5386
5387 static Jim_Obj *
5388 JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
5389 {
5390 char *start, *special;
@@ -5455,18 +5491,19 @@
5455 }
5456 return strObj;
5457 }
5458
5459 static pidtype
5460 JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
5461 {
5462 STARTUPINFO startInfo;
5463 PROCESS_INFORMATION procInfo;
5464 HANDLE hProcess, h;
5465 char execPath[MAX_PATH];
5466 pidtype pid = JIM_BAD_PID;
5467 Jim_Obj *cmdLineObj;
 
5468
5469 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5470 return JIM_BAD_PID;
5471 }
5472 argv[0] = execPath;
@@ -5514,13 +5551,24 @@
5514 0, TRUE, DUPLICATE_SAME_ACCESS);
5515 }
5516 if (startInfo.hStdError == JIM_BAD_FD) {
5517 goto end;
5518 }
 
 
 
 
 
 
 
 
 
 
 
5519
5520 if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5521 0, env, NULL, &startInfo, &procInfo)) {
5522 goto end;
5523 }
5524
5525
5526 WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5568,10 +5616,15 @@
5568 lseek(fd, 0L, SEEK_SET);
5569 }
5570 }
5571 return fd;
5572 }
 
 
 
 
 
5573
5574 static char **JimSaveEnv(char **env)
5575 {
5576 char **saveenv = Jim_GetEnviron();
5577 Jim_SetEnviron(env);
@@ -5601,11 +5654,11 @@
5601 #include <sys/time.h>
5602 #endif
5603
5604 static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5605 {
5606
5607 char buf[100];
5608 time_t t;
5609 long seconds;
5610
5611 const char *format = "%a %b %d %H:%M:%S %Z %Y";
@@ -5642,20 +5695,20 @@
5642
5643 if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
5644 return -1;
5645 }
5646
5647
5648 localtime_r(&now, &tm);
5649
5650 pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
5651 if (pt == 0 || *pt != 0) {
5652 Jim_SetResultString(interp, "Failed to parse time according to format", -1);
5653 return JIM_ERR;
5654 }
5655
5656
5657 Jim_SetResultInt(interp, mktime(&tm));
5658
5659 return JIM_OK;
5660 }
5661 #endif
@@ -5693,47 +5746,47 @@
5693 { "seconds",
5694 NULL,
5695 clock_cmd_seconds,
5696 0,
5697 0,
5698
5699 },
5700 { "clicks",
5701 NULL,
5702 clock_cmd_micros,
5703 0,
5704 0,
5705
5706 },
5707 { "microseconds",
5708 NULL,
5709 clock_cmd_micros,
5710 0,
5711 0,
5712
5713 },
5714 { "milliseconds",
5715 NULL,
5716 clock_cmd_millis,
5717 0,
5718 0,
5719
5720 },
5721 { "format",
5722 "seconds ?-format format?",
5723 clock_cmd_format,
5724 1,
5725 3,
5726
5727 },
5728 #ifdef HAVE_STRPTIME
5729 { "scan",
5730 "str -format format",
5731 clock_cmd_scan,
5732 3,
5733 3,
5734
5735 },
5736 #endif
5737 { NULL }
5738 };
5739
@@ -5753,12 +5806,13 @@
5753 #include <errno.h>
5754
5755
5756 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5757 {
5758
5759 Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
 
5760 return JIM_OK;
5761 }
5762
5763 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5764 {
@@ -5769,21 +5823,20 @@
5769 return JIM_OK;
5770 }
5771
5772 patternObj = (argc == 1) ? NULL : argv[1];
5773
5774
5775 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5776 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5777
5778 Jim_SetResult(interp, objPtr);
5779 return JIM_OK;
5780 }
5781 }
5782
5783
5784 return Jim_DictValues(interp, objPtr, patternObj);
5785 }
5786
5787 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5788 {
5789 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5843,11 @@
5790
5791 if (!objPtr) {
5792 return JIM_OK;
5793 }
5794
5795 return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
5796 }
5797
5798 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5799 {
5800 int i;
@@ -5802,27 +5855,29 @@
5802 Jim_Obj *resultObj;
5803 Jim_Obj *objPtr;
5804 Jim_Obj **dictValuesObj;
5805
5806 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5807
5808 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5809 return JIM_OK;
5810 }
5811
5812 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5813
5814 if (objPtr == NULL) {
5815
5816 return JIM_OK;
5817 }
5818
5819 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5820 return JIM_ERR;
 
 
5821 }
5822
5823
5824 resultObj = Jim_NewDictObj(interp, NULL, 0);
5825
5826 for (i = 0; i < len; i += 2) {
5827 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
5828 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5892,18 @@
5837 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5838 {
5839 Jim_Obj *objPtr;
5840 int len = 0;
5841
5842
5843 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5844 if (objPtr) {
5845 len = Jim_DictSize(interp, objPtr);
5846 if (len < 0) {
5847 return JIM_ERR;
 
 
5848 }
5849 }
5850
5851 Jim_SetResultInt(interp, len);
5852
@@ -5876,11 +5933,11 @@
5876 return JIM_ERR;
5877 }
5878
5879 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5880 if (!dictObj) {
5881
5882 return Jim_SetVariable(interp, argv[0], listObj);
5883 }
5884 else if (Jim_DictSize(interp, dictObj) < 0) {
5885 return JIM_ERR;
5886 }
@@ -5905,53 +5962,53 @@
5905 { "exists",
5906 "arrayName",
5907 array_cmd_exists,
5908 1,
5909 1,
5910
5911 },
5912 { "get",
5913 "arrayName ?pattern?",
5914 array_cmd_get,
5915 1,
5916 2,
5917
5918 },
5919 { "names",
5920 "arrayName ?pattern?",
5921 array_cmd_names,
5922 1,
5923 2,
5924
5925 },
5926 { "set",
5927 "arrayName list",
5928 array_cmd_set,
5929 2,
5930 2,
5931
5932 },
5933 { "size",
5934 "arrayName",
5935 array_cmd_size,
5936 1,
5937 1,
5938
5939 },
5940 { "stat",
5941 "arrayName",
5942 array_cmd_stat,
5943 1,
5944 1,
5945
5946 },
5947 { "unset",
5948 "arrayName ?pattern?",
5949 array_cmd_unset,
5950 1,
5951 2,
5952
5953 },
5954 { NULL
5955 }
5956 };
5957
@@ -5987,11 +6044,14 @@
5987 Jim_arrayInit(interp);
5988 Jim_stdlibInit(interp);
5989 Jim_tclcompatInit(interp);
5990 return JIM_OK;
5991 }
5992 #define JIM_OPTIMIZATION
 
 
 
5993
5994 #include <stdio.h>
5995 #include <stdlib.h>
5996
5997 #include <string.h>
@@ -6056,10 +6116,16 @@
6056 #define JimPanic(X) JimPanicDump X
6057 #else
6058 #define JimPanic(X)
6059 #endif
6060
 
 
 
 
 
 
6061
6062 static char JimEmptyStringRep[] = "";
6063
6064 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
6065 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6178,34 @@
6112 if (*pattern == '^') {
6113 not++;
6114 pattern++;
6115 }
6116
6117
6118 if (*pattern == ']') {
6119 goto first;
6120 }
6121 }
6122
6123 while (*pattern && *pattern != ']') {
6124
6125 if (pattern[0] == '\\') {
6126 first:
6127 pattern += utf8_tounicode_case(pattern, &pchar, nocase);
6128 }
6129 else {
6130
6131 int start;
6132 int end;
6133
6134 pattern += utf8_tounicode_case(pattern, &start, nocase);
6135 if (pattern[0] == '-' && pattern[1]) {
6136
6137 pattern += utf8_tounicode(pattern, &pchar);
6138 pattern += utf8_tounicode_case(pattern, &end, nocase);
6139
6140
6141 if ((c >= start && c <= end) || (c >= end && c <= start)) {
6142 match = 1;
6143 }
6144 continue;
6145 }
@@ -6169,19 +6235,19 @@
6169 while (pattern[1] == '*') {
6170 pattern++;
6171 }
6172 pattern++;
6173 if (!pattern[0]) {
6174 return 1;
6175 }
6176 while (*string) {
6177
6178 if (JimGlobMatch(pattern, string, nocase))
6179 return 1;
6180 string += utf8_tounicode(string, &c);
6181 }
6182 return 0;
6183
6184 case '?':
6185 string += utf8_tounicode(string, &c);
6186 break;
6187
@@ -6190,20 +6256,20 @@
6190 pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
6191 if (!pattern) {
6192 return 0;
6193 }
6194 if (!*pattern) {
6195
6196 continue;
6197 }
6198 break;
6199 }
6200 case '\\':
6201 if (pattern[1]) {
6202 pattern++;
6203 }
6204
6205 default:
6206 string += utf8_tounicode_case(string, &c, nocase);
6207 utf8_tounicode_case(pattern, &pchar, nocase);
6208 if (pchar != c) {
6209 return 0;
@@ -6249,11 +6315,11 @@
6249 maxchars--;
6250 }
6251 if (!maxchars) {
6252 return 0;
6253 }
6254
6255 if (*s1) {
6256 return 1;
6257 }
6258 if (*s2) {
6259 return -1;
@@ -6290,11 +6356,11 @@
6290 const char *p;
6291
6292 if (!l1 || !l2 || l1 > l2)
6293 return -1;
6294
6295
6296 for (p = s2 + l2 - 1; p != s2 - 1; p--) {
6297 if (*p == *s1 && memcmp(s1, p, l1) == 0) {
6298 return p - s2;
6299 }
6300 }
@@ -6349,28 +6415,28 @@
6349 }
6350 *sign = 1;
6351 }
6352
6353 if (str[i] != '0') {
6354
6355 return 0;
6356 }
6357
6358
6359 switch (str[i + 1]) {
6360 case 'x': case 'X': *base = 16; break;
6361 case 'o': case 'O': *base = 8; break;
6362 case 'b': case 'B': *base = 2; break;
6363 default: return 0;
6364 }
6365 i += 2;
6366
6367 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6368
6369 return i;
6370 }
6371
6372 *base = 10;
6373 return 0;
6374 }
6375
6376 static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6450,11 @@
6384 if (endptr == NULL || *endptr != str + i) {
6385 return value * sign;
6386 }
6387 }
6388
6389
6390 return strtol(str, endptr, 10);
6391 }
6392
6393
6394 static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6469,11 @@
6403 if (endptr == NULL || *endptr != str + i) {
6404 return value * sign;
6405 }
6406 }
6407
6408
6409 return strtoull(str, endptr, 10);
6410 #else
6411 return (unsigned long)jim_strtol(str, endptr);
6412 #endif
6413 }
@@ -6428,26 +6494,40 @@
6428
6429 int Jim_StringToDouble(const char *str, double *doublePtr)
6430 {
6431 char *endptr;
6432
6433
6434 errno = 0;
6435
6436 *doublePtr = strtod(str, &endptr);
6437
6438 return JimCheckConversion(str, endptr);
6439 }
6440
6441 static jim_wide JimPowWide(jim_wide b, jim_wide e)
6442 {
6443 jim_wide i, res = 1;
6444
6445 if ((b == 0 && e != 0) || (e < 0))
6446 return 0;
6447 for (i = 0; i < e; i++) {
6448 res *= b;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6449 }
6450 return res;
6451 }
6452
6453 #ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6589,11 @@
6509 char *Jim_StrDupLen(const char *s, int l)
6510 {
6511 char *copy = Jim_Alloc(l + 1);
6512
6513 memcpy(copy, s, l + 1);
6514 copy[l] = 0;
6515 return copy;
6516 }
6517
6518
6519
@@ -6598,52 +6678,52 @@
6598 }
6599
6600
6601 void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
6602 {
6603 Jim_HashTable n;
6604 unsigned int realsize = JimHashTableNextPower(size), i;
6605
6606 if (size <= ht->used)
6607 return;
6608
6609 Jim_InitHashTable(&n, ht->type, ht->privdata);
6610 n.size = realsize;
6611 n.sizemask = realsize - 1;
6612 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6613
6614 n.uniq = ht->uniq;
6615
6616
6617 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6618
6619 n.used = ht->used;
6620 for (i = 0; ht->used > 0; i++) {
6621 Jim_HashEntry *he, *nextHe;
6622
6623 if (ht->table[i] == NULL)
6624 continue;
6625
6626
6627 he = ht->table[i];
6628 while (he) {
6629 unsigned int h;
6630
6631 nextHe = he->next;
6632
6633 h = Jim_HashKey(ht, he->key) & n.sizemask;
6634 he->next = n.table[h];
6635 n.table[h] = he;
6636 ht->used--;
6637
6638 he = nextHe;
6639 }
6640 }
6641 assert(ht->used == 0);
6642 Jim_Free(ht->table);
6643
6644
6645 *ht = n;
6646 }
6647
6648
6649 int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6732,11 @@
6652
6653 entry = JimInsertHashEntry(ht, key, 0);
6654 if (entry == NULL)
6655 return JIM_ERR;
6656
6657
6658 Jim_SetHashKey(ht, entry, key);
6659 Jim_SetHashVal(ht, entry, val);
6660 return JIM_OK;
6661 }
6662
@@ -6678,11 +6758,11 @@
6678 Jim_SetHashVal(ht, entry, val);
6679 }
6680 existed = 1;
6681 }
6682 else {
6683
6684 Jim_SetHashKey(ht, entry, key);
6685 Jim_SetHashVal(ht, entry, val);
6686 existed = 0;
6687 }
6688
@@ -6701,11 +6781,11 @@
6701 he = ht->table[h];
6702
6703 prevHe = NULL;
6704 while (he) {
6705 if (Jim_CompareHashKeys(ht, key, he->key)) {
6706
6707 if (prevHe)
6708 prevHe->next = he->next;
6709 else
6710 ht->table[h] = he->next;
6711 Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6795,19 @@
6715 return JIM_OK;
6716 }
6717 prevHe = he;
6718 he = he->next;
6719 }
6720 return JIM_ERR;
6721 }
6722
6723
6724 int Jim_FreeHashTable(Jim_HashTable *ht)
6725 {
6726 unsigned int i;
6727
6728
6729 for (i = 0; ht->used > 0; i++) {
6730 Jim_HashEntry *he, *nextHe;
6731
6732 if ((he = ht->table[i]) == NULL)
6733 continue;
@@ -6738,15 +6818,15 @@
6738 Jim_Free(he);
6739 ht->used--;
6740 he = nextHe;
6741 }
6742 }
6743
6744 Jim_Free(ht->table);
6745
6746 JimResetHashTable(ht);
6747 return JIM_OK;
6748 }
6749
6750 Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
6751 {
6752 Jim_HashEntry *he;
@@ -6819,24 +6899,24 @@
6819 static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
6820 {
6821 unsigned int h;
6822 Jim_HashEntry *he;
6823
6824
6825 JimExpandHashTableIfNeeded(ht);
6826
6827
6828 h = Jim_HashKey(ht, key) & ht->sizemask;
6829
6830 he = ht->table[h];
6831 while (he) {
6832 if (Jim_CompareHashKeys(ht, key, he->key))
6833 return replace ? he : NULL;
6834 he = he->next;
6835 }
6836
6837
6838 he = Jim_Alloc(sizeof(*he));
6839 he->next = ht->table[h];
6840 ht->table[h] = he;
6841 ht->used++;
6842 he->key = NULL;
@@ -6865,16 +6945,16 @@
6865 {
6866 Jim_Free(key);
6867 }
6868
6869 static const Jim_HashTableType JimPackageHashTableType = {
6870 JimStringCopyHTHashFunction,
6871 JimStringCopyHTDup,
6872 NULL,
6873 JimStringCopyHTKeyCompare,
6874 JimStringCopyHTKeyDestructor,
6875 NULL
6876 };
6877
6878 typedef struct AssocDataValue
6879 {
6880 Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6969,16 @@
6889 assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
6890 Jim_Free(data);
6891 }
6892
6893 static const Jim_HashTableType JimAssocDataHashTableType = {
6894 JimStringCopyHTHashFunction,
6895 JimStringCopyHTDup,
6896 NULL,
6897 JimStringCopyHTKeyCompare,
6898 JimStringCopyHTKeyDestructor,
6899 JimAssocDataHashTableValueDestructor
6900 };
6901
6902 void Jim_InitStack(Jim_Stack *stack)
6903 {
6904 stack->len = 0;
@@ -6951,56 +7031,61 @@
6951 freeFunc(stack->vector[i]);
6952 }
6953
6954
6955
6956 #define JIM_TT_NONE 0
6957 #define JIM_TT_STR 1
6958 #define JIM_TT_ESC 2
6959 #define JIM_TT_VAR 3
6960 #define JIM_TT_DICTSUGAR 4
6961 #define JIM_TT_CMD 5
6962
6963 #define JIM_TT_SEP 6
6964 #define JIM_TT_EOL 7
6965 #define JIM_TT_EOF 8
6966
6967 #define JIM_TT_LINE 9
6968 #define JIM_TT_WORD 10
6969
6970
6971 #define JIM_TT_SUBEXPR_START 11
6972 #define JIM_TT_SUBEXPR_END 12
6973 #define JIM_TT_SUBEXPR_COMMA 13
6974 #define JIM_TT_EXPR_INT 14
6975 #define JIM_TT_EXPR_DOUBLE 15
 
6976
6977 #define JIM_TT_EXPRSUGAR 16
6978
6979
6980 #define JIM_TT_EXPR_OP 20
6981
6982 #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
6983
 
 
 
 
6984 struct JimParseMissing {
6985 int ch;
6986 int line;
6987 };
6988
6989 struct JimParserCtx
6990 {
6991 const char *p;
6992 int len;
6993 int linenr;
6994 const char *tstart;
6995 const char *tend;
6996 int tline;
6997 int tt;
6998 int eof;
6999 int inquote;
7000 int comment;
7001 struct JimParseMissing missing;
7002 };
7003
7004 static int JimParseScript(struct JimParserCtx *pc);
7005 static int JimParseSep(struct JimParserCtx *pc);
7006 static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7115,11 @@
7030 pc->missing.line = linenr;
7031 }
7032
7033 static int JimParseScript(struct JimParserCtx *pc)
7034 {
7035 while (1) {
7036 if (!pc->len) {
7037 pc->tstart = pc->p;
7038 pc->tend = pc->p - 1;
7039 pc->tline = pc->linenr;
7040 pc->tt = JIM_TT_EOL;
@@ -7066,11 +7151,11 @@
7066 pc->comment = 0;
7067 return JimParseCmd(pc);
7068 case '$':
7069 pc->comment = 0;
7070 if (JimParseVar(pc) == JIM_ERR) {
7071
7072 pc->tstart = pc->tend = pc->p++;
7073 pc->len--;
7074 pc->tt = JIM_TT_ESC;
7075 }
7076 return JIM_OK;
@@ -7127,11 +7212,11 @@
7127
7128 static void JimParseSubBrace(struct JimParserCtx *pc)
7129 {
7130 int level = 1;
7131
7132
7133 pc->p++;
7134 pc->len--;
7135 while (pc->len) {
7136 switch (*pc->p) {
7137 case '\\':
@@ -7171,11 +7256,11 @@
7171 static int JimParseSubQuote(struct JimParserCtx *pc)
7172 {
7173 int tt = JIM_TT_STR;
7174 int line = pc->tline;
7175
7176
7177 pc->p++;
7178 pc->len--;
7179 while (pc->len) {
7180 switch (*pc->p) {
7181 case '\\':
@@ -7220,11 +7305,11 @@
7220 {
7221 int level = 1;
7222 int startofword = 1;
7223 int line = pc->tline;
7224
7225
7226 pc->p++;
7227 pc->len--;
7228 while (pc->len) {
7229 switch (*pc->p) {
7230 case '\\':
@@ -7300,17 +7385,17 @@
7300 return JIM_OK;
7301 }
7302
7303 static int JimParseVar(struct JimParserCtx *pc)
7304 {
7305
7306 pc->p++;
7307 pc->len--;
7308
7309 #ifdef EXPRSUGAR_BRACKET
7310 if (*pc->p == '[') {
7311
7312 JimParseCmd(pc);
7313 pc->tt = JIM_TT_EXPRSUGAR;
7314 return JIM_OK;
7315 }
7316 #endif
@@ -7336,11 +7421,11 @@
7336 pc->len--;
7337 }
7338 }
7339 else {
7340 while (1) {
7341
7342 if (pc->p[0] == ':' && pc->p[1] == ':') {
7343 while (*pc->p == ':') {
7344 pc->p++;
7345 pc->len--;
7346 }
@@ -7351,11 +7436,11 @@
7351 pc->len--;
7352 continue;
7353 }
7354 break;
7355 }
7356
7357 if (*pc->p == '(') {
7358 int count = 1;
7359 const char *paren = NULL;
7360
7361 pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7463,11 @@
7378 if (count == 0) {
7379 pc->p++;
7380 pc->len--;
7381 }
7382 else if (paren) {
7383
7384 paren++;
7385 pc->len += (pc->p - paren);
7386 pc->p = paren;
7387 }
7388 #ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7488,19 @@
7403
7404 static int JimParseStr(struct JimParserCtx *pc)
7405 {
7406 if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
7407 pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7408
7409 if (*pc->p == '{') {
7410 return JimParseBrace(pc);
7411 }
7412 if (*pc->p == '"') {
7413 pc->inquote = 1;
7414 pc->p++;
7415 pc->len--;
7416
7417 pc->missing.line = pc->tline;
7418 }
7419 }
7420 pc->tstart = pc->p;
7421 pc->tline = pc->linenr;
@@ -7441,25 +7526,25 @@
7441 }
7442 pc->p++;
7443 pc->len--;
7444 }
7445 else if (pc->len == 1) {
7446
7447 pc->missing.ch = '\\';
7448 }
7449 break;
7450 case '(':
7451
7452 if (pc->len > 1 && pc->p[1] != '$') {
7453 break;
7454 }
7455
7456 case ')':
7457
7458 if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
7459 if (pc->p == pc->tstart) {
7460
7461 pc->p++;
7462 pc->len--;
7463 }
7464 pc->tend = pc->p - 1;
7465 pc->tt = JIM_TT_ESC;
@@ -7499,11 +7584,11 @@
7499 break;
7500 }
7501 pc->p++;
7502 pc->len--;
7503 }
7504 return JIM_OK;
7505 }
7506
7507 static int JimParseComment(struct JimParserCtx *pc)
7508 {
7509 while (*pc->p) {
@@ -7610,34 +7695,34 @@
7610 if (c == -1) {
7611 break;
7612 }
7613 val = (val << 4) | c;
7614 }
7615
7616 if (s[i] == '{') {
7617 if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7618
7619 i--;
7620 k = 0;
7621 }
7622 else {
7623
7624 k++;
7625 }
7626 }
7627 if (k) {
7628
7629 if (s[i] == 'x') {
7630 *p++ = val;
7631 }
7632 else {
7633 p += utf8_fromunicode(p, val);
7634 }
7635 i += k;
7636 break;
7637 }
7638
7639 *p++ = s[i];
7640 }
7641 break;
7642 case 'v':
7643 *p++ = 0xb;
@@ -7646,11 +7731,11 @@
7646 case '\0':
7647 *p++ = '\\';
7648 i++;
7649 break;
7650 case '\n':
7651
7652 *p++ = ' ';
7653 do {
7654 i++;
7655 } while (s[i + 1] == ' ' || s[i + 1] == '\t');
7656 break;
@@ -7660,11 +7745,11 @@
7660 case '3':
7661 case '4':
7662 case '5':
7663 case '6':
7664 case '7':
7665
7666 {
7667 int val = 0;
7668 int c = odigitval(s[i + 1]);
7669
7670 val = c;
@@ -7717,16 +7802,16 @@
7717 }
7718 else {
7719 len = (end - start) + 1;
7720 token = Jim_Alloc(len + 1);
7721 if (pc->tt != JIM_TT_ESC) {
7722
7723 memcpy(token, start, len);
7724 token[len] = '\0';
7725 }
7726 else {
7727
7728 len = JimEscape(token, start, len);
7729 }
7730 }
7731
7732 return Jim_NewStringObjNoAlloc(interp, token, len);
@@ -7790,11 +7875,11 @@
7790 while (pc->len) {
7791 switch (*pc->p) {
7792 case '\\':
7793 pc->tt = JIM_TT_ESC;
7794 if (--pc->len == 0) {
7795
7796 pc->tend = pc->p;
7797 return JIM_OK;
7798 }
7799 pc->p++;
7800 break;
@@ -7826,11 +7911,11 @@
7826 pc->tend = pc->p - 1;
7827 return JIM_OK;
7828 }
7829 if (*pc->p == '\\') {
7830 if (--pc->len == 0) {
7831
7832 pc->tend = pc->p;
7833 return JIM_OK;
7834 }
7835 pc->tt = JIM_TT_ESC;
7836 pc->p++;
@@ -7846,24 +7931,24 @@
7846
7847 Jim_Obj *Jim_NewObj(Jim_Interp *interp)
7848 {
7849 Jim_Obj *objPtr;
7850
7851
7852 if (interp->freeList != NULL) {
7853
7854 objPtr = interp->freeList;
7855 interp->freeList = objPtr->nextObjPtr;
7856 }
7857 else {
7858
7859 objPtr = Jim_Alloc(sizeof(*objPtr));
7860 }
7861
7862 objPtr->refCount = 0;
7863
7864
7865 objPtr->prevObjPtr = NULL;
7866 objPtr->nextObjPtr = interp->liveList;
7867 if (interp->liveList)
7868 interp->liveList->prevObjPtr = objPtr;
7869 interp->liveList = objPtr;
@@ -7871,32 +7956,32 @@
7871 return objPtr;
7872 }
7873
7874 void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
7875 {
7876
7877 JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
7878 objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
7879
7880
7881 Jim_FreeIntRep(interp, objPtr);
7882
7883 if (objPtr->bytes != NULL) {
7884 if (objPtr->bytes != JimEmptyStringRep)
7885 Jim_Free(objPtr->bytes);
7886 }
7887
7888 if (objPtr->prevObjPtr)
7889 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7890 if (objPtr->nextObjPtr)
7891 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7892 if (interp->liveList == objPtr)
7893 interp->liveList = objPtr->nextObjPtr;
7894 #ifdef JIM_DISABLE_OBJECT_POOL
7895 Jim_Free(objPtr);
7896 #else
7897
7898 objPtr->prevObjPtr = NULL;
7899 objPtr->nextObjPtr = interp->freeList;
7900 if (interp->freeList)
7901 interp->freeList->prevObjPtr = objPtr;
7902 interp->freeList = objPtr;
@@ -7919,45 +8004,45 @@
7919 {
7920 Jim_Obj *dupPtr;
7921
7922 dupPtr = Jim_NewObj(interp);
7923 if (objPtr->bytes == NULL) {
7924
7925 dupPtr->bytes = NULL;
7926 }
7927 else if (objPtr->length == 0) {
7928
7929 dupPtr->bytes = JimEmptyStringRep;
7930 dupPtr->length = 0;
7931 dupPtr->typePtr = NULL;
7932 return dupPtr;
7933 }
7934 else {
7935 dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
7936 dupPtr->length = objPtr->length;
7937
7938 memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
7939 }
7940
7941
7942 dupPtr->typePtr = objPtr->typePtr;
7943 if (objPtr->typePtr != NULL) {
7944 if (objPtr->typePtr->dupIntRepProc == NULL) {
7945 dupPtr->internalRep = objPtr->internalRep;
7946 }
7947 else {
7948
7949 objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
7950 }
7951 }
7952 return dupPtr;
7953 }
7954
7955 const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
7956 {
7957 if (objPtr->bytes == NULL) {
7958
7959 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7960 objPtr->typePtr->updateStringProc(objPtr);
7961 }
7962 if (lenPtr)
7963 *lenPtr = objPtr->length;
@@ -7966,11 +8051,11 @@
7966
7967
7968 int Jim_Length(Jim_Obj *objPtr)
7969 {
7970 if (objPtr->bytes == NULL) {
7971
7972 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7973 objPtr->typePtr->updateStringProc(objPtr);
7974 }
7975 return objPtr->length;
7976 }
@@ -7977,11 +8062,11 @@
7977
7978
7979 const char *Jim_String(Jim_Obj *objPtr)
7980 {
7981 if (objPtr->bytes == NULL) {
7982
7983 JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
7984 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7985 objPtr->typePtr->updateStringProc(objPtr);
7986 }
7987 return objPtr->bytes;
@@ -8037,22 +8122,22 @@
8037 }
8038
8039 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
8040 {
8041 if (objPtr->typePtr != &stringObjType) {
8042
8043 if (objPtr->bytes == NULL) {
8044
8045 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8046 objPtr->typePtr->updateStringProc(objPtr);
8047 }
8048
8049 Jim_FreeIntRep(interp, objPtr);
8050
8051 objPtr->typePtr = &stringObjType;
8052 objPtr->internalRep.strValue.maxLength = objPtr->length;
8053
8054 objPtr->internalRep.strValue.charLength = -1;
8055 }
8056 return JIM_OK;
8057 }
8058
@@ -8073,14 +8158,14 @@
8073
8074 Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
8075 {
8076 Jim_Obj *objPtr = Jim_NewObj(interp);
8077
8078
8079 if (len == -1)
8080 len = strlen(s);
8081
8082 if (len == 0) {
8083 objPtr->bytes = JimEmptyStringRep;
8084 }
8085 else {
8086 objPtr->bytes = Jim_Alloc(len + 1);
@@ -8087,25 +8172,25 @@
8087 memcpy(objPtr->bytes, s, len);
8088 objPtr->bytes[len] = '\0';
8089 }
8090 objPtr->length = len;
8091
8092
8093 objPtr->typePtr = NULL;
8094 return objPtr;
8095 }
8096
8097
8098 Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
8099 {
8100 #ifdef JIM_UTF8
8101
8102 int bytelen = utf8_index(s, charlen);
8103
8104 Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
8105
8106
8107 objPtr->typePtr = &stringObjType;
8108 objPtr->internalRep.strValue.maxLength = bytelen;
8109 objPtr->internalRep.strValue.charLength = charlen;
8110
8111 return objPtr;
@@ -8132,11 +8217,11 @@
8132 len = strlen(str);
8133 needlen = objPtr->length + len;
8134 if (objPtr->internalRep.strValue.maxLength < needlen ||
8135 objPtr->internalRep.strValue.maxLength == 0) {
8136 needlen *= 2;
8137
8138 if (needlen < 7) {
8139 needlen = 7;
8140 }
8141 if (objPtr->bytes == JimEmptyStringRep) {
8142 objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8233,11 @@
8148 }
8149 memcpy(objPtr->bytes + objPtr->length, str, len);
8150 objPtr->bytes[objPtr->length + len] = '\0';
8151
8152 if (objPtr->internalRep.strValue.charLength >= 0) {
8153
8154 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
8155 }
8156 objPtr->length += len;
8157 }
8158
@@ -8210,11 +8295,11 @@
8210 int l1, l2;
8211 const char *s1 = Jim_GetString(firstObjPtr, &l1);
8212 const char *s2 = Jim_GetString(secondObjPtr, &l2);
8213
8214 if (nocase) {
8215
8216 return JimStringCompareLen(s1, s2, -1, nocase);
8217 }
8218 return JimStringCompare(s1, l1, s2, l2);
8219 }
8220
@@ -8312,11 +8397,11 @@
8312
8313 if (first == 0 && rangeLen == len) {
8314 return strObjPtr;
8315 }
8316 if (len == bytelen) {
8317
8318 return Jim_NewStringObj(interp, str + first, rangeLen);
8319 }
8320 return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
8321 #else
8322 return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8426,19 @@
8341 return strObjPtr;
8342 }
8343
8344 str = Jim_String(strObjPtr);
8345
8346
8347 objPtr = Jim_NewStringObjUtf8(interp, str, first);
8348
8349
8350 if (newStrObj) {
8351 Jim_AppendObj(interp, objPtr, newStrObj);
8352 }
8353
8354
8355 Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
8356
8357 return objPtr;
8358 }
8359
@@ -8452,11 +8537,11 @@
8452 while (len) {
8453 int c;
8454 int n = utf8_tounicode(str, &c);
8455
8456 if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8457
8458 break;
8459 }
8460 str += n;
8461 len -= n;
8462 }
@@ -8523,41 +8608,41 @@
8523
8524 len = Jim_Length(strObjPtr);
8525 nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
8526
8527 if (nontrim == NULL) {
8528
8529 return Jim_NewEmptyStringObj(interp);
8530 }
8531 if (nontrim == strObjPtr->bytes + len) {
8532
8533 return strObjPtr;
8534 }
8535
8536 if (Jim_IsShared(strObjPtr)) {
8537 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
8538 }
8539 else {
8540
8541 strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
8542 strObjPtr->length = (nontrim - strObjPtr->bytes);
8543 }
8544
8545 return strObjPtr;
8546 }
8547
8548 static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
8549 {
8550
8551 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8552
8553
8554 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8555
8556
8557 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8558
8559 Jim_FreeNewObj(interp, objPtr);
8560 }
8561
8562 return strObjPtr;
8563 }
@@ -8575,17 +8660,17 @@
8575 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8576 {
8577 static const char * const strclassnames[] = {
8578 "integer", "alpha", "alnum", "ascii", "digit",
8579 "double", "lower", "upper", "space", "xdigit",
8580 "control", "print", "graph", "punct",
8581 NULL
8582 };
8583 enum {
8584 STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
8585 STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8586 STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT
8587 };
8588 int strclass;
8589 int len;
8590 int i;
8591 const char *str;
@@ -8613,10 +8698,17 @@
8613 {
8614 double d;
8615 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8616 return JIM_OK;
8617 }
 
 
 
 
 
 
 
8618
8619 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8620 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8621 case STR_IS_ASCII: isclassfunc = jim_isascii; break;
8622 case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8723,11 @@
8631 default:
8632 return JIM_ERR;
8633 }
8634
8635 for (i = 0; i < len; i++) {
8636 if (!isclassfunc(str[i])) {
8637 Jim_SetResultBool(interp, 0);
8638 return JIM_OK;
8639 }
8640 }
8641 Jim_SetResultBool(interp, 1);
@@ -8665,11 +8757,11 @@
8665
8666 if (objPtr->typePtr != &comparedStringObjType) {
8667 Jim_FreeIntRep(interp, objPtr);
8668 objPtr->typePtr = &comparedStringObjType;
8669 }
8670 objPtr->internalRep.ptr = (char *)str;
8671 return 1;
8672 }
8673 }
8674
8675 static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8850,20 @@
8758 int type;
8759 } ScriptToken;
8760
8761 typedef struct ScriptObj
8762 {
8763 ScriptToken *token;
8764 Jim_Obj *fileNameObj;
8765 int len;
8766 int substFlags;
8767 int inUse; /* Used to share a ScriptObj. Currently
8768 only used by Jim_EvalObj() as protection against
8769 shimmering of the currently evaluated object. */
8770 int firstline;
8771 int linenr;
8772 int missing;
8773 } ScriptObj;
8774
8775 static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8776 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8777 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8891,23 @@
8799 dupPtr->typePtr = NULL;
8800 }
8801
8802 typedef struct
8803 {
8804 const char *token;
8805 int len;
8806 int type;
8807 int line;
8808 } ParseToken;
8809
8810 typedef struct
8811 {
8812
8813 ParseToken *list;
8814 int size;
8815 int count;
8816 ParseToken static_list[20];
8817 } ParseTokenList;
8818
8819 static void ScriptTokenListInit(ParseTokenList *tokenlist)
8820 {
8821 tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8926,18 @@
8834 int line)
8835 {
8836 ParseToken *t;
8837
8838 if (tokenlist->count == tokenlist->size) {
8839
8840 tokenlist->size *= 2;
8841 if (tokenlist->list != tokenlist->static_list) {
8842 tokenlist->list =
8843 Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
8844 }
8845 else {
8846
8847 tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
8848 memcpy(tokenlist->list, tokenlist->static_list,
8849 tokenlist->count * sizeof(*tokenlist->list));
8850 }
8851 }
@@ -8859,20 +8951,20 @@
8859 static int JimCountWordTokens(ParseToken *t)
8860 {
8861 int expand = 1;
8862 int count = 0;
8863
8864
8865 if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
8866 if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8867
8868 expand = -1;
8869 t++;
8870 }
8871 }
8872
8873
8874 while (!TOKEN_IS_SEP(t->type)) {
8875 t++;
8876 count++;
8877 }
8878
@@ -8882,11 +8974,11 @@
8882 static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
8883 {
8884 Jim_Obj *objPtr;
8885
8886 if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8887
8888 int len = t->len;
8889 char *str = Jim_Alloc(len + 1);
8890 len = JimEscape(str, t->token, len);
8891 objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
8892 }
@@ -8899,13 +8991,13 @@
8899 static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8900 ParseTokenList *tokenlist)
8901 {
8902 int i;
8903 struct ScriptToken *token;
8904
8905 int lineargs = 0;
8906
8907 ScriptToken *linefirst;
8908 int count;
8909 int linenr;
8910
8911 #ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +9006,11 @@
8914 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
8915 tokenlist->list[i].len, tokenlist->list[i].token);
8916 }
8917 #endif
8918
8919
8920 count = tokenlist->count;
8921 for (i = 0; i < tokenlist->count; i++) {
8922 if (tokenlist->list[i].type == JIM_TT_EOL) {
8923 count++;
8924 }
@@ -8925,59 +9017,59 @@
8925 }
8926 linenr = script->firstline = tokenlist->list[0].line;
8927
8928 token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
8929
8930
8931 linefirst = token++;
8932
8933 for (i = 0; i < tokenlist->count; ) {
8934
8935 int wordtokens;
8936
8937
8938 while (tokenlist->list[i].type == JIM_TT_SEP) {
8939 i++;
8940 }
8941
8942 wordtokens = JimCountWordTokens(tokenlist->list + i);
8943
8944 if (wordtokens == 0) {
8945
8946 if (lineargs) {
8947 linefirst->type = JIM_TT_LINE;
8948 linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
8949 Jim_IncrRefCount(linefirst->objPtr);
8950
8951
8952 lineargs = 0;
8953 linefirst = token++;
8954 }
8955 i++;
8956 continue;
8957 }
8958 else if (wordtokens != 1) {
8959
8960 token->type = JIM_TT_WORD;
8961 token->objPtr = Jim_NewIntObj(interp, wordtokens);
8962 Jim_IncrRefCount(token->objPtr);
8963 token++;
8964 if (wordtokens < 0) {
8965
8966 i++;
8967 wordtokens = -wordtokens - 1;
8968 lineargs--;
8969 }
8970 }
8971
8972 if (lineargs == 0) {
8973
8974 linenr = tokenlist->list[i].line;
8975 }
8976 lineargs++;
8977
8978
8979 while (wordtokens--) {
8980 const ParseToken *t = &tokenlist->list[i++];
8981
8982 token->type = t->type;
8983 token->objPtr = JimMakeScriptObj(interp, t);
@@ -9049,11 +9141,11 @@
9049 token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
9050
9051 for (i = 0; i < tokenlist->count; i++) {
9052 const ParseToken *t = &tokenlist->list[i];
9053
9054
9055 token->type = t->type;
9056 token->objPtr = JimMakeScriptObj(interp, t);
9057 Jim_IncrRefCount(token->objPtr);
9058 token++;
9059 }
@@ -9068,29 +9160,29 @@
9068 struct JimParserCtx parser;
9069 struct ScriptObj *script;
9070 ParseTokenList tokenlist;
9071 int line = 1;
9072
9073
9074 if (objPtr->typePtr == &sourceObjType) {
9075 line = objPtr->internalRep.sourceValue.lineNumber;
9076 }
9077
9078
9079 ScriptTokenListInit(&tokenlist);
9080
9081 JimParserInit(&parser, scriptText, scriptTextLen, line);
9082 while (!parser.eof) {
9083 JimParseScript(&parser);
9084 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
9085 parser.tline);
9086 }
9087
9088
9089 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
9090
9091
9092 script = Jim_Alloc(sizeof(*script));
9093 memset(script, 0, sizeof(*script));
9094 script->inUse = 1;
9095 if (objPtr->typePtr == &sourceObjType) {
9096 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9194,14 @@
9102 script->missing = parser.missing.ch;
9103 script->linenr = parser.missing.line;
9104
9105 ScriptObjAddTokens(interp, script, &tokenlist);
9106
9107
9108 ScriptTokenListFree(&tokenlist);
9109
9110
9111 Jim_FreeIntRep(interp, objPtr);
9112 Jim_SetIntRepPtr(objPtr, script);
9113 objPtr->typePtr = &scriptObjType;
9114 }
9115
@@ -9116,11 +9208,11 @@
9116 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
9117
9118 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
9119 {
9120 if (objPtr == interp->emptyObj) {
9121
9122 objPtr = interp->nullScriptObj;
9123 }
9124
9125 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
9126 JimSetScriptFromAny(interp, objPtr);
@@ -9155,17 +9247,17 @@
9155 Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
9156 Jim_Free(cmdPtr->u.proc.staticVars);
9157 }
9158 }
9159 else {
9160
9161 if (cmdPtr->u.native.delProc) {
9162 cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
9163 }
9164 }
9165 if (cmdPtr->prevCmd) {
9166
9167 JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
9168 }
9169 Jim_Free(cmdPtr);
9170 }
9171 }
@@ -9176,46 +9268,46 @@
9176 Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
9177 Jim_Free(val);
9178 }
9179
9180 static const Jim_HashTableType JimVariablesHashTableType = {
9181 JimStringCopyHTHashFunction,
9182 JimStringCopyHTDup,
9183 NULL,
9184 JimStringCopyHTKeyCompare,
9185 JimStringCopyHTKeyDestructor,
9186 JimVariablesHTValDestructor
9187 };
9188
9189 static void JimCommandsHT_ValDestructor(void *interp, void *val)
9190 {
9191 JimDecrCmdRefCount(interp, val);
9192 }
9193
9194 static const Jim_HashTableType JimCommandsHashTableType = {
9195 JimStringCopyHTHashFunction,
9196 JimStringCopyHTDup,
9197 NULL,
9198 JimStringCopyHTKeyCompare,
9199 JimStringCopyHTKeyDestructor,
9200 JimCommandsHT_ValDestructor
9201 };
9202
9203
9204
9205 #ifdef jim_ext_namespace
9206 static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
9207 {
9208 const char *name = Jim_String(nsObj);
9209 if (name[0] == ':' && name[1] == ':') {
9210
9211 while (*++name == ':') {
9212 }
9213 nsObj = Jim_NewStringObj(interp, name, -1);
9214 }
9215 else if (Jim_Length(interp->framePtr->nsObj)) {
9216
9217 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9218 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
9219 }
9220 return nsObj;
9221 }
@@ -9239,16 +9331,16 @@
9239 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9240 {
9241 Jim_Obj *objPtr = interp->emptyObj;
9242
9243 if (name[0] == ':' && name[1] == ':') {
9244
9245 while (*++name == ':') {
9246 }
9247 }
9248 else if (Jim_Length(interp->framePtr->nsObj)) {
9249
9250 objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9251 Jim_AppendStrings(interp, objPtr, "::", name, NULL);
9252 name = Jim_String(objPtr);
9253 }
9254 Jim_IncrRefCount(objPtr);
@@ -9257,11 +9349,11 @@
9257 }
9258
9259 #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
9260
9261 #else
9262
9263 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9264 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9265
9266 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9267 {
@@ -9276,17 +9368,17 @@
9276
9277 Jim_InterpIncrProcEpoch(interp);
9278 }
9279
9280 if (he && interp->local) {
9281
9282 cmd->prevCmd = Jim_GetHashEntryVal(he);
9283 Jim_SetHashVal(&interp->commands, he, cmd);
9284 }
9285 else {
9286 if (he) {
9287
9288 Jim_DeleteHashEntry(&interp->commands, name);
9289 }
9290
9291 Jim_AddHashEntry(&interp->commands, name, cmd);
9292 }
@@ -9297,11 +9389,11 @@
9297 int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
9298 Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
9299 {
9300 Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
9301
9302
9303 memset(cmdPtr, 0, sizeof(*cmdPtr));
9304 cmdPtr->inUse = 1;
9305 cmdPtr->u.native.delProc = delProc;
9306 cmdPtr->u.native.cmdProc = cmdProc;
9307 cmdPtr->u.native.privData = privData;
@@ -9326,11 +9418,11 @@
9326 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9327 Jim_Var *varPtr;
9328 int subLen;
9329
9330 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9331
9332 subLen = Jim_ListLength(interp, objPtr);
9333 if (subLen == 1 || subLen == 2) {
9334 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9335 if (subLen == 1) {
9336 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9464,19 @@
9372
9373 static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
9374 {
9375 #ifdef jim_ext_namespace
9376 if (cmdPtr->isproc) {
9377
9378 const char *pt = strrchr(cmdname, ':');
9379 if (pt && pt != cmdname && pt[-1] == ':') {
9380 Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
9381 cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
9382 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9383
9384 if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9385
9386 Jim_InterpIncrProcEpoch(interp);
9387 }
9388 }
9389 }
9390 #endif
@@ -9397,11 +9489,11 @@
9397 int argListLen;
9398 int i;
9399
9400 argListLen = Jim_ListLength(interp, argListObjPtr);
9401
9402
9403 cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
9404 memset(cmdPtr, 0, sizeof(*cmdPtr));
9405 cmdPtr->inUse = 1;
9406 cmdPtr->isproc = 1;
9407 cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9504,24 @@
9412 cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
9413 Jim_IncrRefCount(argListObjPtr);
9414 Jim_IncrRefCount(bodyObjPtr);
9415 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9416
9417
9418 if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
9419 goto err;
9420 }
9421
9422
9423
9424 for (i = 0; i < argListLen; i++) {
9425 Jim_Obj *argPtr;
9426 Jim_Obj *nameObjPtr;
9427 Jim_Obj *defaultObjPtr;
9428 int len;
9429
9430
9431 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9432 len = Jim_ListLength(interp, argPtr);
9433 if (len == 0) {
9434 Jim_SetResultString(interp, "argument with no name", -1);
9435 err:
@@ -9440,16 +9532,16 @@
9440 Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
9441 goto err;
9442 }
9443
9444 if (len == 2) {
9445
9446 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9447 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9448 }
9449 else {
9450
9451 nameObjPtr = argPtr;
9452 defaultObjPtr = NULL;
9453 }
9454
9455
@@ -9510,29 +9602,29 @@
9510 }
9511
9512 fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
9513 fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
9514
9515
9516 he = Jim_FindHashEntry(&interp->commands, fqold);
9517 if (he == NULL) {
9518 Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
9519 }
9520 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9521 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9522 }
9523 else {
9524
9525 cmdPtr = Jim_GetHashEntryVal(he);
9526 JimIncrCmdRefCount(cmdPtr);
9527 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9528 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9529
9530
9531 Jim_DeleteHashEntry(&interp->commands, fqold);
9532
9533
9534 Jim_InterpIncrProcEpoch(interp);
9535
9536 ret = JIM_OK;
9537 }
9538
@@ -9571,23 +9663,23 @@
9571 objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
9572 #ifdef jim_ext_namespace
9573 || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
9574 #endif
9575 ) {
9576
9577
9578
 
9579 const char *name = Jim_String(objPtr);
9580 Jim_HashEntry *he;
9581
9582 if (name[0] == ':' && name[1] == ':') {
9583 while (*++name == ':') {
9584 }
9585 }
9586 #ifdef jim_ext_namespace
9587 else if (Jim_Length(interp->framePtr->nsObj)) {
9588
9589 Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9590 Jim_AppendStrings(interp, nameObj, "::", name, NULL);
9591 he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
9592 Jim_FreeNewObj(interp, nameObj);
9593 if (he) {
@@ -9594,11 +9686,11 @@
9594 goto found;
9595 }
9596 }
9597 #endif
9598
9599
9600 he = Jim_FindHashEntry(&interp->commands, name);
9601 if (he == NULL) {
9602 if (flags & JIM_ERRMSG) {
9603 Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
9604 }
@@ -9607,11 +9699,11 @@
9607 #ifdef jim_ext_namespace
9608 found:
9609 #endif
9610 cmd = Jim_GetHashEntryVal(he);
9611
9612
9613 Jim_FreeIntRep(interp, objPtr);
9614 objPtr->typePtr = &commandObjType;
9615 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
9616 objPtr->internalRep.cmdValue.cmdPtr = cmd;
9617 objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9718,11 @@
9626 return cmd;
9627 }
9628
9629
9630
9631 #define JIM_DICT_SUGAR 100
9632
9633 static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
9634
9635 static const Jim_ObjType variableObjType = {
9636 "variable",
@@ -9640,11 +9732,11 @@
9640 JIM_TYPE_REFERENCES,
9641 };
9642
9643 static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
9644 {
9645
9646 if (nameObjPtr->typePtr != &variableObjType) {
9647 int len;
9648 const char *str = Jim_GetString(nameObjPtr, &len);
9649 if (memchr(str, '\0', len)) {
9650 Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9752,18 @@
9660 Jim_CallFrame *framePtr;
9661 Jim_HashEntry *he;
9662 int global;
9663 int len;
9664
9665
9666 if (objPtr->typePtr == &variableObjType) {
9667 framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
9668 if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9669
9670 return JIM_OK;
9671 }
9672
9673 }
9674 else if (objPtr->typePtr == &dictSubstObjType) {
9675 return JIM_DICT_SUGAR;
9676 }
9677 else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9771,11 @@
9679 }
9680
9681
9682 varName = Jim_GetString(objPtr, &len);
9683
9684
9685 if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
9686 return JIM_DICT_SUGAR;
9687 }
9688
9689 if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9787,23 @@
9695 else {
9696 global = 0;
9697 framePtr = interp->framePtr;
9698 }
9699
9700
9701 he = Jim_FindHashEntry(&framePtr->vars, varName);
9702 if (he == NULL) {
9703 if (!global && framePtr->staticVars) {
9704
9705 he = Jim_FindHashEntry(framePtr->staticVars, varName);
9706 }
9707 if (he == NULL) {
9708 return JIM_ERR;
9709 }
9710 }
9711
9712
9713 Jim_FreeIntRep(interp, objPtr);
9714 objPtr->typePtr = &variableObjType;
9715 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9716 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9717 objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9818,11 @@
9726 {
9727 const char *name;
9728 Jim_CallFrame *framePtr;
9729 int global;
9730
9731
9732 Jim_Var *var = Jim_Alloc(sizeof(*var));
9733
9734 var->objPtr = valObjPtr;
9735 Jim_IncrRefCount(valObjPtr);
9736 var->linkFramePtr = NULL;
@@ -9745,14 +9837,14 @@
9745 else {
9746 framePtr = interp->framePtr;
9747 global = 0;
9748 }
9749
9750
9751 Jim_AddHashEntry(&framePtr->vars, name, var);
9752
9753
9754 Jim_FreeIntRep(interp, nameObjPtr);
9755 nameObjPtr->typePtr = &variableObjType;
9756 nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
9757 nameObjPtr->internalRep.varValue.varPtr = var;
9758 nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9874,11 @@
9782 if (var->linkFramePtr == NULL) {
9783 Jim_IncrRefCount(valObjPtr);
9784 Jim_DecrRefCount(interp, var->objPtr);
9785 var->objPtr = valObjPtr;
9786 }
9787 else {
9788 Jim_CallFrame *savedCallFrame;
9789
9790 savedCallFrame = interp->framePtr;
9791 interp->framePtr = var->linkFramePtr;
9792 err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9843,14 +9935,14 @@
9843 const char *varName;
9844 const char *targetName;
9845 Jim_CallFrame *framePtr;
9846 Jim_Var *varPtr;
9847
9848
9849 switch (SetVariableFromAny(interp, nameObjPtr)) {
9850 case JIM_DICT_SUGAR:
9851
9852 Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
9853 return JIM_ERR;
9854
9855 case JIM_OK:
9856 varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9950,23 @@
9858 if (varPtr->linkFramePtr == NULL) {
9859 Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
9860 return JIM_ERR;
9861 }
9862
9863
9864 varPtr->linkFramePtr = NULL;
9865 break;
9866 }
9867
9868
9869
9870 varName = Jim_String(nameObjPtr);
9871
9872 if (varName[0] == ':' && varName[1] == ':') {
9873 while (*++varName == ':') {
9874 }
9875
9876 framePtr = interp->topFramePtr;
9877 }
9878 else {
9879 framePtr = interp->framePtr;
9880 }
@@ -9894,15 +9986,15 @@
9894 nameObjPtr);
9895 Jim_DecrRefCount(interp, targetNameObjPtr);
9896 return JIM_ERR;
9897 }
9898
9899
9900 if (framePtr == targetCallFrame) {
9901 Jim_Obj *objPtr = targetNameObjPtr;
9902
9903
9904 while (1) {
9905 if (strcmp(Jim_String(objPtr), varName) == 0) {
9906 Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
9907 Jim_DecrRefCount(interp, targetNameObjPtr);
9908 return JIM_ERR;
@@ -9914,13 +10006,13 @@
9914 break;
9915 objPtr = varPtr->objPtr;
9916 }
9917 }
9918
9919
9920 Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
9921
9922 nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
9923 Jim_DecrRefCount(interp, targetNameObjPtr);
9924 return JIM_OK;
9925 }
9926
@@ -9934,26 +10026,26 @@
9934 return varPtr->objPtr;
9935 }
9936 else {
9937 Jim_Obj *objPtr;
9938
9939
9940 Jim_CallFrame *savedCallFrame = interp->framePtr;
9941
9942 interp->framePtr = varPtr->linkFramePtr;
9943 objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
9944 interp->framePtr = savedCallFrame;
9945 if (objPtr) {
9946 return objPtr;
9947 }
9948
9949 }
9950 }
9951 break;
9952
9953 case JIM_DICT_SUGAR:
9954
9955 return JimDictSugarGet(interp, nameObjPtr, flags);
9956 }
9957 if (flags & JIM_ERRMSG) {
9958 Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
9959 }
@@ -10003,17 +10095,17 @@
10003 int retval;
10004 Jim_CallFrame *framePtr;
10005
10006 retval = SetVariableFromAny(interp, nameObjPtr);
10007 if (retval == JIM_DICT_SUGAR) {
10008
10009 return JimDictSugarSet(interp, nameObjPtr, NULL);
10010 }
10011 else if (retval == JIM_OK) {
10012 varPtr = nameObjPtr->internalRep.varValue.varPtr;
10013
10014
10015 if (varPtr->linkFramePtr) {
10016 framePtr = interp->framePtr;
10017 interp->framePtr = varPtr->linkFramePtr;
10018 retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
10019 interp->framePtr = framePtr;
@@ -10028,11 +10120,11 @@
10028 framePtr = interp->framePtr;
10029 }
10030
10031 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
10032 if (retval == JIM_OK) {
10033
10034 framePtr->id = interp->callFrameEpoch++;
10035 }
10036 }
10037 }
10038 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10153,11 @@
10061 keyLen = (str + len) - p;
10062 if (str[len - 1] == ')') {
10063 keyLen--;
10064 }
10065
10066
10067 keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
10068
10069 Jim_IncrRefCount(varObjPtr);
10070 Jim_IncrRefCount(keyObjPtr);
10071 *varPtrPtr = varObjPtr;
@@ -10080,23 +10172,23 @@
10080
10081 err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
10082 &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
10083
10084 if (err == JIM_OK) {
10085
10086 Jim_SetEmptyResult(interp);
10087 }
10088 else {
10089 if (!valObjPtr) {
10090
10091 if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
10092 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
10093 objPtr);
10094 return err;
10095 }
10096 }
10097
10098 Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
10099 (valObjPtr ? "set" : "unset"), objPtr);
10100 }
10101 return err;
10102 }
@@ -10118,11 +10210,11 @@
10118 Jim_SetResultFormatted(interp,
10119 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
10120 ret < 0 ? "variable isn't" : "no such element in");
10121 }
10122 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10123
10124 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
10125 }
10126
10127 return resObjPtr;
10128 }
@@ -10160,11 +10252,11 @@
10160 {
10161 if (objPtr->typePtr != &dictSubstObjType) {
10162 Jim_Obj *varObjPtr, *keyObjPtr;
10163
10164 if (objPtr->typePtr == &interpolatedObjType) {
10165
10166
10167 varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
10168 keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
10169
10170 Jim_IncrRefCount(varObjPtr);
@@ -10205,11 +10297,11 @@
10205 static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
10206 {
10207 Jim_Obj *resultObjPtr;
10208
10209 if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
10210
10211 resultObjPtr->refCount--;
10212 return resultObjPtr;
10213 }
10214 return NULL;
10215 }
@@ -10249,11 +10341,11 @@
10249 return cf;
10250 }
10251
10252 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10253 {
10254
10255 if (localCommands) {
10256 Jim_Obj *cmdNameObj;
10257
10258 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10259 Jim_HashEntry *he;
@@ -10268,20 +10360,20 @@
10268 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10269 if (cmd->prevCmd) {
10270 Jim_Cmd *prevCmd = cmd->prevCmd;
10271 cmd->prevCmd = NULL;
10272
10273
10274 JimDecrCmdRefCount(interp, cmd);
10275
10276
10277 Jim_SetHashVal(ht, he, prevCmd);
10278 }
10279 else {
10280 Jim_DeleteHashEntry(ht, fqname);
10281 Jim_InterpIncrProcEpoch(interp);
10282 }
 
10283 }
10284 Jim_DecrRefCount(interp, cmdNameObj);
10285 JimFreeQualifiedName(interp, fqObjName);
10286 }
10287 Jim_FreeStack(localCommands);
@@ -10289,12 +10381,12 @@
10289 }
10290 return JIM_OK;
10291 }
10292
10293
10294 #define JIM_FCF_FULL 0
10295 #define JIM_FCF_REUSE 1
10296 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10297 {
10298 JimDeleteLocalProcs(interp, cf->localCommands);
10299
10300 if (cf->procArgsObjPtr)
@@ -10327,263 +10419,10 @@
10327 cf->next = interp->freeFramesList;
10328 interp->freeFramesList = cf;
10329 }
10330
10331
10332 #ifdef JIM_REFERENCES
10333
10334 static void JimReferencesHTValDestructor(void *interp, void *val)
10335 {
10336 Jim_Reference *refPtr = (void *)val;
10337
10338 Jim_DecrRefCount(interp, refPtr->objPtr);
10339 if (refPtr->finalizerCmdNamePtr != NULL) {
10340 Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10341 }
10342 Jim_Free(val);
10343 }
10344
10345 static unsigned int JimReferencesHTHashFunction(const void *key)
10346 {
10347
10348 const unsigned long *widePtr = key;
10349 unsigned int intValue = (unsigned int)*widePtr;
10350
10351 return Jim_IntHashFunction(intValue);
10352 }
10353
10354 static void *JimReferencesHTKeyDup(void *privdata, const void *key)
10355 {
10356 void *copy = Jim_Alloc(sizeof(unsigned long));
10357
10358 JIM_NOTUSED(privdata);
10359
10360 memcpy(copy, key, sizeof(unsigned long));
10361 return copy;
10362 }
10363
10364 static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2)
10365 {
10366 JIM_NOTUSED(privdata);
10367
10368 return memcmp(key1, key2, sizeof(unsigned long)) == 0;
10369 }
10370
10371 static void JimReferencesHTKeyDestructor(void *privdata, void *key)
10372 {
10373 JIM_NOTUSED(privdata);
10374
10375 Jim_Free(key);
10376 }
10377
10378 static const Jim_HashTableType JimReferencesHashTableType = {
10379 JimReferencesHTHashFunction,
10380 JimReferencesHTKeyDup,
10381 NULL,
10382 JimReferencesHTKeyCompare,
10383 JimReferencesHTKeyDestructor,
10384 JimReferencesHTValDestructor
10385 };
10386
10387
10388
10389 #define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
10390
10391 static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
10392 {
10393 const char *fmt = "<reference.<%s>.%020lu>";
10394
10395 sprintf(buf, fmt, refPtr->tag, id);
10396 return JIM_REFERENCE_SPACE;
10397 }
10398
10399 static void UpdateStringOfReference(struct Jim_Obj *objPtr);
10400
10401 static const Jim_ObjType referenceObjType = {
10402 "reference",
10403 NULL,
10404 NULL,
10405 UpdateStringOfReference,
10406 JIM_TYPE_REFERENCES,
10407 };
10408
10409 static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10410 {
10411 char buf[JIM_REFERENCE_SPACE + 1];
10412
10413 JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10414 JimSetStringBytes(objPtr, buf);
10415 }
10416
10417 static int isrefchar(int c)
10418 {
10419 return (c == '_' || isalnum(c));
10420 }
10421
10422 static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10423 {
10424 unsigned long value;
10425 int i, len;
10426 const char *str, *start, *end;
10427 char refId[21];
10428 Jim_Reference *refPtr;
10429 Jim_HashEntry *he;
10430 char *endptr;
10431
10432
10433 str = Jim_GetString(objPtr, &len);
10434
10435 if (len < JIM_REFERENCE_SPACE)
10436 goto badformat;
10437
10438 start = str;
10439 end = str + len - 1;
10440 while (*start == ' ')
10441 start++;
10442 while (*end == ' ' && end > start)
10443 end--;
10444 if (end - start + 1 != JIM_REFERENCE_SPACE)
10445 goto badformat;
10446
10447 if (memcmp(start, "<reference.<", 12) != 0)
10448 goto badformat;
10449 if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
10450 goto badformat;
10451
10452 for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10453 if (!isrefchar(start[12 + i]))
10454 goto badformat;
10455 }
10456
10457 memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
10458 refId[20] = '\0';
10459
10460 value = strtoul(refId, &endptr, 10);
10461 if (JimCheckConversion(refId, endptr) != JIM_OK)
10462 goto badformat;
10463
10464 he = Jim_FindHashEntry(&interp->references, &value);
10465 if (he == NULL) {
10466 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10467 return JIM_ERR;
10468 }
10469 refPtr = Jim_GetHashEntryVal(he);
10470
10471 Jim_FreeIntRep(interp, objPtr);
10472 objPtr->typePtr = &referenceObjType;
10473 objPtr->internalRep.refValue.id = value;
10474 objPtr->internalRep.refValue.refPtr = refPtr;
10475 return JIM_OK;
10476
10477 badformat:
10478 Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr);
10479 return JIM_ERR;
10480 }
10481
10482 Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
10483 {
10484 struct Jim_Reference *refPtr;
10485 unsigned long id;
10486 Jim_Obj *refObjPtr;
10487 const char *tag;
10488 int tagLen, i;
10489
10490
10491 Jim_CollectIfNeeded(interp);
10492
10493 refPtr = Jim_Alloc(sizeof(*refPtr));
10494 refPtr->objPtr = objPtr;
10495 Jim_IncrRefCount(objPtr);
10496 refPtr->finalizerCmdNamePtr = cmdNamePtr;
10497 if (cmdNamePtr)
10498 Jim_IncrRefCount(cmdNamePtr);
10499 id = interp->referenceNextId++;
10500 Jim_AddHashEntry(&interp->references, &id, refPtr);
10501 refObjPtr = Jim_NewObj(interp);
10502 refObjPtr->typePtr = &referenceObjType;
10503 refObjPtr->bytes = NULL;
10504 refObjPtr->internalRep.refValue.id = id;
10505 refObjPtr->internalRep.refValue.refPtr = refPtr;
10506 interp->referenceNextId++;
10507 tag = Jim_GetString(tagPtr, &tagLen);
10508 if (tagLen > JIM_REFERENCE_TAGLEN)
10509 tagLen = JIM_REFERENCE_TAGLEN;
10510 for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
10511 if (i < tagLen && isrefchar(tag[i]))
10512 refPtr->tag[i] = tag[i];
10513 else
10514 refPtr->tag[i] = '_';
10515 }
10516 refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0';
10517 return refObjPtr;
10518 }
10519
10520 Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr)
10521 {
10522 if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR)
10523 return NULL;
10524 return objPtr->internalRep.refValue.refPtr;
10525 }
10526
10527 int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr)
10528 {
10529 Jim_Reference *refPtr;
10530
10531 if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10532 return JIM_ERR;
10533 Jim_IncrRefCount(cmdNamePtr);
10534 if (refPtr->finalizerCmdNamePtr)
10535 Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
10536 refPtr->finalizerCmdNamePtr = cmdNamePtr;
10537 return JIM_OK;
10538 }
10539
10540 int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr)
10541 {
10542 Jim_Reference *refPtr;
10543
10544 if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
10545 return JIM_ERR;
10546 *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr;
10547 return JIM_OK;
10548 }
10549
10550
10551
10552 static const Jim_HashTableType JimRefMarkHashTableType = {
10553 JimReferencesHTHashFunction,
10554 JimReferencesHTKeyDup,
10555 NULL,
10556 JimReferencesHTKeyCompare,
10557 JimReferencesHTKeyDestructor,
10558 NULL
10559 };
10560
10561
10562 int Jim_Collect(Jim_Interp *interp)
10563 {
10564 int collected = 0;
10565 return collected;
10566 }
10567
10568 #define JIM_COLLECT_ID_PERIOD 5000
10569 #define JIM_COLLECT_TIME_PERIOD 300
10570
10571 void Jim_CollectIfNeeded(Jim_Interp *interp)
10572 {
10573 unsigned long elapsedId;
10574 int elapsedTime;
10575
10576 elapsedId = interp->referenceNextId - interp->lastCollectId;
10577 elapsedTime = time(NULL) - interp->lastCollectTime;
10578
10579
10580 if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
10581 Jim_Collect(interp);
10582 }
10583 }
10584 #endif
10585
10586 int Jim_IsBigEndian(void)
10587 {
10588 union {
10589 unsigned short s;
@@ -10630,11 +10469,11 @@
10630 Jim_IncrRefCount(i->nullScriptObj);
10631 Jim_IncrRefCount(i->errorProc);
10632 Jim_IncrRefCount(i->trueObj);
10633 Jim_IncrRefCount(i->falseObj);
10634
10635
10636 Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
10637 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10638
10639 Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
10640 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,11 +10491,11 @@
10652 {
10653 Jim_CallFrame *cf, *cfx;
10654
10655 Jim_Obj *objPtr, *nextObjPtr;
10656
10657
10658 for (cf = i->framePtr; cf; cf = cfx) {
10659 cfx = cf->parent;
10660 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10661 }
10662
@@ -10705,27 +10544,27 @@
10705 printf("-------------------------------------\n\n");
10706 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10707 }
10708 #endif
10709
10710
10711 objPtr = i->freeList;
10712 while (objPtr) {
10713 nextObjPtr = objPtr->nextObjPtr;
10714 Jim_Free(objPtr);
10715 objPtr = nextObjPtr;
10716 }
10717
10718
10719 for (cf = i->freeFramesList; cf; cf = cfx) {
10720 cfx = cf->next;
10721 if (cf->vars.table)
10722 Jim_FreeHashTable(&cf->vars);
10723 Jim_Free(cf);
10724 }
10725
10726
10727 Jim_Free(i);
10728 }
10729
10730 Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
10731 {
@@ -10746,25 +10585,25 @@
10746 else {
10747 if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
10748 level = -1;
10749 }
10750 else {
10751
10752 level = interp->framePtr->level - level;
10753 }
10754 }
10755 }
10756 else {
10757 str = "1";
10758 level = interp->framePtr->level - 1;
10759 }
10760
10761 if (level == 0) {
10762 return interp->topFramePtr;
10763 }
10764 if (level > 0) {
10765
10766 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10767 if (framePtr->level == level) {
10768 return framePtr;
10769 }
10770 }
@@ -10779,19 +10618,19 @@
10779 long level;
10780 Jim_CallFrame *framePtr;
10781
10782 if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
10783 if (level <= 0) {
10784
10785 level = interp->framePtr->level + level;
10786 }
10787
10788 if (level == 0) {
10789 return interp->topFramePtr;
10790 }
10791
10792
10793 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10794 if (framePtr->level == level) {
10795 return framePtr;
10796 }
10797 }
@@ -10810,11 +10649,11 @@
10810
10811 static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
10812 {
10813 int len;
10814
10815
10816 Jim_IncrRefCount(stackTraceObj);
10817 Jim_DecrRefCount(interp, interp->stackTrace);
10818 interp->stackTrace = stackTraceObj;
10819 interp->errorFlag = 1;
10820
@@ -10831,32 +10670,32 @@
10831 {
10832 if (strcmp(procname, "unknown") == 0) {
10833 procname = "";
10834 }
10835 if (!*procname && !Jim_Length(fileNameObj)) {
10836
10837 return;
10838 }
10839
10840 if (Jim_IsShared(interp->stackTrace)) {
10841 Jim_DecrRefCount(interp, interp->stackTrace);
10842 interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
10843 Jim_IncrRefCount(interp->stackTrace);
10844 }
10845
10846
10847 if (!*procname && Jim_Length(fileNameObj)) {
10848
10849 int len = Jim_ListLength(interp, interp->stackTrace);
10850
10851 if (len >= 3) {
10852 Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10853 if (Jim_Length(objPtr)) {
10854
10855 objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10856 if (Jim_Length(objPtr) == 0) {
10857
10858 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10859 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10860 return;
10861 }
10862 }
@@ -10958,18 +10797,18 @@
10958 {
10959 jim_wide wideValue;
10960 const char *str;
10961
10962 if (objPtr->typePtr == &coercedDoubleObjType) {
10963
10964 objPtr->typePtr = &intObjType;
10965 return JIM_OK;
10966 }
10967
10968
10969 str = Jim_String(objPtr);
10970
10971 if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
10972 if (flags & JIM_ERRMSG) {
10973 Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
10974 }
10975 return JIM_ERR;
@@ -10976,11 +10815,11 @@
10976 }
10977 if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
10978 Jim_SetResultString(interp, "Integer value too big to be represented", -1);
10979 return JIM_ERR;
10980 }
10981
10982 Jim_FreeIntRep(interp, objPtr);
10983 objPtr->typePtr = &intObjType;
10984 objPtr->internalRep.wideValue = wideValue;
10985 return JIM_OK;
10986 }
@@ -11075,17 +10914,17 @@
11075 {
11076 char buf[JIM_DOUBLE_SPACE + 1];
11077 int i;
11078 int len = sprintf(buf, "%.12g", value);
11079
11080
11081 for (i = 0; i < len; i++) {
11082 if (buf[i] == '.' || buf[i] == 'e') {
11083 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
11084 char *e = strchr(buf, 'e');
11085 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
11086
11087 e += 2;
11088 memmove(e, e + 1, len - (e - buf));
11089 }
11090 #endif
11091 break;
@@ -11107,38 +10946,38 @@
11107 const char *str;
11108
11109 str = Jim_String(objPtr);
11110
11111 #ifdef HAVE_LONG_LONG
11112
11113 #define MIN_INT_IN_DOUBLE -(1LL << 53)
11114 #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
11115
11116 if (objPtr->typePtr == &intObjType
11117 && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
11118 && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
11119
11120
11121 objPtr->typePtr = &coercedDoubleObjType;
11122 return JIM_OK;
11123 }
11124 else
11125 #endif
11126 if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
11127
11128 Jim_FreeIntRep(interp, objPtr);
11129 objPtr->typePtr = &coercedDoubleObjType;
11130 objPtr->internalRep.wideValue = wideValue;
11131 return JIM_OK;
11132 }
11133 else {
11134
11135 if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
11136 Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
11137 return JIM_ERR;
11138 }
11139
11140 Jim_FreeIntRep(interp, objPtr);
11141 }
11142 objPtr->typePtr = &doubleObjType;
11143 objPtr->internalRep.doubleValue = doubleValue;
11144 return JIM_OK;
@@ -11170,10 +11009,50 @@
11170 objPtr->typePtr = &doubleObjType;
11171 objPtr->bytes = NULL;
11172 objPtr->internalRep.doubleValue = doubleValue;
11173 return objPtr;
11174 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11175
11176 static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
11177 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
11178 static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
11179 static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11100,11 @@
11221 #define JIM_ELESTR_QUOTE 2
11222 static unsigned char ListElementQuotingType(const char *s, int len)
11223 {
11224 int i, level, blevel, trySimple = 1;
11225
11226
11227 if (len == 0)
11228 return JIM_ELESTR_BRACE;
11229 if (s[0] == '"' || s[0] == '{') {
11230 trySimple = 0;
11231 goto testbrace;
@@ -11243,20 +11122,20 @@
11243 case '\n':
11244 case '\t':
11245 case '\f':
11246 case '\v':
11247 trySimple = 0;
11248
11249 case '{':
11250 case '}':
11251 goto testbrace;
11252 }
11253 }
11254 return JIM_ELESTR_SIMPLE;
11255
11256 testbrace:
11257
11258 if (s[len - 1] == '\\')
11259 return JIM_ELESTR_QUOTE;
11260 level = 0;
11261 blevel = 0;
11262 for (i = 0; i < len; i++) {
@@ -11372,11 +11251,11 @@
11372 int i, bufLen, realLength;
11373 const char *strRep;
11374 char *p;
11375 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
11376
11377
11378 if (objc > STATIC_QUOTING_LEN) {
11379 quotingType = Jim_Alloc(objc);
11380 }
11381 else {
11382 quotingType = staticQuoting;
@@ -11391,25 +11270,25 @@
11391 case JIM_ELESTR_SIMPLE:
11392 if (i != 0 || strRep[0] != '#') {
11393 bufLen += len;
11394 break;
11395 }
11396
11397 quotingType[i] = JIM_ELESTR_BRACE;
11398
11399 case JIM_ELESTR_BRACE:
11400 bufLen += len + 2;
11401 break;
11402 case JIM_ELESTR_QUOTE:
11403 bufLen += len * 2;
11404 break;
11405 }
11406 bufLen++;
11407 }
11408 bufLen++;
11409
11410
11411 p = objPtr->bytes = Jim_Alloc(bufLen + 1);
11412 realLength = 0;
11413 for (i = 0; i < objc; i++) {
11414 int len, qlen;
11415
@@ -11436,17 +11315,17 @@
11436 qlen = BackslashQuoteString(strRep, len, p);
11437 p += qlen;
11438 realLength += qlen;
11439 break;
11440 }
11441
11442 if (i + 1 != objc) {
11443 *p++ = ' ';
11444 realLength++;
11445 }
11446 }
11447 *p = '\0';
11448 objPtr->length = realLength;
11449
11450 if (quotingType != staticQuoting) {
11451 Jim_Free(quotingType);
11452 }
@@ -11477,21 +11356,21 @@
11477 listObjPtrPtr = JimDictPairs(objPtr, &len);
11478 for (i = 0; i < len; i++) {
11479 Jim_IncrRefCount(listObjPtrPtr[i]);
11480 }
11481
11482
11483 Jim_FreeIntRep(interp, objPtr);
11484 objPtr->typePtr = &listObjType;
11485 objPtr->internalRep.listValue.len = len;
11486 objPtr->internalRep.listValue.maxLen = len;
11487 objPtr->internalRep.listValue.ele = listObjPtrPtr;
11488
11489 return JIM_OK;
11490 }
11491
11492
11493 if (objPtr->typePtr == &sourceObjType) {
11494 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
11495 linenr = objPtr->internalRep.sourceValue.lineNumber;
11496 }
11497 else {
@@ -11498,20 +11377,20 @@
11498 fileNameObj = interp->emptyObj;
11499 linenr = 1;
11500 }
11501 Jim_IncrRefCount(fileNameObj);
11502
11503
11504 str = Jim_GetString(objPtr, &strLen);
11505
11506 Jim_FreeIntRep(interp, objPtr);
11507 objPtr->typePtr = &listObjType;
11508 objPtr->internalRep.listValue.len = 0;
11509 objPtr->internalRep.listValue.maxLen = 0;
11510 objPtr->internalRep.listValue.ele = NULL;
11511
11512
11513 if (strLen) {
11514 JimParserInit(&parser, str, strLen, linenr);
11515 while (!parser.eof) {
11516 Jim_Obj *elementPtr;
11517
@@ -11641,11 +11520,11 @@
11641 Jim_Obj *compare_script;
11642 int rc;
11643
11644 jim_wide ret = 0;
11645
11646
11647 compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
11648 Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
11649 Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
11650
11651 rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11542,23 @@
11663 int dst = 0;
11664 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11665
11666 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11667 if (comp(&ele[dst], &ele[src]) == 0) {
11668
11669 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11670 }
11671 else {
11672
11673 dst++;
11674 }
11675 ele[dst] = ele[src];
11676 }
11677
11678 ele[++dst] = ele[src];
11679
11680
11681 listObjPtr->internalRep.listValue.len = dst;
11682 }
11683
11684
11685 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11572,11 @@
11693 int rc;
11694
11695 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11696 SetListFromAny(interp, listObjPtr);
11697
11698
11699 prev_info = sort_info;
11700 sort_info = info;
11701
11702 vector = listObjPtr->internalRep.listValue.ele;
11703 len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11595,17 @@
11716 break;
11717 case JIM_LSORT_COMMAND:
11718 fn = ListSortCommand;
11719 break;
11720 default:
11721 fn = NULL;
11722 JimPanic((1, "ListSort called with invalid sort type"));
11723 return -1;
11724 }
11725
11726 if (info->indexed) {
11727
11728 info->subfn = fn;
11729 fn = ListSortIndexHelper;
11730 }
11731
11732 if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11629,11 @@
11750 int i;
11751 Jim_Obj **point;
11752
11753 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11754 if (requiredLen < 2) {
11755
11756 requiredLen = 4;
11757 }
11758 else {
11759 requiredLen *= 2;
11760 }
@@ -11936,34 +11815,34 @@
11936 for (i = 0; i < objc; i++)
11937 ListAppendList(objPtr, objv[i]);
11938 return objPtr;
11939 }
11940 else {
11941
11942 int len = 0, objLen;
11943 char *bytes, *p;
11944
11945
11946 for (i = 0; i < objc; i++) {
11947 len += Jim_Length(objv[i]);
11948 }
11949 if (objc)
11950 len += objc - 1;
11951
11952 p = bytes = Jim_Alloc(len + 1);
11953 for (i = 0; i < objc; i++) {
11954 const char *s = Jim_GetString(objv[i], &objLen);
11955
11956
11957 while (objLen && isspace(UCHAR(*s))) {
11958 s++;
11959 objLen--;
11960 len--;
11961 }
11962
11963 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11964
11965 if (objLen > 1 && s[objLen - 2] == '\\') {
11966 break;
11967 }
11968 objLen--;
11969 len--;
@@ -11990,11 +11869,11 @@
11990 int len, rangeLen;
11991
11992 if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
11993 Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
11994 return NULL;
11995 len = Jim_ListLength(interp, listObjPtr);
11996 first = JimRelToAbsIndex(len, first);
11997 last = JimRelToAbsIndex(len, last);
11998 JimRelToAbsRange(len, &first, &last, &rangeLen);
11999 if (first == 0 && last == len) {
12000 return listObjPtr;
@@ -12030,16 +11909,16 @@
12030 {
12031 Jim_DecrRefCount(interp, (Jim_Obj *)val);
12032 }
12033
12034 static const Jim_HashTableType JimDictHashTableType = {
12035 JimObjectHTHashFunction,
12036 JimObjectHTKeyValDup,
12037 JimObjectHTKeyValDup,
12038 JimObjectHTKeyCompare,
12039 JimObjectHTKeyValDestructor,
12040 JimObjectHTKeyValDestructor
12041 };
12042
12043 static const Jim_ObjType dictObjType = {
12044 "dict",
12045 FreeDictInternalRep,
@@ -12060,17 +11939,17 @@
12060 {
12061 Jim_HashTable *ht, *dupHt;
12062 Jim_HashTableIterator htiter;
12063 Jim_HashEntry *he;
12064
12065
12066 ht = srcPtr->internalRep.ptr;
12067 dupHt = Jim_Alloc(sizeof(*dupHt));
12068 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
12069 if (ht->size != 0)
12070 Jim_ExpandHashTable(dupHt, ht->size);
12071
12072 JimInitHashTableIterator(ht, &htiter);
12073 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
12074 Jim_AddHashEntry(dupHt, he->key, he->u.val);
12075 }
12076
@@ -12086,11 +11965,11 @@
12086 Jim_Obj **objv;
12087 int i;
12088
12089 ht = dictPtr->internalRep.ptr;
12090
12091
12092 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
12093 JimInitHashTableIterator(ht, &htiter);
12094 i = 0;
12095 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
12096 objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11979,15 @@
12100 return objv;
12101 }
12102
12103 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
12104 {
12105
12106 int len;
12107 Jim_Obj **objv = JimDictPairs(objPtr, &len);
12108
12109
12110 JimMakeListStringRep(objPtr, objv, len);
12111
12112 Jim_Free(objv);
12113 }
12114
@@ -12122,18 +12001,18 @@
12122
12123 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
12124 Jim_String(objPtr);
12125 }
12126
12127
12128 listlen = Jim_ListLength(interp, objPtr);
12129 if (listlen % 2) {
12130 Jim_SetResultString(interp, "missing value to go with key", -1);
12131 return JIM_ERR;
12132 }
12133 else {
12134
12135 Jim_HashTable *ht;
12136 int i;
12137
12138 ht = Jim_Alloc(sizeof(*ht));
12139 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12037,11 @@
12158 static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
12159 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
12160 {
12161 Jim_HashTable *ht = objPtr->internalRep.ptr;
12162
12163 if (valueObjPtr == NULL) {
12164 return Jim_DeleteHashEntry(ht, keyObjPtr);
12165 }
12166 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
12167 return JIM_OK;
12168 }
@@ -12209,12 +12088,14 @@
12209 if (flags & JIM_ERRMSG) {
12210 Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
12211 }
12212 return JIM_ERR;
12213 }
12214 *objPtrPtr = he->u.val;
12215 return JIM_OK;
 
 
12216 }
12217
12218
12219 int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
12220 {
@@ -12258,11 +12139,11 @@
12258 int shared, i;
12259
12260 varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
12261 if (objPtr == NULL) {
12262 if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12263
12264 return JIM_ERR;
12265 }
12266 varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
12267 if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
12268 Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12153,26 @@
12272 if ((shared = Jim_IsShared(objPtr)))
12273 varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
12274 for (i = 0; i < keyc; i++) {
12275 dictObjPtr = objPtr;
12276
12277
12278 if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
12279 goto err;
12280 }
12281
12282 if (i == keyc - 1) {
12283
12284 if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
12285 if (newObjPtr || (flags & JIM_MUSTEXIST)) {
12286 goto err;
12287 }
12288 }
12289 break;
12290 }
12291
12292
12293 Jim_InvalidateStringRep(dictObjPtr);
12294 if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
12295 newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
12296 if (Jim_IsShared(objPtr)) {
12297 objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12185,11 @@
12304 }
12305 objPtr = Jim_NewDictObj(interp, NULL, 0);
12306 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12307 }
12308 }
12309
12310 Jim_InvalidateStringRep(objPtr);
12311 Jim_InvalidateStringRep(varObjPtr);
12312 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12313 goto err;
12314 }
@@ -12341,11 +12222,11 @@
12341 char buf[JIM_INTEGER_SPACE + 1];
12342 if (objPtr->internalRep.intValue >= 0) {
12343 sprintf(buf, "%d", objPtr->internalRep.intValue);
12344 }
12345 else {
12346
12347 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12348 }
12349 JimSetStringBytes(objPtr, buf);
12350 }
12351 }
@@ -12354,14 +12235,14 @@
12354 {
12355 int idx, end = 0;
12356 const char *str;
12357 char *endptr;
12358
12359
12360 str = Jim_String(objPtr);
12361
12362
12363 if (strncmp(str, "end", 3) == 0) {
12364 end = 1;
12365 str += 3;
12366 idx = 0;
12367 }
@@ -12372,21 +12253,21 @@
12372 goto badindex;
12373 }
12374 str = endptr;
12375 }
12376
12377
12378 if (*str == '+' || *str == '-') {
12379 int sign = (*str == '+' ? 1 : -1);
12380
12381 idx += sign * jim_strtol(++str, &endptr);
12382 if (str == endptr || *endptr) {
12383 goto badindex;
12384 }
12385 str = endptr;
12386 }
12387
12388 while (isspace(UCHAR(*str))) {
12389 str++;
12390 }
12391 if (*str) {
12392 goto badindex;
@@ -12394,19 +12275,19 @@
12394 if (end) {
12395 if (idx > 0) {
12396 idx = INT_MAX;
12397 }
12398 else {
12399
12400 idx--;
12401 }
12402 }
12403 else if (idx < 0) {
12404 idx = -INT_MAX;
12405 }
12406
12407
12408 Jim_FreeIntRep(interp, objPtr);
12409 objPtr->typePtr = &indexObjType;
12410 objPtr->internalRep.intValue = idx;
12411 return JIM_OK;
12412
@@ -12416,11 +12297,11 @@
12416 return JIM_ERR;
12417 }
12418
12419 int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
12420 {
12421
12422 if (objPtr->typePtr == &intObjType) {
12423 jim_wide val = JimWideValue(objPtr);
12424
12425 if (val < 0)
12426 *indexPtr = -INT_MAX;
@@ -12473,18 +12354,18 @@
12473 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12474 {
12475 int returnCode;
12476 jim_wide wideValue;
12477
12478
12479 if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
12480 returnCode = (int)wideValue;
12481 else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
12482 Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
12483 return JIM_ERR;
12484 }
12485
12486 Jim_FreeIntRep(interp, objPtr);
12487 objPtr->typePtr = &returnCodeObjType;
12488 objPtr->internalRep.intValue = returnCode;
12489 return JIM_OK;
12490 }
@@ -12498,19 +12379,20 @@
12498 }
12499
12500 static int JimParseExprOperator(struct JimParserCtx *pc);
12501 static int JimParseExprNumber(struct JimParserCtx *pc);
12502 static int JimParseExprIrrational(struct JimParserCtx *pc);
 
12503
12504
12505
12506
12507 enum
12508 {
12509
12510
12511 JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
12512 JIM_EXPROP_DIV,
12513 JIM_EXPROP_MOD,
12514 JIM_EXPROP_SUB,
12515 JIM_EXPROP_ADD,
12516 JIM_EXPROP_LSHIFT,
@@ -12521,66 +12403,67 @@
12521 JIM_EXPROP_GT,
12522 JIM_EXPROP_LTE,
12523 JIM_EXPROP_GTE,
12524 JIM_EXPROP_NUMEQ,
12525 JIM_EXPROP_NUMNE,
12526 JIM_EXPROP_BITAND,
12527 JIM_EXPROP_BITXOR,
12528 JIM_EXPROP_BITOR,
12529
12530
12531 JIM_EXPROP_LOGICAND,
12532 JIM_EXPROP_LOGICAND_LEFT,
12533 JIM_EXPROP_LOGICAND_RIGHT,
12534
12535
12536 JIM_EXPROP_LOGICOR,
12537 JIM_EXPROP_LOGICOR_LEFT,
12538 JIM_EXPROP_LOGICOR_RIGHT,
12539
12540
12541
12542 JIM_EXPROP_TERNARY,
12543 JIM_EXPROP_TERNARY_LEFT,
12544 JIM_EXPROP_TERNARY_RIGHT,
12545
12546
12547 JIM_EXPROP_COLON,
12548 JIM_EXPROP_COLON_LEFT,
12549 JIM_EXPROP_COLON_RIGHT,
12550
12551 JIM_EXPROP_POW,
12552
12553
12554 JIM_EXPROP_STREQ,
12555 JIM_EXPROP_STRNE,
12556 JIM_EXPROP_STRIN,
12557 JIM_EXPROP_STRNI,
12558
12559
12560 JIM_EXPROP_NOT,
12561 JIM_EXPROP_BITNOT,
12562 JIM_EXPROP_UNARYMINUS,
12563 JIM_EXPROP_UNARYPLUS,
12564
12565
12566 JIM_EXPROP_FUNC_FIRST,
12567 JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
12568 JIM_EXPROP_FUNC_WIDE,
12569 JIM_EXPROP_FUNC_ABS,
12570 JIM_EXPROP_FUNC_DOUBLE,
12571 JIM_EXPROP_FUNC_ROUND,
12572 JIM_EXPROP_FUNC_RAND,
12573 JIM_EXPROP_FUNC_SRAND,
12574
12575
12576 JIM_EXPROP_FUNC_SIN,
12577 JIM_EXPROP_FUNC_COS,
12578 JIM_EXPROP_FUNC_TAN,
12579 JIM_EXPROP_FUNC_ASIN,
12580 JIM_EXPROP_FUNC_ACOS,
12581 JIM_EXPROP_FUNC_ATAN,
 
12582 JIM_EXPROP_FUNC_SINH,
12583 JIM_EXPROP_FUNC_COSH,
12584 JIM_EXPROP_FUNC_TANH,
12585 JIM_EXPROP_FUNC_CEIL,
12586 JIM_EXPROP_FUNC_FLOOR,
@@ -12587,10 +12470,12 @@
12587 JIM_EXPROP_FUNC_EXP,
12588 JIM_EXPROP_FUNC_LOG,
12589 JIM_EXPROP_FUNC_LOG10,
12590 JIM_EXPROP_FUNC_SQRT,
12591 JIM_EXPROP_FUNC_POW,
 
 
12592 };
12593
12594 struct JimExprState
12595 {
12596 Jim_Obj **stack;
@@ -12667,11 +12552,15 @@
12667 case JIM_EXPROP_UNARYPLUS:
12668 dC = dA;
12669 intresult = 0;
12670 break;
12671 case JIM_EXPROP_FUNC_ABS:
 
 
 
12672 dC = dA >= 0 ? dA : -dA;
 
12673 intresult = 0;
12674 break;
12675 case JIM_EXPROP_UNARYMINUS:
12676 dC = -dA;
12677 intresult = 0;
@@ -12859,16 +12748,16 @@
12859 }
12860 }
12861 break;
12862 case JIM_EXPROP_ROTL:
12863 case JIM_EXPROP_ROTR:{
12864
12865 unsigned long uA = (unsigned long)wA;
12866 unsigned long uB = (unsigned long)wB;
12867 const unsigned int S = sizeof(unsigned long) * 8;
12868
12869
12870 uB %= S;
12871
12872 if (e->opcode == JIM_EXPROP_ROTR) {
12873 uB = S - uB;
12874 }
@@ -12890,11 +12779,10 @@
12890
12891
12892
12893 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12894 {
12895 int intresult = 1;
12896 int rc = JIM_OK;
12897 double dA, dB, dC = 0;
12898 jim_wide wA, wB, wC = 0;
12899
12900 Jim_Obj *B = ExprPop(e);
@@ -12902,30 +12790,36 @@
12902
12903 if ((A->typePtr != &doubleObjType || A->bytes) &&
12904 (B->typePtr != &doubleObjType || B->bytes) &&
12905 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12906
12907
12908
12909 switch (e->opcode) {
12910 case JIM_EXPROP_POW:
12911 case JIM_EXPROP_FUNC_POW:
 
 
 
 
 
12912 wC = JimPowWide(wA, wB);
12913 break;
12914 case JIM_EXPROP_ADD:
12915 wC = wA + wB;
12916 break;
12917 case JIM_EXPROP_SUB:
12918 wC = wA - wB;
12919 break;
12920 case JIM_EXPROP_MUL:
12921 wC = wA * wB;
12922 break;
12923 case JIM_EXPROP_DIV:
12924 if (wB == 0) {
12925 Jim_SetResultString(interp, "Division by zero", -1);
12926 rc = JIM_ERR;
 
12927 }
12928 else {
12929 if (wB < 0) {
12930 wB = -wB;
12931 wA = -wA;
@@ -12932,55 +12826,67 @@
12932 }
12933 wC = wA / wB;
12934 if (wA % wB < 0) {
12935 wC--;
12936 }
 
12937 }
12938 break;
12939 case JIM_EXPROP_LT:
12940 wC = wA < wB;
12941 break;
12942 case JIM_EXPROP_GT:
12943 wC = wA > wB;
12944 break;
12945 case JIM_EXPROP_LTE:
12946 wC = wA <= wB;
12947 break;
12948 case JIM_EXPROP_GTE:
12949 wC = wA >= wB;
12950 break;
12951 case JIM_EXPROP_NUMEQ:
12952 wC = wA == wB;
12953 break;
12954 case JIM_EXPROP_NUMNE:
12955 wC = wA != wB;
12956 break;
12957 default:
12958 abort();
12959 }
12960 }
12961 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12962 intresult = 0;
12963 switch (e->opcode) {
 
12964 case JIM_EXPROP_POW:
12965 case JIM_EXPROP_FUNC_POW:
12966 #ifdef JIM_MATH_FUNCTIONS
12967 dC = pow(dA, dB);
12968 #else
12969 Jim_SetResultString(interp, "unsupported", -1);
12970 rc = JIM_ERR;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12971 #endif
12972 break;
12973 case JIM_EXPROP_ADD:
12974 dC = dA + dB;
12975 break;
12976 case JIM_EXPROP_SUB:
12977 dC = dA - dB;
12978 break;
12979 case JIM_EXPROP_MUL:
12980 dC = dA * dB;
12981 break;
12982 case JIM_EXPROP_DIV:
12983 if (dB == 0) {
12984 #ifdef INFINITY
12985 dC = dA < 0 ? -INFINITY : INFINITY;
12986 #else
@@ -12988,83 +12894,70 @@
12988 #endif
12989 }
12990 else {
12991 dC = dA / dB;
12992 }
12993 break;
12994 case JIM_EXPROP_LT:
12995 wC = dA < dB;
12996 intresult = 1;
12997 break;
12998 case JIM_EXPROP_GT:
12999 wC = dA > dB;
13000 intresult = 1;
13001 break;
13002 case JIM_EXPROP_LTE:
13003 wC = dA <= dB;
13004 intresult = 1;
13005 break;
13006 case JIM_EXPROP_GTE:
13007 wC = dA >= dB;
13008 intresult = 1;
13009 break;
13010 case JIM_EXPROP_NUMEQ:
13011 wC = dA == dB;
13012 intresult = 1;
13013 break;
13014 case JIM_EXPROP_NUMNE:
13015 wC = dA != dB;
13016 intresult = 1;
13017 break;
13018 default:
13019 abort();
13020 }
13021 }
13022 else {
13023
13024
13025
 
13026 int i = Jim_StringCompareObj(interp, A, B, 0);
13027
13028 switch (e->opcode) {
13029 case JIM_EXPROP_LT:
13030 wC = i < 0;
13031 break;
13032 case JIM_EXPROP_GT:
13033 wC = i > 0;
13034 break;
13035 case JIM_EXPROP_LTE:
13036 wC = i <= 0;
13037 break;
13038 case JIM_EXPROP_GTE:
13039 wC = i >= 0;
13040 break;
13041 case JIM_EXPROP_NUMEQ:
13042 wC = i == 0;
13043 break;
13044 case JIM_EXPROP_NUMNE:
13045 wC = i != 0;
13046 break;
13047 default:
13048 rc = JIM_ERR;
13049 break;
13050 }
13051 }
13052
13053 if (rc == JIM_OK) {
13054 if (intresult) {
13055 ExprPush(e, Jim_NewIntObj(interp, wC));
13056 }
13057 else {
13058 ExprPush(e, Jim_NewDoubleObj(interp, dC));
13059 }
13060 }
13061
13062 Jim_DecrRefCount(interp, A);
13063 Jim_DecrRefCount(interp, B);
13064
13065 return rc;
 
 
 
 
 
 
13066 }
13067
13068 static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
13069 {
13070 int listlen;
@@ -13113,16 +13006,20 @@
13113
13114 static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
13115 {
13116 long l;
13117 double d;
 
13118
13119 if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
13120 return l != 0;
13121 }
13122 if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13123 return d != 0;
 
 
 
13124 }
13125 return -1;
13126 }
13127
13128 static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
@@ -13131,21 +13028,21 @@
13131 Jim_Obj *A = ExprPop(e);
13132 int rc = JIM_OK;
13133
13134 switch (ExprBool(interp, A)) {
13135 case 0:
13136
13137 e->skip = JimWideValue(skip);
13138 ExprPush(e, Jim_NewIntObj(interp, 0));
13139 break;
13140
13141 case 1:
13142
13143 break;
13144
13145 case -1:
13146
13147 rc = JIM_ERR;
13148 }
13149 Jim_DecrRefCount(interp, A);
13150 Jim_DecrRefCount(interp, skip);
13151
@@ -13158,21 +13055,21 @@
13158 Jim_Obj *A = ExprPop(e);
13159 int rc = JIM_OK;
13160
13161 switch (ExprBool(interp, A)) {
13162 case 0:
13163
13164 break;
13165
13166 case 1:
13167
13168 e->skip = JimWideValue(skip);
13169 ExprPush(e, Jim_NewIntObj(interp, 1));
13170 break;
13171
13172 case -1:
13173
13174 rc = JIM_ERR;
13175 break;
13176 }
13177 Jim_DecrRefCount(interp, A);
13178 Jim_DecrRefCount(interp, skip);
@@ -13193,11 +13090,11 @@
13193 case 1:
13194 ExprPush(e, Jim_NewIntObj(interp, 1));
13195 break;
13196
13197 case -1:
13198
13199 rc = JIM_ERR;
13200 break;
13201 }
13202 Jim_DecrRefCount(interp, A);
13203
@@ -13208,27 +13105,27 @@
13208 {
13209 Jim_Obj *skip = ExprPop(e);
13210 Jim_Obj *A = ExprPop(e);
13211 int rc = JIM_OK;
13212
13213
13214 ExprPush(e, A);
13215
13216 switch (ExprBool(interp, A)) {
13217 case 0:
13218
13219 e->skip = JimWideValue(skip);
13220
13221 ExprPush(e, Jim_NewIntObj(interp, 0));
13222 break;
13223
13224 case 1:
13225
13226 break;
13227
13228 case -1:
13229
13230 rc = JIM_ERR;
13231 break;
13232 }
13233 Jim_DecrRefCount(interp, A);
13234 Jim_DecrRefCount(interp, skip);
@@ -13240,15 +13137,15 @@
13240 {
13241 Jim_Obj *skip = ExprPop(e);
13242 Jim_Obj *B = ExprPop(e);
13243 Jim_Obj *A = ExprPop(e);
13244
13245
13246 if (ExprBool(interp, A)) {
13247
13248 e->skip = JimWideValue(skip);
13249
13250 ExprPush(e, B);
13251 }
13252
13253 Jim_DecrRefCount(interp, skip);
13254 Jim_DecrRefCount(interp, A);
@@ -13264,15 +13161,16 @@
13264 enum
13265 {
13266 LAZY_NONE,
13267 LAZY_OP,
13268 LAZY_LEFT,
13269 LAZY_RIGHT
 
13270 };
13271
13272 #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13273 #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13274
13275 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13276 OPRINIT("*", 110, 2, JimExprOpBin),
13277 OPRINIT("/", 110, 2, JimExprOpBin),
13278 OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,27 +13194,28 @@
13296
13297 OPRINIT("&", 50, 2, JimExprOpIntBin),
13298 OPRINIT("^", 49, 2, JimExprOpIntBin),
13299 OPRINIT("|", 48, 2, JimExprOpIntBin),
13300
13301 OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13302 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13303 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13304
13305 OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13306 OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13307 OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13308
13309 OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13310 OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13311 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13312
13313 OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13314 OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13315 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13316
13317 OPRINIT("**", 250, 2, JimExprOpBin),
 
13318
13319 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13320 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13321
13322 OPRINIT("in", 55, 2, JimExprOpStrBin),
@@ -13342,10 +13241,11 @@
13342 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13343 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13344 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13345 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13346 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
 
13347 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13348 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13349 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13350 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13351 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
@@ -13352,10 +13252,12 @@
13352 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13353 OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13354 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13355 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13356 OPRINIT("pow", 200, 2, JimExprOpBin),
 
 
13357 #endif
13358 };
13359 #undef OPRINIT
13360 #undef OPRINIT_LAZY
13361
@@ -13362,20 +13264,20 @@
13362 #define JIM_EXPR_OPERATORS_NUM \
13363 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13364
13365 static int JimParseExpression(struct JimParserCtx *pc)
13366 {
13367
13368 while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
13369 if (*pc->p == '\n') {
13370 pc->linenr++;
13371 }
13372 pc->p++;
13373 pc->len--;
13374 }
13375
13376
13377 pc->tline = pc->linenr;
13378 pc->tstart = pc->p;
13379
13380 if (pc->len == 0) {
13381 pc->tend = pc->p;
@@ -13401,11 +13303,11 @@
13401 return JimParseCmd(pc);
13402 case '$':
13403 if (JimParseVar(pc) == JIM_ERR)
13404 return JimParseExprOperator(pc);
13405 else {
13406
13407 if (pc->tt == JIM_TT_EXPRSUGAR) {
13408 return JIM_ERR;
13409 }
13410 return JIM_OK;
13411 }
@@ -13430,10 +13332,18 @@
13430 case 'N':
13431 case 'I':
13432 case 'n':
13433 case 'i':
13434 if (JimParseExprIrrational(pc) == JIM_ERR)
 
 
 
 
 
 
 
 
13435 return JimParseExprOperator(pc);
13436 break;
13437 default:
13438 return JimParseExprOperator(pc);
13439 break;
@@ -13443,21 +13353,21 @@
13443
13444 static int JimParseExprNumber(struct JimParserCtx *pc)
13445 {
13446 char *end;
13447
13448
13449 pc->tt = JIM_TT_EXPR_INT;
13450
13451 jim_strtoull(pc->p, (char **)&pc->p);
13452
13453 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13454 if (strtod(pc->tstart, &end)) { }
13455 if (end == pc->tstart)
13456 return JIM_ERR;
13457 if (end > pc->p) {
13458
13459 pc->tt = JIM_TT_EXPR_DOUBLE;
13460 pc->p = end;
13461 }
13462 }
13463 pc->tend = pc->p - 1;
@@ -13481,17 +13391,38 @@
13481 return JIM_OK;
13482 }
13483 }
13484 return JIM_ERR;
13485 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13486
13487 static int JimParseExprOperator(struct JimParserCtx *pc)
13488 {
13489 int i;
13490 int bestIdx = -1, bestLen = 0;
13491
13492
13493 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13494 const char * const opname = Jim_ExprOperators[i].name;
13495 const int oplen = Jim_ExprOperators[i].namelen;
13496
13497 if (opname == NULL || opname[0] != pc->p[0]) {
@@ -13505,11 +13436,11 @@
13505 }
13506 if (bestIdx == -1) {
13507 return JIM_ERR;
13508 }
13509
13510
13511 if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
13512 const char *p = pc->p + bestLen;
13513 int len = pc->len - bestLen;
13514
13515 while (len && isspace(UCHAR(*p))) {
@@ -13539,13 +13470,19 @@
13539
13540 const char *jim_tt_name(int type)
13541 {
13542 static const char * const tt_names[JIM_TT_EXPR_OP] =
13543 { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13544 "DBL", "$()" };
13545 if (type < JIM_TT_EXPR_OP) {
13546 return tt_names[type];
 
 
 
 
 
 
13547 }
13548 else {
13549 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
13550 static char buf[20];
13551
@@ -13570,13 +13507,13 @@
13570 };
13571
13572
13573 typedef struct ExprByteCode
13574 {
13575 ScriptToken *token;
13576 int len;
13577 int inUse;
13578 } ExprByteCode;
13579
13580 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13581 {
13582 int i;
@@ -13604,26 +13541,29 @@
13604 static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
13605 {
13606 JIM_NOTUSED(interp);
13607 JIM_NOTUSED(srcPtr);
13608
13609
13610 dupPtr->typePtr = NULL;
13611 }
13612
13613
13614 static int ExprCheckCorrectness(ExprByteCode * expr)
13615 {
13616 int i;
13617 int stacklen = 0;
13618 int ternary = 0;
 
 
13619
13620 for (i = 0; i < expr->len; i++) {
13621 ScriptToken *t = &expr->token[i];
13622 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
 
13623
13624 stacklen -= op->arity;
 
13625 if (stacklen < 0) {
13626 break;
13627 }
13628 if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
13629 ternary++;
@@ -13630,26 +13570,47 @@
13630 }
13631 else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
13632 ternary--;
13633 }
13634
13635
13636 stacklen++;
13637 }
13638 if (stacklen != 1 || ternary != 0) {
13639 return JIM_ERR;
13640 }
13641 return JIM_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13642 }
13643
13644 static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13645 {
13646 int i;
13647
13648 int leftindex, arity, offset;
13649
13650
13651 leftindex = expr->len - 1;
13652
13653 arity = 1;
13654 while (arity) {
13655 ScriptToken *tt = &expr->token[leftindex];
@@ -13662,11 +13623,11 @@
13662 return JIM_ERR;
13663 }
13664 }
13665 leftindex++;
13666
13667
13668 memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
13669 sizeof(*expr->token) * (expr->len - leftindex));
13670 expr->len += 2;
13671 offset = (expr->len - leftindex) - 1;
13672
@@ -13674,16 +13635,16 @@
13674 expr->token[leftindex + 1].objPtr = interp->emptyObj;
13675
13676 expr->token[leftindex].type = JIM_TT_EXPR_INT;
13677 expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
13678
13679
13680 expr->token[expr->len].objPtr = interp->emptyObj;
13681 expr->token[expr->len].type = t->type + 2;
13682 expr->len++;
13683
13684
13685 for (i = leftindex - 1; i > 0; i--) {
13686 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
13687 if (op->lazy == LAZY_LEFT) {
13688 if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
13689 JimWideValue(expr->token[i - 1].objPtr) += 2;
@@ -13729,11 +13690,11 @@
13729 return right_index;
13730 }
13731 right_index--;
13732 }
13733
13734
13735 return -1;
13736 }
13737
13738 static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
13739 {
@@ -13771,11 +13732,11 @@
13771
13772 if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
13773 continue;
13774 }
13775
13776
13777 if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
13778 continue;
13779 }
13780
13781 tmp = expr->token[prev_right_index];
@@ -13784,25 +13745,25 @@
13784 }
13785 expr->token[i] = tmp;
13786
13787 JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
13788
13789
13790 i++;
13791 }
13792 }
13793
13794 static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
13795 {
13796 Jim_Stack stack;
13797 ExprByteCode *expr;
13798 int ok = 1;
13799 int i;
13800 int prevtt = JIM_TT_NONE;
13801 int have_ternary = 0;
13802
13803
13804 int count = tokenlist->count - 1;
13805
13806 expr = Jim_Alloc(sizeof(*expr));
13807 expr->inUse = 1;
13808 expr->len = 0;
@@ -13813,11 +13774,11 @@
13813 ParseToken *t = &tokenlist->list[i];
13814 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13815
13816 if (op->lazy == LAZY_OP) {
13817 count += 2;
13818
13819 if (t->type == JIM_EXPROP_TERNARY) {
13820 have_ternary = 1;
13821 }
13822 }
13823 }
@@ -13825,128 +13786,128 @@
13825 expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
13826
13827 for (i = 0; i < tokenlist->count && ok; i++) {
13828 ParseToken *t = &tokenlist->list[i];
13829
13830
13831 struct ScriptToken *token = &expr->token[expr->len];
13832
13833 if (t->type == JIM_TT_EOL) {
13834 break;
13835 }
13836
13837 switch (t->type) {
13838 case JIM_TT_STR:
13839 case JIM_TT_ESC:
13840 case JIM_TT_VAR:
13841 case JIM_TT_DICTSUGAR:
13842 case JIM_TT_EXPRSUGAR:
13843 case JIM_TT_CMD:
13844 token->type = t->type;
13845 strexpr:
13846 token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13847 if (t->type == JIM_TT_CMD) {
13848
13849 JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13850 }
13851 expr->len++;
13852 break;
13853
13854 case JIM_TT_EXPR_INT:
13855 case JIM_TT_EXPR_DOUBLE:
13856 {
13857 char *endptr;
13858 if (t->type == JIM_TT_EXPR_INT) {
13859 token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13860 }
13861 else {
13862 token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13863 }
13864 if (endptr != t->token + t->len) {
13865
13866 Jim_FreeNewObj(interp, token->objPtr);
13867 token->type = JIM_TT_STR;
13868 goto strexpr;
13869 }
13870 token->type = t->type;
13871 expr->len++;
13872 }
13873 break;
13874
13875 case JIM_TT_SUBEXPR_START:
13876 Jim_StackPush(&stack, t);
13877 prevtt = JIM_TT_NONE;
13878 continue;
13879
13880 case JIM_TT_SUBEXPR_COMMA:
13881
13882 continue;
13883
13884 case JIM_TT_SUBEXPR_END:
13885 ok = 0;
13886 while (Jim_StackLen(&stack)) {
13887 ParseToken *tt = Jim_StackPop(&stack);
13888
13889 if (tt->type == JIM_TT_SUBEXPR_START) {
13890 ok = 1;
13891 break;
13892 }
13893
13894 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13895 goto err;
13896 }
13897 }
13898 if (!ok) {
13899 Jim_SetResultString(interp, "Unexpected close parenthesis", -1);
13900 goto err;
13901 }
13902 break;
13903
13904
13905 default:{
13906
13907 const struct Jim_ExprOperator *op;
13908 ParseToken *tt;
13909
13910
13911 if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
13912 if (t->type == JIM_EXPROP_SUB) {
13913 t->type = JIM_EXPROP_UNARYMINUS;
13914 }
13915 else if (t->type == JIM_EXPROP_ADD) {
13916 t->type = JIM_EXPROP_UNARYPLUS;
13917 }
13918 }
13919
13920 op = JimExprOperatorInfoByOpcode(t->type);
13921
13922
13923 while ((tt = Jim_StackPeek(&stack)) != NULL) {
13924 const struct Jim_ExprOperator *tt_op =
13925 JimExprOperatorInfoByOpcode(tt->type);
13926
13927
13928
13929 if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13930 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13931 ok = 0;
13932 goto err;
13933 }
13934 Jim_StackPop(&stack);
13935 }
13936 else {
13937 break;
13938 }
13939 }
13940 Jim_StackPush(&stack, t);
13941 break;
13942 }
13943 }
13944 prevtt = t->type;
13945 }
13946
13947
13948 while (Jim_StackLen(&stack)) {
13949 ParseToken *tt = Jim_StackPop(&stack);
13950
13951 if (tt->type == JIM_TT_SUBEXPR_START) {
13952 ok = 0;
@@ -13962,11 +13923,11 @@
13962 if (have_ternary) {
13963 ExprTernaryReorderExpression(interp, expr);
13964 }
13965
13966 err:
13967
13968 Jim_FreeStack(&stack);
13969
13970 for (i = 0; i < expr->len; i++) {
13971 Jim_IncrRefCount(expr->token[i].objPtr);
13972 }
@@ -13989,11 +13950,11 @@
13989 ParseTokenList tokenlist;
13990 int line;
13991 Jim_Obj *fileNameObj;
13992 int rc = JIM_ERR;
13993
13994
13995 if (objPtr->typePtr == &sourceObjType) {
13996 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
13997 line = objPtr->internalRep.sourceValue.lineNumber;
13998 }
13999 else {
@@ -14002,18 +13963,17 @@
14002 }
14003 Jim_IncrRefCount(fileNameObj);
14004
14005 exprText = Jim_GetString(objPtr, &exprTextLen);
14006
14007
14008 ScriptTokenListInit(&tokenlist);
14009
14010 JimParserInit(&parser, exprText, exprTextLen, line);
14011 while (!parser.eof) {
14012 if (JimParseExpression(&parser) != JIM_OK) {
14013 ScriptTokenListFree(&tokenlist);
14014 invalidexpr:
14015 Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
14016 expr = NULL;
14017 goto err;
14018 }
14019
@@ -14036,14 +13996,14 @@
14036 ScriptTokenListFree(&tokenlist);
14037 Jim_DecrRefCount(interp, fileNameObj);
14038 return JIM_ERR;
14039 }
14040
14041
14042 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
14043
14044
 
 
14045 ScriptTokenListFree(&tokenlist);
14046
14047 if (!expr) {
14048 goto err;
14049 }
@@ -14059,20 +14019,22 @@
14059 printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
14060 }
14061 }
14062 #endif
14063
14064
14065 if (ExprCheckCorrectness(expr) != JIM_OK) {
 
14066 ExprFreeByteCode(interp, expr);
14067 goto invalidexpr;
 
14068 }
14069
14070 rc = JIM_OK;
14071
14072 err:
14073
14074 Jim_DecrRefCount(interp, fileNameObj);
14075 Jim_FreeIntRep(interp, objPtr);
14076 Jim_SetIntRepPtr(objPtr, expr);
14077 objPtr->typePtr = &exprObjType;
14078 return rc;
@@ -14112,11 +14074,11 @@
14112 int retcode = JIM_OK;
14113 struct JimExprState e;
14114
14115 expr = JimGetExpression(interp, exprObjPtr);
14116 if (!expr) {
14117 return JIM_ERR;
14118 }
14119
14120 #ifdef JIM_OPTIMIZATION
14121 {
14122 Jim_Obj *objPtr;
@@ -14185,26 +14147,27 @@
14185 noopt:
14186 #endif
14187
14188 expr->inUse++;
14189
14190
14191
14192 if (expr->len > JIM_EE_STATICSTACK_LEN)
14193 e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
14194 else
14195 e.stack = staticStack;
14196
14197 e.stacklen = 0;
14198
14199
14200 for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
14201 Jim_Obj *objPtr;
14202
14203 switch (expr->token[i].type) {
14204 case JIM_TT_EXPR_INT:
14205 case JIM_TT_EXPR_DOUBLE:
 
14206 case JIM_TT_STR:
14207 ExprPush(&e, expr->token[i].objPtr);
14208 break;
14209
14210 case JIM_TT_VAR:
@@ -14240,16 +14203,16 @@
14240 ExprPush(&e, Jim_GetResult(interp));
14241 }
14242 break;
14243
14244 default:{
14245
14246 e.skip = 0;
14247 e.opcode = expr->token[i].type;
14248
14249 retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
14250
14251 i += e.skip;
14252 continue;
14253 }
14254 }
14255 }
@@ -14273,20 +14236,27 @@
14273 int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
14274 {
14275 int retcode;
14276 jim_wide wideValue;
14277 double doubleValue;
 
14278 Jim_Obj *exprResultPtr;
14279
14280 retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
14281 if (retcode != JIM_OK)
14282 return retcode;
14283
14284 if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
14285 if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
14286 Jim_DecrRefCount(interp, exprResultPtr);
14287 return JIM_ERR;
 
 
 
 
 
 
14288 }
14289 else {
14290 Jim_DecrRefCount(interp, exprResultPtr);
14291 *boolPtr = doubleValue != 0;
14292 return JIM_OK;
@@ -14301,29 +14271,29 @@
14301
14302
14303
14304 typedef struct ScanFmtPartDescr
14305 {
14306 char *arg;
14307 char *prefix;
14308 size_t width;
14309 int pos;
14310 char type;
14311 char modifier;
14312 } ScanFmtPartDescr;
14313
14314
14315 typedef struct ScanFmtStringObj
14316 {
14317 jim_wide size;
14318 char *stringRep;
14319 size_t count;
14320 size_t convCount;
14321 size_t maxPos;
14322 const char *error;
14323 char *scratch;
14324 ScanFmtPartDescr descr[1];
14325 } ScanFmtStringObj;
14326
14327
14328 static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
14329 static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14370,22 +14340,22 @@
14370 int maxFmtLen = objPtr->length;
14371 const char *fmtEnd = fmt + maxFmtLen;
14372 int curr;
14373
14374 Jim_FreeIntRep(interp, objPtr);
14375
14376 for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
14377 if (fmt[i] == '%')
14378 ++maxCount;
14379
14380 approxSize = sizeof(ScanFmtStringObj)
14381 +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14382 +maxFmtLen * sizeof(char) + 3 + 1
14383 + maxFmtLen * sizeof(char) + 1
14384 + maxFmtLen * sizeof(char)
14385 +(maxCount + 1) * sizeof(char)
14386 +1;
14387 fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
14388 memset(fmtObj, 0, approxSize);
14389 fmtObj->size = approxSize;
14390 fmtObj->maxPos = 0;
14391 fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14367,12 @@
14397 for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
14398 int width = 0, skip;
14399 ScanFmtPartDescr *descr = &fmtObj->descr[curr];
14400
14401 fmtObj->count++;
14402 descr->width = 0;
14403
14404 if (*fmt != '%' || fmt[1] == '%') {
14405 descr->type = 0;
14406 descr->prefix = &buffer[i];
14407 for (; fmt < fmtEnd; ++fmt) {
14408 if (*fmt == '%') {
@@ -14412,65 +14382,65 @@
14412 }
14413 buffer[i++] = *fmt;
14414 }
14415 buffer[i++] = 0;
14416 }
14417
14418 ++fmt;
14419
14420 if (fmt >= fmtEnd)
14421 goto done;
14422 descr->pos = 0;
14423 if (*fmt == '*') {
14424 descr->pos = -1;
14425 ++fmt;
14426 }
14427 else
14428 fmtObj->convCount++;
14429
14430 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14431 fmt += skip;
14432
14433 if (descr->pos != -1 && *fmt == '$') {
14434 int prev;
14435
14436 ++fmt;
14437 descr->pos = width;
14438 width = 0;
14439
14440 if ((lastPos == 0 && descr->pos > 0)
14441 || (lastPos > 0 && descr->pos == 0)) {
14442 fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
14443 return JIM_ERR;
14444 }
14445
14446 for (prev = 0; prev < curr; ++prev) {
14447 if (fmtObj->descr[prev].pos == -1)
14448 continue;
14449 if (fmtObj->descr[prev].pos == descr->pos) {
14450 fmtObj->error =
14451 "variable is assigned by multiple \"%n$\" conversion specifiers";
14452 return JIM_ERR;
14453 }
14454 }
14455
14456 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14457 descr->width = width;
14458 fmt += skip;
14459 }
14460 if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
14461 fmtObj->maxPos = descr->pos;
14462 }
14463 else {
14464
14465 descr->width = width;
14466 }
14467 }
14468
14469 if (lastPos == -1)
14470 lastPos = descr->pos;
14471
14472 if (*fmt == '[') {
14473 int swapped = 1, beg = i, end, j;
14474
14475 descr->type = '[';
14476 descr->arg = &buffer[i];
@@ -14485,11 +14455,11 @@
14485 fmtObj->error = "unmatched [ in format string";
14486 return JIM_ERR;
14487 }
14488 end = i;
14489 buffer[i++] = 0;
14490
14491 while (swapped) {
14492 swapped = 0;
14493 for (j = beg + 1; j < end - 1; ++j) {
14494 if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
14495 char tmp = buffer[j - 1];
@@ -14500,11 +14470,11 @@
14500 }
14501 }
14502 }
14503 }
14504 else {
14505
14506 if (strchr("hlL", *fmt) != 0)
14507 descr->modifier = tolower((int)*fmt++);
14508
14509 descr->type = *fmt;
14510 if (strchr("efgcsndoxui", *fmt) == 0) {
@@ -14543,11 +14513,11 @@
14543 while (*str) {
14544 int c;
14545 int n;
14546
14547 if (!sdescr && isspace(UCHAR(*str)))
14548 break;
14549
14550 n = utf8_tounicode(str, &c);
14551 if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
14552 break;
14553 while (n--)
@@ -14566,89 +14536,89 @@
14566 size_t scanned = 0;
14567 size_t anchor = pos;
14568 int i;
14569 Jim_Obj *tmpObj = NULL;
14570
14571
14572 *valObjPtr = 0;
14573 if (descr->prefix) {
14574 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14575
14576 if (isspace(UCHAR(descr->prefix[i])))
14577 while (pos < strLen && isspace(UCHAR(str[pos])))
14578 ++pos;
14579 else if (descr->prefix[i] != str[pos])
14580 break;
14581 else
14582 ++pos;
14583 }
14584 if (pos >= strLen) {
14585 return -1;
14586 }
14587 else if (descr->prefix[i] != 0)
14588 return 0;
14589 }
14590
14591 if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
14592 while (isspace(UCHAR(str[pos])))
14593 ++pos;
14594
14595 scanned = pos - anchor;
14596
14597
14598 if (descr->type == 'n') {
14599
14600 *valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
14601 }
14602 else if (pos >= strLen) {
14603
14604 return -1;
14605 }
14606 else if (descr->type == 'c') {
14607 int c;
14608 scanned += utf8_tounicode(&str[pos], &c);
14609 *valObjPtr = Jim_NewIntObj(interp, c);
14610 return scanned;
14611 }
14612 else {
14613
14614 if (descr->width > 0) {
14615 size_t sLen = utf8_strlen(&str[pos], strLen - pos);
14616 size_t tLen = descr->width > sLen ? sLen : descr->width;
14617
14618 tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
14619 tok = tmpObj->bytes;
14620 }
14621 else {
14622
14623 tok = &str[pos];
14624 }
14625 switch (descr->type) {
14626 case 'd':
14627 case 'o':
14628 case 'x':
14629 case 'u':
14630 case 'i':{
14631 char *endp;
14632 jim_wide w;
14633
14634 int base = descr->type == 'o' ? 8
14635 : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
14636
14637
14638 if (base == 0) {
14639 w = jim_strtoull(tok, &endp);
14640 }
14641 else {
14642 w = strtoull(tok, &endp, base);
14643 }
14644
14645 if (endp != tok) {
14646
14647 *valObjPtr = Jim_NewIntObj(interp, w);
14648
14649
14650 scanned += endp - tok;
14651 }
14652 else {
14653 scanned = *tok ? 0 : -1;
14654 }
@@ -14665,13 +14635,13 @@
14665 case 'g':{
14666 char *endp;
14667 double value = strtod(tok, &endp);
14668
14669 if (endp != tok) {
14670
14671 *valObjPtr = Jim_NewDoubleObj(interp, value);
14672
14673 scanned += endp - tok;
14674 }
14675 else {
14676 scanned = *tok ? 0 : -1;
14677 }
@@ -14696,65 +14666,65 @@
14696 Jim_Obj **resultVec = 0;
14697 int resultc;
14698 Jim_Obj *emptyStr = 0;
14699 ScanFmtStringObj *fmtObj;
14700
14701
14702 JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
14703
14704 fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14705
14706 if (fmtObj->error != 0) {
14707 if (flags & JIM_ERRMSG)
14708 Jim_SetResultString(interp, fmtObj->error, -1);
14709 return 0;
14710 }
14711
14712 emptyStr = Jim_NewEmptyStringObj(interp);
14713 Jim_IncrRefCount(emptyStr);
14714
14715 resultList = Jim_NewListObj(interp, NULL, 0);
14716 if (fmtObj->maxPos > 0) {
14717 for (i = 0; i < fmtObj->maxPos; ++i)
14718 Jim_ListAppendElement(interp, resultList, emptyStr);
14719 JimListGetElements(interp, resultList, &resultc, &resultVec);
14720 }
14721
14722 for (i = 0, pos = 0; i < fmtObj->count; ++i) {
14723 ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
14724 Jim_Obj *value = 0;
14725
14726
14727 if (descr->type == 0)
14728 continue;
14729
14730 if (scanned > 0)
14731 scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14732
14733 if (scanned == -1 && i == 0)
14734 goto eof;
14735
14736 pos += scanned;
14737
14738
14739 if (value == 0)
14740 value = Jim_NewEmptyStringObj(interp);
14741
14742 if (descr->pos == -1) {
14743 Jim_FreeNewObj(interp, value);
14744 }
14745 else if (descr->pos == 0)
14746
14747 Jim_ListAppendElement(interp, resultList, value);
14748 else if (resultVec[descr->pos - 1] == emptyStr) {
14749
14750 Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
14751 Jim_IncrRefCount(value);
14752 resultVec[descr->pos - 1] = value;
14753 }
14754 else {
14755
14756 Jim_FreeNewObj(interp, value);
14757 goto err;
14758 }
14759 }
14760 Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14762,15 @@
14792 {
14793 Jim_PrngState *prng;
14794 unsigned char *destByte = (unsigned char *)dest;
14795 unsigned int si, sj, x;
14796
14797
14798 if (interp->prngState == NULL)
14799 JimPrngInit(interp);
14800 prng = interp->prngState;
14801
14802 for (x = 0; x < len; x++) {
14803 prng->i = (prng->i + 1) & 0xff;
14804 si = prng->sbox[prng->i];
14805 prng->j = (prng->j + si) & 0xff;
14806 sj = prng->sbox[prng->j];
@@ -14814,19 +14784,19 @@
14814 static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
14815 {
14816 int i;
14817 Jim_PrngState *prng;
14818
14819
14820 if (interp->prngState == NULL)
14821 JimPrngInit(interp);
14822 prng = interp->prngState;
14823
14824
14825 for (i = 0; i < 256; i++)
14826 prng->sbox[i] = i;
14827
14828 for (i = 0; i < seedLen; i++) {
14829 unsigned char t;
14830
14831 t = prng->sbox[i & 0xFF];
14832 prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14823,11 @@
14853 if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
14854 return JIM_ERR;
14855 }
14856 intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
14857 if (!intObjPtr) {
14858
14859 wideValue = 0;
14860 }
14861 else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
14862 return JIM_ERR;
14863 }
@@ -14867,26 +14837,26 @@
14867 Jim_FreeNewObj(interp, intObjPtr);
14868 return JIM_ERR;
14869 }
14870 }
14871 else {
14872
14873 Jim_InvalidateStringRep(intObjPtr);
14874 JimWideValue(intObjPtr) = wideValue + increment;
14875
14876 if (argv[1]->typePtr != &variableObjType) {
14877
14878 Jim_SetVariable(interp, argv[1], intObjPtr);
14879 }
14880 }
14881 Jim_SetResult(interp, intObjPtr);
14882 return JIM_OK;
14883 }
14884
14885
14886 #define JIM_EVAL_SARGV_LEN 8
14887 #define JIM_EVAL_SINTV_LEN 8
14888
14889
14890 static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
14891 {
14892 int retcode;
@@ -14894,16 +14864,16 @@
14894 if (interp->unknown_called > 50) {
14895 return JIM_ERR;
14896 }
14897
14898
14899
14900 if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
14901 return JIM_ERR;
14902
14903 interp->unknown_called++;
14904
14905 retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
14906 interp->unknown_called--;
14907
14908 return retcode;
14909 }
@@ -14921,11 +14891,11 @@
14921 }
14922 printf("\n");
14923 #endif
14924
14925 if (interp->framePtr->tailcallCmd) {
14926
14927 cmdPtr = interp->framePtr->tailcallCmd;
14928 interp->framePtr->tailcallCmd = NULL;
14929 }
14930 else {
14931 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14940,11 +14910,11 @@
14940 retcode = JIM_ERR;
14941 goto out;
14942 }
14943 interp->evalDepth++;
14944
14945
14946 Jim_SetEmptyResult(interp);
14947 if (cmdPtr->isproc) {
14948 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14949 }
14950 else {
@@ -14961,17 +14931,17 @@
14961
14962 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14963 {
14964 int i, retcode;
14965
14966
14967 for (i = 0; i < objc; i++)
14968 Jim_IncrRefCount(objv[i]);
14969
14970 retcode = JimInvokeCommand(interp, objc, objv);
14971
14972
14973 for (i = 0; i < objc; i++)
14974 Jim_DecrRefCount(interp, objv[i]);
14975
14976 return retcode;
14977 }
@@ -14989,25 +14959,25 @@
14989 }
14990
14991 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
14992 {
14993 if (!interp->errorFlag) {
14994
14995 interp->errorFlag = 1;
14996 Jim_IncrRefCount(script->fileNameObj);
14997 Jim_DecrRefCount(interp, interp->errorFileNameObj);
14998 interp->errorFileNameObj = script->fileNameObj;
14999 interp->errorLine = script->linenr;
15000
15001 JimResetStackTrace(interp);
15002
15003 interp->addStackTrace++;
15004 }
15005
15006
15007 if (interp->addStackTrace > 0) {
15008
15009
15010 JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
15011
15012 if (Jim_Length(script->fileNameObj)) {
15013 interp->addStackTrace = 0;
@@ -15042,14 +15012,14 @@
15042 case JIM_OK:
15043 case JIM_RETURN:
15044 objPtr = interp->result;
15045 break;
15046 case JIM_BREAK:
15047
15048 return JIM_BREAK;
15049 case JIM_CONTINUE:
15050
15051 return JIM_CONTINUE;
15052 default:
15053 return JIM_ERR;
15054 }
15055 break;
@@ -15084,23 +15054,23 @@
15084 case JIM_OK:
15085 case JIM_RETURN:
15086 break;
15087 case JIM_BREAK:
15088 if (flags & JIM_SUBST_FLAG) {
15089
15090 tokens = i;
15091 continue;
15092 }
15093
15094
15095 case JIM_CONTINUE:
15096 if (flags & JIM_SUBST_FLAG) {
15097 intv[i] = NULL;
15098 continue;
15099 }
15100
15101
15102 default:
15103 while (i--) {
15104 Jim_DecrRefCount(interp, intv[i]);
15105 }
15106 if (intv != sintv) {
@@ -15111,28 +15081,28 @@
15111 Jim_IncrRefCount(intv[i]);
15112 Jim_String(intv[i]);
15113 totlen += intv[i]->length;
15114 }
15115
15116
15117 if (tokens == 1 && intv[0] && intv == sintv) {
15118 Jim_DecrRefCount(interp, intv[0]);
15119 return intv[0];
15120 }
15121
15122 objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
15123
15124 if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
15125 && token[2].type == JIM_TT_VAR) {
15126
15127 objPtr->typePtr = &interpolatedObjType;
15128 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
15129 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
15130 Jim_IncrRefCount(intv[2]);
15131 }
15132 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
15133
15134 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
15135 }
15136
15137
15138 s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +15113,11 @@
15143 s += intv[i]->length;
15144 Jim_DecrRefCount(interp, intv[i]);
15145 }
15146 }
15147 objPtr->bytes[totlen] = '\0';
15148
15149 if (intv != sintv) {
15150 Jim_Free(intv);
15151 }
15152
15153 return objPtr;
@@ -15187,11 +15157,11 @@
15187
15188 if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
15189 return JimEvalObjList(interp, scriptObjPtr);
15190 }
15191
15192 Jim_IncrRefCount(scriptObjPtr);
15193 script = JimGetScript(interp, scriptObjPtr);
15194 if (!JimScriptValid(interp, script)) {
15195 Jim_DecrRefCount(interp, scriptObjPtr);
15196 return JIM_ERR;
15197 }
@@ -15223,11 +15193,11 @@
15223 }
15224 #endif
15225
15226 script->inUse++;
15227
15228
15229 prevScriptObj = interp->currentScriptObj;
15230 interp->currentScriptObj = scriptObjPtr;
15231
15232 interp->errorFlag = 0;
15233 argv = sargv;
@@ -15234,19 +15204,19 @@
15234
15235 for (i = 0; i < script->len && retcode == JIM_OK; ) {
15236 int argc;
15237 int j;
15238
15239
15240 argc = token[i].objPtr->internalRep.scriptLineValue.argc;
15241 script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
15242
15243
15244 if (argc > JIM_EVAL_SARGV_LEN)
15245 argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
15246
15247
15248 i++;
15249
15250 for (j = 0; j < argc; j++) {
15251 long wordtokens = 1;
15252 int expand = 0;
@@ -15302,11 +15272,11 @@
15302
15303 if (!expand) {
15304 argv[j] = wordObjPtr;
15305 }
15306 else {
15307
15308 int len = Jim_ListLength(interp, wordObjPtr);
15309 int newargc = argc + len - 1;
15310 int k;
15311
15312 if (len > 1) {
@@ -15315,39 +15285,39 @@
15315 argv = Jim_Alloc(sizeof(*argv) * newargc);
15316 memcpy(argv, sargv, sizeof(*argv) * j);
15317 }
15318 }
15319 else {
15320
15321 argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
15322 }
15323 }
15324
15325
15326 for (k = 0; k < len; k++) {
15327 argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
15328 Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
15329 }
15330
15331 Jim_DecrRefCount(interp, wordObjPtr);
15332
15333
15334 j--;
15335 argc += len - 1;
15336 }
15337 }
15338
15339 if (retcode == JIM_OK && argc) {
15340
15341 retcode = JimInvokeCommand(interp, argc, argv);
15342
15343 if (Jim_CheckSignal(interp)) {
15344 retcode = JIM_SIGNAL;
15345 }
15346 }
15347
15348
15349 while (j-- > 0) {
15350 Jim_DecrRefCount(interp, argv[j]);
15351 }
15352
15353 if (argv != sargv) {
@@ -15354,21 +15324,21 @@
15354 Jim_Free(argv);
15355 argv = sargv;
15356 }
15357 }
15358
15359
15360 if (retcode == JIM_ERR) {
15361 JimAddErrorToStack(interp, script);
15362 }
15363
15364 else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15365
15366 interp->addStackTrace = 0;
15367 }
15368
15369
15370 interp->currentScriptObj = prevScriptObj;
15371
15372 Jim_FreeIntRep(interp, scriptObjPtr);
15373 scriptObjPtr->typePtr = &scriptObjType;
15374 Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15348,14 @@
15378 }
15379
15380 static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
15381 {
15382 int retcode;
15383
15384 const char *varname = Jim_String(argNameObj);
15385 if (*varname == '&') {
15386
15387 Jim_Obj *objPtr;
15388 Jim_CallFrame *savedCallFrame = interp->framePtr;
15389
15390 interp->framePtr = interp->framePtr->parent;
15391 objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15362,11 @@
15392 interp->framePtr = savedCallFrame;
15393 if (!objPtr) {
15394 return JIM_ERR;
15395 }
15396
15397
15398 objPtr = Jim_NewStringObj(interp, varname + 1, -1);
15399 Jim_IncrRefCount(objPtr);
15400 retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
15401 Jim_DecrRefCount(interp, objPtr);
15402 }
@@ -15406,26 +15376,26 @@
15406 return retcode;
15407 }
15408
15409 static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
15410 {
15411
15412 Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
15413 int i;
15414
15415 for (i = 0; i < cmd->u.proc.argListLen; i++) {
15416 Jim_AppendString(interp, argmsg, " ", 1);
15417
15418 if (i == cmd->u.proc.argsPos) {
15419 if (cmd->u.proc.arglist[i].defaultObjPtr) {
15420
15421 Jim_AppendString(interp, argmsg, "?", 1);
15422 Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
15423 Jim_AppendString(interp, argmsg, " ...?", -1);
15424 }
15425 else {
15426
15427 Jim_AppendString(interp, argmsg, "?arg...?", -1);
15428 }
15429 }
15430 else {
15431 if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15411,19 @@
15441 Jim_AppendString(interp, argmsg, arg, -1);
15442 }
15443 }
15444 }
15445 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
15446 Jim_FreeNewObj(interp, argmsg);
15447 }
15448
15449 #ifdef jim_ext_namespace
15450 int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
15451 {
15452 Jim_CallFrame *callFramePtr;
15453 int retcode;
15454
15455
15456 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
15457 callFramePtr->argv = &interp->emptyObj;
15458 callFramePtr->argc = 0;
15459 callFramePtr->procArgsObjPtr = NULL;
15460 callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15431,21 @@
15462 callFramePtr->fileNameObj = interp->emptyObj;
15463 callFramePtr->line = 0;
15464 Jim_IncrRefCount(scriptObj);
15465 interp->framePtr = callFramePtr;
15466
15467
15468 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15469 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15470 retcode = JIM_ERR;
15471 }
15472 else {
15473
15474 retcode = Jim_EvalObj(interp, scriptObj);
15475 }
15476
15477
15478 interp->framePtr = interp->framePtr->parent;
15479 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15480
15481 return retcode;
15482 }
@@ -15486,62 +15455,62 @@
15486 {
15487 Jim_CallFrame *callFramePtr;
15488 int i, d, retcode, optargs;
15489 ScriptObj *script;
15490
15491
15492 if (argc - 1 < cmd->u.proc.reqArity ||
15493 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
15494 JimSetProcWrongArgs(interp, argv[0], cmd);
15495 return JIM_ERR;
15496 }
15497
15498 if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15499
15500 return JIM_OK;
15501 }
15502
15503
15504 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15505 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15506 return JIM_ERR;
15507 }
15508
15509
15510 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
15511 callFramePtr->argv = argv;
15512 callFramePtr->argc = argc;
15513 callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
15514 callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
15515 callFramePtr->staticVars = cmd->u.proc.staticVars;
15516
15517
15518 script = JimGetScript(interp, interp->currentScriptObj);
15519 callFramePtr->fileNameObj = script->fileNameObj;
15520 callFramePtr->line = script->linenr;
15521
15522 Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
15523 Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
15524 interp->framePtr = callFramePtr;
15525
15526
15527 optargs = (argc - 1 - cmd->u.proc.reqArity);
15528
15529
15530 i = 1;
15531 for (d = 0; d < cmd->u.proc.argListLen; d++) {
15532 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
15533 if (d == cmd->u.proc.argsPos) {
15534
15535 Jim_Obj *listObjPtr;
15536 int argsLen = 0;
15537 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
15538 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
15539 }
15540 listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
15541
15542
15543 if (cmd->u.proc.arglist[d].defaultObjPtr) {
15544 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
15545 }
15546 retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
15547 if (retcode != JIM_OK) {
@@ -15550,33 +15519,33 @@
15550
15551 i += argsLen;
15552 continue;
15553 }
15554
15555
15556 if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
15557 retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
15558 }
15559 else {
15560
15561 retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
15562 }
15563 if (retcode != JIM_OK) {
15564 goto badargset;
15565 }
15566 }
15567
15568
15569 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15570
15571 badargset:
15572
15573
15574 interp->framePtr = interp->framePtr->parent;
15575 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15576
15577
15578 if (interp->framePtr->tailcallObj) {
15579 do {
15580 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15581
15582 interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15557,18 @@
15588 }
15589 }
15590 Jim_DecrRefCount(interp, tailcallObj);
15591 } while (interp->framePtr->tailcallObj);
15592
15593
15594 if (interp->framePtr->tailcallCmd) {
15595 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15596 interp->framePtr->tailcallCmd = NULL;
15597 }
15598 }
15599
15600
15601 if (retcode == JIM_RETURN) {
15602 if (--interp->returnLevel <= 0) {
15603 retcode = interp->returnCode;
15604 interp->returnCode = JIM_OK;
15605 interp->returnLevel = 0;
@@ -15711,20 +15680,20 @@
15711 prevScriptObj = interp->currentScriptObj;
15712 interp->currentScriptObj = scriptObjPtr;
15713
15714 retcode = Jim_EvalObj(interp, scriptObjPtr);
15715
15716
15717 if (retcode == JIM_RETURN) {
15718 if (--interp->returnLevel <= 0) {
15719 retcode = interp->returnCode;
15720 interp->returnCode = JIM_OK;
15721 interp->returnLevel = 0;
15722 }
15723 }
15724 if (retcode == JIM_ERR) {
15725
15726 interp->addStackTrace++;
15727 }
15728
15729 interp->currentScriptObj = prevScriptObj;
15730
@@ -15750,11 +15719,11 @@
15750 }
15751 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
15752 if (JimParseVar(pc) == JIM_OK) {
15753 return;
15754 }
15755
15756 pc->tstart = pc->p;
15757 flags |= JIM_SUBST_NOVAR;
15758 }
15759 while (pc->len) {
15760 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15750,32 @@
15781 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
15782 struct JimParserCtx parser;
15783 struct ScriptObj *script = Jim_Alloc(sizeof(*script));
15784 ParseTokenList tokenlist;
15785
15786
15787 ScriptTokenListInit(&tokenlist);
15788
15789 JimParserInit(&parser, scriptText, scriptTextLen, 1);
15790 while (1) {
15791 JimParseSubst(&parser, flags);
15792 if (parser.eof) {
15793
15794 break;
15795 }
15796 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
15797 parser.tline);
15798 }
15799
15800
15801 script->inUse = 1;
15802 script->substFlags = flags;
15803 script->fileNameObj = interp->emptyObj;
15804 Jim_IncrRefCount(script->fileNameObj);
15805 SubstObjAddTokens(interp, script, &tokenlist);
15806
15807
15808 ScriptTokenListFree(&tokenlist);
15809
15810 #ifdef DEBUG_SHOW_SUBST
15811 {
15812 int i;
@@ -15817,11 +15786,11 @@
15817 Jim_String(script->token[i].objPtr));
15818 }
15819 }
15820 #endif
15821
15822
15823 Jim_FreeIntRep(interp, objPtr);
15824 Jim_SetIntRepPtr(objPtr, script);
15825 objPtr->typePtr = &scriptObjType;
15826 return JIM_OK;
15827 }
@@ -15835,11 +15804,11 @@
15835
15836 int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
15837 {
15838 ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
15839
15840 Jim_IncrRefCount(substObjPtr);
15841 script->inUse++;
15842
15843 *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
15844
15845 script->inUse--;
@@ -15851,22 +15820,24 @@
15851 }
15852
15853 void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
15854 {
15855 Jim_Obj *objPtr;
15856 Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
 
 
 
 
15857
15858 if (*msg) {
15859 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
15860 }
15861 Jim_IncrRefCount(listObjPtr);
15862 objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
15863 Jim_DecrRefCount(interp, listObjPtr);
15864
15865 Jim_IncrRefCount(objPtr);
15866 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
15867 Jim_DecrRefCount(interp, objPtr);
15868 }
15869
15870 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15871 Jim_HashEntry *he, int type);
15872
@@ -15876,11 +15847,11 @@
15876 JimHashtableIteratorCallbackType *callback, int type)
15877 {
15878 Jim_HashEntry *he;
15879 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
15880
15881
15882 if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
15883 he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
15884 if (he) {
15885 callback(interp, listObjPtr, he, type);
15886 }
@@ -15907,11 +15878,11 @@
15907 {
15908 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15909 Jim_Obj *objPtr;
15910
15911 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15912
15913 return;
15914 }
15915
15916 objPtr = Jim_NewStringObj(interp, he->key, -1);
15917 Jim_IncrRefCount(objPtr);
@@ -15967,11 +15938,11 @@
15967
15968 targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
15969 if (targetCallFrame == NULL) {
15970 return JIM_ERR;
15971 }
15972
15973 if (targetCallFrame == interp->topFramePtr) {
15974 Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
15975 return JIM_ERR;
15976 }
15977 if (info_level_cmd) {
@@ -16154,11 +16125,11 @@
16154 if (!objPtr)
16155 return JIM_ERR;
16156 Jim_SetResult(interp, objPtr);
16157 return JIM_OK;
16158 }
16159
16160 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16161 return JIM_ERR;
16162 Jim_SetResult(interp, argv[2]);
16163 return JIM_OK;
16164 }
@@ -16197,11 +16168,11 @@
16197 if (argc != 3) {
16198 Jim_WrongNumArgs(interp, 1, argv, "condition body");
16199 return JIM_ERR;
16200 }
16201
16202
16203 while (1) {
16204 int boolean, retval;
16205
16206 if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
16207 return retval;
@@ -16237,11 +16208,11 @@
16237 if (argc != 5) {
16238 Jim_WrongNumArgs(interp, 1, argv, "start test next body");
16239 return JIM_ERR;
16240 }
16241
16242
16243 if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
16244 return retval;
16245 }
16246
16247 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16253,19 +16224,19 @@
16253 ExprByteCode *expr;
16254 jim_wide stop, currentVal;
16255 Jim_Obj *objPtr;
16256 int cmpOffset;
16257
16258
16259 expr = JimGetExpression(interp, argv[2]);
16260 incrScript = JimGetScript(interp, argv[3]);
16261
16262
16263 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16264 goto evalstart;
16265 }
16266
16267 if (incrScript->token[1].type != JIM_TT_ESC ||
16268 expr->token[0].type != JIM_TT_VAR ||
16269 (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
16270 goto evalstart;
16271 }
@@ -16278,48 +16249,48 @@
16278 }
16279 else {
16280 goto evalstart;
16281 }
16282
16283
16284 if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
16285 goto evalstart;
16286 }
16287
16288
16289 if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
16290 goto evalstart;
16291 }
16292
16293
16294 if (expr->token[1].type == JIM_TT_EXPR_INT) {
16295 if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
16296 goto evalstart;
16297 }
16298 }
16299 else {
16300 stopVarNamePtr = expr->token[1].objPtr;
16301 Jim_IncrRefCount(stopVarNamePtr);
16302
16303 stop = 0;
16304 }
16305
16306
16307 varNamePtr = expr->token[0].objPtr;
16308 Jim_IncrRefCount(varNamePtr);
16309
16310 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
16311 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
16312 goto testcond;
16313 }
16314
16315
16316 while (retval == JIM_OK) {
16317
16318
16319
16320
 
 
16321 if (stopVarNamePtr) {
16322 objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
16323 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
16324 goto testcond;
16325 }
@@ -16327,18 +16298,18 @@
16327
16328 if (currentVal >= stop + cmpOffset) {
16329 break;
16330 }
16331
16332
16333 retval = Jim_EvalObj(interp, argv[4]);
16334 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16335 retval = JIM_OK;
16336
16337 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
16338
16339
16340 if (objPtr == NULL) {
16341 retval = JIM_ERR;
16342 goto out;
16343 }
16344 if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16329,25 @@
16358 }
16359 evalstart:
16360 #endif
16361
16362 while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16363
16364 retval = Jim_EvalObj(interp, argv[4]);
16365
16366 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16367
16368 evalnext:
16369 retval = Jim_EvalObj(interp, argv[3]);
16370 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16371
16372 testcond:
16373 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
16374 }
16375 }
16376 }
16377 out:
16378 if (stopVarNamePtr) {
16379 Jim_DecrRefCount(interp, stopVarNamePtr);
16380 }
16381 if (varNamePtr) {
16382 Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16389,11 @@
16418 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16419 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
16420
16421 retval = JIM_OK;
16422
16423
16424 i += incr;
16425
16426 if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
16427 if (argv[1]->typePtr != &variableObjType) {
16428 if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16454,21 @@
16483
16484 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16485 {
16486 int result = JIM_OK;
16487 int i, numargs;
16488 Jim_ListIter twoiters[2];
16489 Jim_ListIter *iters;
16490 Jim_Obj *script;
16491 Jim_Obj *resultObj;
16492
16493 if (argc < 4 || argc % 2 != 0) {
16494 Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
16495 return JIM_ERR;
16496 }
16497 script = argv[argc - 1];
16498 numargs = (argc - 1 - 1);
16499
16500 if (numargs == 2) {
16501 iters = twoiters;
16502 }
16503 else {
@@ -16521,34 +16492,34 @@
16521 resultObj = interp->emptyObj;
16522 }
16523 Jim_IncrRefCount(resultObj);
16524
16525 while (1) {
16526
16527 for (i = 0; i < numargs; i += 2) {
16528 if (!JimListIterDone(interp, &iters[i + 1])) {
16529 break;
16530 }
16531 }
16532 if (i == numargs) {
16533
16534 break;
16535 }
16536
16537
16538 for (i = 0; i < numargs; i += 2) {
16539 Jim_Obj *varName;
16540
16541
16542 JimListIterInit(&iters[i], argv[i + 1]);
16543 while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
16544 Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
16545 if (!valObj) {
16546
16547 valObj = interp->emptyObj;
16548 }
16549
16550 Jim_IncrRefCount(valObj);
16551 result = Jim_SetVariable(interp, varName, valObj);
16552 Jim_DecrRefCount(interp, valObj);
16553 if (result != JIM_OK) {
16554 goto err;
@@ -16630,41 +16601,41 @@
16630 {
16631 int boolean, retval, current = 1, falsebody = 0;
16632
16633 if (argc >= 3) {
16634 while (1) {
16635
16636 if (current >= argc)
16637 goto err;
16638 if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
16639 != JIM_OK)
16640 return retval;
16641
16642 if (current >= argc)
16643 goto err;
16644 if (Jim_CompareStringImmediate(interp, argv[current], "then"))
16645 current++;
16646
16647 if (current >= argc)
16648 goto err;
16649 if (boolean)
16650 return Jim_EvalObj(interp, argv[current]);
16651
16652 if (++current >= argc) {
16653 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
16654 return JIM_OK;
16655 }
16656 falsebody = current++;
16657 if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16658
16659 if (current != argc - 1)
16660 goto err;
16661 return Jim_EvalObj(interp, argv[current]);
16662 }
16663 else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
16664 continue;
16665
16666 else if (falsebody != argc - 1)
16667 goto err;
16668 return Jim_EvalObj(interp, argv[falsebody]);
16669 }
16670 return JIM_OK;
@@ -16772,21 +16743,21 @@
16772 if (Jim_StringMatchObj(interp, patObj, strObj, 0))
16773 script = caseList[i + 1];
16774 break;
16775 case SWITCH_RE:
16776 command = Jim_NewStringObj(interp, "regexp", -1);
16777
16778 case SWITCH_CMD:{
16779 int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
16780
16781 if (argc - opt == 1) {
16782 Jim_Obj **vector;
16783
16784 JimListGetElements(interp, argv[opt], &patCount, &vector);
16785 caseList = vector;
16786 }
16787
16788 if (rc < 0) {
16789 return -rc;
16790 }
16791 if (rc)
16792 script = caseList[i + 1];
@@ -16920,11 +16891,11 @@
16920 case OPT_COMMAND:
16921 if (i >= argc - 2) {
16922 goto wrongargs;
16923 }
16924 commandObj = argv[++i];
16925
16926 case OPT_EXACT:
16927 case OPT_GLOB:
16928 case OPT_REGEXP:
16929 opt_match = option;
16930 break;
@@ -16968,17 +16939,17 @@
16968 goto done;
16969 }
16970 break;
16971 }
16972
16973
16974 if (!eq && opt_bool && opt_not && !opt_all) {
16975 continue;
16976 }
16977
16978 if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16979
16980 Jim_Obj *resultObj;
16981
16982 if (opt_bool) {
16983 resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
16984 }
@@ -17001,11 +16972,11 @@
17001
17002 if (opt_all) {
17003 Jim_SetResult(interp, listObjPtr);
17004 }
17005 else {
17006
17007 if (opt_bool) {
17008 Jim_SetResultBool(interp, opt_not);
17009 }
17010 else if (!opt_inline) {
17011 Jim_SetResultInt(interp, -1);
@@ -17030,11 +17001,11 @@
17030 Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
17031 return JIM_ERR;
17032 }
17033 listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17034 if (!listObjPtr) {
17035
17036 listObjPtr = Jim_NewListObj(interp, NULL, 0);
17037 new_obj = 1;
17038 }
17039 else if (Jim_IsShared(listObjPtr)) {
17040 listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +17074,31 @@
17103 first = JimRelToAbsIndex(len, first);
17104 last = JimRelToAbsIndex(len, last);
17105 JimRelToAbsRange(len, &first, &last, &rangeLen);
17106
17107
17108
17109 if (first < len) {
17110
17111 }
17112 else if (len == 0) {
17113
17114 first = 0;
17115 }
17116 else {
17117 Jim_SetResultString(interp, "list doesn't contain element ", -1);
17118 Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
17119 return JIM_ERR;
17120 }
17121
17122
17123 newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
17124
17125
17126 ListInsertElements(newListObj, -1, argc - 4, argv + 4);
17127
17128
17129 ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
17130
17131 Jim_SetResult(interp, newListObj);
17132 return JIM_OK;
17133 }
@@ -17138,11 +17109,11 @@
17138 if (argc < 3) {
17139 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
17140 return JIM_ERR;
17141 }
17142 else if (argc == 3) {
17143
17144 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
17145 return JIM_ERR;
17146 Jim_SetResult(interp, argv[2]);
17147 return JIM_OK;
17148 }
@@ -17253,11 +17224,11 @@
17253 }
17254 else {
17255 int new_obj = 0;
17256 stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17257 if (!stringObjPtr) {
17258
17259 stringObjPtr = Jim_NewEmptyStringObj(interp);
17260 new_obj = 1;
17261 }
17262 else if (Jim_IsShared(stringObjPtr)) {
17263 new_obj = 1;
@@ -17302,11 +17273,11 @@
17302 else {
17303 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
17304 }
17305
17306 if (rc == JIM_ERR) {
17307
17308 interp->addStackTrace++;
17309 }
17310 return rc;
17311 }
17312
@@ -17316,14 +17287,14 @@
17316 if (argc >= 2) {
17317 int retcode;
17318 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17319 const char *str;
17320
17321
17322 savedCallFrame = interp->framePtr;
17323
17324
17325 str = Jim_String(argv[1]);
17326 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17327 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17328 argc--;
17329 argv++;
@@ -17336,11 +17307,11 @@
17336 }
17337 if (argc < 2) {
17338 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
17339 return JIM_ERR;
17340 }
17341
17342 interp->framePtr = targetCallFrame;
17343 if (argc == 2) {
17344 retcode = Jim_EvalObj(interp, argv[1]);
17345 }
17346 else {
@@ -17438,15 +17409,15 @@
17438 if (i != argc - 1 && i != argc) {
17439 Jim_WrongNumArgs(interp, 1, argv,
17440 "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
17441 }
17442
17443
17444 if (stackTraceObj && returnCode == JIM_ERR) {
17445 JimSetStackTrace(interp, stackTraceObj);
17446 }
17447
17448 if (errorCodeObj && returnCode == JIM_ERR) {
17449 Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
17450 }
17451 interp->returnCode = returnCode;
17452 interp->returnLevel = level;
@@ -17463,31 +17434,31 @@
17463 if (interp->framePtr->level == 0) {
17464 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17465 return JIM_ERR;
17466 }
17467 else if (argc >= 2) {
17468
17469 Jim_CallFrame *cf = interp->framePtr->parent;
17470
17471 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17472 if (cmdPtr == NULL) {
17473 return JIM_ERR;
17474 }
17475
17476 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17477
17478
17479 JimIncrCmdRefCount(cmdPtr);
17480 cf->tailcallCmd = cmdPtr;
17481
17482
17483 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17484
17485 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17486 Jim_IncrRefCount(cf->tailcallObj);
17487
17488
17489 return JIM_EVAL;
17490 }
17491 return JIM_OK;
17492 }
17493
@@ -17494,11 +17465,11 @@
17494 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17495 {
17496 Jim_Obj *cmdList;
17497 Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
17498
17499
17500 cmdList = Jim_DuplicateObj(interp, prefixListObj);
17501 Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
17502
17503 return JimEvalObjList(interp, cmdList);
17504 }
@@ -17552,22 +17523,22 @@
17552 else {
17553 cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
17554 }
17555
17556 if (cmd) {
17557
17558 Jim_Obj *qualifiedCmdNameObj;
17559 const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
17560
17561 JimCreateCommand(interp, cmdname, cmd);
17562
17563
17564 JimUpdateProcNamespace(interp, cmd, cmdname);
17565
17566 JimFreeQualifiedName(interp, qualifiedCmdNameObj);
17567
17568
17569 Jim_SetResult(interp, argv[1]);
17570 return JIM_OK;
17571 }
17572 return JIM_ERR;
17573 }
@@ -17580,17 +17551,17 @@
17580 if (argc < 2) {
17581 Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17582 return JIM_ERR;
17583 }
17584
17585
17586 interp->local++;
17587 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17588 interp->local--;
17589
17590
17591
17592 if (retcode == 0) {
17593 Jim_Obj *cmdNameObj = Jim_GetResult(interp);
17594
17595 if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
17596 return JIM_ERR;
@@ -17619,18 +17590,18 @@
17619 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17620 if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
17621 Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
17622 return JIM_ERR;
17623 }
17624
17625 cmdPtr->u.proc.upcall++;
17626 JimIncrCmdRefCount(cmdPtr);
17627
17628
17629 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17630
17631
17632 cmdPtr->u.proc.upcall--;
17633 JimDecrCmdRefCount(interp, cmdPtr);
17634
17635 return retcode;
17636 }
@@ -17657,11 +17628,11 @@
17657 return JIM_ERR;
17658 }
17659
17660 if (len == 3) {
17661 #ifdef jim_ext_namespace
17662
17663 nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
17664 #else
17665 Jim_SetResultString(interp, "namespaces not enabled", -1);
17666 return JIM_ERR;
17667 #endif
@@ -17670,11 +17641,11 @@
17670 bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
17671
17672 cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
17673
17674 if (cmd) {
17675
17676 nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
17677 nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
17678 Jim_IncrRefCount(nargv[0]);
17679 memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
17680 ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17671,11 @@
17700 static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17701 {
17702 int i;
17703 Jim_CallFrame *targetCallFrame;
17704
17705
17706 if (argc > 3 && (argc % 2 == 0)) {
17707 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17708 argc--;
17709 argv++;
17710 }
@@ -17713,17 +17684,17 @@
17713 }
17714 if (targetCallFrame == NULL) {
17715 return JIM_ERR;
17716 }
17717
17718
17719 if (argc < 3) {
17720 Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
17721 return JIM_ERR;
17722 }
17723
17724
17725 for (i = 1; i < argc; i += 2) {
17726 if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
17727 return JIM_ERR;
17728 }
17729 return JIM_OK;
@@ -17736,15 +17707,15 @@
17736
17737 if (argc < 2) {
17738 Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
17739 return JIM_ERR;
17740 }
17741
17742 if (interp->framePtr->level == 0)
17743 return JIM_OK;
17744 for (i = 1; i < argc; i++) {
17745
17746 const char *name = Jim_String(argv[i]);
17747 if (name[0] != ':' || name[1] != ':') {
17748 if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
17749 return JIM_ERR;
17750 }
@@ -17767,21 +17738,21 @@
17767 }
17768
17769 str = Jim_String(objPtr);
17770 strLen = Jim_Utf8Length(interp, objPtr);
17771
17772
17773 resultObjPtr = Jim_NewStringObj(interp, "", 0);
17774 while (strLen) {
17775 for (i = 0; i < numMaps; i += 2) {
17776 Jim_Obj *objPtr;
17777 const char *k;
17778 int kl;
17779
17780 objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17781 k = Jim_String(objPtr);
17782 kl = Jim_Utf8Length(interp, objPtr);
17783
17784 if (strLen >= kl && kl) {
17785 int rc;
17786 rc = JimStringCompareLen(str, k, kl, nocase);
17787 if (rc == 0) {
@@ -17794,11 +17765,11 @@
17794 strLen -= kl;
17795 break;
17796 }
17797 }
17798 }
17799 if (i == numMaps) {
17800 int c;
17801 if (noMatchStart == NULL)
17802 noMatchStart = str;
17803 str += utf8_tounicode(str, &c);
17804 strLen--;
@@ -17838,11 +17809,11 @@
17838 Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
17839 return JIM_ERR;
17840 }
17841 if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
17842 JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17843 return JIM_ERR;
17844
17845 switch (option) {
17846 case OPT_LENGTH:
17847 case OPT_BYTELENGTH:
17848 if (argc != 3) {
@@ -17859,11 +17830,11 @@
17859 return JIM_OK;
17860
17861 case OPT_CAT:{
17862 Jim_Obj *objPtr;
17863 if (argc == 3) {
17864
17865 objPtr = argv[2];
17866 }
17867 else {
17868 int i;
17869
@@ -17878,11 +17849,11 @@
17878 }
17879
17880 case OPT_COMPARE:
17881 case OPT_EQUAL:
17882 {
17883
17884 long opt_length = -1;
17885 int n = argc - 4;
17886 int i = 2;
17887 while (n > 0) {
17888 int subopt;
@@ -17891,16 +17862,16 @@
17891 badcompareargs:
17892 Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
17893 return JIM_ERR;
17894 }
17895 if (subopt == 0) {
17896
17897 opt_case = 0;
17898 n--;
17899 }
17900 else {
17901
17902 if (n < 2) {
17903 goto badcompareargs;
17904 }
17905 if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
17906 return JIM_ERR;
@@ -17911,11 +17882,11 @@
17911 if (n) {
17912 goto badcompareargs;
17913 }
17914 argv += argc - 2;
17915 if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17916
17917 Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
17918 }
17919 else {
17920 if (opt_length >= 0) {
17921 n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17996,10 @@
18025 }
18026
18027 case OPT_REVERSE:{
18028 char *buf, *p;
18029 const char *str;
18030 int len;
18031 int i;
18032
18033 if (argc != 3) {
18034 Jim_WrongNumArgs(interp, 2, argv, "string");
18035 return JIM_ERR;
@@ -18069,11 +18039,11 @@
18069 }
18070 if (idx < 0 || idx >= len || str == NULL) {
18071 Jim_SetResultString(interp, "", 0);
18072 }
18073 else if (len == Jim_Length(argv[2])) {
18074
18075 Jim_SetResultString(interp, str + idx, 1);
18076 }
18077 else {
18078 int c;
18079 int i = utf8_index(str, idx);
@@ -18223,11 +18193,11 @@
18223 {
18224 int exitCode = 0;
18225 int i;
18226 int sig = 0;
18227
18228
18229 jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
18230 static const int max_ignore_code = sizeof(ignore_mask) * 8;
18231
18232 Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
18233
@@ -18234,11 +18204,11 @@
18234 for (i = 1; i < argc - 1; i++) {
18235 const char *arg = Jim_String(argv[i]);
18236 jim_wide option;
18237 int ignore;
18238
18239
18240 if (strcmp(arg, "--") == 0) {
18241 i++;
18242 break;
18243 }
18244 if (*arg != '-') {
@@ -18285,28 +18255,28 @@
18285 sig++;
18286 }
18287
18288 interp->signal_level += sig;
18289 if (Jim_CheckSignal(interp)) {
18290
18291 exitCode = JIM_SIGNAL;
18292 }
18293 else {
18294 exitCode = Jim_EvalObj(interp, argv[0]);
18295
18296 interp->errorFlag = 0;
18297 }
18298 interp->signal_level -= sig;
18299
18300
18301 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18302
18303 return exitCode;
18304 }
18305
18306 if (sig && exitCode == JIM_SIGNAL) {
18307
18308 if (interp->signal_set_result) {
18309 interp->signal_set_result(interp, interp->sigmask);
18310 }
18311 else {
18312 Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18315,10 @@
18345 }
18346 Jim_SetResultInt(interp, exitCode);
18347 return JIM_OK;
18348 }
18349
18350 #ifdef JIM_REFERENCES
18351
18352
18353 static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18354 {
18355 if (argc != 3 && argc != 4) {
18356 Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?");
18357 return JIM_ERR;
18358 }
18359 if (argc == 3) {
18360 Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL));
18361 }
18362 else {
18363 Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3]));
18364 }
18365 return JIM_OK;
18366 }
18367
18368
18369 static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18370 {
18371 Jim_Reference *refPtr;
18372
18373 if (argc != 2) {
18374 Jim_WrongNumArgs(interp, 1, argv, "reference");
18375 return JIM_ERR;
18376 }
18377 if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18378 return JIM_ERR;
18379 Jim_SetResult(interp, refPtr->objPtr);
18380 return JIM_OK;
18381 }
18382
18383
18384 static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18385 {
18386 Jim_Reference *refPtr;
18387
18388 if (argc != 3) {
18389 Jim_WrongNumArgs(interp, 1, argv, "reference newValue");
18390 return JIM_ERR;
18391 }
18392 if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
18393 return JIM_ERR;
18394 Jim_IncrRefCount(argv[2]);
18395 Jim_DecrRefCount(interp, refPtr->objPtr);
18396 refPtr->objPtr = argv[2];
18397 Jim_SetResult(interp, argv[2]);
18398 return JIM_OK;
18399 }
18400
18401
18402 static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18403 {
18404 if (argc != 1) {
18405 Jim_WrongNumArgs(interp, 1, argv, "");
18406 return JIM_ERR;
18407 }
18408 Jim_SetResultInt(interp, Jim_Collect(interp));
18409
18410
18411 while (interp->freeList) {
18412 Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
18413 Jim_Free(interp->freeList);
18414 interp->freeList = nextObjPtr;
18415 }
18416
18417 return JIM_OK;
18418 }
18419
18420
18421 static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18422 {
18423 if (argc != 2 && argc != 3) {
18424 Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?");
18425 return JIM_ERR;
18426 }
18427 if (argc == 2) {
18428 Jim_Obj *cmdNamePtr;
18429
18430 if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
18431 return JIM_ERR;
18432 if (cmdNamePtr != NULL)
18433 Jim_SetResult(interp, cmdNamePtr);
18434 }
18435 else {
18436 if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK)
18437 return JIM_ERR;
18438 Jim_SetResult(interp, argv[2]);
18439 }
18440 return JIM_OK;
18441 }
18442
18443
18444 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18445 {
18446 Jim_Obj *listObjPtr;
18447 Jim_HashTableIterator htiter;
18448 Jim_HashEntry *he;
18449
18450 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18451
18452 JimInitHashTableIterator(&interp->references, &htiter);
18453 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18454 char buf[JIM_REFERENCE_SPACE + 1];
18455 Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18456 const unsigned long *refId = he->key;
18457
18458 JimFormatReference(buf, refPtr, *refId);
18459 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18460 }
18461 Jim_SetResult(interp, listObjPtr);
18462 return JIM_OK;
18463 }
18464 #endif
18465
18466
18467 static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18468 {
18469 if (argc != 3) {
@@ -18476,56 +18331,43 @@
18476 }
18477
18478 return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
18479 }
18480
18481 #define JIM_DICTMATCH_VALUES 0x0001
18482
18483 typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
18484
18485 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18486 {
18487 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18488 if (type & JIM_DICTMATCH_VALUES) {
18489 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18490 }
18491 }
18492
18493 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18494 JimDictMatchCallbackType *callback, int type)
18495 {
18496 Jim_HashEntry *he;
18497 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18498
18499
18500 Jim_HashTableIterator htiter;
18501 JimInitHashTableIterator(ht, &htiter);
18502 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18503 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18504 callback(interp, listObjPtr, he, type);
18505 }
18506 }
18507
18508 return listObjPtr;
18509 }
18510
18511
18512 int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18513 {
18514 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18515 return JIM_ERR;
18516 }
18517 Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
18518 return JIM_OK;
18519 }
18520
18521 int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
18522 {
18523 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18524 return JIM_ERR;
18525 }
18526 Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
18527 return JIM_OK;
18528 }
18529
18530 int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
18531 {
@@ -18532,38 +18374,85 @@
18532 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18533 return -1;
18534 }
18535 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18536 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18537
18538 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18539 {
18540 Jim_HashTable *ht;
18541 unsigned int i;
 
 
 
 
 
18542
18543 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18544 return JIM_ERR;
18545 }
18546
18547 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18548
18549
18550 printf("%d entries in table, %d buckets\n", ht->used, ht->size);
 
18551
18552 for (i = 0; i < ht->size; i++) {
18553 Jim_HashEntry *he = ht->table[i];
18554
18555 if (he) {
18556 printf("%d: ", i);
18557
18558 while (he) {
18559 printf(" %s", Jim_String(he->key));
18560 he = he->next;
18561 }
18562 printf("\n");
 
 
 
 
 
18563 }
18564 }
 
 
 
 
 
 
 
 
 
18565 return JIM_OK;
18566 }
18567
18568 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18569 {
@@ -18573,14 +18462,67 @@
18573 Jim_AppendString(interp, prefixObj, subcmd, -1);
18574
18575 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18576 }
18577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18578
18579 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18580 {
18581 Jim_Obj *objPtr;
 
18582 int option;
18583 static const char * const options[] = {
18584 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18585 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18586 "replace", "update", NULL
@@ -18596,11 +18538,11 @@
18596 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18597 return JIM_ERR;
18598 }
18599
18600 if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18601 return JIM_ERR;
18602 }
18603
18604 switch (option) {
18605 case OPT_GET:
18606 if (argc < 3) {
@@ -18643,16 +18585,19 @@
18643 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18644 return JIM_ERR;
18645 }
18646 return JIM_OK;
18647
 
 
 
18648 case OPT_KEYS:
18649 if (argc != 3 && argc != 4) {
18650 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18651 return JIM_ERR;
18652 }
18653 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18654
18655 case OPT_SIZE:
18656 if (argc != 3) {
18657 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18658 return JIM_ERR;
@@ -18665,19 +18610,20 @@
18665
18666 case OPT_MERGE:
18667 if (argc == 2) {
18668 return JIM_OK;
18669 }
18670 if (Jim_DictSize(interp, argv[2]) < 0) {
 
18671 return JIM_ERR;
18672 }
18673
18674 break;
18675
18676 case OPT_UPDATE:
18677 if (argc < 6 || argc % 2) {
18678
18679 argc = 2;
18680 }
18681 break;
18682
18683 case OPT_CREATE:
@@ -18693,12 +18639,19 @@
18693 if (argc != 3) {
18694 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18695 return JIM_ERR;
18696 }
18697 return Jim_DictInfo(interp, argv[2]);
 
 
 
 
 
 
 
18698 }
18699
18700 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18701 }
18702
18703
18704 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18717,11 @@
18764
18765 #ifdef jim_ext_namespace
18766 int nons = 0;
18767
18768 if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18769
18770 argc--;
18771 argv++;
18772 nons = 1;
18773 }
18774 #endif
@@ -18775,16 +18728,15 @@
18775
18776 if (argc < 2) {
18777 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
18778 return JIM_ERR;
18779 }
18780 if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV)
18781 != JIM_OK) {
18782 return JIM_ERR;
18783 }
18784
18785
18786 switch (cmd) {
18787 case INFO_EXISTS:
18788 if (argc != 3) {
18789 Jim_WrongNumArgs(interp, 2, argv, "varName");
18790 return JIM_ERR;
@@ -18809,21 +18761,21 @@
18809 Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
18810 return JIM_OK;
18811 }
18812
18813 case INFO_CHANNELS:
18814 mode++;
18815 #ifndef jim_ext_aio
18816 Jim_SetResultString(interp, "aio not enabled", -1);
18817 return JIM_ERR;
18818 #endif
18819
18820 case INFO_PROCS:
18821 mode++;
18822
18823 case INFO_COMMANDS:
18824
18825 if (argc != 2 && argc != 3) {
18826 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18827 return JIM_ERR;
18828 }
18829 #ifdef jim_ext_namespace
@@ -18835,17 +18787,17 @@
18835 #endif
18836 Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
18837 break;
18838
18839 case INFO_VARS:
18840 mode++;
18841
18842 case INFO_LOCALS:
18843 mode++;
18844
18845 case INFO_GLOBALS:
18846
18847 if (argc != 2 && argc != 3) {
18848 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18849 return JIM_ERR;
18850 }
18851 #ifdef jim_ext_namespace
@@ -18951,13 +18903,12 @@
18951 case INFO_ARGS:
18952 Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
18953 break;
18954 case INFO_STATICS:
18955 if (cmdPtr->u.proc.staticVars) {
18956 int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
18957 Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18958 NULL, JimVariablesMatch, mode));
18959 }
18960 break;
18961 }
18962 break;
18963 }
@@ -18985,15 +18936,15 @@
18985 }
18986 }
18987 break;
18988
18989 case INFO_HOSTNAME:
18990
18991 return Jim_Eval(interp, "os.gethostname");
18992
18993 case INFO_NAMEOFEXECUTABLE:
18994
18995 return Jim_Eval(interp, "{info nameofexecutable}");
18996
18997 case INFO_RETURNCODES:
18998 if (argc == 2) {
18999 int i;
@@ -19070,11 +19021,11 @@
19070
19071 if (option == OPT_VAR) {
19072 result = Jim_GetVariable(interp, objPtr, 0) != NULL;
19073 }
19074 else {
19075
19076 Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
19077
19078 if (cmd) {
19079 switch (option) {
19080 case OPT_COMMAND:
@@ -19113,11 +19064,11 @@
19113 if (len == 0) {
19114 return JIM_OK;
19115 }
19116 strLen = Jim_Utf8Length(interp, argv[1]);
19117
19118
19119 if (argc == 2) {
19120 splitChars = " \n\t\r";
19121 splitLen = 4;
19122 }
19123 else {
@@ -19126,11 +19077,11 @@
19126 }
19127
19128 noMatchStart = str;
19129 resObjPtr = Jim_NewListObj(interp, NULL, 0);
19130
19131
19132 if (splitLen) {
19133 Jim_Obj *objPtr;
19134 while (strLen--) {
19135 const char *sc = splitChars;
19136 int scLen = splitLen;
@@ -19155,11 +19106,11 @@
19155 #define NUM_COMMON (128 - 9)
19156 while (strLen--) {
19157 int n = utf8_tounicode(str, &c);
19158 #ifdef JIM_OPTIMIZATION
19159 if (c >= 9 && c < 128) {
19160
19161 c -= 9;
19162 if (!commonObj) {
19163 commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
19164 memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
19165 }
@@ -19189,11 +19140,11 @@
19189
19190 if (argc != 2 && argc != 3) {
19191 Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
19192 return JIM_ERR;
19193 }
19194
19195 if (argc == 2) {
19196 joinStr = " ";
19197 joinStrLen = 1;
19198 }
19199 else {
@@ -19468,13 +19419,13 @@
19468 return -1;
19469 else if (step < 0 && end > start)
19470 return -1;
19471 len = end - start;
19472 if (len < 0)
19473 len = -len;
19474 if (step < 0)
19475 step = -step;
19476 len = 1 + ((len - 1) / step);
19477 if (len > INT_MAX)
19478 len = INT_MAX;
19479 return (int)((len < 0) ? -1 : len);
19480 }
@@ -19644,40 +19595,68 @@
19644 argv[1] = interp->result;
19645
19646 Jim_EvalObjVector(interp, 2, argv);
19647 }
19648
19649 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19650 const char *prefix, const char *const *tablePtr, const char *name)
19651 {
19652 int count;
19653 char **tablePtrSorted;
19654 int i;
19655
19656 for (count = 0; tablePtr[count]; count++) {
19657 }
19658
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19659 if (name == NULL) {
19660 name = "option";
19661 }
19662
19663 Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19664 tablePtrSorted = Jim_Alloc(sizeof(char *) * count);
19665 memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19666 qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19667 for (i = 0; i < count; i++) {
19668 if (i + 1 == count && count > 1) {
19669 Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
19670 }
19671 Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19672 if (i + 1 != count) {
19673 Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
19674 }
19675 }
19676 Jim_Free(tablePtrSorted);
19677 }
19678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19679 int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
19680 const char *const *tablePtr, int *indexPtr, const char *name, int flags)
19681 {
19682 const char *bad = "bad ";
19683 const char *const *entryPtr = NULL;
@@ -19688,11 +19667,11 @@
19688
19689 *indexPtr = -1;
19690
19691 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
19692 if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19693
19694 *indexPtr = i;
19695 return JIM_OK;
19696 }
19697 if (flags & JIM_ENUM_ABBREV) {
19698 if (strncmp(arg, *entryPtr, arglen) == 0) {
@@ -19706,11 +19685,11 @@
19706 match = i;
19707 }
19708 }
19709 }
19710
19711
19712 if (match >= 0) {
19713 *indexPtr = match;
19714 return JIM_OK;
19715 }
19716
@@ -19743,15 +19722,17 @@
19743 return objPtr->typePtr == &listObjType;
19744 }
19745
19746 void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
19747 {
19748
19749 int len = strlen(format);
19750 int extra = 0;
19751 int n = 0;
19752 const char *params[5];
 
 
19753 char *buf;
19754 va_list args;
19755 int i;
19756
19757 va_start(args, format);
@@ -19766,10 +19747,12 @@
19766 }
19767 else if (strncmp(format + i, "%#s", 3) == 0) {
19768 Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
19769
19770 params[n] = Jim_GetString(objPtr, &l);
 
 
19771 }
19772 else {
19773 if (format[i] == '%') {
19774 i++;
19775 }
@@ -19784,10 +19767,14 @@
19784 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19785
19786 va_end(args);
19787
19788 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
 
 
 
 
19789 }
19790
19791
19792 #ifndef jim_ext_package
19793 int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19795,11 @@
19808 #include <string.h>
19809
19810
19811 static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19812 {
19813
19814 return JIM_OK;
19815 }
19816
19817 static const jim_subcmd_type dummy_subcmd = {
19818 "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19887,43 +19874,43 @@
19887 return 0;
19888 }
19889
19890 cmd = argv[1];
19891
19892
19893 if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
19894 if (argc == 2) {
19895
19896 show_cmd_usage(interp, command_table, argc, argv);
19897 return &dummy_subcmd;
19898 }
19899 help = 1;
19900
19901
19902 cmd = argv[2];
19903 }
19904
19905
19906 if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19907
19908 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19909 add_commands(interp, command_table, " ");
19910 return &dummy_subcmd;
19911 }
19912
19913 cmdstr = Jim_GetString(cmd, &cmdlen);
19914
19915 for (ct = command_table; ct->cmd; ct++) {
19916 if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19917
19918 break;
19919 }
19920 if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
19921 if (partial) {
19922
19923 if (help) {
19924
19925 show_cmd_usage(interp, command_table, argc, argv);
19926 return &dummy_subcmd;
19927 }
19928 bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
19929 return 0;
@@ -19931,44 +19918,44 @@
19931 partial = ct;
19932 }
19933 continue;
19934 }
19935
19936
19937 if (partial && !ct->cmd) {
19938 ct = partial;
19939 }
19940
19941 if (!ct->cmd) {
19942
19943 if (help) {
19944
19945 show_cmd_usage(interp, command_table, argc, argv);
19946 return &dummy_subcmd;
19947 }
19948 bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
19949 return 0;
19950 }
19951
19952 if (help) {
19953 Jim_SetResultString(interp, "Usage: ", -1);
19954
19955 add_cmd_usage(interp, ct, argv[0]);
19956 return &dummy_subcmd;
19957 }
19958
19959
19960 if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
19961 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19962
19963 add_cmd_usage(interp, ct, argv[0]);
19964 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19965
19966 return 0;
19967 }
19968
19969
19970 return ct;
19971 }
19972
19973 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
19974 {
@@ -20019,11 +20006,11 @@
20019 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
20020 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20021 *p = 0x80 | (uc & 0x3f);
20022 return 3;
20023 }
20024
20025 else {
20026 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
20027 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
20028 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20029 *p = 0x80 | (uc & 0x3f);
@@ -20210,11 +20197,11 @@
20210 if (ch == 'h') {
20211 useShort = 1;
20212 format += step;
20213 step = utf8_tounicode(format, &ch);
20214 } else if (ch == 'l') {
20215
20216 format += step;
20217 step = utf8_tounicode(format, &ch);
20218 if (ch == 'l') {
20219 format += step;
20220 step = utf8_tounicode(format, &ch);
@@ -20237,11 +20224,11 @@
20237 goto errorMsg;
20238 case 's': {
20239 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
20240 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
20241 if (gotPrecision && (precision < formatted_chars)) {
20242
20243 formatted_chars = precision;
20244 formatted_bytes = utf8_index(formatted_buf, precision);
20245 }
20246 break;
20247 }
@@ -20249,11 +20236,11 @@
20249 jim_wide code;
20250
20251 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20252 goto error;
20253 }
20254
20255 formatted_bytes = utf8_getchars(spec, code);
20256 formatted_buf = spec;
20257 formatted_chars = 1;
20258 break;
20259 }
@@ -20267,11 +20254,11 @@
20267 goto error;
20268 }
20269 length = sizeof(w) * 8;
20270
20271
20272
20273 if (num_buffer_size < length + 1) {
20274 num_buffer_size = length + 1;
20275 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20276 }
20277
@@ -20295,29 +20282,29 @@
20295 case 'E':
20296 case 'f':
20297 case 'g':
20298 case 'G':
20299 doubleType = 1;
20300
20301 case 'd':
20302 case 'u':
20303 case 'o':
20304 case 'x':
20305 case 'X': {
20306 jim_wide w;
20307 double d;
20308 int length;
20309
20310
20311 if (width) {
20312 p += sprintf(p, "%ld", width);
20313 }
20314 if (gotPrecision) {
20315 p += sprintf(p, ".%ld", precision);
20316 }
20317
20318
20319 if (doubleType) {
20320 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20321 goto error;
20322 }
20323 length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20331,19 @@
20344 }
20345
20346 *p++ = (char) ch;
20347 *p = '\0';
20348
20349
20350 if (width > length) {
20351 length = width;
20352 }
20353 if (gotPrecision) {
20354 length += precision;
20355 }
20356
20357
20358 if (num_buffer_size < length + 1) {
20359 num_buffer_size = length + 1;
20360 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20361 }
20362
@@ -20370,11 +20357,11 @@
20370 formatted_buf = num_buffer;
20371 break;
20372 }
20373
20374 default: {
20375
20376 spec[0] = ch;
20377 spec[1] = '\0';
20378 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20379 goto error;
20380 }
@@ -20422,37 +20409,37 @@
20422
20423 #define REG_MAX_PAREN 100
20424
20425
20426
20427 #define END 0
20428 #define BOL 1
20429 #define EOL 2
20430 #define ANY 3
20431 #define ANYOF 4
20432 #define ANYBUT 5
20433 #define BRANCH 6
20434 #define BACK 7
20435 #define EXACTLY 8
20436 #define NOTHING 9
20437 #define REP 10
20438 #define REPMIN 11
20439 #define REPX 12
20440 #define REPXMIN 13
20441 #define BOLX 14
20442 #define EOLX 15
20443 #define WORDA 16
20444 #define WORDZ 17
20445
20446 #define OPENNC 1000
20447 #define OPEN 1001
20448
20449
20450
20451
20452 #define CLOSENC 2000
20453 #define CLOSE 2001
20454 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
20455
20456 #define REG_MAGIC 0xFADED00D
20457
20458
@@ -20465,18 +20452,18 @@
20465
20466 #define FAIL(R,M) { (R)->err = (M); return (M); }
20467 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20468 #define META "^$.[()|?{+*"
20469
20470 #define HASWIDTH 1
20471 #define SIMPLE 2
20472 #define SPSTART 4
20473 #define WORST 0
20474
20475 #define MAX_REP_COUNT 1000000
20476
20477 static int reg(regex_t *preg, int paren , int *flagp );
20478 static int regpiece(regex_t *preg, int *flagp );
20479 static int regbranch(regex_t *preg, int *flagp );
20480 static int regatom(regex_t *preg, int *flagp );
20481 static int regnode(regex_t *preg, int op );
20482 static int regnext(regex_t *preg, int p );
@@ -20520,15 +20507,15 @@
20520 memset(preg, 0, sizeof(*preg));
20521
20522 if (exp == NULL)
20523 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20524
20525
20526 preg->cflags = cflags;
20527 preg->regparse = exp;
20528
20529
20530 preg->proglen = (strlen(exp) + 1) * 5;
20531 preg->program = malloc(preg->proglen * sizeof(int));
20532 if (preg->program == NULL)
20533 FAIL(preg, REG_ERR_NOMEM);
20534
@@ -20535,24 +20522,24 @@
20535 regc(preg, REG_MAGIC);
20536 if (reg(preg, 0, &flags) == 0) {
20537 return preg->err;
20538 }
20539
20540
20541 if (preg->re_nsub >= REG_MAX_PAREN)
20542 FAIL(preg,REG_ERR_TOO_BIG);
20543
20544
20545 preg->regstart = 0;
20546 preg->reganch = 0;
20547 preg->regmust = 0;
20548 preg->regmlen = 0;
20549 scan = 1;
20550 if (OP(preg, regnext(preg, scan)) == END) {
20551 scan = OPERAND(scan);
20552
20553
20554 if (OP(preg, scan) == EXACTLY) {
20555 preg->regstart = preg->program[OPERAND(scan)];
20556 }
20557 else if (OP(preg, scan) == BOL)
20558 preg->reganch++;
@@ -20579,24 +20566,24 @@
20579 #endif
20580
20581 return 0;
20582 }
20583
20584 static int reg(regex_t *preg, int paren , int *flagp )
20585 {
20586 int ret;
20587 int br;
20588 int ender;
20589 int parno = 0;
20590 int flags;
20591
20592 *flagp = HASWIDTH;
20593
20594
20595 if (paren) {
20596 if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20597
20598 preg->regparse += 2;
20599 parno = -1;
20600 }
20601 else {
20602 parno = ++preg->re_nsub;
@@ -20603,16 +20590,16 @@
20603 }
20604 ret = regnode(preg, OPEN+parno);
20605 } else
20606 ret = 0;
20607
20608
20609 br = regbranch(preg, &flags);
20610 if (br == 0)
20611 return 0;
20612 if (ret != 0)
20613 regtail(preg, ret, br);
20614 else
20615 ret = br;
20616 if (!(flags&HASWIDTH))
20617 *flagp &= ~HASWIDTH;
20618 *flagp |= flags&SPSTART;
@@ -20619,25 +20606,25 @@
20619 while (*preg->regparse == '|') {
20620 preg->regparse++;
20621 br = regbranch(preg, &flags);
20622 if (br == 0)
20623 return 0;
20624 regtail(preg, ret, br);
20625 if (!(flags&HASWIDTH))
20626 *flagp &= ~HASWIDTH;
20627 *flagp |= flags&SPSTART;
20628 }
20629
20630
20631 ender = regnode(preg, (paren) ? CLOSE+parno : END);
20632 regtail(preg, ret, ender);
20633
20634
20635 for (br = ret; br != 0; br = regnext(preg, br))
20636 regoptail(preg, br, ender);
20637
20638
20639 if (paren && *preg->regparse++ != ')') {
20640 preg->err = REG_ERR_UNMATCHED_PAREN;
20641 return 0;
20642 } else if (!paren && *preg->regparse != '\0') {
20643 if (*preg->regparse == ')') {
@@ -20657,11 +20644,11 @@
20657 int ret;
20658 int chain;
20659 int latest;
20660 int flags;
20661
20662 *flagp = WORST;
20663
20664 ret = regnode(preg, BRANCH);
20665 chain = 0;
20666 while (*preg->regparse != '\0' && *preg->regparse != ')' &&
20667 *preg->regparse != '|') {
@@ -20675,11 +20662,11 @@
20675 else {
20676 regtail(preg, chain, latest);
20677 }
20678 chain = latest;
20679 }
20680 if (chain == 0)
20681 (void) regnode(preg, NOTHING);
20682
20683 return(ret);
20684 }
20685
@@ -20705,11 +20692,11 @@
20705 if (!(flags&HASWIDTH) && op != '?') {
20706 preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
20707 return 0;
20708 }
20709
20710
20711 if (op == '{') {
20712 char *end;
20713
20714 min = strtoul(preg->regparse + 1, &end, 10);
20715 if (end == preg->regparse + 1) {
@@ -20777,11 +20764,11 @@
20777 static void reg_addrange(regex_t *preg, int lower, int upper)
20778 {
20779 if (lower > upper) {
20780 reg_addrange(preg, upper, lower);
20781 }
20782
20783 regc(preg, upper - lower + 1);
20784 regc(preg, lower);
20785 }
20786
20787 static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20832,17 @@
20845 case 'r': *ch = '\r'; break;
20846 case 't': *ch = '\t'; break;
20847 case 'v': *ch = '\v'; break;
20848 case 'u':
20849 if (*s == '{') {
20850
20851 n = parse_hex(s + 1, 6, ch);
20852 if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
20853 s += n + 2;
20854 }
20855 else {
20856
20857 *ch = 'u';
20858 }
20859 }
20860 else if ((n = parse_hex(s, 4, ch)) > 0) {
20861 s += n;
@@ -20886,15 +20873,15 @@
20886 int nocase = (preg->cflags & REG_ICASE);
20887
20888 int ch;
20889 int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
20890
20891 *flagp = WORST;
20892
20893 preg->regparse += n;
20894 switch (ch) {
20895
20896 case '^':
20897 ret = regnode(preg, BOL);
20898 break;
20899 case '$':
20900 ret = regnode(preg, EOL);
@@ -20904,24 +20891,24 @@
20904 *flagp |= HASWIDTH|SIMPLE;
20905 break;
20906 case '[': {
20907 const char *pattern = preg->regparse;
20908
20909 if (*pattern == '^') {
20910 ret = regnode(preg, ANYBUT);
20911 pattern++;
20912 } else
20913 ret = regnode(preg, ANYOF);
20914
20915
20916 if (*pattern == ']' || *pattern == '-') {
20917 reg_addrange(preg, *pattern, *pattern);
20918 pattern++;
20919 }
20920
20921 while (*pattern && *pattern != ']') {
20922
20923 int start;
20924 int end;
20925
20926 pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
20927 if (start == '\\') {
@@ -20930,11 +20917,11 @@
20930 preg->err = REG_ERR_NULL_CHAR;
20931 return 0;
20932 }
20933 }
20934 if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20935
20936 pattern += utf8_tounicode(pattern, &end);
20937 pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
20938 if (end == '\\') {
20939 pattern += reg_decode_escape(pattern, &end);
20940 if (end == 0) {
@@ -20957,22 +20944,22 @@
20957 CC_NUM
20958 };
20959 int i;
20960
20961 for (i = 0; i < CC_NUM; i++) {
20962 int n = strlen(character_class[i]);
20963 if (strncmp(pattern, character_class[i], n) == 0) {
20964
20965 pattern += n + 1;
20966 break;
20967 }
20968 }
20969 if (i != CC_NUM) {
20970 switch (i) {
20971 case CC_ALNUM:
20972 reg_addrange(preg, '0', '9');
20973
20974 case CC_ALPHA:
20975 if ((preg->cflags & REG_ICASE) == 0) {
20976 reg_addrange(preg, 'a', 'z');
20977 }
20978 reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20977,11 @@
20990 reg_addrange(preg, 'a', 'z');
20991 break;
20992 case CC_XDIGIT:
20993 reg_addrange(preg, 'a', 'f');
20994 reg_addrange(preg, 'A', 'F');
20995
20996 case CC_DIGIT:
20997 reg_addrange(preg, '0', '9');
20998 break;
20999 case CC_CNTRL:
21000 reg_addrange(preg, 0, 31);
@@ -21014,11 +21001,11 @@
21014 break;
21015 }
21016 continue;
21017 }
21018 }
21019
21020 reg_addrange(preg, start, start);
21021 }
21022 regc(preg, '\0');
21023
21024 if (*pattern) {
@@ -21037,11 +21024,11 @@
21037 break;
21038 case '\0':
21039 case '|':
21040 case ')':
21041 preg->err = REG_ERR_INTERNAL;
21042 return 0;
21043 case '?':
21044 case '+':
21045 case '*':
21046 case '{':
21047 preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +21077,34 @@
21090 ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
21091 reg_addrange_str(preg," \t\r\n\f\v");
21092 regc(preg, '\0');
21093 *flagp |= HASWIDTH|SIMPLE;
21094 break;
21095
21096 default:
21097
21098
21099 preg->regparse--;
21100 goto de_fault;
21101 }
21102 break;
21103 de_fault:
21104 default: {
21105 int added = 0;
21106
21107
21108 preg->regparse -= n;
21109
21110 ret = regnode(preg, EXACTLY);
21111
21112
21113
21114 while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
21115 n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
21116 if (ch == '\\' && preg->regparse[n]) {
21117 if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
21118
21119 break;
21120 }
21121 n += reg_decode_escape(preg->regparse + n, &ch);
21122 if (ch == 0) {
21123 preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21112,23 @@
21125 }
21126 }
21127
21128
21129 if (ISMULT(preg->regparse[n])) {
21130
21131 if (added) {
21132
21133 break;
21134 }
21135
21136 regc(preg, ch);
21137 added++;
21138 preg->regparse += n;
21139 break;
21140 }
21141
21142
21143 regc(preg, ch);
21144 added++;
21145 preg->regparse += n;
21146 }
21147 regc(preg, '\0');
@@ -21168,15 +21155,15 @@
21168
21169 static int regnode(regex_t *preg, int op)
21170 {
21171 reg_grow(preg, 2);
21172
21173
21174 preg->program[preg->p++] = op;
21175 preg->program[preg->p++] = 0;
21176
21177
21178 return preg->p - 2;
21179 }
21180
21181 static void regc(regex_t *preg, int b )
21182 {
@@ -21186,13 +21173,13 @@
21186
21187 static int reginsert(regex_t *preg, int op, int size, int opnd )
21188 {
21189 reg_grow(preg, size);
21190
21191
21192 memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21193
21194 memset(preg->program + opnd, 0, sizeof(int) * size);
21195
21196 preg->program[opnd] = op;
21197
21198 preg->p += size;
@@ -21204,11 +21191,11 @@
21204 {
21205 int scan;
21206 int temp;
21207 int offset;
21208
21209
21210 scan = p;
21211 for (;;) {
21212 temp = regnext(preg, scan);
21213 if (temp == 0)
21214 break;
@@ -21224,11 +21211,11 @@
21224 }
21225
21226
21227 static void regoptail(regex_t *preg, int p, int val )
21228 {
21229
21230 if (p != 0 && OP(preg, p) == BRANCH) {
21231 regtail(preg, OPERAND(p), val);
21232 }
21233 }
21234
@@ -21240,16 +21227,16 @@
21240 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
21241 {
21242 const char *s;
21243 int scan;
21244
21245
21246 if (preg == NULL || preg->program == NULL || string == NULL) {
21247 return REG_ERR_NULL_ARGUMENT;
21248 }
21249
21250
21251 if (*preg->program != REG_MAGIC) {
21252 return REG_ERR_CORRUPTED;
21253 }
21254
21255 #ifdef DEBUG
@@ -21258,51 +21245,51 @@
21258 #endif
21259
21260 preg->eflags = eflags;
21261 preg->pmatch = pmatch;
21262 preg->nmatch = nmatch;
21263 preg->start = string;
21264
21265
21266 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
21267 int op = OP(preg, scan);
21268 if (op == END)
21269 break;
21270 if (op == REPX || op == REPXMIN)
21271 preg->program[scan + 4] = 0;
21272 }
21273
21274
21275 if (preg->regmust != 0) {
21276 s = string;
21277 while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
21278 if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
21279 break;
21280 }
21281 s++;
21282 }
21283 if (s == NULL)
21284 return REG_NOMATCH;
21285 }
21286
21287
21288 preg->regbol = string;
21289
21290
21291 if (preg->reganch) {
21292 if (eflags & REG_NOTBOL) {
21293
21294 goto nextline;
21295 }
21296 while (1) {
21297 if (regtry(preg, string)) {
21298 return REG_NOERROR;
21299 }
21300 if (*string) {
21301 nextline:
21302 if (preg->cflags & REG_NEWLINE) {
21303
21304 string = strchr(string, '\n');
21305 if (string) {
21306 preg->regbol = ++string;
21307 continue;
21308 }
@@ -21310,22 +21297,22 @@
21310 }
21311 return REG_NOMATCH;
21312 }
21313 }
21314
21315
21316 s = string;
21317 if (preg->regstart != '\0') {
21318
21319 while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
21320 if (regtry(preg, s))
21321 return REG_NOERROR;
21322 s++;
21323 }
21324 }
21325 else
21326
21327 while (1) {
21328 if (regtry(preg, s))
21329 return REG_NOERROR;
21330 if (*s == '\0') {
21331 break;
@@ -21334,15 +21321,15 @@
21334 int c;
21335 s += utf8_tounicode(s, &c);
21336 }
21337 }
21338
21339
21340 return REG_NOMATCH;
21341 }
21342
21343
21344 static int regtry( regex_t *preg, const char *string )
21345 {
21346 int i;
21347
21348 preg->reginput = string;
@@ -21379,11 +21366,11 @@
21379 }
21380
21381 static int reg_range_find(const int *range, int c)
21382 {
21383 while (*range) {
21384
21385 if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
21386 return 1;
21387 }
21388 range += 2;
21389 }
@@ -21391,11 +21378,11 @@
21391 }
21392
21393 static const char *str_find(const char *string, int c, int nocase)
21394 {
21395 if (nocase) {
21396
21397 c = utf8_upper(c);
21398 }
21399 while (*string) {
21400 int ch;
21401 int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21422,15 @@
21435 no = regrepeat(preg, scan + 5, max);
21436 if (no < min) {
21437 return 0;
21438 }
21439 if (matchmin) {
21440
21441 max = no;
21442 no = min;
21443 }
21444
21445 while (1) {
21446 if (matchmin) {
21447 if (no > max) {
21448 break;
21449 }
@@ -21453,22 +21440,22 @@
21453 break;
21454 }
21455 }
21456 preg->reginput = save + utf8_index(save, no);
21457 reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21458
21459 if (reg_iseol(preg, nextch) || c == nextch) {
21460 if (regmatch(preg, next)) {
21461 return(1);
21462 }
21463 }
21464 if (matchmin) {
21465
21466 no++;
21467 }
21468 else {
21469
21470 no--;
21471 }
21472 }
21473 return(0);
21474 }
@@ -21478,13 +21465,13 @@
21478 int *scanpt = preg->program + scan;
21479
21480 int max = scanpt[2];
21481 int min = scanpt[3];
21482
21483
21484 if (scanpt[4] < min) {
21485
21486 scanpt[4]++;
21487 if (regmatch(preg, scan + 5)) {
21488 return 1;
21489 }
21490 scanpt[4]--;
@@ -21493,39 +21480,39 @@
21493 if (scanpt[4] > max) {
21494 return 0;
21495 }
21496
21497 if (matchmin) {
21498
21499 if (regmatch(preg, regnext(preg, scan))) {
21500 return 1;
21501 }
21502
21503 scanpt[4]++;
21504 if (regmatch(preg, scan + 5)) {
21505 return 1;
21506 }
21507 scanpt[4]--;
21508 return 0;
21509 }
21510
21511 if (scanpt[4] < max) {
21512 scanpt[4]++;
21513 if (regmatch(preg, scan + 5)) {
21514 return 1;
21515 }
21516 scanpt[4]--;
21517 }
21518
21519 return regmatch(preg, regnext(preg, scan));
21520 }
21521
21522
21523 static int regmatch(regex_t *preg, int prog)
21524 {
21525 int scan;
21526 int next;
21527 const char *save;
21528
21529 scan = prog;
21530
21531 #ifdef DEBUG
@@ -21535,11 +21522,11 @@
21535 while (scan != 0) {
21536 int n;
21537 int c;
21538 #ifdef DEBUG
21539 if (regnarrate) {
21540 fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21541 }
21542 #endif
21543 next = regnext(preg, scan);
21544 n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21545
@@ -21546,49 +21533,49 @@
21546 switch (OP(preg, scan)) {
21547 case BOLX:
21548 if ((preg->eflags & REG_NOTBOL)) {
21549 return(0);
21550 }
21551
21552 case BOL:
21553 if (preg->reginput != preg->regbol) {
21554 return(0);
21555 }
21556 break;
21557 case EOLX:
21558 if (c != 0) {
21559
21560 return 0;
21561 }
21562 break;
21563 case EOL:
21564 if (!reg_iseol(preg, c)) {
21565 return(0);
21566 }
21567 break;
21568 case WORDA:
21569
21570 if ((!isalnum(UCHAR(c))) && c != '_')
21571 return(0);
21572
21573 if (preg->reginput > preg->regbol &&
21574 (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
21575 return(0);
21576 break;
21577 case WORDZ:
21578
21579 if (preg->reginput > preg->regbol) {
21580
21581 if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
21582 c = preg->reginput[-1];
21583
21584 if (isalnum(UCHAR(c)) || c == '_') {
21585 break;
21586 }
21587 }
21588 }
21589
21590 return(0);
21591
21592 case ANY:
21593 if (reg_iseol(preg, c))
21594 return 0;
@@ -21624,12 +21611,12 @@
21624 case NOTHING:
21625 break;
21626 case BACK:
21627 break;
21628 case BRANCH:
21629 if (OP(preg, next) != BRANCH)
21630 next = OPERAND(scan);
21631 else {
21632 do {
21633 save = preg->reginput;
21634 if (regmatch(preg, OPERAND(scan))) {
21635 return(1);
@@ -21636,11 +21623,11 @@
21636 }
21637 preg->reginput = save;
21638 scan = regnext(preg, scan);
21639 } while (scan != 0 && OP(preg, scan) == BRANCH);
21640 return(0);
21641
21642 }
21643 break;
21644 case REP:
21645 case REPMIN:
21646 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21635,11 @@
21648 case REPX:
21649 case REPXMIN:
21650 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21651
21652 case END:
21653 return 1;
21654
21655 case OPENNC:
21656 case CLOSENC:
21657 return regmatch(preg, next);
21658
@@ -21695,11 +21682,11 @@
21695
21696 scan = preg->reginput;
21697 opnd = OPERAND(p);
21698 switch (OP(preg, p)) {
21699 case ANY:
21700
21701 while (!reg_iseol(preg, *scan) && count < max) {
21702 count++;
21703 scan++;
21704 }
21705 break;
@@ -21731,13 +21718,13 @@
21731 }
21732 count++;
21733 scan += n;
21734 }
21735 break;
21736 default:
21737 preg->err = REG_ERR_INTERNAL;
21738 count = 0;
21739 break;
21740 }
21741 preg->reginput = scan;
21742
21743 return(count);
@@ -21758,11 +21745,11 @@
21758 return(p+offset);
21759 }
21760
21761 static int regopsize(regex_t *preg, int p )
21762 {
21763
21764 switch (OP(preg, p)) {
21765 case REP:
21766 case REPMIN:
21767 case REPX:
21768 case REPXMIN:
@@ -21879,26 +21866,26 @@
21879 {
21880 DIR *dir = 0;
21881
21882 if (name && name[0]) {
21883 size_t base_length = strlen(name);
21884 const char *all =
21885 strchr("/\\", name[base_length - 1]) ? "*" : "/*";
21886
21887 if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
21888 (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
21889 strcat(strcpy(dir->name, name), all);
21890
21891 if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
21892 dir->result.d_name = 0;
21893 else {
21894 Jim_Free(dir->name);
21895 Jim_Free(dir);
21896 dir = 0;
21897 }
21898 }
21899 else {
21900 Jim_Free(dir);
21901 dir = 0;
21902 errno = ENOMEM;
21903 }
21904 }
@@ -21916,11 +21903,11 @@
21916 if (dir->handle != -1)
21917 result = _findclose(dir->handle);
21918 Jim_Free(dir->name);
21919 Jim_Free(dir);
21920 }
21921 if (result == -1)
21922 errno = EBADF;
21923 return result;
21924 }
21925
21926 struct dirent *readdir(DIR * dir)
@@ -21947,10 +21934,13 @@
21947
21948 #ifdef USE_LINENOISE
21949 #ifdef HAVE_UNISTD_H
21950 #include <unistd.h>
21951 #endif
 
 
 
21952 #include "linenoise.h"
21953 #else
21954 #define MAX_LINE_LEN 512
21955 #endif
21956
@@ -21992,41 +21982,86 @@
21992 }
21993
21994 void Jim_HistorySave(const char *filename)
21995 {
21996 #ifdef USE_LINENOISE
 
 
 
 
 
21997 linenoiseHistorySave(filename);
 
 
 
21998 #endif
21999 }
22000
22001 void Jim_HistoryShow(void)
22002 {
22003 #ifdef USE_LINENOISE
22004
22005 int i;
22006 int len;
22007 char **history = linenoiseHistory(&len);
22008 for (i = 0; i < len; i++) {
22009 printf("%4d %s\n", i + 1, history[i]);
22010 }
22011 #endif
22012 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22013
22014 int Jim_InteractivePrompt(Jim_Interp *interp)
22015 {
22016 int retcode = JIM_OK;
22017 char *history_file = NULL;
22018 #ifdef USE_LINENOISE
22019 const char *home;
 
22020
22021 home = getenv("HOME");
22022 if (home && isatty(STDIN_FILENO)) {
22023 int history_len = strlen(home) + sizeof("/.jim_history");
22024 history_file = Jim_Alloc(history_len);
22025 snprintf(history_file, history_len, "%s/.jim_history", home);
22026 Jim_HistoryLoad(history_file);
22027 }
 
 
 
 
 
 
 
22028 #endif
22029
22030 printf("Welcome to Jim version %d.%d\n",
22031 JIM_VERSION / 100, JIM_VERSION % 100);
22032 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22065,11 +22100,11 @@
22065 Jim_DecrRefCount(interp, scriptObjPtr);
22066 retcode = JIM_OK;
22067 goto out;
22068 }
22069 if (Jim_Length(scriptObjPtr) != 0) {
22070
22071 Jim_AppendString(interp, scriptObjPtr, "\n", 1);
22072 }
22073 Jim_AppendString(interp, scriptObjPtr, line, -1);
22074 free(line);
22075 if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22112,11 @@
22077
22078 snprintf(prompt, sizeof(prompt), "%c> ", state);
22079 }
22080 #ifdef USE_LINENOISE
22081 if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22082
22083 Jim_HistoryShow();
22084 Jim_DecrRefCount(interp, scriptObjPtr);
22085 continue;
22086 }
22087
@@ -22104,10 +22139,16 @@
22104 printf("%s\n", result);
22105 }
22106 }
22107 out:
22108 Jim_Free(history_file);
 
 
 
 
 
 
22109 return retcode;
22110 }
22111
22112 #include <stdio.h>
22113 #include <stdlib.h>
@@ -22120,11 +22161,11 @@
22120 static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
22121 {
22122 int n;
22123 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
22124
22125
22126 for (n = 0; n < argc; n++) {
22127 Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
22128
22129 Jim_ListAppendElement(interp, listObj, obj);
22130 }
@@ -22146,71 +22187,75 @@
22146 printf("or : %s [options] [filename]\n", executable_name);
22147 printf("\n");
22148 printf("Without options: Interactive mode\n");
22149 printf("\n");
22150 printf("Options:\n");
22151 printf(" --version : prints the version string\n");
22152 printf(" --help : prints this text\n");
22153 printf(" -e CMD : executes command CMD\n");
22154 printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22155 printf(" [filename] : executes the script contained in the named file\n");
22156 printf(" NOTE: all subsequent options will be passed to the script\n\n");
22157 }
22158
22159 int main(int argc, char *const argv[])
22160 {
22161 int retcode;
22162 Jim_Interp *interp;
22163 char *const orig_argv0 = argv[0];
22164
22165
22166 if (argc > 1 && strcmp(argv[1], "--version") == 0) {
22167 printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
22168 return 0;
22169 }
22170 else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
22171 usage(argv[0]);
22172 return 0;
22173 }
22174
22175
22176 interp = Jim_CreateInterp();
22177 Jim_RegisterCoreCommands(interp);
22178
22179
22180 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
22181 JimPrintErrorMessage(interp);
22182 }
22183
22184 Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
22185 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
22186 retcode = Jim_initjimshInit(interp);
22187
22188 if (argc == 1) {
22189
22190 if (retcode == JIM_ERR) {
22191 JimPrintErrorMessage(interp);
22192 }
22193 if (retcode != JIM_EXIT) {
22194 JimSetArgv(interp, 0, NULL);
22195 retcode = Jim_InteractivePrompt(interp);
22196 }
22197 }
22198 else {
22199
22200 if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22201
22202 JimSetArgv(interp, argc - 3, argv + 3);
22203 retcode = Jim_Eval(interp, argv[2]);
22204 if (retcode != JIM_ERR) {
22205 printf("%s\n", Jim_String(Jim_GetResult(interp)));
22206 }
22207 }
22208 else {
22209 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
22210 JimSetArgv(interp, argc - 2, argv + 2);
22211 retcode = Jim_EvalFile(interp, argv[1]);
 
 
 
 
22212 }
22213 if (retcode == JIM_ERR) {
22214 JimPrintErrorMessage(interp);
22215 }
22216 }
22217
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,9 +1,7 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
 
2 #define JIM_TCL_COMPAT
 
3 #define JIM_ANSIC
4 #define JIM_REGEXP
5 #define HAVE_NO_AUTOCONF
6 #define _JIMAUTOCONF_H
7 #define TCL_LIBRARY "."
@@ -31,24 +29,39 @@
29 #define HAVE_MKDIR_ONE_ARG
30 #define HAVE_SYSTEM
31 #define HAVE_SYS_TIME_H
32 #define HAVE_DIRENT_H
33 #define HAVE_UNISTD_H
34 #define HAVE_UMASK
35 #include <sys/stat.h>
36 #ifndef S_IRWXG
37 #define S_IRWXG 0
38 #endif
39 #ifndef S_IRWXO
40 #define S_IRWXO 0
41 #endif
42 #else
43 #define TCL_PLATFORM_OS "unknown"
44 #define TCL_PLATFORM_PLATFORM "unix"
45 #define TCL_PLATFORM_PATH_SEPARATOR ":"
46 #ifdef _MINIX
47 #define vfork fork
48 #define _POSIX_SOURCE
49 #else
50 #define _GNU_SOURCE
51 #endif
52 #define HAVE_VFORK
53 #define HAVE_WAITPID
54 #define HAVE_ISATTY
55 #define HAVE_MKSTEMP
56 #define HAVE_LINK
57 #define HAVE_SYS_TIME_H
58 #define HAVE_DIRENT_H
59 #define HAVE_UNISTD_H
60 #define HAVE_UMASK
61 #endif
62 #define JIM_VERSION 77
63 #ifndef JIM_WIN32COMPAT_H
64 #define JIM_WIN32COMPAT_H
65
66
67
@@ -88,11 +101,10 @@
101 #define JIM_WIDE_MIN LLONG_MIN
102 #define JIM_WIDE_MAX LLONG_MAX
103 #define JIM_WIDE_MODIFIER "I64d"
104 #define strcasecmp _stricmp
105 #define strtoull _strtoui64
 
106
107 #include <io.h>
108
109 struct timeval {
110 long tv_sec;
@@ -105,14 +117,14 @@
117 struct dirent {
118 char *d_name;
119 };
120
121 typedef struct DIR {
122 long handle;
123 struct _finddata_t info;
124 struct dirent result;
125 char *name;
126 } DIR;
127
128 DIR *opendir(const char *name);
129 int closedir(DIR *dir);
130 struct dirent *readdir(DIR *dir);
@@ -122,11 +134,11 @@
134 #include <stdlib.h>
135 #define strtod __strtod
136
137 #endif
138
139 #endif
140
141 #ifdef __cplusplus
142 }
143 #endif
144
@@ -146,19 +158,21 @@
158
159 #ifndef JIM_UTF8
160 #include <ctype.h>
161
162
163 #define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
164 #define utf8_strwidth(S, B) utf8_strlen((S), (B))
165 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
166 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
167 #define utf8_upper(C) toupper(C)
168 #define utf8_title(C) toupper(C)
169 #define utf8_lower(C) tolower(C)
170 #define utf8_index(C, I) (I)
171 #define utf8_charlen(C) 1
172 #define utf8_prev_len(S, L) 1
173 #define utf8_width(C) 1
174
175 #else
176
177 #endif
178
@@ -175,13 +189,13 @@
189 extern "C" {
190 #endif
191
192 #include <time.h>
193 #include <limits.h>
194 #include <stdio.h>
195 #include <stdlib.h>
196 #include <stdarg.h>
197
198
199 #ifndef HAVE_NO_AUTOCONF
200 #endif
201
@@ -224,31 +238,31 @@
238 #define JIM_SIGNAL 5
239 #define JIM_EXIT 6
240
241 #define JIM_EVAL 7
242
243 #define JIM_MAX_CALLFRAME_DEPTH 1000
244 #define JIM_MAX_EVAL_DEPTH 2000
245
246
247 #define JIM_PRIV_FLAG_SHIFT 20
248
249 #define JIM_NONE 0
250 #define JIM_ERRMSG 1
251 #define JIM_ENUM_ABBREV 2
252 #define JIM_UNSHARED 4
253 #define JIM_MUSTEXIST 8
254
255
256 #define JIM_SUBST_NOVAR 1
257 #define JIM_SUBST_NOCMD 2
258 #define JIM_SUBST_NOESC 4
259 #define JIM_SUBST_FLAG 128
260
261
262 #define JIM_CASESENS 0
263 #define JIM_NOCASE 1
264
265
266 #define JIM_PATH_LEN 1024
267
268
@@ -339,79 +353,79 @@
353 #define Jim_GetHashTableSize(ht) ((ht)->size)
354 #define Jim_GetHashTableUsed(ht) ((ht)->used)
355
356
357 typedef struct Jim_Obj {
358 char *bytes;
359 const struct Jim_ObjType *typePtr;
360 int refCount;
361 int length;
362
363 union {
364
365 jim_wide wideValue;
366
367 int intValue;
368
369 double doubleValue;
370
371 void *ptr;
372
373 struct {
374 void *ptr1;
375 void *ptr2;
376 } twoPtrValue;
377
378 struct {
379 struct Jim_Var *varPtr;
380 unsigned long callFrameId;
381 int global;
382 } varValue;
383
384 struct {
385 struct Jim_Obj *nsObj;
386 struct Jim_Cmd *cmdPtr;
387 unsigned long procEpoch;
388 } cmdValue;
389
390 struct {
391 struct Jim_Obj **ele;
392 int len;
393 int maxLen;
394 } listValue;
395
396 struct {
397 int maxLength;
398 int charLength;
399 } strValue;
400
401 struct {
402 unsigned long id;
403 struct Jim_Reference *refPtr;
404 } refValue;
405
406 struct {
407 struct Jim_Obj *fileNameObj;
408 int lineNumber;
409 } sourceValue;
410
411 struct {
412 struct Jim_Obj *varNameObjPtr;
413 struct Jim_Obj *indexObjPtr;
414 } dictSubstValue;
415
416 struct {
417 void *compre;
418 unsigned flags;
419 } regexpValue;
420 struct {
421 int line;
422 int argc;
423 } scriptLineValue;
424 } internalRep;
425 struct Jim_Obj *prevObjPtr;
426 struct Jim_Obj *nextObjPtr;
427 } Jim_Obj;
428
429
430 #define Jim_IncrRefCount(objPtr) \
431 ++(objPtr)->refCount
@@ -442,40 +456,40 @@
456 typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
457 struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
458 typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
459
460 typedef struct Jim_ObjType {
461 const char *name;
462 Jim_FreeInternalRepProc *freeIntRepProc;
463 Jim_DupInternalRepProc *dupIntRepProc;
464 Jim_UpdateStringProc *updateStringProc;
465 int flags;
466 } Jim_ObjType;
467
468
469 #define JIM_TYPE_NONE 0
470 #define JIM_TYPE_REFERENCES 1
471
472
473
474 typedef struct Jim_CallFrame {
475 unsigned long id;
476 int level;
477 struct Jim_HashTable vars;
478 struct Jim_HashTable *staticVars;
479 struct Jim_CallFrame *parent;
480 Jim_Obj *const *argv;
481 int argc;
482 Jim_Obj *procArgsObjPtr;
483 Jim_Obj *procBodyObjPtr;
484 struct Jim_CallFrame *next;
485 Jim_Obj *nsObj;
486 Jim_Obj *fileNameObj;
487 int line;
488 Jim_Stack *localCommands;
489 struct Jim_Obj *tailcallObj;
490 struct Jim_Cmd *tailcallCmd;
491 } Jim_CallFrame;
492
493 typedef struct Jim_Var {
494 Jim_Obj *objPtr;
495 struct Jim_CallFrame *linkFramePtr;
@@ -487,35 +501,35 @@
501 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
502
503
504
505 typedef struct Jim_Cmd {
506 int inUse;
507 int isproc;
508 struct Jim_Cmd *prevCmd;
509 union {
510 struct {
511
512 Jim_CmdProc *cmdProc;
513 Jim_DelCmdProc *delProc;
514 void *privData;
515 } native;
516 struct {
517
518 Jim_Obj *argListObjPtr;
519 Jim_Obj *bodyObjPtr;
520 Jim_HashTable *staticVars;
521 int argListLen;
522 int reqArity;
523 int optArity;
524 int argsPos;
525 int upcall;
526 struct Jim_ProcArg {
527 Jim_Obj *nameObjPtr;
528 Jim_Obj *defaultObjPtr;
529 } *arglist;
530 Jim_Obj *nsObj;
531 } proc;
532 } u;
533 } Jim_Cmd;
534
535
@@ -523,64 +537,64 @@
537 unsigned char sbox[256];
538 unsigned int i, j;
539 } Jim_PrngState;
540
541 typedef struct Jim_Interp {
542 Jim_Obj *result;
543 int errorLine;
544 Jim_Obj *errorFileNameObj;
545 int addStackTrace;
546 int maxCallFrameDepth;
547 int maxEvalDepth;
548 int evalDepth;
549 int returnCode;
550 int returnLevel;
551 int exitCode;
552 long id;
553 int signal_level;
554 jim_wide sigmask;
555 int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
556 Jim_CallFrame *framePtr;
557 Jim_CallFrame *topFramePtr;
558 struct Jim_HashTable commands;
559 unsigned long procEpoch; /* Incremented every time the result
560 of procedures names lookup caching
561 may no longer be valid. */
562 unsigned long callFrameEpoch; /* Incremented every time a new
563 callframe is created. This id is used for the
564 'ID' field contained in the Jim_CallFrame
565 structure. */
566 int local;
567 Jim_Obj *liveList;
568 Jim_Obj *freeList;
569 Jim_Obj *currentScriptObj;
570 Jim_Obj *nullScriptObj;
571 Jim_Obj *emptyObj;
572 Jim_Obj *trueObj;
573 Jim_Obj *falseObj;
574 unsigned long referenceNextId;
575 struct Jim_HashTable references;
576 unsigned long lastCollectId; /* reference max Id of the last GC
577 execution. It's set to -1 while the collection
578 is running as sentinel to avoid to recursive
579 calls via the [collect] command inside
580 finalizers. */
581 time_t lastCollectTime;
582 Jim_Obj *stackTrace;
583 Jim_Obj *errorProc;
584 Jim_Obj *unknown;
585 int unknown_called;
586 int errorFlag;
587 void *cmdPrivData; /* Used to pass the private data pointer to
588 a command. It is set to what the user specified
589 via Jim_CreateCommand(). */
590
591 struct Jim_CallFrame *freeFramesList;
592 struct Jim_HashTable assocData;
593 Jim_PrngState *prngState;
594 struct Jim_HashTable packages;
595 Jim_Stack *loadHandles;
596 } Jim_Interp;
597
598 #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
599 #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
600 #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,11 +637,11 @@
637 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
638
639
640 JIM_EXPORT char **Jim_GetEnviron(void);
641 JIM_EXPORT void Jim_SetEnviron(char **env);
642 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template);
643
644
645 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
646
647
@@ -816,14 +830,18 @@
830 Jim_Obj *newObjPtr, int flags);
831 JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
832 Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
833 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
834 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
835
836 #define JIM_DICTMATCH_KEYS 0x0001
837 #define JIM_DICTMATCH_VALUES 0x002
838
839 JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types);
840 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
841 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
842 JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv);
843
844
845 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
846 int *intPtr);
847
@@ -831,10 +849,14 @@
849 JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
850 Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
851 JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
852 Jim_Obj *exprObjPtr, int *boolPtr);
853
854
855 JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr,
856 int *booleanPtr);
857
858
859 JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
860 jim_wide *widePtr);
861 JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
862 long *longPtr);
@@ -852,10 +874,12 @@
874
875 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
876 Jim_Obj *const *argv, const char *msg);
877 JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
878 const char * const *tablePtr, int *indexPtr, const char *name, int flags);
879 JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr,
880 const char *const *tablePtr);
881 JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
882 Jim_Obj *scriptObj, char *stateCharPtr);
883
884 JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
885
@@ -904,11 +928,11 @@
928
929 #ifdef __cplusplus
930 }
931 #endif
932
933 #endif
934
935 #ifndef JIM_SUBCMD_H
936 #define JIM_SUBCMD_H
937
938
@@ -915,24 +939,24 @@
939 #ifdef __cplusplus
940 extern "C" {
941 #endif
942
943
944 #define JIM_MODFLAG_HIDDEN 0x0001
945 #define JIM_MODFLAG_FULLARGV 0x0002
946
947
948
949 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
950
951 typedef struct {
952 const char *cmd;
953 const char *args;
954 jim_subcmd_function *function;
955 short minargs;
956 short maxargs;
957 unsigned short flags;
958 } jim_subcmd_type;
959
960 const jim_subcmd_type *
961 Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
962
@@ -960,36 +984,36 @@
984 int rm_eo;
985 } regmatch_t;
986
987
988 typedef struct regexp {
989
990 int re_nsub;
991
992
993 int cflags;
994 int err;
995 int regstart;
996 int reganch;
997 int regmust;
998 int regmlen;
999 int *program;
1000
1001
1002 const char *regparse;
1003 int p;
1004 int proglen;
1005
1006
1007 int eflags;
1008 const char *start;
1009 const char *reginput;
1010 const char *regbol;
1011
1012
1013 regmatch_t *pmatch;
1014 int nmatch;
1015 } regexp;
1016
1017 typedef regexp regex_t;
1018
1019 #define REG_EXTENDED 0
@@ -997,13 +1021,13 @@
1021 #define REG_ICASE 2
1022
1023 #define REG_NOTBOL 16
1024
1025 enum {
1026 REG_NOERROR,
1027 REG_NOMATCH,
1028 REG_BADPAT,
1029 REG_ERR_NULL_ARGUMENT,
1030 REG_ERR_UNKNOWN,
1031 REG_ERR_TOO_BIG,
1032 REG_ERR_NOMEM,
1033 REG_ERR_TOO_MANY_PAREN,
@@ -1100,10 +1124,43 @@
1124 "\n"
1125 "if {$tcl_platform(platform) eq \"windows\"} {\n"
1126 " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n"
1127 "}\n"
1128 "\n"
1129 "\n"
1130 "set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n"
1131 "\n"
1132 "\n"
1133 "\n"
1134 "proc tcl::autocomplete {prefix} {\n"
1135 " if {[set space [string first \" \" $prefix]] != -1} {\n"
1136 " set cmd [string range $prefix 0 $space-1]\n"
1137 " if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n"
1138 " set arg [string range $prefix $space+1 end]\n"
1139 "\n"
1140 " return [lmap p [$cmd -commands] {\n"
1141 " if {![string match \"${arg}*\" $p]} continue\n"
1142 " function \"$cmd $p\"\n"
1143 " }]\n"
1144 " }\n"
1145 " }\n"
1146 "\n"
1147 " if {[string match \"source *\" $prefix]} {\n"
1148 " set path [string range $prefix 7 end]\n"
1149 " return [lmap p [glob -nocomplain \"${path}*\"] {\n"
1150 " function \"source $p\"\n"
1151 " }]\n"
1152 " }\n"
1153 "\n"
1154 " return [lmap p [lsort [info commands $prefix*]] {\n"
1155 " if {[string match \"* *\" $p]} {\n"
1156 " continue\n"
1157 " }\n"
1158 " function $p\n"
1159 " }]\n"
1160 "}\n"
1161 "\n"
1162 "_jimsh_init\n"
1163 );
1164 }
1165 int Jim_globInit(Jim_Interp *interp)
1166 {
@@ -1402,31 +1459,10 @@
1459 " if {[exists ::jim::exe]} {\n"
1460 " return $::jim::exe\n"
1461 " }\n"
1462 "}\n"
1463 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1464 "\n"
1465 "proc {dict update} {&varName args script} {\n"
1466 " set keys {}\n"
1467 " foreach {n v} $args {\n"
1468 " upvar $v var_$v\n"
@@ -1445,23 +1481,10 @@
1481 " }\n"
1482 " }\n"
1483 " return {*}$opts $msg\n"
1484 "}\n"
1485 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
1486 "proc {dict replace} {dictionary {args {key value}}} {\n"
1487 " if {[llength ${key value}] % 2} {\n"
1488 " tailcall {dict replace}\n"
1489 " }\n"
1490 " tailcall dict merge $dictionary ${key value}\n"
@@ -1503,15 +1526,10 @@
1526 " dict unset dictionary $k\n"
1527 " }\n"
1528 " return $dictionary\n"
1529 "}\n"
1530 "\n"
 
 
 
 
 
1531 "\n"
1532 "proc {dict for} {vars dictionary script} {\n"
1533 " if {[llength $vars] != 2} {\n"
1534 " return -code error \"must have exactly two variable names\"\n"
1535 " }\n"
@@ -1588,11 +1606,10 @@
1606 "\n"
1607 "\n"
1608 "proc fileevent {args} {\n"
1609 " tailcall {*}$args\n"
1610 "}\n"
 
1611 "\n"
1612 "\n"
1613 "\n"
1614 "proc parray {arrayname {pattern *} {puts puts}} {\n"
1615 " upvar $arrayname a\n"
@@ -1701,15 +1718,10 @@
1718 "\n"
1719 "\n"
1720 "\n"
1721 "\n"
1722 "\n"
 
 
 
 
 
1723 "proc try {args} {\n"
1724 " set catchopts {}\n"
1725 " while {[string match -* [lindex $args 0]]} {\n"
1726 " set args [lassign $args opt]\n"
1727 " if {$opt eq \"--\"} {\n"
@@ -1780,10 +1792,13 @@
1792 "}\n"
1793 );
1794 }
1795
1796
1797 #ifndef _GNU_SOURCE
1798 #define _GNU_SOURCE
1799 #endif
1800 #include <stdio.h>
1801 #include <string.h>
1802 #include <errno.h>
1803 #include <fcntl.h>
1804 #ifdef HAVE_UNISTD_H
@@ -1807,13 +1822,16 @@
1822 #if defined(JIM_SSL)
1823 #include <openssl/ssl.h>
1824 #include <openssl/err.h>
1825 #endif
1826
1827 #ifdef HAVE_TERMIOS_H
1828 #endif
1829
1830
1831 #define AIO_CMD_LEN 32
1832 #define AIO_BUF_LEN 256
1833
1834 #ifndef HAVE_FTELLO
1835 #define ftello ftell
1836 #endif
1837 #ifndef HAVE_FSEEKO
@@ -1848,11 +1866,11 @@
1866 typedef struct AioFile
1867 {
1868 FILE *fp;
1869 Jim_Obj *filename;
1870 int type;
1871 int openFlags;
1872 int fd;
1873 Jim_Obj *rEvent;
1874 Jim_Obj *wEvent;
1875 Jim_Obj *eEvent;
1876 int addr_family;
@@ -1879,21 +1897,21 @@
1897 {
1898 if (!ferror(af->fp)) {
1899 return JIM_OK;
1900 }
1901 clearerr(af->fp);
1902
1903 if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
1904 return JIM_OK;
1905 }
1906 #ifdef ECONNRESET
1907 if (errno == ECONNRESET) {
1908 return JIM_OK;
1909 }
1910 #endif
1911 #ifdef ECONNABORTED
1912 if (errno == ECONNABORTED) {
1913 return JIM_OK;
1914 }
1915 #endif
1916 return JIM_ERR;
1917 }
@@ -1945,20 +1963,19 @@
1963 JIM_NOTUSED(interp);
1964
1965 Jim_DecrRefCount(interp, af->filename);
1966
1967 #ifdef jim_ext_eventloop
1968
1969 Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1970 #endif
1971
1972 #if defined(JIM_SSL)
1973 if (af->ssl != NULL) {
1974 SSL_free(af->ssl);
1975 }
1976 #endif
 
1977 if (!(af->openFlags & AIO_KEEPOPEN)) {
1978 fclose(af->fp);
1979 }
1980
1981 Jim_Free(af);
@@ -1968,11 +1985,11 @@
1985 {
1986 AioFile *af = Jim_CmdPrivData(interp);
1987 char buf[AIO_BUF_LEN];
1988 Jim_Obj *objPtr;
1989 int nonewline = 0;
1990 jim_wide neededLen = -1;
1991
1992 if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
1993 nonewline = 1;
1994 argv++;
1995 argc--;
@@ -2007,11 +2024,11 @@
2024 }
2025 }
2026 if (retval != readlen)
2027 break;
2028 }
2029
2030 if (JimCheckStreamError(interp, af)) {
2031 Jim_FreeNewObj(interp, objPtr);
2032 return JIM_ERR;
2033 }
2034 if (nonewline) {
@@ -2029,11 +2046,11 @@
2046
2047 AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
2048 {
2049 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2050
2051
2052 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2053 return (AioFile *) cmdPtr->u.native.privData;
2054 }
2055 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2056 return NULL;
@@ -2110,21 +2127,21 @@
2127 }
2128 else {
2129 len = strlen(buf);
2130
2131 if (len && (buf[len - 1] == '\n')) {
2132
2133 len--;
2134 }
2135
2136 Jim_AppendString(interp, objPtr, buf, len);
2137 break;
2138 }
2139 }
2140
2141 if (JimCheckStreamError(interp, af)) {
2142
2143 Jim_FreeNewObj(interp, objPtr);
2144 return JIM_ERR;
2145 }
2146
2147 if (argc) {
@@ -2134,11 +2151,11 @@
2151 }
2152
2153 len = Jim_Length(objPtr);
2154
2155 if (len == 0 && feof(af->fp)) {
2156
2157 len = -1;
2158 }
2159 Jim_SetResultInt(interp, len);
2160 }
2161 else {
@@ -2364,33 +2381,33 @@
2381
2382 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
2383 int argc, Jim_Obj * const *argv)
2384 {
2385 if (argc == 0) {
2386
2387 if (*scriptHandlerObj) {
2388 Jim_SetResult(interp, *scriptHandlerObj);
2389 }
2390 return JIM_OK;
2391 }
2392
2393 if (*scriptHandlerObj) {
2394
2395 Jim_DeleteFileHandler(interp, af->fd, mask);
2396 }
2397
2398
2399 if (Jim_Length(argv[0]) == 0) {
2400
2401 return JIM_OK;
2402 }
2403
2404
2405 Jim_IncrRefCount(argv[0]);
2406 *scriptHandlerObj = argv[0];
2407
2408 Jim_CreateFileHandler(interp, af->fd, mask,
2409 JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
2410
2411 return JIM_OK;
2412 }
2413
@@ -2414,136 +2431,138 @@
2431
2432 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2433 }
2434 #endif
2435
2436
2437
2438
2439 static const jim_subcmd_type aio_command_table[] = {
2440 { "read",
2441 "?-nonewline? ?len?",
2442 aio_cmd_read,
2443 0,
2444 2,
2445
2446 },
2447 { "copyto",
2448 "handle ?size?",
2449 aio_cmd_copy,
2450 1,
2451 2,
2452
2453 },
2454 { "gets",
2455 "?var?",
2456 aio_cmd_gets,
2457 0,
2458 1,
2459
2460 },
2461 { "puts",
2462 "?-nonewline? str",
2463 aio_cmd_puts,
2464 1,
2465 2,
2466
2467 },
2468 { "isatty",
2469 NULL,
2470 aio_cmd_isatty,
2471 0,
2472 0,
2473
2474 },
2475 { "flush",
2476 NULL,
2477 aio_cmd_flush,
2478 0,
2479 0,
2480
2481 },
2482 { "eof",
2483 NULL,
2484 aio_cmd_eof,
2485 0,
2486 0,
2487
2488 },
2489 { "close",
2490 "?r(ead)|w(rite)?",
2491 aio_cmd_close,
2492 0,
2493 1,
2494 JIM_MODFLAG_FULLARGV,
2495
2496 },
2497 { "seek",
2498 "offset ?start|current|end",
2499 aio_cmd_seek,
2500 1,
2501 2,
2502
2503 },
2504 { "tell",
2505 NULL,
2506 aio_cmd_tell,
2507 0,
2508 0,
2509
2510 },
2511 { "filename",
2512 NULL,
2513 aio_cmd_filename,
2514 0,
2515 0,
2516
2517 },
2518 #ifdef O_NDELAY
2519 { "ndelay",
2520 "?0|1?",
2521 aio_cmd_ndelay,
2522 0,
2523 1,
2524
2525 },
2526 #endif
2527 #ifdef HAVE_FSYNC
2528 { "sync",
2529 NULL,
2530 aio_cmd_sync,
2531 0,
2532 0,
2533
2534 },
2535 #endif
2536 { "buffering",
2537 "none|line|full",
2538 aio_cmd_buffering,
2539 1,
2540 1,
2541
2542 },
2543 #ifdef jim_ext_eventloop
2544 { "readable",
2545 "?readable-script?",
2546 aio_cmd_readable,
2547 0,
2548 1,
2549
2550 },
2551 { "writable",
2552 "?writable-script?",
2553 aio_cmd_writable,
2554 0,
2555 1,
2556
2557 },
2558 { "onexception",
2559 "?exception-script?",
2560 aio_cmd_onexception,
2561 0,
2562 1,
2563
2564 },
2565 #endif
2566 { NULL }
2567 };
2568
@@ -2566,11 +2585,11 @@
2585
2586 #ifdef jim_ext_tclcompat
2587 {
2588 const char *filename = Jim_String(argv[1]);
2589
2590
2591 if (*filename == '|') {
2592 Jim_Obj *evalObj[3];
2593
2594 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2595 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
@@ -2623,11 +2642,11 @@
2642 Jim_DecrRefCount(interp, filename);
2643 return NULL;
2644 }
2645 }
2646
2647
2648 af = Jim_Alloc(sizeof(*af));
2649 memset(af, 0, sizeof(*af));
2650 af->fp = fh;
2651 af->fd = fileno(fh);
2652 af->filename = filename;
@@ -2661,27 +2680,27 @@
2680 Jim_SetResult(interp, objPtr);
2681 return JIM_OK;
2682 }
2683 }
2684
2685
2686 close(p[0]);
2687 close(p[1]);
2688 JimAioSetError(interp, NULL);
2689 return JIM_ERR;
2690 }
2691 #endif
2692
2693
2694 int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template)
2695 {
2696 #ifdef HAVE_MKSTEMP
2697 int fd;
2698 mode_t mask;
2699 Jim_Obj *filenameObj;
2700
2701 if (filename_template == NULL) {
2702 const char *tmpdir = getenv("TMPDIR");
2703 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2704 tmpdir = "/tmp/";
2705 }
2706 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
@@ -2689,21 +2708,15 @@
2708 Jim_AppendString(interp, filenameObj, "/", 1);
2709 }
2710 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2711 }
2712 else {
2713 filenameObj = Jim_NewStringObj(interp, filename_template, -1);
2714 }
2715
2716
2717 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
 
 
 
 
 
 
2718 fd = mkstemp(filenameObj->bytes);
2719 umask(mask);
2720 if (fd < 0) {
2721 JimAioSetError(interp, filenameObj);
2722 Jim_FreeNewObj(interp, filenameObj);
@@ -2731,11 +2744,11 @@
2744 Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
2745 #ifndef JIM_ANSIC
2746 Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
2747 #endif
2748
2749
2750 JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
2751 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2752 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2753
2754 return JIM_OK;
@@ -2831,20 +2844,20 @@
2844 {
2845 regex_t *compre;
2846 const char *pattern;
2847 int ret;
2848
2849
2850 if (objPtr->typePtr == &regexpObjType &&
2851 objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
2852
2853 return objPtr->internalRep.regexpValue.compre;
2854 }
2855
 
2856
2857
2858
2859 pattern = Jim_String(objPtr);
2860 compre = Jim_Alloc(sizeof(regex_t));
2861
2862 if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
2863 char buf[100];
@@ -3001,11 +3014,11 @@
3014 }
3015
3016 num_matches++;
3017
3018 if (opt_all && !opt_inline) {
3019
3020 goto try_next_match;
3021 }
3022
3023
3024 j = 0;
@@ -3041,11 +3054,11 @@
3054
3055 if (opt_inline) {
3056 Jim_ListAppendElement(interp, resultListObj, resultObj);
3057 }
3058 else {
3059
3060 result = Jim_SetVariable(interp, argv[i], resultObj);
3061
3062 if (result != JIM_OK) {
3063 Jim_FreeObj(interp, resultObj);
3064 break;
@@ -3168,11 +3181,11 @@
3181
3182 source_str = Jim_GetString(argv[i + 1], &source_len);
3183 replace_str = Jim_GetString(argv[i + 2], &replace_len);
3184 varname = argv[i + 3];
3185
3186
3187 resultObj = Jim_NewStringObj(interp, "", 0);
3188
3189 if (offset) {
3190 if (offset < 0) {
3191 offset += source_len + 1;
@@ -3183,11 +3196,11 @@
3196 else if (offset < 0) {
3197 offset = 0;
3198 }
3199 }
3200
3201
3202 Jim_AppendString(interp, resultObj, source_str, offset);
3203
3204
3205 n = source_len - offset;
3206 p = source_str + offset;
@@ -3242,23 +3255,23 @@
3255 }
3256
3257 p += pmatch[0].rm_eo;
3258 n -= pmatch[0].rm_eo;
3259
3260
3261 if (!opt_all || n == 0) {
3262 break;
3263 }
3264
3265
3266 if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
3267 break;
3268 }
3269
3270
3271 if (pattern[0] == '\0' && n) {
3272
3273 Jim_AppendString(interp, resultObj, p, 1);
3274 p++;
3275 n--;
3276 }
3277
@@ -3265,11 +3278,11 @@
3278 regexec_flags |= REG_NOTBOL;
3279 } while (n);
3280
3281 Jim_AppendString(interp, resultObj, p, -1);
3282
3283
3284 if (argc - i == 4) {
3285 result = Jim_SetVariable(interp, varname, resultObj);
3286
3287 if (result == JIM_OK) {
3288 Jim_SetResultInt(interp, num_matches);
@@ -3371,11 +3384,11 @@
3384 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
3385 }
3386
3387 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3388 {
3389
3390 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3391
3392 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3393 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3394 AppendStatElement(interp, listObj, "mode", sb->st_mode);
@@ -3387,36 +3400,38 @@
3400 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3401 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3402 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3403 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3404
3405
3406 if (varName) {
3407 Jim_Obj *objPtr;
3408 objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3409
3410 if (objPtr) {
3411 Jim_Obj *objv[2];
3412
3413 objv[0] = objPtr;
3414 objv[1] = listObj;
3415
3416 objPtr = Jim_DictMerge(interp, 2, objv);
3417 if (objPtr == NULL) {
3418
3419 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3420 Jim_FreeNewObj(interp, listObj);
3421 return JIM_ERR;
3422 }
3423
 
 
 
 
 
 
3424 Jim_InvalidateStringRep(objPtr);
3425
3426 Jim_FreeNewObj(interp, listObj);
3427 listObj = objPtr;
3428 }
3429 Jim_SetVariable(interp, varName, listObj);
3430 }
3431
3432
3433 Jim_SetResult(interp, listObj);
3434
3435 return JIM_OK;
3436 }
3437
@@ -3432,11 +3447,11 @@
3447 }
3448 else if (p == path) {
3449 Jim_SetResultString(interp, "/", -1);
3450 }
3451 else if (ISWINDOWS && p[-1] == ':') {
3452
3453 Jim_SetResultString(interp, path, p - path + 1);
3454 }
3455 else {
3456 Jim_SetResultString(interp, path, p - path);
3457 }
@@ -3512,35 +3527,35 @@
3527 char *newname = Jim_Alloc(MAXPATHLEN + 1);
3528 char *last = newname;
3529
3530 *newname = 0;
3531
3532
3533 for (i = 0; i < argc; i++) {
3534 int len;
3535 const char *part = Jim_GetString(argv[i], &len);
3536
3537 if (*part == '/') {
3538
3539 last = newname;
3540 }
3541 else if (ISWINDOWS && strchr(part, ':')) {
3542
3543 last = newname;
3544 }
3545 else if (part[0] == '.') {
3546 if (part[1] == '/') {
3547 part += 2;
3548 len -= 2;
3549 }
3550 else if (part[1] == 0 && last != newname) {
3551
3552 continue;
3553 }
3554 }
3555
3556
3557 if (last != newname && last[-1] != '/') {
3558 *last++ = '/';
3559 }
3560
3561 if (len) {
@@ -3551,22 +3566,22 @@
3566 }
3567 memcpy(last, part, len);
3568 last += len;
3569 }
3570
3571
3572 if (last > newname + 1 && last[-1] == '/') {
3573
3574 if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) {
3575 *--last = 0;
3576 }
3577 }
3578 }
3579
3580 *last = 0;
3581
3582
3583
3584 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
3585
3586 return JIM_OK;
3587 }
@@ -3591,11 +3606,11 @@
3606 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3607 {
3608 #ifdef X_OK
3609 return file_access(interp, argv[0], X_OK);
3610 #else
3611
3612 Jim_SetResultBool(interp, 1);
3613 return JIM_OK;
3614 #endif
3615 }
3616
@@ -3616,11 +3631,11 @@
3631 while (argc--) {
3632 const char *path = Jim_String(argv[0]);
3633
3634 if (unlink(path) == -1 && errno != ENOENT) {
3635 if (rmdir(path) == -1) {
3636
3637 if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
3638 Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
3639 strerror(errno));
3640 return JIM_ERR;
3641 }
@@ -3639,15 +3654,15 @@
3654
3655 static int mkdir_all(char *path)
3656 {
3657 int ok = 1;
3658
3659
3660 goto first;
3661
3662 while (ok--) {
3663
3664 {
3665 char *slash = strrchr(path, '/');
3666
3667 if (slash && slash != path) {
3668 *slash = 0;
@@ -3660,24 +3675,24 @@
3675 first:
3676 if (MKDIR_DEFAULT(path) == 0) {
3677 return 0;
3678 }
3679 if (errno == ENOENT) {
3680
3681 continue;
3682 }
3683
3684 if (errno == EEXIST) {
3685 struct stat sb;
3686
3687 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
3688 return 0;
3689 }
3690
3691 errno = EEXIST;
3692 }
3693
3694 break;
3695 }
3696 return -1;
3697 }
3698
@@ -3962,192 +3977,192 @@
3977 { "atime",
3978 "name",
3979 file_cmd_atime,
3980 1,
3981 1,
3982
3983 },
3984 { "mtime",
3985 "name ?time?",
3986 file_cmd_mtime,
3987 1,
3988 2,
3989
3990 },
3991 { "copy",
3992 "?-force? source dest",
3993 file_cmd_copy,
3994 2,
3995 3,
3996
3997 },
3998 { "dirname",
3999 "name",
4000 file_cmd_dirname,
4001 1,
4002 1,
4003
4004 },
4005 { "rootname",
4006 "name",
4007 file_cmd_rootname,
4008 1,
4009 1,
4010
4011 },
4012 { "extension",
4013 "name",
4014 file_cmd_extension,
4015 1,
4016 1,
4017
4018 },
4019 { "tail",
4020 "name",
4021 file_cmd_tail,
4022 1,
4023 1,
4024
4025 },
4026 { "normalize",
4027 "name",
4028 file_cmd_normalize,
4029 1,
4030 1,
4031
4032 },
4033 { "join",
4034 "name ?name ...?",
4035 file_cmd_join,
4036 1,
4037 -1,
4038
4039 },
4040 { "readable",
4041 "name",
4042 file_cmd_readable,
4043 1,
4044 1,
4045
4046 },
4047 { "writable",
4048 "name",
4049 file_cmd_writable,
4050 1,
4051 1,
4052
4053 },
4054 { "executable",
4055 "name",
4056 file_cmd_executable,
4057 1,
4058 1,
4059
4060 },
4061 { "exists",
4062 "name",
4063 file_cmd_exists,
4064 1,
4065 1,
4066
4067 },
4068 { "delete",
4069 "?-force|--? name ...",
4070 file_cmd_delete,
4071 1,
4072 -1,
4073
4074 },
4075 { "mkdir",
4076 "dir ...",
4077 file_cmd_mkdir,
4078 1,
4079 -1,
4080
4081 },
4082 { "tempfile",
4083 "?template?",
4084 file_cmd_tempfile,
4085 0,
4086 1,
4087
4088 },
4089 { "rename",
4090 "?-force? source dest",
4091 file_cmd_rename,
4092 2,
4093 3,
4094
4095 },
4096 #if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
4097 { "link",
4098 "?-symbolic|-hard? newname target",
4099 file_cmd_link,
4100 2,
4101 3,
4102
4103 },
4104 #endif
4105 #if defined(HAVE_READLINK)
4106 { "readlink",
4107 "name",
4108 file_cmd_readlink,
4109 1,
4110 1,
4111
4112 },
4113 #endif
4114 { "size",
4115 "name",
4116 file_cmd_size,
4117 1,
4118 1,
4119
4120 },
4121 { "stat",
4122 "name ?var?",
4123 file_cmd_stat,
4124 1,
4125 2,
4126
4127 },
4128 { "lstat",
4129 "name ?var?",
4130 file_cmd_lstat,
4131 1,
4132 2,
4133
4134 },
4135 { "type",
4136 "name",
4137 file_cmd_type,
4138 1,
4139 1,
4140
4141 },
4142 #ifdef HAVE_GETEUID
4143 { "owned",
4144 "name",
4145 file_cmd_owned,
4146 1,
4147 1,
4148
4149 },
4150 #endif
4151 { "isdirectory",
4152 "name",
4153 file_cmd_isdirectory,
4154 1,
4155 1,
4156
4157 },
4158 { "isfile",
4159 "name",
4160 file_cmd_isfile,
4161 1,
4162 1,
4163
4164 },
4165 {
4166 NULL
4167 }
4168 };
@@ -4179,11 +4194,11 @@
4194 Jim_SetResultString(interp, "Failed to get pwd", -1);
4195 Jim_Free(cwd);
4196 return JIM_ERR;
4197 }
4198 else if (ISWINDOWS) {
4199
4200 char *p = cwd;
4201 while ((p = strchr(p, '\\')) != NULL) {
4202 *p++ = '/';
4203 }
4204 }
@@ -4203,10 +4218,13 @@
4218 Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
4219 Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
4220 return JIM_OK;
4221 }
4222
4223 #ifndef _GNU_SOURCE
4224 #define _GNU_SOURCE
4225 #endif
4226 #include <string.h>
4227 #include <ctype.h>
4228
4229
4230 #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
@@ -4214,20 +4232,20 @@
4232 {
4233 Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
4234 int i, j;
4235 int rc;
4236
4237
4238 for (i = 1; i < argc; i++) {
4239 int len;
4240 const char *arg = Jim_GetString(argv[i], &len);
4241
4242 if (i > 1) {
4243 Jim_AppendString(interp, cmdlineObj, " ", 1);
4244 }
4245 if (strpbrk(arg, "\\\" ") == NULL) {
4246
4247 Jim_AppendString(interp, cmdlineObj, arg, len);
4248 continue;
4249 }
4250
4251 Jim_AppendString(interp, cmdlineObj, "\"", 1);
@@ -4268,11 +4286,11 @@
4286
4287 #include <errno.h>
4288 #include <signal.h>
4289
4290 #if defined(__MINGW32__)
4291
4292 #ifndef STRICT
4293 #define STRICT
4294 #endif
4295 #define WIN32_LEAN_AND_MEAN
4296 #include <windows.h>
@@ -4294,11 +4312,11 @@
4312 static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
4313 static fdtype JimDupFd(fdtype infd);
4314 static fdtype JimOpenForRead(const char *filename);
4315 static FILE *JimFdOpenForRead(fdtype fd);
4316 static int JimPipe(fdtype pipefd[2]);
4317 static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env,
4318 fdtype inputId, fdtype outputId, fdtype errorId);
4319 static int JimErrno(void);
4320 #else
4321 #include <unistd.h>
4322 #include <fcntl.h>
@@ -4323,10 +4341,11 @@
4341 #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
4342 #endif
4343 #endif
4344
4345 static const char *JimStrError(void);
4346 static char **JimOriginalEnviron(void);
4347 static char **JimSaveEnv(char **env);
4348 static void JimRestoreEnv(char **env);
4349 static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
4350 pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
4351 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
@@ -4390,18 +4409,18 @@
4409 char *envdata;
4410
4411 Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
4412
4413 if (!objPtr) {
4414 return JimOriginalEnviron();
4415 }
4416
4417
4418
4419 num = Jim_ListLength(interp, objPtr);
4420 if (num % 2) {
4421
4422 num--;
4423 }
4424 size = Jim_Length(objPtr) + 2;
4425
4426 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4493,19 +4512,19 @@
4512 }
4513
4514
4515 struct WaitInfo
4516 {
4517 pidtype pid;
4518 int status;
4519 int flags;
4520 };
4521
4522 struct WaitInfoTable {
4523 struct WaitInfo *info;
4524 int size;
4525 int used;
4526 };
4527
4528
4529 #define WI_DETACHED 2
4530
@@ -4528,12 +4547,12 @@
4547 return table;
4548 }
4549
4550 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4551 {
4552 fdtype outputId;
4553 fdtype errorId;
4554 pidtype *pidPtr;
4555 int numPids, result;
4556 int child_siginfo = 1;
4557 Jim_Obj *childErrObj;
4558 Jim_Obj *errStrObj;
@@ -4545,11 +4564,11 @@
4564 argc--;
4565 numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
4566 if (numPids < 0) {
4567 return JIM_ERR;
4568 }
4569
4570 listObj = Jim_NewListObj(interp, NULL, 0);
4571 for (i = 0; i < numPids; i++) {
4572 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
4573 }
4574 Jim_SetResult(interp, listObj);
@@ -4567,19 +4586,19 @@
4586
4587 result = JIM_OK;
4588
4589 errStrObj = Jim_NewStringObj(interp, "", 0);
4590
4591
4592 if (outputId != JIM_BAD_FD) {
4593 if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
4594 result = JIM_ERR;
4595 Jim_SetResultErrno(interp, "error reading from output pipe");
4596 }
4597 }
4598
4599
4600 childErrObj = Jim_NewStringObj(interp, "", 0);
4601 Jim_IncrRefCount(childErrObj);
4602
4603 if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
4604 result = JIM_ERR;
@@ -4592,25 +4611,25 @@
4611 if (ret < 0) {
4612 Jim_SetResultErrno(interp, "error reading from error pipe");
4613 result = JIM_ERR;
4614 }
4615 else if (ret > 0) {
4616
4617 child_siginfo = 0;
4618 }
4619 }
4620
4621 if (child_siginfo) {
4622
4623 Jim_AppendObj(interp, errStrObj, childErrObj);
4624 }
4625 Jim_DecrRefCount(interp, childErrObj);
4626
4627
4628 Jim_RemoveTrailingNewline(errStrObj);
4629
4630
4631 Jim_SetResult(interp, errStrObj);
4632
4633 return result;
4634 }
4635
@@ -4629,11 +4648,11 @@
4648 for (count = table->used; count > 0; waitPtr++, count--) {
4649 if (waitPtr->flags & WI_DETACHED) {
4650 int status;
4651 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4652 if (pid == waitPtr->pid) {
4653
4654 table->used--;
4655 continue;
4656 }
4657 }
4658 if (waitPtr != &table->info[dest]) {
@@ -4645,36 +4664,36 @@
4664
4665 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4666 {
4667 int i;
4668
4669
4670 for (i = 0; i < table->used; i++) {
4671 if (pid == table->info[i].pid) {
4672
4673 JimWaitPid(pid, statusPtr, 0);
4674
4675
4676 if (i != table->used - 1) {
4677 table->info[i] = table->info[table->used - 1];
4678 }
4679 table->used--;
4680 return pid;
4681 }
4682 }
4683
4684
4685 return JIM_BAD_PID;
4686 }
4687
4688 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4689 {
4690 int j;
4691 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4692
4693 for (j = 0; j < numPids; j++) {
4694
4695 int i;
4696 for (i = 0; i < table->used; i++) {
4697 if (pidPtr[j] == table->info[i].pid) {
4698 table->info[i].flags |= WI_DETACHED;
4699 break;
@@ -4707,16 +4726,16 @@
4726 int cmdCount; /* Count of number of distinct commands
4727 * found in argc/argv. */
4728 const char *input = NULL; /* Describes input for pipeline, depending
4729 * on "inputFile". NULL means take input
4730 * from stdin/pipe. */
4731 int input_len = 0;
4732
4733 #define FILE_NAME 0
4734 #define FILE_APPEND 1
4735 #define FILE_HANDLE 2
4736 #define FILE_TEXT 3
4737
4738 int inputFile = FILE_NAME; /* 1 means input is name of input file.
4739 * 2 means input is filehandle name.
4740 * 0 means input holds actual
4741 * text to be input to command. */
@@ -4737,20 +4756,20 @@
4756 * or NULL if stderr goes to stderr/pipe. */
4757 fdtype inputId = JIM_BAD_FD;
4758 fdtype outputId = JIM_BAD_FD;
4759 fdtype errorId = JIM_BAD_FD;
4760 fdtype lastOutputId = JIM_BAD_FD;
4761 fdtype pipeIds[2];
4762 int firstArg, lastArg; /* Indexes of first and last arguments in
4763 * current command. */
4764 int lastBar;
4765 int i;
4766 pidtype pid;
4767 char **save_environ;
4768 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
4769
4770
4771 char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
4772 int arg_count = 0;
4773
4774 JimReapDetachedPids(table);
4775
@@ -4796,11 +4815,11 @@
4815 if (*output == '>') {
4816 outputFile = FILE_APPEND;
4817 output++;
4818 }
4819 if (*output == '&') {
4820
4821 output++;
4822 dup_error = 1;
4823 }
4824 if (*output == '@') {
4825 outputFile = FILE_HANDLE;
@@ -4837,11 +4856,11 @@
4856 goto badargs;
4857 }
4858 lastBar = i;
4859 cmdCount++;
4860 }
4861
4862 arg_array[arg_count++] = (char *)arg;
4863 continue;
4864 }
4865
4866 if (i >= argc) {
@@ -4855,11 +4874,11 @@
4874 badargs:
4875 Jim_Free(arg_array);
4876 return -1;
4877 }
4878
4879
4880 save_environ = JimSaveEnv(JimBuildEnv(interp));
4881
4882 if (input != NULL) {
4883 if (inputFile == FILE_TEXT) {
4884 inputId = JimCreateTemp(interp, input, input_len);
@@ -4866,11 +4885,11 @@
4885 if (inputId == JIM_BAD_FD) {
4886 goto error;
4887 }
4888 }
4889 else if (inputFile == FILE_HANDLE) {
4890
4891 FILE *fh = JimGetAioFilehandle(interp, input);
4892
4893 if (fh == NULL) {
4894 goto error;
4895 }
@@ -4918,20 +4937,20 @@
4937 }
4938 lastOutputId = pipeIds[1];
4939 *outPipePtr = pipeIds[0];
4940 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
4941 }
4942
4943 if (error != NULL) {
4944 if (errorFile == FILE_HANDLE) {
4945 if (strcmp(error, "1") == 0) {
4946
4947 if (lastOutputId != JIM_BAD_FD) {
4948 errorId = JimDupFd(lastOutputId);
4949 }
4950 else {
4951
4952 error = "stdout";
4953 }
4954 }
4955 if (errorId == JIM_BAD_FD) {
4956 FILE *fh = JimGetAioFilehandle(interp, error);
@@ -4973,11 +4992,11 @@
4992 pipe_dup_err = 1;
4993 }
4994 break;
4995 }
4996 }
4997
4998 arg_array[lastArg] = NULL;
4999 if (lastArg == arg_count) {
5000 outputId = lastOutputId;
5001 }
5002 else {
@@ -4986,19 +5005,19 @@
5005 goto error;
5006 }
5007 outputId = pipeIds[1];
5008 }
5009
5010
5011 if (pipe_dup_err) {
5012 errorId = outputId;
5013 }
5014
5015
5016
5017 #ifdef __MINGW32__
5018 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
5019 if (pid == JIM_BAD_PID) {
5020 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
5021 goto error;
5022 }
5023 #else
@@ -5006,32 +5025,39 @@
5025 if (pid < 0) {
5026 Jim_SetResultErrno(interp, "couldn't fork child process");
5027 goto error;
5028 }
5029 if (pid == 0) {
5030
5031
5032 if (inputId != -1) dup2(inputId, 0);
5033 if (outputId != -1) dup2(outputId, 1);
5034 if (errorId != -1) dup2(errorId, 2);
5035
5036 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
5037 close(i);
5038 }
5039
5040
5041 (void)signal(SIGPIPE, SIG_DFL);
5042
5043 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
5044
5045
5046 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
5047 #ifdef JIM_MAINTAINER
5048 {
5049
5050 static char *const false_argv[2] = {"false", NULL};
5051 execvp(false_argv[0],false_argv);
5052 }
5053 #endif
5054 _exit(127);
5055 }
5056 #endif
5057
5058
5059
5060 if (table->used == table->size) {
5061 table->size += WAIT_TABLE_GROW_BY;
5062 table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
5063 }
@@ -5040,19 +5066,20 @@
5066 table->info[table->used].flags = 0;
5067 table->used++;
5068
5069 pidPtr[numPids] = pid;
5070
5071
5072 errorId = origErrorId;
5073
5074
5075 if (inputId != JIM_BAD_FD) {
5076 JimCloseFd(inputId);
5077 }
5078 if (outputId != JIM_BAD_FD) {
5079 JimCloseFd(outputId);
5080 outputId = JIM_BAD_FD;
5081 }
5082 inputId = pipeIds[0];
5083 pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
5084 }
5085 *pidArrayPtr = pidPtr;
@@ -5111,11 +5138,11 @@
5138 {
5139 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
5140 int result = JIM_OK;
5141 int i;
5142
5143
5144 for (i = 0; i < numPids; i++) {
5145 int waitStatus = 0;
5146 if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
5147 if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
5148 result = JIM_ERR;
@@ -5284,17 +5311,21 @@
5311 }
5312
5313 static fdtype JimOpenForRead(const char *filename)
5314 {
5315 return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
5316 JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
5317 }
5318
5319 static fdtype JimOpenForWrite(const char *filename, int append)
5320 {
5321 fdtype fd = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5322 JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
5323 if (append && fd != JIM_BAD_FD) {
5324 SetFilePointer(fd, 0, NULL, FILE_END);
5325 }
5326 return fd;
5327 }
5328
5329 static FILE *JimFdOpenForWrite(fdtype fd)
5330 {
5331 return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
@@ -5302,11 +5333,11 @@
5333
5334 static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
5335 {
5336 DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
5337 if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
5338
5339 return JIM_BAD_PID;
5340 }
5341 GetExitCodeProcess(pid, &ret);
5342 *status = ret;
5343 CloseHandle(pid);
@@ -5329,11 +5360,11 @@
5360 if (handle == INVALID_HANDLE_VALUE) {
5361 goto error;
5362 }
5363
5364 if (contents != NULL) {
5365
5366 FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
5367 if (fh == NULL) {
5368 goto error;
5369 }
5370
@@ -5381,10 +5412,15 @@
5412
5413 static void JimRestoreEnv(char **env)
5414 {
5415 JimFreeEnv(env, Jim_GetEnviron());
5416 }
5417
5418 static char **JimOriginalEnviron(void)
5419 {
5420 return NULL;
5421 }
5422
5423 static Jim_Obj *
5424 JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
5425 {
5426 char *start, *special;
@@ -5455,18 +5491,19 @@
5491 }
5492 return strObj;
5493 }
5494
5495 static pidtype
5496 JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, fdtype inputId, fdtype outputId, fdtype errorId)
5497 {
5498 STARTUPINFO startInfo;
5499 PROCESS_INFORMATION procInfo;
5500 HANDLE hProcess, h;
5501 char execPath[MAX_PATH];
5502 pidtype pid = JIM_BAD_PID;
5503 Jim_Obj *cmdLineObj;
5504 char *winenv;
5505
5506 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5507 return JIM_BAD_PID;
5508 }
5509 argv[0] = execPath;
@@ -5514,13 +5551,24 @@
5551 0, TRUE, DUPLICATE_SAME_ACCESS);
5552 }
5553 if (startInfo.hStdError == JIM_BAD_FD) {
5554 goto end;
5555 }
5556
5557 if (env == NULL) {
5558
5559 winenv = NULL;
5560 }
5561 else if (env[0] == NULL) {
5562 winenv = (char *)"\0";
5563 }
5564 else {
5565 winenv = env[0];
5566 }
5567
5568 if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
5569 0, winenv, NULL, &startInfo, &procInfo)) {
5570 goto end;
5571 }
5572
5573
5574 WaitForInputIdle(procInfo.hProcess, 5000);
@@ -5568,10 +5616,15 @@
5616 lseek(fd, 0L, SEEK_SET);
5617 }
5618 }
5619 return fd;
5620 }
5621
5622 static char **JimOriginalEnviron(void)
5623 {
5624 return Jim_GetEnviron();
5625 }
5626
5627 static char **JimSaveEnv(char **env)
5628 {
5629 char **saveenv = Jim_GetEnviron();
5630 Jim_SetEnviron(env);
@@ -5601,11 +5654,11 @@
5654 #include <sys/time.h>
5655 #endif
5656
5657 static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5658 {
5659
5660 char buf[100];
5661 time_t t;
5662 long seconds;
5663
5664 const char *format = "%a %b %d %H:%M:%S %Z %Y";
@@ -5642,20 +5695,20 @@
5695
5696 if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
5697 return -1;
5698 }
5699
5700
5701 localtime_r(&now, &tm);
5702
5703 pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
5704 if (pt == 0 || *pt != 0) {
5705 Jim_SetResultString(interp, "Failed to parse time according to format", -1);
5706 return JIM_ERR;
5707 }
5708
5709
5710 Jim_SetResultInt(interp, mktime(&tm));
5711
5712 return JIM_OK;
5713 }
5714 #endif
@@ -5693,47 +5746,47 @@
5746 { "seconds",
5747 NULL,
5748 clock_cmd_seconds,
5749 0,
5750 0,
5751
5752 },
5753 { "clicks",
5754 NULL,
5755 clock_cmd_micros,
5756 0,
5757 0,
5758
5759 },
5760 { "microseconds",
5761 NULL,
5762 clock_cmd_micros,
5763 0,
5764 0,
5765
5766 },
5767 { "milliseconds",
5768 NULL,
5769 clock_cmd_millis,
5770 0,
5771 0,
5772
5773 },
5774 { "format",
5775 "seconds ?-format format?",
5776 clock_cmd_format,
5777 1,
5778 3,
5779
5780 },
5781 #ifdef HAVE_STRPTIME
5782 { "scan",
5783 "str -format format",
5784 clock_cmd_scan,
5785 3,
5786 3,
5787
5788 },
5789 #endif
5790 { NULL }
5791 };
5792
@@ -5753,12 +5806,13 @@
5806 #include <errno.h>
5807
5808
5809 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5810 {
5811
5812 Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5813 Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
5814 return JIM_OK;
5815 }
5816
5817 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5818 {
@@ -5769,21 +5823,20 @@
5823 return JIM_OK;
5824 }
5825
5826 patternObj = (argc == 1) ? NULL : argv[1];
5827
5828
5829 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5830 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5831
5832 Jim_SetResult(interp, objPtr);
5833 return JIM_OK;
5834 }
5835 }
5836
5837 return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES);
 
5838 }
5839
5840 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5841 {
5842 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5790,11 +5843,11 @@
5843
5844 if (!objPtr) {
5845 return JIM_OK;
5846 }
5847
5848 return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS);
5849 }
5850
5851 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5852 {
5853 int i;
@@ -5802,27 +5855,29 @@
5855 Jim_Obj *resultObj;
5856 Jim_Obj *objPtr;
5857 Jim_Obj **dictValuesObj;
5858
5859 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5860
5861 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5862 return JIM_OK;
5863 }
5864
5865 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5866
5867 if (objPtr == NULL) {
5868
5869 return JIM_OK;
5870 }
5871
5872 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5873
5874 Jim_SetResultString(interp, "", -1);
5875 return JIM_OK;
5876 }
5877
5878
5879 resultObj = Jim_NewDictObj(interp, NULL, 0);
5880
5881 for (i = 0; i < len; i += 2) {
5882 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
5883 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
@@ -5837,16 +5892,18 @@
5892 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5893 {
5894 Jim_Obj *objPtr;
5895 int len = 0;
5896
5897
5898 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5899 if (objPtr) {
5900 len = Jim_DictSize(interp, objPtr);
5901 if (len < 0) {
5902
5903 Jim_SetResultInt(interp, 0);
5904 return JIM_OK;
5905 }
5906 }
5907
5908 Jim_SetResultInt(interp, len);
5909
@@ -5876,11 +5933,11 @@
5933 return JIM_ERR;
5934 }
5935
5936 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5937 if (!dictObj) {
5938
5939 return Jim_SetVariable(interp, argv[0], listObj);
5940 }
5941 else if (Jim_DictSize(interp, dictObj) < 0) {
5942 return JIM_ERR;
5943 }
@@ -5905,53 +5962,53 @@
5962 { "exists",
5963 "arrayName",
5964 array_cmd_exists,
5965 1,
5966 1,
5967
5968 },
5969 { "get",
5970 "arrayName ?pattern?",
5971 array_cmd_get,
5972 1,
5973 2,
5974
5975 },
5976 { "names",
5977 "arrayName ?pattern?",
5978 array_cmd_names,
5979 1,
5980 2,
5981
5982 },
5983 { "set",
5984 "arrayName list",
5985 array_cmd_set,
5986 2,
5987 2,
5988
5989 },
5990 { "size",
5991 "arrayName",
5992 array_cmd_size,
5993 1,
5994 1,
5995
5996 },
5997 { "stat",
5998 "arrayName",
5999 array_cmd_stat,
6000 1,
6001 1,
6002
6003 },
6004 { "unset",
6005 "arrayName ?pattern?",
6006 array_cmd_unset,
6007 1,
6008 2,
6009
6010 },
6011 { NULL
6012 }
6013 };
6014
@@ -5987,11 +6044,14 @@
6044 Jim_arrayInit(interp);
6045 Jim_stdlibInit(interp);
6046 Jim_tclcompatInit(interp);
6047 return JIM_OK;
6048 }
6049 #define JIM_OPTIMIZATION
6050 #ifndef _GNU_SOURCE
6051 #define _GNU_SOURCE
6052 #endif
6053
6054 #include <stdio.h>
6055 #include <stdlib.h>
6056
6057 #include <string.h>
@@ -6056,10 +6116,16 @@
6116 #define JimPanic(X) JimPanicDump X
6117 #else
6118 #define JimPanic(X)
6119 #endif
6120
6121 #ifdef JIM_OPTIMIZATION
6122 #define JIM_IF_OPTIM(X) X
6123 #else
6124 #define JIM_IF_OPTIM(X)
6125 #endif
6126
6127
6128 static char JimEmptyStringRep[] = "";
6129
6130 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
6131 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6112,34 +6178,34 @@
6178 if (*pattern == '^') {
6179 not++;
6180 pattern++;
6181 }
6182
6183
6184 if (*pattern == ']') {
6185 goto first;
6186 }
6187 }
6188
6189 while (*pattern && *pattern != ']') {
6190
6191 if (pattern[0] == '\\') {
6192 first:
6193 pattern += utf8_tounicode_case(pattern, &pchar, nocase);
6194 }
6195 else {
6196
6197 int start;
6198 int end;
6199
6200 pattern += utf8_tounicode_case(pattern, &start, nocase);
6201 if (pattern[0] == '-' && pattern[1]) {
6202
6203 pattern += utf8_tounicode(pattern, &pchar);
6204 pattern += utf8_tounicode_case(pattern, &end, nocase);
6205
6206
6207 if ((c >= start && c <= end) || (c >= end && c <= start)) {
6208 match = 1;
6209 }
6210 continue;
6211 }
@@ -6169,19 +6235,19 @@
6235 while (pattern[1] == '*') {
6236 pattern++;
6237 }
6238 pattern++;
6239 if (!pattern[0]) {
6240 return 1;
6241 }
6242 while (*string) {
6243
6244 if (JimGlobMatch(pattern, string, nocase))
6245 return 1;
6246 string += utf8_tounicode(string, &c);
6247 }
6248 return 0;
6249
6250 case '?':
6251 string += utf8_tounicode(string, &c);
6252 break;
6253
@@ -6190,20 +6256,20 @@
6256 pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
6257 if (!pattern) {
6258 return 0;
6259 }
6260 if (!*pattern) {
6261
6262 continue;
6263 }
6264 break;
6265 }
6266 case '\\':
6267 if (pattern[1]) {
6268 pattern++;
6269 }
6270
6271 default:
6272 string += utf8_tounicode_case(string, &c, nocase);
6273 utf8_tounicode_case(pattern, &pchar, nocase);
6274 if (pchar != c) {
6275 return 0;
@@ -6249,11 +6315,11 @@
6315 maxchars--;
6316 }
6317 if (!maxchars) {
6318 return 0;
6319 }
6320
6321 if (*s1) {
6322 return 1;
6323 }
6324 if (*s2) {
6325 return -1;
@@ -6290,11 +6356,11 @@
6356 const char *p;
6357
6358 if (!l1 || !l2 || l1 > l2)
6359 return -1;
6360
6361
6362 for (p = s2 + l2 - 1; p != s2 - 1; p--) {
6363 if (*p == *s1 && memcmp(s1, p, l1) == 0) {
6364 return p - s2;
6365 }
6366 }
@@ -6349,28 +6415,28 @@
6415 }
6416 *sign = 1;
6417 }
6418
6419 if (str[i] != '0') {
6420
6421 return 0;
6422 }
6423
6424
6425 switch (str[i + 1]) {
6426 case 'x': case 'X': *base = 16; break;
6427 case 'o': case 'O': *base = 8; break;
6428 case 'b': case 'B': *base = 2; break;
6429 default: return 0;
6430 }
6431 i += 2;
6432
6433 if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
6434
6435 return i;
6436 }
6437
6438 *base = 10;
6439 return 0;
6440 }
6441
6442 static long jim_strtol(const char *str, char **endptr)
@@ -6384,11 +6450,11 @@
6450 if (endptr == NULL || *endptr != str + i) {
6451 return value * sign;
6452 }
6453 }
6454
6455
6456 return strtol(str, endptr, 10);
6457 }
6458
6459
6460 static jim_wide jim_strtoull(const char *str, char **endptr)
@@ -6403,11 +6469,11 @@
6469 if (endptr == NULL || *endptr != str + i) {
6470 return value * sign;
6471 }
6472 }
6473
6474
6475 return strtoull(str, endptr, 10);
6476 #else
6477 return (unsigned long)jim_strtol(str, endptr);
6478 #endif
6479 }
@@ -6428,26 +6494,40 @@
6494
6495 int Jim_StringToDouble(const char *str, double *doublePtr)
6496 {
6497 char *endptr;
6498
6499
6500 errno = 0;
6501
6502 *doublePtr = strtod(str, &endptr);
6503
6504 return JimCheckConversion(str, endptr);
6505 }
6506
6507 static jim_wide JimPowWide(jim_wide b, jim_wide e)
6508 {
6509 jim_wide res = 1;
6510
6511
6512 if (b == 1) {
6513
6514 return 1;
6515 }
6516 if (e < 0) {
6517 if (b != -1) {
6518 return 0;
6519 }
6520 e = -e;
6521 }
6522 while (e)
6523 {
6524 if (e & 1) {
6525 res *= b;
6526 }
6527 e >>= 1;
6528 b *= b;
6529 }
6530 return res;
6531 }
6532
6533 #ifdef JIM_DEBUG_PANIC
@@ -6509,11 +6589,11 @@
6589 char *Jim_StrDupLen(const char *s, int l)
6590 {
6591 char *copy = Jim_Alloc(l + 1);
6592
6593 memcpy(copy, s, l + 1);
6594 copy[l] = 0;
6595 return copy;
6596 }
6597
6598
6599
@@ -6598,52 +6678,52 @@
6678 }
6679
6680
6681 void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
6682 {
6683 Jim_HashTable n;
6684 unsigned int realsize = JimHashTableNextPower(size), i;
6685
6686 if (size <= ht->used)
6687 return;
6688
6689 Jim_InitHashTable(&n, ht->type, ht->privdata);
6690 n.size = realsize;
6691 n.sizemask = realsize - 1;
6692 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6693
6694 n.uniq = ht->uniq;
6695
6696
6697 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6698
6699 n.used = ht->used;
6700 for (i = 0; ht->used > 0; i++) {
6701 Jim_HashEntry *he, *nextHe;
6702
6703 if (ht->table[i] == NULL)
6704 continue;
6705
6706
6707 he = ht->table[i];
6708 while (he) {
6709 unsigned int h;
6710
6711 nextHe = he->next;
6712
6713 h = Jim_HashKey(ht, he->key) & n.sizemask;
6714 he->next = n.table[h];
6715 n.table[h] = he;
6716 ht->used--;
6717
6718 he = nextHe;
6719 }
6720 }
6721 assert(ht->used == 0);
6722 Jim_Free(ht->table);
6723
6724
6725 *ht = n;
6726 }
6727
6728
6729 int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
@@ -6652,11 +6732,11 @@
6732
6733 entry = JimInsertHashEntry(ht, key, 0);
6734 if (entry == NULL)
6735 return JIM_ERR;
6736
6737
6738 Jim_SetHashKey(ht, entry, key);
6739 Jim_SetHashVal(ht, entry, val);
6740 return JIM_OK;
6741 }
6742
@@ -6678,11 +6758,11 @@
6758 Jim_SetHashVal(ht, entry, val);
6759 }
6760 existed = 1;
6761 }
6762 else {
6763
6764 Jim_SetHashKey(ht, entry, key);
6765 Jim_SetHashVal(ht, entry, val);
6766 existed = 0;
6767 }
6768
@@ -6701,11 +6781,11 @@
6781 he = ht->table[h];
6782
6783 prevHe = NULL;
6784 while (he) {
6785 if (Jim_CompareHashKeys(ht, key, he->key)) {
6786
6787 if (prevHe)
6788 prevHe->next = he->next;
6789 else
6790 ht->table[h] = he->next;
6791 Jim_FreeEntryKey(ht, he);
@@ -6715,19 +6795,19 @@
6795 return JIM_OK;
6796 }
6797 prevHe = he;
6798 he = he->next;
6799 }
6800 return JIM_ERR;
6801 }
6802
6803
6804 int Jim_FreeHashTable(Jim_HashTable *ht)
6805 {
6806 unsigned int i;
6807
6808
6809 for (i = 0; ht->used > 0; i++) {
6810 Jim_HashEntry *he, *nextHe;
6811
6812 if ((he = ht->table[i]) == NULL)
6813 continue;
@@ -6738,15 +6818,15 @@
6818 Jim_Free(he);
6819 ht->used--;
6820 he = nextHe;
6821 }
6822 }
6823
6824 Jim_Free(ht->table);
6825
6826 JimResetHashTable(ht);
6827 return JIM_OK;
6828 }
6829
6830 Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
6831 {
6832 Jim_HashEntry *he;
@@ -6819,24 +6899,24 @@
6899 static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
6900 {
6901 unsigned int h;
6902 Jim_HashEntry *he;
6903
6904
6905 JimExpandHashTableIfNeeded(ht);
6906
6907
6908 h = Jim_HashKey(ht, key) & ht->sizemask;
6909
6910 he = ht->table[h];
6911 while (he) {
6912 if (Jim_CompareHashKeys(ht, key, he->key))
6913 return replace ? he : NULL;
6914 he = he->next;
6915 }
6916
6917
6918 he = Jim_Alloc(sizeof(*he));
6919 he->next = ht->table[h];
6920 ht->table[h] = he;
6921 ht->used++;
6922 he->key = NULL;
@@ -6865,16 +6945,16 @@
6945 {
6946 Jim_Free(key);
6947 }
6948
6949 static const Jim_HashTableType JimPackageHashTableType = {
6950 JimStringCopyHTHashFunction,
6951 JimStringCopyHTDup,
6952 NULL,
6953 JimStringCopyHTKeyCompare,
6954 JimStringCopyHTKeyDestructor,
6955 NULL
6956 };
6957
6958 typedef struct AssocDataValue
6959 {
6960 Jim_InterpDeleteProc *delProc;
@@ -6889,16 +6969,16 @@
6969 assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
6970 Jim_Free(data);
6971 }
6972
6973 static const Jim_HashTableType JimAssocDataHashTableType = {
6974 JimStringCopyHTHashFunction,
6975 JimStringCopyHTDup,
6976 NULL,
6977 JimStringCopyHTKeyCompare,
6978 JimStringCopyHTKeyDestructor,
6979 JimAssocDataHashTableValueDestructor
6980 };
6981
6982 void Jim_InitStack(Jim_Stack *stack)
6983 {
6984 stack->len = 0;
@@ -6951,56 +7031,61 @@
7031 freeFunc(stack->vector[i]);
7032 }
7033
7034
7035
7036 #define JIM_TT_NONE 0
7037 #define JIM_TT_STR 1
7038 #define JIM_TT_ESC 2
7039 #define JIM_TT_VAR 3
7040 #define JIM_TT_DICTSUGAR 4
7041 #define JIM_TT_CMD 5
7042
7043 #define JIM_TT_SEP 6
7044 #define JIM_TT_EOL 7
7045 #define JIM_TT_EOF 8
7046
7047 #define JIM_TT_LINE 9
7048 #define JIM_TT_WORD 10
7049
7050
7051 #define JIM_TT_SUBEXPR_START 11
7052 #define JIM_TT_SUBEXPR_END 12
7053 #define JIM_TT_SUBEXPR_COMMA 13
7054 #define JIM_TT_EXPR_INT 14
7055 #define JIM_TT_EXPR_DOUBLE 15
7056 #define JIM_TT_EXPR_BOOLEAN 16
7057
7058 #define JIM_TT_EXPRSUGAR 17
7059
7060
7061 #define JIM_TT_EXPR_OP 20
7062
7063 #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
7064
7065 #define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA)
7066
7067 #define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP)
7068
7069 struct JimParseMissing {
7070 int ch;
7071 int line;
7072 };
7073
7074 struct JimParserCtx
7075 {
7076 const char *p;
7077 int len;
7078 int linenr;
7079 const char *tstart;
7080 const char *tend;
7081 int tline;
7082 int tt;
7083 int eof;
7084 int inquote;
7085 int comment;
7086 struct JimParseMissing missing;
7087 };
7088
7089 static int JimParseScript(struct JimParserCtx *pc);
7090 static int JimParseSep(struct JimParserCtx *pc);
7091 static int JimParseEol(struct JimParserCtx *pc);
@@ -7030,11 +7115,11 @@
7115 pc->missing.line = linenr;
7116 }
7117
7118 static int JimParseScript(struct JimParserCtx *pc)
7119 {
7120 while (1) {
7121 if (!pc->len) {
7122 pc->tstart = pc->p;
7123 pc->tend = pc->p - 1;
7124 pc->tline = pc->linenr;
7125 pc->tt = JIM_TT_EOL;
@@ -7066,11 +7151,11 @@
7151 pc->comment = 0;
7152 return JimParseCmd(pc);
7153 case '$':
7154 pc->comment = 0;
7155 if (JimParseVar(pc) == JIM_ERR) {
7156
7157 pc->tstart = pc->tend = pc->p++;
7158 pc->len--;
7159 pc->tt = JIM_TT_ESC;
7160 }
7161 return JIM_OK;
@@ -7127,11 +7212,11 @@
7212
7213 static void JimParseSubBrace(struct JimParserCtx *pc)
7214 {
7215 int level = 1;
7216
7217
7218 pc->p++;
7219 pc->len--;
7220 while (pc->len) {
7221 switch (*pc->p) {
7222 case '\\':
@@ -7171,11 +7256,11 @@
7256 static int JimParseSubQuote(struct JimParserCtx *pc)
7257 {
7258 int tt = JIM_TT_STR;
7259 int line = pc->tline;
7260
7261
7262 pc->p++;
7263 pc->len--;
7264 while (pc->len) {
7265 switch (*pc->p) {
7266 case '\\':
@@ -7220,11 +7305,11 @@
7305 {
7306 int level = 1;
7307 int startofword = 1;
7308 int line = pc->tline;
7309
7310
7311 pc->p++;
7312 pc->len--;
7313 while (pc->len) {
7314 switch (*pc->p) {
7315 case '\\':
@@ -7300,17 +7385,17 @@
7385 return JIM_OK;
7386 }
7387
7388 static int JimParseVar(struct JimParserCtx *pc)
7389 {
7390
7391 pc->p++;
7392 pc->len--;
7393
7394 #ifdef EXPRSUGAR_BRACKET
7395 if (*pc->p == '[') {
7396
7397 JimParseCmd(pc);
7398 pc->tt = JIM_TT_EXPRSUGAR;
7399 return JIM_OK;
7400 }
7401 #endif
@@ -7336,11 +7421,11 @@
7421 pc->len--;
7422 }
7423 }
7424 else {
7425 while (1) {
7426
7427 if (pc->p[0] == ':' && pc->p[1] == ':') {
7428 while (*pc->p == ':') {
7429 pc->p++;
7430 pc->len--;
7431 }
@@ -7351,11 +7436,11 @@
7436 pc->len--;
7437 continue;
7438 }
7439 break;
7440 }
7441
7442 if (*pc->p == '(') {
7443 int count = 1;
7444 const char *paren = NULL;
7445
7446 pc->tt = JIM_TT_DICTSUGAR;
@@ -7378,11 +7463,11 @@
7463 if (count == 0) {
7464 pc->p++;
7465 pc->len--;
7466 }
7467 else if (paren) {
7468
7469 paren++;
7470 pc->len += (pc->p - paren);
7471 pc->p = paren;
7472 }
7473 #ifndef EXPRSUGAR_BRACKET
@@ -7403,19 +7488,19 @@
7488
7489 static int JimParseStr(struct JimParserCtx *pc)
7490 {
7491 if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
7492 pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
7493
7494 if (*pc->p == '{') {
7495 return JimParseBrace(pc);
7496 }
7497 if (*pc->p == '"') {
7498 pc->inquote = 1;
7499 pc->p++;
7500 pc->len--;
7501
7502 pc->missing.line = pc->tline;
7503 }
7504 }
7505 pc->tstart = pc->p;
7506 pc->tline = pc->linenr;
@@ -7441,25 +7526,25 @@
7526 }
7527 pc->p++;
7528 pc->len--;
7529 }
7530 else if (pc->len == 1) {
7531
7532 pc->missing.ch = '\\';
7533 }
7534 break;
7535 case '(':
7536
7537 if (pc->len > 1 && pc->p[1] != '$') {
7538 break;
7539 }
7540
7541 case ')':
7542
7543 if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
7544 if (pc->p == pc->tstart) {
7545
7546 pc->p++;
7547 pc->len--;
7548 }
7549 pc->tend = pc->p - 1;
7550 pc->tt = JIM_TT_ESC;
@@ -7499,11 +7584,11 @@
7584 break;
7585 }
7586 pc->p++;
7587 pc->len--;
7588 }
7589 return JIM_OK;
7590 }
7591
7592 static int JimParseComment(struct JimParserCtx *pc)
7593 {
7594 while (*pc->p) {
@@ -7610,34 +7695,34 @@
7695 if (c == -1) {
7696 break;
7697 }
7698 val = (val << 4) | c;
7699 }
7700
7701 if (s[i] == '{') {
7702 if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
7703
7704 i--;
7705 k = 0;
7706 }
7707 else {
7708
7709 k++;
7710 }
7711 }
7712 if (k) {
7713
7714 if (s[i] == 'x') {
7715 *p++ = val;
7716 }
7717 else {
7718 p += utf8_fromunicode(p, val);
7719 }
7720 i += k;
7721 break;
7722 }
7723
7724 *p++ = s[i];
7725 }
7726 break;
7727 case 'v':
7728 *p++ = 0xb;
@@ -7646,11 +7731,11 @@
7731 case '\0':
7732 *p++ = '\\';
7733 i++;
7734 break;
7735 case '\n':
7736
7737 *p++ = ' ';
7738 do {
7739 i++;
7740 } while (s[i + 1] == ' ' || s[i + 1] == '\t');
7741 break;
@@ -7660,11 +7745,11 @@
7745 case '3':
7746 case '4':
7747 case '5':
7748 case '6':
7749 case '7':
7750
7751 {
7752 int val = 0;
7753 int c = odigitval(s[i + 1]);
7754
7755 val = c;
@@ -7717,16 +7802,16 @@
7802 }
7803 else {
7804 len = (end - start) + 1;
7805 token = Jim_Alloc(len + 1);
7806 if (pc->tt != JIM_TT_ESC) {
7807
7808 memcpy(token, start, len);
7809 token[len] = '\0';
7810 }
7811 else {
7812
7813 len = JimEscape(token, start, len);
7814 }
7815 }
7816
7817 return Jim_NewStringObjNoAlloc(interp, token, len);
@@ -7790,11 +7875,11 @@
7875 while (pc->len) {
7876 switch (*pc->p) {
7877 case '\\':
7878 pc->tt = JIM_TT_ESC;
7879 if (--pc->len == 0) {
7880
7881 pc->tend = pc->p;
7882 return JIM_OK;
7883 }
7884 pc->p++;
7885 break;
@@ -7826,11 +7911,11 @@
7911 pc->tend = pc->p - 1;
7912 return JIM_OK;
7913 }
7914 if (*pc->p == '\\') {
7915 if (--pc->len == 0) {
7916
7917 pc->tend = pc->p;
7918 return JIM_OK;
7919 }
7920 pc->tt = JIM_TT_ESC;
7921 pc->p++;
@@ -7846,24 +7931,24 @@
7931
7932 Jim_Obj *Jim_NewObj(Jim_Interp *interp)
7933 {
7934 Jim_Obj *objPtr;
7935
7936
7937 if (interp->freeList != NULL) {
7938
7939 objPtr = interp->freeList;
7940 interp->freeList = objPtr->nextObjPtr;
7941 }
7942 else {
7943
7944 objPtr = Jim_Alloc(sizeof(*objPtr));
7945 }
7946
7947 objPtr->refCount = 0;
7948
7949
7950 objPtr->prevObjPtr = NULL;
7951 objPtr->nextObjPtr = interp->liveList;
7952 if (interp->liveList)
7953 interp->liveList->prevObjPtr = objPtr;
7954 interp->liveList = objPtr;
@@ -7871,32 +7956,32 @@
7956 return objPtr;
7957 }
7958
7959 void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
7960 {
7961
7962 JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
7963 objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
7964
7965
7966 Jim_FreeIntRep(interp, objPtr);
7967
7968 if (objPtr->bytes != NULL) {
7969 if (objPtr->bytes != JimEmptyStringRep)
7970 Jim_Free(objPtr->bytes);
7971 }
7972
7973 if (objPtr->prevObjPtr)
7974 objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
7975 if (objPtr->nextObjPtr)
7976 objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
7977 if (interp->liveList == objPtr)
7978 interp->liveList = objPtr->nextObjPtr;
7979 #ifdef JIM_DISABLE_OBJECT_POOL
7980 Jim_Free(objPtr);
7981 #else
7982
7983 objPtr->prevObjPtr = NULL;
7984 objPtr->nextObjPtr = interp->freeList;
7985 if (interp->freeList)
7986 interp->freeList->prevObjPtr = objPtr;
7987 interp->freeList = objPtr;
@@ -7919,45 +8004,45 @@
8004 {
8005 Jim_Obj *dupPtr;
8006
8007 dupPtr = Jim_NewObj(interp);
8008 if (objPtr->bytes == NULL) {
8009
8010 dupPtr->bytes = NULL;
8011 }
8012 else if (objPtr->length == 0) {
8013
8014 dupPtr->bytes = JimEmptyStringRep;
8015 dupPtr->length = 0;
8016 dupPtr->typePtr = NULL;
8017 return dupPtr;
8018 }
8019 else {
8020 dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
8021 dupPtr->length = objPtr->length;
8022
8023 memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
8024 }
8025
8026
8027 dupPtr->typePtr = objPtr->typePtr;
8028 if (objPtr->typePtr != NULL) {
8029 if (objPtr->typePtr->dupIntRepProc == NULL) {
8030 dupPtr->internalRep = objPtr->internalRep;
8031 }
8032 else {
8033
8034 objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
8035 }
8036 }
8037 return dupPtr;
8038 }
8039
8040 const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
8041 {
8042 if (objPtr->bytes == NULL) {
8043
8044 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8045 objPtr->typePtr->updateStringProc(objPtr);
8046 }
8047 if (lenPtr)
8048 *lenPtr = objPtr->length;
@@ -7966,11 +8051,11 @@
8051
8052
8053 int Jim_Length(Jim_Obj *objPtr)
8054 {
8055 if (objPtr->bytes == NULL) {
8056
8057 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8058 objPtr->typePtr->updateStringProc(objPtr);
8059 }
8060 return objPtr->length;
8061 }
@@ -7977,11 +8062,11 @@
8062
8063
8064 const char *Jim_String(Jim_Obj *objPtr)
8065 {
8066 if (objPtr->bytes == NULL) {
8067
8068 JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
8069 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8070 objPtr->typePtr->updateStringProc(objPtr);
8071 }
8072 return objPtr->bytes;
@@ -8037,22 +8122,22 @@
8122 }
8123
8124 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
8125 {
8126 if (objPtr->typePtr != &stringObjType) {
8127
8128 if (objPtr->bytes == NULL) {
8129
8130 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
8131 objPtr->typePtr->updateStringProc(objPtr);
8132 }
8133
8134 Jim_FreeIntRep(interp, objPtr);
8135
8136 objPtr->typePtr = &stringObjType;
8137 objPtr->internalRep.strValue.maxLength = objPtr->length;
8138
8139 objPtr->internalRep.strValue.charLength = -1;
8140 }
8141 return JIM_OK;
8142 }
8143
@@ -8073,14 +8158,14 @@
8158
8159 Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
8160 {
8161 Jim_Obj *objPtr = Jim_NewObj(interp);
8162
8163
8164 if (len == -1)
8165 len = strlen(s);
8166
8167 if (len == 0) {
8168 objPtr->bytes = JimEmptyStringRep;
8169 }
8170 else {
8171 objPtr->bytes = Jim_Alloc(len + 1);
@@ -8087,25 +8172,25 @@
8172 memcpy(objPtr->bytes, s, len);
8173 objPtr->bytes[len] = '\0';
8174 }
8175 objPtr->length = len;
8176
8177
8178 objPtr->typePtr = NULL;
8179 return objPtr;
8180 }
8181
8182
8183 Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
8184 {
8185 #ifdef JIM_UTF8
8186
8187 int bytelen = utf8_index(s, charlen);
8188
8189 Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
8190
8191
8192 objPtr->typePtr = &stringObjType;
8193 objPtr->internalRep.strValue.maxLength = bytelen;
8194 objPtr->internalRep.strValue.charLength = charlen;
8195
8196 return objPtr;
@@ -8132,11 +8217,11 @@
8217 len = strlen(str);
8218 needlen = objPtr->length + len;
8219 if (objPtr->internalRep.strValue.maxLength < needlen ||
8220 objPtr->internalRep.strValue.maxLength == 0) {
8221 needlen *= 2;
8222
8223 if (needlen < 7) {
8224 needlen = 7;
8225 }
8226 if (objPtr->bytes == JimEmptyStringRep) {
8227 objPtr->bytes = Jim_Alloc(needlen + 1);
@@ -8148,11 +8233,11 @@
8233 }
8234 memcpy(objPtr->bytes + objPtr->length, str, len);
8235 objPtr->bytes[objPtr->length + len] = '\0';
8236
8237 if (objPtr->internalRep.strValue.charLength >= 0) {
8238
8239 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
8240 }
8241 objPtr->length += len;
8242 }
8243
@@ -8210,11 +8295,11 @@
8295 int l1, l2;
8296 const char *s1 = Jim_GetString(firstObjPtr, &l1);
8297 const char *s2 = Jim_GetString(secondObjPtr, &l2);
8298
8299 if (nocase) {
8300
8301 return JimStringCompareLen(s1, s2, -1, nocase);
8302 }
8303 return JimStringCompare(s1, l1, s2, l2);
8304 }
8305
@@ -8312,11 +8397,11 @@
8397
8398 if (first == 0 && rangeLen == len) {
8399 return strObjPtr;
8400 }
8401 if (len == bytelen) {
8402
8403 return Jim_NewStringObj(interp, str + first, rangeLen);
8404 }
8405 return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
8406 #else
8407 return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
@@ -8341,19 +8426,19 @@
8426 return strObjPtr;
8427 }
8428
8429 str = Jim_String(strObjPtr);
8430
8431
8432 objPtr = Jim_NewStringObjUtf8(interp, str, first);
8433
8434
8435 if (newStrObj) {
8436 Jim_AppendObj(interp, objPtr, newStrObj);
8437 }
8438
8439
8440 Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
8441
8442 return objPtr;
8443 }
8444
@@ -8452,11 +8537,11 @@
8537 while (len) {
8538 int c;
8539 int n = utf8_tounicode(str, &c);
8540
8541 if (utf8_memchr(trimchars, trimlen, c) == NULL) {
8542
8543 break;
8544 }
8545 str += n;
8546 len -= n;
8547 }
@@ -8523,41 +8608,41 @@
8608
8609 len = Jim_Length(strObjPtr);
8610 nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
8611
8612 if (nontrim == NULL) {
8613
8614 return Jim_NewEmptyStringObj(interp);
8615 }
8616 if (nontrim == strObjPtr->bytes + len) {
8617
8618 return strObjPtr;
8619 }
8620
8621 if (Jim_IsShared(strObjPtr)) {
8622 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
8623 }
8624 else {
8625
8626 strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
8627 strObjPtr->length = (nontrim - strObjPtr->bytes);
8628 }
8629
8630 return strObjPtr;
8631 }
8632
8633 static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
8634 {
8635
8636 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8637
8638
8639 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8640
8641
8642 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8643
8644 Jim_FreeNewObj(interp, objPtr);
8645 }
8646
8647 return strObjPtr;
8648 }
@@ -8575,17 +8660,17 @@
8660 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
8661 {
8662 static const char * const strclassnames[] = {
8663 "integer", "alpha", "alnum", "ascii", "digit",
8664 "double", "lower", "upper", "space", "xdigit",
8665 "control", "print", "graph", "punct", "boolean",
8666 NULL
8667 };
8668 enum {
8669 STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
8670 STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
8671 STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN,
8672 };
8673 int strclass;
8674 int len;
8675 int i;
8676 const char *str;
@@ -8613,10 +8698,17 @@
8698 {
8699 double d;
8700 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8701 return JIM_OK;
8702 }
8703
8704 case STR_IS_BOOLEAN:
8705 {
8706 int b;
8707 Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK);
8708 return JIM_OK;
8709 }
8710
8711 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8712 case STR_IS_ALNUM: isclassfunc = isalnum; break;
8713 case STR_IS_ASCII: isclassfunc = jim_isascii; break;
8714 case STR_IS_DIGIT: isclassfunc = isdigit; break;
@@ -8631,11 +8723,11 @@
8723 default:
8724 return JIM_ERR;
8725 }
8726
8727 for (i = 0; i < len; i++) {
8728 if (!isclassfunc(UCHAR(str[i]))) {
8729 Jim_SetResultBool(interp, 0);
8730 return JIM_OK;
8731 }
8732 }
8733 Jim_SetResultBool(interp, 1);
@@ -8665,11 +8757,11 @@
8757
8758 if (objPtr->typePtr != &comparedStringObjType) {
8759 Jim_FreeIntRep(interp, objPtr);
8760 objPtr->typePtr = &comparedStringObjType;
8761 }
8762 objPtr->internalRep.ptr = (char *)str;
8763 return 1;
8764 }
8765 }
8766
8767 static int qsortCompareStringPointers(const void *a, const void *b)
@@ -8758,20 +8850,20 @@
8850 int type;
8851 } ScriptToken;
8852
8853 typedef struct ScriptObj
8854 {
8855 ScriptToken *token;
8856 Jim_Obj *fileNameObj;
8857 int len;
8858 int substFlags;
8859 int inUse; /* Used to share a ScriptObj. Currently
8860 only used by Jim_EvalObj() as protection against
8861 shimmering of the currently evaluated object. */
8862 int firstline;
8863 int linenr;
8864 int missing;
8865 } ScriptObj;
8866
8867 static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8868 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8869 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -8799,23 +8891,23 @@
8891 dupPtr->typePtr = NULL;
8892 }
8893
8894 typedef struct
8895 {
8896 const char *token;
8897 int len;
8898 int type;
8899 int line;
8900 } ParseToken;
8901
8902 typedef struct
8903 {
8904
8905 ParseToken *list;
8906 int size;
8907 int count;
8908 ParseToken static_list[20];
8909 } ParseTokenList;
8910
8911 static void ScriptTokenListInit(ParseTokenList *tokenlist)
8912 {
8913 tokenlist->list = tokenlist->static_list;
@@ -8834,18 +8926,18 @@
8926 int line)
8927 {
8928 ParseToken *t;
8929
8930 if (tokenlist->count == tokenlist->size) {
8931
8932 tokenlist->size *= 2;
8933 if (tokenlist->list != tokenlist->static_list) {
8934 tokenlist->list =
8935 Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
8936 }
8937 else {
8938
8939 tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
8940 memcpy(tokenlist->list, tokenlist->static_list,
8941 tokenlist->count * sizeof(*tokenlist->list));
8942 }
8943 }
@@ -8859,20 +8951,20 @@
8951 static int JimCountWordTokens(ParseToken *t)
8952 {
8953 int expand = 1;
8954 int count = 0;
8955
8956
8957 if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
8958 if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
8959
8960 expand = -1;
8961 t++;
8962 }
8963 }
8964
8965
8966 while (!TOKEN_IS_SEP(t->type)) {
8967 t++;
8968 count++;
8969 }
8970
@@ -8882,11 +8974,11 @@
8974 static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
8975 {
8976 Jim_Obj *objPtr;
8977
8978 if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
8979
8980 int len = t->len;
8981 char *str = Jim_Alloc(len + 1);
8982 len = JimEscape(str, t->token, len);
8983 objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
8984 }
@@ -8899,13 +8991,13 @@
8991 static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8992 ParseTokenList *tokenlist)
8993 {
8994 int i;
8995 struct ScriptToken *token;
8996
8997 int lineargs = 0;
8998
8999 ScriptToken *linefirst;
9000 int count;
9001 int linenr;
9002
9003 #ifdef DEBUG_SHOW_SCRIPT_TOKENS
@@ -8914,11 +9006,11 @@
9006 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
9007 tokenlist->list[i].len, tokenlist->list[i].token);
9008 }
9009 #endif
9010
9011
9012 count = tokenlist->count;
9013 for (i = 0; i < tokenlist->count; i++) {
9014 if (tokenlist->list[i].type == JIM_TT_EOL) {
9015 count++;
9016 }
@@ -8925,59 +9017,59 @@
9017 }
9018 linenr = script->firstline = tokenlist->list[0].line;
9019
9020 token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
9021
9022
9023 linefirst = token++;
9024
9025 for (i = 0; i < tokenlist->count; ) {
9026
9027 int wordtokens;
9028
9029
9030 while (tokenlist->list[i].type == JIM_TT_SEP) {
9031 i++;
9032 }
9033
9034 wordtokens = JimCountWordTokens(tokenlist->list + i);
9035
9036 if (wordtokens == 0) {
9037
9038 if (lineargs) {
9039 linefirst->type = JIM_TT_LINE;
9040 linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
9041 Jim_IncrRefCount(linefirst->objPtr);
9042
9043
9044 lineargs = 0;
9045 linefirst = token++;
9046 }
9047 i++;
9048 continue;
9049 }
9050 else if (wordtokens != 1) {
9051
9052 token->type = JIM_TT_WORD;
9053 token->objPtr = Jim_NewIntObj(interp, wordtokens);
9054 Jim_IncrRefCount(token->objPtr);
9055 token++;
9056 if (wordtokens < 0) {
9057
9058 i++;
9059 wordtokens = -wordtokens - 1;
9060 lineargs--;
9061 }
9062 }
9063
9064 if (lineargs == 0) {
9065
9066 linenr = tokenlist->list[i].line;
9067 }
9068 lineargs++;
9069
9070
9071 while (wordtokens--) {
9072 const ParseToken *t = &tokenlist->list[i++];
9073
9074 token->type = t->type;
9075 token->objPtr = JimMakeScriptObj(interp, t);
@@ -9049,11 +9141,11 @@
9141 token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
9142
9143 for (i = 0; i < tokenlist->count; i++) {
9144 const ParseToken *t = &tokenlist->list[i];
9145
9146
9147 token->type = t->type;
9148 token->objPtr = JimMakeScriptObj(interp, t);
9149 Jim_IncrRefCount(token->objPtr);
9150 token++;
9151 }
@@ -9068,29 +9160,29 @@
9160 struct JimParserCtx parser;
9161 struct ScriptObj *script;
9162 ParseTokenList tokenlist;
9163 int line = 1;
9164
9165
9166 if (objPtr->typePtr == &sourceObjType) {
9167 line = objPtr->internalRep.sourceValue.lineNumber;
9168 }
9169
9170
9171 ScriptTokenListInit(&tokenlist);
9172
9173 JimParserInit(&parser, scriptText, scriptTextLen, line);
9174 while (!parser.eof) {
9175 JimParseScript(&parser);
9176 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
9177 parser.tline);
9178 }
9179
9180
9181 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
9182
9183
9184 script = Jim_Alloc(sizeof(*script));
9185 memset(script, 0, sizeof(*script));
9186 script->inUse = 1;
9187 if (objPtr->typePtr == &sourceObjType) {
9188 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -9102,14 +9194,14 @@
9194 script->missing = parser.missing.ch;
9195 script->linenr = parser.missing.line;
9196
9197 ScriptObjAddTokens(interp, script, &tokenlist);
9198
9199
9200 ScriptTokenListFree(&tokenlist);
9201
9202
9203 Jim_FreeIntRep(interp, objPtr);
9204 Jim_SetIntRepPtr(objPtr, script);
9205 objPtr->typePtr = &scriptObjType;
9206 }
9207
@@ -9116,11 +9208,11 @@
9208 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
9209
9210 static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
9211 {
9212 if (objPtr == interp->emptyObj) {
9213
9214 objPtr = interp->nullScriptObj;
9215 }
9216
9217 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
9218 JimSetScriptFromAny(interp, objPtr);
@@ -9155,17 +9247,17 @@
9247 Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
9248 Jim_Free(cmdPtr->u.proc.staticVars);
9249 }
9250 }
9251 else {
9252
9253 if (cmdPtr->u.native.delProc) {
9254 cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
9255 }
9256 }
9257 if (cmdPtr->prevCmd) {
9258
9259 JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
9260 }
9261 Jim_Free(cmdPtr);
9262 }
9263 }
@@ -9176,46 +9268,46 @@
9268 Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
9269 Jim_Free(val);
9270 }
9271
9272 static const Jim_HashTableType JimVariablesHashTableType = {
9273 JimStringCopyHTHashFunction,
9274 JimStringCopyHTDup,
9275 NULL,
9276 JimStringCopyHTKeyCompare,
9277 JimStringCopyHTKeyDestructor,
9278 JimVariablesHTValDestructor
9279 };
9280
9281 static void JimCommandsHT_ValDestructor(void *interp, void *val)
9282 {
9283 JimDecrCmdRefCount(interp, val);
9284 }
9285
9286 static const Jim_HashTableType JimCommandsHashTableType = {
9287 JimStringCopyHTHashFunction,
9288 JimStringCopyHTDup,
9289 NULL,
9290 JimStringCopyHTKeyCompare,
9291 JimStringCopyHTKeyDestructor,
9292 JimCommandsHT_ValDestructor
9293 };
9294
9295
9296
9297 #ifdef jim_ext_namespace
9298 static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
9299 {
9300 const char *name = Jim_String(nsObj);
9301 if (name[0] == ':' && name[1] == ':') {
9302
9303 while (*++name == ':') {
9304 }
9305 nsObj = Jim_NewStringObj(interp, name, -1);
9306 }
9307 else if (Jim_Length(interp->framePtr->nsObj)) {
9308
9309 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9310 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
9311 }
9312 return nsObj;
9313 }
@@ -9239,16 +9331,16 @@
9331 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9332 {
9333 Jim_Obj *objPtr = interp->emptyObj;
9334
9335 if (name[0] == ':' && name[1] == ':') {
9336
9337 while (*++name == ':') {
9338 }
9339 }
9340 else if (Jim_Length(interp->framePtr->nsObj)) {
9341
9342 objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9343 Jim_AppendStrings(interp, objPtr, "::", name, NULL);
9344 name = Jim_String(objPtr);
9345 }
9346 Jim_IncrRefCount(objPtr);
@@ -9257,11 +9349,11 @@
9349 }
9350
9351 #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
9352
9353 #else
9354
9355 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9356 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9357
9358 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9359 {
@@ -9276,17 +9368,17 @@
9368
9369 Jim_InterpIncrProcEpoch(interp);
9370 }
9371
9372 if (he && interp->local) {
9373
9374 cmd->prevCmd = Jim_GetHashEntryVal(he);
9375 Jim_SetHashVal(&interp->commands, he, cmd);
9376 }
9377 else {
9378 if (he) {
9379
9380 Jim_DeleteHashEntry(&interp->commands, name);
9381 }
9382
9383 Jim_AddHashEntry(&interp->commands, name, cmd);
9384 }
@@ -9297,11 +9389,11 @@
9389 int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
9390 Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
9391 {
9392 Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
9393
9394
9395 memset(cmdPtr, 0, sizeof(*cmdPtr));
9396 cmdPtr->inUse = 1;
9397 cmdPtr->u.native.delProc = delProc;
9398 cmdPtr->u.native.cmdProc = cmdProc;
9399 cmdPtr->u.native.privData = privData;
@@ -9326,11 +9418,11 @@
9418 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9419 Jim_Var *varPtr;
9420 int subLen;
9421
9422 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9423
9424 subLen = Jim_ListLength(interp, objPtr);
9425 if (subLen == 1 || subLen == 2) {
9426 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9427 if (subLen == 1) {
9428 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -9372,19 +9464,19 @@
9464
9465 static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
9466 {
9467 #ifdef jim_ext_namespace
9468 if (cmdPtr->isproc) {
9469
9470 const char *pt = strrchr(cmdname, ':');
9471 if (pt && pt != cmdname && pt[-1] == ':') {
9472 Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
9473 cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
9474 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9475
9476 if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
9477
9478 Jim_InterpIncrProcEpoch(interp);
9479 }
9480 }
9481 }
9482 #endif
@@ -9397,11 +9489,11 @@
9489 int argListLen;
9490 int i;
9491
9492 argListLen = Jim_ListLength(interp, argListObjPtr);
9493
9494
9495 cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
9496 memset(cmdPtr, 0, sizeof(*cmdPtr));
9497 cmdPtr->inUse = 1;
9498 cmdPtr->isproc = 1;
9499 cmdPtr->u.proc.argListObjPtr = argListObjPtr;
@@ -9412,24 +9504,24 @@
9504 cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
9505 Jim_IncrRefCount(argListObjPtr);
9506 Jim_IncrRefCount(bodyObjPtr);
9507 Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
9508
9509
9510 if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
9511 goto err;
9512 }
9513
9514
9515
9516 for (i = 0; i < argListLen; i++) {
9517 Jim_Obj *argPtr;
9518 Jim_Obj *nameObjPtr;
9519 Jim_Obj *defaultObjPtr;
9520 int len;
9521
9522
9523 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9524 len = Jim_ListLength(interp, argPtr);
9525 if (len == 0) {
9526 Jim_SetResultString(interp, "argument with no name", -1);
9527 err:
@@ -9440,16 +9532,16 @@
9532 Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
9533 goto err;
9534 }
9535
9536 if (len == 2) {
9537
9538 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9539 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9540 }
9541 else {
9542
9543 nameObjPtr = argPtr;
9544 defaultObjPtr = NULL;
9545 }
9546
9547
@@ -9510,29 +9602,29 @@
9602 }
9603
9604 fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
9605 fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
9606
9607
9608 he = Jim_FindHashEntry(&interp->commands, fqold);
9609 if (he == NULL) {
9610 Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
9611 }
9612 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9613 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9614 }
9615 else {
9616
9617 cmdPtr = Jim_GetHashEntryVal(he);
9618 JimIncrCmdRefCount(cmdPtr);
9619 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9620 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9621
9622
9623 Jim_DeleteHashEntry(&interp->commands, fqold);
9624
9625
9626 Jim_InterpIncrProcEpoch(interp);
9627
9628 ret = JIM_OK;
9629 }
9630
@@ -9571,23 +9663,23 @@
9663 objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
9664 #ifdef jim_ext_namespace
9665 || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
9666 #endif
9667 ) {
 
9668
9669
9670
9671 const char *name = Jim_String(objPtr);
9672 Jim_HashEntry *he;
9673
9674 if (name[0] == ':' && name[1] == ':') {
9675 while (*++name == ':') {
9676 }
9677 }
9678 #ifdef jim_ext_namespace
9679 else if (Jim_Length(interp->framePtr->nsObj)) {
9680
9681 Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
9682 Jim_AppendStrings(interp, nameObj, "::", name, NULL);
9683 he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
9684 Jim_FreeNewObj(interp, nameObj);
9685 if (he) {
@@ -9594,11 +9686,11 @@
9686 goto found;
9687 }
9688 }
9689 #endif
9690
9691
9692 he = Jim_FindHashEntry(&interp->commands, name);
9693 if (he == NULL) {
9694 if (flags & JIM_ERRMSG) {
9695 Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
9696 }
@@ -9607,11 +9699,11 @@
9699 #ifdef jim_ext_namespace
9700 found:
9701 #endif
9702 cmd = Jim_GetHashEntryVal(he);
9703
9704
9705 Jim_FreeIntRep(interp, objPtr);
9706 objPtr->typePtr = &commandObjType;
9707 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
9708 objPtr->internalRep.cmdValue.cmdPtr = cmd;
9709 objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
@@ -9626,11 +9718,11 @@
9718 return cmd;
9719 }
9720
9721
9722
9723 #define JIM_DICT_SUGAR 100
9724
9725 static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
9726
9727 static const Jim_ObjType variableObjType = {
9728 "variable",
@@ -9640,11 +9732,11 @@
9732 JIM_TYPE_REFERENCES,
9733 };
9734
9735 static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
9736 {
9737
9738 if (nameObjPtr->typePtr != &variableObjType) {
9739 int len;
9740 const char *str = Jim_GetString(nameObjPtr, &len);
9741 if (memchr(str, '\0', len)) {
9742 Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
@@ -9660,18 +9752,18 @@
9752 Jim_CallFrame *framePtr;
9753 Jim_HashEntry *he;
9754 int global;
9755 int len;
9756
9757
9758 if (objPtr->typePtr == &variableObjType) {
9759 framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
9760 if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
9761
9762 return JIM_OK;
9763 }
9764
9765 }
9766 else if (objPtr->typePtr == &dictSubstObjType) {
9767 return JIM_DICT_SUGAR;
9768 }
9769 else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
@@ -9679,11 +9771,11 @@
9771 }
9772
9773
9774 varName = Jim_GetString(objPtr, &len);
9775
9776
9777 if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
9778 return JIM_DICT_SUGAR;
9779 }
9780
9781 if (varName[0] == ':' && varName[1] == ':') {
@@ -9695,23 +9787,23 @@
9787 else {
9788 global = 0;
9789 framePtr = interp->framePtr;
9790 }
9791
9792
9793 he = Jim_FindHashEntry(&framePtr->vars, varName);
9794 if (he == NULL) {
9795 if (!global && framePtr->staticVars) {
9796
9797 he = Jim_FindHashEntry(framePtr->staticVars, varName);
9798 }
9799 if (he == NULL) {
9800 return JIM_ERR;
9801 }
9802 }
9803
9804
9805 Jim_FreeIntRep(interp, objPtr);
9806 objPtr->typePtr = &variableObjType;
9807 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9808 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9809 objPtr->internalRep.varValue.global = global;
@@ -9726,11 +9818,11 @@
9818 {
9819 const char *name;
9820 Jim_CallFrame *framePtr;
9821 int global;
9822
9823
9824 Jim_Var *var = Jim_Alloc(sizeof(*var));
9825
9826 var->objPtr = valObjPtr;
9827 Jim_IncrRefCount(valObjPtr);
9828 var->linkFramePtr = NULL;
@@ -9745,14 +9837,14 @@
9837 else {
9838 framePtr = interp->framePtr;
9839 global = 0;
9840 }
9841
9842
9843 Jim_AddHashEntry(&framePtr->vars, name, var);
9844
9845
9846 Jim_FreeIntRep(interp, nameObjPtr);
9847 nameObjPtr->typePtr = &variableObjType;
9848 nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
9849 nameObjPtr->internalRep.varValue.varPtr = var;
9850 nameObjPtr->internalRep.varValue.global = global;
@@ -9782,11 +9874,11 @@
9874 if (var->linkFramePtr == NULL) {
9875 Jim_IncrRefCount(valObjPtr);
9876 Jim_DecrRefCount(interp, var->objPtr);
9877 var->objPtr = valObjPtr;
9878 }
9879 else {
9880 Jim_CallFrame *savedCallFrame;
9881
9882 savedCallFrame = interp->framePtr;
9883 interp->framePtr = var->linkFramePtr;
9884 err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
@@ -9843,14 +9935,14 @@
9935 const char *varName;
9936 const char *targetName;
9937 Jim_CallFrame *framePtr;
9938 Jim_Var *varPtr;
9939
9940
9941 switch (SetVariableFromAny(interp, nameObjPtr)) {
9942 case JIM_DICT_SUGAR:
9943
9944 Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
9945 return JIM_ERR;
9946
9947 case JIM_OK:
9948 varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -9858,23 +9950,23 @@
9950 if (varPtr->linkFramePtr == NULL) {
9951 Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
9952 return JIM_ERR;
9953 }
9954
9955
9956 varPtr->linkFramePtr = NULL;
9957 break;
9958 }
9959
9960
9961
9962 varName = Jim_String(nameObjPtr);
9963
9964 if (varName[0] == ':' && varName[1] == ':') {
9965 while (*++varName == ':') {
9966 }
9967
9968 framePtr = interp->topFramePtr;
9969 }
9970 else {
9971 framePtr = interp->framePtr;
9972 }
@@ -9894,15 +9986,15 @@
9986 nameObjPtr);
9987 Jim_DecrRefCount(interp, targetNameObjPtr);
9988 return JIM_ERR;
9989 }
9990
9991
9992 if (framePtr == targetCallFrame) {
9993 Jim_Obj *objPtr = targetNameObjPtr;
9994
9995
9996 while (1) {
9997 if (strcmp(Jim_String(objPtr), varName) == 0) {
9998 Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
9999 Jim_DecrRefCount(interp, targetNameObjPtr);
10000 return JIM_ERR;
@@ -9914,13 +10006,13 @@
10006 break;
10007 objPtr = varPtr->objPtr;
10008 }
10009 }
10010
10011
10012 Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
10013
10014 nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
10015 Jim_DecrRefCount(interp, targetNameObjPtr);
10016 return JIM_OK;
10017 }
10018
@@ -9934,26 +10026,26 @@
10026 return varPtr->objPtr;
10027 }
10028 else {
10029 Jim_Obj *objPtr;
10030
10031
10032 Jim_CallFrame *savedCallFrame = interp->framePtr;
10033
10034 interp->framePtr = varPtr->linkFramePtr;
10035 objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
10036 interp->framePtr = savedCallFrame;
10037 if (objPtr) {
10038 return objPtr;
10039 }
10040
10041 }
10042 }
10043 break;
10044
10045 case JIM_DICT_SUGAR:
10046
10047 return JimDictSugarGet(interp, nameObjPtr, flags);
10048 }
10049 if (flags & JIM_ERRMSG) {
10050 Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
10051 }
@@ -10003,17 +10095,17 @@
10095 int retval;
10096 Jim_CallFrame *framePtr;
10097
10098 retval = SetVariableFromAny(interp, nameObjPtr);
10099 if (retval == JIM_DICT_SUGAR) {
10100
10101 return JimDictSugarSet(interp, nameObjPtr, NULL);
10102 }
10103 else if (retval == JIM_OK) {
10104 varPtr = nameObjPtr->internalRep.varValue.varPtr;
10105
10106
10107 if (varPtr->linkFramePtr) {
10108 framePtr = interp->framePtr;
10109 interp->framePtr = varPtr->linkFramePtr;
10110 retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
10111 interp->framePtr = framePtr;
@@ -10028,11 +10120,11 @@
10120 framePtr = interp->framePtr;
10121 }
10122
10123 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
10124 if (retval == JIM_OK) {
10125
10126 framePtr->id = interp->callFrameEpoch++;
10127 }
10128 }
10129 }
10130 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
@@ -10061,11 +10153,11 @@
10153 keyLen = (str + len) - p;
10154 if (str[len - 1] == ')') {
10155 keyLen--;
10156 }
10157
10158
10159 keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
10160
10161 Jim_IncrRefCount(varObjPtr);
10162 Jim_IncrRefCount(keyObjPtr);
10163 *varPtrPtr = varObjPtr;
@@ -10080,23 +10172,23 @@
10172
10173 err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
10174 &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
10175
10176 if (err == JIM_OK) {
10177
10178 Jim_SetEmptyResult(interp);
10179 }
10180 else {
10181 if (!valObjPtr) {
10182
10183 if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
10184 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
10185 objPtr);
10186 return err;
10187 }
10188 }
10189
10190 Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
10191 (valObjPtr ? "set" : "unset"), objPtr);
10192 }
10193 return err;
10194 }
@@ -10118,11 +10210,11 @@
10210 Jim_SetResultFormatted(interp,
10211 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
10212 ret < 0 ? "variable isn't" : "no such element in");
10213 }
10214 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
10215
10216 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
10217 }
10218
10219 return resObjPtr;
10220 }
@@ -10160,11 +10252,11 @@
10252 {
10253 if (objPtr->typePtr != &dictSubstObjType) {
10254 Jim_Obj *varObjPtr, *keyObjPtr;
10255
10256 if (objPtr->typePtr == &interpolatedObjType) {
10257
10258
10259 varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
10260 keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
10261
10262 Jim_IncrRefCount(varObjPtr);
@@ -10205,11 +10297,11 @@
10297 static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
10298 {
10299 Jim_Obj *resultObjPtr;
10300
10301 if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
10302
10303 resultObjPtr->refCount--;
10304 return resultObjPtr;
10305 }
10306 return NULL;
10307 }
@@ -10249,11 +10341,11 @@
10341 return cf;
10342 }
10343
10344 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10345 {
10346
10347 if (localCommands) {
10348 Jim_Obj *cmdNameObj;
10349
10350 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10351 Jim_HashEntry *he;
@@ -10268,20 +10360,20 @@
10360 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10361 if (cmd->prevCmd) {
10362 Jim_Cmd *prevCmd = cmd->prevCmd;
10363 cmd->prevCmd = NULL;
10364
10365
10366 JimDecrCmdRefCount(interp, cmd);
10367
10368
10369 Jim_SetHashVal(ht, he, prevCmd);
10370 }
10371 else {
10372 Jim_DeleteHashEntry(ht, fqname);
 
10373 }
10374 Jim_InterpIncrProcEpoch(interp);
10375 }
10376 Jim_DecrRefCount(interp, cmdNameObj);
10377 JimFreeQualifiedName(interp, fqObjName);
10378 }
10379 Jim_FreeStack(localCommands);
@@ -10289,12 +10381,12 @@
10381 }
10382 return JIM_OK;
10383 }
10384
10385
10386 #define JIM_FCF_FULL 0
10387 #define JIM_FCF_REUSE 1
10388 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10389 {
10390 JimDeleteLocalProcs(interp, cf->localCommands);
10391
10392 if (cf->procArgsObjPtr)
@@ -10327,263 +10419,10 @@
10419 cf->next = interp->freeFramesList;
10420 interp->freeFramesList = cf;
10421 }
10422
10423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10424
10425 int Jim_IsBigEndian(void)
10426 {
10427 union {
10428 unsigned short s;
@@ -10630,11 +10469,11 @@
10469 Jim_IncrRefCount(i->nullScriptObj);
10470 Jim_IncrRefCount(i->errorProc);
10471 Jim_IncrRefCount(i->trueObj);
10472 Jim_IncrRefCount(i->falseObj);
10473
10474
10475 Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
10476 Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
10477
10478 Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
10479 Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
@@ -10652,11 +10491,11 @@
10491 {
10492 Jim_CallFrame *cf, *cfx;
10493
10494 Jim_Obj *objPtr, *nextObjPtr;
10495
10496
10497 for (cf = i->framePtr; cf; cf = cfx) {
10498 cfx = cf->parent;
10499 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10500 }
10501
@@ -10705,27 +10544,27 @@
10544 printf("-------------------------------------\n\n");
10545 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10546 }
10547 #endif
10548
10549
10550 objPtr = i->freeList;
10551 while (objPtr) {
10552 nextObjPtr = objPtr->nextObjPtr;
10553 Jim_Free(objPtr);
10554 objPtr = nextObjPtr;
10555 }
10556
10557
10558 for (cf = i->freeFramesList; cf; cf = cfx) {
10559 cfx = cf->next;
10560 if (cf->vars.table)
10561 Jim_FreeHashTable(&cf->vars);
10562 Jim_Free(cf);
10563 }
10564
10565
10566 Jim_Free(i);
10567 }
10568
10569 Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
10570 {
@@ -10746,25 +10585,25 @@
10585 else {
10586 if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
10587 level = -1;
10588 }
10589 else {
10590
10591 level = interp->framePtr->level - level;
10592 }
10593 }
10594 }
10595 else {
10596 str = "1";
10597 level = interp->framePtr->level - 1;
10598 }
10599
10600 if (level == 0) {
10601 return interp->topFramePtr;
10602 }
10603 if (level > 0) {
10604
10605 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10606 if (framePtr->level == level) {
10607 return framePtr;
10608 }
10609 }
@@ -10779,19 +10618,19 @@
10618 long level;
10619 Jim_CallFrame *framePtr;
10620
10621 if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
10622 if (level <= 0) {
10623
10624 level = interp->framePtr->level + level;
10625 }
10626
10627 if (level == 0) {
10628 return interp->topFramePtr;
10629 }
10630
10631
10632 for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
10633 if (framePtr->level == level) {
10634 return framePtr;
10635 }
10636 }
@@ -10810,11 +10649,11 @@
10649
10650 static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
10651 {
10652 int len;
10653
10654
10655 Jim_IncrRefCount(stackTraceObj);
10656 Jim_DecrRefCount(interp, interp->stackTrace);
10657 interp->stackTrace = stackTraceObj;
10658 interp->errorFlag = 1;
10659
@@ -10831,32 +10670,32 @@
10670 {
10671 if (strcmp(procname, "unknown") == 0) {
10672 procname = "";
10673 }
10674 if (!*procname && !Jim_Length(fileNameObj)) {
10675
10676 return;
10677 }
10678
10679 if (Jim_IsShared(interp->stackTrace)) {
10680 Jim_DecrRefCount(interp, interp->stackTrace);
10681 interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
10682 Jim_IncrRefCount(interp->stackTrace);
10683 }
10684
10685
10686 if (!*procname && Jim_Length(fileNameObj)) {
10687
10688 int len = Jim_ListLength(interp, interp->stackTrace);
10689
10690 if (len >= 3) {
10691 Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
10692 if (Jim_Length(objPtr)) {
10693
10694 objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
10695 if (Jim_Length(objPtr) == 0) {
10696
10697 ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
10698 ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
10699 return;
10700 }
10701 }
@@ -10958,18 +10797,18 @@
10797 {
10798 jim_wide wideValue;
10799 const char *str;
10800
10801 if (objPtr->typePtr == &coercedDoubleObjType) {
10802
10803 objPtr->typePtr = &intObjType;
10804 return JIM_OK;
10805 }
10806
10807
10808 str = Jim_String(objPtr);
10809
10810 if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
10811 if (flags & JIM_ERRMSG) {
10812 Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
10813 }
10814 return JIM_ERR;
@@ -10976,11 +10815,11 @@
10815 }
10816 if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
10817 Jim_SetResultString(interp, "Integer value too big to be represented", -1);
10818 return JIM_ERR;
10819 }
10820
10821 Jim_FreeIntRep(interp, objPtr);
10822 objPtr->typePtr = &intObjType;
10823 objPtr->internalRep.wideValue = wideValue;
10824 return JIM_OK;
10825 }
@@ -11075,17 +10914,17 @@
10914 {
10915 char buf[JIM_DOUBLE_SPACE + 1];
10916 int i;
10917 int len = sprintf(buf, "%.12g", value);
10918
10919
10920 for (i = 0; i < len; i++) {
10921 if (buf[i] == '.' || buf[i] == 'e') {
10922 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10923 char *e = strchr(buf, 'e');
10924 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10925
10926 e += 2;
10927 memmove(e, e + 1, len - (e - buf));
10928 }
10929 #endif
10930 break;
@@ -11107,38 +10946,38 @@
10946 const char *str;
10947
10948 str = Jim_String(objPtr);
10949
10950 #ifdef HAVE_LONG_LONG
10951
10952 #define MIN_INT_IN_DOUBLE -(1LL << 53)
10953 #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
10954
10955 if (objPtr->typePtr == &intObjType
10956 && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
10957 && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
10958
10959
10960 objPtr->typePtr = &coercedDoubleObjType;
10961 return JIM_OK;
10962 }
10963 else
10964 #endif
10965 if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
10966
10967 Jim_FreeIntRep(interp, objPtr);
10968 objPtr->typePtr = &coercedDoubleObjType;
10969 objPtr->internalRep.wideValue = wideValue;
10970 return JIM_OK;
10971 }
10972 else {
10973
10974 if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
10975 Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr);
10976 return JIM_ERR;
10977 }
10978
10979 Jim_FreeIntRep(interp, objPtr);
10980 }
10981 objPtr->typePtr = &doubleObjType;
10982 objPtr->internalRep.doubleValue = doubleValue;
10983 return JIM_OK;
@@ -11170,10 +11009,50 @@
11009 objPtr->typePtr = &doubleObjType;
11010 objPtr->bytes = NULL;
11011 objPtr->internalRep.doubleValue = doubleValue;
11012 return objPtr;
11013 }
11014
11015 static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
11016
11017 int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr)
11018 {
11019 if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR)
11020 return JIM_ERR;
11021 *booleanPtr = (int) JimWideValue(objPtr);
11022 return JIM_OK;
11023 }
11024
11025 static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
11026 {
11027 static const char * const falses[] = {
11028 "0", "false", "no", "off", NULL
11029 };
11030 static const char * const trues[] = {
11031 "1", "true", "yes", "on", NULL
11032 };
11033
11034 int boolean;
11035
11036 int index;
11037 if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) {
11038 boolean = 0;
11039 } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) {
11040 boolean = 1;
11041 } else {
11042 if (flags & JIM_ERRMSG) {
11043 Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr);
11044 }
11045 return JIM_ERR;
11046 }
11047
11048
11049 Jim_FreeIntRep(interp, objPtr);
11050 objPtr->typePtr = &intObjType;
11051 objPtr->internalRep.wideValue = boolean;
11052 return JIM_OK;
11053 }
11054
11055 static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
11056 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
11057 static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
11058 static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -11221,11 +11100,11 @@
11100 #define JIM_ELESTR_QUOTE 2
11101 static unsigned char ListElementQuotingType(const char *s, int len)
11102 {
11103 int i, level, blevel, trySimple = 1;
11104
11105
11106 if (len == 0)
11107 return JIM_ELESTR_BRACE;
11108 if (s[0] == '"' || s[0] == '{') {
11109 trySimple = 0;
11110 goto testbrace;
@@ -11243,20 +11122,20 @@
11122 case '\n':
11123 case '\t':
11124 case '\f':
11125 case '\v':
11126 trySimple = 0;
11127
11128 case '{':
11129 case '}':
11130 goto testbrace;
11131 }
11132 }
11133 return JIM_ELESTR_SIMPLE;
11134
11135 testbrace:
11136
11137 if (s[len - 1] == '\\')
11138 return JIM_ELESTR_QUOTE;
11139 level = 0;
11140 blevel = 0;
11141 for (i = 0; i < len; i++) {
@@ -11372,11 +11251,11 @@
11251 int i, bufLen, realLength;
11252 const char *strRep;
11253 char *p;
11254 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
11255
11256
11257 if (objc > STATIC_QUOTING_LEN) {
11258 quotingType = Jim_Alloc(objc);
11259 }
11260 else {
11261 quotingType = staticQuoting;
@@ -11391,25 +11270,25 @@
11270 case JIM_ELESTR_SIMPLE:
11271 if (i != 0 || strRep[0] != '#') {
11272 bufLen += len;
11273 break;
11274 }
11275
11276 quotingType[i] = JIM_ELESTR_BRACE;
11277
11278 case JIM_ELESTR_BRACE:
11279 bufLen += len + 2;
11280 break;
11281 case JIM_ELESTR_QUOTE:
11282 bufLen += len * 2;
11283 break;
11284 }
11285 bufLen++;
11286 }
11287 bufLen++;
11288
11289
11290 p = objPtr->bytes = Jim_Alloc(bufLen + 1);
11291 realLength = 0;
11292 for (i = 0; i < objc; i++) {
11293 int len, qlen;
11294
@@ -11436,17 +11315,17 @@
11315 qlen = BackslashQuoteString(strRep, len, p);
11316 p += qlen;
11317 realLength += qlen;
11318 break;
11319 }
11320
11321 if (i + 1 != objc) {
11322 *p++ = ' ';
11323 realLength++;
11324 }
11325 }
11326 *p = '\0';
11327 objPtr->length = realLength;
11328
11329 if (quotingType != staticQuoting) {
11330 Jim_Free(quotingType);
11331 }
@@ -11477,21 +11356,21 @@
11356 listObjPtrPtr = JimDictPairs(objPtr, &len);
11357 for (i = 0; i < len; i++) {
11358 Jim_IncrRefCount(listObjPtrPtr[i]);
11359 }
11360
11361
11362 Jim_FreeIntRep(interp, objPtr);
11363 objPtr->typePtr = &listObjType;
11364 objPtr->internalRep.listValue.len = len;
11365 objPtr->internalRep.listValue.maxLen = len;
11366 objPtr->internalRep.listValue.ele = listObjPtrPtr;
11367
11368 return JIM_OK;
11369 }
11370
11371
11372 if (objPtr->typePtr == &sourceObjType) {
11373 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
11374 linenr = objPtr->internalRep.sourceValue.lineNumber;
11375 }
11376 else {
@@ -11498,20 +11377,20 @@
11377 fileNameObj = interp->emptyObj;
11378 linenr = 1;
11379 }
11380 Jim_IncrRefCount(fileNameObj);
11381
11382
11383 str = Jim_GetString(objPtr, &strLen);
11384
11385 Jim_FreeIntRep(interp, objPtr);
11386 objPtr->typePtr = &listObjType;
11387 objPtr->internalRep.listValue.len = 0;
11388 objPtr->internalRep.listValue.maxLen = 0;
11389 objPtr->internalRep.listValue.ele = NULL;
11390
11391
11392 if (strLen) {
11393 JimParserInit(&parser, str, strLen, linenr);
11394 while (!parser.eof) {
11395 Jim_Obj *elementPtr;
11396
@@ -11641,11 +11520,11 @@
11520 Jim_Obj *compare_script;
11521 int rc;
11522
11523 jim_wide ret = 0;
11524
11525
11526 compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
11527 Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
11528 Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
11529
11530 rc = Jim_EvalObj(sort_info->interp, compare_script);
@@ -11663,23 +11542,23 @@
11542 int dst = 0;
11543 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11544
11545 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11546 if (comp(&ele[dst], &ele[src]) == 0) {
11547
11548 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11549 }
11550 else {
11551
11552 dst++;
11553 }
11554 ele[dst] = ele[src];
11555 }
11556
11557 ele[++dst] = ele[src];
11558
11559
11560 listObjPtr->internalRep.listValue.len = dst;
11561 }
11562
11563
11564 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
@@ -11693,11 +11572,11 @@
11572 int rc;
11573
11574 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11575 SetListFromAny(interp, listObjPtr);
11576
11577
11578 prev_info = sort_info;
11579 sort_info = info;
11580
11581 vector = listObjPtr->internalRep.listValue.ele;
11582 len = listObjPtr->internalRep.listValue.len;
@@ -11716,17 +11595,17 @@
11595 break;
11596 case JIM_LSORT_COMMAND:
11597 fn = ListSortCommand;
11598 break;
11599 default:
11600 fn = NULL;
11601 JimPanic((1, "ListSort called with invalid sort type"));
11602 return -1;
11603 }
11604
11605 if (info->indexed) {
11606
11607 info->subfn = fn;
11608 fn = ListSortIndexHelper;
11609 }
11610
11611 if ((rc = setjmp(info->jmpbuf)) == 0) {
@@ -11750,11 +11629,11 @@
11629 int i;
11630 Jim_Obj **point;
11631
11632 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11633 if (requiredLen < 2) {
11634
11635 requiredLen = 4;
11636 }
11637 else {
11638 requiredLen *= 2;
11639 }
@@ -11936,34 +11815,34 @@
11815 for (i = 0; i < objc; i++)
11816 ListAppendList(objPtr, objv[i]);
11817 return objPtr;
11818 }
11819 else {
11820
11821 int len = 0, objLen;
11822 char *bytes, *p;
11823
11824
11825 for (i = 0; i < objc; i++) {
11826 len += Jim_Length(objv[i]);
11827 }
11828 if (objc)
11829 len += objc - 1;
11830
11831 p = bytes = Jim_Alloc(len + 1);
11832 for (i = 0; i < objc; i++) {
11833 const char *s = Jim_GetString(objv[i], &objLen);
11834
11835
11836 while (objLen && isspace(UCHAR(*s))) {
11837 s++;
11838 objLen--;
11839 len--;
11840 }
11841
11842 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
11843
11844 if (objLen > 1 && s[objLen - 2] == '\\') {
11845 break;
11846 }
11847 objLen--;
11848 len--;
@@ -11990,11 +11869,11 @@
11869 int len, rangeLen;
11870
11871 if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
11872 Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
11873 return NULL;
11874 len = Jim_ListLength(interp, listObjPtr);
11875 first = JimRelToAbsIndex(len, first);
11876 last = JimRelToAbsIndex(len, last);
11877 JimRelToAbsRange(len, &first, &last, &rangeLen);
11878 if (first == 0 && last == len) {
11879 return listObjPtr;
@@ -12030,16 +11909,16 @@
11909 {
11910 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11911 }
11912
11913 static const Jim_HashTableType JimDictHashTableType = {
11914 JimObjectHTHashFunction,
11915 JimObjectHTKeyValDup,
11916 JimObjectHTKeyValDup,
11917 JimObjectHTKeyCompare,
11918 JimObjectHTKeyValDestructor,
11919 JimObjectHTKeyValDestructor
11920 };
11921
11922 static const Jim_ObjType dictObjType = {
11923 "dict",
11924 FreeDictInternalRep,
@@ -12060,17 +11939,17 @@
11939 {
11940 Jim_HashTable *ht, *dupHt;
11941 Jim_HashTableIterator htiter;
11942 Jim_HashEntry *he;
11943
11944
11945 ht = srcPtr->internalRep.ptr;
11946 dupHt = Jim_Alloc(sizeof(*dupHt));
11947 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11948 if (ht->size != 0)
11949 Jim_ExpandHashTable(dupHt, ht->size);
11950
11951 JimInitHashTableIterator(ht, &htiter);
11952 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11953 Jim_AddHashEntry(dupHt, he->key, he->u.val);
11954 }
11955
@@ -12086,11 +11965,11 @@
11965 Jim_Obj **objv;
11966 int i;
11967
11968 ht = dictPtr->internalRep.ptr;
11969
11970
11971 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11972 JimInitHashTableIterator(ht, &htiter);
11973 i = 0;
11974 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11975 objv[i++] = Jim_GetHashEntryKey(he);
@@ -12100,15 +11979,15 @@
11979 return objv;
11980 }
11981
11982 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11983 {
11984
11985 int len;
11986 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11987
11988
11989 JimMakeListStringRep(objPtr, objv, len);
11990
11991 Jim_Free(objv);
11992 }
11993
@@ -12122,18 +12001,18 @@
12001
12002 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
12003 Jim_String(objPtr);
12004 }
12005
12006
12007 listlen = Jim_ListLength(interp, objPtr);
12008 if (listlen % 2) {
12009 Jim_SetResultString(interp, "missing value to go with key", -1);
12010 return JIM_ERR;
12011 }
12012 else {
12013
12014 Jim_HashTable *ht;
12015 int i;
12016
12017 ht = Jim_Alloc(sizeof(*ht));
12018 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
@@ -12158,11 +12037,11 @@
12037 static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
12038 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
12039 {
12040 Jim_HashTable *ht = objPtr->internalRep.ptr;
12041
12042 if (valueObjPtr == NULL) {
12043 return Jim_DeleteHashEntry(ht, keyObjPtr);
12044 }
12045 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
12046 return JIM_OK;
12047 }
@@ -12209,12 +12088,14 @@
12088 if (flags & JIM_ERRMSG) {
12089 Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
12090 }
12091 return JIM_ERR;
12092 }
12093 else {
12094 *objPtrPtr = Jim_GetHashEntryVal(he);
12095 return JIM_OK;
12096 }
12097 }
12098
12099
12100 int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
12101 {
@@ -12258,11 +12139,11 @@
12139 int shared, i;
12140
12141 varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
12142 if (objPtr == NULL) {
12143 if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
12144
12145 return JIM_ERR;
12146 }
12147 varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
12148 if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
12149 Jim_FreeNewObj(interp, varObjPtr);
@@ -12272,26 +12153,26 @@
12153 if ((shared = Jim_IsShared(objPtr)))
12154 varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
12155 for (i = 0; i < keyc; i++) {
12156 dictObjPtr = objPtr;
12157
12158
12159 if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
12160 goto err;
12161 }
12162
12163 if (i == keyc - 1) {
12164
12165 if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
12166 if (newObjPtr || (flags & JIM_MUSTEXIST)) {
12167 goto err;
12168 }
12169 }
12170 break;
12171 }
12172
12173
12174 Jim_InvalidateStringRep(dictObjPtr);
12175 if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
12176 newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
12177 if (Jim_IsShared(objPtr)) {
12178 objPtr = Jim_DuplicateObj(interp, objPtr);
@@ -12304,11 +12185,11 @@
12185 }
12186 objPtr = Jim_NewDictObj(interp, NULL, 0);
12187 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12188 }
12189 }
12190
12191 Jim_InvalidateStringRep(objPtr);
12192 Jim_InvalidateStringRep(varObjPtr);
12193 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12194 goto err;
12195 }
@@ -12341,11 +12222,11 @@
12222 char buf[JIM_INTEGER_SPACE + 1];
12223 if (objPtr->internalRep.intValue >= 0) {
12224 sprintf(buf, "%d", objPtr->internalRep.intValue);
12225 }
12226 else {
12227
12228 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12229 }
12230 JimSetStringBytes(objPtr, buf);
12231 }
12232 }
@@ -12354,14 +12235,14 @@
12235 {
12236 int idx, end = 0;
12237 const char *str;
12238 char *endptr;
12239
12240
12241 str = Jim_String(objPtr);
12242
12243
12244 if (strncmp(str, "end", 3) == 0) {
12245 end = 1;
12246 str += 3;
12247 idx = 0;
12248 }
@@ -12372,21 +12253,21 @@
12253 goto badindex;
12254 }
12255 str = endptr;
12256 }
12257
12258
12259 if (*str == '+' || *str == '-') {
12260 int sign = (*str == '+' ? 1 : -1);
12261
12262 idx += sign * jim_strtol(++str, &endptr);
12263 if (str == endptr || *endptr) {
12264 goto badindex;
12265 }
12266 str = endptr;
12267 }
12268
12269 while (isspace(UCHAR(*str))) {
12270 str++;
12271 }
12272 if (*str) {
12273 goto badindex;
@@ -12394,19 +12275,19 @@
12275 if (end) {
12276 if (idx > 0) {
12277 idx = INT_MAX;
12278 }
12279 else {
12280
12281 idx--;
12282 }
12283 }
12284 else if (idx < 0) {
12285 idx = -INT_MAX;
12286 }
12287
12288
12289 Jim_FreeIntRep(interp, objPtr);
12290 objPtr->typePtr = &indexObjType;
12291 objPtr->internalRep.intValue = idx;
12292 return JIM_OK;
12293
@@ -12416,11 +12297,11 @@
12297 return JIM_ERR;
12298 }
12299
12300 int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
12301 {
12302
12303 if (objPtr->typePtr == &intObjType) {
12304 jim_wide val = JimWideValue(objPtr);
12305
12306 if (val < 0)
12307 *indexPtr = -INT_MAX;
@@ -12473,18 +12354,18 @@
12354 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12355 {
12356 int returnCode;
12357 jim_wide wideValue;
12358
12359
12360 if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
12361 returnCode = (int)wideValue;
12362 else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
12363 Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
12364 return JIM_ERR;
12365 }
12366
12367 Jim_FreeIntRep(interp, objPtr);
12368 objPtr->typePtr = &returnCodeObjType;
12369 objPtr->internalRep.intValue = returnCode;
12370 return JIM_OK;
12371 }
@@ -12498,19 +12379,20 @@
12379 }
12380
12381 static int JimParseExprOperator(struct JimParserCtx *pc);
12382 static int JimParseExprNumber(struct JimParserCtx *pc);
12383 static int JimParseExprIrrational(struct JimParserCtx *pc);
12384 static int JimParseExprBoolean(struct JimParserCtx *pc);
12385
12386
12387
12388
12389 enum
12390 {
12391
12392
12393 JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
12394 JIM_EXPROP_DIV,
12395 JIM_EXPROP_MOD,
12396 JIM_EXPROP_SUB,
12397 JIM_EXPROP_ADD,
12398 JIM_EXPROP_LSHIFT,
@@ -12521,66 +12403,67 @@
12403 JIM_EXPROP_GT,
12404 JIM_EXPROP_LTE,
12405 JIM_EXPROP_GTE,
12406 JIM_EXPROP_NUMEQ,
12407 JIM_EXPROP_NUMNE,
12408 JIM_EXPROP_BITAND,
12409 JIM_EXPROP_BITXOR,
12410 JIM_EXPROP_BITOR,
12411
12412
12413 JIM_EXPROP_LOGICAND,
12414 JIM_EXPROP_LOGICAND_LEFT,
12415 JIM_EXPROP_LOGICAND_RIGHT,
12416
12417
12418 JIM_EXPROP_LOGICOR,
12419 JIM_EXPROP_LOGICOR_LEFT,
12420 JIM_EXPROP_LOGICOR_RIGHT,
12421
12422
12423
12424 JIM_EXPROP_TERNARY,
12425 JIM_EXPROP_TERNARY_LEFT,
12426 JIM_EXPROP_TERNARY_RIGHT,
12427
12428
12429 JIM_EXPROP_COLON,
12430 JIM_EXPROP_COLON_LEFT,
12431 JIM_EXPROP_COLON_RIGHT,
12432
12433 JIM_EXPROP_POW,
12434
12435
12436 JIM_EXPROP_STREQ,
12437 JIM_EXPROP_STRNE,
12438 JIM_EXPROP_STRIN,
12439 JIM_EXPROP_STRNI,
12440
12441
12442 JIM_EXPROP_NOT,
12443 JIM_EXPROP_BITNOT,
12444 JIM_EXPROP_UNARYMINUS,
12445 JIM_EXPROP_UNARYPLUS,
12446
12447
12448 JIM_EXPROP_FUNC_FIRST,
12449 JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
12450 JIM_EXPROP_FUNC_WIDE,
12451 JIM_EXPROP_FUNC_ABS,
12452 JIM_EXPROP_FUNC_DOUBLE,
12453 JIM_EXPROP_FUNC_ROUND,
12454 JIM_EXPROP_FUNC_RAND,
12455 JIM_EXPROP_FUNC_SRAND,
12456
12457
12458 JIM_EXPROP_FUNC_SIN,
12459 JIM_EXPROP_FUNC_COS,
12460 JIM_EXPROP_FUNC_TAN,
12461 JIM_EXPROP_FUNC_ASIN,
12462 JIM_EXPROP_FUNC_ACOS,
12463 JIM_EXPROP_FUNC_ATAN,
12464 JIM_EXPROP_FUNC_ATAN2,
12465 JIM_EXPROP_FUNC_SINH,
12466 JIM_EXPROP_FUNC_COSH,
12467 JIM_EXPROP_FUNC_TANH,
12468 JIM_EXPROP_FUNC_CEIL,
12469 JIM_EXPROP_FUNC_FLOOR,
@@ -12587,10 +12470,12 @@
12470 JIM_EXPROP_FUNC_EXP,
12471 JIM_EXPROP_FUNC_LOG,
12472 JIM_EXPROP_FUNC_LOG10,
12473 JIM_EXPROP_FUNC_SQRT,
12474 JIM_EXPROP_FUNC_POW,
12475 JIM_EXPROP_FUNC_HYPOT,
12476 JIM_EXPROP_FUNC_FMOD,
12477 };
12478
12479 struct JimExprState
12480 {
12481 Jim_Obj **stack;
@@ -12667,11 +12552,15 @@
12552 case JIM_EXPROP_UNARYPLUS:
12553 dC = dA;
12554 intresult = 0;
12555 break;
12556 case JIM_EXPROP_FUNC_ABS:
12557 #ifdef JIM_MATH_FUNCTIONS
12558 dC = fabs(dA);
12559 #else
12560 dC = dA >= 0 ? dA : -dA;
12561 #endif
12562 intresult = 0;
12563 break;
12564 case JIM_EXPROP_UNARYMINUS:
12565 dC = -dA;
12566 intresult = 0;
@@ -12859,16 +12748,16 @@
12748 }
12749 }
12750 break;
12751 case JIM_EXPROP_ROTL:
12752 case JIM_EXPROP_ROTR:{
12753
12754 unsigned long uA = (unsigned long)wA;
12755 unsigned long uB = (unsigned long)wB;
12756 const unsigned int S = sizeof(unsigned long) * 8;
12757
12758
12759 uB %= S;
12760
12761 if (e->opcode == JIM_EXPROP_ROTR) {
12762 uB = S - uB;
12763 }
@@ -12890,11 +12779,10 @@
12779
12780
12781
12782 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12783 {
 
12784 int rc = JIM_OK;
12785 double dA, dB, dC = 0;
12786 jim_wide wA, wB, wC = 0;
12787
12788 Jim_Obj *B = ExprPop(e);
@@ -12902,30 +12790,36 @@
12790
12791 if ((A->typePtr != &doubleObjType || A->bytes) &&
12792 (B->typePtr != &doubleObjType || B->bytes) &&
12793 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12794
12795
12796
12797 switch (e->opcode) {
12798 case JIM_EXPROP_POW:
12799 case JIM_EXPROP_FUNC_POW:
12800 if (wA == 0 && wB < 0) {
12801 Jim_SetResultString(interp, "exponentiation of zero by negative power", -1);
12802 rc = JIM_ERR;
12803 goto done;
12804 }
12805 wC = JimPowWide(wA, wB);
12806 goto intresult;
12807 case JIM_EXPROP_ADD:
12808 wC = wA + wB;
12809 goto intresult;
12810 case JIM_EXPROP_SUB:
12811 wC = wA - wB;
12812 goto intresult;
12813 case JIM_EXPROP_MUL:
12814 wC = wA * wB;
12815 goto intresult;
12816 case JIM_EXPROP_DIV:
12817 if (wB == 0) {
12818 Jim_SetResultString(interp, "Division by zero", -1);
12819 rc = JIM_ERR;
12820 goto done;
12821 }
12822 else {
12823 if (wB < 0) {
12824 wB = -wB;
12825 wA = -wA;
@@ -12932,55 +12826,67 @@
12826 }
12827 wC = wA / wB;
12828 if (wA % wB < 0) {
12829 wC--;
12830 }
12831 goto intresult;
12832 }
 
12833 case JIM_EXPROP_LT:
12834 wC = wA < wB;
12835 goto intresult;
12836 case JIM_EXPROP_GT:
12837 wC = wA > wB;
12838 goto intresult;
12839 case JIM_EXPROP_LTE:
12840 wC = wA <= wB;
12841 goto intresult;
12842 case JIM_EXPROP_GTE:
12843 wC = wA >= wB;
12844 goto intresult;
12845 case JIM_EXPROP_NUMEQ:
12846 wC = wA == wB;
12847 goto intresult;
12848 case JIM_EXPROP_NUMNE:
12849 wC = wA != wB;
12850 goto intresult;
 
 
12851 }
12852 }
12853 if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
 
12854 switch (e->opcode) {
12855 #ifndef JIM_MATH_FUNCTIONS
12856 case JIM_EXPROP_POW:
12857 case JIM_EXPROP_FUNC_POW:
12858 case JIM_EXPROP_FUNC_ATAN2:
12859 case JIM_EXPROP_FUNC_HYPOT:
12860 case JIM_EXPROP_FUNC_FMOD:
12861 Jim_SetResultString(interp, "unsupported", -1);
12862 rc = JIM_ERR;
12863 goto done;
12864 #else
12865 case JIM_EXPROP_POW:
12866 case JIM_EXPROP_FUNC_POW:
12867 dC = pow(dA, dB);
12868 goto doubleresult;
12869 case JIM_EXPROP_FUNC_ATAN2:
12870 dC = atan2(dA, dB);
12871 goto doubleresult;
12872 case JIM_EXPROP_FUNC_HYPOT:
12873 dC = hypot(dA, dB);
12874 goto doubleresult;
12875 case JIM_EXPROP_FUNC_FMOD:
12876 dC = fmod(dA, dB);
12877 goto doubleresult;
12878 #endif
 
12879 case JIM_EXPROP_ADD:
12880 dC = dA + dB;
12881 goto doubleresult;
12882 case JIM_EXPROP_SUB:
12883 dC = dA - dB;
12884 goto doubleresult;
12885 case JIM_EXPROP_MUL:
12886 dC = dA * dB;
12887 goto doubleresult;
12888 case JIM_EXPROP_DIV:
12889 if (dB == 0) {
12890 #ifdef INFINITY
12891 dC = dA < 0 ? -INFINITY : INFINITY;
12892 #else
@@ -12988,83 +12894,70 @@
12894 #endif
12895 }
12896 else {
12897 dC = dA / dB;
12898 }
12899 goto doubleresult;
12900 case JIM_EXPROP_LT:
12901 wC = dA < dB;
12902 goto intresult;
 
12903 case JIM_EXPROP_GT:
12904 wC = dA > dB;
12905 goto intresult;
 
12906 case JIM_EXPROP_LTE:
12907 wC = dA <= dB;
12908 goto intresult;
 
12909 case JIM_EXPROP_GTE:
12910 wC = dA >= dB;
12911 goto intresult;
 
12912 case JIM_EXPROP_NUMEQ:
12913 wC = dA == dB;
12914 goto intresult;
 
12915 case JIM_EXPROP_NUMNE:
12916 wC = dA != dB;
12917 goto intresult;
 
 
 
12918 }
12919 }
12920 else {
 
12921
12922
12923
12924 int i = Jim_StringCompareObj(interp, A, B, 0);
12925
12926 switch (e->opcode) {
12927 case JIM_EXPROP_LT:
12928 wC = i < 0;
12929 goto intresult;
12930 case JIM_EXPROP_GT:
12931 wC = i > 0;
12932 goto intresult;
12933 case JIM_EXPROP_LTE:
12934 wC = i <= 0;
12935 goto intresult;
12936 case JIM_EXPROP_GTE:
12937 wC = i >= 0;
12938 goto intresult;
12939 case JIM_EXPROP_NUMEQ:
12940 wC = i == 0;
12941 goto intresult;
12942 case JIM_EXPROP_NUMNE:
12943 wC = i != 0;
12944 goto intresult;
 
 
 
12945 }
12946 }
12947
12948 rc = JIM_ERR;
12949 done:
 
 
 
 
 
 
 
12950 Jim_DecrRefCount(interp, A);
12951 Jim_DecrRefCount(interp, B);
 
12952 return rc;
12953 intresult:
12954 ExprPush(e, Jim_NewIntObj(interp, wC));
12955 goto done;
12956 doubleresult:
12957 ExprPush(e, Jim_NewDoubleObj(interp, dC));
12958 goto done;
12959 }
12960
12961 static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
12962 {
12963 int listlen;
@@ -13113,16 +13006,20 @@
13006
13007 static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
13008 {
13009 long l;
13010 double d;
13011 int b;
13012
13013 if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
13014 return l != 0;
13015 }
13016 if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
13017 return d != 0;
13018 }
13019 if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
13020 return b != 0;
13021 }
13022 return -1;
13023 }
13024
13025 static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
@@ -13131,21 +13028,21 @@
13028 Jim_Obj *A = ExprPop(e);
13029 int rc = JIM_OK;
13030
13031 switch (ExprBool(interp, A)) {
13032 case 0:
13033
13034 e->skip = JimWideValue(skip);
13035 ExprPush(e, Jim_NewIntObj(interp, 0));
13036 break;
13037
13038 case 1:
13039
13040 break;
13041
13042 case -1:
13043
13044 rc = JIM_ERR;
13045 }
13046 Jim_DecrRefCount(interp, A);
13047 Jim_DecrRefCount(interp, skip);
13048
@@ -13158,21 +13055,21 @@
13055 Jim_Obj *A = ExprPop(e);
13056 int rc = JIM_OK;
13057
13058 switch (ExprBool(interp, A)) {
13059 case 0:
13060
13061 break;
13062
13063 case 1:
13064
13065 e->skip = JimWideValue(skip);
13066 ExprPush(e, Jim_NewIntObj(interp, 1));
13067 break;
13068
13069 case -1:
13070
13071 rc = JIM_ERR;
13072 break;
13073 }
13074 Jim_DecrRefCount(interp, A);
13075 Jim_DecrRefCount(interp, skip);
@@ -13193,11 +13090,11 @@
13090 case 1:
13091 ExprPush(e, Jim_NewIntObj(interp, 1));
13092 break;
13093
13094 case -1:
13095
13096 rc = JIM_ERR;
13097 break;
13098 }
13099 Jim_DecrRefCount(interp, A);
13100
@@ -13208,27 +13105,27 @@
13105 {
13106 Jim_Obj *skip = ExprPop(e);
13107 Jim_Obj *A = ExprPop(e);
13108 int rc = JIM_OK;
13109
13110
13111 ExprPush(e, A);
13112
13113 switch (ExprBool(interp, A)) {
13114 case 0:
13115
13116 e->skip = JimWideValue(skip);
13117
13118 ExprPush(e, Jim_NewIntObj(interp, 0));
13119 break;
13120
13121 case 1:
13122
13123 break;
13124
13125 case -1:
13126
13127 rc = JIM_ERR;
13128 break;
13129 }
13130 Jim_DecrRefCount(interp, A);
13131 Jim_DecrRefCount(interp, skip);
@@ -13240,15 +13137,15 @@
13137 {
13138 Jim_Obj *skip = ExprPop(e);
13139 Jim_Obj *B = ExprPop(e);
13140 Jim_Obj *A = ExprPop(e);
13141
13142
13143 if (ExprBool(interp, A)) {
13144
13145 e->skip = JimWideValue(skip);
13146
13147 ExprPush(e, B);
13148 }
13149
13150 Jim_DecrRefCount(interp, skip);
13151 Jim_DecrRefCount(interp, A);
@@ -13264,15 +13161,16 @@
13161 enum
13162 {
13163 LAZY_NONE,
13164 LAZY_OP,
13165 LAZY_LEFT,
13166 LAZY_RIGHT,
13167 RIGHT_ASSOC,
13168 };
13169
13170 #define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1}
13171 #define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, LAZY_NONE)
13172
13173 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13174 OPRINIT("*", 110, 2, JimExprOpBin),
13175 OPRINIT("/", 110, 2, JimExprOpBin),
13176 OPRINIT("%", 110, 2, JimExprOpIntBin),
@@ -13296,27 +13194,28 @@
13194
13195 OPRINIT("&", 50, 2, JimExprOpIntBin),
13196 OPRINIT("^", 49, 2, JimExprOpIntBin),
13197 OPRINIT("|", 48, 2, JimExprOpIntBin),
13198
13199 OPRINIT_ATTR("&&", 10, 2, NULL, LAZY_OP),
13200 OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13201 OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13202
13203 OPRINIT_ATTR("||", 9, 2, NULL, LAZY_OP),
13204 OPRINIT_ATTR(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13205 OPRINIT_ATTR(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13206
13207 OPRINIT_ATTR("?", 5, 2, JimExprOpNull, LAZY_OP),
13208 OPRINIT_ATTR(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13209 OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13210
13211 OPRINIT_ATTR(":", 5, 2, JimExprOpNull, LAZY_OP),
13212 OPRINIT_ATTR(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13213 OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13214
13215
13216 OPRINIT_ATTR("**", 120, 2, JimExprOpBin, RIGHT_ASSOC),
13217
13218 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13219 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13220
13221 OPRINIT("in", 55, 2, JimExprOpStrBin),
@@ -13342,10 +13241,11 @@
13241 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13242 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13243 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13244 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13245 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13246 OPRINIT("atan2", 200, 2, JimExprOpBin),
13247 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13248 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13249 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13250 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13251 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
@@ -13352,10 +13252,12 @@
13252 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13253 OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13254 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13255 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13256 OPRINIT("pow", 200, 2, JimExprOpBin),
13257 OPRINIT("hypot", 200, 2, JimExprOpBin),
13258 OPRINIT("fmod", 200, 2, JimExprOpBin),
13259 #endif
13260 };
13261 #undef OPRINIT
13262 #undef OPRINIT_LAZY
13263
@@ -13362,20 +13264,20 @@
13264 #define JIM_EXPR_OPERATORS_NUM \
13265 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13266
13267 static int JimParseExpression(struct JimParserCtx *pc)
13268 {
13269
13270 while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
13271 if (*pc->p == '\n') {
13272 pc->linenr++;
13273 }
13274 pc->p++;
13275 pc->len--;
13276 }
13277
13278
13279 pc->tline = pc->linenr;
13280 pc->tstart = pc->p;
13281
13282 if (pc->len == 0) {
13283 pc->tend = pc->p;
@@ -13401,11 +13303,11 @@
13303 return JimParseCmd(pc);
13304 case '$':
13305 if (JimParseVar(pc) == JIM_ERR)
13306 return JimParseExprOperator(pc);
13307 else {
13308
13309 if (pc->tt == JIM_TT_EXPRSUGAR) {
13310 return JIM_ERR;
13311 }
13312 return JIM_OK;
13313 }
@@ -13430,10 +13332,18 @@
13332 case 'N':
13333 case 'I':
13334 case 'n':
13335 case 'i':
13336 if (JimParseExprIrrational(pc) == JIM_ERR)
13337 if (JimParseExprBoolean(pc) == JIM_ERR)
13338 return JimParseExprOperator(pc);
13339 break;
13340 case 't':
13341 case 'f':
13342 case 'o':
13343 case 'y':
13344 if (JimParseExprBoolean(pc) == JIM_ERR)
13345 return JimParseExprOperator(pc);
13346 break;
13347 default:
13348 return JimParseExprOperator(pc);
13349 break;
@@ -13443,21 +13353,21 @@
13353
13354 static int JimParseExprNumber(struct JimParserCtx *pc)
13355 {
13356 char *end;
13357
13358
13359 pc->tt = JIM_TT_EXPR_INT;
13360
13361 jim_strtoull(pc->p, (char **)&pc->p);
13362
13363 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13364 if (strtod(pc->tstart, &end)) { }
13365 if (end == pc->tstart)
13366 return JIM_ERR;
13367 if (end > pc->p) {
13368
13369 pc->tt = JIM_TT_EXPR_DOUBLE;
13370 pc->p = end;
13371 }
13372 }
13373 pc->tend = pc->p - 1;
@@ -13481,17 +13391,38 @@
13391 return JIM_OK;
13392 }
13393 }
13394 return JIM_ERR;
13395 }
13396
13397 static int JimParseExprBoolean(struct JimParserCtx *pc)
13398 {
13399 const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL };
13400 const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 };
13401 int i;
13402
13403 for (i = 0; booleans[i]; i++) {
13404 const char *boolean = booleans[i];
13405 int length = lengths[i];
13406
13407 if (strncmp(boolean, pc->p, length) == 0) {
13408 pc->p += length;
13409 pc->len -= length;
13410 pc->tend = pc->p - 1;
13411 pc->tt = JIM_TT_EXPR_BOOLEAN;
13412 return JIM_OK;
13413 }
13414 }
13415 return JIM_ERR;
13416 }
13417
13418 static int JimParseExprOperator(struct JimParserCtx *pc)
13419 {
13420 int i;
13421 int bestIdx = -1, bestLen = 0;
13422
13423
13424 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13425 const char * const opname = Jim_ExprOperators[i].name;
13426 const int oplen = Jim_ExprOperators[i].namelen;
13427
13428 if (opname == NULL || opname[0] != pc->p[0]) {
@@ -13505,11 +13436,11 @@
13436 }
13437 if (bestIdx == -1) {
13438 return JIM_ERR;
13439 }
13440
13441
13442 if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
13443 const char *p = pc->p + bestLen;
13444 int len = pc->len - bestLen;
13445
13446 while (len && isspace(UCHAR(*p))) {
@@ -13539,13 +13470,19 @@
13470
13471 const char *jim_tt_name(int type)
13472 {
13473 static const char * const tt_names[JIM_TT_EXPR_OP] =
13474 { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
13475 "DBL", "BOO", "$()" };
13476 if (type < JIM_TT_EXPR_OP) {
13477 return tt_names[type];
13478 }
13479 else if (type == JIM_EXPROP_UNARYMINUS) {
13480 return "-VE";
13481 }
13482 else if (type == JIM_EXPROP_UNARYPLUS) {
13483 return "+VE";
13484 }
13485 else {
13486 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
13487 static char buf[20];
13488
@@ -13570,13 +13507,13 @@
13507 };
13508
13509
13510 typedef struct ExprByteCode
13511 {
13512 ScriptToken *token;
13513 int len;
13514 int inUse;
13515 } ExprByteCode;
13516
13517 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13518 {
13519 int i;
@@ -13604,26 +13541,29 @@
13541 static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
13542 {
13543 JIM_NOTUSED(interp);
13544 JIM_NOTUSED(srcPtr);
13545
13546
13547 dupPtr->typePtr = NULL;
13548 }
13549
13550 static int ExprCheckCorrectness(Jim_Interp *interp, Jim_Obj *exprObjPtr, ExprByteCode * expr)
 
13551 {
13552 int i;
13553 int stacklen = 0;
13554 int ternary = 0;
13555 int lasttt = JIM_TT_NONE;
13556 const char *errmsg;
13557
13558 for (i = 0; i < expr->len; i++) {
13559 ScriptToken *t = &expr->token[i];
13560 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13561 lasttt = t->type;
13562
13563 stacklen -= op->arity;
13564
13565 if (stacklen < 0) {
13566 break;
13567 }
13568 if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
13569 ternary++;
@@ -13630,26 +13570,47 @@
13570 }
13571 else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
13572 ternary--;
13573 }
13574
13575
13576 stacklen++;
13577 }
13578 if (stacklen == 1 && ternary == 0) {
13579 return JIM_OK;
13580 }
13581
13582 if (stacklen <= 0) {
13583
13584 if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
13585 errmsg = "too few arguments for math function";
13586 Jim_SetResultString(interp, "too few arguments for math function", -1);
13587 } else {
13588 errmsg = "premature end of expression";
13589 }
13590 }
13591 else if (stacklen > 1) {
13592 if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
13593 errmsg = "too many arguments for math function";
13594 } else {
13595 errmsg = "extra tokens at end of expression";
13596 }
13597 }
13598 else {
13599 errmsg = "invalid ternary expression";
13600 }
13601 Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": %s", exprObjPtr, errmsg);
13602 return JIM_ERR;
13603 }
13604
13605 static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
13606 {
13607 int i;
13608
13609 int leftindex, arity, offset;
13610
13611
13612 leftindex = expr->len - 1;
13613
13614 arity = 1;
13615 while (arity) {
13616 ScriptToken *tt = &expr->token[leftindex];
@@ -13662,11 +13623,11 @@
13623 return JIM_ERR;
13624 }
13625 }
13626 leftindex++;
13627
13628
13629 memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
13630 sizeof(*expr->token) * (expr->len - leftindex));
13631 expr->len += 2;
13632 offset = (expr->len - leftindex) - 1;
13633
@@ -13674,16 +13635,16 @@
13635 expr->token[leftindex + 1].objPtr = interp->emptyObj;
13636
13637 expr->token[leftindex].type = JIM_TT_EXPR_INT;
13638 expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
13639
13640
13641 expr->token[expr->len].objPtr = interp->emptyObj;
13642 expr->token[expr->len].type = t->type + 2;
13643 expr->len++;
13644
13645
13646 for (i = leftindex - 1; i > 0; i--) {
13647 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
13648 if (op->lazy == LAZY_LEFT) {
13649 if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
13650 JimWideValue(expr->token[i - 1].objPtr) += 2;
@@ -13729,11 +13690,11 @@
13690 return right_index;
13691 }
13692 right_index--;
13693 }
13694
13695
13696 return -1;
13697 }
13698
13699 static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
13700 {
@@ -13771,11 +13732,11 @@
13732
13733 if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
13734 continue;
13735 }
13736
13737
13738 if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
13739 continue;
13740 }
13741
13742 tmp = expr->token[prev_right_index];
@@ -13784,25 +13745,25 @@
13745 }
13746 expr->token[i] = tmp;
13747
13748 JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
13749
13750
13751 i++;
13752 }
13753 }
13754
13755 static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
13756 {
13757 Jim_Stack stack;
13758 ExprByteCode *expr;
13759 int ok = 1;
13760 int i;
13761 int prevtt = JIM_TT_NONE;
13762 int have_ternary = 0;
13763
13764
13765 int count = tokenlist->count - 1;
13766
13767 expr = Jim_Alloc(sizeof(*expr));
13768 expr->inUse = 1;
13769 expr->len = 0;
@@ -13813,11 +13774,11 @@
13774 ParseToken *t = &tokenlist->list[i];
13775 const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
13776
13777 if (op->lazy == LAZY_OP) {
13778 count += 2;
13779
13780 if (t->type == JIM_EXPROP_TERNARY) {
13781 have_ternary = 1;
13782 }
13783 }
13784 }
@@ -13825,128 +13786,128 @@
13786 expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
13787
13788 for (i = 0; i < tokenlist->count && ok; i++) {
13789 ParseToken *t = &tokenlist->list[i];
13790
13791
13792 struct ScriptToken *token = &expr->token[expr->len];
13793
13794 if (t->type == JIM_TT_EOL) {
13795 break;
13796 }
13797
13798 if (TOKEN_IS_EXPR_OP(t->type)) {
13799 const struct Jim_ExprOperator *op;
13800 ParseToken *tt;
13801
13802
13803 if (prevtt == JIM_TT_NONE || prevtt == JIM_TT_SUBEXPR_START || prevtt == JIM_TT_SUBEXPR_COMMA || prevtt >= JIM_TT_EXPR_OP) {
13804 if (t->type == JIM_EXPROP_SUB) {
13805 t->type = JIM_EXPROP_UNARYMINUS;
13806 }
13807 else if (t->type == JIM_EXPROP_ADD) {
13808 t->type = JIM_EXPROP_UNARYPLUS;
13809 }
13810 }
13811
13812 op = JimExprOperatorInfoByOpcode(t->type);
13813
13814
13815 while ((tt = Jim_StackPeek(&stack)) != NULL) {
13816 const struct Jim_ExprOperator *tt_op =
13817 JimExprOperatorInfoByOpcode(tt->type);
13818
13819
13820 if (op->arity != 1 && tt_op->precedence >= op->precedence) {
13821
13822 if (tt_op->precedence == op->precedence && tt_op->lazy == RIGHT_ASSOC) {
13823 break;
13824 }
13825 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13826 ok = 0;
13827 goto err;
13828 }
13829 Jim_StackPop(&stack);
13830 }
13831 else {
13832 break;
13833 }
13834 }
13835 Jim_StackPush(&stack, t);
13836 }
13837 else if (t->type == JIM_TT_SUBEXPR_START) {
13838 Jim_StackPush(&stack, t);
13839 }
13840 else if (t->type == JIM_TT_SUBEXPR_END || t->type == JIM_TT_SUBEXPR_COMMA) {
13841
13842 ok = 0;
13843 while (Jim_StackLen(&stack)) {
13844 ParseToken *tt = Jim_StackPop(&stack);
13845
13846 if (tt->type == JIM_TT_SUBEXPR_START || tt->type == JIM_TT_SUBEXPR_COMMA) {
13847 if (t->type == JIM_TT_SUBEXPR_COMMA) {
13848
13849 Jim_StackPush(&stack, tt);
13850 }
13851 ok = 1;
13852 break;
13853 }
13854 if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
13855 goto err;
13856 }
13857 }
13858 if (!ok) {
13859 Jim_SetResultFormatted(interp, "Unexpected close parenthesis in expression: \"%#s\"", exprObjPtr);
13860 goto err;
13861 }
13862 }
13863 else {
13864 Jim_Obj *objPtr = NULL;
13865
13866
13867 token->type = t->type;
13868
13869
13870 if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) {
13871 Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", exprObjPtr);
13872 ok = 0;
13873 goto err;
13874 }
13875
13876
13877 if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) {
13878 char *endptr;
13879 if (t->type == JIM_TT_EXPR_INT) {
13880 objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
13881 }
13882 else {
13883 objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
13884 }
13885 if (endptr != t->token + t->len) {
13886
13887 Jim_FreeNewObj(interp, objPtr);
13888 objPtr = NULL;
13889 }
13890 }
13891
13892 if (objPtr) {
13893 token->objPtr = objPtr;
13894 }
13895 else {
13896
13897 token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
13898 if (t->type == JIM_TT_CMD) {
13899
13900 JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
13901 }
13902 }
13903 expr->len++;
13904 }
13905 prevtt = t->type;
13906 }
13907
13908
13909 while (Jim_StackLen(&stack)) {
13910 ParseToken *tt = Jim_StackPop(&stack);
13911
13912 if (tt->type == JIM_TT_SUBEXPR_START) {
13913 ok = 0;
@@ -13962,11 +13923,11 @@
13923 if (have_ternary) {
13924 ExprTernaryReorderExpression(interp, expr);
13925 }
13926
13927 err:
13928
13929 Jim_FreeStack(&stack);
13930
13931 for (i = 0; i < expr->len; i++) {
13932 Jim_IncrRefCount(expr->token[i].objPtr);
13933 }
@@ -13989,11 +13950,11 @@
13950 ParseTokenList tokenlist;
13951 int line;
13952 Jim_Obj *fileNameObj;
13953 int rc = JIM_ERR;
13954
13955
13956 if (objPtr->typePtr == &sourceObjType) {
13957 fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
13958 line = objPtr->internalRep.sourceValue.lineNumber;
13959 }
13960 else {
@@ -14002,18 +13963,17 @@
13963 }
13964 Jim_IncrRefCount(fileNameObj);
13965
13966 exprText = Jim_GetString(objPtr, &exprTextLen);
13967
13968
13969 ScriptTokenListInit(&tokenlist);
13970
13971 JimParserInit(&parser, exprText, exprTextLen, line);
13972 while (!parser.eof) {
13973 if (JimParseExpression(&parser) != JIM_OK) {
13974 ScriptTokenListFree(&tokenlist);
 
13975 Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
13976 expr = NULL;
13977 goto err;
13978 }
13979
@@ -14036,14 +13996,14 @@
13996 ScriptTokenListFree(&tokenlist);
13997 Jim_DecrRefCount(interp, fileNameObj);
13998 return JIM_ERR;
13999 }
14000
 
 
14001
14002 expr = ExprCreateByteCode(interp, &tokenlist, objPtr, fileNameObj);
14003
14004
14005 ScriptTokenListFree(&tokenlist);
14006
14007 if (!expr) {
14008 goto err;
14009 }
@@ -14059,20 +14019,22 @@
14019 printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
14020 }
14021 }
14022 #endif
14023
14024
14025 if (ExprCheckCorrectness(interp, objPtr, expr) != JIM_OK) {
14026
14027 ExprFreeByteCode(interp, expr);
14028 expr = NULL;
14029 goto err;
14030 }
14031
14032 rc = JIM_OK;
14033
14034 err:
14035
14036 Jim_DecrRefCount(interp, fileNameObj);
14037 Jim_FreeIntRep(interp, objPtr);
14038 Jim_SetIntRepPtr(objPtr, expr);
14039 objPtr->typePtr = &exprObjType;
14040 return rc;
@@ -14112,11 +14074,11 @@
14074 int retcode = JIM_OK;
14075 struct JimExprState e;
14076
14077 expr = JimGetExpression(interp, exprObjPtr);
14078 if (!expr) {
14079 return JIM_ERR;
14080 }
14081
14082 #ifdef JIM_OPTIMIZATION
14083 {
14084 Jim_Obj *objPtr;
@@ -14185,26 +14147,27 @@
14147 noopt:
14148 #endif
14149
14150 expr->inUse++;
14151
14152
14153
14154 if (expr->len > JIM_EE_STATICSTACK_LEN)
14155 e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
14156 else
14157 e.stack = staticStack;
14158
14159 e.stacklen = 0;
14160
14161
14162 for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
14163 Jim_Obj *objPtr;
14164
14165 switch (expr->token[i].type) {
14166 case JIM_TT_EXPR_INT:
14167 case JIM_TT_EXPR_DOUBLE:
14168 case JIM_TT_EXPR_BOOLEAN:
14169 case JIM_TT_STR:
14170 ExprPush(&e, expr->token[i].objPtr);
14171 break;
14172
14173 case JIM_TT_VAR:
@@ -14240,16 +14203,16 @@
14203 ExprPush(&e, Jim_GetResult(interp));
14204 }
14205 break;
14206
14207 default:{
14208
14209 e.skip = 0;
14210 e.opcode = expr->token[i].type;
14211
14212 retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
14213
14214 i += e.skip;
14215 continue;
14216 }
14217 }
14218 }
@@ -14273,20 +14236,27 @@
14236 int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
14237 {
14238 int retcode;
14239 jim_wide wideValue;
14240 double doubleValue;
14241 int booleanValue;
14242 Jim_Obj *exprResultPtr;
14243
14244 retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
14245 if (retcode != JIM_OK)
14246 return retcode;
14247
14248 if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
14249 if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
14250 if (Jim_GetBoolean(interp, exprResultPtr, &booleanValue) != JIM_OK) {
14251 Jim_DecrRefCount(interp, exprResultPtr);
14252 return JIM_ERR;
14253 } else {
14254 Jim_DecrRefCount(interp, exprResultPtr);
14255 *boolPtr = booleanValue;
14256 return JIM_OK;
14257 }
14258 }
14259 else {
14260 Jim_DecrRefCount(interp, exprResultPtr);
14261 *boolPtr = doubleValue != 0;
14262 return JIM_OK;
@@ -14301,29 +14271,29 @@
14271
14272
14273
14274 typedef struct ScanFmtPartDescr
14275 {
14276 char *arg;
14277 char *prefix;
14278 size_t width;
14279 int pos;
14280 char type;
14281 char modifier;
14282 } ScanFmtPartDescr;
14283
14284
14285 typedef struct ScanFmtStringObj
14286 {
14287 jim_wide size;
14288 char *stringRep;
14289 size_t count;
14290 size_t convCount;
14291 size_t maxPos;
14292 const char *error;
14293 char *scratch;
14294 ScanFmtPartDescr descr[1];
14295 } ScanFmtStringObj;
14296
14297
14298 static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
14299 static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14370,22 +14340,22 @@
14340 int maxFmtLen = objPtr->length;
14341 const char *fmtEnd = fmt + maxFmtLen;
14342 int curr;
14343
14344 Jim_FreeIntRep(interp, objPtr);
14345
14346 for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
14347 if (fmt[i] == '%')
14348 ++maxCount;
14349
14350 approxSize = sizeof(ScanFmtStringObj)
14351 +(maxCount + 1) * sizeof(ScanFmtPartDescr)
14352 +maxFmtLen * sizeof(char) + 3 + 1
14353 + maxFmtLen * sizeof(char) + 1
14354 + maxFmtLen * sizeof(char)
14355 +(maxCount + 1) * sizeof(char)
14356 +1;
14357 fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
14358 memset(fmtObj, 0, approxSize);
14359 fmtObj->size = approxSize;
14360 fmtObj->maxPos = 0;
14361 fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
@@ -14397,12 +14367,12 @@
14367 for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
14368 int width = 0, skip;
14369 ScanFmtPartDescr *descr = &fmtObj->descr[curr];
14370
14371 fmtObj->count++;
14372 descr->width = 0;
14373
14374 if (*fmt != '%' || fmt[1] == '%') {
14375 descr->type = 0;
14376 descr->prefix = &buffer[i];
14377 for (; fmt < fmtEnd; ++fmt) {
14378 if (*fmt == '%') {
@@ -14412,65 +14382,65 @@
14382 }
14383 buffer[i++] = *fmt;
14384 }
14385 buffer[i++] = 0;
14386 }
14387
14388 ++fmt;
14389
14390 if (fmt >= fmtEnd)
14391 goto done;
14392 descr->pos = 0;
14393 if (*fmt == '*') {
14394 descr->pos = -1;
14395 ++fmt;
14396 }
14397 else
14398 fmtObj->convCount++;
14399
14400 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14401 fmt += skip;
14402
14403 if (descr->pos != -1 && *fmt == '$') {
14404 int prev;
14405
14406 ++fmt;
14407 descr->pos = width;
14408 width = 0;
14409
14410 if ((lastPos == 0 && descr->pos > 0)
14411 || (lastPos > 0 && descr->pos == 0)) {
14412 fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
14413 return JIM_ERR;
14414 }
14415
14416 for (prev = 0; prev < curr; ++prev) {
14417 if (fmtObj->descr[prev].pos == -1)
14418 continue;
14419 if (fmtObj->descr[prev].pos == descr->pos) {
14420 fmtObj->error =
14421 "variable is assigned by multiple \"%n$\" conversion specifiers";
14422 return JIM_ERR;
14423 }
14424 }
14425
14426 if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
14427 descr->width = width;
14428 fmt += skip;
14429 }
14430 if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
14431 fmtObj->maxPos = descr->pos;
14432 }
14433 else {
14434
14435 descr->width = width;
14436 }
14437 }
14438
14439 if (lastPos == -1)
14440 lastPos = descr->pos;
14441
14442 if (*fmt == '[') {
14443 int swapped = 1, beg = i, end, j;
14444
14445 descr->type = '[';
14446 descr->arg = &buffer[i];
@@ -14485,11 +14455,11 @@
14455 fmtObj->error = "unmatched [ in format string";
14456 return JIM_ERR;
14457 }
14458 end = i;
14459 buffer[i++] = 0;
14460
14461 while (swapped) {
14462 swapped = 0;
14463 for (j = beg + 1; j < end - 1; ++j) {
14464 if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
14465 char tmp = buffer[j - 1];
@@ -14500,11 +14470,11 @@
14470 }
14471 }
14472 }
14473 }
14474 else {
14475
14476 if (strchr("hlL", *fmt) != 0)
14477 descr->modifier = tolower((int)*fmt++);
14478
14479 descr->type = *fmt;
14480 if (strchr("efgcsndoxui", *fmt) == 0) {
@@ -14543,11 +14513,11 @@
14513 while (*str) {
14514 int c;
14515 int n;
14516
14517 if (!sdescr && isspace(UCHAR(*str)))
14518 break;
14519
14520 n = utf8_tounicode(str, &c);
14521 if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
14522 break;
14523 while (n--)
@@ -14566,89 +14536,89 @@
14536 size_t scanned = 0;
14537 size_t anchor = pos;
14538 int i;
14539 Jim_Obj *tmpObj = NULL;
14540
14541
14542 *valObjPtr = 0;
14543 if (descr->prefix) {
14544 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14545
14546 if (isspace(UCHAR(descr->prefix[i])))
14547 while (pos < strLen && isspace(UCHAR(str[pos])))
14548 ++pos;
14549 else if (descr->prefix[i] != str[pos])
14550 break;
14551 else
14552 ++pos;
14553 }
14554 if (pos >= strLen) {
14555 return -1;
14556 }
14557 else if (descr->prefix[i] != 0)
14558 return 0;
14559 }
14560
14561 if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
14562 while (isspace(UCHAR(str[pos])))
14563 ++pos;
14564
14565 scanned = pos - anchor;
14566
14567
14568 if (descr->type == 'n') {
14569
14570 *valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
14571 }
14572 else if (pos >= strLen) {
14573
14574 return -1;
14575 }
14576 else if (descr->type == 'c') {
14577 int c;
14578 scanned += utf8_tounicode(&str[pos], &c);
14579 *valObjPtr = Jim_NewIntObj(interp, c);
14580 return scanned;
14581 }
14582 else {
14583
14584 if (descr->width > 0) {
14585 size_t sLen = utf8_strlen(&str[pos], strLen - pos);
14586 size_t tLen = descr->width > sLen ? sLen : descr->width;
14587
14588 tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
14589 tok = tmpObj->bytes;
14590 }
14591 else {
14592
14593 tok = &str[pos];
14594 }
14595 switch (descr->type) {
14596 case 'd':
14597 case 'o':
14598 case 'x':
14599 case 'u':
14600 case 'i':{
14601 char *endp;
14602 jim_wide w;
14603
14604 int base = descr->type == 'o' ? 8
14605 : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
14606
14607
14608 if (base == 0) {
14609 w = jim_strtoull(tok, &endp);
14610 }
14611 else {
14612 w = strtoull(tok, &endp, base);
14613 }
14614
14615 if (endp != tok) {
14616
14617 *valObjPtr = Jim_NewIntObj(interp, w);
14618
14619
14620 scanned += endp - tok;
14621 }
14622 else {
14623 scanned = *tok ? 0 : -1;
14624 }
@@ -14665,13 +14635,13 @@
14635 case 'g':{
14636 char *endp;
14637 double value = strtod(tok, &endp);
14638
14639 if (endp != tok) {
14640
14641 *valObjPtr = Jim_NewDoubleObj(interp, value);
14642
14643 scanned += endp - tok;
14644 }
14645 else {
14646 scanned = *tok ? 0 : -1;
14647 }
@@ -14696,65 +14666,65 @@
14666 Jim_Obj **resultVec = 0;
14667 int resultc;
14668 Jim_Obj *emptyStr = 0;
14669 ScanFmtStringObj *fmtObj;
14670
14671
14672 JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
14673
14674 fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
14675
14676 if (fmtObj->error != 0) {
14677 if (flags & JIM_ERRMSG)
14678 Jim_SetResultString(interp, fmtObj->error, -1);
14679 return 0;
14680 }
14681
14682 emptyStr = Jim_NewEmptyStringObj(interp);
14683 Jim_IncrRefCount(emptyStr);
14684
14685 resultList = Jim_NewListObj(interp, NULL, 0);
14686 if (fmtObj->maxPos > 0) {
14687 for (i = 0; i < fmtObj->maxPos; ++i)
14688 Jim_ListAppendElement(interp, resultList, emptyStr);
14689 JimListGetElements(interp, resultList, &resultc, &resultVec);
14690 }
14691
14692 for (i = 0, pos = 0; i < fmtObj->count; ++i) {
14693 ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
14694 Jim_Obj *value = 0;
14695
14696
14697 if (descr->type == 0)
14698 continue;
14699
14700 if (scanned > 0)
14701 scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
14702
14703 if (scanned == -1 && i == 0)
14704 goto eof;
14705
14706 pos += scanned;
14707
14708
14709 if (value == 0)
14710 value = Jim_NewEmptyStringObj(interp);
14711
14712 if (descr->pos == -1) {
14713 Jim_FreeNewObj(interp, value);
14714 }
14715 else if (descr->pos == 0)
14716
14717 Jim_ListAppendElement(interp, resultList, value);
14718 else if (resultVec[descr->pos - 1] == emptyStr) {
14719
14720 Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
14721 Jim_IncrRefCount(value);
14722 resultVec[descr->pos - 1] = value;
14723 }
14724 else {
14725
14726 Jim_FreeNewObj(interp, value);
14727 goto err;
14728 }
14729 }
14730 Jim_DecrRefCount(interp, emptyStr);
@@ -14792,15 +14762,15 @@
14762 {
14763 Jim_PrngState *prng;
14764 unsigned char *destByte = (unsigned char *)dest;
14765 unsigned int si, sj, x;
14766
14767
14768 if (interp->prngState == NULL)
14769 JimPrngInit(interp);
14770 prng = interp->prngState;
14771
14772 for (x = 0; x < len; x++) {
14773 prng->i = (prng->i + 1) & 0xff;
14774 si = prng->sbox[prng->i];
14775 prng->j = (prng->j + si) & 0xff;
14776 sj = prng->sbox[prng->j];
@@ -14814,19 +14784,19 @@
14784 static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
14785 {
14786 int i;
14787 Jim_PrngState *prng;
14788
14789
14790 if (interp->prngState == NULL)
14791 JimPrngInit(interp);
14792 prng = interp->prngState;
14793
14794
14795 for (i = 0; i < 256; i++)
14796 prng->sbox[i] = i;
14797
14798 for (i = 0; i < seedLen; i++) {
14799 unsigned char t;
14800
14801 t = prng->sbox[i & 0xFF];
14802 prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
@@ -14853,11 +14823,11 @@
14823 if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
14824 return JIM_ERR;
14825 }
14826 intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
14827 if (!intObjPtr) {
14828
14829 wideValue = 0;
14830 }
14831 else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
14832 return JIM_ERR;
14833 }
@@ -14867,26 +14837,26 @@
14837 Jim_FreeNewObj(interp, intObjPtr);
14838 return JIM_ERR;
14839 }
14840 }
14841 else {
14842
14843 Jim_InvalidateStringRep(intObjPtr);
14844 JimWideValue(intObjPtr) = wideValue + increment;
14845
14846 if (argv[1]->typePtr != &variableObjType) {
14847
14848 Jim_SetVariable(interp, argv[1], intObjPtr);
14849 }
14850 }
14851 Jim_SetResult(interp, intObjPtr);
14852 return JIM_OK;
14853 }
14854
14855
14856 #define JIM_EVAL_SARGV_LEN 8
14857 #define JIM_EVAL_SINTV_LEN 8
14858
14859
14860 static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
14861 {
14862 int retcode;
@@ -14894,16 +14864,16 @@
14864 if (interp->unknown_called > 50) {
14865 return JIM_ERR;
14866 }
14867
14868
14869
14870 if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
14871 return JIM_ERR;
14872
14873 interp->unknown_called++;
14874
14875 retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
14876 interp->unknown_called--;
14877
14878 return retcode;
14879 }
@@ -14921,11 +14891,11 @@
14891 }
14892 printf("\n");
14893 #endif
14894
14895 if (interp->framePtr->tailcallCmd) {
14896
14897 cmdPtr = interp->framePtr->tailcallCmd;
14898 interp->framePtr->tailcallCmd = NULL;
14899 }
14900 else {
14901 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
@@ -14940,11 +14910,11 @@
14910 retcode = JIM_ERR;
14911 goto out;
14912 }
14913 interp->evalDepth++;
14914
14915
14916 Jim_SetEmptyResult(interp);
14917 if (cmdPtr->isproc) {
14918 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14919 }
14920 else {
@@ -14961,17 +14931,17 @@
14931
14932 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14933 {
14934 int i, retcode;
14935
14936
14937 for (i = 0; i < objc; i++)
14938 Jim_IncrRefCount(objv[i]);
14939
14940 retcode = JimInvokeCommand(interp, objc, objv);
14941
14942
14943 for (i = 0; i < objc; i++)
14944 Jim_DecrRefCount(interp, objv[i]);
14945
14946 return retcode;
14947 }
@@ -14989,25 +14959,25 @@
14959 }
14960
14961 static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
14962 {
14963 if (!interp->errorFlag) {
14964
14965 interp->errorFlag = 1;
14966 Jim_IncrRefCount(script->fileNameObj);
14967 Jim_DecrRefCount(interp, interp->errorFileNameObj);
14968 interp->errorFileNameObj = script->fileNameObj;
14969 interp->errorLine = script->linenr;
14970
14971 JimResetStackTrace(interp);
14972
14973 interp->addStackTrace++;
14974 }
14975
14976
14977 if (interp->addStackTrace > 0) {
14978
14979
14980 JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
14981
14982 if (Jim_Length(script->fileNameObj)) {
14983 interp->addStackTrace = 0;
@@ -15042,14 +15012,14 @@
15012 case JIM_OK:
15013 case JIM_RETURN:
15014 objPtr = interp->result;
15015 break;
15016 case JIM_BREAK:
15017
15018 return JIM_BREAK;
15019 case JIM_CONTINUE:
15020
15021 return JIM_CONTINUE;
15022 default:
15023 return JIM_ERR;
15024 }
15025 break;
@@ -15084,23 +15054,23 @@
15054 case JIM_OK:
15055 case JIM_RETURN:
15056 break;
15057 case JIM_BREAK:
15058 if (flags & JIM_SUBST_FLAG) {
15059
15060 tokens = i;
15061 continue;
15062 }
15063
15064
15065 case JIM_CONTINUE:
15066 if (flags & JIM_SUBST_FLAG) {
15067 intv[i] = NULL;
15068 continue;
15069 }
15070
15071
15072 default:
15073 while (i--) {
15074 Jim_DecrRefCount(interp, intv[i]);
15075 }
15076 if (intv != sintv) {
@@ -15111,28 +15081,28 @@
15081 Jim_IncrRefCount(intv[i]);
15082 Jim_String(intv[i]);
15083 totlen += intv[i]->length;
15084 }
15085
15086
15087 if (tokens == 1 && intv[0] && intv == sintv) {
15088 Jim_DecrRefCount(interp, intv[0]);
15089 return intv[0];
15090 }
15091
15092 objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
15093
15094 if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
15095 && token[2].type == JIM_TT_VAR) {
15096
15097 objPtr->typePtr = &interpolatedObjType;
15098 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
15099 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
15100 Jim_IncrRefCount(intv[2]);
15101 }
15102 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
15103
15104 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
15105 }
15106
15107
15108 s = objPtr->bytes = Jim_Alloc(totlen + 1);
@@ -15143,11 +15113,11 @@
15113 s += intv[i]->length;
15114 Jim_DecrRefCount(interp, intv[i]);
15115 }
15116 }
15117 objPtr->bytes[totlen] = '\0';
15118
15119 if (intv != sintv) {
15120 Jim_Free(intv);
15121 }
15122
15123 return objPtr;
@@ -15187,11 +15157,11 @@
15157
15158 if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
15159 return JimEvalObjList(interp, scriptObjPtr);
15160 }
15161
15162 Jim_IncrRefCount(scriptObjPtr);
15163 script = JimGetScript(interp, scriptObjPtr);
15164 if (!JimScriptValid(interp, script)) {
15165 Jim_DecrRefCount(interp, scriptObjPtr);
15166 return JIM_ERR;
15167 }
@@ -15223,11 +15193,11 @@
15193 }
15194 #endif
15195
15196 script->inUse++;
15197
15198
15199 prevScriptObj = interp->currentScriptObj;
15200 interp->currentScriptObj = scriptObjPtr;
15201
15202 interp->errorFlag = 0;
15203 argv = sargv;
@@ -15234,19 +15204,19 @@
15204
15205 for (i = 0; i < script->len && retcode == JIM_OK; ) {
15206 int argc;
15207 int j;
15208
15209
15210 argc = token[i].objPtr->internalRep.scriptLineValue.argc;
15211 script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
15212
15213
15214 if (argc > JIM_EVAL_SARGV_LEN)
15215 argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
15216
15217
15218 i++;
15219
15220 for (j = 0; j < argc; j++) {
15221 long wordtokens = 1;
15222 int expand = 0;
@@ -15302,11 +15272,11 @@
15272
15273 if (!expand) {
15274 argv[j] = wordObjPtr;
15275 }
15276 else {
15277
15278 int len = Jim_ListLength(interp, wordObjPtr);
15279 int newargc = argc + len - 1;
15280 int k;
15281
15282 if (len > 1) {
@@ -15315,39 +15285,39 @@
15285 argv = Jim_Alloc(sizeof(*argv) * newargc);
15286 memcpy(argv, sargv, sizeof(*argv) * j);
15287 }
15288 }
15289 else {
15290
15291 argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
15292 }
15293 }
15294
15295
15296 for (k = 0; k < len; k++) {
15297 argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
15298 Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
15299 }
15300
15301 Jim_DecrRefCount(interp, wordObjPtr);
15302
15303
15304 j--;
15305 argc += len - 1;
15306 }
15307 }
15308
15309 if (retcode == JIM_OK && argc) {
15310
15311 retcode = JimInvokeCommand(interp, argc, argv);
15312
15313 if (Jim_CheckSignal(interp)) {
15314 retcode = JIM_SIGNAL;
15315 }
15316 }
15317
15318
15319 while (j-- > 0) {
15320 Jim_DecrRefCount(interp, argv[j]);
15321 }
15322
15323 if (argv != sargv) {
@@ -15354,21 +15324,21 @@
15324 Jim_Free(argv);
15325 argv = sargv;
15326 }
15327 }
15328
15329
15330 if (retcode == JIM_ERR) {
15331 JimAddErrorToStack(interp, script);
15332 }
15333
15334 else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
15335
15336 interp->addStackTrace = 0;
15337 }
15338
15339
15340 interp->currentScriptObj = prevScriptObj;
15341
15342 Jim_FreeIntRep(interp, scriptObjPtr);
15343 scriptObjPtr->typePtr = &scriptObjType;
15344 Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -15378,14 +15348,14 @@
15348 }
15349
15350 static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
15351 {
15352 int retcode;
15353
15354 const char *varname = Jim_String(argNameObj);
15355 if (*varname == '&') {
15356
15357 Jim_Obj *objPtr;
15358 Jim_CallFrame *savedCallFrame = interp->framePtr;
15359
15360 interp->framePtr = interp->framePtr->parent;
15361 objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
@@ -15392,11 +15362,11 @@
15362 interp->framePtr = savedCallFrame;
15363 if (!objPtr) {
15364 return JIM_ERR;
15365 }
15366
15367
15368 objPtr = Jim_NewStringObj(interp, varname + 1, -1);
15369 Jim_IncrRefCount(objPtr);
15370 retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
15371 Jim_DecrRefCount(interp, objPtr);
15372 }
@@ -15406,26 +15376,26 @@
15376 return retcode;
15377 }
15378
15379 static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
15380 {
15381
15382 Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
15383 int i;
15384
15385 for (i = 0; i < cmd->u.proc.argListLen; i++) {
15386 Jim_AppendString(interp, argmsg, " ", 1);
15387
15388 if (i == cmd->u.proc.argsPos) {
15389 if (cmd->u.proc.arglist[i].defaultObjPtr) {
15390
15391 Jim_AppendString(interp, argmsg, "?", 1);
15392 Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
15393 Jim_AppendString(interp, argmsg, " ...?", -1);
15394 }
15395 else {
15396
15397 Jim_AppendString(interp, argmsg, "?arg...?", -1);
15398 }
15399 }
15400 else {
15401 if (cmd->u.proc.arglist[i].defaultObjPtr) {
@@ -15441,20 +15411,19 @@
15411 Jim_AppendString(interp, argmsg, arg, -1);
15412 }
15413 }
15414 }
15415 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
 
15416 }
15417
15418 #ifdef jim_ext_namespace
15419 int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
15420 {
15421 Jim_CallFrame *callFramePtr;
15422 int retcode;
15423
15424
15425 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
15426 callFramePtr->argv = &interp->emptyObj;
15427 callFramePtr->argc = 0;
15428 callFramePtr->procArgsObjPtr = NULL;
15429 callFramePtr->procBodyObjPtr = scriptObj;
@@ -15462,21 +15431,21 @@
15431 callFramePtr->fileNameObj = interp->emptyObj;
15432 callFramePtr->line = 0;
15433 Jim_IncrRefCount(scriptObj);
15434 interp->framePtr = callFramePtr;
15435
15436
15437 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15438 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15439 retcode = JIM_ERR;
15440 }
15441 else {
15442
15443 retcode = Jim_EvalObj(interp, scriptObj);
15444 }
15445
15446
15447 interp->framePtr = interp->framePtr->parent;
15448 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15449
15450 return retcode;
15451 }
@@ -15486,62 +15455,62 @@
15455 {
15456 Jim_CallFrame *callFramePtr;
15457 int i, d, retcode, optargs;
15458 ScriptObj *script;
15459
15460
15461 if (argc - 1 < cmd->u.proc.reqArity ||
15462 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
15463 JimSetProcWrongArgs(interp, argv[0], cmd);
15464 return JIM_ERR;
15465 }
15466
15467 if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
15468
15469 return JIM_OK;
15470 }
15471
15472
15473 if (interp->framePtr->level == interp->maxCallFrameDepth) {
15474 Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
15475 return JIM_ERR;
15476 }
15477
15478
15479 callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
15480 callFramePtr->argv = argv;
15481 callFramePtr->argc = argc;
15482 callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
15483 callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
15484 callFramePtr->staticVars = cmd->u.proc.staticVars;
15485
15486
15487 script = JimGetScript(interp, interp->currentScriptObj);
15488 callFramePtr->fileNameObj = script->fileNameObj;
15489 callFramePtr->line = script->linenr;
15490
15491 Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
15492 Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
15493 interp->framePtr = callFramePtr;
15494
15495
15496 optargs = (argc - 1 - cmd->u.proc.reqArity);
15497
15498
15499 i = 1;
15500 for (d = 0; d < cmd->u.proc.argListLen; d++) {
15501 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
15502 if (d == cmd->u.proc.argsPos) {
15503
15504 Jim_Obj *listObjPtr;
15505 int argsLen = 0;
15506 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
15507 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
15508 }
15509 listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
15510
15511
15512 if (cmd->u.proc.arglist[d].defaultObjPtr) {
15513 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
15514 }
15515 retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
15516 if (retcode != JIM_OK) {
@@ -15550,33 +15519,33 @@
15519
15520 i += argsLen;
15521 continue;
15522 }
15523
15524
15525 if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
15526 retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
15527 }
15528 else {
15529
15530 retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
15531 }
15532 if (retcode != JIM_OK) {
15533 goto badargset;
15534 }
15535 }
15536
15537
15538 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15539
15540 badargset:
15541
15542
15543 interp->framePtr = interp->framePtr->parent;
15544 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15545
15546
15547 if (interp->framePtr->tailcallObj) {
15548 do {
15549 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15550
15551 interp->framePtr->tailcallObj = NULL;
@@ -15588,18 +15557,18 @@
15557 }
15558 }
15559 Jim_DecrRefCount(interp, tailcallObj);
15560 } while (interp->framePtr->tailcallObj);
15561
15562
15563 if (interp->framePtr->tailcallCmd) {
15564 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15565 interp->framePtr->tailcallCmd = NULL;
15566 }
15567 }
15568
15569
15570 if (retcode == JIM_RETURN) {
15571 if (--interp->returnLevel <= 0) {
15572 retcode = interp->returnCode;
15573 interp->returnCode = JIM_OK;
15574 interp->returnLevel = 0;
@@ -15711,20 +15680,20 @@
15680 prevScriptObj = interp->currentScriptObj;
15681 interp->currentScriptObj = scriptObjPtr;
15682
15683 retcode = Jim_EvalObj(interp, scriptObjPtr);
15684
15685
15686 if (retcode == JIM_RETURN) {
15687 if (--interp->returnLevel <= 0) {
15688 retcode = interp->returnCode;
15689 interp->returnCode = JIM_OK;
15690 interp->returnLevel = 0;
15691 }
15692 }
15693 if (retcode == JIM_ERR) {
15694
15695 interp->addStackTrace++;
15696 }
15697
15698 interp->currentScriptObj = prevScriptObj;
15699
@@ -15750,11 +15719,11 @@
15719 }
15720 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
15721 if (JimParseVar(pc) == JIM_OK) {
15722 return;
15723 }
15724
15725 pc->tstart = pc->p;
15726 flags |= JIM_SUBST_NOVAR;
15727 }
15728 while (pc->len) {
15729 if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -15781,32 +15750,32 @@
15750 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
15751 struct JimParserCtx parser;
15752 struct ScriptObj *script = Jim_Alloc(sizeof(*script));
15753 ParseTokenList tokenlist;
15754
15755
15756 ScriptTokenListInit(&tokenlist);
15757
15758 JimParserInit(&parser, scriptText, scriptTextLen, 1);
15759 while (1) {
15760 JimParseSubst(&parser, flags);
15761 if (parser.eof) {
15762
15763 break;
15764 }
15765 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
15766 parser.tline);
15767 }
15768
15769
15770 script->inUse = 1;
15771 script->substFlags = flags;
15772 script->fileNameObj = interp->emptyObj;
15773 Jim_IncrRefCount(script->fileNameObj);
15774 SubstObjAddTokens(interp, script, &tokenlist);
15775
15776
15777 ScriptTokenListFree(&tokenlist);
15778
15779 #ifdef DEBUG_SHOW_SUBST
15780 {
15781 int i;
@@ -15817,11 +15786,11 @@
15786 Jim_String(script->token[i].objPtr));
15787 }
15788 }
15789 #endif
15790
15791
15792 Jim_FreeIntRep(interp, objPtr);
15793 Jim_SetIntRepPtr(objPtr, script);
15794 objPtr->typePtr = &scriptObjType;
15795 return JIM_OK;
15796 }
@@ -15835,11 +15804,11 @@
15804
15805 int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
15806 {
15807 ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
15808
15809 Jim_IncrRefCount(substObjPtr);
15810 script->inUse++;
15811
15812 *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
15813
15814 script->inUse--;
@@ -15851,22 +15820,24 @@
15820 }
15821
15822 void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
15823 {
15824 Jim_Obj *objPtr;
15825 Jim_Obj *listObjPtr;
15826
15827 JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0"));
15828
15829 listObjPtr = Jim_NewListObj(interp, argv, argc);
15830
15831 if (*msg) {
15832 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
15833 }
15834 Jim_IncrRefCount(listObjPtr);
15835 objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
15836 Jim_DecrRefCount(interp, listObjPtr);
15837
 
15838 Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
 
15839 }
15840
15841 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15842 Jim_HashEntry *he, int type);
15843
@@ -15876,11 +15847,11 @@
15847 JimHashtableIteratorCallbackType *callback, int type)
15848 {
15849 Jim_HashEntry *he;
15850 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
15851
15852
15853 if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
15854 he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
15855 if (he) {
15856 callback(interp, listObjPtr, he, type);
15857 }
@@ -15907,11 +15878,11 @@
15878 {
15879 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15880 Jim_Obj *objPtr;
15881
15882 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15883
15884 return;
15885 }
15886
15887 objPtr = Jim_NewStringObj(interp, he->key, -1);
15888 Jim_IncrRefCount(objPtr);
@@ -15967,11 +15938,11 @@
15938
15939 targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
15940 if (targetCallFrame == NULL) {
15941 return JIM_ERR;
15942 }
15943
15944 if (targetCallFrame == interp->topFramePtr) {
15945 Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
15946 return JIM_ERR;
15947 }
15948 if (info_level_cmd) {
@@ -16154,11 +16125,11 @@
16125 if (!objPtr)
16126 return JIM_ERR;
16127 Jim_SetResult(interp, objPtr);
16128 return JIM_OK;
16129 }
16130
16131 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16132 return JIM_ERR;
16133 Jim_SetResult(interp, argv[2]);
16134 return JIM_OK;
16135 }
@@ -16197,11 +16168,11 @@
16168 if (argc != 3) {
16169 Jim_WrongNumArgs(interp, 1, argv, "condition body");
16170 return JIM_ERR;
16171 }
16172
16173
16174 while (1) {
16175 int boolean, retval;
16176
16177 if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
16178 return retval;
@@ -16237,11 +16208,11 @@
16208 if (argc != 5) {
16209 Jim_WrongNumArgs(interp, 1, argv, "start test next body");
16210 return JIM_ERR;
16211 }
16212
16213
16214 if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
16215 return retval;
16216 }
16217
16218 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
@@ -16253,19 +16224,19 @@
16224 ExprByteCode *expr;
16225 jim_wide stop, currentVal;
16226 Jim_Obj *objPtr;
16227 int cmpOffset;
16228
16229
16230 expr = JimGetExpression(interp, argv[2]);
16231 incrScript = JimGetScript(interp, argv[3]);
16232
16233
16234 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16235 goto evalstart;
16236 }
16237
16238 if (incrScript->token[1].type != JIM_TT_ESC ||
16239 expr->token[0].type != JIM_TT_VAR ||
16240 (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
16241 goto evalstart;
16242 }
@@ -16278,48 +16249,48 @@
16249 }
16250 else {
16251 goto evalstart;
16252 }
16253
16254
16255 if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
16256 goto evalstart;
16257 }
16258
16259
16260 if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
16261 goto evalstart;
16262 }
16263
16264
16265 if (expr->token[1].type == JIM_TT_EXPR_INT) {
16266 if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
16267 goto evalstart;
16268 }
16269 }
16270 else {
16271 stopVarNamePtr = expr->token[1].objPtr;
16272 Jim_IncrRefCount(stopVarNamePtr);
16273
16274 stop = 0;
16275 }
16276
16277
16278 varNamePtr = expr->token[0].objPtr;
16279 Jim_IncrRefCount(varNamePtr);
16280
16281 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
16282 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
16283 goto testcond;
16284 }
16285
16286
16287 while (retval == JIM_OK) {
 
 
16288
16289
16290
16291
16292 if (stopVarNamePtr) {
16293 objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
16294 if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
16295 goto testcond;
16296 }
@@ -16327,18 +16298,18 @@
16298
16299 if (currentVal >= stop + cmpOffset) {
16300 break;
16301 }
16302
16303
16304 retval = Jim_EvalObj(interp, argv[4]);
16305 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16306 retval = JIM_OK;
16307
16308 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
16309
16310
16311 if (objPtr == NULL) {
16312 retval = JIM_ERR;
16313 goto out;
16314 }
16315 if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -16358,25 +16329,25 @@
16329 }
16330 evalstart:
16331 #endif
16332
16333 while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
16334
16335 retval = Jim_EvalObj(interp, argv[4]);
16336
16337 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16338
16339 JIM_IF_OPTIM(evalnext:)
16340 retval = Jim_EvalObj(interp, argv[3]);
16341 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16342
16343 JIM_IF_OPTIM(testcond:)
16344 retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
16345 }
16346 }
16347 }
16348 JIM_IF_OPTIM(out:)
16349 if (stopVarNamePtr) {
16350 Jim_DecrRefCount(interp, stopVarNamePtr);
16351 }
16352 if (varNamePtr) {
16353 Jim_DecrRefCount(interp, varNamePtr);
@@ -16418,11 +16389,11 @@
16389 if (retval == JIM_OK || retval == JIM_CONTINUE) {
16390 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
16391
16392 retval = JIM_OK;
16393
16394
16395 i += incr;
16396
16397 if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
16398 if (argv[1]->typePtr != &variableObjType) {
16399 if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
@@ -16483,21 +16454,21 @@
16454
16455 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16456 {
16457 int result = JIM_OK;
16458 int i, numargs;
16459 Jim_ListIter twoiters[2];
16460 Jim_ListIter *iters;
16461 Jim_Obj *script;
16462 Jim_Obj *resultObj;
16463
16464 if (argc < 4 || argc % 2 != 0) {
16465 Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
16466 return JIM_ERR;
16467 }
16468 script = argv[argc - 1];
16469 numargs = (argc - 1 - 1);
16470
16471 if (numargs == 2) {
16472 iters = twoiters;
16473 }
16474 else {
@@ -16521,34 +16492,34 @@
16492 resultObj = interp->emptyObj;
16493 }
16494 Jim_IncrRefCount(resultObj);
16495
16496 while (1) {
16497
16498 for (i = 0; i < numargs; i += 2) {
16499 if (!JimListIterDone(interp, &iters[i + 1])) {
16500 break;
16501 }
16502 }
16503 if (i == numargs) {
16504
16505 break;
16506 }
16507
16508
16509 for (i = 0; i < numargs; i += 2) {
16510 Jim_Obj *varName;
16511
16512
16513 JimListIterInit(&iters[i], argv[i + 1]);
16514 while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
16515 Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
16516 if (!valObj) {
16517
16518 valObj = interp->emptyObj;
16519 }
16520
16521 Jim_IncrRefCount(valObj);
16522 result = Jim_SetVariable(interp, varName, valObj);
16523 Jim_DecrRefCount(interp, valObj);
16524 if (result != JIM_OK) {
16525 goto err;
@@ -16630,41 +16601,41 @@
16601 {
16602 int boolean, retval, current = 1, falsebody = 0;
16603
16604 if (argc >= 3) {
16605 while (1) {
16606
16607 if (current >= argc)
16608 goto err;
16609 if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
16610 != JIM_OK)
16611 return retval;
16612
16613 if (current >= argc)
16614 goto err;
16615 if (Jim_CompareStringImmediate(interp, argv[current], "then"))
16616 current++;
16617
16618 if (current >= argc)
16619 goto err;
16620 if (boolean)
16621 return Jim_EvalObj(interp, argv[current]);
16622
16623 if (++current >= argc) {
16624 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
16625 return JIM_OK;
16626 }
16627 falsebody = current++;
16628 if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
16629
16630 if (current != argc - 1)
16631 goto err;
16632 return Jim_EvalObj(interp, argv[current]);
16633 }
16634 else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
16635 continue;
16636
16637 else if (falsebody != argc - 1)
16638 goto err;
16639 return Jim_EvalObj(interp, argv[falsebody]);
16640 }
16641 return JIM_OK;
@@ -16772,21 +16743,21 @@
16743 if (Jim_StringMatchObj(interp, patObj, strObj, 0))
16744 script = caseList[i + 1];
16745 break;
16746 case SWITCH_RE:
16747 command = Jim_NewStringObj(interp, "regexp", -1);
16748
16749 case SWITCH_CMD:{
16750 int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
16751
16752 if (argc - opt == 1) {
16753 Jim_Obj **vector;
16754
16755 JimListGetElements(interp, argv[opt], &patCount, &vector);
16756 caseList = vector;
16757 }
16758
16759 if (rc < 0) {
16760 return -rc;
16761 }
16762 if (rc)
16763 script = caseList[i + 1];
@@ -16920,11 +16891,11 @@
16891 case OPT_COMMAND:
16892 if (i >= argc - 2) {
16893 goto wrongargs;
16894 }
16895 commandObj = argv[++i];
16896
16897 case OPT_EXACT:
16898 case OPT_GLOB:
16899 case OPT_REGEXP:
16900 opt_match = option;
16901 break;
@@ -16968,17 +16939,17 @@
16939 goto done;
16940 }
16941 break;
16942 }
16943
16944
16945 if (!eq && opt_bool && opt_not && !opt_all) {
16946 continue;
16947 }
16948
16949 if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
16950
16951 Jim_Obj *resultObj;
16952
16953 if (opt_bool) {
16954 resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
16955 }
@@ -17001,11 +16972,11 @@
16972
16973 if (opt_all) {
16974 Jim_SetResult(interp, listObjPtr);
16975 }
16976 else {
16977
16978 if (opt_bool) {
16979 Jim_SetResultBool(interp, opt_not);
16980 }
16981 else if (!opt_inline) {
16982 Jim_SetResultInt(interp, -1);
@@ -17030,11 +17001,11 @@
17001 Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
17002 return JIM_ERR;
17003 }
17004 listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17005 if (!listObjPtr) {
17006
17007 listObjPtr = Jim_NewListObj(interp, NULL, 0);
17008 new_obj = 1;
17009 }
17010 else if (Jim_IsShared(listObjPtr)) {
17011 listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
@@ -17103,31 +17074,31 @@
17074 first = JimRelToAbsIndex(len, first);
17075 last = JimRelToAbsIndex(len, last);
17076 JimRelToAbsRange(len, &first, &last, &rangeLen);
17077
17078
17079
17080 if (first < len) {
17081
17082 }
17083 else if (len == 0) {
17084
17085 first = 0;
17086 }
17087 else {
17088 Jim_SetResultString(interp, "list doesn't contain element ", -1);
17089 Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
17090 return JIM_ERR;
17091 }
17092
17093
17094 newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
17095
17096
17097 ListInsertElements(newListObj, -1, argc - 4, argv + 4);
17098
17099
17100 ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
17101
17102 Jim_SetResult(interp, newListObj);
17103 return JIM_OK;
17104 }
@@ -17138,11 +17109,11 @@
17109 if (argc < 3) {
17110 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
17111 return JIM_ERR;
17112 }
17113 else if (argc == 3) {
17114
17115 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
17116 return JIM_ERR;
17117 Jim_SetResult(interp, argv[2]);
17118 return JIM_OK;
17119 }
@@ -17253,11 +17224,11 @@
17224 }
17225 else {
17226 int new_obj = 0;
17227 stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
17228 if (!stringObjPtr) {
17229
17230 stringObjPtr = Jim_NewEmptyStringObj(interp);
17231 new_obj = 1;
17232 }
17233 else if (Jim_IsShared(stringObjPtr)) {
17234 new_obj = 1;
@@ -17302,11 +17273,11 @@
17273 else {
17274 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
17275 }
17276
17277 if (rc == JIM_ERR) {
17278
17279 interp->addStackTrace++;
17280 }
17281 return rc;
17282 }
17283
@@ -17316,14 +17287,14 @@
17287 if (argc >= 2) {
17288 int retcode;
17289 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17290 const char *str;
17291
17292
17293 savedCallFrame = interp->framePtr;
17294
17295
17296 str = Jim_String(argv[1]);
17297 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17298 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17299 argc--;
17300 argv++;
@@ -17336,11 +17307,11 @@
17307 }
17308 if (argc < 2) {
17309 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
17310 return JIM_ERR;
17311 }
17312
17313 interp->framePtr = targetCallFrame;
17314 if (argc == 2) {
17315 retcode = Jim_EvalObj(interp, argv[1]);
17316 }
17317 else {
@@ -17438,15 +17409,15 @@
17409 if (i != argc - 1 && i != argc) {
17410 Jim_WrongNumArgs(interp, 1, argv,
17411 "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
17412 }
17413
17414
17415 if (stackTraceObj && returnCode == JIM_ERR) {
17416 JimSetStackTrace(interp, stackTraceObj);
17417 }
17418
17419 if (errorCodeObj && returnCode == JIM_ERR) {
17420 Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
17421 }
17422 interp->returnCode = returnCode;
17423 interp->returnLevel = level;
@@ -17463,31 +17434,31 @@
17434 if (interp->framePtr->level == 0) {
17435 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17436 return JIM_ERR;
17437 }
17438 else if (argc >= 2) {
17439
17440 Jim_CallFrame *cf = interp->framePtr->parent;
17441
17442 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17443 if (cmdPtr == NULL) {
17444 return JIM_ERR;
17445 }
17446
17447 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17448
17449
17450 JimIncrCmdRefCount(cmdPtr);
17451 cf->tailcallCmd = cmdPtr;
17452
17453
17454 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17455
17456 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17457 Jim_IncrRefCount(cf->tailcallObj);
17458
17459
17460 return JIM_EVAL;
17461 }
17462 return JIM_OK;
17463 }
17464
@@ -17494,11 +17465,11 @@
17465 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17466 {
17467 Jim_Obj *cmdList;
17468 Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
17469
17470
17471 cmdList = Jim_DuplicateObj(interp, prefixListObj);
17472 Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1);
17473
17474 return JimEvalObjList(interp, cmdList);
17475 }
@@ -17552,22 +17523,22 @@
17523 else {
17524 cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
17525 }
17526
17527 if (cmd) {
17528
17529 Jim_Obj *qualifiedCmdNameObj;
17530 const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
17531
17532 JimCreateCommand(interp, cmdname, cmd);
17533
17534
17535 JimUpdateProcNamespace(interp, cmd, cmdname);
17536
17537 JimFreeQualifiedName(interp, qualifiedCmdNameObj);
17538
17539
17540 Jim_SetResult(interp, argv[1]);
17541 return JIM_OK;
17542 }
17543 return JIM_ERR;
17544 }
@@ -17580,17 +17551,17 @@
17551 if (argc < 2) {
17552 Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
17553 return JIM_ERR;
17554 }
17555
17556
17557 interp->local++;
17558 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17559 interp->local--;
17560
17561
17562
17563 if (retcode == 0) {
17564 Jim_Obj *cmdNameObj = Jim_GetResult(interp);
17565
17566 if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
17567 return JIM_ERR;
@@ -17619,18 +17590,18 @@
17590 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17591 if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
17592 Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
17593 return JIM_ERR;
17594 }
17595
17596 cmdPtr->u.proc.upcall++;
17597 JimIncrCmdRefCount(cmdPtr);
17598
17599
17600 retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
17601
17602
17603 cmdPtr->u.proc.upcall--;
17604 JimDecrCmdRefCount(interp, cmdPtr);
17605
17606 return retcode;
17607 }
@@ -17657,11 +17628,11 @@
17628 return JIM_ERR;
17629 }
17630
17631 if (len == 3) {
17632 #ifdef jim_ext_namespace
17633
17634 nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
17635 #else
17636 Jim_SetResultString(interp, "namespaces not enabled", -1);
17637 return JIM_ERR;
17638 #endif
@@ -17670,11 +17641,11 @@
17641 bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
17642
17643 cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
17644
17645 if (cmd) {
17646
17647 nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
17648 nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
17649 Jim_IncrRefCount(nargv[0]);
17650 memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
17651 ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
@@ -17700,11 +17671,11 @@
17671 static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17672 {
17673 int i;
17674 Jim_CallFrame *targetCallFrame;
17675
17676
17677 if (argc > 3 && (argc % 2 == 0)) {
17678 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17679 argc--;
17680 argv++;
17681 }
@@ -17713,17 +17684,17 @@
17684 }
17685 if (targetCallFrame == NULL) {
17686 return JIM_ERR;
17687 }
17688
17689
17690 if (argc < 3) {
17691 Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
17692 return JIM_ERR;
17693 }
17694
17695
17696 for (i = 1; i < argc; i += 2) {
17697 if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
17698 return JIM_ERR;
17699 }
17700 return JIM_OK;
@@ -17736,15 +17707,15 @@
17707
17708 if (argc < 2) {
17709 Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
17710 return JIM_ERR;
17711 }
17712
17713 if (interp->framePtr->level == 0)
17714 return JIM_OK;
17715 for (i = 1; i < argc; i++) {
17716
17717 const char *name = Jim_String(argv[i]);
17718 if (name[0] != ':' || name[1] != ':') {
17719 if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
17720 return JIM_ERR;
17721 }
@@ -17767,21 +17738,21 @@
17738 }
17739
17740 str = Jim_String(objPtr);
17741 strLen = Jim_Utf8Length(interp, objPtr);
17742
17743
17744 resultObjPtr = Jim_NewStringObj(interp, "", 0);
17745 while (strLen) {
17746 for (i = 0; i < numMaps; i += 2) {
17747 Jim_Obj *eachObjPtr;
17748 const char *k;
17749 int kl;
17750
17751 eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17752 k = Jim_String(eachObjPtr);
17753 kl = Jim_Utf8Length(interp, eachObjPtr);
17754
17755 if (strLen >= kl && kl) {
17756 int rc;
17757 rc = JimStringCompareLen(str, k, kl, nocase);
17758 if (rc == 0) {
@@ -17794,11 +17765,11 @@
17765 strLen -= kl;
17766 break;
17767 }
17768 }
17769 }
17770 if (i == numMaps) {
17771 int c;
17772 if (noMatchStart == NULL)
17773 noMatchStart = str;
17774 str += utf8_tounicode(str, &c);
17775 strLen--;
@@ -17838,11 +17809,11 @@
17809 Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
17810 return JIM_ERR;
17811 }
17812 if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
17813 JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
17814 return Jim_CheckShowCommands(interp, argv[1], options);
17815
17816 switch (option) {
17817 case OPT_LENGTH:
17818 case OPT_BYTELENGTH:
17819 if (argc != 3) {
@@ -17859,11 +17830,11 @@
17830 return JIM_OK;
17831
17832 case OPT_CAT:{
17833 Jim_Obj *objPtr;
17834 if (argc == 3) {
17835
17836 objPtr = argv[2];
17837 }
17838 else {
17839 int i;
17840
@@ -17878,11 +17849,11 @@
17849 }
17850
17851 case OPT_COMPARE:
17852 case OPT_EQUAL:
17853 {
17854
17855 long opt_length = -1;
17856 int n = argc - 4;
17857 int i = 2;
17858 while (n > 0) {
17859 int subopt;
@@ -17891,16 +17862,16 @@
17862 badcompareargs:
17863 Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
17864 return JIM_ERR;
17865 }
17866 if (subopt == 0) {
17867
17868 opt_case = 0;
17869 n--;
17870 }
17871 else {
17872
17873 if (n < 2) {
17874 goto badcompareargs;
17875 }
17876 if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
17877 return JIM_ERR;
@@ -17911,11 +17882,11 @@
17882 if (n) {
17883 goto badcompareargs;
17884 }
17885 argv += argc - 2;
17886 if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
17887
17888 Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
17889 }
17890 else {
17891 if (opt_length >= 0) {
17892 n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
@@ -18025,11 +17996,10 @@
17996 }
17997
17998 case OPT_REVERSE:{
17999 char *buf, *p;
18000 const char *str;
 
18001 int i;
18002
18003 if (argc != 3) {
18004 Jim_WrongNumArgs(interp, 2, argv, "string");
18005 return JIM_ERR;
@@ -18069,11 +18039,11 @@
18039 }
18040 if (idx < 0 || idx >= len || str == NULL) {
18041 Jim_SetResultString(interp, "", 0);
18042 }
18043 else if (len == Jim_Length(argv[2])) {
18044
18045 Jim_SetResultString(interp, str + idx, 1);
18046 }
18047 else {
18048 int c;
18049 int i = utf8_index(str, idx);
@@ -18223,11 +18193,11 @@
18193 {
18194 int exitCode = 0;
18195 int i;
18196 int sig = 0;
18197
18198
18199 jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
18200 static const int max_ignore_code = sizeof(ignore_mask) * 8;
18201
18202 Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
18203
@@ -18234,11 +18204,11 @@
18204 for (i = 1; i < argc - 1; i++) {
18205 const char *arg = Jim_String(argv[i]);
18206 jim_wide option;
18207 int ignore;
18208
18209
18210 if (strcmp(arg, "--") == 0) {
18211 i++;
18212 break;
18213 }
18214 if (*arg != '-') {
@@ -18285,28 +18255,28 @@
18255 sig++;
18256 }
18257
18258 interp->signal_level += sig;
18259 if (Jim_CheckSignal(interp)) {
18260
18261 exitCode = JIM_SIGNAL;
18262 }
18263 else {
18264 exitCode = Jim_EvalObj(interp, argv[0]);
18265
18266 interp->errorFlag = 0;
18267 }
18268 interp->signal_level -= sig;
18269
18270
18271 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18272
18273 return exitCode;
18274 }
18275
18276 if (sig && exitCode == JIM_SIGNAL) {
18277
18278 if (interp->signal_set_result) {
18279 interp->signal_set_result(interp, interp->sigmask);
18280 }
18281 else {
18282 Jim_SetResultInt(interp, interp->sigmask);
@@ -18345,125 +18315,10 @@
18315 }
18316 Jim_SetResultInt(interp, exitCode);
18317 return JIM_OK;
18318 }
18319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18320
18321
18322 static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18323 {
18324 if (argc != 3) {
@@ -18476,56 +18331,43 @@
18331 }
18332
18333 return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
18334 }
18335
18336 #define JIM_DICTMATCH_KEYS 0x0001
18337 #define JIM_DICTMATCH_VALUES 0x002
18338
18339 int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types)
18340 {
18341 Jim_HashEntry *he;
18342 Jim_Obj *listObjPtr;
18343 Jim_HashTableIterator htiter;
18344
18345 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18346 return JIM_ERR;
18347 }
18348
18349 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18350
18351 JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter);
18352 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18353 if (patternObj) {
18354 Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
18355 if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
18356
18357 continue;
18358 }
18359 }
18360 if (return_types & JIM_DICTMATCH_KEYS) {
18361 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18362 }
18363 if (return_types & JIM_DICTMATCH_VALUES) {
18364 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18365 }
18366 }
18367
18368 Jim_SetResult(interp, listObjPtr);
 
 
 
 
 
 
 
 
 
 
 
 
 
18369 return JIM_OK;
18370 }
18371
18372 int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
18373 {
@@ -18532,38 +18374,85 @@
18374 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18375 return -1;
18376 }
18377 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18378 }
18379
18380 Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
18381 {
18382 Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0);
18383 int i;
18384
18385 JimPanic((objc == 0, "Jim_DictMerge called with objc=0"));
18386
18387
18388
18389 for (i = 0; i < objc; i++) {
18390 Jim_HashTable *ht;
18391 Jim_HashTableIterator htiter;
18392 Jim_HashEntry *he;
18393
18394 if (SetDictFromAny(interp, objv[i]) != JIM_OK) {
18395 Jim_FreeNewObj(interp, objPtr);
18396 return NULL;
18397 }
18398 ht = objv[i]->internalRep.ptr;
18399 JimInitHashTableIterator(ht, &htiter);
18400 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18401 Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he));
18402 }
18403 }
18404 return objPtr;
18405 }
18406
18407 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18408 {
18409 Jim_HashTable *ht;
18410 unsigned int i;
18411 char buffer[100];
18412 int sum = 0;
18413 int nonzero_count = 0;
18414 Jim_Obj *output;
18415 int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
18416
18417 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18418 return JIM_ERR;
18419 }
18420
18421 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18422
18423
18424 snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
18425 output = Jim_NewStringObj(interp, buffer, -1);
18426
18427 for (i = 0; i < ht->size; i++) {
18428 Jim_HashEntry *he = ht->table[i];
18429 int entries = 0;
18430 while (he) {
18431 entries++;
18432 he = he->next;
18433 }
18434 if (entries > 9) {
18435 bucket_counts[10]++;
18436 }
18437 else {
18438 bucket_counts[entries]++;
18439 }
18440 if (entries) {
18441 sum += entries;
18442 nonzero_count++;
18443 }
18444 }
18445 for (i = 0; i < 10; i++) {
18446 snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
18447 Jim_AppendString(interp, output, buffer, -1);
18448 }
18449 snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
18450 Jim_AppendString(interp, output, buffer, -1);
18451 snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
18452 Jim_AppendString(interp, output, buffer, -1);
18453 Jim_SetResult(interp, output);
18454 return JIM_OK;
18455 }
18456
18457 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18458 {
@@ -18573,14 +18462,67 @@
18462 Jim_AppendString(interp, prefixObj, subcmd, -1);
18463
18464 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18465 }
18466
18467 static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj)
18468 {
18469 int i;
18470 Jim_Obj *objPtr;
18471 Jim_Obj *dictObj;
18472 Jim_Obj **dictValues;
18473 int len;
18474 int ret = JIM_OK;
18475
18476
18477 dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG);
18478 if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) {
18479 return JIM_ERR;
18480 }
18481
18482 if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) {
18483 return JIM_ERR;
18484 }
18485 for (i = 0; i < len; i += 2) {
18486 if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) {
18487 Jim_Free(dictValues);
18488 return JIM_ERR;
18489 }
18490 }
18491
18492
18493 if (Jim_Length(scriptObj)) {
18494 ret = Jim_EvalObj(interp, scriptObj);
18495
18496
18497 if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) {
18498
18499 Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1));
18500 for (i = 0; i < keyc; i++) {
18501 newkeyv[i] = keyv[i];
18502 }
18503
18504 for (i = 0; i < len; i += 2) {
18505
18506 objPtr = Jim_GetVariable(interp, dictValues[i], 0);
18507 newkeyv[keyc] = dictValues[i];
18508 Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0);
18509 }
18510 Jim_Free(newkeyv);
18511 }
18512 }
18513
18514 Jim_Free(dictValues);
18515
18516 return ret;
18517 }
18518
18519
18520 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18521 {
18522 Jim_Obj *objPtr;
18523 int types = JIM_DICTMATCH_KEYS;
18524 int option;
18525 static const char * const options[] = {
18526 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18527 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18528 "replace", "update", NULL
@@ -18596,11 +18538,11 @@
18538 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18539 return JIM_ERR;
18540 }
18541
18542 if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
18543 return Jim_CheckShowCommands(interp, argv[1], options);
18544 }
18545
18546 switch (option) {
18547 case OPT_GET:
18548 if (argc < 3) {
@@ -18643,16 +18585,19 @@
18585 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18586 return JIM_ERR;
18587 }
18588 return JIM_OK;
18589
18590 case OPT_VALUES:
18591 types = JIM_DICTMATCH_VALUES;
18592
18593 case OPT_KEYS:
18594 if (argc != 3 && argc != 4) {
18595 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18596 return JIM_ERR;
18597 }
18598 return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types);
18599
18600 case OPT_SIZE:
18601 if (argc != 3) {
18602 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18603 return JIM_ERR;
@@ -18665,19 +18610,20 @@
18610
18611 case OPT_MERGE:
18612 if (argc == 2) {
18613 return JIM_OK;
18614 }
18615 objPtr = Jim_DictMerge(interp, argc - 2, argv + 2);
18616 if (objPtr == NULL) {
18617 return JIM_ERR;
18618 }
18619 Jim_SetResult(interp, objPtr);
18620 return JIM_OK;
18621
18622 case OPT_UPDATE:
18623 if (argc < 6 || argc % 2) {
18624
18625 argc = 2;
18626 }
18627 break;
18628
18629 case OPT_CREATE:
@@ -18693,12 +18639,19 @@
18639 if (argc != 3) {
18640 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18641 return JIM_ERR;
18642 }
18643 return Jim_DictInfo(interp, argv[2]);
18644
18645 case OPT_WITH:
18646 if (argc < 4) {
18647 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18648 return JIM_ERR;
18649 }
18650 return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]);
18651 }
18652
18653 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18654 }
18655
18656
18657 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -18764,11 +18717,11 @@
18717
18718 #ifdef jim_ext_namespace
18719 int nons = 0;
18720
18721 if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
18722
18723 argc--;
18724 argv++;
18725 nons = 1;
18726 }
18727 #endif
@@ -18775,16 +18728,15 @@
18728
18729 if (argc < 2) {
18730 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
18731 return JIM_ERR;
18732 }
18733 if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
18734 return Jim_CheckShowCommands(interp, argv[1], commands);
 
18735 }
18736
18737
18738 switch (cmd) {
18739 case INFO_EXISTS:
18740 if (argc != 3) {
18741 Jim_WrongNumArgs(interp, 2, argv, "varName");
18742 return JIM_ERR;
@@ -18809,21 +18761,21 @@
18761 Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
18762 return JIM_OK;
18763 }
18764
18765 case INFO_CHANNELS:
18766 mode++;
18767 #ifndef jim_ext_aio
18768 Jim_SetResultString(interp, "aio not enabled", -1);
18769 return JIM_ERR;
18770 #endif
18771
18772 case INFO_PROCS:
18773 mode++;
18774
18775 case INFO_COMMANDS:
18776
18777 if (argc != 2 && argc != 3) {
18778 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18779 return JIM_ERR;
18780 }
18781 #ifdef jim_ext_namespace
@@ -18835,17 +18787,17 @@
18787 #endif
18788 Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
18789 break;
18790
18791 case INFO_VARS:
18792 mode++;
18793
18794 case INFO_LOCALS:
18795 mode++;
18796
18797 case INFO_GLOBALS:
18798
18799 if (argc != 2 && argc != 3) {
18800 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
18801 return JIM_ERR;
18802 }
18803 #ifdef jim_ext_namespace
@@ -18951,13 +18903,12 @@
18903 case INFO_ARGS:
18904 Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
18905 break;
18906 case INFO_STATICS:
18907 if (cmdPtr->u.proc.staticVars) {
 
18908 Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
18909 NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES));
18910 }
18911 break;
18912 }
18913 break;
18914 }
@@ -18985,15 +18936,15 @@
18936 }
18937 }
18938 break;
18939
18940 case INFO_HOSTNAME:
18941
18942 return Jim_Eval(interp, "os.gethostname");
18943
18944 case INFO_NAMEOFEXECUTABLE:
18945
18946 return Jim_Eval(interp, "{info nameofexecutable}");
18947
18948 case INFO_RETURNCODES:
18949 if (argc == 2) {
18950 int i;
@@ -19070,11 +19021,11 @@
19021
19022 if (option == OPT_VAR) {
19023 result = Jim_GetVariable(interp, objPtr, 0) != NULL;
19024 }
19025 else {
19026
19027 Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
19028
19029 if (cmd) {
19030 switch (option) {
19031 case OPT_COMMAND:
@@ -19113,11 +19064,11 @@
19064 if (len == 0) {
19065 return JIM_OK;
19066 }
19067 strLen = Jim_Utf8Length(interp, argv[1]);
19068
19069
19070 if (argc == 2) {
19071 splitChars = " \n\t\r";
19072 splitLen = 4;
19073 }
19074 else {
@@ -19126,11 +19077,11 @@
19077 }
19078
19079 noMatchStart = str;
19080 resObjPtr = Jim_NewListObj(interp, NULL, 0);
19081
19082
19083 if (splitLen) {
19084 Jim_Obj *objPtr;
19085 while (strLen--) {
19086 const char *sc = splitChars;
19087 int scLen = splitLen;
@@ -19155,11 +19106,11 @@
19106 #define NUM_COMMON (128 - 9)
19107 while (strLen--) {
19108 int n = utf8_tounicode(str, &c);
19109 #ifdef JIM_OPTIMIZATION
19110 if (c >= 9 && c < 128) {
19111
19112 c -= 9;
19113 if (!commonObj) {
19114 commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
19115 memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
19116 }
@@ -19189,11 +19140,11 @@
19140
19141 if (argc != 2 && argc != 3) {
19142 Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
19143 return JIM_ERR;
19144 }
19145
19146 if (argc == 2) {
19147 joinStr = " ";
19148 joinStrLen = 1;
19149 }
19150 else {
@@ -19468,13 +19419,13 @@
19419 return -1;
19420 else if (step < 0 && end > start)
19421 return -1;
19422 len = end - start;
19423 if (len < 0)
19424 len = -len;
19425 if (step < 0)
19426 step = -step;
19427 len = 1 + ((len - 1) / step);
19428 if (len > INT_MAX)
19429 len = INT_MAX;
19430 return (int)((len < 0) ? -1 : len);
19431 }
@@ -19644,40 +19595,68 @@
19595 argv[1] = interp->result;
19596
19597 Jim_EvalObjVector(interp, 2, argv);
19598 }
19599
19600 static char **JimSortStringTable(const char *const *tablePtr)
 
19601 {
19602 int count;
19603 char **tablePtrSorted;
19604
19605
19606 for (count = 0; tablePtr[count]; count++) {
19607 }
19608
19609
19610 tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1));
19611 memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
19612 qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
19613 tablePtrSorted[count] = NULL;
19614
19615 return tablePtrSorted;
19616 }
19617
19618 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
19619 const char *prefix, const char *const *tablePtr, const char *name)
19620 {
19621 char **tablePtrSorted;
19622 int i;
19623
19624 if (name == NULL) {
19625 name = "option";
19626 }
19627
19628 Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
19629 tablePtrSorted = JimSortStringTable(tablePtr);
19630 for (i = 0; tablePtrSorted[i]; i++) {
19631 if (tablePtrSorted[i + 1] == NULL && i > 0) {
 
 
19632 Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
19633 }
19634 Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
19635 if (tablePtrSorted[i + 1]) {
19636 Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
19637 }
19638 }
19639 Jim_Free(tablePtrSorted);
19640 }
19641
19642
19643 int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr)
19644 {
19645 if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) {
19646 int i;
19647 char **tablePtrSorted = JimSortStringTable(tablePtr);
19648 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
19649 for (i = 0; tablePtrSorted[i]; i++) {
19650 Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1));
19651 }
19652 Jim_Free(tablePtrSorted);
19653 return JIM_OK;
19654 }
19655 return JIM_ERR;
19656 }
19657
19658 int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
19659 const char *const *tablePtr, int *indexPtr, const char *name, int flags)
19660 {
19661 const char *bad = "bad ";
19662 const char *const *entryPtr = NULL;
@@ -19688,11 +19667,11 @@
19667
19668 *indexPtr = -1;
19669
19670 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
19671 if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
19672
19673 *indexPtr = i;
19674 return JIM_OK;
19675 }
19676 if (flags & JIM_ENUM_ABBREV) {
19677 if (strncmp(arg, *entryPtr, arglen) == 0) {
@@ -19706,11 +19685,11 @@
19685 match = i;
19686 }
19687 }
19688 }
19689
19690
19691 if (match >= 0) {
19692 *indexPtr = match;
19693 return JIM_OK;
19694 }
19695
@@ -19743,15 +19722,17 @@
19722 return objPtr->typePtr == &listObjType;
19723 }
19724
19725 void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
19726 {
19727
19728 int len = strlen(format);
19729 int extra = 0;
19730 int n = 0;
19731 const char *params[5];
19732 int nobjparam = 0;
19733 Jim_Obj *objparam[5];
19734 char *buf;
19735 va_list args;
19736 int i;
19737
19738 va_start(args, format);
@@ -19766,10 +19747,12 @@
19747 }
19748 else if (strncmp(format + i, "%#s", 3) == 0) {
19749 Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
19750
19751 params[n] = Jim_GetString(objPtr, &l);
19752 objparam[nobjparam++] = objPtr;
19753 Jim_IncrRefCount(objPtr);
19754 }
19755 else {
19756 if (format[i] == '%') {
19757 i++;
19758 }
@@ -19784,10 +19767,14 @@
19767 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19768
19769 va_end(args);
19770
19771 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19772
19773 for (i = 0; i < nobjparam; i++) {
19774 Jim_DecrRefCount(interp, objparam[i]);
19775 }
19776 }
19777
19778
19779 #ifndef jim_ext_package
19780 int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19808,11 +19795,11 @@
19795 #include <string.h>
19796
19797
19798 static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19799 {
19800
19801 return JIM_OK;
19802 }
19803
19804 static const jim_subcmd_type dummy_subcmd = {
19805 "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
@@ -19887,43 +19874,43 @@
19874 return 0;
19875 }
19876
19877 cmd = argv[1];
19878
19879
19880 if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
19881 if (argc == 2) {
19882
19883 show_cmd_usage(interp, command_table, argc, argv);
19884 return &dummy_subcmd;
19885 }
19886 help = 1;
19887
19888
19889 cmd = argv[2];
19890 }
19891
19892
19893 if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
19894
19895 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
19896 add_commands(interp, command_table, " ");
19897 return &dummy_subcmd;
19898 }
19899
19900 cmdstr = Jim_GetString(cmd, &cmdlen);
19901
19902 for (ct = command_table; ct->cmd; ct++) {
19903 if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
19904
19905 break;
19906 }
19907 if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
19908 if (partial) {
19909
19910 if (help) {
19911
19912 show_cmd_usage(interp, command_table, argc, argv);
19913 return &dummy_subcmd;
19914 }
19915 bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
19916 return 0;
@@ -19931,44 +19918,44 @@
19918 partial = ct;
19919 }
19920 continue;
19921 }
19922
19923
19924 if (partial && !ct->cmd) {
19925 ct = partial;
19926 }
19927
19928 if (!ct->cmd) {
19929
19930 if (help) {
19931
19932 show_cmd_usage(interp, command_table, argc, argv);
19933 return &dummy_subcmd;
19934 }
19935 bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
19936 return 0;
19937 }
19938
19939 if (help) {
19940 Jim_SetResultString(interp, "Usage: ", -1);
19941
19942 add_cmd_usage(interp, ct, argv[0]);
19943 return &dummy_subcmd;
19944 }
19945
19946
19947 if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
19948 Jim_SetResultString(interp, "wrong # args: should be \"", -1);
19949
19950 add_cmd_usage(interp, ct, argv[0]);
19951 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
19952
19953 return 0;
19954 }
19955
19956
19957 return ct;
19958 }
19959
19960 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
19961 {
@@ -20019,11 +20006,11 @@
20006 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
20007 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20008 *p = 0x80 | (uc & 0x3f);
20009 return 3;
20010 }
20011
20012 else {
20013 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
20014 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
20015 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
20016 *p = 0x80 | (uc & 0x3f);
@@ -20210,11 +20197,11 @@
20197 if (ch == 'h') {
20198 useShort = 1;
20199 format += step;
20200 step = utf8_tounicode(format, &ch);
20201 } else if (ch == 'l') {
20202
20203 format += step;
20204 step = utf8_tounicode(format, &ch);
20205 if (ch == 'l') {
20206 format += step;
20207 step = utf8_tounicode(format, &ch);
@@ -20237,11 +20224,11 @@
20224 goto errorMsg;
20225 case 's': {
20226 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
20227 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
20228 if (gotPrecision && (precision < formatted_chars)) {
20229
20230 formatted_chars = precision;
20231 formatted_bytes = utf8_index(formatted_buf, precision);
20232 }
20233 break;
20234 }
@@ -20249,11 +20236,11 @@
20236 jim_wide code;
20237
20238 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20239 goto error;
20240 }
20241
20242 formatted_bytes = utf8_getchars(spec, code);
20243 formatted_buf = spec;
20244 formatted_chars = 1;
20245 break;
20246 }
@@ -20267,11 +20254,11 @@
20254 goto error;
20255 }
20256 length = sizeof(w) * 8;
20257
20258
20259
20260 if (num_buffer_size < length + 1) {
20261 num_buffer_size = length + 1;
20262 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20263 }
20264
@@ -20295,29 +20282,29 @@
20282 case 'E':
20283 case 'f':
20284 case 'g':
20285 case 'G':
20286 doubleType = 1;
20287
20288 case 'd':
20289 case 'u':
20290 case 'o':
20291 case 'x':
20292 case 'X': {
20293 jim_wide w;
20294 double d;
20295 int length;
20296
20297
20298 if (width) {
20299 p += sprintf(p, "%ld", width);
20300 }
20301 if (gotPrecision) {
20302 p += sprintf(p, ".%ld", precision);
20303 }
20304
20305
20306 if (doubleType) {
20307 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20308 goto error;
20309 }
20310 length = MAX_FLOAT_WIDTH;
@@ -20344,19 +20331,19 @@
20331 }
20332
20333 *p++ = (char) ch;
20334 *p = '\0';
20335
20336
20337 if (width > length) {
20338 length = width;
20339 }
20340 if (gotPrecision) {
20341 length += precision;
20342 }
20343
20344
20345 if (num_buffer_size < length + 1) {
20346 num_buffer_size = length + 1;
20347 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20348 }
20349
@@ -20370,11 +20357,11 @@
20357 formatted_buf = num_buffer;
20358 break;
20359 }
20360
20361 default: {
20362
20363 spec[0] = ch;
20364 spec[1] = '\0';
20365 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20366 goto error;
20367 }
@@ -20422,37 +20409,37 @@
20409
20410 #define REG_MAX_PAREN 100
20411
20412
20413
20414 #define END 0
20415 #define BOL 1
20416 #define EOL 2
20417 #define ANY 3
20418 #define ANYOF 4
20419 #define ANYBUT 5
20420 #define BRANCH 6
20421 #define BACK 7
20422 #define EXACTLY 8
20423 #define NOTHING 9
20424 #define REP 10
20425 #define REPMIN 11
20426 #define REPX 12
20427 #define REPXMIN 13
20428 #define BOLX 14
20429 #define EOLX 15
20430 #define WORDA 16
20431 #define WORDZ 17
20432
20433 #define OPENNC 1000
20434 #define OPEN 1001
20435
20436
20437
20438
20439 #define CLOSENC 2000
20440 #define CLOSE 2001
20441 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
20442
20443 #define REG_MAGIC 0xFADED00D
20444
20445
@@ -20465,18 +20452,18 @@
20452
20453 #define FAIL(R,M) { (R)->err = (M); return (M); }
20454 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20455 #define META "^$.[()|?{+*"
20456
20457 #define HASWIDTH 1
20458 #define SIMPLE 2
20459 #define SPSTART 4
20460 #define WORST 0
20461
20462 #define MAX_REP_COUNT 1000000
20463
20464 static int reg(regex_t *preg, int paren, int *flagp );
20465 static int regpiece(regex_t *preg, int *flagp );
20466 static int regbranch(regex_t *preg, int *flagp );
20467 static int regatom(regex_t *preg, int *flagp );
20468 static int regnode(regex_t *preg, int op );
20469 static int regnext(regex_t *preg, int p );
@@ -20520,15 +20507,15 @@
20507 memset(preg, 0, sizeof(*preg));
20508
20509 if (exp == NULL)
20510 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20511
20512
20513 preg->cflags = cflags;
20514 preg->regparse = exp;
20515
20516
20517 preg->proglen = (strlen(exp) + 1) * 5;
20518 preg->program = malloc(preg->proglen * sizeof(int));
20519 if (preg->program == NULL)
20520 FAIL(preg, REG_ERR_NOMEM);
20521
@@ -20535,24 +20522,24 @@
20522 regc(preg, REG_MAGIC);
20523 if (reg(preg, 0, &flags) == 0) {
20524 return preg->err;
20525 }
20526
20527
20528 if (preg->re_nsub >= REG_MAX_PAREN)
20529 FAIL(preg,REG_ERR_TOO_BIG);
20530
20531
20532 preg->regstart = 0;
20533 preg->reganch = 0;
20534 preg->regmust = 0;
20535 preg->regmlen = 0;
20536 scan = 1;
20537 if (OP(preg, regnext(preg, scan)) == END) {
20538 scan = OPERAND(scan);
20539
20540
20541 if (OP(preg, scan) == EXACTLY) {
20542 preg->regstart = preg->program[OPERAND(scan)];
20543 }
20544 else if (OP(preg, scan) == BOL)
20545 preg->reganch++;
@@ -20579,24 +20566,24 @@
20566 #endif
20567
20568 return 0;
20569 }
20570
20571 static int reg(regex_t *preg, int paren, int *flagp )
20572 {
20573 int ret;
20574 int br;
20575 int ender;
20576 int parno = 0;
20577 int flags;
20578
20579 *flagp = HASWIDTH;
20580
20581
20582 if (paren) {
20583 if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
20584
20585 preg->regparse += 2;
20586 parno = -1;
20587 }
20588 else {
20589 parno = ++preg->re_nsub;
@@ -20603,16 +20590,16 @@
20590 }
20591 ret = regnode(preg, OPEN+parno);
20592 } else
20593 ret = 0;
20594
20595
20596 br = regbranch(preg, &flags);
20597 if (br == 0)
20598 return 0;
20599 if (ret != 0)
20600 regtail(preg, ret, br);
20601 else
20602 ret = br;
20603 if (!(flags&HASWIDTH))
20604 *flagp &= ~HASWIDTH;
20605 *flagp |= flags&SPSTART;
@@ -20619,25 +20606,25 @@
20606 while (*preg->regparse == '|') {
20607 preg->regparse++;
20608 br = regbranch(preg, &flags);
20609 if (br == 0)
20610 return 0;
20611 regtail(preg, ret, br);
20612 if (!(flags&HASWIDTH))
20613 *flagp &= ~HASWIDTH;
20614 *flagp |= flags&SPSTART;
20615 }
20616
20617
20618 ender = regnode(preg, (paren) ? CLOSE+parno : END);
20619 regtail(preg, ret, ender);
20620
20621
20622 for (br = ret; br != 0; br = regnext(preg, br))
20623 regoptail(preg, br, ender);
20624
20625
20626 if (paren && *preg->regparse++ != ')') {
20627 preg->err = REG_ERR_UNMATCHED_PAREN;
20628 return 0;
20629 } else if (!paren && *preg->regparse != '\0') {
20630 if (*preg->regparse == ')') {
@@ -20657,11 +20644,11 @@
20644 int ret;
20645 int chain;
20646 int latest;
20647 int flags;
20648
20649 *flagp = WORST;
20650
20651 ret = regnode(preg, BRANCH);
20652 chain = 0;
20653 while (*preg->regparse != '\0' && *preg->regparse != ')' &&
20654 *preg->regparse != '|') {
@@ -20675,11 +20662,11 @@
20662 else {
20663 regtail(preg, chain, latest);
20664 }
20665 chain = latest;
20666 }
20667 if (chain == 0)
20668 (void) regnode(preg, NOTHING);
20669
20670 return(ret);
20671 }
20672
@@ -20705,11 +20692,11 @@
20692 if (!(flags&HASWIDTH) && op != '?') {
20693 preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
20694 return 0;
20695 }
20696
20697
20698 if (op == '{') {
20699 char *end;
20700
20701 min = strtoul(preg->regparse + 1, &end, 10);
20702 if (end == preg->regparse + 1) {
@@ -20777,11 +20764,11 @@
20764 static void reg_addrange(regex_t *preg, int lower, int upper)
20765 {
20766 if (lower > upper) {
20767 reg_addrange(preg, upper, lower);
20768 }
20769
20770 regc(preg, upper - lower + 1);
20771 regc(preg, lower);
20772 }
20773
20774 static void reg_addrange_str(regex_t *preg, const char *str)
@@ -20845,17 +20832,17 @@
20832 case 'r': *ch = '\r'; break;
20833 case 't': *ch = '\t'; break;
20834 case 'v': *ch = '\v'; break;
20835 case 'u':
20836 if (*s == '{') {
20837
20838 n = parse_hex(s + 1, 6, ch);
20839 if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
20840 s += n + 2;
20841 }
20842 else {
20843
20844 *ch = 'u';
20845 }
20846 }
20847 else if ((n = parse_hex(s, 4, ch)) > 0) {
20848 s += n;
@@ -20886,15 +20873,15 @@
20873 int nocase = (preg->cflags & REG_ICASE);
20874
20875 int ch;
20876 int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
20877
20878 *flagp = WORST;
20879
20880 preg->regparse += n;
20881 switch (ch) {
20882
20883 case '^':
20884 ret = regnode(preg, BOL);
20885 break;
20886 case '$':
20887 ret = regnode(preg, EOL);
@@ -20904,24 +20891,24 @@
20891 *flagp |= HASWIDTH|SIMPLE;
20892 break;
20893 case '[': {
20894 const char *pattern = preg->regparse;
20895
20896 if (*pattern == '^') {
20897 ret = regnode(preg, ANYBUT);
20898 pattern++;
20899 } else
20900 ret = regnode(preg, ANYOF);
20901
20902
20903 if (*pattern == ']' || *pattern == '-') {
20904 reg_addrange(preg, *pattern, *pattern);
20905 pattern++;
20906 }
20907
20908 while (*pattern && *pattern != ']') {
20909
20910 int start;
20911 int end;
20912
20913 pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
20914 if (start == '\\') {
@@ -20930,11 +20917,11 @@
20917 preg->err = REG_ERR_NULL_CHAR;
20918 return 0;
20919 }
20920 }
20921 if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
20922
20923 pattern += utf8_tounicode(pattern, &end);
20924 pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
20925 if (end == '\\') {
20926 pattern += reg_decode_escape(pattern, &end);
20927 if (end == 0) {
@@ -20957,22 +20944,22 @@
20944 CC_NUM
20945 };
20946 int i;
20947
20948 for (i = 0; i < CC_NUM; i++) {
20949 n = strlen(character_class[i]);
20950 if (strncmp(pattern, character_class[i], n) == 0) {
20951
20952 pattern += n + 1;
20953 break;
20954 }
20955 }
20956 if (i != CC_NUM) {
20957 switch (i) {
20958 case CC_ALNUM:
20959 reg_addrange(preg, '0', '9');
20960
20961 case CC_ALPHA:
20962 if ((preg->cflags & REG_ICASE) == 0) {
20963 reg_addrange(preg, 'a', 'z');
20964 }
20965 reg_addrange(preg, 'A', 'Z');
@@ -20990,11 +20977,11 @@
20977 reg_addrange(preg, 'a', 'z');
20978 break;
20979 case CC_XDIGIT:
20980 reg_addrange(preg, 'a', 'f');
20981 reg_addrange(preg, 'A', 'F');
20982
20983 case CC_DIGIT:
20984 reg_addrange(preg, '0', '9');
20985 break;
20986 case CC_CNTRL:
20987 reg_addrange(preg, 0, 31);
@@ -21014,11 +21001,11 @@
21001 break;
21002 }
21003 continue;
21004 }
21005 }
21006
21007 reg_addrange(preg, start, start);
21008 }
21009 regc(preg, '\0');
21010
21011 if (*pattern) {
@@ -21037,11 +21024,11 @@
21024 break;
21025 case '\0':
21026 case '|':
21027 case ')':
21028 preg->err = REG_ERR_INTERNAL;
21029 return 0;
21030 case '?':
21031 case '+':
21032 case '*':
21033 case '{':
21034 preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
@@ -21090,34 +21077,34 @@
21077 ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
21078 reg_addrange_str(preg," \t\r\n\f\v");
21079 regc(preg, '\0');
21080 *flagp |= HASWIDTH|SIMPLE;
21081 break;
21082
21083 default:
21084
21085
21086 preg->regparse--;
21087 goto de_fault;
21088 }
21089 break;
21090 de_fault:
21091 default: {
21092 int added = 0;
21093
21094
21095 preg->regparse -= n;
21096
21097 ret = regnode(preg, EXACTLY);
21098
21099
21100
21101 while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
21102 n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
21103 if (ch == '\\' && preg->regparse[n]) {
21104 if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
21105
21106 break;
21107 }
21108 n += reg_decode_escape(preg->regparse + n, &ch);
21109 if (ch == 0) {
21110 preg->err = REG_ERR_NULL_CHAR;
@@ -21125,23 +21112,23 @@
21112 }
21113 }
21114
21115
21116 if (ISMULT(preg->regparse[n])) {
21117
21118 if (added) {
21119
21120 break;
21121 }
21122
21123 regc(preg, ch);
21124 added++;
21125 preg->regparse += n;
21126 break;
21127 }
21128
21129
21130 regc(preg, ch);
21131 added++;
21132 preg->regparse += n;
21133 }
21134 regc(preg, '\0');
@@ -21168,15 +21155,15 @@
21155
21156 static int regnode(regex_t *preg, int op)
21157 {
21158 reg_grow(preg, 2);
21159
21160
21161 preg->program[preg->p++] = op;
21162 preg->program[preg->p++] = 0;
21163
21164
21165 return preg->p - 2;
21166 }
21167
21168 static void regc(regex_t *preg, int b )
21169 {
@@ -21186,13 +21173,13 @@
21173
21174 static int reginsert(regex_t *preg, int op, int size, int opnd )
21175 {
21176 reg_grow(preg, size);
21177
21178
21179 memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
21180
21181 memset(preg->program + opnd, 0, sizeof(int) * size);
21182
21183 preg->program[opnd] = op;
21184
21185 preg->p += size;
@@ -21204,11 +21191,11 @@
21191 {
21192 int scan;
21193 int temp;
21194 int offset;
21195
21196
21197 scan = p;
21198 for (;;) {
21199 temp = regnext(preg, scan);
21200 if (temp == 0)
21201 break;
@@ -21224,11 +21211,11 @@
21211 }
21212
21213
21214 static void regoptail(regex_t *preg, int p, int val )
21215 {
21216
21217 if (p != 0 && OP(preg, p) == BRANCH) {
21218 regtail(preg, OPERAND(p), val);
21219 }
21220 }
21221
@@ -21240,16 +21227,16 @@
21227 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
21228 {
21229 const char *s;
21230 int scan;
21231
21232
21233 if (preg == NULL || preg->program == NULL || string == NULL) {
21234 return REG_ERR_NULL_ARGUMENT;
21235 }
21236
21237
21238 if (*preg->program != REG_MAGIC) {
21239 return REG_ERR_CORRUPTED;
21240 }
21241
21242 #ifdef DEBUG
@@ -21258,51 +21245,51 @@
21245 #endif
21246
21247 preg->eflags = eflags;
21248 preg->pmatch = pmatch;
21249 preg->nmatch = nmatch;
21250 preg->start = string;
21251
21252
21253 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
21254 int op = OP(preg, scan);
21255 if (op == END)
21256 break;
21257 if (op == REPX || op == REPXMIN)
21258 preg->program[scan + 4] = 0;
21259 }
21260
21261
21262 if (preg->regmust != 0) {
21263 s = string;
21264 while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
21265 if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
21266 break;
21267 }
21268 s++;
21269 }
21270 if (s == NULL)
21271 return REG_NOMATCH;
21272 }
21273
21274
21275 preg->regbol = string;
21276
21277
21278 if (preg->reganch) {
21279 if (eflags & REG_NOTBOL) {
21280
21281 goto nextline;
21282 }
21283 while (1) {
21284 if (regtry(preg, string)) {
21285 return REG_NOERROR;
21286 }
21287 if (*string) {
21288 nextline:
21289 if (preg->cflags & REG_NEWLINE) {
21290
21291 string = strchr(string, '\n');
21292 if (string) {
21293 preg->regbol = ++string;
21294 continue;
21295 }
@@ -21310,22 +21297,22 @@
21297 }
21298 return REG_NOMATCH;
21299 }
21300 }
21301
21302
21303 s = string;
21304 if (preg->regstart != '\0') {
21305
21306 while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
21307 if (regtry(preg, s))
21308 return REG_NOERROR;
21309 s++;
21310 }
21311 }
21312 else
21313
21314 while (1) {
21315 if (regtry(preg, s))
21316 return REG_NOERROR;
21317 if (*s == '\0') {
21318 break;
@@ -21334,15 +21321,15 @@
21321 int c;
21322 s += utf8_tounicode(s, &c);
21323 }
21324 }
21325
21326
21327 return REG_NOMATCH;
21328 }
21329
21330
21331 static int regtry( regex_t *preg, const char *string )
21332 {
21333 int i;
21334
21335 preg->reginput = string;
@@ -21379,11 +21366,11 @@
21366 }
21367
21368 static int reg_range_find(const int *range, int c)
21369 {
21370 while (*range) {
21371
21372 if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
21373 return 1;
21374 }
21375 range += 2;
21376 }
@@ -21391,11 +21378,11 @@
21378 }
21379
21380 static const char *str_find(const char *string, int c, int nocase)
21381 {
21382 if (nocase) {
21383
21384 c = utf8_upper(c);
21385 }
21386 while (*string) {
21387 int ch;
21388 int n = reg_utf8_tounicode_case(string, &ch, nocase);
@@ -21435,15 +21422,15 @@
21422 no = regrepeat(preg, scan + 5, max);
21423 if (no < min) {
21424 return 0;
21425 }
21426 if (matchmin) {
21427
21428 max = no;
21429 no = min;
21430 }
21431
21432 while (1) {
21433 if (matchmin) {
21434 if (no > max) {
21435 break;
21436 }
@@ -21453,22 +21440,22 @@
21440 break;
21441 }
21442 }
21443 preg->reginput = save + utf8_index(save, no);
21444 reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21445
21446 if (reg_iseol(preg, nextch) || c == nextch) {
21447 if (regmatch(preg, next)) {
21448 return(1);
21449 }
21450 }
21451 if (matchmin) {
21452
21453 no++;
21454 }
21455 else {
21456
21457 no--;
21458 }
21459 }
21460 return(0);
21461 }
@@ -21478,13 +21465,13 @@
21465 int *scanpt = preg->program + scan;
21466
21467 int max = scanpt[2];
21468 int min = scanpt[3];
21469
21470
21471 if (scanpt[4] < min) {
21472
21473 scanpt[4]++;
21474 if (regmatch(preg, scan + 5)) {
21475 return 1;
21476 }
21477 scanpt[4]--;
@@ -21493,39 +21480,39 @@
21480 if (scanpt[4] > max) {
21481 return 0;
21482 }
21483
21484 if (matchmin) {
21485
21486 if (regmatch(preg, regnext(preg, scan))) {
21487 return 1;
21488 }
21489
21490 scanpt[4]++;
21491 if (regmatch(preg, scan + 5)) {
21492 return 1;
21493 }
21494 scanpt[4]--;
21495 return 0;
21496 }
21497
21498 if (scanpt[4] < max) {
21499 scanpt[4]++;
21500 if (regmatch(preg, scan + 5)) {
21501 return 1;
21502 }
21503 scanpt[4]--;
21504 }
21505
21506 return regmatch(preg, regnext(preg, scan));
21507 }
21508
21509
21510 static int regmatch(regex_t *preg, int prog)
21511 {
21512 int scan;
21513 int next;
21514 const char *save;
21515
21516 scan = prog;
21517
21518 #ifdef DEBUG
@@ -21535,11 +21522,11 @@
21522 while (scan != 0) {
21523 int n;
21524 int c;
21525 #ifdef DEBUG
21526 if (regnarrate) {
21527 fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
21528 }
21529 #endif
21530 next = regnext(preg, scan);
21531 n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
21532
@@ -21546,49 +21533,49 @@
21533 switch (OP(preg, scan)) {
21534 case BOLX:
21535 if ((preg->eflags & REG_NOTBOL)) {
21536 return(0);
21537 }
21538
21539 case BOL:
21540 if (preg->reginput != preg->regbol) {
21541 return(0);
21542 }
21543 break;
21544 case EOLX:
21545 if (c != 0) {
21546
21547 return 0;
21548 }
21549 break;
21550 case EOL:
21551 if (!reg_iseol(preg, c)) {
21552 return(0);
21553 }
21554 break;
21555 case WORDA:
21556
21557 if ((!isalnum(UCHAR(c))) && c != '_')
21558 return(0);
21559
21560 if (preg->reginput > preg->regbol &&
21561 (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
21562 return(0);
21563 break;
21564 case WORDZ:
21565
21566 if (preg->reginput > preg->regbol) {
21567
21568 if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
21569 c = preg->reginput[-1];
21570
21571 if (isalnum(UCHAR(c)) || c == '_') {
21572 break;
21573 }
21574 }
21575 }
21576
21577 return(0);
21578
21579 case ANY:
21580 if (reg_iseol(preg, c))
21581 return 0;
@@ -21624,12 +21611,12 @@
21611 case NOTHING:
21612 break;
21613 case BACK:
21614 break;
21615 case BRANCH:
21616 if (OP(preg, next) != BRANCH)
21617 next = OPERAND(scan);
21618 else {
21619 do {
21620 save = preg->reginput;
21621 if (regmatch(preg, OPERAND(scan))) {
21622 return(1);
@@ -21636,11 +21623,11 @@
21623 }
21624 preg->reginput = save;
21625 scan = regnext(preg, scan);
21626 } while (scan != 0 && OP(preg, scan) == BRANCH);
21627 return(0);
21628
21629 }
21630 break;
21631 case REP:
21632 case REPMIN:
21633 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21648,11 +21635,11 @@
21635 case REPX:
21636 case REPXMIN:
21637 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21638
21639 case END:
21640 return 1;
21641
21642 case OPENNC:
21643 case CLOSENC:
21644 return regmatch(preg, next);
21645
@@ -21695,11 +21682,11 @@
21682
21683 scan = preg->reginput;
21684 opnd = OPERAND(p);
21685 switch (OP(preg, p)) {
21686 case ANY:
21687
21688 while (!reg_iseol(preg, *scan) && count < max) {
21689 count++;
21690 scan++;
21691 }
21692 break;
@@ -21731,13 +21718,13 @@
21718 }
21719 count++;
21720 scan += n;
21721 }
21722 break;
21723 default:
21724 preg->err = REG_ERR_INTERNAL;
21725 count = 0;
21726 break;
21727 }
21728 preg->reginput = scan;
21729
21730 return(count);
@@ -21758,11 +21745,11 @@
21745 return(p+offset);
21746 }
21747
21748 static int regopsize(regex_t *preg, int p )
21749 {
21750
21751 switch (OP(preg, p)) {
21752 case REP:
21753 case REPMIN:
21754 case REPX:
21755 case REPXMIN:
@@ -21879,26 +21866,26 @@
21866 {
21867 DIR *dir = 0;
21868
21869 if (name && name[0]) {
21870 size_t base_length = strlen(name);
21871 const char *all =
21872 strchr("/\\", name[base_length - 1]) ? "*" : "/*";
21873
21874 if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
21875 (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
21876 strcat(strcpy(dir->name, name), all);
21877
21878 if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
21879 dir->result.d_name = 0;
21880 else {
21881 Jim_Free(dir->name);
21882 Jim_Free(dir);
21883 dir = 0;
21884 }
21885 }
21886 else {
21887 Jim_Free(dir);
21888 dir = 0;
21889 errno = ENOMEM;
21890 }
21891 }
@@ -21916,11 +21903,11 @@
21903 if (dir->handle != -1)
21904 result = _findclose(dir->handle);
21905 Jim_Free(dir->name);
21906 Jim_Free(dir);
21907 }
21908 if (result == -1)
21909 errno = EBADF;
21910 return result;
21911 }
21912
21913 struct dirent *readdir(DIR * dir)
@@ -21947,10 +21934,13 @@
21934
21935 #ifdef USE_LINENOISE
21936 #ifdef HAVE_UNISTD_H
21937 #include <unistd.h>
21938 #endif
21939 #ifdef HAVE_SYS_STAT_H
21940 #include <sys/stat.h>
21941 #endif
21942 #include "linenoise.h"
21943 #else
21944 #define MAX_LINE_LEN 512
21945 #endif
21946
@@ -21992,41 +21982,86 @@
21982 }
21983
21984 void Jim_HistorySave(const char *filename)
21985 {
21986 #ifdef USE_LINENOISE
21987 #ifdef HAVE_UMASK
21988 mode_t mask;
21989
21990 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
21991 #endif
21992 linenoiseHistorySave(filename);
21993 #ifdef HAVE_UMASK
21994 mask = umask(mask);
21995 #endif
21996 #endif
21997 }
21998
21999 void Jim_HistoryShow(void)
22000 {
22001 #ifdef USE_LINENOISE
22002
22003 int i;
22004 int len;
22005 char **history = linenoiseHistory(&len);
22006 for (i = 0; i < len; i++) {
22007 printf("%4d %s\n", i + 1, history[i]);
22008 }
22009 #endif
22010 }
22011
22012 #ifdef USE_LINENOISE
22013 struct JimCompletionInfo {
22014 Jim_Interp *interp;
22015 Jim_Obj *command;
22016 };
22017
22018 void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
22019 {
22020 struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
22021 Jim_Obj *objv[2];
22022 int ret;
22023
22024 objv[0] = info->command;
22025 objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
22026
22027 ret = Jim_EvalObjVector(info->interp, 2, objv);
22028
22029
22030 if (ret == JIM_OK) {
22031 int i;
22032 Jim_Obj *listObj = Jim_GetResult(info->interp);
22033 int len = Jim_ListLength(info->interp, listObj);
22034 for (i = 0; i < len; i++) {
22035 linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i)));
22036 }
22037 }
22038 }
22039 #endif
22040
22041 int Jim_InteractivePrompt(Jim_Interp *interp)
22042 {
22043 int retcode = JIM_OK;
22044 char *history_file = NULL;
22045 #ifdef USE_LINENOISE
22046 const char *home;
22047 struct JimCompletionInfo compinfo;
22048
22049 home = getenv("HOME");
22050 if (home && isatty(STDIN_FILENO)) {
22051 int history_len = strlen(home) + sizeof("/.jim_history");
22052 history_file = Jim_Alloc(history_len);
22053 snprintf(history_file, history_len, "%s/.jim_history", home);
22054 Jim_HistoryLoad(history_file);
22055 }
22056
22057 compinfo.interp = interp;
22058 compinfo.command = Jim_NewStringObj(interp, "tcl::autocomplete", -1);
22059 Jim_IncrRefCount(compinfo.command);
22060
22061
22062 linenoiseSetCompletionCallback(JimCompletionCallback, &compinfo);
22063 #endif
22064
22065 printf("Welcome to Jim version %d.%d\n",
22066 JIM_VERSION / 100, JIM_VERSION % 100);
22067 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
@@ -22065,11 +22100,11 @@
22100 Jim_DecrRefCount(interp, scriptObjPtr);
22101 retcode = JIM_OK;
22102 goto out;
22103 }
22104 if (Jim_Length(scriptObjPtr) != 0) {
22105
22106 Jim_AppendString(interp, scriptObjPtr, "\n", 1);
22107 }
22108 Jim_AppendString(interp, scriptObjPtr, line, -1);
22109 free(line);
22110 if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
@@ -22077,11 +22112,11 @@
22112
22113 snprintf(prompt, sizeof(prompt), "%c> ", state);
22114 }
22115 #ifdef USE_LINENOISE
22116 if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
22117
22118 Jim_HistoryShow();
22119 Jim_DecrRefCount(interp, scriptObjPtr);
22120 continue;
22121 }
22122
@@ -22104,10 +22139,16 @@
22139 printf("%s\n", result);
22140 }
22141 }
22142 out:
22143 Jim_Free(history_file);
22144
22145 #ifdef USE_LINENOISE
22146 Jim_DecrRefCount(interp, compinfo.command);
22147 linenoiseSetCompletionCallback(NULL, NULL);
22148 #endif
22149
22150 return retcode;
22151 }
22152
22153 #include <stdio.h>
22154 #include <stdlib.h>
@@ -22120,11 +22161,11 @@
22161 static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
22162 {
22163 int n;
22164 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
22165
22166
22167 for (n = 0; n < argc; n++) {
22168 Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
22169
22170 Jim_ListAppendElement(interp, listObj, obj);
22171 }
@@ -22146,71 +22187,75 @@
22187 printf("or : %s [options] [filename]\n", executable_name);
22188 printf("\n");
22189 printf("Without options: Interactive mode\n");
22190 printf("\n");
22191 printf("Options:\n");
22192 printf(" --version : prints the version string\n");
22193 printf(" --help : prints this text\n");
22194 printf(" -e CMD : executes command CMD\n");
22195 printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
22196 printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n");
22197 printf(" NOTE: all subsequent options will be passed to the script\n\n");
22198 }
22199
22200 int main(int argc, char *const argv[])
22201 {
22202 int retcode;
22203 Jim_Interp *interp;
22204 char *const orig_argv0 = argv[0];
22205
22206
22207 if (argc > 1 && strcmp(argv[1], "--version") == 0) {
22208 printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
22209 return 0;
22210 }
22211 else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
22212 usage(argv[0]);
22213 return 0;
22214 }
22215
22216
22217 interp = Jim_CreateInterp();
22218 Jim_RegisterCoreCommands(interp);
22219
22220
22221 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
22222 JimPrintErrorMessage(interp);
22223 }
22224
22225 Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
22226 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
22227 retcode = Jim_initjimshInit(interp);
22228
22229 if (argc == 1) {
22230
22231 if (retcode == JIM_ERR) {
22232 JimPrintErrorMessage(interp);
22233 }
22234 if (retcode != JIM_EXIT) {
22235 JimSetArgv(interp, 0, NULL);
22236 retcode = Jim_InteractivePrompt(interp);
22237 }
22238 }
22239 else {
22240
22241 if (argc > 2 && strcmp(argv[1], "-e") == 0) {
22242
22243 JimSetArgv(interp, argc - 3, argv + 3);
22244 retcode = Jim_Eval(interp, argv[2]);
22245 if (retcode != JIM_ERR) {
22246 printf("%s\n", Jim_String(Jim_GetResult(interp)));
22247 }
22248 }
22249 else {
22250 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
22251 JimSetArgv(interp, argc - 2, argv + 2);
22252 if (strcmp(argv[1], "-") == 0) {
22253 retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
22254 } else {
22255 retcode = Jim_EvalFile(interp, argv[1]);
22256 }
22257 }
22258 if (retcode == JIM_ERR) {
22259 JimPrintErrorMessage(interp);
22260 }
22261 }
22262
--- autosetup/pkg-config.tcl
+++ autosetup/pkg-config.tcl
@@ -1,34 +1,35 @@
11
# Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
22
# All rights reserved
33
44
# @synopsis:
55
#
6
-# The 'pkg-config' module allows package information to be found via pkg-config
6
+# The 'pkg-config' module allows package information to be found via 'pkg-config'.
77
#
88
# If not cross-compiling, the package path should be determined automatically
9
-# by pkg-config.
9
+# by 'pkg-config'.
1010
# If cross-compiling, the default package path is the compiler sysroot.
11
-# If the C compiler doesn't support -print-sysroot, the path can be supplied
12
-# by the --sysroot option or by defining SYSROOT.
11
+# If the C compiler doesn't support '-print-sysroot', the path can be supplied
12
+# by the '--sysroot' option or by defining 'SYSROOT'.
1313
#
14
-# PKG_CONFIG may be set to use an alternative to pkg-config
14
+# 'PKG_CONFIG' may be set to use an alternative to 'pkg-config'.
1515
1616
use cc
1717
1818
module-options {
1919
sysroot:dir => "Override compiler sysroot for pkg-config search path"
2020
}
2121
2222
# @pkg-config-init ?required?
2323
#
24
-# Initialises the pkg-config system. Unless required is set to 0,
25
-# it is a fatal error if the pkg-config
24
+# Initialises the 'pkg-config' system. Unless '$required' is set to 0,
25
+# it is a fatal error if a usable 'pkg-config' is not found .
26
+#
2627
# This command will normally be called automatically as required,
27
-# but it may be invoked explicitly if lack of pkg-config is acceptable.
28
+# but it may be invoked explicitly if lack of 'pkg-config' is acceptable.
2829
#
29
-# Returns 1 if ok, or 0 if pkg-config not found/usable (only if required=0)
30
+# Returns 1 if ok, or 0 if 'pkg-config' not found/usable (only if '$required' is 0).
3031
#
3132
proc pkg-config-init {{required 1}} {
3233
if {[is-defined HAVE_PKG_CONFIG]} {
3334
return [get-define HAVE_PKG_CONFIG]
3435
}
@@ -47,11 +48,11 @@
4748
define PKG_CONFIG_VERSION $version
4849
4950
set found 1
5051
5152
if {[opt-val sysroot] ne ""} {
52
- define SYSROOT [file-normalize [opt-val sysroot]]
53
+ define SYSROOT [file-normalize [lindex [opt-val sysroot] end]]
5354
msg-result "Using specified sysroot [get-define SYSROOT]"
5455
} elseif {[get-define build] ne [get-define host]} {
5556
if {[catch {exec-with-stderr [get-define CC] -print-sysroot} result errinfo] == 0} {
5657
# Use the compiler sysroot, if there is one
5758
define SYSROOT $result
@@ -81,21 +82,21 @@
8182
return $found
8283
}
8384
8485
# @pkg-config module ?requirements?
8586
#
86
-# Use pkg-config to find the given module meeting the given requirements.
87
+# Use 'pkg-config' to find the given module meeting the given requirements.
8788
# e.g.
8889
#
8990
## pkg-config pango >= 1.37.0
9091
#
91
-# If found, returns 1 and sets HAVE_PKG_PANGO to 1 along with:
92
+# If found, returns 1 and sets 'HAVE_PKG_PANGO' to 1 along with:
9293
#
9394
## PKG_PANGO_VERSION to the found version
94
-## PKG_PANGO_LIBS to the required libs (--libs-only-l)
95
+## PKG_PANGO_LIBS to the required libs (--libs-only-l)
9596
## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
96
-## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
97
+## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
9798
#
9899
# If not found, returns 0.
99100
#
100101
proc pkg-config {module args} {
101102
set ok [pkg-config-init]
@@ -122,13 +123,13 @@
122123
return 1
123124
}
124125
125126
# @pkg-config-get module setting
126127
#
127
-# Convenience access to the results of pkg-config
128
+# Convenience access to the results of 'pkg-config'.
128129
#
129
-# For example, [pkg-config-get pango CFLAGS] returns
130
-# the value of PKG_PANGO_CFLAGS, or "" if not defined.
130
+# For example, '[pkg-config-get pango CFLAGS]' returns
131
+# the value of 'PKG_PANGO_CFLAGS', or '""' if not defined.
131132
proc pkg-config-get {module name} {
132133
set prefix [feature-define-name $module PKG_]
133134
get-define ${prefix}_${name} ""
134135
}
135136
--- autosetup/pkg-config.tcl
+++ autosetup/pkg-config.tcl
@@ -1,34 +1,35 @@
1 # Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'pkg-config' module allows package information to be found via pkg-config
7 #
8 # If not cross-compiling, the package path should be determined automatically
9 # by pkg-config.
10 # If cross-compiling, the default package path is the compiler sysroot.
11 # If the C compiler doesn't support -print-sysroot, the path can be supplied
12 # by the --sysroot option or by defining SYSROOT.
13 #
14 # PKG_CONFIG may be set to use an alternative to pkg-config
15
16 use cc
17
18 module-options {
19 sysroot:dir => "Override compiler sysroot for pkg-config search path"
20 }
21
22 # @pkg-config-init ?required?
23 #
24 # Initialises the pkg-config system. Unless required is set to 0,
25 # it is a fatal error if the pkg-config
 
26 # This command will normally be called automatically as required,
27 # but it may be invoked explicitly if lack of pkg-config is acceptable.
28 #
29 # Returns 1 if ok, or 0 if pkg-config not found/usable (only if required=0)
30 #
31 proc pkg-config-init {{required 1}} {
32 if {[is-defined HAVE_PKG_CONFIG]} {
33 return [get-define HAVE_PKG_CONFIG]
34 }
@@ -47,11 +48,11 @@
47 define PKG_CONFIG_VERSION $version
48
49 set found 1
50
51 if {[opt-val sysroot] ne ""} {
52 define SYSROOT [file-normalize [opt-val sysroot]]
53 msg-result "Using specified sysroot [get-define SYSROOT]"
54 } elseif {[get-define build] ne [get-define host]} {
55 if {[catch {exec-with-stderr [get-define CC] -print-sysroot} result errinfo] == 0} {
56 # Use the compiler sysroot, if there is one
57 define SYSROOT $result
@@ -81,21 +82,21 @@
81 return $found
82 }
83
84 # @pkg-config module ?requirements?
85 #
86 # Use pkg-config to find the given module meeting the given requirements.
87 # e.g.
88 #
89 ## pkg-config pango >= 1.37.0
90 #
91 # If found, returns 1 and sets HAVE_PKG_PANGO to 1 along with:
92 #
93 ## PKG_PANGO_VERSION to the found version
94 ## PKG_PANGO_LIBS to the required libs (--libs-only-l)
95 ## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
96 ## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
97 #
98 # If not found, returns 0.
99 #
100 proc pkg-config {module args} {
101 set ok [pkg-config-init]
@@ -122,13 +123,13 @@
122 return 1
123 }
124
125 # @pkg-config-get module setting
126 #
127 # Convenience access to the results of pkg-config
128 #
129 # For example, [pkg-config-get pango CFLAGS] returns
130 # the value of PKG_PANGO_CFLAGS, or "" if not defined.
131 proc pkg-config-get {module name} {
132 set prefix [feature-define-name $module PKG_]
133 get-define ${prefix}_${name} ""
134 }
135
--- autosetup/pkg-config.tcl
+++ autosetup/pkg-config.tcl
@@ -1,34 +1,35 @@
1 # Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'pkg-config' module allows package information to be found via 'pkg-config'.
7 #
8 # If not cross-compiling, the package path should be determined automatically
9 # by 'pkg-config'.
10 # If cross-compiling, the default package path is the compiler sysroot.
11 # If the C compiler doesn't support '-print-sysroot', the path can be supplied
12 # by the '--sysroot' option or by defining 'SYSROOT'.
13 #
14 # 'PKG_CONFIG' may be set to use an alternative to 'pkg-config'.
15
16 use cc
17
18 module-options {
19 sysroot:dir => "Override compiler sysroot for pkg-config search path"
20 }
21
22 # @pkg-config-init ?required?
23 #
24 # Initialises the 'pkg-config' system. Unless '$required' is set to 0,
25 # it is a fatal error if a usable 'pkg-config' is not found .
26 #
27 # This command will normally be called automatically as required,
28 # but it may be invoked explicitly if lack of 'pkg-config' is acceptable.
29 #
30 # Returns 1 if ok, or 0 if 'pkg-config' not found/usable (only if '$required' is 0).
31 #
32 proc pkg-config-init {{required 1}} {
33 if {[is-defined HAVE_PKG_CONFIG]} {
34 return [get-define HAVE_PKG_CONFIG]
35 }
@@ -47,11 +48,11 @@
48 define PKG_CONFIG_VERSION $version
49
50 set found 1
51
52 if {[opt-val sysroot] ne ""} {
53 define SYSROOT [file-normalize [lindex [opt-val sysroot] end]]
54 msg-result "Using specified sysroot [get-define SYSROOT]"
55 } elseif {[get-define build] ne [get-define host]} {
56 if {[catch {exec-with-stderr [get-define CC] -print-sysroot} result errinfo] == 0} {
57 # Use the compiler sysroot, if there is one
58 define SYSROOT $result
@@ -81,21 +82,21 @@
82 return $found
83 }
84
85 # @pkg-config module ?requirements?
86 #
87 # Use 'pkg-config' to find the given module meeting the given requirements.
88 # e.g.
89 #
90 ## pkg-config pango >= 1.37.0
91 #
92 # If found, returns 1 and sets 'HAVE_PKG_PANGO' to 1 along with:
93 #
94 ## PKG_PANGO_VERSION to the found version
95 ## PKG_PANGO_LIBS to the required libs (--libs-only-l)
96 ## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
97 ## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
98 #
99 # If not found, returns 0.
100 #
101 proc pkg-config {module args} {
102 set ok [pkg-config-init]
@@ -122,13 +123,13 @@
123 return 1
124 }
125
126 # @pkg-config-get module setting
127 #
128 # Convenience access to the results of 'pkg-config'.
129 #
130 # For example, '[pkg-config-get pango CFLAGS]' returns
131 # the value of 'PKG_PANGO_CFLAGS', or '""' if not defined.
132 proc pkg-config-get {module name} {
133 set prefix [feature-define-name $module PKG_]
134 get-define ${prefix}_${name} ""
135 }
136
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -2,26 +2,28 @@
22
# All rights reserved
33
44
# @synopsis:
55
#
66
# This module supports common system interrogation and options
7
-# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEEXT
7
+# such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
88
#
9
-# It also support the 'feature' naming convention, where searching
10
-# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H
9
+# It also support the "feature" naming convention, where searching
10
+# for a feature such as 'sys/type.h' defines 'HAVE_SYS_TYPES_H'.
1111
#
12
-# It defines the following variables, based on --prefix unless overridden by the user:
12
+# It defines the following variables, based on '--prefix' unless overridden by the user:
1313
#
1414
## datadir
1515
## sysconfdir
1616
## sharedstatedir
1717
## localstatedir
1818
## infodir
1919
## mandir
2020
## includedir
21
+#
22
+# If '--prefix' is not supplied, it defaults to '/usr/local' unless 'defaultprefix' is defined *before*
23
+# including the 'system' module.
2124
22
-# Do "define defaultprefix myvalue" to set the default prefix *before* the first "use"
2325
set defaultprefix [get-define defaultprefix /usr/local]
2426
2527
module-options [subst -noc -nob {
2628
host:host-alias => {a complete or partial cpu-vendor-opsys for the system where
2729
the application will run (defaults to the same value as --build)}
@@ -45,12 +47,20 @@
4547
localstatedir:
4648
maintainer-mode=0
4749
dependency-tracking=0
4850
}]
4951
50
-# Returns 1 if exists, or 0 if not
52
+# @check-feature name { script }
53
+#
54
+# defines feature '$name' to the return value of '$script',
55
+# which should be 1 if found or 0 if not found.
56
+#
57
+# e.g. the following will define 'HAVE_CONST' to 0 or 1.
5158
#
59
+## check-feature const {
60
+## cctest -code {const int _x = 0;}
61
+## }
5262
proc check-feature {name code} {
5363
msg-checking "Checking for $name..."
5464
set r [uplevel 1 $code]
5565
define-feature $name $r
5666
if {$r} {
@@ -61,49 +71,54 @@
6171
return $r
6272
}
6373
6474
# @have-feature name ?default=0?
6575
#
66
-# Returns the value of the feature if defined, or $default if not.
67
-# See 'feature-define-name' for how the feature name
68
-# is translated into the define name.
76
+# Returns the value of feature '$name' if defined, or '$default' if not.
77
+#
78
+# See 'feature-define-name' for how the "feature" name
79
+# is translated into the "define" name.
6980
#
7081
proc have-feature {name {default 0}} {
7182
get-define [feature-define-name $name] $default
7283
}
7384
7485
# @define-feature name ?value=1?
7586
#
76
-# Sets the feature 'define' to the given value.
77
-# See 'feature-define-name' for how the feature name
78
-# is translated into the define name.
87
+# Sets the feature 'define' to '$value'.
88
+#
89
+# See 'feature-define-name' for how the "feature" name
90
+# is translated into the "define" name.
7991
#
8092
proc define-feature {name {value 1}} {
8193
define [feature-define-name $name] $value
8294
}
8395
8496
# @feature-checked name
8597
#
86
-# Returns 1 if the feature has been checked, whether true or not
98
+# Returns 1 if feature '$name' has been checked, whether true or not.
8799
#
88100
proc feature-checked {name} {
89101
is-defined [feature-define-name $name]
90102
}
91103
92104
# @feature-define-name name ?prefix=HAVE_?
93105
#
94
-# Converts a name to the corresponding define,
95
-# e.g. sys/stat.h becomes HAVE_SYS_STAT_H.
106
+# Converts a "feature" name to the corresponding "define",
107
+# e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
96108
#
97
-# Converts * to P and all non-alphanumeric to underscore.
109
+# Converts '*' to 'P' and all non-alphanumeric to underscore.
98110
#
99111
proc feature-define-name {name {prefix HAVE_}} {
100112
string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
101113
}
102114
103
-# If $file doesn't exist, or it's contents are different than $buf,
104
-# the file is written and $script is executed.
115
+# @write-if-changed filename contents ?script?
116
+#
117
+# If '$filename' doesn't exist, or it's contents are different to '$contents',
118
+# the file is written and '$script' is evaluated.
119
+#
105120
# Otherwise a "file is unchanged" message is displayed.
106121
proc write-if-changed {file buf {script {}}} {
107122
set old [readfile $file ""]
108123
if {$old eq $buf && [file exists $file]} {
109124
msg-result "$file is unchanged"
@@ -113,37 +128,38 @@
113128
}
114129
}
115130
116131
# @make-template template ?outfile?
117132
#
118
-# Reads the input file <srcdir>/$template and writes the output file $outfile.
119
-# If $outfile is blank/omitted, $template should end with ".in" which
133
+# Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
134
+# (unless unchanged).
135
+# If '$outfile' is blank/omitted, '$template' should end with '.in' which
120136
# is removed to create the output file name.
121137
#
122
-# Each pattern of the form @define@ is replaced with the corresponding
123
-# define, if it exists, or left unchanged if not.
138
+# Each pattern of the form '@define@' is replaced with the corresponding
139
+# "define", if it exists, or left unchanged if not.
124140
#
125
-# The special value @srcdir@ is substituted with the relative
141
+# The special value '@srcdir@' is substituted with the relative
126142
# path to the source directory from the directory where the output
127
-# file is created, while the special value @top_srcdir@ is substituted
143
+# file is created, while the special value '@top_srcdir@' is substituted
128144
# with the relative path to the top level source directory.
129145
#
130146
# Conditional sections may be specified as follows:
131147
## @if name == value
132148
## lines
133149
## @else
134150
## lines
135151
## @endif
136152
#
137
-# Where 'name' is a defined variable name and @else is optional.
153
+# Where 'name' is a defined variable name and '@else' is optional.
138154
# If the expression does not match, all lines through '@endif' are ignored.
139155
#
140156
# The alternative forms may also be used:
141157
## @if name
142158
## @if name != value
143159
#
144
-# Where the first form is true if the variable is defined, but not empty or 0
160
+# Where the first form is true if the variable is defined, but not empty nor 0.
145161
#
146162
# Currently these expressions can't be nested.
147163
#
148164
proc make-template {template {out {}}} {
149165
set infile [file join $::autosetup(srcdir) $template]
@@ -205,25 +221,25 @@
205221
}
206222
continue
207223
}
208224
lappend result $line
209225
}
210
- write-if-changed $out [string map $mapping [join $result \n]]\n {
211
- msg-result "Created [relative-path $out] from [relative-path $template]"
212
- }
226
+ write-if-changed $out [string map $mapping [join $result \n]]\n {
227
+ msg-result "Created [relative-path $out] from [relative-path $template]"
228
+ }
213229
}
214230
215231
# build/host tuples and cross-compilation prefix
216
-set build [opt-val build]
232
+set build [lindex [opt-val build] end]
217233
define build_alias $build
218234
if {$build eq ""} {
219235
define build [config_guess]
220236
} else {
221237
define build [config_sub $build]
222238
}
223239
224
-set host [opt-val host]
240
+set host [lindex [opt-val host] end]
225241
define host_alias $host
226242
if {$host eq ""} {
227243
define host [get-define build]
228244
set cross ""
229245
} else {
@@ -230,30 +246,42 @@
230246
define host [config_sub $host]
231247
set cross $host-
232248
}
233249
define cross [get-env CROSS $cross]
234250
235
-set prefix [opt-val prefix $defaultprefix]
251
+# build/host _cpu, _vendor and _os
252
+foreach type {build host} {
253
+ set v [get-define $type]
254
+ if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
255
+ user-error "Invalid canonical $type: $v"
256
+ }
257
+ define ${type}_cpu $cpu
258
+ define ${type}_vendor $vendor
259
+ define ${type}_os $os
260
+}
261
+
262
+set prefix [lindex [opt-val prefix $defaultprefix] end]
236263
237264
# These are for compatibility with autoconf
238265
define target [get-define host]
239266
define prefix $prefix
240267
define builddir $autosetup(builddir)
241268
define srcdir $autosetup(srcdir)
242
-# Allow this to come from the environment
243
-define top_srcdir [get-env top_srcdir [get-define srcdir]]
269
+define top_srcdir $autosetup(srcdir)
270
+define abs_top_srcdir [file-normalize $autosetup(srcdir)]
271
+define abs_top_builddir [file-normalize $autosetup(builddir)]
244272
245273
# autoconf supports all of these
246
-set exec_prefix [opt-val exec-prefix $prefix]
274
+set exec_prefix [lindex [opt-val exec-prefix $prefix] end]
247275
define exec_prefix $exec_prefix
248276
foreach {name defpath} {
249277
bindir /bin
250278
sbindir /sbin
251279
libexecdir /libexec
252280
libdir /lib
253281
} {
254
- define $name [opt-val $name $exec_prefix$defpath]
282
+ define $name [lindex [opt-val $name $exec_prefix$defpath] end]
255283
}
256284
foreach {name defpath} {
257285
datadir /share
258286
sysconfdir /etc
259287
sharedstatedir /com
@@ -260,11 +288,11 @@
260288
localstatedir /var
261289
infodir /share/info
262290
mandir /share/man
263291
includedir /include
264292
} {
265
- define $name [opt-val $name $prefix$defpath]
293
+ define $name [lindex [opt-val $name $prefix$defpath] end]
266294
}
267295
268296
define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
269297
270298
# Windows vs. non-Windows
271299
272300
DELETED autosetup/test-tclsh
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -2,26 +2,28 @@
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # This module supports common system interrogation and options
7 # such as --host, --build, --prefix, and setting srcdir, builddir, and EXEEXT
8 #
9 # It also support the 'feature' naming convention, where searching
10 # for a feature such as sys/type.h defines HAVE_SYS_TYPES_H
11 #
12 # It defines the following variables, based on --prefix unless overridden by the user:
13 #
14 ## datadir
15 ## sysconfdir
16 ## sharedstatedir
17 ## localstatedir
18 ## infodir
19 ## mandir
20 ## includedir
 
 
 
21
22 # Do "define defaultprefix myvalue" to set the default prefix *before* the first "use"
23 set defaultprefix [get-define defaultprefix /usr/local]
24
25 module-options [subst -noc -nob {
26 host:host-alias => {a complete or partial cpu-vendor-opsys for the system where
27 the application will run (defaults to the same value as --build)}
@@ -45,12 +47,20 @@
45 localstatedir:
46 maintainer-mode=0
47 dependency-tracking=0
48 }]
49
50 # Returns 1 if exists, or 0 if not
 
 
 
 
 
51 #
 
 
 
52 proc check-feature {name code} {
53 msg-checking "Checking for $name..."
54 set r [uplevel 1 $code]
55 define-feature $name $r
56 if {$r} {
@@ -61,49 +71,54 @@
61 return $r
62 }
63
64 # @have-feature name ?default=0?
65 #
66 # Returns the value of the feature if defined, or $default if not.
67 # See 'feature-define-name' for how the feature name
68 # is translated into the define name.
 
69 #
70 proc have-feature {name {default 0}} {
71 get-define [feature-define-name $name] $default
72 }
73
74 # @define-feature name ?value=1?
75 #
76 # Sets the feature 'define' to the given value.
77 # See 'feature-define-name' for how the feature name
78 # is translated into the define name.
 
79 #
80 proc define-feature {name {value 1}} {
81 define [feature-define-name $name] $value
82 }
83
84 # @feature-checked name
85 #
86 # Returns 1 if the feature has been checked, whether true or not
87 #
88 proc feature-checked {name} {
89 is-defined [feature-define-name $name]
90 }
91
92 # @feature-define-name name ?prefix=HAVE_?
93 #
94 # Converts a name to the corresponding define,
95 # e.g. sys/stat.h becomes HAVE_SYS_STAT_H.
96 #
97 # Converts * to P and all non-alphanumeric to underscore.
98 #
99 proc feature-define-name {name {prefix HAVE_}} {
100 string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
101 }
102
103 # If $file doesn't exist, or it's contents are different than $buf,
104 # the file is written and $script is executed.
 
 
 
105 # Otherwise a "file is unchanged" message is displayed.
106 proc write-if-changed {file buf {script {}}} {
107 set old [readfile $file ""]
108 if {$old eq $buf && [file exists $file]} {
109 msg-result "$file is unchanged"
@@ -113,37 +128,38 @@
113 }
114 }
115
116 # @make-template template ?outfile?
117 #
118 # Reads the input file <srcdir>/$template and writes the output file $outfile.
119 # If $outfile is blank/omitted, $template should end with ".in" which
 
120 # is removed to create the output file name.
121 #
122 # Each pattern of the form @define@ is replaced with the corresponding
123 # define, if it exists, or left unchanged if not.
124 #
125 # The special value @srcdir@ is substituted with the relative
126 # path to the source directory from the directory where the output
127 # file is created, while the special value @top_srcdir@ is substituted
128 # with the relative path to the top level source directory.
129 #
130 # Conditional sections may be specified as follows:
131 ## @if name == value
132 ## lines
133 ## @else
134 ## lines
135 ## @endif
136 #
137 # Where 'name' is a defined variable name and @else is optional.
138 # If the expression does not match, all lines through '@endif' are ignored.
139 #
140 # The alternative forms may also be used:
141 ## @if name
142 ## @if name != value
143 #
144 # Where the first form is true if the variable is defined, but not empty or 0
145 #
146 # Currently these expressions can't be nested.
147 #
148 proc make-template {template {out {}}} {
149 set infile [file join $::autosetup(srcdir) $template]
@@ -205,25 +221,25 @@
205 }
206 continue
207 }
208 lappend result $line
209 }
210 write-if-changed $out [string map $mapping [join $result \n]]\n {
211 msg-result "Created [relative-path $out] from [relative-path $template]"
212 }
213 }
214
215 # build/host tuples and cross-compilation prefix
216 set build [opt-val build]
217 define build_alias $build
218 if {$build eq ""} {
219 define build [config_guess]
220 } else {
221 define build [config_sub $build]
222 }
223
224 set host [opt-val host]
225 define host_alias $host
226 if {$host eq ""} {
227 define host [get-define build]
228 set cross ""
229 } else {
@@ -230,30 +246,42 @@
230 define host [config_sub $host]
231 set cross $host-
232 }
233 define cross [get-env CROSS $cross]
234
235 set prefix [opt-val prefix $defaultprefix]
 
 
 
 
 
 
 
 
 
 
 
236
237 # These are for compatibility with autoconf
238 define target [get-define host]
239 define prefix $prefix
240 define builddir $autosetup(builddir)
241 define srcdir $autosetup(srcdir)
242 # Allow this to come from the environment
243 define top_srcdir [get-env top_srcdir [get-define srcdir]]
 
244
245 # autoconf supports all of these
246 set exec_prefix [opt-val exec-prefix $prefix]
247 define exec_prefix $exec_prefix
248 foreach {name defpath} {
249 bindir /bin
250 sbindir /sbin
251 libexecdir /libexec
252 libdir /lib
253 } {
254 define $name [opt-val $name $exec_prefix$defpath]
255 }
256 foreach {name defpath} {
257 datadir /share
258 sysconfdir /etc
259 sharedstatedir /com
@@ -260,11 +288,11 @@
260 localstatedir /var
261 infodir /share/info
262 mandir /share/man
263 includedir /include
264 } {
265 define $name [opt-val $name $prefix$defpath]
266 }
267
268 define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
269
270 # Windows vs. non-Windows
271
272 ELETED autosetup/test-tclsh
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -2,26 +2,28 @@
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # This module supports common system interrogation and options
7 # such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
8 #
9 # It also support the "feature" naming convention, where searching
10 # for a feature such as 'sys/type.h' defines 'HAVE_SYS_TYPES_H'.
11 #
12 # It defines the following variables, based on '--prefix' unless overridden by the user:
13 #
14 ## datadir
15 ## sysconfdir
16 ## sharedstatedir
17 ## localstatedir
18 ## infodir
19 ## mandir
20 ## includedir
21 #
22 # If '--prefix' is not supplied, it defaults to '/usr/local' unless 'defaultprefix' is defined *before*
23 # including the 'system' module.
24
 
25 set defaultprefix [get-define defaultprefix /usr/local]
26
27 module-options [subst -noc -nob {
28 host:host-alias => {a complete or partial cpu-vendor-opsys for the system where
29 the application will run (defaults to the same value as --build)}
@@ -45,12 +47,20 @@
47 localstatedir:
48 maintainer-mode=0
49 dependency-tracking=0
50 }]
51
52 # @check-feature name { script }
53 #
54 # defines feature '$name' to the return value of '$script',
55 # which should be 1 if found or 0 if not found.
56 #
57 # e.g. the following will define 'HAVE_CONST' to 0 or 1.
58 #
59 ## check-feature const {
60 ## cctest -code {const int _x = 0;}
61 ## }
62 proc check-feature {name code} {
63 msg-checking "Checking for $name..."
64 set r [uplevel 1 $code]
65 define-feature $name $r
66 if {$r} {
@@ -61,49 +71,54 @@
71 return $r
72 }
73
74 # @have-feature name ?default=0?
75 #
76 # Returns the value of feature '$name' if defined, or '$default' if not.
77 #
78 # See 'feature-define-name' for how the "feature" name
79 # is translated into the "define" name.
80 #
81 proc have-feature {name {default 0}} {
82 get-define [feature-define-name $name] $default
83 }
84
85 # @define-feature name ?value=1?
86 #
87 # Sets the feature 'define' to '$value'.
88 #
89 # See 'feature-define-name' for how the "feature" name
90 # is translated into the "define" name.
91 #
92 proc define-feature {name {value 1}} {
93 define [feature-define-name $name] $value
94 }
95
96 # @feature-checked name
97 #
98 # Returns 1 if feature '$name' has been checked, whether true or not.
99 #
100 proc feature-checked {name} {
101 is-defined [feature-define-name $name]
102 }
103
104 # @feature-define-name name ?prefix=HAVE_?
105 #
106 # Converts a "feature" name to the corresponding "define",
107 # e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
108 #
109 # Converts '*' to 'P' and all non-alphanumeric to underscore.
110 #
111 proc feature-define-name {name {prefix HAVE_}} {
112 string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
113 }
114
115 # @write-if-changed filename contents ?script?
116 #
117 # If '$filename' doesn't exist, or it's contents are different to '$contents',
118 # the file is written and '$script' is evaluated.
119 #
120 # Otherwise a "file is unchanged" message is displayed.
121 proc write-if-changed {file buf {script {}}} {
122 set old [readfile $file ""]
123 if {$old eq $buf && [file exists $file]} {
124 msg-result "$file is unchanged"
@@ -113,37 +128,38 @@
128 }
129 }
130
131 # @make-template template ?outfile?
132 #
133 # Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
134 # (unless unchanged).
135 # If '$outfile' is blank/omitted, '$template' should end with '.in' which
136 # is removed to create the output file name.
137 #
138 # Each pattern of the form '@define@' is replaced with the corresponding
139 # "define", if it exists, or left unchanged if not.
140 #
141 # The special value '@srcdir@' is substituted with the relative
142 # path to the source directory from the directory where the output
143 # file is created, while the special value '@top_srcdir@' is substituted
144 # with the relative path to the top level source directory.
145 #
146 # Conditional sections may be specified as follows:
147 ## @if name == value
148 ## lines
149 ## @else
150 ## lines
151 ## @endif
152 #
153 # Where 'name' is a defined variable name and '@else' is optional.
154 # If the expression does not match, all lines through '@endif' are ignored.
155 #
156 # The alternative forms may also be used:
157 ## @if name
158 ## @if name != value
159 #
160 # Where the first form is true if the variable is defined, but not empty nor 0.
161 #
162 # Currently these expressions can't be nested.
163 #
164 proc make-template {template {out {}}} {
165 set infile [file join $::autosetup(srcdir) $template]
@@ -205,25 +221,25 @@
221 }
222 continue
223 }
224 lappend result $line
225 }
226 write-if-changed $out [string map $mapping [join $result \n]]\n {
227 msg-result "Created [relative-path $out] from [relative-path $template]"
228 }
229 }
230
231 # build/host tuples and cross-compilation prefix
232 set build [lindex [opt-val build] end]
233 define build_alias $build
234 if {$build eq ""} {
235 define build [config_guess]
236 } else {
237 define build [config_sub $build]
238 }
239
240 set host [lindex [opt-val host] end]
241 define host_alias $host
242 if {$host eq ""} {
243 define host [get-define build]
244 set cross ""
245 } else {
@@ -230,30 +246,42 @@
246 define host [config_sub $host]
247 set cross $host-
248 }
249 define cross [get-env CROSS $cross]
250
251 # build/host _cpu, _vendor and _os
252 foreach type {build host} {
253 set v [get-define $type]
254 if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
255 user-error "Invalid canonical $type: $v"
256 }
257 define ${type}_cpu $cpu
258 define ${type}_vendor $vendor
259 define ${type}_os $os
260 }
261
262 set prefix [lindex [opt-val prefix $defaultprefix] end]
263
264 # These are for compatibility with autoconf
265 define target [get-define host]
266 define prefix $prefix
267 define builddir $autosetup(builddir)
268 define srcdir $autosetup(srcdir)
269 define top_srcdir $autosetup(srcdir)
270 define abs_top_srcdir [file-normalize $autosetup(srcdir)]
271 define abs_top_builddir [file-normalize $autosetup(builddir)]
272
273 # autoconf supports all of these
274 set exec_prefix [lindex [opt-val exec-prefix $prefix] end]
275 define exec_prefix $exec_prefix
276 foreach {name defpath} {
277 bindir /bin
278 sbindir /sbin
279 libexecdir /libexec
280 libdir /lib
281 } {
282 define $name [lindex [opt-val $name $exec_prefix$defpath] end]
283 }
284 foreach {name defpath} {
285 datadir /share
286 sysconfdir /etc
287 sharedstatedir /com
@@ -260,11 +288,11 @@
288 localstatedir /var
289 infodir /share/info
290 mandir /share/man
291 includedir /include
292 } {
293 define $name [lindex [opt-val $name $prefix$defpath] end]
294 }
295
296 define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
297
298 # Windows vs. non-Windows
299
300 ELETED autosetup/test-tclsh
D autosetup/test-tclsh
-20
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -1,20 +0,0 @@
1
-# A small Tcl script to verify that the chosen
2
-# interpreter works. Sometimes we might e.g. pick up
3
-# an interpreter for a different arch.
4
-# Outputs the full path to the interpreter
5
-
6
-if {[catch {info version} version] == 0} {
7
- # This is Jim Tcl
8
- if {$version >= 0.72} {
9
- # Ensure that regexp works
10
- regexp (a.*?) a
11
- puts [info nameofexecutable]
12
- exit 0
13
- }
14
-} elseif {[catch {info tclversion} version] == 0} {
15
- if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
16
- puts [info nameofexecutable]
17
- exit 0
18
- }
19
-}
20
-exit 1
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -1,20 +0,0 @@
1 # A small Tcl script to verify that the chosen
2 # interpreter works. Sometimes we might e.g. pick up
3 # an interpreter for a different arch.
4 # Outputs the full path to the interpreter
5
6 if {[catch {info version} version] == 0} {
7 # This is Jim Tcl
8 if {$version >= 0.72} {
9 # Ensure that regexp works
10 regexp (a.*?) a
11 puts [info nameofexecutable]
12 exit 0
13 }
14 } elseif {[catch {info tclversion} version] == 0} {
15 if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
16 puts [info nameofexecutable]
17 exit 0
18 }
19 }
20 exit 1
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -1,20 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- autosetup/tmake.auto
+++ autosetup/tmake.auto
@@ -21,45 +21,34 @@
2121
cc-check-tools ar ranlib
2222
2323
set objdir [get-env BUILDDIR objdir]
2424
2525
make-config-header $objdir/include/autoconf.h
26
-make-tmake-settings $objdir/settings.conf {[A-Z]*}
26
+make-tmake-settings $objdir/settings.conf {[A-Z]*} *dir lib_*
2727
}
2828
2929
autosetup_check_create project.spec \
3030
{# Initial project.spec created by 'autosetup --init=tmake'
31
+
32
+tmake-require-version 0.7.3
3133
3234
# vim:set syntax=tcl:
3335
define? DESTDIR _install
3436
3537
# XXX If configure creates additional/different files than include/autoconf.h
3638
# that should be reflected here
37
-
38
-# We use [set AUTOREMAKE] here to avoid rebuilding settings.conf
39
-# if the AUTOREMAKE command changes
40
-Depends {settings.conf include/autoconf.h} auto.def -msg {note Configuring...} -do {
41
- run [set AUTOREMAKE] >$build/config.out
42
-} -onerror {puts [readfile $build/config.out]} -fatal
43
-Clean config.out
44
-DistClean --source config.log
45
-DistClean settings.conf include/autoconf.h
46
-
47
-# If not configured, configure with default options
48
-# Note that it is expected that configure will normally be run
49
-# separately. This is just a convenience for a host build
50
-define? AUTOREMAKE configure TOPBUILDDIR=$TOPBUILDDIR --conf=auto.def
51
-
52
-Load settings.conf
53
-
54
-# e.g. for up autoconf.h
39
+Autosetup include/autoconf.h
40
+
41
+# e.g. for autoconf.h
5542
IncludePaths include
5643
57
-ifconfig CONFIGURED
58
-
59
-# Hmmm, but should we turn off AutoSubDirs?
60
-#AutoSubDirs off
44
+ifconfig !CONFIGURED {
45
+ # Not configured, so don't process subdirs
46
+ AutoSubDirs off
47
+ # And don't process this file any further
48
+ ifconfig false
49
+}
6150
}
6251
6352
if {![file exists build.spec]} {
6453
puts "Note: I don't see build.spec. Try running: tmake --genie"
6554
}
6655
--- autosetup/tmake.auto
+++ autosetup/tmake.auto
@@ -21,45 +21,34 @@
21 cc-check-tools ar ranlib
22
23 set objdir [get-env BUILDDIR objdir]
24
25 make-config-header $objdir/include/autoconf.h
26 make-tmake-settings $objdir/settings.conf {[A-Z]*}
27 }
28
29 autosetup_check_create project.spec \
30 {# Initial project.spec created by 'autosetup --init=tmake'
 
 
31
32 # vim:set syntax=tcl:
33 define? DESTDIR _install
34
35 # XXX If configure creates additional/different files than include/autoconf.h
36 # that should be reflected here
37
38 # We use [set AUTOREMAKE] here to avoid rebuilding settings.conf
39 # if the AUTOREMAKE command changes
40 Depends {settings.conf include/autoconf.h} auto.def -msg {note Configuring...} -do {
41 run [set AUTOREMAKE] >$build/config.out
42 } -onerror {puts [readfile $build/config.out]} -fatal
43 Clean config.out
44 DistClean --source config.log
45 DistClean settings.conf include/autoconf.h
46
47 # If not configured, configure with default options
48 # Note that it is expected that configure will normally be run
49 # separately. This is just a convenience for a host build
50 define? AUTOREMAKE configure TOPBUILDDIR=$TOPBUILDDIR --conf=auto.def
51
52 Load settings.conf
53
54 # e.g. for up autoconf.h
55 IncludePaths include
56
57 ifconfig CONFIGURED
58
59 # Hmmm, but should we turn off AutoSubDirs?
60 #AutoSubDirs off
 
 
61 }
62
63 if {![file exists build.spec]} {
64 puts "Note: I don't see build.spec. Try running: tmake --genie"
65 }
66
--- autosetup/tmake.auto
+++ autosetup/tmake.auto
@@ -21,45 +21,34 @@
21 cc-check-tools ar ranlib
22
23 set objdir [get-env BUILDDIR objdir]
24
25 make-config-header $objdir/include/autoconf.h
26 make-tmake-settings $objdir/settings.conf {[A-Z]*} *dir lib_*
27 }
28
29 autosetup_check_create project.spec \
30 {# Initial project.spec created by 'autosetup --init=tmake'
31
32 tmake-require-version 0.7.3
33
34 # vim:set syntax=tcl:
35 define? DESTDIR _install
36
37 # XXX If configure creates additional/different files than include/autoconf.h
38 # that should be reflected here
39 Autosetup include/autoconf.h
40
41 # e.g. for autoconf.h
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42 IncludePaths include
43
44 ifconfig !CONFIGURED {
45 # Not configured, so don't process subdirs
46 AutoSubDirs off
47 # And don't process this file any further
48 ifconfig false
49 }
50 }
51
52 if {![file exists build.spec]} {
53 puts "Note: I don't see build.spec. Try running: tmake --genie"
54 }
55
--- autosetup/tmake.tcl
+++ autosetup/tmake.tcl
@@ -15,21 +15,21 @@
1515
1616
define CONFIGURED
1717
1818
# @make-tmake-settings outfile patterns ...
1919
#
20
-# Examines all defined variables which match the given patterns (defaults to "*")
20
+# Examines all defined variables which match the given patterns (defaults to '*')
2121
# and writes a tmake-compatible .conf file defining those variables.
22
-# For example, if ABC is "3 monkeys" and ABC matches a pattern, then the file will include:
22
+# For example, if 'ABC' is '"3 monkeys"' and 'ABC' matches a pattern, then the file will include:
2323
#
2424
## define ABC {3 monkeys}
2525
#
2626
# If the file would be unchanged, it is not written.
2727
#
2828
# Typical usage is:
2929
#
30
-# make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
30
+## make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
3131
proc make-tmake-settings {file args} {
3232
file mkdir [file dirname $file]
3333
set lines {}
3434
3535
if {[llength $args] == 0} {
3636
--- autosetup/tmake.tcl
+++ autosetup/tmake.tcl
@@ -15,21 +15,21 @@
15
16 define CONFIGURED
17
18 # @make-tmake-settings outfile patterns ...
19 #
20 # Examines all defined variables which match the given patterns (defaults to "*")
21 # and writes a tmake-compatible .conf file defining those variables.
22 # For example, if ABC is "3 monkeys" and ABC matches a pattern, then the file will include:
23 #
24 ## define ABC {3 monkeys}
25 #
26 # If the file would be unchanged, it is not written.
27 #
28 # Typical usage is:
29 #
30 # make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
31 proc make-tmake-settings {file args} {
32 file mkdir [file dirname $file]
33 set lines {}
34
35 if {[llength $args] == 0} {
36
--- autosetup/tmake.tcl
+++ autosetup/tmake.tcl
@@ -15,21 +15,21 @@
15
16 define CONFIGURED
17
18 # @make-tmake-settings outfile patterns ...
19 #
20 # Examines all defined variables which match the given patterns (defaults to '*')
21 # and writes a tmake-compatible .conf file defining those variables.
22 # For example, if 'ABC' is '"3 monkeys"' and 'ABC' matches a pattern, then the file will include:
23 #
24 ## define ABC {3 monkeys}
25 #
26 # If the file would be unchanged, it is not written.
27 #
28 # Typical usage is:
29 #
30 ## make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
31 proc make-tmake-settings {file args} {
32 file mkdir [file dirname $file]
33 set lines {}
34
35 if {[llength $args] == 0} {
36
+1 -1
--- configure
+++ configure
@@ -1,3 +1,3 @@
11
#!/bin/sh
22
dir="`dirname "$0"`/autosetup"
3
-WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
3
+WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
44
--- configure
+++ configure
@@ -1,3 +1,3 @@
1 #!/bin/sh
2 dir="`dirname "$0"`/autosetup"
3 WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
4
--- configure
+++ configure
@@ -1,3 +1,3 @@
1 #!/bin/sh
2 dir="`dirname "$0"`/autosetup"
3 WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
4

Keyboard Shortcuts

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