Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch jimtcl Excluding Merge-Ins
This is equivalent to a diff from 238b761afa to de9c2f08d7
2012-01-24
| ||
13:28 | Fix several blob leaks that can lead to out of memory conditions for very large push operations. Revise the order of error messages so that simple HTTP timeout produces a better diagnostic. The HTTP trace files need to be opened in binary mode. check-in: 1e39808853 user: mistachkin tags: trunk | |
2012-01-23
| ||
03:51 | Merge latest trunk changes into jimtcl branch. Lightly tested. Should allow xfer scripts to be written in Jim Tcl. Leaf check-in: de9c2f08d7 user: steveb tags: jimtcl | |
2012-01-22
| ||
06:59 | Revise previous commit: since the FOSSIL_ENABLE_TCL macro is used in source files as well as the Makefile itself, it cannot be initially set to an empty string in auto.def. check-in: 238b761afa user: mistachkin tags: trunk | |
06:52 | Make sure that autosetup ends up defining FOSSIL_ENABLE_TCL in the Makefile when necessary. check-in: 21555be397 user: mistachkin tags: trunk | |
2011-11-07
| ||
07:07 | fossil already provides compatibility wrappers for dirent and struct timeval check-in: 5905232d45 user: steveb tags: jimtcl | |
Changes to auto.def.
85 85 } 86 86 if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} { 87 87 user-error "zlib not found please install it or specify the location with --with-zlib" 88 88 } 89 89 90 90 set tclpath [opt-val with-tcl] 91 91 if {$tclpath ne ""} { 92 - # Note parse-tclconfig-sh is in autosetup/local.tcl 92 + # Note parse-tclconfig-sh is in autosetup/local.tcl 93 93 if {$tclpath eq "1"} { 94 94 # Use the system Tcl. Look in some likely places. 95 95 array set tclconfig [parse-tclconfig-sh /usr /usr/local /usr/share /opt/local] 96 - set msg "on your system" 97 - } else { 96 + set msg "on your system" 97 + } else { 98 98 array set tclconfig [parse-tclconfig-sh $tclpath] 99 - set msg "at $tclpath" 100 - } 101 - if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} { 102 - user-error "Cannot find Tcl $msg" 103 - } 104 - set cflags $tclconfig(TCL_INCLUDE_SPEC) 105 - set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)" 106 - cc-with [list -cflags $cflags -libs $libs] { 107 - if {![cc-check-functions Tcl_CreateInterp]} { 108 - user-error "Cannot find a usable Tcl $msg" 109 - } 110 - } 111 - set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL) 112 - msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)" 113 - define-append LIBS $libs 114 - define-append EXTRA_CFLAGS $cflags 115 - define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS) 99 + set msg "at $tclpath" 100 + } 101 + if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} { 102 + user-error "Cannot find Tcl $msg" 103 + } 104 + set cflags $tclconfig(TCL_INCLUDE_SPEC) 105 + set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)" 106 + cc-with [list -cflags $cflags -libs $libs] { 107 + if {![cc-check-functions Tcl_CreateInterp]} { 108 + user-error "Cannot find a usable Tcl $msg" 109 + } 110 + } 111 + set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL) 112 + msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)" 113 + define-append LIBS $libs 114 + define-append EXTRA_CFLAGS $cflags 115 + define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS) 116 116 117 117 define FOSSIL_ENABLE_TCL 118 118 } 119 119 120 120 # Helper for openssl checking 121 121 proc check-for-openssl {msg {cflags {}}} { 122 122 msg-checking "Checking for $msg..."
Changes to autosetup/README.autosetup.
1 -This is autosetup v0.6.2. See http://msteveb.github.com/autosetup/ 1 +This is autosetup v0.6.3. See http://msteveb.github.com/autosetup/
Changes to autosetup/autosetup.
1 1 #!/bin/sh 2 2 # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ 3 3 # All rights reserved 4 4 # vim:se syntax=tcl: 5 5 # \ 6 6 dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" 7 7 8 -set autosetup(version) 0.6.2 8 +set autosetup(version) 0.6.3 9 9 10 10 # Can be set to 1 to debug early-init problems 11 11 set autosetup(debug) 0 12 12 13 13 ################################################################## 14 14 # 15 15 # Main flow of control, option handling ................................................................................ 514 514 } 515 515 getenv $name $default 516 516 } 517 517 518 518 # @env-is-set name 519 519 # 520 520 # Returns 1 if the $name was specified on the command line or in the environment. 521 +# Note that an empty environment variable is not considered to be set. 521 522 # 522 523 proc env-is-set {name} { 523 524 if {[dict exists $::autosetup(cmdline) $name]} { 524 525 return 1 525 526 } 526 - info exists ::env($name) 527 + if {[getenv $name ""] ne ""} { 528 + return 1 529 + } 530 + return 0 527 531 } 528 532 529 533 # @readfile filename ?default=""? 530 534 # 531 535 # Return the contents of the file, without the trailing newline. 532 536 # If the doesn't exist or can't be read, returns $default. 533 537 # ................................................................................ 1539 1543 } 1540 1544 } elseif {$autosetup(iswin)} { 1541 1545 # On Windows, backslash convert all environment variables 1542 1546 # (Assume that Tcl does this for us) 1543 1547 proc getenv {name args} { 1544 1548 string map {\\ /} [env $name {*}$args] 1545 1549 } 1546 - # Jim uses system() for exec under mingw, so 1547 - # we need to fetch the output ourselves 1548 - proc exec-with-stderr {args} { 1549 - set tmpfile auto[format %04x [rand 10000]].tmp 1550 - set rc [catch [list exec {*}$args >$tmpfile 2>&1] result] 1551 - set result [readfile $tmpfile] 1552 - file delete $tmpfile 1553 - return -code $rc $result 1554 - } 1555 1550 } else { 1556 1551 # Jim on unix is simple 1557 1552 alias getenv env 1558 1553 } 1559 1554 1560 1555 # In case 'file normalize' doesn't exist 1561 1556 #
Changes to autosetup/cc-shared.tcl.
54 54 } 55 55 * { 56 56 # Generic Unix settings 57 57 define SH_LINKFLAGS -rdynamic 58 58 define SH_CFLAGS -fpic 59 59 define SH_LDFLAGS -shared 60 60 define SHOBJ_CFLAGS -fpic 61 - define SHOBJ_LDFLAGS "-shared -nostartfiles" 61 + define SHOBJ_LDFLAGS -shared 62 62 } 63 63 }
Changes to autosetup/cc.tcl.
370 370 } elseif {[llength $args] > 1} { 371 371 autosetup-error "usage: cc-with settings ?script?" 372 372 } else { 373 373 set save [cc-add-settings $settings] 374 374 set rc [catch {uplevel 1 [lindex $args 0]} result info] 375 375 cc-store-settings $save 376 376 if {$rc != 0} { 377 - return $result -code [dict get $info -code] 377 + return -code [dict get $info -code] $result 378 378 } 379 379 return $result 380 380 } 381 381 } 382 382 383 383 # @cctest ?settings? 384 384 #
Changes to autosetup/find-tclsh.
1 1 #!/bin/sh 2 2 # Looks for a suitable tclsh or jimsh in the PATH 3 3 # If not found, builds a bootstrap jimsh from source 4 4 d=`dirname "$0"` 5 +{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0 5 6 PATH="$PATH:$d" 6 -for tclsh in jimsh tclsh tclsh8.5 tclsh8.6 jimsh0; do 7 +for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do 7 8 { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0 8 9 done 9 10 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" 10 11 for cc in ${CC_FOR_BUILD:-cc} gcc; do 11 12 { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue 12 13 "$d/jimsh0" "$d/test-tclsh" && exit 0 13 14 done 14 15 echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." 15 16 echo false
Changes to autosetup/jimsh0.c.
more than 10,000 changes
Changes to autosetup/system.tcl.
224 224 define prefix $prefix 225 225 define builddir $autosetup(builddir) 226 226 define srcdir $autosetup(srcdir) 227 227 # Allow this to come from the environment 228 228 define top_srcdir [get-env top_srcdir [get-define srcdir]] 229 229 230 230 # autoconf supports all of these 231 -define exec_prefix [opt-val exec-prefix [get-env exec-prefix \${prefix}]] 231 +set exec_prefix [opt-val exec-prefix $prefix] 232 +define exec_prefix $exec_prefix 233 +foreach {name defpath} { 234 + bindir /bin 235 + sbindir /sbin 236 + libexecdir /libexec 237 + libdir /lib 238 +} { 239 + define $name [opt-val $name $exec_prefix$defpath] 240 +} 232 241 foreach {name defpath} { 233 - bindir \${exec_prefix}/bin 234 - sbindir \${exec_prefix}/sbin 235 - libexecdir \${exec_prefix}/libexec 236 - libdir \${exec_prefix}/lib 237 - datadir \${prefix}/share 238 - sysconfdir \${prefix}/etc 239 - sharedstatedir \${prefix}/com 240 - localstatedir \${prefix}/var 241 - infodir \${prefix}/share/info 242 - mandir \${prefix}/share/man 243 - includedir \${prefix}/include 242 + datadir /share 243 + sysconfdir /etc 244 + sharedstatedir /com 245 + localstatedir /var 246 + infodir /share/info 247 + mandir /share/man 248 + includedir /include 244 249 } { 245 - define $name [opt-val $name [get-env $name $defpath]] 250 + define $name [opt-val $name $prefix$defpath] 246 251 } 247 252 248 253 define SHELL [get-env SHELL [find-an-executable sh bash ksh]] 249 254 250 255 # Windows vs. non-Windows 251 256 switch -glob -- [get-define host] { 252 257 *-*-ming* - *-*-cygwin {
Changes to autosetup/test-tclsh.
1 1 # A small Tcl script to verify that the chosen 2 2 # interpreter works. Sometimes we might e.g. pick up 3 3 # an interpreter for a different arch. 4 4 # Outputs the full path to the interpreter 5 5 6 6 if {[catch {info version} version] == 0} { 7 7 # This is Jim Tcl 8 - if {$version >= 0.70} { 8 + if {$version >= 0.72} { 9 9 # Ensure that regexp works 10 10 regexp (a.*?) a 11 - 12 - # Older versions of jimsh may return a relative path for [info nameofexecutable] 13 - puts [file join [pwd] [info nameofexecutable]] 11 + puts [info nameofexecutable] 14 12 exit 0 15 13 } 16 14 } elseif {[catch {info tclversion} version] == 0} { 17 15 if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} { 18 16 puts [info nameofexecutable] 19 17 exit 0 20 18 } 21 19 } 22 20 exit 1
Added src/jim-config.h.
1 +#ifndef _JIM_CONFIG_H 2 +#define _JIM_CONFIG_H 3 +/*#undef HAVE_LONG_LONG*/ 4 +/*#undef JIM_UTF8*/ 5 +#endif
Added src/jim-win32compat.h.
1 +#ifndef JIM_WIN32COMPAT_H 2 +#define JIM_WIN32COMPAT_H 3 + 4 +/* Compatibility for Windows (mingw and msvc, not cygwin */ 5 + 6 +/* Note that at this point we don't yet have access to jimautoconf.h */ 7 +#if defined(_WIN32) || defined(WIN32) 8 + 9 +#define HAVE_DLOPEN 10 +void *dlopen(const char *path, int mode); 11 +int dlclose(void *handle); 12 +void *dlsym(void *handle, const char *symbol); 13 +char *dlerror(void); 14 + 15 +#ifdef _MSC_VER 16 +/* These are msvc vs gcc */ 17 + 18 +#if _MSC_VER >= 1000 19 + #pragma warning(disable:4146) 20 +#endif 21 + 22 +#include <limits.h> 23 +#define jim_wide _int64 24 +#ifndef LLONG_MAX 25 + #define LLONG_MAX 9223372036854775807I64 26 +#endif 27 +#ifndef LLONG_MIN 28 + #define LLONG_MIN (-LLONG_MAX - 1I64) 29 +#endif 30 +#define JIM_WIDE_MIN LLONG_MIN 31 +#define JIM_WIDE_MAX LLONG_MAX 32 +#define JIM_WIDE_MODIFIER "I64d" 33 +#define strcasecmp _stricmp 34 +#define strtoull _strtoui64 35 +#define snprintf _snprintf 36 + 37 +#include <io.h> 38 + 39 +#ifndef NO_TIMEVAL 40 +struct timeval { 41 + long tv_sec; 42 + long tv_usec; 43 +}; 44 +#endif 45 + 46 +int gettimeofday(struct timeval *tv, void *unused); 47 + 48 +#define HAVE_OPENDIR 49 +#ifndef NO_DIRENT 50 +struct dirent { 51 + char *d_name; 52 +}; 53 + 54 +typedef struct DIR { 55 + long handle; /* -1 for failed rewind */ 56 + struct _finddata_t info; 57 + struct dirent result; /* d_name null iff first time */ 58 + char *name; /* null-terminated char string */ 59 +} DIR; 60 + 61 +DIR *opendir(const char *name); 62 +int closedir(DIR *dir); 63 +struct dirent *readdir(DIR *dir); 64 +#endif 65 +#endif /* _MSC_VER */ 66 + 67 +#endif /* WIN32 */ 68 + 69 +#endif
Added src/jim.h.
1 +/* Jim - A small embeddable Tcl interpreter 2 + * 3 + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> 4 + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> 5 + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> 6 + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com 7 + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> 8 + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> 9 + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> 10 + * 11 + * Redistribution and use in source and binary forms, with or without 12 + * modification, are permitted provided that the following conditions 13 + * are met: 14 + * 15 + * 1. Redistributions of source code must retain the above copyright 16 + * notice, this list of conditions and the following disclaimer. 17 + * 2. Redistributions in binary form must reproduce the above 18 + * copyright notice, this list of conditions and the following 19 + * disclaimer in the documentation and/or other materials 20 + * provided with the distribution. 21 + * 22 + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY 23 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 + * 35 + * The views and conclusions contained in the software and documentation 36 + * are those of the authors and should not be interpreted as representing 37 + * official policies, either expressed or implied, of the Jim Tcl Project. 38 + * 39 + *--- Inline Header File Documentation --- 40 + * [By Duane Ellis, openocd@duaneellis.com, 8/18/8] 41 + * 42 + * Belief is "Jim" would greatly benifit if Jim Internals where 43 + * documented in some way - form whatever, and perhaps - the package: 44 + * 'doxygen' is the correct approach to do that. 45 + * 46 + * Details, see: http://www.stack.nl/~dimitri/doxygen/ 47 + * 48 + * To that end please follow these guide lines: 49 + * 50 + * (A) Document the PUBLIC api in the .H file. 51 + * 52 + * (B) Document JIM Internals, in the .C file. 53 + * 54 + * (C) Remember JIM is embedded in other packages, to that end do 55 + * not assume that your way of documenting is the right way, Jim's 56 + * public documentation should be agnostic, such that it is some 57 + * what agreeable with the "package" that is embedding JIM inside 58 + * of it's own doxygen documentation. 59 + * 60 + * (D) Use minimal Doxygen tags. 61 + * 62 + * This will be an "ongoing work in progress" for some time. 63 + **/ 64 + 65 +#ifndef __JIM__H 66 +#define __JIM__H 67 + 68 +#ifdef __cplusplus 69 +extern "C" { 70 +#endif 71 + 72 +#include <time.h> 73 +#include <limits.h> 74 +#include <stdio.h> /* for the FILE typedef definition */ 75 +#include <stdlib.h> /* In order to export the Jim_Free() macro */ 76 +#include <stdarg.h> /* In order to get type va_list */ 77 + 78 +/* ----------------------------------------------------------------------------- 79 + * System configuration 80 + * autoconf (configure) will set these 81 + * ---------------------------------------------------------------------------*/ 82 +#include <jim-win32compat.h> 83 + 84 +#ifndef HAVE_NO_AUTOCONF 85 +#include <jim-config.h> 86 +#endif 87 + 88 +/* ----------------------------------------------------------------------------- 89 + * Compiler specific fixes. 90 + * ---------------------------------------------------------------------------*/ 91 + 92 +/* Long Long type and related issues */ 93 +#ifndef jim_wide 94 +# ifdef HAVE_LONG_LONG 95 +# define jim_wide long long 96 +# ifndef LLONG_MAX 97 +# define LLONG_MAX 9223372036854775807LL 98 +# endif 99 +# ifndef LLONG_MIN 100 +# define LLONG_MIN (-LLONG_MAX - 1LL) 101 +# endif 102 +# define JIM_WIDE_MIN LLONG_MIN 103 +# define JIM_WIDE_MAX LLONG_MAX 104 +# else 105 +# define jim_wide long 106 +# define JIM_WIDE_MIN LONG_MIN 107 +# define JIM_WIDE_MAX LONG_MAX 108 +# endif 109 + 110 +/* ----------------------------------------------------------------------------- 111 + * LIBC specific fixes 112 + * ---------------------------------------------------------------------------*/ 113 + 114 +# ifdef HAVE_LONG_LONG 115 +# define JIM_WIDE_MODIFIER "lld" 116 +# else 117 +# define JIM_WIDE_MODIFIER "ld" 118 +# define strtoull strtoul 119 +# endif 120 +#endif 121 + 122 +#define UCHAR(c) ((unsigned char)(c)) 123 + 124 +/* ----------------------------------------------------------------------------- 125 + * Exported defines 126 + * ---------------------------------------------------------------------------*/ 127 + 128 +/* Jim version numbering: every version of jim is marked with a 129 + * successive integer number. This is version 0. The first 130 + * stable version will be 1, then 2, 3, and so on. */ 131 +#define JIM_VERSION 73 132 + 133 +#define JIM_OK 0 134 +#define JIM_ERR 1 135 +#define JIM_RETURN 2 136 +#define JIM_BREAK 3 137 +#define JIM_CONTINUE 4 138 +#define JIM_SIGNAL 5 139 +#define JIM_EXIT 6 140 +/* The following are internal codes and should never been seen/used */ 141 +#define JIM_EVAL 7 142 + 143 +#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */ 144 + 145 +/* Some function get an integer argument with flags to change 146 + * the behaviour. */ 147 +#define JIM_NONE 0 /* no flags set */ 148 +#define JIM_ERRMSG 1 /* set an error message in the interpreter. */ 149 + 150 +#define JIM_UNSHARED 4 /* Flag to Jim_GetVariable() */ 151 + 152 +/* Flags for Jim_SubstObj() */ 153 +#define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */ 154 +#define JIM_SUBST_NOCMD 2 /* don't perform command substitutions */ 155 +#define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */ 156 +#define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */ 157 + 158 +/* Unused arguments generate annoying warnings... */ 159 +#define JIM_NOTUSED(V) ((void) V) 160 + 161 +/* Flags for Jim_GetEnum() */ 162 +#define JIM_ENUM_ABBREV 2 /* Allow unambiguous abbreviation */ 163 + 164 +/* Flags used by API calls getting a 'nocase' argument. */ 165 +#define JIM_CASESENS 0 /* case sensitive */ 166 +#define JIM_NOCASE 1 /* no case */ 167 + 168 +/* Filesystem related */ 169 +#define JIM_PATH_LEN 1024 170 + 171 +/* Newline, some embedded system may need -DJIM_CRLF */ 172 +#ifdef JIM_CRLF 173 +#define JIM_NL "\r\n" 174 +#else 175 +#define JIM_NL "\n" 176 +#endif 177 + 178 +#define JIM_LIBPATH "auto_path" 179 +#define JIM_INTERACTIVE "tcl_interactive" 180 + 181 +/* ----------------------------------------------------------------------------- 182 + * Stack 183 + * ---------------------------------------------------------------------------*/ 184 + 185 +typedef struct Jim_Stack { 186 + int len; 187 + int maxlen; 188 + void **vector; 189 +} Jim_Stack; 190 + 191 +/* ----------------------------------------------------------------------------- 192 + * Hash table 193 + * ---------------------------------------------------------------------------*/ 194 + 195 +typedef struct Jim_HashEntry { 196 + const void *key; 197 + union { 198 + void *val; 199 + int intval; 200 + } u; 201 + struct Jim_HashEntry *next; 202 +} Jim_HashEntry; 203 + 204 +typedef struct Jim_HashTableType { 205 + unsigned int (*hashFunction)(const void *key); 206 + const void *(*keyDup)(void *privdata, const void *key); 207 + void *(*valDup)(void *privdata, const void *obj); 208 + int (*keyCompare)(void *privdata, const void *key1, const void *key2); 209 + void (*keyDestructor)(void *privdata, const void *key); 210 + void (*valDestructor)(void *privdata, void *obj); 211 +} Jim_HashTableType; 212 + 213 +typedef struct Jim_HashTable { 214 + Jim_HashEntry **table; 215 + const Jim_HashTableType *type; 216 + unsigned int size; 217 + unsigned int sizemask; 218 + unsigned int used; 219 + unsigned int collisions; 220 + void *privdata; 221 +} Jim_HashTable; 222 + 223 +typedef struct Jim_HashTableIterator { 224 + Jim_HashTable *ht; 225 + int index; 226 + Jim_HashEntry *entry, *nextEntry; 227 +} Jim_HashTableIterator; 228 + 229 +/* This is the initial size of every hash table */ 230 +#define JIM_HT_INITIAL_SIZE 16 231 + 232 +/* ------------------------------- Macros ------------------------------------*/ 233 +#define Jim_FreeEntryVal(ht, entry) \ 234 + if ((ht)->type->valDestructor) \ 235 + (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) 236 + 237 +#define Jim_SetHashVal(ht, entry, _val_) do { \ 238 + if ((ht)->type->valDup) \ 239 + entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ 240 + else \ 241 + entry->u.val = (_val_); \ 242 +} while(0) 243 + 244 +#define Jim_FreeEntryKey(ht, entry) \ 245 + if ((ht)->type->keyDestructor) \ 246 + (ht)->type->keyDestructor((ht)->privdata, (entry)->key) 247 + 248 +#define Jim_SetHashKey(ht, entry, _key_) do { \ 249 + if ((ht)->type->keyDup) \ 250 + entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ 251 + else \ 252 + entry->key = (_key_); \ 253 +} while(0) 254 + 255 +#define Jim_CompareHashKeys(ht, key1, key2) \ 256 + (((ht)->type->keyCompare) ? \ 257 + (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ 258 + (key1) == (key2)) 259 + 260 +#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) 261 + 262 +#define Jim_GetHashEntryKey(he) ((he)->key) 263 +#define Jim_GetHashEntryVal(he) ((he)->val) 264 +#define Jim_GetHashTableCollisions(ht) ((ht)->collisions) 265 +#define Jim_GetHashTableSize(ht) ((ht)->size) 266 +#define Jim_GetHashTableUsed(ht) ((ht)->used) 267 + 268 +/* ----------------------------------------------------------------------------- 269 + * Jim_Obj structure 270 + * ---------------------------------------------------------------------------*/ 271 + 272 +/* ----------------------------------------------------------------------------- 273 + * Jim object. This is mostly the same as Tcl_Obj itself, 274 + * with the addition of the 'prev' and 'next' pointers. 275 + * In Jim all the objects are stored into a linked list for GC purposes, 276 + * so that it's possible to access every object living in a given interpreter 277 + * sequentially. When an object is freed, it's moved into a different 278 + * linked list, used as object pool. 279 + * 280 + * The refcount of a freed object is always -1. 281 + * ---------------------------------------------------------------------------*/ 282 +typedef struct Jim_Obj { 283 + int refCount; /* reference count */ 284 + char *bytes; /* string representation buffer. NULL = no string repr. */ 285 + int length; /* number of bytes in 'bytes', not including the numterm. */ 286 + const struct Jim_ObjType *typePtr; /* object type. */ 287 + /* Internal representation union */ 288 + union { 289 + /* integer number type */ 290 + jim_wide wideValue; 291 + /* hashed object type value */ 292 + int hashValue; 293 + /* index type */ 294 + int indexValue; 295 + /* return code type */ 296 + int returnCode; 297 + /* double number type */ 298 + double doubleValue; 299 + /* Generic pointer */ 300 + void *ptr; 301 + /* Generic two pointers value */ 302 + struct { 303 + void *ptr1; 304 + void *ptr2; 305 + } twoPtrValue; 306 + /* Variable object */ 307 + struct { 308 + unsigned jim_wide callFrameId; 309 + struct Jim_Var *varPtr; 310 + } varValue; 311 + /* Command object */ 312 + struct { 313 + unsigned jim_wide procEpoch; 314 + struct Jim_Cmd *cmdPtr; 315 + } cmdValue; 316 + /* List object */ 317 + struct { 318 + struct Jim_Obj **ele; /* Elements vector */ 319 + int len; /* Length */ 320 + int maxLen; /* Allocated 'ele' length */ 321 + } listValue; 322 + /* String type */ 323 + struct { 324 + int maxLength; 325 + int charLength; /* utf-8 char length. -1 if unknown */ 326 + } strValue; 327 + /* Reference type */ 328 + struct { 329 + jim_wide id; 330 + struct Jim_Reference *refPtr; 331 + } refValue; 332 + /* Source type */ 333 + struct { 334 + struct Jim_Obj *fileNameObj; 335 + int lineNumber; 336 + } sourceValue; 337 + /* Dict substitution type */ 338 + struct { 339 + struct Jim_Obj *varNameObjPtr; 340 + struct Jim_Obj *indexObjPtr; 341 + } dictSubstValue; 342 + /* tagged binary type */ 343 + struct { 344 + unsigned char *data; 345 + size_t len; 346 + } binaryValue; 347 + /* Regular expression pattern */ 348 + struct { 349 + unsigned flags; 350 + void *compre; /* really an allocated (regex_t *) */ 351 + } regexpValue; 352 + struct { 353 + int line; 354 + int argc; 355 + } scriptLineValue; 356 + } internalRep; 357 + /* This are 8 or 16 bytes more for every object 358 + * but this is required for efficient garbage collection 359 + * of Jim references. */ 360 + struct Jim_Obj *prevObjPtr; /* pointer to the prev object. */ 361 + struct Jim_Obj *nextObjPtr; /* pointer to the next object. */ 362 +} Jim_Obj; 363 + 364 +/* Jim_Obj related macros */ 365 +#define Jim_IncrRefCount(objPtr) \ 366 + ++(objPtr)->refCount 367 +#define Jim_DecrRefCount(interp, objPtr) \ 368 + if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr) 369 +#define Jim_IsShared(objPtr) \ 370 + ((objPtr)->refCount > 1) 371 + 372 +/* This macro is used when we allocate a new object using 373 + * Jim_New...Obj(), but for some error we need to destroy it. 374 + * Instead to use Jim_IncrRefCount() + Jim_DecrRefCount() we 375 + * can just call Jim_FreeNewObj. To call Jim_Free directly 376 + * seems too raw, the object handling may change and we want 377 + * that Jim_FreeNewObj() can be called only against objects 378 + * that are belived to have refcount == 0. */ 379 +#define Jim_FreeNewObj Jim_FreeObj 380 + 381 +/* Free the internal representation of the object. */ 382 +#define Jim_FreeIntRep(i,o) \ 383 + if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \ 384 + (o)->typePtr->freeIntRepProc(i, o) 385 + 386 +/* Get the internal representation pointer */ 387 +#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr 388 + 389 +/* Set the internal representation pointer */ 390 +#define Jim_SetIntRepPtr(o, p) \ 391 + (o)->internalRep.ptr = (p) 392 + 393 +/* The object type structure. 394 + * There are four methods. 395 + * 396 + * - FreeIntRep is used to free the internal representation of the object. 397 + * Can be NULL if there is nothing to free. 398 + * - DupIntRep is used to duplicate the internal representation of the object. 399 + * If NULL, when an object is duplicated, the internalRep union is 400 + * directly copied from an object to another. 401 + * Note that it's up to the caller to free the old internal repr of the 402 + * object before to call the Dup method. 403 + * - UpdateString is used to create the string from the internal repr. 404 + * - setFromAny is used to convert the current object into one of this type. 405 + */ 406 + 407 +struct Jim_Interp; 408 + 409 +typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp, 410 + struct Jim_Obj *objPtr); 411 +typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, 412 + struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); 413 +typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); 414 + 415 +typedef struct Jim_ObjType { 416 + const char *name; /* The name of the type. */ 417 + Jim_FreeInternalRepProc *freeIntRepProc; 418 + Jim_DupInternalRepProc *dupIntRepProc; 419 + Jim_UpdateStringProc *updateStringProc; 420 + int flags; 421 +} Jim_ObjType; 422 + 423 +/* Jim_ObjType flags */ 424 +#define JIM_TYPE_NONE 0 /* No flags */ 425 +#define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */ 426 + 427 +/* Starting from 1 << 20 flags are reserved for private uses of 428 + * different calls. This way the same 'flags' argument may be used 429 + * to pass both global flags and private flags. */ 430 +#define JIM_PRIV_FLAG_SHIFT 20 431 + 432 +/* ----------------------------------------------------------------------------- 433 + * Call frame, vars, commands structures 434 + * ---------------------------------------------------------------------------*/ 435 + 436 +/* Call frame */ 437 +typedef struct Jim_CallFrame { 438 + unsigned jim_wide id; /* Call Frame ID. Used for caching. */ 439 + int level; /* Level of this call frame. 0 = global */ 440 + struct Jim_HashTable vars; /* Where local vars are stored */ 441 + struct Jim_HashTable *staticVars; /* pointer to procedure static vars */ 442 + struct Jim_CallFrame *parentCallFrame; 443 + Jim_Obj *const *argv; /* object vector of the current procedure call. */ 444 + int argc; /* number of args of the current procedure call. */ 445 + Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */ 446 + Jim_Obj *procBodyObjPtr; /* body object of the running procedure */ 447 + struct Jim_CallFrame *nextFramePtr; 448 + Jim_Obj *fileNameObj; /* file and line of caller of this proc (if available) */ 449 + int line; 450 +} Jim_CallFrame; 451 + 452 +/* The var structure. It just holds the pointer of the referenced 453 + * object. If linkFramePtr is not NULL the variable is a link 454 + * to a variable of name store on objPtr living on the given callframe 455 + * (this happens when the [global] or [upvar] command is used). 456 + * The interp in order to always know how to free the Jim_Obj associated 457 + * with a given variable because In Jim objects memory managment is 458 + * bound to interpreters. */ 459 +typedef struct Jim_Var { 460 + Jim_Obj *objPtr; 461 + struct Jim_CallFrame *linkFramePtr; 462 +} Jim_Var; 463 + 464 +/* The cmd structure. */ 465 +typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, 466 + Jim_Obj *const *argv); 467 +typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); 468 + 469 + 470 + 471 +/* A command is implemented in C if funcPtr is != NULL, otherwise 472 + * it's a Tcl procedure with the arglist and body represented by the 473 + * two objects referenced by arglistObjPtr and bodyoObjPtr. */ 474 +typedef struct Jim_Cmd { 475 + int inUse; /* Reference count */ 476 + int isproc; /* Is this a procedure? */ 477 + union { 478 + struct { 479 + /* native (C) command */ 480 + Jim_CmdProc cmdProc; /* The command implementation */ 481 + Jim_DelCmdProc delProc; /* Called when the command is deleted if != NULL */ 482 + void *privData; /* command-private data available via Jim_CmdPrivData() */ 483 + } native; 484 + struct { 485 + /* Tcl procedure */ 486 + Jim_Obj *argListObjPtr; 487 + Jim_Obj *bodyObjPtr; 488 + Jim_HashTable *staticVars; /* Static vars hash table. NULL if no statics. */ 489 + struct Jim_Cmd *prevCmd; /* Previous command defn if proc created 'local' */ 490 + int argListLen; /* Length of argListObjPtr */ 491 + int reqArity; /* Number of required parameters */ 492 + int optArity; /* Number of optional parameters */ 493 + int argsPos; /* Position of 'args', if specified, or -1 */ 494 + int upcall; /* True if proc is currently in upcall */ 495 + struct Jim_ProcArg { 496 + Jim_Obj *nameObjPtr; /* Name of this arg */ 497 + Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */ 498 + } *arglist; 499 + } proc; 500 + } u; 501 +} Jim_Cmd; 502 + 503 +/* Pseudo Random Number Generator State structure */ 504 +typedef struct Jim_PrngState { 505 + unsigned char sbox[256]; 506 + unsigned int i, j; 507 +} Jim_PrngState; 508 + 509 +/* ----------------------------------------------------------------------------- 510 + * Jim interpreter structure. 511 + * Fields similar to the real Tcl interpreter structure have the same names. 512 + * ---------------------------------------------------------------------------*/ 513 +typedef struct Jim_Interp { 514 + Jim_Obj *result; /* object returned by the last command called. */ 515 + int errorLine; /* Error line where an error occurred. */ 516 + Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */ 517 + int addStackTrace; /* > 0 If a level should be added to the stack trace */ 518 + int maxNestingDepth; /* Used for infinite loop detection. */ 519 + int returnCode; /* Completion code to return on JIM_RETURN. */ 520 + int returnLevel; /* Current level of 'return -level' */ 521 + int exitCode; /* Code to return to the OS on JIM_EXIT. */ 522 + long id; /* Hold unique id for various purposes */ 523 + int signal_level; /* A nesting level of catch -signal */ 524 + jim_wide sigmask; /* Bit mask of caught signals, or 0 if none */ 525 + int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); /* Set a result for the sigmask */ 526 + Jim_CallFrame *framePtr; /* Pointer to the current call frame */ 527 + Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */ 528 + struct Jim_HashTable commands; /* Commands hash table */ 529 + unsigned jim_wide procEpoch; /* Incremented every time the result 530 + of procedures names lookup caching 531 + may no longer be valid. */ 532 + unsigned jim_wide callFrameEpoch; /* Incremented every time a new 533 + callframe is created. This id is used for the 534 + 'ID' field contained in the Jim_CallFrame 535 + structure. */ 536 + int local; /* If 'local' is in effect, newly defined procs keep a reference to the old defn */ 537 + Jim_Obj *liveList; /* Linked list of all the live objects. */ 538 + Jim_Obj *freeList; /* Linked list of all the unused objects. */ 539 + Jim_Obj *currentScriptObj; /* Script currently in execution. */ 540 + Jim_Obj *emptyObj; /* Shared empty string object. */ 541 + Jim_Obj *trueObj; /* Shared true int object. */ 542 + Jim_Obj *falseObj; /* Shared false int object. */ 543 + unsigned jim_wide referenceNextId; /* Next id for reference. */ 544 + struct Jim_HashTable references; /* References hash table. */ 545 + jim_wide lastCollectId; /* reference max Id of the last GC 546 + execution. It's set to -1 while the collection 547 + is running as sentinel to avoid to recursive 548 + calls via the [collect] command inside 549 + finalizers. */ 550 + time_t lastCollectTime; /* unix time of the last GC execution */ 551 + Jim_Obj *stackTrace; /* Stack trace object. */ 552 + Jim_Obj *errorProc; /* Name of last procedure which returned an error */ 553 + Jim_Obj *unknown; /* Unknown command cache */ 554 + int unknown_called; /* The unknown command has been invoked */ 555 + int errorFlag; /* Set if an error occurred during execution. */ 556 + void *cmdPrivData; /* Used to pass the private data pointer to 557 + a command. It is set to what the user specified 558 + via Jim_CreateCommand(). */ 559 + 560 + struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ 561 + struct Jim_HashTable assocData; /* per-interp storage for use by packages */ 562 + Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ 563 + struct Jim_HashTable packages; /* Provided packages hash table */ 564 + Jim_Stack *localProcs; /* procs to be destroyed on end of evaluation */ 565 + Jim_Stack *loadHandles; /* handles of loaded modules [load] */ 566 +} Jim_Interp; 567 + 568 +/* Currently provided as macro that performs the increment. 569 + * At some point may be a real function doing more work. 570 + * The proc epoch is used in order to know when a command lookup 571 + * cached can no longer considered valid. */ 572 +#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ 573 +#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) 574 +#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) 575 +/* Note: Using trueObj and falseObj here makes some things slower...*/ 576 +#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) 577 +#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) 578 +#define Jim_GetResult(i) ((i)->result) 579 +#define Jim_CmdPrivData(i) ((i)->cmdPrivData) 580 +#define Jim_String(o) Jim_GetString((o), NULL) 581 + 582 +/* Note that 'o' is expanded only one time inside this macro, 583 + * so it's safe to use side effects. */ 584 +#define Jim_SetResult(i,o) do { \ 585 + Jim_Obj *_resultObjPtr_ = (o); \ 586 + Jim_IncrRefCount(_resultObjPtr_); \ 587 + Jim_DecrRefCount(i,(i)->result); \ 588 + (i)->result = _resultObjPtr_; \ 589 +} while(0) 590 + 591 +/* Use this for filehandles, etc. which need a unique id */ 592 +#define Jim_GetId(i) (++(i)->id) 593 + 594 +/* Reference structure. The interpreter pointer is held within privdata member in HashTable */ 595 +#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference 596 + string representation must be fixed length. */ 597 +typedef struct Jim_Reference { 598 + Jim_Obj *objPtr; 599 + Jim_Obj *finalizerCmdNamePtr; 600 + char tag[JIM_REFERENCE_TAGLEN+1]; 601 +} Jim_Reference; 602 + 603 +/* ----------------------------------------------------------------------------- 604 + * Exported API prototypes. 605 + * ---------------------------------------------------------------------------*/ 606 + 607 +/* Macros that are common for extensions and core. */ 608 +#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) 609 + 610 +/* The core includes real prototypes, extensions instead 611 + * include a global function pointer for every function exported. 612 + * Once the extension calls Jim_InitExtension(), the global 613 + * functon pointers are set to the value of the STUB table 614 + * contained in the Jim_Interp structure. 615 + * 616 + * This makes Jim able to load extensions even if it is statically 617 + * linked itself, and to load extensions compiled with different 618 + * versions of Jim (as long as the API is still compatible.) */ 619 + 620 +/* Macros are common for core and extensions */ 621 +#define Jim_FreeHashTableIterator(iter) Jim_Free(iter) 622 + 623 +#define JIM_EXPORT 624 + 625 +/* Memory allocation */ 626 +JIM_EXPORT void *Jim_Alloc (int size); 627 +JIM_EXPORT void *Jim_Realloc(void *ptr, int size); 628 +JIM_EXPORT void Jim_Free (void *ptr); 629 +JIM_EXPORT char * Jim_StrDup (const char *s); 630 +JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); 631 + 632 +/* environment */ 633 +JIM_EXPORT char **Jim_GetEnviron(void); 634 +JIM_EXPORT void Jim_SetEnviron(char **env); 635 + 636 +/* evaluation */ 637 +JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); 638 +/* in C code, you can do this and get better error messages */ 639 +/* Jim_EvalSource( interp, __FILE__, __LINE__ , "some tcl commands"); */ 640 +JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); 641 +/* Backwards compatibility */ 642 +#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S)) 643 + 644 +JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script); 645 +JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename); 646 +JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename); 647 +JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr); 648 +JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc, 649 + Jim_Obj *const *objv); 650 +JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, 651 + int objc, Jim_Obj *const *objv); 652 +#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov)) 653 +JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr, 654 + Jim_Obj **resObjPtrPtr, int flags); 655 + 656 +/* stack */ 657 +JIM_EXPORT void Jim_InitStack(Jim_Stack *stack); 658 +JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack); 659 +JIM_EXPORT int Jim_StackLen(Jim_Stack *stack); 660 +JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element); 661 +JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack); 662 +JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack); 663 +JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr)); 664 + 665 +/* hash table */ 666 +JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht, 667 + const Jim_HashTableType *type, void *privdata); 668 +JIM_EXPORT int Jim_ExpandHashTable (Jim_HashTable *ht, 669 + unsigned int size); 670 +JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key, 671 + void *val); 672 +JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht, 673 + const void *key, void *val); 674 +JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, 675 + const void *key); 676 +JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); 677 +JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, 678 + const void *key); 679 +JIM_EXPORT int Jim_ResizeHashTable (Jim_HashTable *ht); 680 +JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator 681 + (Jim_HashTable *ht); 682 +JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry 683 + (Jim_HashTableIterator *iter); 684 + 685 +/* objects */ 686 +JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); 687 +JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); 688 +JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); 689 +JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes, 690 + int length); 691 +JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, 692 + Jim_Obj *objPtr); 693 +JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, 694 + int *lenPtr); 695 +JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); 696 + 697 +/* string object */ 698 +JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp, 699 + const char *s, int len); 700 +JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, 701 + const char *s, int charlen); 702 +JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp, 703 + char *s, int len); 704 +JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr, 705 + const char *str, int len); 706 +JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr, 707 + Jim_Obj *appendObjPtr); 708 +JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp, 709 + Jim_Obj *objPtr, ...); 710 +JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr); 711 +JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr, 712 + Jim_Obj *objPtr, int nocase); 713 +JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp, 714 + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, 715 + Jim_Obj *lastObjPtr); 716 +JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp, 717 + Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv); 718 +JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr, 719 + Jim_Obj *fmtObjPtr, int flags); 720 +JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, 721 + Jim_Obj *objPtr, const char *str); 722 +JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, 723 + Jim_Obj *secondObjPtr, int nocase); 724 +JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); 725 + 726 +/* reference object */ 727 +JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, 728 + Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); 729 +JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp, 730 + Jim_Obj *objPtr); 731 +JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr); 732 +JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr); 733 + 734 +/* interpreter */ 735 +JIM_EXPORT Jim_Interp * Jim_CreateInterp (void); 736 +JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i); 737 +JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp); 738 +JIM_EXPORT const char *Jim_ReturnCode(int code); 739 +JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...); 740 + 741 +/* commands */ 742 +JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); 743 +JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, 744 + const char *cmdName, Jim_CmdProc cmdProc, void *privData, 745 + Jim_DelCmdProc delProc); 746 +JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, 747 + const char *cmdName); 748 +JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, 749 + const char *oldName, const char *newName); 750 +JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, 751 + Jim_Obj *objPtr, int flags); 752 +JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, 753 + Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); 754 +JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, 755 + const char *name, Jim_Obj *objPtr); 756 +JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp, 757 + const char *name, Jim_Obj *objPtr); 758 +JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, 759 + const char *name, const char *val); 760 +JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, 761 + Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, 762 + Jim_CallFrame *targetCallFrame); 763 +JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, 764 + Jim_Obj *nameObjPtr, int flags); 765 +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, 766 + Jim_Obj *nameObjPtr, int flags); 767 +JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, 768 + const char *name, int flags); 769 +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp, 770 + const char *name, int flags); 771 +JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp, 772 + Jim_Obj *nameObjPtr, int flags); 773 + 774 +/* call frame */ 775 +JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, 776 + Jim_Obj *levelObjPtr); 777 + 778 +/* garbage collection */ 779 +JIM_EXPORT int Jim_Collect (Jim_Interp *interp); 780 +JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp); 781 + 782 +/* index object */ 783 +JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr, 784 + int *indexPtr); 785 + 786 +/* list object */ 787 +JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp, 788 + Jim_Obj *const *elements, int len); 789 +JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp, 790 + Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec); 791 +JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp, 792 + Jim_Obj *listPtr, Jim_Obj *objPtr); 793 +JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp, 794 + Jim_Obj *listPtr, Jim_Obj *appendListPtr); 795 +JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr); 796 +JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt, 797 + int listindex, Jim_Obj **objPtrPtr, int seterr); 798 +JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp, 799 + Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, 800 + Jim_Obj *newObjPtr); 801 +JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc, 802 + Jim_Obj *const *objv); 803 + 804 +/* dict object */ 805 +JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp, 806 + Jim_Obj *const *elements, int len); 807 +JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr, 808 + Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags); 809 +JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp, 810 + Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, 811 + Jim_Obj **objPtrPtr, int flags); 812 +JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, 813 + Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, 814 + Jim_Obj *newObjPtr, int flags); 815 +JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, 816 + Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); 817 +JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, 818 + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); 819 +JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); 820 +JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); 821 + 822 +/* return code object */ 823 +JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, 824 + int *intPtr); 825 + 826 +/* expression object */ 827 +JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, 828 + Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); 829 +JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, 830 + Jim_Obj *exprObjPtr, int *boolPtr); 831 + 832 +/* integer object */ 833 +JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, 834 + jim_wide *widePtr); 835 +JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, 836 + long *longPtr); 837 +#define Jim_NewWideObj Jim_NewIntObj 838 +JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, 839 + jim_wide wideValue); 840 + 841 +/* double object */ 842 +JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, 843 + double *doublePtr); 844 +JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, 845 + double doubleValue); 846 +JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); 847 + 848 +/* shared strings */ 849 +JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp, 850 + const char *str); 851 +JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp, 852 + const char *str); 853 + 854 +/* commands utilities */ 855 +JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, 856 + Jim_Obj *const *argv, const char *msg); 857 +JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, 858 + const char * const *tablePtr, int *indexPtr, const char *name, int flags); 859 +JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len, 860 + char *stateCharPtr); 861 +/** 862 + * Find a matching name in the array of the given length. 863 + * 864 + * NULL entries are ignored. 865 + * 866 + * Returns the matching index if found, or -1 if not. 867 + */ 868 +JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); 869 + 870 +/* package utilities */ 871 +typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); 872 +JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); 873 +JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, 874 + Jim_InterpDeleteProc *delProc, void *data); 875 +JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); 876 + 877 +/* Packages C API */ 878 +/* jim-package.c */ 879 +JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, 880 + const char *name, const char *ver, int flags); 881 +JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, 882 + const char *name, int flags); 883 + 884 +/* error messages */ 885 +JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); 886 + 887 +/* interactive mode */ 888 +JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); 889 + 890 +/* Misc */ 891 +JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); 892 +JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); 893 + 894 +/* jim-load.c */ 895 +JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); 896 +JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); 897 + 898 +/* jim-aio.c */ 899 +JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); 900 + 901 + 902 +/* type inspection - avoid where possible */ 903 +JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); 904 +JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); 905 + 906 +#ifdef __cplusplus 907 +} 908 +#endif 909 + 910 +#endif /* __JIM__H */ 911 + 912 +/* 913 + * Local Variables: *** 914 + * c-basic-offset: 4 *** 915 + * tab-width: 4 *** 916 + * End: *** 917 + */
Changes to src/main.c.
24 24 #include <time.h> 25 25 #include <fcntl.h> 26 26 #include <sys/types.h> 27 27 #include <sys/stat.h> 28 28 #include <stdlib.h> /* atexit() */ 29 29 30 30 #if INTERFACE 31 +#include <jim.h> 32 + 31 33 #ifdef FOSSIL_ENABLE_JSON 32 34 # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ 33 35 # include "json_detail.h" 34 36 #endif 35 37 #ifdef FOSSIL_ENABLE_TCL 36 38 #include "tcl.h" 37 39 #endif ................................................................................ 125 127 int iErrPriority; /* Priority of current error message */ 126 128 char *zErrMsg; /* Text of an error message */ 127 129 int sslNotAvailable; /* SSL is not available. Do not redirect to https: */ 128 130 Blob cgiIn; /* Input to an xfer www method */ 129 131 int cgiOutput; /* Write error and status messages to CGI */ 130 132 int xferPanic; /* Write error messages in XFER protocol */ 131 133 int fullHttpReply; /* True for full HTTP reply. False for CGI reply */ 132 - Th_Interp *interp; /* The TH1 interpreter */ 134 + Jim_Interp *interp; /* The script interpreter */ 133 135 FILE *httpIn; /* Accept HTTP input from here */ 134 136 FILE *httpOut; /* Send HTTP output here */ 135 137 int xlinkClusterOnly; /* Set when cloning. Only process clusters */ 136 138 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ 137 139 int *aCommitFile; /* Array of files to be committed */ 138 140 int markPrivate; /* All new artifacts are private if true */ 139 141 int clockSkewSeen; /* True if clocks on client and server out of sync */ ................................................................................ 176 178 177 179 /* For defense against Cross-site Request Forgery attacks */ 178 180 char zCsrfToken[12]; /* Value of the anti-CSRF token */ 179 181 int okCsrf; /* Anti-CSRF token is present and valid */ 180 182 181 183 int parseCnt[10]; /* Counts of artifacts parsed */ 182 184 FILE *fDebug; /* Write debug information here, if the file exists */ 183 - int thTrace; /* True to enable TH1 debugging output */ 184 - Blob thLog; /* Text of the TH1 debugging output */ 185 + int thTrace; /* True to enable script debugging output */ 186 + Blob thLog; /* Text of the script debugging output */ 185 187 186 188 int isHome; /* True if rendering the "home" page */ 187 189 188 190 /* Storage for the aux() and/or option() SQL function arguments */ 189 191 int nAux; /* Number of distinct aux() or option() values */ 190 192 const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */ 191 193 char *azAuxParam[MX_AUX]; /* Param of each aux() or option() value */
Changes to src/main.mk.
345 345 # The FOSSIL_ENABLE_TCL variable may be undefined, set to 0, or set to 1. 346 346 # If it is set to 1, then we need to build the Tcl integration code and 347 347 # link to the Tcl library. 348 348 TCL_OBJ.0 = 349 349 TCL_OBJ.1 = $(OBJDIR)/th_tcl.o 350 350 TCL_OBJ. = $(TCL_OBJ.0) 351 351 352 -EXTRAOBJ = $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o $(TCL_OBJ.$(FOSSIL_ENABLE_TCL)) $(OBJDIR)/cson_amalgamation.o 352 +EXTRAOBJ = $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) $(OBJDIR)/shell.o $(OBJDIR)/jimtcl.o $(TCL_OBJ.$(FOSSIL_ENABLE_TCL)) $(OBJDIR)/cson_amalgamation.o 353 353 354 354 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) 355 355 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) 356 356 357 357 # This rule prevents make from using its default rules to try build 358 358 # an executable named "manifest" out of the file named "manifest.c" 359 359 # ................................................................................ 363 363 clean: 364 364 rm -rf $(OBJDIR)/* $(APPNAME) 365 365 366 366 367 367 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 368 368 $(OBJDIR)/mkindex $(TRANS_SRC) >$@ 369 369 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 370 - $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 370 + $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/jim.h $(OBJDIR)/VERSION.h 371 371 touch $(OBJDIR)/headers 372 372 $(OBJDIR)/headers: Makefile 373 373 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h 374 374 Makefile: 375 375 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate 376 376 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c 377 377 ................................................................................ 1038 1038 1039 1039 $(OBJDIR)/th.o: $(SRCDIR)/th.c 1040 1040 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o 1041 1041 1042 1042 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c 1043 1043 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o 1044 1044 1045 +$(OBJDIR)/jimtcl.o: $(SRCDIR)/../autosetup/jimsh0.c 1046 + $(XTCC) -I$(SRCDIR) -DJIM_BOOTSTRAP_LIB_ONLY -c $(SRCDIR)/../autosetup/jimsh0.c -o $(OBJDIR)/jimtcl.o 1047 + 1045 1048 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c 1046 1049 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o 1047 1050 1048 1051 1049 1052 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c 1050 1053 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE 1051 1054
Changes to src/makemake.tcl.
221 221 TCL_OBJ.0 = 222 222 TCL_OBJ.1 = $(OBJDIR)/th_tcl.o 223 223 TCL_OBJ. = $(TCL_OBJ.0) 224 224 225 225 EXTRAOBJ = \ 226 226 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \ 227 227 $(OBJDIR)/shell.o \ 228 - $(OBJDIR)/th.o \ 229 - $(OBJDIR)/th_lang.o \ 228 + $(OBJDIR)/jimtcl.o \ 230 229 $(TCL_OBJ.$(FOSSIL_ENABLE_TCL)) \ 231 230 $(OBJDIR)/cson_amalgamation.o 232 231 233 232 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) 234 233 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) 235 234 236 235 # This rule prevents make from using its default rules to try build ................................................................................ 246 245 247 246 set mhargs {} 248 247 foreach s [lsort $src] { 249 248 append mhargs " \$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h" 250 249 set extra_h($s) {} 251 250 } 252 251 append mhargs " \$(SRCDIR)/sqlite3.h" 253 -append mhargs " \$(SRCDIR)/th.h" 252 +append mhargs " \$(SRCDIR)/jim.h" 254 253 #append mhargs " \$(SRCDIR)/cson_amalgamation.h" 255 254 append mhargs " \$(OBJDIR)/VERSION.h" 256 255 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex" 257 256 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@" 258 257 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h" 259 258 writeln "\t\$(OBJDIR)/makeheaders $mhargs" 260 259 writeln "\ttouch \$(OBJDIR)/headers" ................................................................................ 289 288 290 289 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c" 291 290 writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n" 292 291 293 292 writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c" 294 293 writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n" 295 294 295 +writeln "\$(OBJDIR)/jimtcl.o:\t\$(SRCDIR)/../autosetup/jimsh0.c" 296 +writeln "\t\$(XTCC) -I\$(SRCDIR) -DJIM_BOOTSTRAP_LIB_ONLY -c \$(SRCDIR)/../autosetup/jimsh0.c -o \$(OBJDIR)/jimtcl.o\n" 297 + 296 298 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c" 297 299 writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n" 298 300 299 301 set opt {} 300 302 writeln { 301 303 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c 302 304 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE ................................................................................ 569 571 570 572 set mhargs {} 571 573 foreach s [lsort $src] { 572 574 append mhargs " \$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h" 573 575 set extra_h($s) {} 574 576 } 575 577 append mhargs " \$(SRCDIR)/sqlite3.h" 576 -append mhargs " \$(SRCDIR)/th.h" 578 +append mhargs " \$(SRCDIR)/jim.h" 577 579 append mhargs " \$(OBJDIR)/VERSION.h" 578 580 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex" 579 581 writeln "\t\$(MKINDEX) \$(TRANS_SRC) >$@" 580 582 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h" 581 583 writeln "\t\$(MAKEHEADERS) $mhargs" 582 584 writeln "\techo Done >\$(OBJDIR)/headers" 583 585 writeln "" ................................................................................ 761 763 writeln "\t+translate\$E \$** > \$@\n" 762 764 } 763 765 764 766 writeln -nonewline "headers: makeheaders\$E page_index.h VERSION.h\n\t +makeheaders\$E " 765 767 foreach s [lsort $src] { 766 768 writeln -nonewline "${s}_.c:$s.h " 767 769 } 768 -writeln "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h" 770 +writeln "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\jim.h VERSION.h" 771 +writeln "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\jim.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h" 769 772 writeln "\t@copy /Y nul: headers" 770 773 771 774 close $output_file 772 775 # 773 776 # End of the win/Makefile.dmc output 774 777 ############################################################################## 775 778 ############################################################################## ................................................................................ 917 920 writeln "\ttranslate\$E \$** > \$@\n" 918 921 } 919 922 920 923 writeln -nonewline "headers: makeheaders\$E page_index.h VERSION.h\n\tmakeheaders\$E " 921 924 foreach s [lsort $src] { 922 925 writeln -nonewline "${s}_.c:$s.h " 923 926 } 924 -writeln "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h" 927 +writeln "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\jim.h VERSION.h \$(SRCDIR)\\cson_amalgamation.h" 925 928 writeln "\t@copy /Y nul: headers" 926 929 927 930 928 931 close $output_file 929 932 # 930 933 # End of the win/Makefile.msc output 931 934 ############################################################################## ................................................................................ 1082 1085 mkindex.exe $(TRANSLATEDSRC) >$@ 1083 1086 1084 1087 # extracting version info from manifest 1085 1088 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION 1086 1089 version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@ 1087 1090 1088 1091 # generate the simplified headers 1089 -headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h 1090 - makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h 1092 +headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/jim.h VERSION.h 1093 + makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/jim.h VERSION.h 1091 1094 echo Done >$@ 1092 1095 1093 1096 # compile C sources with relevant options 1094 1097 1095 1098 $(TRANSLATEDOBJ): %_.obj: %_.c %.h 1096 1099 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 1097 1100 1098 1101 $(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h 1099 1102 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@" 1100 1103 1101 1104 $(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c 1102 1105 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@" 1103 1106 1104 -$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h 1107 +$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)jim.h 1105 1108 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 1106 1109 1107 1110 $(ZLIBOBJ): %.obj: $(ZLIBSRCDIR)%.c 1108 1111 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 1109 1112 1110 1113 # create the windows resource with icon and version info 1111 1114 $(RESOURCE): %.res: ../win/%.rc ../win/*.ico
Changes to src/name.c.
424 424 } 425 425 db_finalize(&q); 426 426 db_prepare(&q, 427 427 "SELECT type, datetime(mtime,'localtime')," 428 428 " coalesce(euser,user), coalesce(ecomment,comment)" 429 429 " FROM event WHERE objid=%d", rid); 430 430 if( db_step(&q)==SQLITE_ROW ){ 431 - const char *zType; 431 + const char *zType = 0; 432 432 switch( db_column_text(&q,0)[0] ){ 433 433 case 'c': zType = "Check-in"; break; 434 434 case 'w': zType = "Wiki-edit"; break; 435 435 case 'e': zType = "Event"; break; 436 436 case 't': zType = "Ticket-change"; break; 437 437 case 'g': zType = "Tag-change"; break; 438 438 default: zType = "Unknown"; break;
Deleted src/th.c.
1 - 2 -/* 3 -** The implementation of the TH core. This file contains the parser, and 4 -** the implementation of the interface in th.h. 5 -*/ 6 - 7 -#include "th.h" 8 -#include <string.h> 9 -#include <assert.h> 10 - 11 -typedef struct Th_Command Th_Command; 12 -typedef struct Th_Frame Th_Frame; 13 -typedef struct Th_Variable Th_Variable; 14 - 15 -/* 16 -** Interpreter structure. 17 -*/ 18 -struct Th_Interp { 19 - Th_Vtab *pVtab; /* Copy of the argument passed to Th_CreateInterp() */ 20 - char *zResult; /* Current interpreter result (Th_Malloc()ed) */ 21 - int nResult; /* number of bytes in zResult */ 22 - Th_Hash *paCmd; /* Table of registered commands */ 23 - Th_Frame *pFrame; /* Current execution frame */ 24 - int isListMode; /* True if thSplitList() should operate in "list" mode */ 25 -}; 26 - 27 -/* 28 -** Each TH command registered using Th_CreateCommand() is represented 29 -** by an instance of the following structure stored in the Th_Interp.paCmd 30 -** hash-table. 31 -*/ 32 -struct Th_Command { 33 - int (*xProc)(Th_Interp *, void *, int, const char **, int *); 34 - void *pContext; 35 - void (*xDel)(Th_Interp *, void *); 36 -}; 37 - 38 -/* 39 -** Each stack frame (variable scope) is represented by an instance 40 -** of this structure. Variable values set using the Th_SetVar command 41 -** are stored in the Th_Frame.paVar hash table member of the associated 42 -** stack frame object. 43 -** 44 -** When an interpreter is created, a single Th_Frame structure is also 45 -** allocated - the global variable scope. Th_Interp.pFrame (the current 46 -** interpreter frame) is initialised to point to this Th_Frame. It is 47 -** not deleted for the lifetime of the interpreter (because the global 48 -** frame never goes out of scope). 49 -** 50 -** New stack frames are created by the Th_InFrame() function. Before 51 -** invoking its callback function, Th_InFrame() allocates a new Th_Frame 52 -** structure with pCaller set to the current frame (Th_Interp.pFrame), 53 -** and sets the current frame to the new frame object. After the callback 54 -** has been invoked, the allocated Th_Frame is deleted and the value 55 -** of the current frame pointer restored. 56 -** 57 -** By default, the Th_SetVar(), Th_UnsetVar() and Th_GetVar() functions 58 -** access variable values in the current frame. If they need to access 59 -** the global frame, they do so by traversing the pCaller pointer list. 60 -** Likewise, the Th_LinkVar() function uses the pCaller pointers to 61 -** link to variables located in the global or other stack frames. 62 -*/ 63 -struct Th_Frame { 64 - Th_Hash *paVar; /* Variables defined in this scope */ 65 - Th_Frame *pCaller; /* Calling frame */ 66 -}; 67 - 68 -/* 69 -** This structure represents a value assigned to a th1 variable. 70 -** 71 -** The Th_Frame.paVar hash table maps from variable name (a th1 string) 72 -** to a pointer to an instance of the following structure. More than 73 -** one hash table entry may map to a single structure if variable 74 -** links have been created using Th_LinkVar(). The number of references 75 -** is stored in Th_Variable.nRef. 76 -** 77 -** For scalar variables, Th_Variable.zData is never 0. Th_Variable.nData 78 -** stores the number of bytes in the value pointed to by zData. 79 -** 80 -** For an array variable, Th_Variable.zData is 0 and pHash points to 81 -** a hash table mapping between array key name (a th1 string) and 82 -** a the pointer to the Th_Variable structure holding the scalar 83 -** value. 84 -*/ 85 -struct Th_Variable { 86 - int nRef; /* Number of references to this structure */ 87 - int nData; /* Number of bytes at Th_Variable.zData */ 88 - char *zData; /* Data for scalar variables */ 89 - Th_Hash *pHash; /* Data for array variables */ 90 -}; 91 - 92 -/* 93 -** Hash table API: 94 -*/ 95 -#define TH_HASHSIZE 257 96 -struct Th_Hash { 97 - Th_HashEntry *a[TH_HASHSIZE]; 98 -}; 99 - 100 -static int thEvalLocal(Th_Interp *, const char *, int); 101 -static int thSplitList(Th_Interp*, const char*, int, char***, int **, int*); 102 - 103 -static int thHexdigit(char c); 104 -static int thEndOfLine(const char *, int); 105 - 106 -static int thPushFrame(Th_Interp*, Th_Frame*); 107 -static void thPopFrame(Th_Interp*); 108 - 109 -static void thFreeVariable(Th_HashEntry*, void*); 110 -static void thFreeCommand(Th_HashEntry*, void*); 111 - 112 -/* 113 -** The following are used by both the expression and language parsers. 114 -** Given that the start of the input string (z, n) is a language 115 -** construct of the relevant type (a command enclosed in [], an escape 116 -** sequence etc.), these functions determine the number of bytes 117 -** of the input consumed by the construct. For example: 118 -** 119 -** int nByte; 120 -** thNextCommand(interp, "[expr $a+1] $nIter", 18, &nByte); 121 -** 122 -** results in variable nByte being set to 11. Or, 123 -** 124 -** thNextVarname(interp, "$a+1", 4, &nByte); 125 -** 126 -** results in nByte being set to 2. 127 -*/ 128 -static int thNextCommand(Th_Interp*, const char *z, int n, int *pN); 129 -static int thNextEscape (Th_Interp*, const char *z, int n, int *pN); 130 -static int thNextVarname(Th_Interp*, const char *z, int n, int *pN); 131 -static int thNextNumber (Th_Interp*, const char *z, int n, int *pN); 132 -static int thNextSpace (Th_Interp*, const char *z, int n, int *pN); 133 - 134 -/* 135 -** Given that the input string (z, n) contains a language construct of 136 -** the relevant type (a command enclosed in [], an escape sequence 137 -** like "\xFF" or a variable reference like "${varname}", perform 138 -** substitution on the string and store the resulting string in 139 -** the interpreter result. 140 -*/ 141 -static int thSubstCommand(Th_Interp*, const char *z, int n); 142 -static int thSubstEscape (Th_Interp*, const char *z, int n); 143 -static int thSubstVarname(Th_Interp*, const char *z, int n); 144 - 145 -/* 146 -** Given that there is a th1 word located at the start of the input 147 -** string (z, n), determine the length in bytes of that word. If the 148 -** isCmd argument is non-zero, then an unescaped ";" byte not 149 -** located inside of a block or quoted string is considered to mark 150 -** the end of the word. 151 -*/ 152 -static int thNextWord(Th_Interp*, const char *z, int n, int *pN, int isCmd); 153 - 154 -/* 155 -** Perform substitution on the word contained in the input string (z, n). 156 -** Store the resulting string in the interpreter result. 157 -*/ 158 -static int thSubstWord(Th_Interp*, const char *z, int n); 159 - 160 -/* 161 -** The Buffer structure and the thBufferXXX() functions are used to make 162 -** memory allocation easier when building up a result. 163 -*/ 164 -struct Buffer { 165 - char *zBuf; 166 - int nBuf; 167 - int nBufAlloc; 168 -}; 169 -typedef struct Buffer Buffer; 170 -static int thBufferWrite(Th_Interp *interp, Buffer *, const char *, int); 171 -static void thBufferInit(Buffer *); 172 -static void thBufferFree(Th_Interp *interp, Buffer *); 173 - 174 -/* 175 -** Append nAdd bytes of content copied from zAdd to the end of buffer 176 -** pBuffer. If there is not enough space currently allocated, resize 177 -** the allocation to make space. 178 -*/ 179 -static int thBufferWrite( 180 - Th_Interp *interp, 181 - Buffer *pBuffer, 182 - const char *zAdd, 183 - int nAdd 184 -){ 185 - int nReq; 186 - 187 - if( nAdd<0 ){ 188 - nAdd = th_strlen(zAdd); 189 - } 190 - nReq = pBuffer->nBuf+nAdd+1; 191 - 192 - if( nReq>pBuffer->nBufAlloc ){ 193 - char *zNew; 194 - int nNew; 195 - 196 - nNew = nReq*2; 197 - zNew = (char *)Th_Malloc(interp, nNew); 198 - memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf); 199 - Th_Free(interp, pBuffer->zBuf); 200 - pBuffer->nBufAlloc = nNew; 201 - pBuffer->zBuf = zNew; 202 - } 203 - 204 - memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd); 205 - pBuffer->nBuf += nAdd; 206 - pBuffer->zBuf[pBuffer->nBuf] = '\0'; 207 - 208 - return TH_OK; 209 -} 210 -#define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d) 211 - 212 -/* 213 -** Initialize the Buffer structure pointed to by pBuffer. 214 -*/ 215 -static void thBufferInit(Buffer *pBuffer){ 216 - memset(pBuffer, 0, sizeof(Buffer)); 217 -} 218 - 219 -/* 220 -** Zero the buffer pointed to by pBuffer and free the associated memory 221 -** allocation. 222 -*/ 223 -static void thBufferFree(Th_Interp *interp, Buffer *pBuffer){ 224 - Th_Free(interp, pBuffer->zBuf); 225 - thBufferInit(pBuffer); 226 -} 227 - 228 -/* 229 -** Assuming parameter c contains a hexadecimal digit character, 230 -** return the corresponding value of that digit. If c is not 231 -** a hexadecimal digit character, -1 is returned. 232 -*/ 233 -static int thHexdigit(char c){ 234 - switch (c) { 235 - case '0': return 0; 236 - case '1': return 1; 237 - case '2': return 2; 238 - case '3': return 3; 239 - case '4': return 4; 240 - case '5': return 5; 241 - case '6': return 6; 242 - case '7': return 7; 243 - case '8': return 8; 244 - case '9': return 9; 245 - case 'a': case 'A': return 10; 246 - case 'b': case 'B': return 11; 247 - case 'c': case 'C': return 12; 248 - case 'd': case 'D': return 13; 249 - case 'e': case 'E': return 14; 250 - case 'f': case 'F': return 15; 251 - } 252 - return -1; 253 -} 254 - 255 -/* 256 -** Argument pEntry points to an entry in a stack frame hash table 257 -** (Th_Frame.paVar). Decrement the refrerence count of the Th_Variable 258 -** structure that the entry points to. Free the Th_Variable if its 259 -** reference count reaches 0. 260 -** 261 -** Argument pContext is a pointer to the interpreter structure. 262 -*/ 263 -static void thFreeVariable(Th_HashEntry *pEntry, void *pContext){ 264 - Th_Variable *pValue = (Th_Variable *)pEntry->pData; 265 - pValue->nRef--; 266 - assert( pValue->nRef>=0 ); 267 - if( pValue->nRef==0 ){ 268 - Th_Interp *interp = (Th_Interp *)pContext; 269 - Th_Free(interp, pValue->zData); 270 - if( pValue->pHash ){ 271 - Th_HashIterate(interp, pValue->pHash, thFreeVariable, pContext); 272 - Th_HashDelete(interp, pValue->pHash); 273 - } 274 - Th_Free(interp, pValue); 275 - } 276 -} 277 - 278 -/* 279 -** Argument pEntry points to an entry in the command hash table 280 -** (Th_Interp.paCmd). Delete the Th_Command structure that the 281 -** entry points to. 282 -** 283 -** Argument pContext is a pointer to the interpreter structure. 284 -*/ 285 -static void thFreeCommand(Th_HashEntry *pEntry, void *pContext){ 286 - Th_Command *pCommand = (Th_Command *)pEntry->pData; 287 - if( pCommand->xDel ){ 288 - pCommand->xDel((Th_Interp *)pContext, pCommand->pContext); 289 - } 290 - Th_Free((Th_Interp *)pContext, pEntry->pData); 291 - pEntry->pData = 0; 292 -} 293 - 294 -/* 295 -** Push a new frame onto the stack. 296 -*/ 297 -static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){ 298 - pFrame->paVar = Th_HashNew(interp); 299 - pFrame->pCaller = interp->pFrame; 300 - interp->pFrame = pFrame; 301 - return TH_OK; 302 -} 303 - 304 -/* 305 -** Pop a frame off the top of the stack. 306 -*/ 307 -static void thPopFrame(Th_Interp *interp){ 308 - Th_Frame *pFrame = interp->pFrame; 309 - Th_HashIterate(interp, pFrame->paVar, thFreeVariable, (void *)interp); 310 - Th_HashDelete(interp, pFrame->paVar); 311 - interp->pFrame = pFrame->pCaller; 312 -} 313 - 314 -/* 315 -** The first part of the string (zInput,nInput) contains an escape 316 -** sequence. Set *pnEscape to the number of bytes in the escape sequence. 317 -** If there is a parse error, return TH_ERROR and set the interpreter 318 -** result to an error message. Otherwise return TH_OK. 319 -*/ 320 -static int thNextEscape( 321 - Th_Interp *interp, 322 - const char *zInput, 323 - int nInput, 324 - int *pnEscape 325 -){ 326 - int i = 2; 327 - 328 - assert(nInput>0); 329 - assert(zInput[0]=='\\'); 330 - 331 - if( nInput<=1 ){ 332 - return TH_ERROR; 333 - } 334 - 335 - switch( zInput[1] ){ 336 - case 'x': i = 4; 337 - } 338 - 339 - if( i>nInput ){ 340 - return TH_ERROR; 341 - } 342 - *pnEscape = i; 343 - return TH_OK; 344 -} 345 - 346 -/* 347 -** The first part of the string (zInput,nInput) contains a variable 348 -** reference. Set *pnVarname to the number of bytes in the variable 349 -** reference. If there is a parse error, return TH_ERROR and set the 350 -** interpreter result to an error message. Otherwise return TH_OK. 351 -*/ 352 -int thNextVarname( 353 - Th_Interp *interp, 354 - const char *zInput, 355 - int nInput, 356 - int *pnVarname 357 -){ 358 - int i; 359 - 360 - assert(nInput>0); 361 - assert(zInput[0]=='$'); 362 - 363 - if( nInput>0 && zInput[1]=='{' ){ 364 - for(i=2; i<nInput && zInput[i]!='}'; i++); 365 - if( i==nInput ){ 366 - return TH_ERROR; 367 - } 368 - i++; 369 - }else{ 370 - i = 1; 371 - if( nInput>2 && zInput[1]==':' && zInput[2]==':' ){ 372 - i += 2; 373 - } 374 - for(; i<nInput; i++){ 375 - if( zInput[i]=='(' ){ 376 - for(i++; i<nInput; i++){ 377 - if( zInput[i]==')' ) break; 378 - if( zInput[i]=='\\' ) i++; 379 - if( zInput[i]=='{' || zInput[i]=='[' || zInput[i]=='"' ){ 380 - int nWord; 381 - int rc = thNextWord(interp, &zInput[i], nInput-i, &nWord, 0); 382 - if( rc!=TH_OK ){ 383 - return rc; 384 - } 385 - i += nWord; 386 - } 387 - } 388 - if( i>=nInput ){ 389 - Th_ErrorMessage(interp, "Unmatched brackets:", zInput, nInput); 390 - return TH_ERROR; 391 - } 392 - i++; 393 - break; 394 - } 395 - if( !th_isalnum(zInput[i]) && zInput[i]!='_' ) break; 396 - } 397 - } 398 - 399 - *pnVarname = i; 400 - return TH_OK; 401 -} 402 - 403 -/* 404 -** The first part of the string (zInput,nInput) contains a command 405 -** enclosed in a "[]" block. Set *pnCommand to the number of bytes in 406 -** the variable reference. If there is a parse error, return TH_ERROR 407 -** and set the interpreter result to an error message. Otherwise return 408 -** TH_OK. 409 -*/ 410 -int thNextCommand( 411 - Th_Interp *interp, 412 - const char *zInput, 413 - int nInput, 414 - int *pnCommand 415 -){ 416 - int nBrace = 0; 417 - int nSquare = 0; 418 - int i; 419 - 420 - assert(nInput>0); 421 - assert( zInput[0]=='[' || zInput[0]=='{' ); 422 - 423 - for(i=0; i<nInput && (i==0 || nBrace>0 || nSquare>0); i++){ 424 - switch( zInput[i] ){ 425 - case '\\': i++; break; 426 - case '{': nBrace++; break; 427 - case '}': nBrace--; break; 428 - case '[': nSquare++; break; 429 - case ']': nSquare--; break; 430 - } 431 - } 432 - if( nBrace || nSquare ){ 433 - return TH_ERROR; 434 - } 435 - 436 - *pnCommand = i; 437 - 438 - return TH_OK; 439 -} 440 - 441 -/* 442 -** Set *pnSpace to the number of whitespace bytes at the start of 443 -** input string (zInput, nInput). Always return TH_OK. 444 -*/ 445 -int thNextSpace( 446 - Th_Interp *interp, 447 - const char *zInput, 448 - int nInput, 449 - int *pnSpace 450 -){ 451 - int i; 452 - for(i=0; i<nInput && th_isspace(zInput[i]); i++); 453 - *pnSpace = i; 454 - return TH_OK; 455 -} 456 - 457 -/* 458 -** The first byte of the string (zInput,nInput) is not white-space. 459 -** Set *pnWord to the number of bytes in the th1 word that starts 460 -** with this byte. If a complete word cannot be parsed or some other 461 -** error occurs, return TH_ERROR and set the interpreter result to 462 -** an error message. Otherwise return TH_OK. 463 -** 464 -** If the isCmd argument is non-zero, then an unescaped ";" byte not 465 -** located inside of a block or quoted string is considered to mark 466 -** the end of the word. 467 -*/ 468 -static int thNextWord( 469 - Th_Interp *interp, 470 - const char *zInput, 471 - int nInput, 472 - int *pnWord, 473 - int isCmd 474 -){ 475 - int iEnd = 0; 476 - 477 - assert( !th_isspace(zInput[0]) ); 478 - 479 - if( zInput[0]=='"' ){ 480 - /* The word is terminated by the next unescaped '"' character. */ 481 - iEnd++; 482 - while( iEnd<nInput && zInput[iEnd]!='"' ){ 483 - if( zInput[iEnd]=='\\' ){ 484 - iEnd++; 485 - } 486 - iEnd++; 487 - } 488 - iEnd++; 489 - }else{ 490 - int nBrace = 0; 491 - int nSq = 0; 492 - while( iEnd<nInput && (nBrace>0 || nSq>0 || 493 - (!th_isspace(zInput[iEnd]) && (!isCmd || zInput[iEnd]!=';')) 494 - )){ 495 - switch( zInput[iEnd] ){ 496 - case '\\': iEnd++; break; 497 - case '{': if( nSq==0 ) nBrace++; break; 498 - case '}': if( nSq==0 ) nBrace--; break; 499 - case '[': if( nBrace==0 ) nSq++; break; 500 - case ']': if( nBrace==0 ) nSq--; break; 501 - } 502 - iEnd++; 503 - } 504 - if( nBrace>0 || nSq>0 ){ 505 - /* Parse error */ 506 - return TH_ERROR; 507 - } 508 - } 509 - 510 - if( iEnd>nInput ){ 511 - /* Parse error */ 512 - return TH_ERROR; 513 - } 514 - *pnWord = iEnd; 515 - return TH_OK; 516 -} 517 - 518 -/* 519 -** The input string (zWord, nWord) contains a th1 script enclosed in 520 -** a [] block. Perform substitution on the input string and store the 521 -** resulting string in the interpreter result. 522 -*/ 523 -static int thSubstCommand( 524 - Th_Interp *interp, 525 - const char *zWord, 526 - int nWord 527 -){ 528 - assert(nWord>=2); 529 - assert(zWord[0]=='[' && zWord[nWord-1]==']'); 530 - return thEvalLocal(interp, &zWord[1], nWord-2); 531 -} 532 - 533 -/* 534 -** The input string (zWord, nWord) contains a th1 variable reference 535 -** (a '$' byte followed by a variable name). Perform substitution on 536 -** the input string and store the resulting string in the interpreter 537 -** result. 538 -*/ 539 -static int thSubstVarname( 540 - Th_Interp *interp, 541 - const char *zWord, 542 - int nWord 543 -){ 544 - assert(nWord>=1); 545 - assert(zWord[0]=='$'); 546 - assert(nWord==1 || zWord[1]!='{' || zWord[nWord-1]=='}'); 547 - if( nWord>1 && zWord[1]=='{' ){ 548 - zWord++; 549 - nWord -= 2; 550 - }else if( zWord[nWord-1]==')' ){ 551 - int i; 552 - for(i=1; i<nWord && zWord[i]!='('; i++); 553 - if( i<nWord ){ 554 - Buffer varname; 555 - int nInner; 556 - const char *zInner; 557 - 558 - int rc = thSubstWord(interp, &zWord[i+1], nWord-i-2); 559 - if( rc!=TH_OK ) return rc; 560 - 561 - zInner = Th_GetResult(interp, &nInner); 562 - thBufferInit(&varname); 563 - thBufferWrite(interp, &varname, &zWord[1], i); 564 - thBufferWrite(interp, &varname, zInner, nInner); 565 - thBufferWrite(interp, &varname, ")", 1); 566 - rc = Th_GetVar(interp, varname.zBuf, varname.nBuf); 567 - thBufferFree(interp, &varname); 568 - return rc; 569 - } 570 - } 571 - return Th_GetVar(interp, &zWord[1], nWord-1); 572 -} 573 - 574 -/* 575 -** The input string (zWord, nWord) contains a th1 escape sequence. 576 -** Perform substitution on the input string and store the resulting 577 -** string in the interpreter result. 578 -*/ 579 -static int thSubstEscape( 580 - Th_Interp *interp, 581 - const char *zWord, 582 - int nWord 583 -){ 584 - char c; 585 - 586 - assert(nWord>=2); 587 - assert(zWord[0]=='\\'); 588 - 589 - switch( zWord[1] ){ 590 - case 'x': { 591 - assert(nWord==4); 592 - c = ((thHexdigit(zWord[2])<<4) + thHexdigit(zWord[3])); 593 - break; 594 - } 595 - case 'n': { 596 - c = '\n'; 597 - break; 598 - } 599 - default: { 600 - assert(nWord==2); 601 - c = zWord[1]; 602 - break; 603 - } 604 - } 605 - 606 - Th_SetResult(interp, &c, 1); 607 - return TH_OK; 608 -} 609 - 610 -/* 611 -** The input string (zWord, nWord) contains a th1 word. Perform 612 -** substitution on the input string and store the resulting 613 -** string in the interpreter result. 614 -*/ 615 -static int thSubstWord( 616 - Th_Interp *interp, 617 - const char *zWord, 618 - int nWord 619 -){ 620 - int rc = TH_OK; 621 - Buffer output; 622 - int i; 623 - 624 - thBufferInit(&output); 625 - 626 - if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){ 627 - rc = thBufferWrite(interp, &output, &zWord[1], nWord-2); 628 - }else{ 629 - 630 - /* If the word is surrounded by double-quotes strip these away. */ 631 - if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){ 632 - zWord++; 633 - nWord -= 2; 634 - } 635 - 636 - for(i=0; rc==TH_OK && i<nWord; i++){ 637 - int nGet; 638 - 639 - int (*xGet)(Th_Interp *, const char*, int, int *) = 0; 640 - int (*xSubst)(Th_Interp *, const char*, int) = 0; 641 - 642 - switch( zWord[i] ){ 643 - case '\\': 644 - xGet = thNextEscape; xSubst = thSubstEscape; 645 - break; 646 - case '[': 647 - if( !interp->isListMode ){ 648 - xGet = thNextCommand; xSubst = thSubstCommand; 649 - break; 650 - } 651 - case '$': 652 - if( !interp->isListMode ){ 653 - xGet = thNextVarname; xSubst = thSubstVarname; 654 - break; 655 - } 656 - default: { 657 - thBufferWrite(interp, &output, &zWord[i], 1); 658 - continue; /* Go to the next iteration of the for(...) loop */ 659 - } 660 - } 661 - 662 - rc = xGet(interp, &zWord[i], nWord-i, &nGet); 663 - if( rc==TH_OK ){ 664 - rc = xSubst(interp, &zWord[i], nGet); 665 - } 666 - if( rc==TH_OK ){ 667 - const char *zRes; 668 - int nRes; 669 - zRes = Th_GetResult(interp, &nRes); 670 - rc = thBufferWrite(interp, &output, zRes, nRes); 671 - i += (nGet-1); 672 - } 673 - } 674 - } 675 - 676 - if( rc==TH_OK ){ 677 - Th_SetResult(interp, output.zBuf, output.nBuf); 678 - } 679 - thBufferFree(interp, &output); 680 - return rc; 681 -} 682 - 683 -/* 684 -** Return true if one of the following is true of the buffer pointed 685 -** to by zInput, length nInput: 686 -** 687 -** + It is empty, or 688 -** + It contains nothing but white-space, or 689 -** + It contains no non-white-space characters before the first 690 -** newline character. 691 -** 692 -** Otherwise return false. 693 -*/ 694 -static int thEndOfLine(const char *zInput, int nInput){ 695 - int i; 696 - for(i=0; i<nInput && zInput[i]!='\n' && th_isspace(zInput[i]); i++); 697 - return ((i==nInput || zInput[i]=='\n')?1:0); 698 -} 699 - 700 -/* 701 -** This function splits the supplied th1 list (contained in buffer zList, 702 -** size nList) into elements and performs word-substitution on each 703 -** element. If the Th_Interp.isListMode variable is true, then only 704 -** escape sequences are substituted (used by the Th_SplitList() function). 705 -** If Th_Interp.isListMode is false, then variable and command substitution 706 -** is also performed (used by Th_Eval()). 707 -** 708 -** If zList/nList does not contain a valid list, TH_ERROR is returned 709 -** and an error message stored in interp. 710 -** 711 -** If TH_OK is returned and pazElem is not NULL, the caller should free the 712 -** pointer written to (*pazElem) using Th_Free(). This releases memory 713 -** allocated for both the (*pazElem) and (*panElem) arrays. Example: 714 -** 715 -** char **argv; 716 -** int *argl; 717 -** int argc; 718 -** 719 -** // After this call, argv and argl point to valid arrays. The 720 -** // number of elements in each is argc. 721 -** // 722 -** Th_SplitList(interp, zList, nList, &argv, &argl, &argc); 723 -** 724 -** // Free all memory allocated by Th_SplitList(). The arrays pointed 725 -** // to by argv and argl are invalidated by this call. 726 -** // 727 -** Th_Free(interp, argv); 728 -** 729 -*/ 730 -static int thSplitList( 731 - Th_Interp *interp, /* Interpreter context */ 732 - const char *zList, /* Pointer to buffer containing input list */ 733 - int nList, /* Size of buffer pointed to by zList */ 734 - char ***pazElem, /* OUT: Array of list elements */ 735 - int **panElem, /* OUT: Lengths of each list element */ 736 - int *pnCount /* OUT: Number of list elements */ 737 -){ 738 - int rc = TH_OK; 739 - 740 - Buffer strbuf; 741 - Buffer lenbuf; 742 - int nCount = 0; 743 - 744 - const char *zInput = zList; 745 - int nInput = nList; 746 - 747 - thBufferInit(&strbuf); 748 - thBufferInit(&lenbuf); 749 - 750 - while( nInput>0 ){ 751 - const char *zWord; 752 - int nWord; 753 - 754 - thNextSpace(interp, zInput, nInput, &nWord); 755 - zInput += nWord; 756 - nInput = nList-(zInput-zList); 757 - 758 - if( TH_OK!=(rc = thNextWord(interp, zInput, nInput, &nWord, 0)) 759 - || TH_OK!=(rc = thSubstWord(interp, zInput, nWord)) 760 - ){ 761 - goto finish; 762 - } 763 - zInput = &zInput[nWord]; 764 - nInput = nList-(zInput-zList); 765 - if( nWord>0 ){ 766 - zWord = Th_GetResult(interp, &nWord); 767 - thBufferWrite(interp, &strbuf, zWord, nWord); 768 - thBufferWrite(interp, &strbuf, "\0", 1); 769 - thBufferWrite(interp, &lenbuf, &nWord, sizeof(int)); 770 - nCount++; 771 - } 772 - } 773 - assert((lenbuf.nBuf/sizeof(int))==nCount); 774 - 775 - assert((pazElem && panElem) || (!pazElem && !panElem)); 776 - if( pazElem && rc==TH_OK ){ 777 - int i; 778 - char *zElem; 779 - int *anElem; 780 - char **azElem = Th_Malloc(interp, 781 - sizeof(char*) * nCount + /* azElem */ 782 - sizeof(int) * nCount + /* anElem */ 783 - strbuf.nBuf /* space for list element strings */ 784 - ); 785 - anElem = (int *)&azElem[nCount]; 786 - zElem = (char *)&anElem[nCount]; 787 - memcpy(anElem, lenbuf.zBuf, lenbuf.nBuf); 788 - memcpy(zElem, strbuf.zBuf, strbuf.nBuf); 789 - for(i=0; i<nCount;i++){ 790 - azElem[i] = zElem; 791 - zElem += (anElem[i] + 1); 792 - } 793 - *pazElem = azElem; 794 - *panElem = anElem; 795 - } 796 - if( pnCount ){ 797 - *pnCount = nCount; 798 - } 799 - 800 - finish: 801 - thBufferFree(interp, &strbuf); 802 - thBufferFree(interp, &lenbuf); 803 - return rc; 804 -} 805 - 806 -/* 807 -** Evaluate the th1 script contained in the string (zProgram, nProgram) 808 -** in the current stack frame. 809 -*/ 810 -static int thEvalLocal(Th_Interp *interp, const char *zProgram, int nProgram){ 811 - int rc = TH_OK; 812 - const char *zInput = zProgram; 813 - int nInput = nProgram; 814 - 815 - while( rc==TH_OK && nInput ){ 816 - Th_HashEntry *pEntry; 817 - int nSpace; 818 - const char *zFirst; 819 - 820 - char **argv; 821 - int *argl; 822 - int argc; 823 - 824 - assert(nInput>=0); 825 - 826 - /* Skip a semi-colon */ 827 - if( *zInput==';' ){ 828 - zInput++; 829 - nInput--; 830 - } 831 - 832 - /* Skip past leading white-space. */ 833 - thNextSpace(interp, zInput, nInput, &nSpace); 834 - zInput += nSpace; 835 - nInput -= nSpace; 836 - zFirst = zInput; 837 - 838 - /* Check for a comment. If found, skip to the end of the line. */ 839 - if( zInput[0]=='#' ){ 840 - while( !thEndOfLine(zInput, nInput) ){ 841 - zInput++; 842 - nInput--; 843 - } 844 - continue; 845 - } 846 - 847 - /* Gobble up input a word at a time until the end of the command 848 - ** (a semi-colon or end of line). 849 - */ 850 - while( rc==TH_OK && *zInput!=';' && !thEndOfLine(zInput, nInput) ){ 851 - int nWord=0; 852 - thNextSpace(interp, zInput, nInput, &nSpace); 853 - rc = thNextWord(interp, &zInput[nSpace], nInput-nSpace, &nWord, 1); 854 - zInput += (nSpace+nWord); 855 - nInput -= (nSpace+nWord); 856 - } 857 - if( rc!=TH_OK ) continue; 858 - 859 - /* Split the command into an array of words. This call also does 860 - ** substitution of each individual word. 861 - */ 862 - rc = thSplitList(interp, zFirst, zInput-zFirst, &argv, &argl, &argc); 863 - if( rc!=TH_OK ) continue; 864 - 865 - if( argc>0 ){ 866 - 867 - /* Look up the command name in the command hash-table. */ 868 - pEntry = Th_HashFind(interp, interp->paCmd, argv[0], argl[0], 0); 869 - if( !pEntry ){ 870 - Th_ErrorMessage(interp, "no such command: ", argv[0], argl[0]); 871 - rc = TH_ERROR; 872 - } 873 - 874 - /* Call the command procedure. */ 875 - if( rc==TH_OK ){ 876 - Th_Command *p = (Th_Command *)(pEntry->pData); 877 - const char **azArg = (const char **)argv; 878 - rc = p->xProc(interp, p->pContext, argc, azArg, argl); 879 - } 880 - 881 - /* If an error occured, add this command to the stack trace report. */ 882 - if( rc==TH_ERROR ){ 883 - char *zRes; 884 - int nRes; 885 - char *zStack = 0; 886 - int nStack = 0; 887 - 888 - zRes = Th_TakeResult(interp, &nRes); 889 - if( TH_OK==Th_GetVar(interp, (char *)"::th_stack_trace", -1) ){ 890 - zStack = Th_TakeResult(interp, &nStack); 891 - } 892 - Th_ListAppend(interp, &zStack, &nStack, zFirst, zInput-zFirst); 893 - Th_SetVar(interp, (char *)"::th_stack_trace", -1, zStack, nStack); 894 - Th_SetResult(interp, zRes, nRes); 895 - Th_Free(interp, zRes); 896 - Th_Free(interp, zStack); 897 - } 898 - } 899 - 900 - Th_Free(interp, argv); 901 - } 902 - 903 - return rc; 904 -} 905 - 906 -/* 907 -** Interpret an integer frame identifier passed to either Th_Eval() or 908 -** Th_LinkVar(). If successful, return a pointer to the identified 909 -** Th_Frame structure. If unsuccessful (no such frame), return 0 and 910 -** leave an error message in the interpreter result. 911 -** 912 -** Argument iFrame is interpreted as follows: 913 -** 914 -** * If iFrame is 0, this means the current frame. 915 -** 916 -** * If iFrame is negative, then the nth frame up the stack, where 917 -** n is the absolute value of iFrame. A value of -1 means the 918 -** calling procedure. 919 -** 920 -** * If iFrame is +ve, then the nth frame from the bottom of the 921 -** stack. An iFrame value of 1 means the toplevel (global) frame. 922 -*/ 923 -static Th_Frame *getFrame(Th_Interp *interp, int iFrame){ 924 - Th_Frame *p = interp->pFrame; 925 - int i; 926 - if( iFrame>0 ){ 927 - for(i=0; p; i++){ 928 - p = p->pCaller; 929 - } 930 - iFrame = (i*-1) + iFrame; 931 - p = interp->pFrame; 932 - } 933 - for(i=0; p && i<(iFrame*-1); i++){ 934 - p = p->pCaller; 935 - } 936 - 937 - if( !p ){ 938 - char *zFrame; 939 - int nFrame; 940 - Th_SetResultInt(interp, iFrame); 941 - zFrame = Th_TakeResult(interp, &nFrame); 942 - Th_ErrorMessage(interp, "no such frame:", zFrame, nFrame); 943 - Th_Free(interp, zFrame); 944 - } 945 - return p; 946 -} 947 - 948 - 949 -/* 950 -** Evaluate th1 script (zProgram, nProgram) in the frame identified by 951 -** argument iFrame. Leave either an error message or a result in the 952 -** interpreter result and return a th1 error code (TH_OK, TH_ERROR, 953 -** TH_RETURN, TH_CONTINUE or TH_BREAK). 954 -*/ 955 -int Th_Eval(Th_Interp *interp, int iFrame, const char *zProgram, int nProgram){ 956 - int rc = TH_OK; 957 - Th_Frame *pSavedFrame = interp->pFrame; 958 - 959 - /* Set Th_Interp.pFrame to the frame that this script is to be 960 - ** evaluated in. The current frame is saved in pSavedFrame and will 961 - ** be restored before this function returns. 962 - */ 963 - interp->pFrame = getFrame(interp, iFrame); 964 - 965 - if( !interp->pFrame ){ 966 - rc = TH_ERROR; 967 - }else{ 968 - int nInput = nProgram; 969 - 970 - if( nInput<0 ){ 971 - nInput = th_strlen(zProgram); 972 - } 973 - rc = thEvalLocal(interp, zProgram, nInput); 974 - } 975 - 976 - interp->pFrame = pSavedFrame; 977 - return rc; 978 -} 979 - 980 -/* 981 -** Input string (zVarname, nVarname) contains a th1 variable name. It 982 -** may be a simple scalar variable name or it may be a reference 983 -** to an array member. The variable name may or may not begin with 984 -** "::", indicating that the name refers to a global variable, not 985 -** a local scope one. 986 -** 987 -** This function inspects and categorizes the supplied variable name. 988 -** 989 -** If the name is a global reference, *pisGlobal is set to true. Otherwise 990 -** false. Output string (*pzOuter, *pnOuter) is set to the variable name 991 -** if it is a scalar reference, or the name of the array if it is an 992 -** array variable. If the variable is a scalar, *pzInner is set to 0. 993 -** If it is an array variable, (*pzInner, *pnInner) is set to the 994 -** array key name. 995 -*/ 996 -static int thAnalyseVarname( 997 - const char *zVarname, 998 - int nVarname, 999 - const char **pzOuter, /* OUT: Pointer to scalar/array name */ 1000 - int *pnOuter, /* OUT: Number of bytes at *pzOuter */ 1001 - const char **pzInner, /* OUT: Pointer to array key (or null) */ 1002 - int *pnInner, /* OUT: Number of bytes at *pzInner */ 1003 - int *pisGlobal /* OUT: Set to true if this is a global ref */ 1004 -){ 1005 - const char *zOuter = zVarname; 1006 - int nOuter; 1007 - const char *zInner = 0; 1008 - int nInner = 0; 1009 - int isGlobal = 0; 1010 - int i; 1011 - 1012 - if( nVarname<0 ){ 1013 - nVarname = th_strlen(zVarname); 1014 - } 1015 - nOuter = nVarname; 1016 - 1017 - /* If the variable name starts with "::", then do the lookup is in the 1018 - ** uppermost (global) frame. 1019 - */ 1020 - if( nVarname>2 && zVarname[0]==':' && zVarname[1]==':' ){ 1021 - zOuter += 2; 1022 - nOuter -= 2; 1023 - isGlobal = 1; 1024 - } 1025 - 1026 - /* Check if this is an array reference. */ 1027 - if( zOuter[nOuter-1]==')' ){ 1028 - for(i=0; i<nOuter; i++){ 1029 - if( zOuter[i]=='(' ){ 1030 - zInner = &zOuter[i+1]; 1031 - nInner = nOuter-i-2; 1032 - nOuter = i; 1033 - break; 1034 - } 1035 - } 1036 - } 1037 - 1038 - *pzOuter = zOuter; 1039 - *pnOuter = nOuter; 1040 - *pzInner = zInner; 1041 - *pnInner = nInner; 1042 - *pisGlobal = isGlobal; 1043 - return TH_OK; 1044 -} 1045 - 1046 -/* 1047 -** Input string (zVar, nVar) contains a variable name. This function locates 1048 -** the Th_Variable structure associated with the named variable. The 1049 -** variable name may be a global or local scalar or array variable 1050 -** 1051 -** If the create argument is non-zero and the named variable does not exist 1052 -** it is created. Otherwise, an error is left in the interpreter result 1053 -** and NULL returned. 1054 -** 1055 -** If the arrayok argument is false and the named variable is an array, 1056 -** an error is left in the interpreter result and NULL returned. If 1057 -** arrayok is true an array name is Ok. 1058 -*/ 1059 -static Th_Variable *thFindValue( 1060 - Th_Interp *interp, 1061 - const char *zVar, /* Pointer to variable name */ 1062 - int nVar, /* Number of bytes at nVar */ 1063 - int create, /* If true, create the variable if not found */ 1064 - int arrayok /* If true, an array is Ok. Othewise array==error */ 1065 -){ 1066 - const char *zOuter; 1067 - int nOuter; 1068 - const char *zInner; 1069 - int nInner; 1070 - int isGlobal; 1071 - 1072 - Th_HashEntry *pEntry; 1073 - Th_Frame *pFrame = interp->pFrame; 1074 - Th_Variable *pValue; 1075 - 1076 - thAnalyseVarname(zVar, nVar, &zOuter, &nOuter, &zInner, &nInner, &isGlobal); 1077 - if( isGlobal ){ 1078 - while( pFrame->pCaller ) pFrame = pFrame->pCaller; 1079 - } 1080 - 1081 - pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create); 1082 - assert(pEntry || !create); 1083 - if( !pEntry ){ 1084 - goto no_such_var; 1085 - } 1086 - 1087 - pValue = (Th_Variable *)pEntry->pData; 1088 - if( !pValue ){ 1089 - assert(create); 1090 - pValue = Th_Malloc(interp, sizeof(Th_Variable)); 1091 - pValue->nRef = 1; 1092 - pEntry->pData = (void *)pValue; 1093 - } 1094 - 1095 - if( zInner ){ 1096 - if( pValue->zData ){ 1097 - Th_ErrorMessage(interp, "variable is a scalar:", zOuter, nOuter); 1098 - return 0; 1099 - } 1100 - if( !pValue->pHash ){ 1101 - if( !create ){ 1102 - goto no_such_var; 1103 - } 1104 - pValue->pHash = Th_HashNew(interp); 1105 - } 1106 - pEntry = Th_HashFind(interp, pValue->pHash, zInner, nInner, create); 1107 - if( !pEntry ){ 1108 - goto no_such_var; 1109 - } 1110 - pValue = (Th_Variable *)pEntry->pData; 1111 - if( !pValue ){ 1112 - assert(create); 1113 - pValue = Th_Malloc(interp, sizeof(Th_Variable)); 1114 - pValue->nRef = 1; 1115 - pEntry->pData = (void *)pValue; 1116 - } 1117 - }else{ 1118 - if( pValue->pHash && !arrayok ){ 1119 - Th_ErrorMessage(interp, "variable is an array:", zOuter, nOuter); 1120 - return 0; 1121 - } 1122 - } 1123 - 1124 - return pValue; 1125 - 1126 -no_such_var: 1127 - Th_ErrorMessage(interp, "no such variable:", zVar, nVar); 1128 - return 0; 1129 -} 1130 - 1131 -/* 1132 -** String (zVar, nVar) must contain the name of a scalar variable or 1133 -** array member. Look up the variable, store its current value in 1134 -** the interpreter result and return TH_OK. 1135 -** 1136 -** If the named variable does not exist, return TH_ERROR and leave 1137 -** an error message in the interpreter result. 1138 -*/ 1139 -int Th_GetVar(Th_Interp *interp, const char *zVar, int nVar){ 1140 - Th_Variable *pValue; 1141 - 1142 - pValue = thFindValue(interp, zVar, nVar, 0, 0); 1143 - if( !pValue ){ 1144 - return TH_ERROR; 1145 - } 1146 - if( !pValue->zData ){ 1147 - Th_ErrorMessage(interp, "no such variable:", zVar, nVar); 1148 - return TH_ERROR; 1149 - } 1150 - 1151 - return Th_SetResult(interp, pValue->zData, pValue->nData); 1152 -} 1153 - 1154 -/* 1155 -** String (zVar, nVar) must contain the name of a scalar variable or 1156 -** array member. If the variable does not exist it is created. The 1157 -** variable is set to the value supplied in string (zValue, nValue). 1158 -** 1159 -** If (zVar, nVar) refers to an existing array, TH_ERROR is returned 1160 -** and an error message left in the interpreter result. 1161 -*/ 1162 -int Th_SetVar( 1163 - Th_Interp *interp, 1164 - const char *zVar, 1165 - int nVar, 1166 - const char *zValue, 1167 - int nValue 1168 -){ 1169 - Th_Variable *pValue; 1170 - 1171 - pValue = thFindValue(interp, zVar, nVar, 1, 0); 1172 - if( !pValue ){ 1173 - return TH_ERROR; 1174 - } 1175 - 1176 - if( nValue<0 ){ 1177 - nValue = th_strlen(zValue); 1178 - } 1179 - if( pValue->zData ){ 1180 - Th_Free(interp, pValue->zData); 1181 - pValue->zData = 0; 1182 - } 1183 - 1184 - assert(zValue || nValue==0); 1185 - pValue->zData = Th_Malloc(interp, nValue+1); 1186 - pValue->zData[nValue] = '\0'; 1187 - memcpy(pValue->zData, zValue, nValue); 1188 - pValue->nData = nValue; 1189 - 1190 - return TH_OK; 1191 -} 1192 - 1193 -/* 1194 -** Create a variable link so that accessing variable (zLocal, nLocal) is 1195 -** the same as accessing variable (zLink, nLink) in stack frame iFrame. 1196 -*/ 1197 -int Th_LinkVar( 1198 - Th_Interp *interp, /* Interpreter */ 1199 - const char *zLocal, int nLocal, /* Local varname */ 1200 - int iFrame, /* Stack frame of linked var */ 1201 - const char *zLink, int nLink /* Linked varname */ 1202 -){ 1203 - Th_Frame *pSavedFrame = interp->pFrame; 1204 - Th_Frame *pFrame; 1205 - Th_HashEntry *pEntry; 1206 - Th_Variable *pValue; 1207 - 1208 - pFrame = getFrame(interp, iFrame); 1209 - if( !pFrame ){ 1210 - return TH_ERROR; 1211 - } 1212 - pSavedFrame = interp->pFrame; 1213 - interp->pFrame = pFrame; 1214 - pValue = thFindValue(interp, zLink, nLink, 1, 1); 1215 - interp->pFrame = pSavedFrame; 1216 - 1217 - pEntry = Th_HashFind(interp, interp->pFrame->paVar, zLocal, nLocal, 1); 1218 - if( pEntry->pData ){ 1219 - Th_ErrorMessage(interp, "variable exists:", zLocal, nLocal); 1220 - return TH_ERROR; 1221 - } 1222 - pEntry->pData = (void *)pValue; 1223 - pValue->nRef++; 1224 - 1225 - return TH_OK; 1226 -} 1227 - 1228 -/* 1229 -** Input string (zVar, nVar) must contain the name of a scalar variable, 1230 -** an array, or an array member. If the identified variable exists, it 1231 -** is deleted and TH_OK returned. Otherwise, an error message is left 1232 -** in the interpreter result and TH_ERROR is returned. 1233 -*/ 1234 -int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){ 1235 - Th_Variable *pValue; 1236 - 1237 - pValue = thFindValue(interp, zVar, nVar, 1, 1); 1238 - if( !pValue ){ 1239 - return TH_ERROR; 1240 - } 1241 - 1242 - Th_Free(interp, pValue->zData); 1243 - pValue->zData = 0; 1244 - if( pValue->pHash ){ 1245 - Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp); 1246 - Th_HashDelete(interp, pValue->pHash); 1247 - pValue->pHash = 0; 1248 - } 1249 - return TH_OK; 1250 -} 1251 - 1252 -/* 1253 -** Return an allocated buffer containing a copy of string (z, n). The 1254 -** caller is responsible for eventually calling Th_Free() to free 1255 -** the returned buffer. 1256 -*/ 1257 -char *th_strdup(Th_Interp *interp, const char *z, int n){ 1258 - char *zRes; 1259 - if( n<0 ){ 1260 - n = th_strlen(z); 1261 - } 1262 - zRes = Th_Malloc(interp, n+1); 1263 - memcpy(zRes, z, n); 1264 - zRes[n] = '\0'; 1265 - return zRes; 1266 -} 1267 - 1268 -/* 1269 -** Argument zPre must be a nul-terminated string. Set the interpreter 1270 -** result to a string containing the contents of zPre, followed by 1271 -** a space (" ") character, followed by a copy of string (z, n). 1272 -** 1273 -** In other words, the equivalent of: 1274 -* 1275 -** printf("%s %.*s", zPre, n, z); 1276 -** 1277 -** Example: 1278 -** 1279 -** Th_ErrorMessage(interp, "no such variable:", zVarname, nVarname); 1280 -** 1281 -*/ 1282 -int Th_ErrorMessage(Th_Interp *interp, const char *zPre, const char *z, int n){ 1283 - if( interp ){ 1284 - char *zRes = 0; 1285 - int nRes = 0; 1286 - 1287 - Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0); 1288 - 1289 - Th_StringAppend(interp, &zRes, &nRes, zPre, -1); 1290 - if( zRes[nRes-1]=='"' ){ 1291 - Th_StringAppend(interp, &zRes, &nRes, z, n); 1292 - Th_StringAppend(interp, &zRes, &nRes, (const char *)"\"", 1); 1293 - }else{ 1294 - Th_StringAppend(interp, &zRes, &nRes, (const char *)" ", 1); 1295 - Th_StringAppend(interp, &zRes, &nRes, z, n); 1296 - } 1297 - 1298 - Th_SetResult(interp, zRes, nRes); 1299 - Th_Free(interp, zRes); 1300 - } 1301 - 1302 - return TH_OK; 1303 -} 1304 - 1305 -/* 1306 -** Set the current interpreter result by taking a copy of the buffer 1307 -** pointed to by z, size n bytes. TH_OK is always returned. 1308 -*/ 1309 -int Th_SetResult(Th_Interp *pInterp, const char *z, int n){ 1310 - 1311 - /* Free the current result */ 1312 - Th_Free(pInterp, pInterp->zResult); 1313 - pInterp->zResult = 0; 1314 - pInterp->nResult = 0; 1315 - 1316 - if( n<0 ){ 1317 - n = th_strlen(z); 1318 - } 1319 - 1320 - if( z && n>0 ){ 1321 - char *zResult; 1322 - zResult = Th_Malloc(pInterp, n+1); 1323 - memcpy(zResult, z, n); 1324 - zResult[n] = '\0'; 1325 - pInterp->zResult = zResult; 1326 - pInterp->nResult = n; 1327 - } 1328 - 1329 - return TH_OK; 1330 -} 1331 - 1332 -/* 1333 -** Return a pointer to the buffer containing the current interpreter 1334 -** result. If pN is not NULL, set *pN to the size of the returned 1335 -** buffer. 1336 -*/ 1337 -const char *Th_GetResult(Th_Interp *pInterp, int *pN){ 1338 - assert(pInterp->zResult || pInterp->nResult==0); 1339 - if( pN ){ 1340 - *pN = pInterp->nResult; 1341 - } 1342 - return (pInterp->zResult ? pInterp->zResult : (const char *)""); 1343 -} 1344 - 1345 -/* 1346 -** Return a pointer to the buffer containing the current interpreter 1347 -** result. If pN is not NULL, set *pN to the size of the returned 1348 -** buffer. 1349 -** 1350 -** This function is the same as Th_GetResult() except that the 1351 -** caller is responsible for eventually calling Th_Free() on the 1352 -** returned buffer. The internal interpreter result is cleared 1353 -** after this function is called. 1354 -*/ 1355 -char *Th_TakeResult(Th_Interp *pInterp, int *pN){ 1356 - if( pN ){ 1357 - *pN = pInterp->nResult; 1358 - } 1359 - if( pInterp->zResult ){ 1360 - char *zResult = pInterp->zResult; 1361 - pInterp->zResult = 0; 1362 - pInterp->nResult = 0; 1363 - return zResult; 1364 - }else{ 1365 - return (char *)Th_Malloc(pInterp, 1); 1366 - } 1367 -} 1368 - 1369 - 1370 -/* 1371 -** Wrappers around the supplied malloc() and free() 1372 -*/ 1373 -void *Th_Malloc(Th_Interp *pInterp, int nByte){ 1374 - void *p = pInterp->pVtab->xMalloc(nByte); 1375 - if( p ){ 1376 - memset(p, 0, nByte); 1377 - } 1378 - return p; 1379 -} 1380 -void Th_Free(Th_Interp *pInterp, void *z){ 1381 - if( z ){ 1382 - pInterp->pVtab->xFree(z); 1383 - } 1384 -} 1385 - 1386 -/* 1387 -** Install a new th1 command. 1388 -** 1389 -** If a command of the same name already exists, it is deleted automatically. 1390 -*/ 1391 -int Th_CreateCommand( 1392 - Th_Interp *interp, 1393 - const char *zName, /* New command name */ 1394 - Th_CommandProc xProc, /* Command callback proc */ 1395 - void *pContext, /* Value to pass as second arg to xProc */ 1396 - void (*xDel)(Th_Interp *, void *) /* Command destructor callback */ 1397 -){ 1398 - Th_HashEntry *pEntry; 1399 - Th_Command *pCommand; 1400 - 1401 - pEntry = Th_HashFind(interp, interp->paCmd, (const char *)zName, -1, 1); 1402 - if( pEntry->pData ){ 1403 - pCommand = pEntry->pData; 1404 - if( pCommand->xDel ){ 1405 - pCommand->xDel(interp, pCommand->pContext); 1406 - } 1407 - }else{ 1408 - pCommand = Th_Malloc(interp, sizeof(Th_Command)); 1409 - } 1410 - pCommand->xProc = xProc; 1411 - pCommand->pContext = pContext; 1412 - pCommand->xDel = xDel; 1413 - pEntry->pData = (void *)pCommand; 1414 - 1415 - return TH_OK; 1416 -} 1417 - 1418 -/* 1419 -** Rename the existing command (zName, nName) to (zNew, nNew). If nNew is 0, 1420 -** the command is deleted instead of renamed. 1421 -** 1422 -** If successful, TH_OK is returned. If command zName does not exist, or 1423 -** if command zNew already exists, an error message is left in the 1424 -** interpreter result and TH_ERROR is returned. 1425 -*/ 1426 -int Th_RenameCommand( 1427 - Th_Interp *interp, 1428 - const char *zName, /* Existing command name */ 1429 - int nName, /* Number of bytes at zName */ 1430 - const char *zNew, /* New command name */ 1431 - int nNew /* Number of bytes at zNew */ 1432 -){ 1433 - Th_HashEntry *pEntry; 1434 - Th_HashEntry *pNewEntry; 1435 - 1436 - pEntry = Th_HashFind(interp, interp->paCmd, zName, nName, 0); 1437 - if( !pEntry ){ 1438 - Th_ErrorMessage(interp, "no such command:", zName, nName); 1439 - return TH_ERROR; 1440 - } 1441 - assert(pEntry->pData); 1442 - 1443 - if( nNew>0 ){ 1444 - pNewEntry = Th_HashFind(interp, interp->paCmd, zNew, nNew, 1); 1445 - if( pNewEntry->pData ){ 1446 - Th_ErrorMessage(interp, "command exists:", zNew, nNew); 1447 - return TH_ERROR; 1448 - } 1449 - pNewEntry->pData = pEntry->pData; 1450 - }else{ 1451 - Th_Command *pCommand = (Th_Command *)(pEntry->pData); 1452 - if( pCommand->xDel ){ 1453 - pCommand->xDel(interp, pCommand->pContext); 1454 - } 1455 - Th_Free(interp, pCommand); 1456 - } 1457 - 1458 - Th_HashFind(interp, interp->paCmd, zName, nName, -1); 1459 - return TH_OK; 1460 -} 1461 - 1462 -/* 1463 -** Push a stack frame onto the interpreter stack, invoke the 1464 -** callback, and pop the frame back off again. See the implementation 1465 -** of [proc] (th_lang.c) for an example. 1466 -*/ 1467 -int Th_InFrame(Th_Interp *interp, 1468 - int (*xCall)(Th_Interp *, void *pContext1, void *pContext2), 1469 - void *pContext1, 1470 - void *pContext2 1471 -){ 1472 - Th_Frame frame; 1473 - int rc; 1474 - thPushFrame(interp, &frame); 1475 - rc = xCall(interp, pContext1, pContext2); 1476 - thPopFrame(interp); 1477 - return rc; 1478 -} 1479 - 1480 -/* 1481 -** Split a th1 list into its component elements. The list to split is 1482 -** passed via arguments (zList, nList). If successful, TH_OK is returned. 1483 -** If an error occurs (if (zList, nList) is not a valid list) an error 1484 -** message is left in the interpreter result and TH_ERROR returned. 1485 -** 1486 -** If successful, *pnCount is set to the number of elements in the list. 1487 -** panElem is set to point at an array of *pnCount integers - the lengths 1488 -** of the element values. *pazElem is set to point at an array of 1489 -** pointers to buffers containing the array element's data. 1490 -** 1491 -** To free the arrays allocated at *pazElem and *panElem, the caller 1492 -** should call Th_Free() on *pazElem only. Exactly one such call to 1493 -** Th_Free() must be made per call to Th_SplitList(). 1494 -** 1495 -** Example: 1496 -** 1497 -** int nElem; 1498 -** int *anElem; 1499 -** char **azElem; 1500 -** int i; 1501 -** 1502 -** Th_SplitList(interp, zList, nList, &azElem, &anElem, &nElem); 1503 -** for(i=0; i<nElem; i++){ 1504 -** int nData = anElem[i]; 1505 -** char *zData = azElem[i]; 1506 -** ... 1507 -** } 1508 -** 1509 -** Th_Free(interp, azElem); 1510 -** 1511 -*/ 1512 -int Th_SplitList( 1513 - Th_Interp *interp, 1514 - const char *zList, /* Pointer to buffer containing list */ 1515 - int nList, /* Number of bytes at zList */ 1516 - char ***pazElem, /* OUT: Array of pointers to element data */ 1517 - int **panElem, /* OUT: Array of element data lengths */ 1518 - int *pnCount /* OUT: Number of elements in list */ 1519 -){ 1520 - int rc; 1521 - interp->isListMode = 1; 1522 - rc = thSplitList(interp, zList, nList, pazElem, panElem, pnCount); 1523 - interp->isListMode = 0; 1524 - if( rc ){ 1525 - Th_ErrorMessage(interp, "Expected list, got: \"", zList, nList); 1526 - } 1527 - return rc; 1528 -} 1529 - 1530 -/* 1531 -** Append a new element to an existing th1 list. The element to append 1532 -** to the list is (zElem, nElem). 1533 -** 1534 -** A pointer to the existing list must be stored at *pzList when this 1535 -** function is called. The length must be stored in *pnList. The value 1536 -** of *pzList must either be NULL (in which case *pnList must be 0), or 1537 -** a pointer to memory obtained from Th_Malloc(). 1538 -** 1539 -** This function calls Th_Free() to free the buffer at *pzList and sets 1540 -** *pzList to point to a new buffer containing the new list value. *pnList 1541 -** is similarly updated before returning. The return value is always TH_OK. 1542 -** 1543 -** Example: 1544 -** 1545 -** char *zList = 0; 1546 -** int nList = 0; 1547 -** for (...) { 1548 -** char *zElem = <some expression>; 1549 -** Th_ListAppend(interp, &zList, &nList, zElem, -1); 1550 -** } 1551 -** Th_SetResult(interp, zList, nList); 1552 -** Th_Free(interp, zList); 1553 -** 1554 -*/ 1555 -int Th_ListAppend( 1556 - Th_Interp *interp, /* Interpreter context */ 1557 - char **pzList, /* IN/OUT: Ptr to ptr to list */ 1558 - int *pnList, /* IN/OUT: Current length of *pzList */ 1559 - const char *zElem, /* Data to append */ 1560 - int nElem /* Length of nElem */ 1561 -){ 1562 - Buffer output; 1563 - int i; 1564 - 1565 - int hasSpecialChar = 0; 1566 - int hasEscapeChar = 0; 1567 - int nBrace = 0; 1568 - 1569 - output.zBuf = *pzList; 1570 - output.nBuf = *pnList; 1571 - output.nBufAlloc = output.nBuf; 1572 - 1573 - if( nElem<0 ){ 1574 - nElem = th_strlen(zElem); 1575 - } 1576 - if( output.nBuf>0 ){ 1577 - thBufferWrite(interp, &output, " ", 1); 1578 - } 1579 - 1580 - for(i=0; i<nElem; i++){ 1581 - char c = zElem[i]; 1582 - if( th_isspecial(c) ) hasSpecialChar = 1; 1583 - if( c=='\\' ) hasEscapeChar = 1; 1584 - if( c=='{' ) nBrace++; 1585 - if( c=='}' ) nBrace--; 1586 - } 1587 - 1588 - if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){ 1589 - thBufferWrite(interp, &output, "{", 1); 1590 - thBufferWrite(interp, &output, zElem, nElem); 1591 - thBufferWrite(interp, &output, "}", 1); 1592 - }else{ 1593 - for(i=0; i<nElem; i++){ 1594 - char c = zElem[i]; 1595 - if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1); 1596 - thBufferWrite(interp, &output, &c, 1); 1597 - } 1598 - } 1599 - 1600 - *pzList = output.zBuf; 1601 - *pnList = output.nBuf; 1602 - 1603 - return TH_OK; 1604 -} 1605 - 1606 -/* 1607 -** Append a new element to an existing th1 string. This function uses 1608 -** the same interface as the Th_ListAppend() function. 1609 -*/ 1610 -int Th_StringAppend( 1611 - Th_Interp *interp, /* Interpreter context */ 1612 - char **pzStr, /* IN/OUT: Ptr to ptr to list */ 1613 - int *pnStr, /* IN/OUT: Current length of *pzStr */ 1614 - const char *zElem, /* Data to append */ 1615 - int nElem /* Length of nElem */ 1616 -){ 1617 - char *zNew; 1618 - int nNew; 1619 - 1620 - if( nElem<0 ){ 1621 - nElem = th_strlen(zElem); 1622 - } 1623 - 1624 - nNew = *pnStr + nElem; 1625 - zNew = Th_Malloc(interp, nNew); 1626 - memcpy(zNew, *pzStr, *pnStr); 1627 - memcpy(&zNew[*pnStr], zElem, nElem); 1628 - 1629 - Th_Free(interp, *pzStr); 1630 - *pzStr = zNew; 1631 - *pnStr = nNew; 1632 - 1633 - return TH_OK; 1634 -} 1635 - 1636 -/* 1637 -** Delete an interpreter. 1638 -*/ 1639 -void Th_DeleteInterp(Th_Interp *interp){ 1640 - assert(interp->pFrame); 1641 - assert(0==interp->pFrame->pCaller); 1642 - 1643 - /* Delete the contents of the global frame. */ 1644 - thPopFrame(interp); 1645 - 1646 - /* Delete any result currently stored in the interpreter. */ 1647 - Th_SetResult(interp, 0, 0); 1648 - 1649 - /* Delete all registered commands and the command hash-table itself. */ 1650 - Th_HashIterate(interp, interp->paCmd, thFreeCommand, (void *)interp); 1651 - Th_HashDelete(interp, interp->paCmd); 1652 - 1653 - /* Delete the interpreter structure itself. */ 1654 - Th_Free(interp, (void *)interp); 1655 -} 1656 - 1657 -/* 1658 -** Create a new interpreter. 1659 -*/ 1660 -Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){ 1661 - Th_Interp *p; 1662 - 1663 - /* Allocate and initialise the interpreter and the global frame */ 1664 - p = pVtab->xMalloc(sizeof(Th_Interp) + sizeof(Th_Frame)); 1665 - memset(p, 0, sizeof(Th_Interp)); 1666 - p->pVtab = pVtab; 1667 - p->paCmd = Th_HashNew(p); 1668 - thPushFrame(p, (Th_Frame *)&p[1]); 1669 - 1670 - return p; 1671 -} 1672 - 1673 -/* 1674 -** These two types are used only by the expression module, where 1675 -** the expression module means the Th_Expr() and exprXXX() functions. 1676 -*/ 1677 -typedef struct Operator Operator; 1678 -struct Operator { 1679 - const char *zOp; 1680 - int eOp; 1681 - int iPrecedence; 1682 - int eArgType; 1683 -}; 1684 -typedef struct Expr Expr; 1685 -struct Expr { 1686 - Operator *pOp; 1687 - Expr *pParent; 1688 - Expr *pLeft; 1689 - Expr *pRight; 1690 - 1691 - char *zValue; /* Pointer to literal value */ 1692 - int nValue; /* Length of literal value buffer */ 1693 -}; 1694 - 1695 -/* Unary operators */ 1696 -#define OP_UNARY_MINUS 2 1697 -#define OP_UNARY_PLUS 3 1698 -#define OP_BITWISE_NOT 4 1699 -#define OP_LOGICAL_NOT 5 1700 - 1701 -/* Binary operators */ 1702 -#define OP_MULTIPLY 6 1703 -#define OP_DIVIDE 7 1704 -#define OP_MODULUS 8 1705 -#define OP_ADD 9 1706 -#define OP_SUBTRACT 10 1707 -#define OP_LEFTSHIFT 11 1708 -#define OP_RIGHTSHIFT 12 1709 -#define OP_LT 13 1710 -#define OP_GT 14 1711 -#define OP_LE 15 1712 -#define OP_GE 16 1713 -#define OP_EQ 17 1714 -#define OP_NE 18 1715 -#define OP_SEQ 19 1716 -#define OP_SNE 20 1717 -#define OP_BITWISE_AND 21 1718 -#define OP_BITWISE_XOR 22 1719 -#define OP_BITWISE_OR 24 1720 -#define OP_LOGICAL_AND 25 1721 -#define OP_LOGICAL_OR 26 1722 - 1723 -/* Other symbols */ 1724 -#define OP_OPEN_BRACKET 27 1725 -#define OP_CLOSE_BRACKET 28 1726 - 1727 -/* Argument types. Each operator in the expression syntax is defined 1728 -** as requiring either integer, number (real or integer) or string 1729 -** operands. 1730 -*/ 1731 -#define ARG_INTEGER 1 1732 -#define ARG_NUMBER 2 1733 -#define ARG_STRING 3 1734 - 1735 -static Operator aOperator[] = { 1736 - 1737 - {"(", OP_OPEN_BRACKET, -1, 0}, 1738 - {")", OP_CLOSE_BRACKET, -1, 0}, 1739 - 1740 - /* Note: all unary operators have (iPrecedence==1) */ 1741 - {"-", OP_UNARY_MINUS, 1, ARG_NUMBER}, 1742 - {"+", OP_UNARY_PLUS, 1, ARG_NUMBER}, 1743 - {"~", OP_BITWISE_NOT, 1, ARG_INTEGER}, 1744 - {"!", OP_LOGICAL_NOT, 1, ARG_INTEGER}, 1745 - 1746 - /* Binary operators. It is important to the parsing in Th_Expr() that 1747 - * the two-character symbols ("==") appear before the one-character 1748 - * ones ("="). And that the priorities of all binary operators are 1749 - * integers between 2 and 12. 1750 - */ 1751 - {"<<", OP_LEFTSHIFT, 4, ARG_INTEGER}, 1752 - {">>", OP_RIGHTSHIFT, 4, ARG_INTEGER}, 1753 - {"<=", OP_LE, 5, ARG_NUMBER}, 1754 - {">=", OP_GE, 5, ARG_NUMBER}, 1755 - {"==", OP_EQ, 6, ARG_NUMBER}, 1756 - {"!=", OP_NE, 6, ARG_NUMBER}, 1757 - {"eq", OP_SEQ, 7, ARG_STRING}, 1758 - {"ne", OP_SNE, 7, ARG_STRING}, 1759 - {"&&", OP_LOGICAL_AND, 11, ARG_INTEGER}, 1760 - {"||", OP_LOGICAL_OR, 12, ARG_INTEGER}, 1761 - 1762 - {"*", OP_MULTIPLY, 2, ARG_NUMBER}, 1763 - {"/", OP_DIVIDE, 2, ARG_NUMBER}, 1764 - {"%", OP_MODULUS, 2, ARG_INTEGER}, 1765 - {"+", OP_ADD, 3, ARG_NUMBER}, 1766 - {"-", OP_SUBTRACT, 3, ARG_NUMBER}, 1767 - {"<", OP_LT, 5, ARG_NUMBER}, 1768 - {">", OP_GT, 5, ARG_NUMBER}, 1769 - {"&", OP_BITWISE_AND, 8, ARG_INTEGER}, 1770 - {"^", OP_BITWISE_XOR, 9, ARG_INTEGER}, 1771 - {"|", OP_BITWISE_OR, 10, ARG_INTEGER}, 1772 - 1773 - {0,0,0} 1774 -}; 1775 - 1776 -/* 1777 -** The first part of the string (zInput,nInput) contains a number. 1778 -** Set *pnVarname to the number of bytes in the numeric string. 1779 -*/ 1780 -static int thNextNumber( 1781 - Th_Interp *interp, 1782 - const char *zInput, 1783 - int nInput, 1784 - int *pnLiteral 1785 -){ 1786 - int i; 1787 - int seenDot = 0; 1788 - for(i=0; i<nInput; i++){ 1789 - char c = zInput[i]; 1790 - if( (seenDot || c!='.') && !th_isdigit(c) ) break; 1791 - if( c=='.' ) seenDot = 1; 1792 - } 1793 - *pnLiteral = i; 1794 - return TH_OK; 1795 -} 1796 - 1797 -/* 1798 -** Free an expression tree. 1799 -*/ 1800 -static void exprFree(Th_Interp *interp, Expr *pExpr){ 1801 - if( pExpr ){ 1802 - exprFree(interp, pExpr->pLeft); 1803 - exprFree(interp, pExpr->pRight); 1804 - Th_Free(interp, pExpr->zValue); 1805 - Th_Free(interp, pExpr); 1806 - } 1807 -} 1808 - 1809 -/* 1810 -** Evaluate an expression tree. 1811 -*/ 1812 -static int exprEval(Th_Interp *interp, Expr *pExpr){ 1813 - int rc = TH_OK; 1814 - 1815 - if( pExpr->pOp==0 ){ 1816 - /* A literal */ 1817 - rc = thSubstWord(interp, pExpr->zValue, pExpr->nValue); 1818 - }else{ 1819 - int eArgType = 0; /* Actual type of arguments */ 1820 - 1821 - /* Argument values */ 1822 - int iLeft = 0; 1823 - int iRight = 0; 1824 - double fLeft; 1825 - double fRight; 1826 - 1827 - /* Left and right arguments as strings */ 1828 - char *zLeft = 0; int nLeft = 0; 1829 - char *zRight = 0; int nRight = 0; 1830 - 1831 - /* Evaluate left and right arguments, if they exist. */ 1832 - if( pExpr->pLeft ){ 1833 - rc = exprEval(interp, pExpr->pLeft); 1834 - if( rc==TH_OK ){ 1835 - zLeft = Th_TakeResult(interp, &nLeft); 1836 - } 1837 - } 1838 - if( rc==TH_OK && pExpr->pRight ){ 1839 - rc = exprEval(interp, pExpr->pRight); 1840 - if( rc==TH_OK ){ 1841 - zRight = Th_TakeResult(interp, &nRight); 1842 - } 1843 - } 1844 - 1845 - /* Convert arguments to their required forms. */ 1846 - if( rc==TH_OK ){ 1847 - eArgType = pExpr->pOp->eArgType; 1848 - if( eArgType==ARG_NUMBER ){ 1849 - if( (zLeft==0 || TH_OK==Th_ToInt(0, zLeft, nLeft, &iLeft)) 1850 - && (zRight==0 || TH_OK==Th_ToInt(0, zRight, nRight, &iRight)) 1851 - ){ 1852 - eArgType = ARG_INTEGER; 1853 - }else if( 1854 - (zLeft && TH_OK!=Th_ToDouble(interp, zLeft, nLeft, &fLeft)) || 1855 - (zRight && TH_OK!=Th_ToDouble(interp, zRight, nRight, &fRight)) 1856 - ){ 1857 - /* A type error. */ 1858 - rc = TH_ERROR; 1859 - } 1860 - }else if( eArgType==ARG_INTEGER ){ 1861 - rc = Th_ToInt(interp, zLeft, nLeft, &iLeft); 1862 - if( rc==TH_OK && zRight ){ 1863 - rc = Th_ToInt(interp, zRight, nRight, &iRight); 1864 - } 1865 - } 1866 - } 1867 - 1868 - if( rc==TH_OK && eArgType==ARG_INTEGER ){ 1869 - int iRes = 0; 1870 - switch( pExpr->pOp->eOp ) { 1871 - case OP_MULTIPLY: iRes = iLeft*iRight; break; 1872 - case OP_DIVIDE: iRes = iLeft/iRight; break; 1873 - case OP_MODULUS: iRes = iLeft%iRight; break; 1874 - case OP_ADD: iRes = iLeft+iRight; break; 1875 - case OP_SUBTRACT: iRes = iLeft-iRight; break; 1876 - case OP_LEFTSHIFT: iRes = iLeft<<iRight; break; 1877 - case OP_RIGHTSHIFT: iRes = iLeft>>iRight; break; 1878 - case OP_LT: iRes = iLeft<iRight; break; 1879 - case OP_GT: iRes = iLeft>iRight; break; 1880 - case OP_LE: iRes = iLeft<=iRight; break; 1881 - case OP_GE: iRes = iLeft>=iRight; break; 1882 - case OP_EQ: iRes = iLeft==iRight; break; 1883 - case OP_NE: iRes = iLeft!=iRight; break; 1884 - case OP_BITWISE_AND: iRes = iLeft&iRight; break; 1885 - case OP_BITWISE_XOR: iRes = iLeft^iRight; break; 1886 - case OP_BITWISE_OR: iRes = iLeft|iRight; break; 1887 - case OP_LOGICAL_AND: iRes = iLeft&&iRight; break; 1888 - case OP_LOGICAL_OR: iRes = iLeft||iRight; break; 1889 - case OP_UNARY_MINUS: iRes = -iLeft; break; 1890 - case OP_UNARY_PLUS: iRes = +iLeft; break; 1891 - case OP_LOGICAL_NOT: iRes = !iLeft; break; 1892 - default: assert(!"Internal error"); 1893 - } 1894 - Th_SetResultInt(interp, iRes); 1895 - }else if( rc==TH_OK && eArgType==ARG_NUMBER ){ 1896 - switch( pExpr->pOp->eOp ) { 1897 - case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; 1898 - case OP_DIVIDE: Th_SetResultDouble(interp, fLeft/fRight); break; 1899 - case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; 1900 - case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; 1901 - case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break; 1902 - case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break; 1903 - case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; 1904 - case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break; 1905 - case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break; 1906 - case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break; 1907 - default: assert(!"Internal error"); 1908 - } 1909 - }else if( rc==TH_OK ){ 1910 - int iEqual = 0; 1911 - assert( eArgType==ARG_STRING ); 1912 - if( nRight==nLeft && 0==memcmp(zRight, zLeft, nRight) ){ 1913 - iEqual = 1; 1914 - } 1915 - switch( pExpr->pOp->eOp ) { 1916 - case OP_SEQ: Th_SetResultInt(interp, iEqual); break; 1917 - case OP_SNE: Th_SetResultInt(interp, !iEqual); break; 1918 - default: assert(!"Internal error"); 1919 - } 1920 - } 1921 - 1922 - Th_Free(interp, zLeft); 1923 - Th_Free(interp, zRight); 1924 - } 1925 - 1926 - return rc; 1927 -} 1928 - 1929 -/* 1930 -** Create an expression tree from an array of tokens. If successful, 1931 -** the root of the tree is stored in apToken[0]. 1932 -*/ 1933 -int exprMakeTree(Th_Interp *interp, Expr **apToken, int nToken){ 1934 - int iLeft; 1935 - int i; 1936 - int jj; 1937 - 1938 - assert(nToken>0); 1939 -#define ISTERM(x) (apToken[x] && (!apToken[x]->pOp || apToken[x]->pLeft)) 1940 - 1941 - for(jj=0; jj<nToken; jj++){ 1942 - if( apToken[jj]->pOp && apToken[jj]->pOp->eOp==OP_OPEN_BRACKET ){ 1943 - int nNest = 1; 1944 - int iLeft = jj; 1945 - 1946 - for(jj++; jj<nToken; jj++){ 1947 - Operator *pOp = apToken[jj]->pOp; 1948 - if( pOp && pOp->eOp==OP_OPEN_BRACKET ) nNest++; 1949 - if( pOp && pOp->eOp==OP_CLOSE_BRACKET ) nNest--; 1950 - if( nNest==0 ) break; 1951 - } 1952 - if( jj==nToken ){ 1953 - return TH_ERROR; 1954 - } 1955 - if( (jj-iLeft)>1 ){ 1956 - if( exprMakeTree(interp, &apToken[iLeft+1], jj-iLeft-1) ){ 1957 - return TH_ERROR; 1958 - } 1959 - exprFree(interp, apToken[jj]); 1960 - exprFree(interp, apToken[iLeft]); 1961 - apToken[jj] = 0; 1962 - apToken[iLeft] = 0; 1963 - } 1964 - } 1965 - } 1966 - 1967 - iLeft = 0; 1968 - for(jj=nToken-1; jj>=0; jj--){ 1969 - if( apToken[jj] ){ 1970 - if( apToken[jj]->pOp && apToken[jj]->pOp->iPrecedence==1 && iLeft>0 ){ 1971 - apToken[jj]->pLeft = apToken[iLeft]; 1972 - apToken[jj]->pLeft->pParent = apToken[jj]; 1973 - apToken[iLeft] = 0; 1974 - } 1975 - iLeft = jj; 1976 - } 1977 - } 1978 - for(i=2; i<=12; i++){ 1979 - iLeft = -1; 1980 - for(jj=0; jj<nToken; jj++){ 1981 - Expr *pToken = apToken[jj]; 1982 - if( apToken[jj] ){ 1983 - if( pToken->pOp && !pToken->pLeft && pToken->pOp->iPrecedence==i ){ 1984 - int iRight = jj+1; 1985 - 1986 - iRight = jj+1; 1987 - for(iRight=jj+1; !apToken[iRight] && iRight<nToken; iRight++); 1988 - if( iRight==nToken || iLeft<0 || !ISTERM(iRight) || !ISTERM(iLeft) ){ 1989 - return TH_ERROR; 1990 - } 1991 - pToken->pLeft = apToken[iLeft]; 1992 - apToken[iLeft] = 0; 1993 - pToken->pLeft->pParent = pToken; 1994 - pToken->pRight = apToken[iRight]; 1995 - apToken[iRight] = 0; 1996 - pToken->pRight->pParent = pToken; 1997 - } 1998 - iLeft = jj; 1999 - } 2000 - } 2001 - } 2002 - for(jj=1; jj<nToken; jj++){ 2003 - assert( !apToken[jj] || !apToken[0] ); 2004 - if( apToken[jj] ){ 2005 - apToken[0] = apToken[jj]; 2006 - apToken[jj] = 0; 2007 - } 2008 - } 2009 - 2010 - return TH_OK; 2011 -} 2012 - 2013 -/* 2014 -** Parse a string containing a TH expression to a list of tokens. 2015 -*/ 2016 -static int exprParse( 2017 - Th_Interp *interp, /* Interpreter to leave error message in */ 2018 - const char *zExpr, /* Pointer to input string */ 2019 - int nExpr, /* Number of bytes at zExpr */ 2020 - Expr ***papToken, /* OUT: Array of tokens. */ 2021 - int *pnToken /* OUT: Size of token array */ 2022 -){ 2023 - int i; 2024 - 2025 - int rc = TH_OK; 2026 - int nToken = 0; 2027 - Expr **apToken = 0; 2028 - 2029 - for(i=0; rc==TH_OK && i<nExpr; ){ 2030 - char c = zExpr[i]; 2031 - if( th_isspace(c) ){ /* White-space */ 2032 - i++; 2033 - }else{ 2034 - Expr *pNew = (Expr *)Th_Malloc(interp, sizeof(Expr)); 2035 - const char *z = &zExpr[i]; 2036 - 2037 - switch (c) { 2038 - case '0': case '1': case '2': case '3': case '4': 2039 - case '5': case '6': case '7': case '8': case '9': 2040 - thNextNumber(interp, z, nExpr-i, &pNew->nValue); 2041 - break; 2042 - 2043 - case '$': 2044 - thNextVarname(interp, z, nExpr-i, &pNew->nValue); 2045 - break; 2046 - 2047 - case '{': case '[': { 2048 - thNextCommand(interp, z, nExpr-i, &pNew->nValue); 2049 - break; 2050 - } 2051 - 2052 - case '"': { 2053 - int iEnd = i; 2054 - while( ++iEnd<nExpr && zExpr[iEnd]!='"' ){ 2055 - if( zExpr[iEnd]=='\\' ) iEnd++; 2056 - } 2057 - if( iEnd<nExpr ){ 2058 - pNew->nValue = iEnd+1-i; 2059 - } 2060 - break; 2061 - } 2062 - 2063 - default: { 2064 - int j; 2065 - for(j=0; aOperator[j].zOp; j++){ 2066 - int nOp; 2067 - if( aOperator[j].iPrecedence==1 && nToken>0 ){ 2068 - Expr *pPrev = apToken[nToken-1]; 2069 - if( !pPrev->pOp || pPrev->pOp->eOp==OP_CLOSE_BRACKET ){ 2070 - continue; 2071 - } 2072 - } 2073 - nOp = th_strlen((const char *)aOperator[j].zOp); 2074 - if( (nExpr-i)>=nOp && 0==memcmp(aOperator[j].zOp, &zExpr[i], nOp) ){ 2075 - pNew->pOp = &aOperator[j]; 2076 - i += nOp; 2077 - break; 2078 - } 2079 - } 2080 - } 2081 - } 2082 - 2083 - if( pNew->pOp || pNew->nValue ){ 2084 - if( pNew->nValue ){ 2085 - /* A terminal. Copy the string value. */ 2086 - assert( !pNew->pOp ); 2087 - pNew->zValue = Th_Malloc(interp, pNew->nValue); 2088 - memcpy(pNew->zValue, z, pNew->nValue); 2089 - i += pNew->nValue; 2090 - } 2091 - if( (nToken%16)==0 ){ 2092 - /* Grow the apToken array. */ 2093 - Expr **apTokenOld = apToken; 2094 - apToken = Th_Malloc(interp, sizeof(Expr *)*(nToken+16)); 2095 - memcpy(apToken, apTokenOld, sizeof(Expr *)*nToken); 2096 - } 2097 - 2098 - /* Put the new token at the end of the apToken array */ 2099 - apToken[nToken] = pNew; 2100 - nToken++; 2101 - }else{ 2102 - Th_Free(interp, pNew); 2103 - rc = TH_ERROR; 2104 - } 2105 - } 2106 - } 2107 - 2108 - *papToken = apToken; 2109 - *pnToken = nToken; 2110 - return rc; 2111 -} 2112 - 2113 -/* 2114 -** Evaluate the string (zExpr, nExpr) as a Th expression. Store 2115 -** the result in the interpreter interp and return TH_OK if 2116 -** successful. If an error occurs, store an error message in 2117 -** the interpreter result and return an error code. 2118 -*/ 2119 -int Th_Expr(Th_Interp *interp, const char *zExpr, int nExpr){ 2120 - int rc; /* Return Code */ 2121 - int i; /* Loop counter */ 2122 - 2123 - int nToken = 0; 2124 - Expr **apToken = 0; 2125 - 2126 - if( nExpr<0 ){ 2127 - nExpr = th_strlen(zExpr); 2128 - } 2129 - 2130 - /* Parse the expression to a list of tokens. */ 2131 - rc = exprParse(interp, zExpr, nExpr, &apToken, &nToken); 2132 - 2133 - /* If the parsing was successful, create an expression tree from 2134 - ** the parsed list of tokens. If successful, apToken[0] is set 2135 - ** to point to the root of the expression tree. 2136 - */ 2137 - if( rc==TH_OK ){ 2138 - rc = exprMakeTree(interp, apToken, nToken); 2139 - } 2140 - 2141 - if( rc!=TH_OK ){ 2142 - Th_ErrorMessage(interp, "syntax error in expression: \"", zExpr, nExpr); 2143 - } 2144 - 2145 - /* Evaluate the expression tree. */ 2146 - if( rc==TH_OK ){ 2147 - rc = exprEval(interp, apToken[0]); 2148 - } 2149 - 2150 - /* Free memory allocated by exprParse(). */ 2151 - for(i=0; i<nToken; i++){ 2152 - exprFree(interp, apToken[i]); 2153 - } 2154 - Th_Free(interp, apToken); 2155 - 2156 - return rc; 2157 -} 2158 - 2159 -/* 2160 -** Allocate and return a pointer to a new hash-table. The caller should 2161 -** (eventually) delete the hash-table by passing it to Th_HashDelete(). 2162 -*/ 2163 -Th_Hash *Th_HashNew(Th_Interp *interp){ 2164 - Th_Hash *p; 2165 - p = Th_Malloc(interp, sizeof(Th_Hash)); 2166 - return p; 2167 -} 2168 - 2169 -/* 2170 -** Iterate through all values currently stored in the hash table. Invoke 2171 -** the callback function xCallback for each entry. The second argument 2172 -** passed to xCallback is a copy of the fourth argument passed to this 2173 -** function. 2174 -*/ 2175 -void Th_HashIterate( 2176 - Th_Interp *interp, 2177 - Th_Hash *pHash, 2178 - void (*xCallback)(Th_HashEntry *pEntry, void *pContext), 2179 - void *pContext 2180 -){ 2181 - int i; 2182 - for(i=0; i<TH_HASHSIZE; i++){ 2183 - Th_HashEntry *pEntry; 2184 - Th_HashEntry *pNext; 2185 - for(pEntry=pHash->a[i]; pEntry; pEntry=pNext){ 2186 - pNext = pEntry->pNext; 2187 - xCallback(pEntry, pContext); 2188 - } 2189 - } 2190 -} 2191 - 2192 -/* 2193 -** Helper function for Th_HashDelete(). 2194 -*/ 2195 -static void xFreeHashEntry(Th_HashEntry *pEntry, void *pContext){ 2196 - Th_Free((Th_Interp *)pContext, (void *)pEntry); 2197 -} 2198 - 2199 -/* 2200 -** Free a hash-table previously allocated by Th_HashNew(). 2201 -*/ 2202 -void Th_HashDelete(Th_Interp *interp, Th_Hash *pHash){ 2203 - if( pHash ){ 2204 - Th_HashIterate(interp, pHash, xFreeHashEntry, (void *)interp); 2205 - Th_Free(interp, pHash); 2206 - } 2207 -} 2208 - 2209 -/* 2210 -** This function is used to insert or delete hash table items, or to 2211 -** query a hash table for an existing item. 2212 -** 2213 -** If parameter op is less than zero, then the hash-table element 2214 -** identified by (zKey, nKey) is removed from the hash-table if it 2215 -** exists. NULL is returned. 2216 -** 2217 -** Otherwise, if the hash-table contains an item with key (zKey, nKey), 2218 -** a pointer to the associated Th_HashEntry is returned. If parameter 2219 -** op is greater than zero, then a new entry is added if one cannot 2220 -** be found. If op is zero, then NULL is returned if the item is 2221 -** not already present in the hash-table. 2222 -*/ 2223 -Th_HashEntry *Th_HashFind( 2224 - Th_Interp *interp, 2225 - Th_Hash *pHash, 2226 - const char *zKey, 2227 - int nKey, 2228 - int op /* -ve = delete, 0 = find, +ve = insert */ 2229 -){ 2230 - unsigned int iKey = 0; 2231 - int i; 2232 - Th_HashEntry *pRet; 2233 - Th_HashEntry **ppRet; 2234 - 2235 - if( nKey<0 ){ 2236 - nKey = th_strlen(zKey); 2237 - } 2238 - 2239 - for(i=0; i<nKey; i++){ 2240 - iKey = (iKey<<3) ^ iKey ^ zKey[i]; 2241 - } 2242 - iKey = iKey % TH_HASHSIZE; 2243 - 2244 - for(ppRet=&pHash->a[iKey]; (pRet=*ppRet); ppRet=&pRet->pNext){ 2245 - assert( pRet && ppRet && *ppRet==pRet ); 2246 - if( pRet->nKey==nKey && 0==memcmp(pRet->zKey, zKey, nKey) ) break; 2247 - } 2248 - 2249 - if( op<0 && pRet ){ 2250 - assert( ppRet && *ppRet==pRet ); 2251 - *ppRet = pRet->pNext; 2252 - Th_Free(interp, pRet); 2253 - pRet = 0; 2254 - } 2255 - 2256 - if( op>0 && !pRet ){ 2257 - pRet = (Th_HashEntry *)Th_Malloc(interp, sizeof(Th_HashEntry) + nKey); 2258 - pRet->zKey = (char *)&pRet[1]; 2259 - pRet->nKey = nKey; 2260 - memcpy(pRet->zKey, zKey, nKey); 2261 - pRet->pNext = pHash->a[iKey]; 2262 - pHash->a[iKey] = pRet; 2263 - } 2264 - 2265 - return pRet; 2266 -} 2267 - 2268 -/* 2269 -** This function is the same as the standard strlen() function, except 2270 -** that it returns 0 (instead of being undefined) if the argument is 2271 -** a null pointer. 2272 -*/ 2273 -int th_strlen(const char *zStr){ 2274 - int n = 0; 2275 - if( zStr ){ 2276 - while( zStr[n] ) n++; 2277 - } 2278 - return n; 2279 -} 2280 - 2281 -/* Whitespace characters: 2282 -** 2283 -** ' ' 0x20 2284 -** '\t' 0x09 2285 -** '\n' 0x0A 2286 -** '\v' 0x0B 2287 -** '\f' 0x0C 2288 -** '\r' 0x0D 2289 -** 2290 -** Whitespace characters have the 0x01 flag set. Decimal digits have the 2291 -** 0x2 flag set. Single byte printable characters have the 0x4 flag set. 2292 -** Alphabet characters have the 0x8 bit set. 2293 -** 2294 -** The special list characters have the 0x10 flag set 2295 -** 2296 -** { } [ ] \ ; ' " 2297 -** 2298 -** " 0x22 2299 -** 2300 -*/ 2301 -static unsigned char aCharProp[256] = { 2302 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */ 2303 - 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */ 2304 - 5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */ 2305 - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 20, 4, 4, 4, 4, /* 0x3. */ 2306 - 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */ 2307 - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */ 2308 - 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */ 2309 - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */ 2310 - 2311 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */ 2312 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */ 2313 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */ 2314 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB. */ 2315 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC. */ 2316 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD. */ 2317 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE. */ 2318 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF. */ 2319 -}; 2320 - 2321 -/* 2322 -** Clone of the standard isspace() and isdigit function/macros. 2323 -*/ 2324 -int th_isspace(char c){ 2325 - return (aCharProp[(unsigned char)c] & 0x01); 2326 -} 2327 -int th_isdigit(char c){ 2328 - return (aCharProp[(unsigned char)c] & 0x02); 2329 -} 2330 -int th_isspecial(char c){ 2331 - return (aCharProp[(unsigned char)c] & 0x11); 2332 -} 2333 -int th_isalnum(char c){ 2334 - return (aCharProp[(unsigned char)c] & 0x0A); 2335 -} 2336 - 2337 -#ifndef LONGDOUBLE_TYPE 2338 -# define LONGDOUBLE_TYPE long double 2339 -#endif 2340 -typedef char u8; 2341 - 2342 - 2343 -/* 2344 -** Return TRUE if z is a pure numeric string. Return FALSE if the 2345 -** string contains any character which is not part of a number. If 2346 -** the string is numeric and contains the '.' character, set *realnum 2347 -** to TRUE (otherwise FALSE). 2348 -** 2349 -** An empty string is considered non-numeric. 2350 -*/ 2351 -static int sqlite3IsNumber(const char *z, int *realnum){ 2352 - int incr = 1; 2353 - if( *z=='-' || *z=='+' ) z += incr; 2354 - if( !th_isdigit(*(u8*)z) ){ 2355 - return 0; 2356 - } 2357 - z += incr; 2358 - if( realnum ) *realnum = 0; 2359 - while( th_isdigit(*(u8*)z) ){ z += incr; } 2360 - if( *z=='.' ){ 2361 - z += incr; 2362 - if( !th_isdigit(*(u8*)z) ) return 0; 2363 - while( th_isdigit(*(u8*)z) ){ z += incr; } 2364 - if( realnum ) *realnum = 1; 2365 - } 2366 - if( *z=='e' || *z=='E' ){ 2367 - z += incr; 2368 - if( *z=='+' || *z=='-' ) z += incr; 2369 - if( !th_isdigit(*(u8*)z) ) return 0; 2370 - while( th_isdigit(*(u8*)z) ){ z += incr; } 2371 - if( realnum ) *realnum = 1; 2372 - } 2373 - return *z==0; 2374 -} 2375 - 2376 -/* 2377 -** The string z[] is an ascii representation of a real number. 2378 -** Convert this string to a double. 2379 -** 2380 -** This routine assumes that z[] really is a valid number. If it 2381 -** is not, the result is undefined. 2382 -** 2383 -** This routine is used instead of the library atof() function because 2384 -** the library atof() might want to use "," as the decimal point instead 2385 -** of "." depending on how locale is set. But that would cause problems 2386 -** for SQL. So this routine always uses "." regardless of locale. 2387 -*/ 2388 -static int sqlite3AtoF(const char *z, double *pResult){ 2389 - int sign = 1; 2390 - const char *zBegin = z; 2391 - LONGDOUBLE_TYPE v1 = 0.0; 2392 - while( th_isspace(*(u8*)z) ) z++; 2393 - if( *z=='-' ){ 2394 - sign = -1; 2395 - z++; 2396 - }else if( *z=='+' ){ 2397 - z++; 2398 - } 2399 - while( th_isdigit(*(u8*)z) ){ 2400 - v1 = v1*10.0 + (*z - '0'); 2401 - z++; 2402 - } 2403 - if( *z=='.' ){ 2404 - LONGDOUBLE_TYPE divisor = 1.0; 2405 - z++; 2406 - while( th_isdigit(*(u8*)z) ){ 2407 - v1 = v1*10.0 + (*z - '0'); 2408 - divisor *= 10.0; 2409 - z++; 2410 - } 2411 - v1 /= divisor; 2412 - } 2413 - if( *z=='e' || *z=='E' ){ 2414 - int esign = 1; 2415 - int eval = 0; 2416 - LONGDOUBLE_TYPE scale = 1.0; 2417 - z++; 2418 - if( *z=='-' ){ 2419 - esign = -1; 2420 - z++; 2421 - }else if( *z=='+' ){ 2422 - z++; 2423 - } 2424 - while( th_isdigit(*(u8*)z) ){ 2425 - eval = eval*10 + *z - '0'; 2426 - z++; 2427 - } 2428 - while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; } 2429 - while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; } 2430 - while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; } 2431 - while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } 2432 - if( esign<0 ){ 2433 - v1 /= scale; 2434 - }else{ 2435 - v1 *= scale; 2436 - } 2437 - } 2438 - *pResult = sign<0 ? -v1 : v1; 2439 - return z - zBegin; 2440 -} 2441 - 2442 -/* 2443 -** Try to convert the string passed as arguments (z, n) to an integer. 2444 -** If successful, store the result in *piOut and return TH_OK. 2445 -** 2446 -** If the string cannot be converted to an integer, return TH_ERROR. 2447 -** If the interp argument is not NULL, leave an error message in the 2448 -** interpreter result too. 2449 -*/ 2450 -int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){ 2451 - int i = 0; 2452 - int iOut = 0; 2453 - 2454 - if( n<0 ){ 2455 - n = th_strlen(z); 2456 - } 2457 - 2458 - if( n>0 && (z[0]=='-' || z[0]=='+') ){ 2459 - i = 1; 2460 - } 2461 - for(; i<n; i++){ 2462 - if( !th_isdigit(z[i]) ){ 2463 - Th_ErrorMessage(interp, "expected integer, got: \"", z, n); 2464 - return TH_ERROR; 2465 - } 2466 - iOut = iOut * 10 + (z[i] - 48); 2467 - } 2468 - 2469 - if( n>0 && z[0]=='-' ){ 2470 - iOut *= -1; 2471 - } 2472 - 2473 - *piOut = iOut; 2474 - return TH_OK; 2475 -} 2476 - 2477 -/* 2478 -** Try to convert the string passed as arguments (z, n) to a double. 2479 -** If successful, store the result in *pfOut and return TH_OK. 2480 -** 2481 -** If the string cannot be converted to a double, return TH_ERROR. 2482 -** If the interp argument is not NULL, leave an error message in the 2483 -** interpreter result too. 2484 -*/ 2485 -int Th_ToDouble( 2486 - Th_Interp *interp, 2487 - const char *z, 2488 - int n, 2489 - double *pfOut 2490 -){ 2491 - if( !sqlite3IsNumber((const char *)z, 0) ){ 2492 - Th_ErrorMessage(interp, "expected number, got: \"", z, n); 2493 - return TH_ERROR; 2494 - } 2495 - 2496 - sqlite3AtoF((const char *)z, pfOut); 2497 - return TH_OK; 2498 -} 2499 - 2500 -/* 2501 -** Set the result of the interpreter to the th1 representation of 2502 -** the integer iVal and return TH_OK. 2503 -*/ 2504 -int Th_SetResultInt(Th_Interp *interp, int iVal){ 2505 - int isNegative = 0; 2506 - char zBuf[32]; 2507 - char *z = &zBuf[32]; 2508 - 2509 - if( iVal<0 ){ 2510 - isNegative = 1; 2511 - iVal = iVal * -1; 2512 - } 2513 - *(--z) = '\0'; 2514 - *(--z) = (char)(48+(iVal%10)); 2515 - while( (iVal = (iVal/10))>0 ){ 2516 - *(--z) = (char)(48+(iVal%10)); 2517 - assert(z>zBuf); 2518 - } 2519 - if( isNegative ){ 2520 - *(--z) = '-'; 2521 - } 2522 - 2523 - return Th_SetResult(interp, z, -1); 2524 -} 2525 - 2526 -/* 2527 -** Set the result of the interpreter to the th1 representation of 2528 -** the double fVal and return TH_OK. 2529 -*/ 2530 -int Th_SetResultDouble(Th_Interp *interp, double fVal){ 2531 - int i; /* Iterator variable */ 2532 - double v = fVal; /* Input value */ 2533 - char zBuf[128]; /* Output buffer */ 2534 - char *z = zBuf; /* Output cursor */ 2535 - int iDot = 0; /* Digit after which to place decimal point */ 2536 - int iExp = 0; /* Exponent (NN in eNN) */ 2537 - const char *zExp; /* String representation of iExp */ 2538 - 2539 - /* Precision: */ 2540 - #define INSIGNIFICANT 0.000000000001 2541 - #define ROUNDER 0.0000000000005 2542 - double insignificant = INSIGNIFICANT; 2543 - 2544 - /* If the real value is negative, write a '-' character to the 2545 - * output and transform v to the corresponding positive number. 2546 - */ 2547 - if( v<0.0 ){ 2548 - *z++ = '-'; 2549 - v *= -1.0; 2550 - } 2551 - 2552 - /* Normalize v to a value between 1.0 and 10.0. Integer 2553 - * variable iExp is set to the exponent. i.e the original 2554 - * value is (v * 10^iExp) (or the negative thereof). 2555 - */ 2556 - if( v>0.0 ){ 2557 - while( (v+ROUNDER)>=10.0 ) { iExp++; v *= 0.1; } 2558 - while( (v+ROUNDER)<1.0 ) { iExp--; v *= 10.0; } 2559 - } 2560 - v += ROUNDER; 2561 - 2562 - /* For a small (<12) positive exponent, move the decimal point 2563 - * instead of using the "eXX" notation. 2564 - */ 2565 - if( iExp>0 && iExp<12 ){ 2566 - iDot = iExp; 2567 - iExp = 0; 2568 - } 2569 - 2570 - /* For a small (>-4) negative exponent, write leading zeroes 2571 - * instead of using the "eXX" notation. 2572 - */ 2573 - if( iExp<0 && iExp>-4 ){ 2574 - *z++ = '0'; 2575 - *z++ = '.'; 2576 - for(i=0; i>(iExp+1); i--){ 2577 - *z++ = '0'; 2578 - } 2579 - iDot = -1; 2580 - iExp = 0; 2581 - } 2582 - 2583 - /* Output the digits in real value v. The value of iDot determines 2584 - * where (if at all) the decimal point is placed. 2585 - */ 2586 - for(i=0; i<=(iDot+1) || v>=insignificant; i++){ 2587 - *z++ = (char)(48 + (int)v); 2588 - v = (v - ((double)(int)v)) * 10.0; 2589 - insignificant *= 10.0; 2590 - if( iDot==i ){ 2591 - *z++ = '.'; 2592 - } 2593 - } 2594 - 2595 - /* If the exponent is not zero, add the "eXX" notation to the 2596 - * end of the string. 2597 - */ 2598 - if( iExp!=0 ){ 2599 - *z++ = 'e'; 2600 - Th_SetResultInt(interp, iExp); 2601 - zExp = Th_GetResult(interp, 0); 2602 - for(i=0; zExp[i]; i++){ 2603 - *z++ = zExp[i]; 2604 - } 2605 - } 2606 - 2607 - *z = '\0'; 2608 - return Th_SetResult(interp, zBuf, -1); 2609 -}
Deleted src/th.h.
1 - 2 -/* This header file defines the external interface to the custom Scripting 3 -** Language (TH) interpreter. TH is very similar to TCL but is not an 4 -** exact clone. 5 -*/ 6 - 7 -/* 8 -** Before creating an interpreter, the application must allocate and 9 -** populate an instance of the following structure. It must remain valid 10 -** for the lifetime of the interpreter. 11 -*/ 12 -struct Th_Vtab { 13 - void *(*xMalloc)(unsigned int); 14 - void (*xFree)(void *); 15 -}; 16 -typedef struct Th_Vtab Th_Vtab; 17 - 18 -/* 19 -** Opaque handle for interpeter. 20 -*/ 21 -typedef struct Th_Interp Th_Interp; 22 - 23 -/* 24 -** Create and delete interpreters. 25 -*/ 26 -Th_Interp * Th_CreateInterp(Th_Vtab *pVtab); 27 -void Th_DeleteInterp(Th_Interp *); 28 - 29 -/* 30 -** Evaluate an TH program in the stack frame identified by parameter 31 -** iFrame, according to the following rules: 32 -** 33 -** * If iFrame is 0, this means the current frame. 34 -** 35 -** * If iFrame is negative, then the nth frame up the stack, where n is 36 -** the absolute value of iFrame. A value of -1 means the calling 37 -** procedure. 38 -** 39 -** * If iFrame is +ve, then the nth frame from the bottom of the stack. 40 -** An iFrame value of 1 means the toplevel (global) frame. 41 -*/ 42 -int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg); 43 - 44 -/* 45 -** Evaluate a TH expression. The result is stored in the 46 -** interpreter result. 47 -*/ 48 -int Th_Expr(Th_Interp *interp, const char *, int); 49 - 50 -/* 51 -** Access TH variables in the current stack frame. If the variable name 52 -** begins with "::", the lookup is in the top level (global) frame. 53 -*/ 54 -int Th_GetVar(Th_Interp *, const char *, int); 55 -int Th_SetVar(Th_Interp *, const char *, int, const char *, int); 56 -int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int); 57 -int Th_UnsetVar(Th_Interp *, const char *, int); 58 - 59 -typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *); 60 - 61 -/* 62 -** Register new commands. 63 -*/ 64 -int Th_CreateCommand( 65 - Th_Interp *interp, 66 - const char *zName, 67 - /* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */ 68 - Th_CommandProc xProc, 69 - void *pContext, 70 - void (*xDel)(Th_Interp *, void *) 71 -); 72 - 73 -/* 74 -** Delete or rename commands. 75 -*/ 76 -int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int); 77 - 78 -/* 79 -** Push a new stack frame (local variable context) onto the interpreter 80 -** stack, call the function supplied as parameter xCall with the two 81 -** context arguments, 82 -** 83 -** xCall(interp, pContext1, pContext2) 84 -** 85 -** , then pop the frame off of the interpreter stack. The value returned 86 -** by the xCall() function is returned as the result of this function. 87 -** 88 -** This is intended for use by the implementation of commands such as 89 -** those created by [proc]. 90 -*/ 91 -int Th_InFrame(Th_Interp *interp, 92 - int (*xCall)(Th_Interp *, void *pContext1, void *pContext2), 93 - void *pContext1, 94 - void *pContext2 95 -); 96 - 97 -/* 98 -** Valid return codes for xProc callbacks. 99 -*/ 100 -#define TH_OK 0 101 -#define TH_ERROR 1 102 -#define TH_BREAK 2 103 -#define TH_RETURN 3 104 -#define TH_CONTINUE 4 105 - 106 -/* 107 -** Set and get the interpreter result. 108 -*/ 109 -int Th_SetResult(Th_Interp *, const char *, int); 110 -const char *Th_GetResult(Th_Interp *, int *); 111 -char *Th_TakeResult(Th_Interp *, int *); 112 - 113 -/* 114 -** Set an error message as the interpreter result. This also 115 -** sets the global stack-trace variable $::th_stack_trace. 116 -*/ 117 -int Th_ErrorMessage(Th_Interp *, const char *, const char *, int); 118 - 119 -/* 120 -** Access the memory management functions associated with the specified 121 -** interpreter. 122 -*/ 123 -void *Th_Malloc(Th_Interp *, int); 124 -void Th_Free(Th_Interp *, void *); 125 - 126 -/* 127 -** Functions for handling TH lists. 128 -*/ 129 -int Th_ListAppend(Th_Interp *, char **, int *, const char *, int); 130 -int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *); 131 - 132 -int Th_StringAppend(Th_Interp *, char **, int *, const char *, int); 133 - 134 -/* 135 -** Functions for handling numbers and pointers. 136 -*/ 137 -int Th_ToInt(Th_Interp *, const char *, int, int *); 138 -int Th_ToDouble(Th_Interp *, const char *, int, double *); 139 -int Th_SetResultInt(Th_Interp *, int); 140 -int Th_SetResultDouble(Th_Interp *, double); 141 - 142 -/* 143 -** Drop in replacements for the corresponding standard library functions. 144 -*/ 145 -int th_strlen(const char *); 146 -int th_isdigit(char); 147 -int th_isspace(char); 148 -int th_isalnum(char); 149 -int th_isspecial(char); 150 -char *th_strdup(Th_Interp *interp, const char *z, int n); 151 - 152 -/* 153 -** Interfaces to register the language extensions. 154 -*/ 155 -int th_register_language(Th_Interp *interp); /* th_lang.c */ 156 -int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */ 157 -int th_register_vfs(Th_Interp *interp); /* th_vfs.c */ 158 -int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */ 159 -int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */ 160 - 161 -/* 162 -** General purpose hash table from th_lang.c. 163 -*/ 164 -typedef struct Th_Hash Th_Hash; 165 -typedef struct Th_HashEntry Th_HashEntry; 166 -struct Th_HashEntry { 167 - void *pData; 168 - char *zKey; 169 - int nKey; 170 - Th_HashEntry *pNext; /* Internal use only */ 171 -}; 172 -Th_Hash *Th_HashNew(Th_Interp *); 173 -void Th_HashDelete(Th_Interp *, Th_Hash *); 174 -void Th_HashIterate(Th_Interp*,Th_Hash*,void (*x)(Th_HashEntry*, void*),void*); 175 -Th_HashEntry *Th_HashFind(Th_Interp*, Th_Hash*, const char*, int, int); 176 - 177 -/* 178 -** Useful functions from th_lang.c. 179 -*/ 180 -int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg); 181 - 182 -typedef struct Th_SubCommand {char *zName; Th_CommandProc xProc;} Th_SubCommand; 183 -int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,Th_SubCommand*);
Deleted src/th_lang.c.
1 - 2 -/* 3 -** This file contains the implementation of all of the TH language 4 -** built-in commands. 5 -** 6 -** All built-in commands are implemented using the public interface 7 -** declared in th.h, so this file serves as both a part of the language 8 -** implementation and an example of how to extend the language with 9 -** new commands. 10 -*/ 11 - 12 -#include "config.h" 13 -#include "th.h" 14 -#include <string.h> 15 -#include <assert.h> 16 - 17 -int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg){ 18 - Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1); 19 - return TH_ERROR; 20 -} 21 - 22 -/* 23 -** Syntax: 24 -** 25 -** catch script ?varname? 26 -*/ 27 -static int catch_command( 28 - Th_Interp *interp, 29 - void *ctx, 30 - int argc, 31 - const char **argv, 32 - int *argl 33 -){ 34 - int rc; 35 - 36 - if( argc!=2 && argc!=3 ){ 37 - return Th_WrongNumArgs(interp, "catch script ?varname?"); 38 - } 39 - 40 - rc = Th_Eval(interp, 0, argv[1], -1); 41 - if( argc==3 ){ 42 - int nResult; 43 - const char *zResult = Th_GetResult(interp, &nResult); 44 - Th_SetVar(interp, argv[2], argl[2], zResult, nResult); 45 - } 46 - 47 - Th_SetResultInt(interp, rc); 48 - return TH_OK; 49 -} 50 - 51 -/* 52 -** TH Syntax: 53 -** 54 -** if expr1 body1 ?elseif expr2 body2? ? ?else? bodyN? 55 -*/ 56 -static int if_command( 57 - Th_Interp *interp, 58 - void *ctx, 59 - int argc, 60 - const char **argv, 61 - int *argl 62 -){ 63 - int rc = TH_OK; 64 - 65 - int iCond; /* Result of evaluating expression */ 66 - int i; 67 - 68 - const char *zResult; 69 - int nResult; 70 - 71 - if( argc<3 ){ 72 - goto wrong_args; 73 - } 74 - 75 - for(i=0; i<argc && rc==TH_OK; i+=3){ 76 - if( i>argc-3 ){ 77 - i = argc-3; 78 - iCond = 1; 79 - }else{ 80 - if( TH_OK!=Th_Expr(interp, argv[i+1], argl[i+1]) ){ 81 - return TH_ERROR; 82 - } 83 - zResult = Th_GetResult(interp, &nResult); 84 - rc = Th_ToInt(interp, zResult, nResult, &iCond); 85 - } 86 - if( iCond && rc==TH_OK ){ 87 - rc = Th_Eval(interp, 0, argv[i+2], -1); 88 - break; 89 - } 90 - } 91 - 92 - return rc; 93 - 94 -wrong_args: 95 - return Th_WrongNumArgs(interp, "if ..."); 96 -} 97 - 98 -/* 99 -** TH Syntax: 100 -** 101 -** expr expr 102 -*/ 103 -static int expr_command( 104 - Th_Interp *interp, 105 - void *ctx, 106 - int argc, 107 - const char **argv, 108 - int *argl 109 -){ 110 - if( argc!=2 ){ 111 - return Th_WrongNumArgs(interp, "expr expression"); 112 - } 113 - 114 - return Th_Expr(interp, argv[1], argl[1]); 115 -} 116 - 117 -/* 118 -** Evaluate the th1 script (zBody, nBody) in the local stack frame. 119 -** Return the result of the evaluation, except if the result 120 -** is TH_CONTINUE, return TH_OK instead. 121 -*/ 122 -static int eval_loopbody(Th_Interp *interp, const char *zBody, int nBody){ 123 - int rc = Th_Eval(interp, 0, zBody, nBody); 124 - if( rc==TH_CONTINUE ){ 125 - rc = TH_OK; 126 - } 127 - return rc; 128 -} 129 - 130 -/* 131 -** TH Syntax: 132 -** 133 -** for init condition incr script 134 -*/ 135 -static int for_command( 136 - Th_Interp *interp, 137 - void *ctx, 138 - int argc, 139 - const char **argv, 140 - int *argl 141 -){ 142 - int rc; 143 - int iCond; 144 - 145 - if( argc!=5 ){ 146 - return Th_WrongNumArgs(interp, "for init condition incr script"); 147 - } 148 - 149 - /* Evaluate the 'init' script */ 150 - rc = Th_Eval(interp, 0, argv[1], -1); 151 - 152 - while( rc==TH_OK 153 - && TH_OK==(rc = Th_Expr(interp, argv[2], -1)) 154 - && TH_OK==(rc = Th_ToInt(interp, Th_GetResult(interp, 0), -1, &iCond)) 155 - && iCond 156 - && TH_OK==(rc = eval_loopbody(interp, argv[4], argl[4])) 157 - ){ 158 - rc = Th_Eval(interp, 0, argv[3], -1); 159 - } 160 - 161 - if( rc==TH_BREAK ) rc = TH_OK; 162 - return rc; 163 -} 164 - 165 -/* 166 -** TH Syntax: 167 -** 168 -** list ?arg1 ?arg2? ...? 169 -*/ 170 -static int list_command( 171 - Th_Interp *interp, 172 - void *ctx, 173 - int argc, 174 - const char **argv, 175 - int *argl 176 -){ 177 - char *zList = 0; 178 - int nList = 0; 179 - int i; 180 - 181 - for(i=1; i<argc; i++){ 182 - Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]); 183 - } 184 - 185 - Th_SetResult(interp, zList, nList); 186 - Th_Free(interp, zList); 187 - 188 - return TH_OK; 189 -} 190 - 191 -/* 192 -** TH Syntax: 193 -** 194 -** lindex list index 195 -*/ 196 -static int lindex_command( 197 - Th_Interp *interp, 198 - void *ctx, 199 - int argc, 200 - const char **argv, 201 - int *argl 202 -){ 203 - int iElem; 204 - int rc; 205 - 206 - char **azElem; 207 - int *anElem; 208 - int nCount; 209 - 210 - if( argc!=3 ){ 211 - return Th_WrongNumArgs(interp, "lindex list index"); 212 - } 213 - 214 - if( TH_OK!=Th_ToInt(interp, argv[2], argl[2], &iElem) ){ 215 - return TH_ERROR; 216 - } 217 - 218 - rc = Th_SplitList(interp, argv[1], argl[1], &azElem, &anElem, &nCount); 219 - if( rc==TH_OK ){ 220 - if( iElem<nCount && iElem>=0 ){ 221 - Th_SetResult(interp, azElem[iElem], anElem[iElem]); 222 - }else{ 223 - Th_SetResult(interp, 0, 0); 224 - } 225 - Th_Free(interp, azElem); 226 - } 227 - 228 - return rc; 229 -} 230 - 231 -/* 232 -** TH Syntax: 233 -** 234 -** llength list 235 -*/ 236 -static int llength_command( 237 - Th_Interp *interp, 238 - void *ctx, 239 - int argc, 240 - const char **argv, 241 - int *argl 242 -){ 243 - int nElem; 244 - int rc; 245 - 246 - if( argc!=2 ){ 247 - return Th_WrongNumArgs(interp, "llength list"); 248 - } 249 - 250 - rc = Th_SplitList(interp, argv[1], argl[1], 0, 0, &nElem); 251 - if( rc==TH_OK ){ 252 - Th_SetResultInt(interp, nElem); 253 - } 254 - 255 - return rc; 256 -} 257 - 258 -/* 259 -** TH Syntax: 260 -** 261 -** set varname ?value? 262 -*/ 263 -static int set_command( 264 - Th_Interp *interp, 265 - void *ctx, 266 - int argc, 267 - const char **argv, 268 - int *argl 269 -){ 270 - if( argc!=2 && argc!=3 ){ 271 - return Th_WrongNumArgs(interp, "set varname ?value?"); 272 - } 273 - 274 - if( argc==3 ){ 275 - Th_SetVar(interp, argv[1], argl[1], argv[2], argl[2]); 276 - } 277 - return Th_GetVar(interp, argv[1], argl[1]); 278 -} 279 - 280 -/* 281 -** When a new command is created using the built-in [proc] command, an 282 -** instance of the following structure is allocated and populated. A 283 -** pointer to the structure is passed as the context (second) argument 284 -** to function proc_call1() when the new command is executed. 285 -*/ 286 -typedef struct ProcDefn ProcDefn; 287 -struct ProcDefn { 288 - int nParam; /* Number of formal (non "args") parameters */ 289 - char **azParam; /* Parameter names */ 290 - int *anParam; /* Lengths of parameter names */ 291 - char **azDefault; /* Default values */ 292 - int *anDefault; /* Lengths of default values */ 293 - int hasArgs; /* True if there is an "args" parameter */ 294 - char *zProgram; /* Body of proc */ 295 - int nProgram; /* Number of bytes at zProgram */ 296 - char *zUsage; /* Usage message */ 297 - int nUsage; /* Number of bytes at zUsage */ 298 -}; 299 - 300 -/* This structure is used to temporarily store arguments passed to an 301 -** invocation of a command created using [proc]. A pointer to an 302 -** instance is passed as the second argument to the proc_call2() function. 303 -*/ 304 -typedef struct ProcArgs ProcArgs; 305 -struct ProcArgs { 306 - int argc; 307 - const char **argv; 308 - int *argl; 309 -}; 310 - 311 -/* 312 -** Each time a command created using [proc] is invoked, a new 313 -** th1 stack frame is allocated (for the proc's local variables) and 314 -** this function invoked. 315 -** 316 -** Argument pContext1 points to the associated ProcDefn structure. 317 -** Argument pContext2 points to a ProcArgs structure that contains 318 -** the arguments passed to this specific invocation of the proc. 319 -*/ 320 -static int proc_call2(Th_Interp *interp, void *pContext1, void *pContext2){ 321 - int i; 322 - ProcDefn *p = (ProcDefn *)pContext1; 323 - ProcArgs *pArgs = (ProcArgs *)pContext2; 324 - 325 - /* Check if there are the right number of arguments. If there are 326 - ** not, generate a usage message for the command. 327 - */ 328 - if( (pArgs->argc>(p->nParam+1) && !p->hasArgs) 329 - || (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1]) 330 - ){ 331 - char *zUsage = 0; 332 - int nUsage = 0; 333 - Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]); 334 - Th_StringAppend(interp, &zUsage, &nUsage, p->zUsage, p->nUsage); 335 - Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"", 1); 336 - Th_WrongNumArgs(interp, zUsage); 337 - Th_Free(interp, zUsage); 338 - return TH_ERROR; 339 - } 340 - 341 - /* Populate the formal proc parameters. */ 342 - for(i=0; i<p->nParam; i++){ 343 - const char *zVal; 344 - int nVal; 345 - if( pArgs->argc>(i+1) ){ 346 - zVal = pArgs->argv[i+1]; 347 - nVal = pArgs->argl[i+1]; 348 - }else{ 349 - zVal = p->azDefault[i]; 350 - nVal = p->anDefault[i]; 351 - } 352 - Th_SetVar(interp, p->azParam[i], p->anParam[i], zVal, nVal); 353 - } 354 - 355 - /* Populate the "args" parameter, if it exists */ 356 - if( p->hasArgs ){ 357 - char *zArgs = 0; 358 - int nArgs = 0; 359 - for(i=p->nParam+1; i<pArgs->argc; i++){ 360 - Th_ListAppend(interp, &zArgs, &nArgs, pArgs->argv[i], pArgs->argl[i]); 361 - } 362 - Th_SetVar(interp, (const char *)"args", -1, zArgs, nArgs); 363 - } 364 - 365 - Th_SetResult(interp, 0, 0); 366 - return Th_Eval(interp, 0, p->zProgram, p->nProgram); 367 -} 368 - 369 -/* 370 -** This function is the command callback registered for all commands 371 -** created using the [proc] command. The second argument, pContext, 372 -** is a pointer to the associated ProcDefn structure. 373 -*/ 374 -static int proc_call1( 375 - Th_Interp *interp, 376 - void *pContext, 377 - int argc, 378 - const char **argv, 379 - int *argl 380 -){ 381 - int rc; 382 - 383 - ProcDefn *p = (ProcDefn *)pContext; 384 - ProcArgs procargs; 385 - 386 - /* Call function proc_call2(), which will call Th_Eval() to evaluate 387 - ** the body of the [proc], in a new Th stack frame. This is so that 388 - ** the proc body has its own local variable context. 389 - */ 390 - procargs.argc = argc; 391 - procargs.argv = argv; 392 - procargs.argl = argl; 393 - rc = Th_InFrame(interp, proc_call2, (void *)p, (void *)&procargs); 394 - 395 - if( rc==TH_RETURN ){ 396 - rc = TH_OK; 397 - } 398 - return rc; 399 -} 400 - 401 -/* 402 -** This function is registered as the delete callback for all commands 403 -** created using the built-in [proc] command. It is called automatically 404 -** when a command created using [proc] is deleted. 405 -** 406 -** It frees the ProcDefn structure allocated when the command was created. 407 -*/ 408 -static void proc_del(Th_Interp *interp, void *pContext){ 409 - ProcDefn *p = (ProcDefn *)pContext; 410 - Th_Free(interp, (void *)p->zUsage); 411 - Th_Free(interp, (void *)p); 412 -} 413 - 414 -/* 415 -** TH Syntax: 416 -** 417 -** proc name arglist code 418 -*/ 419 -static int proc_command( 420 - Th_Interp *interp, 421 - void *ctx, 422 - int argc, 423 - const char **argv, 424 - int *argl 425 -){ 426 - int rc; 427 - char *zName; 428 - 429 - ProcDefn *p; 430 - int nByte; 431 - int i; 432 - char *zSpace; 433 - 434 - char **azParam; 435 - int *anParam; 436 - int nParam; 437 - 438 - char *zUsage = 0; /* Build up a usage message here */ 439 - int nUsage = 0; /* Number of bytes at zUsage */ 440 - 441 - if( argc!=4 ){ 442 - return Th_WrongNumArgs(interp, "proc name arglist code"); 443 - } 444 - if( Th_SplitList(interp, argv[2], argl[2], &azParam, &anParam, &nParam) ){ 445 - return TH_ERROR; 446 - } 447 - 448 - /* Allocate the new ProcDefn structure. */ 449 - nByte = sizeof(ProcDefn) + /* ProcDefn structure */ 450 - (sizeof(char *) + sizeof(int)) * nParam + /* azParam, anParam */ 451 - (sizeof(char *) + sizeof(int)) * nParam + /* azDefault, anDefault */ 452 - argl[3] + /* zProgram */ 453 - argl[2]; /* Space for copies of parameter names and default values */ 454 - p = (ProcDefn *)Th_Malloc(interp, nByte); 455 - 456 - /* If the last parameter in the parameter list is "args", then set the 457 - ** ProcDefn.hasArgs flag. The "args" parameter does not require an 458 - ** entry in the ProcDefn.azParam[] or ProcDefn.azDefault[] arrays. 459 - */ 460 - if( anParam[nParam-1]==4 && 0==memcmp(azParam[nParam-1], "args", 4) ){ 461 - p->hasArgs = 1; 462 - nParam--; 463 - } 464 - 465 - p->nParam = nParam; 466 - p->azParam = (char **)&p[1]; 467 - p->anParam = (int *)&p->azParam[nParam]; 468 - p->azDefault = (char **)&p->anParam[nParam]; 469 - p->anDefault = (int *)&p->azDefault[nParam]; 470 - p->zProgram = (char *)&p->anDefault[nParam]; 471 - memcpy(p->zProgram, argv[3], argl[3]); 472 - p->nProgram = argl[3]; 473 - zSpace = &p->zProgram[p->nProgram]; 474 - 475 - for(i=0; i<nParam; i++){ 476 - char **az; 477 - int *an; 478 - int n; 479 - if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){ 480 - goto error_out; 481 - } 482 - if( n<1 || n>2 ){ 483 - const char expected[] = "expected parameter, got \""; 484 - Th_ErrorMessage(interp, expected, azParam[i], anParam[i]); 485 - Th_Free(interp, az); 486 - goto error_out; 487 - } 488 - p->anParam[i] = an[0]; 489 - p->azParam[i] = zSpace; 490 - memcpy(zSpace, az[0], an[0]); 491 - zSpace += an[0]; 492 - if( n==2 ){ 493 - p->anDefault[i] = an[1]; 494 - p->azDefault[i] = zSpace; 495 - memcpy(zSpace, az[1], an[1]); 496 - zSpace += an[1]; 497 - } 498 - 499 - Th_StringAppend(interp, &zUsage, &nUsage, (const char *)" ", 1); 500 - if( n==2 ){ 501 - Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"?", 1); 502 - Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]); 503 - Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"?", 1); 504 - }else{ 505 - Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]); 506 - } 507 - 508 - Th_Free(interp, az); 509 - } 510 - assert( zSpace-(char *)p<=nByte ); 511 - 512 - /* If there is an "args" parameter, append it to the end of the usage 513 - ** message. Set ProcDefn.zUsage to point at the usage message. It will 514 - ** be freed along with the rest of the proc-definition by proc_del(). 515 - */ 516 - if( p->hasArgs ){ 517 - Th_StringAppend(interp, &zUsage, &nUsage, (const char *)" ?args...?", -1); 518 - } 519 - p->zUsage = zUsage; 520 - p->nUsage = nUsage; 521 - 522 - /* Register the new command with the th1 interpreter. */ 523 - zName = (char *)argv[1]; 524 - rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del); 525 - if( rc==TH_OK ){ 526 - Th_SetResult(interp, 0, 0); 527 - } 528 - 529 - Th_Free(interp, azParam); 530 - return TH_OK; 531 - 532 - error_out: 533 - Th_Free(interp, azParam); 534 - Th_Free(interp, zUsage); 535 - return TH_ERROR; 536 -} 537 - 538 -/* 539 -** TH Syntax: 540 -** 541 -** rename oldcmd newcmd 542 -*/ 543 -static int rename_command( 544 - Th_Interp *interp, 545 - void *ctx, 546 - int argc, 547 - const char **argv, 548 - int *argl 549 -){ 550 - if( argc!=3 ){ 551 - return Th_WrongNumArgs(interp, "rename oldcmd newcmd"); 552 - } 553 - return Th_RenameCommand(interp, argv[1], argl[1], argv[2], argl[2]); 554 -} 555 - 556 -/* 557 -** TH Syntax: 558 -** 559 -** break ?value...? 560 -** continue ?value...? 561 -** ok ?value...? 562 -** error ?value...? 563 -*/ 564 -static int simple_command( 565 - Th_Interp *interp, 566 - void *ctx, 567 - int argc, 568 - const char **argv, 569 - int *argl 570 -){ 571 - if( argc!=1 && argc!=2 ){ 572 - return Th_WrongNumArgs(interp, "return ?value?"); 573 - } 574 - if( argc==2 ){ 575 - Th_SetResult(interp, argv[1], argl[1]); 576 - } 577 - return FOSSIL_PTR_TO_INT(ctx); 578 -} 579 - 580 -/* 581 -** TH Syntax: 582 -** 583 -** return ?-code code? ?value? 584 -*/ 585 -static int return_command( 586 - Th_Interp *interp, 587 - void *ctx, 588 - int argc, 589 - const char **argv, 590 - int *argl 591 -){ 592 - int iCode = TH_RETURN; 593 - if( argc<1 || argc>4 ){ 594 - return Th_WrongNumArgs(interp, "return ?-code code? ?value?"); 595 - } 596 - if( argc>2 ){ 597 - int rc = Th_ToInt(interp, argv[2], argl[2], &iCode); 598 - if( rc!=TH_OK ){ 599 - return rc; 600 - } 601 - } 602 - if( argc==2 || argc==4 ){ 603 - Th_SetResult(interp, argv[argc-1], argl[argc-1]); 604 - } 605 - return iCode; 606 -} 607 - 608 -/* 609 -** TH Syntax: 610 -** 611 -** string compare STRING1 STRING2 612 -*/ 613 -static int string_compare_command( 614 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 615 -){ 616 - const char *zRight; int nRight; 617 - const char *zLeft; int nLeft; 618 - 619 - int i; 620 - int iRes = 0; 621 - 622 - if( argc!=4 ){ 623 - return Th_WrongNumArgs(interp, "string compare str1 str2"); 624 - } 625 - 626 - zLeft = argv[2]; 627 - nLeft = argl[2]; 628 - zRight = argv[3]; 629 - nRight = argl[3]; 630 - 631 - for(i=0; iRes==0 && i<nLeft && i<nRight; i++){ 632 - iRes = zLeft[i]-zRight[i]; 633 - } 634 - if( iRes==0 ){ 635 - iRes = nLeft-nRight; 636 - } 637 - 638 - if( iRes<0 ) iRes = -1; 639 - if( iRes>0 ) iRes = 1; 640 - 641 - return Th_SetResultInt(interp, iRes); 642 -} 643 - 644 -/* 645 -** TH Syntax: 646 -** 647 -** string first NEEDLE HAYSTACK 648 -*/ 649 -static int string_first_command( 650 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 651 -){ 652 - const char *zNeedle; 653 - int nNeedle; 654 - const char *zHaystack; 655 - int nHaystack; 656 - int i; 657 - int iRes = -1; 658 - 659 - if( argc!=4 ){ 660 - return Th_WrongNumArgs(interp, "string first needle haystack"); 661 - } 662 - 663 - zNeedle = argv[2]; 664 - nNeedle = argl[2]; 665 - zHaystack = argv[3]; 666 - nHaystack = argl[3]; 667 - 668 - for(i=0; i<(nHaystack-nNeedle); i++){ 669 - if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ 670 - iRes = i; 671 - break; 672 - } 673 - } 674 - 675 - return Th_SetResultInt(interp, iRes); 676 -} 677 - 678 -/* 679 -** TH Syntax: 680 -** 681 -** string is CLASS STRING 682 -*/ 683 -static int string_is_command( 684 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 685 -){ 686 - int i; 687 - int iRes = 1; 688 - if( argc!=4 ){ 689 - return Th_WrongNumArgs(interp, "string is class string"); 690 - } 691 - if( argl[2]!=5 || 0!=memcmp(argv[2], "alnum", 5) ){ 692 - Th_ErrorMessage(interp, "Expected alnum, got: ", argv[2], argl[2]); 693 - return TH_ERROR; 694 - } 695 - 696 - for(i=0; i<argl[3]; i++){ 697 - if( !th_isalnum(argv[3][i]) ){ 698 - iRes = 0; 699 - } 700 - } 701 - 702 - return Th_SetResultInt(interp, iRes); 703 -} 704 - 705 -/* 706 -** TH Syntax: 707 -** 708 -** string last NEEDLE HAYSTACK 709 -*/ 710 -static int string_last_command( 711 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 712 -){ 713 - const char *zNeedle; 714 - int nNeedle; 715 - const char *zHaystack; 716 - int nHaystack; 717 - int i; 718 - int iRes = -1; 719 - 720 - if( argc!=4 ){ 721 - return Th_WrongNumArgs(interp, "string first needle haystack"); 722 - } 723 - 724 - zNeedle = argv[2]; 725 - nNeedle = argl[2]; 726 - zHaystack = argv[3]; 727 - nHaystack = argl[3]; 728 - 729 - for(i=nHaystack-nNeedle-1; i>=0; i--){ 730 - if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ 731 - iRes = i; 732 - break; 733 - } 734 - } 735 - 736 - return Th_SetResultInt(interp, iRes); 737 -} 738 - 739 -/* 740 -** TH Syntax: 741 -** 742 -** string length STRING 743 -*/ 744 -static int string_length_command( 745 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 746 -){ 747 - if( argc!=3 ){ 748 - return Th_WrongNumArgs(interp, "string length string"); 749 - } 750 - return Th_SetResultInt(interp, argl[2]); 751 -} 752 - 753 -/* 754 -** TH Syntax: 755 -** 756 -** string range STRING FIRST LAST 757 -*/ 758 -static int string_range_command( 759 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 760 -){ 761 - int iStart; 762 - int iEnd; 763 - 764 - if( argc!=5 ){ 765 - return Th_WrongNumArgs(interp, "string range string first last"); 766 - } 767 - 768 - if( argl[4]==3 && 0==memcmp("end", argv[4], 3) ){ 769 - iEnd = argl[2]; 770 - }else if( Th_ToInt(interp, argv[4], argl[4], &iEnd) ){ 771 - Th_ErrorMessage( 772 - interp, "Expected \"end\" or integer, got:", argv[4], argl[4]); 773 - return TH_ERROR; 774 - } 775 - if( Th_ToInt(interp, argv[3], argl[3], &iStart) ){ 776 - return TH_ERROR; 777 - } 778 - 779 - if( iStart<0 ) iStart = 0; 780 - if( iEnd>=argl[2] ) iEnd = argl[2]-1; 781 - if( iStart>iEnd ) iEnd = iStart-1; 782 - 783 - return Th_SetResult(interp, &argv[2][iStart], iEnd-iStart+1); 784 -} 785 - 786 -/* 787 -** TH Syntax: 788 -** 789 -** string repeat STRING COUNT 790 -*/ 791 -static int string_repeat_command( 792 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 793 -){ 794 - int n; 795 - int i; 796 - int nByte; 797 - char *zByte; 798 - 799 - if( argc!=4 ){ 800 - return Th_WrongNumArgs(interp, "string repeat string n"); 801 - } 802 - if( Th_ToInt(interp, argv[3], argl[3], &n) ){ 803 - return TH_ERROR; 804 - } 805 - 806 - nByte = argl[2] * n; 807 - zByte = Th_Malloc(interp, nByte+1); 808 - for(i=0; i<nByte; i+=argl[2]){ 809 - memcpy(&zByte[i], argv[2], argl[2]); 810 - } 811 - 812 - Th_SetResult(interp, zByte, nByte); 813 - Th_Free(interp, zByte); 814 - return TH_OK; 815 -} 816 - 817 -/* 818 -** TH Syntax: 819 -** 820 -** info exists VAR 821 -*/ 822 -static int info_exists_command( 823 - Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl 824 -){ 825 - int rc; 826 - 827 - if( argc!=3 ){ 828 - return Th_WrongNumArgs(interp, "info exists var"); 829 - } 830 - rc = Th_GetVar(interp, argv[2], argl[2]); 831 - Th_SetResultInt(interp, rc?0:1); 832 - return TH_OK; 833 -} 834 - 835 -/* 836 -** TH Syntax: 837 -** 838 -** unset VAR 839 -*/ 840 -static int unset_command( 841 - Th_Interp *interp, 842 - void *ctx, 843 - int argc, 844 - const char **argv, 845 - int *argl 846 -){ 847 - if( argc!=2 ){ 848 - return Th_WrongNumArgs(interp, "unset var"); 849 - } 850 - return Th_UnsetVar(interp, argv[1], argl[1]); 851 -} 852 - 853 -int Th_CallSubCommand( 854 - Th_Interp *interp, 855 - void *ctx, 856 - int argc, 857 - const char **argv, 858 - int *argl, 859 - Th_SubCommand *aSub 860 -){ 861 - int i; 862 - for(i=0; aSub[i].zName; i++){ 863 - char *zName = (char *)aSub[i].zName; 864 - if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){ 865 - return aSub[i].xProc(interp, ctx, argc, argv, argl); 866 - } 867 - } 868 - 869 - Th_ErrorMessage(interp, "Expected sub-command, got:", argv[1], argl[1]); 870 - return TH_ERROR; 871 -} 872 - 873 -/* 874 -** TH Syntax: 875 -** 876 -** string compare STR1 STR2 877 -** string first NEEDLE HAYSTACK ?STARTINDEX? 878 -** string is CLASS STRING 879 -** string last NEEDLE HAYSTACK ?STARTINDEX? 880 -** string length STRING 881 -** string range STRING FIRST LAST 882 -** string repeat STRING COUNT 883 -*/ 884 -static int string_command( 885 - Th_Interp *interp, 886 - void *ctx, 887 - int argc, 888 - const char **argv, 889 - int *argl 890 -){ 891 - Th_SubCommand aSub[] = { 892 - { "compare", string_compare_command }, 893 - { "first", string_first_command }, 894 - { "is", string_is_command }, 895 - { "last", string_last_command }, 896 - { "length", string_length_command }, 897 - { "range", string_range_command }, 898 - { "repeat", string_repeat_command }, 899 - { 0, 0 } 900 - }; 901 - return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); 902 -} 903 - 904 -/* 905 -** TH Syntax: 906 -** 907 -** info exists VARNAME 908 -*/ 909 -static int info_command( 910 - Th_Interp *interp, 911 - void *ctx, 912 - int argc, 913 - const char **argv, 914 - int *argl 915 -){ 916 - Th_SubCommand aSub[] = { 917 - { "exists", info_exists_command }, 918 - { 0, 0 } 919 - }; 920 - return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); 921 -} 922 - 923 -/* 924 -** Convert the script level frame specification (used by the commands 925 -** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as 926 -** used by Th_LinkVar() and Th_Eval(). If successful, write the integer 927 -** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR 928 -** and leave an error message in the interpreter result. 929 -*/ 930 -static int thToFrame( 931 - Th_Interp *interp, 932 - const char *zFrame, 933 - int nFrame, 934 - int *piFrame 935 -){ 936 - int iFrame; 937 - if( th_isdigit(zFrame[0]) ){ 938 - int rc = Th_ToInt(interp, zFrame, nFrame, &iFrame); 939 - if( rc!=TH_OK ) return rc; 940 - iFrame = iFrame * -1; 941 - }else if( zFrame[0]=='#' ){ 942 - int rc = Th_ToInt(interp, &zFrame[1], nFrame-1, &iFrame); 943 - if( rc!=TH_OK ) return rc; 944 - iFrame = iFrame + 1; 945 - }else{ 946 - return TH_ERROR; 947 - } 948 - *piFrame = iFrame; 949 - return TH_OK; 950 -} 951 - 952 -/* 953 -** TH Syntax: 954 -** 955 -** uplevel ?LEVEL? SCRIPT 956 -*/ 957 -static int uplevel_command( 958 - Th_Interp *interp, 959 - void *ctx, 960 - int argc, 961 - const char **argv, 962 - int *argl 963 -){ 964 - int iFrame = -1; 965 - 966 - if( argc!=2 && argc!=3 ){ 967 - return Th_WrongNumArgs(interp, "uplevel ?level? script..."); 968 - } 969 - if( argc==3 && TH_OK!=thToFrame(interp, argv[1], argl[1], &iFrame) ){ 970 - return TH_ERROR; 971 - } 972 - return Th_Eval(interp, iFrame, argv[argc-1], -1); 973 -} 974 - 975 -/* 976 -** TH Syntax: 977 -** 978 -** upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR ...? 979 -*/ 980 -static int upvar_command( 981 - Th_Interp *interp, 982 - void *ctx, 983 - int argc, 984 - const char **argv, 985 - int *argl 986 -){ 987 - int iVar = 1; 988 - int iFrame = -1; 989 - int rc = TH_OK; 990 - int i; 991 - 992 - if( TH_OK==thToFrame(0, argv[1], argl[1], &iFrame) ){ 993 - iVar++; 994 - } 995 - if( argc==iVar || (argc-iVar)%2 ){ 996 - return Th_WrongNumArgs(interp, 997 - "upvar frame othervar myvar ?othervar myvar...?"); 998 - } 999 - for(i=iVar; rc==TH_OK && i<argc; i=i+2){ 1000 - rc = Th_LinkVar(interp, argv[i+1], argl[i+1], iFrame, argv[i], argl[i]); 1001 - } 1002 - return rc; 1003 -} 1004 - 1005 -/* 1006 -** TH Syntax: 1007 -** 1008 -** breakpoint ARGS 1009 -** 1010 -** This command does nothing at all. Its purpose in life is to serve 1011 -** as a point for setting breakpoints in a debugger. 1012 -*/ 1013 -static int breakpoint_command( 1014 - Th_Interp *interp, 1015 - void *ctx, 1016 - int argc, 1017 - const char **argv, 1018 - int *argl 1019 -){ 1020 - int cnt = 0; 1021 - cnt++; 1022 - return TH_OK; 1023 -} 1024 - 1025 -/* 1026 -** Register the built-in th1 language commands with interpreter interp. 1027 -** Usually this is called soon after interpreter creation. 1028 -*/ 1029 -int th_register_language(Th_Interp *interp){ 1030 - /* Array of built-in commands. */ 1031 - struct _Command { 1032 - const char *zName; 1033 - Th_CommandProc xProc; 1034 - void *pContext; 1035 - } aCommand[] = { 1036 - {"catch", catch_command, 0}, 1037 - {"expr", expr_command, 0}, 1038 - {"for", for_command, 0}, 1039 - {"if", if_command, 0}, 1040 - {"info", info_command, 0}, 1041 - {"lindex", lindex_command, 0}, 1042 - {"list", list_command, 0}, 1043 - {"llength", llength_command, 0}, 1044 - {"proc", proc_command, 0}, 1045 - {"rename", rename_command, 0}, 1046 - {"set", set_command, 0}, 1047 - {"string", string_command, 0}, 1048 - {"unset", unset_command, 0}, 1049 - {"uplevel", uplevel_command, 0}, 1050 - {"upvar", upvar_command, 0}, 1051 - 1052 - {"breakpoint", breakpoint_command, 0}, 1053 - 1054 - {"return", return_command, 0}, 1055 - {"break", simple_command, (void *)TH_BREAK}, 1056 - {"continue", simple_command, (void *)TH_CONTINUE}, 1057 - {"error", simple_command, (void *)TH_ERROR}, 1058 - 1059 - {0, 0, 0} 1060 - }; 1061 - int i; 1062 - 1063 - /* Add the language commands. */ 1064 - for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ 1065 - void *ctx; 1066 - if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; 1067 - ctx = aCommand[i].pContext; 1068 - Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0); 1069 - } 1070 - 1071 - return TH_OK; 1072 -}
Changes to src/th_main.c.
18 18 ** This file contains an interface between the TH scripting language 19 19 ** (an independent project) and fossil. 20 20 */ 21 21 #include "config.h" 22 22 #include "th_main.h" 23 23 24 24 /* 25 -** Global variable counting the number of outstanding calls to malloc() 26 -** made by the th1 implementation. This is used to catch memory leaks 27 -** in the interpreter. Obviously, it also means th1 is not threadsafe. 25 +** Interfaces to register the scripting language extensions. 28 26 */ 29 -static int nOutstandingMalloc = 0; 30 - 31 -/* 32 -** Implementations of malloc() and free() to pass to the interpreter. 33 -*/ 34 -static void *xMalloc(unsigned int n){ 35 - void *p = fossil_malloc(n); 36 - if( p ){ 37 - nOutstandingMalloc++; 38 - } 39 - return p; 40 -} 41 -static void xFree(void *p){ 42 - if( p ){ 43 - nOutstandingMalloc--; 44 - } 45 - free(p); 46 -} 47 -static Th_Vtab vtab = { xMalloc, xFree }; 27 +int register_tcl(Jim_Interp *interp, void *pContext); /* th_tcl.c */ 48 28 49 29 /* 50 30 ** Generate a TH1 trace message if debugging is enabled. 51 31 */ 52 32 void Th_Trace(const char *zFormat, ...){ 53 33 va_list ap; 54 34 va_start(ap, zFormat); ................................................................................ 56 36 va_end(ap); 57 37 } 58 38 59 39 60 40 /* 61 41 ** True if output is enabled. False if disabled. 62 42 */ 63 -static int enableOutput = 1; 43 +static long enableOutput = 1; 64 44 65 45 /* 66 46 ** TH command: enable_output BOOLEAN 67 47 ** 68 48 ** Enable or disable the puts and hputs commands. 69 49 */ 70 -static int enableOutputCmd( 71 - Th_Interp *interp, 72 - void *p, 73 - int argc, 74 - const char **argv, 75 - int *argl 76 -){ 50 +static int enableOutputCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 51 +{ 77 52 if( argc!=2 ){ 78 - return Th_WrongNumArgs(interp, "enable_output BOOLEAN"); 53 + Jim_WrongNumArgs(interp, 1, argv, "BOOLEAN"); 54 + return JIM_ERR; 79 55 } 80 - return Th_ToInt(interp, argv[1], argl[1], &enableOutput); 56 + return Jim_GetLong(interp, argv[1], &enableOutput); 81 57 } 82 58 83 59 /* 84 60 ** Send text to the appropriate output: Either to the console 85 61 ** or to the CGI reply buffer. 86 62 */ 87 63 static void sendText(const char *z, int n, int encode){ ................................................................................ 96 72 }else{ 97 73 fwrite(z, 1, n, stdout); 98 74 fflush(stdout); 99 75 } 100 76 if( encode ) free((char*)z); 101 77 } 102 78 } 79 + 80 +static void sendTextObj(Jim_Obj *objPtr, int encode) 81 +{ 82 + sendText(Jim_String(objPtr), Jim_Length(objPtr), encode); 83 +} 103 84 104 85 /* 105 86 ** TH command: puts STRING 87 +** 88 +** Output STRING as HTML 89 +*/ 90 +static int putsCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 91 +{ 92 + if( argc!=2 ){ 93 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 94 + return JIM_ERR; 95 + } 96 + sendText(Jim_String(argv[1]), -1, 1); 97 + return JIM_OK; 98 +} 99 + 100 +/* 106 101 ** TH command: html STRING 107 102 ** 108 -** Output STRING as HTML (html) or unchanged (puts). 103 +** Output STRING unchanged 109 104 */ 110 -static int putsCmd( 111 - Th_Interp *interp, 112 - void *pConvert, 113 - int argc, 114 - const char **argv, 115 - int *argl 116 -){ 105 +static int htmlCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 106 +{ 117 107 if( argc!=2 ){ 118 - return Th_WrongNumArgs(interp, "puts STRING"); 108 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 109 + return JIM_ERR; 119 110 } 120 - sendText((char*)argv[1], argl[1], pConvert!=0); 121 - return TH_OK; 111 + sendText(Jim_String(argv[1]), -1, 0); 112 + return JIM_OK; 122 113 } 123 114 124 115 /* 125 116 ** TH command: wiki STRING 126 117 ** 127 118 ** Render the input string as wiki. 128 119 */ 129 -static int wikiCmd( 130 - Th_Interp *interp, 131 - void *p, 132 - int argc, 133 - const char **argv, 134 - int *argl 135 -){ 120 +static int wikiCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 121 +{ 136 122 if( argc!=2 ){ 137 - return Th_WrongNumArgs(interp, "wiki STRING"); 123 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 124 + return JIM_ERR; 138 125 } 139 126 if( enableOutput ){ 140 127 Blob src; 141 - blob_init(&src, (char*)argv[1], argl[1]); 128 + blob_init(&src, Jim_String(argv[1]), Jim_Length(argv[1])); 142 129 wiki_convert(&src, 0, WIKI_INLINE); 143 130 blob_reset(&src); 144 131 } 145 - return TH_OK; 132 + return JIM_OK; 146 133 } 147 134 148 135 /* 149 136 ** TH command: htmlize STRING 150 137 ** 151 138 ** Escape all characters of STRING which have special meaning in HTML. 152 139 ** Return a new string result. 153 140 */ 154 -static int htmlizeCmd( 155 - Th_Interp *interp, 156 - void *p, 157 - int argc, 158 - const char **argv, 159 - int *argl 160 -){ 141 +static int htmlizeCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 142 +{ 161 143 char *zOut; 162 144 if( argc!=2 ){ 163 - return Th_WrongNumArgs(interp, "htmlize STRING"); 145 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 146 + return JIM_ERR; 164 147 } 165 - zOut = htmlize((char*)argv[1], argl[1]); 166 - Th_SetResult(interp, zOut, -1); 148 + zOut = htmlize(Jim_String(argv[1]), Jim_Length(argv[1])); 149 + Jim_SetResultString(interp, zOut, -1); 167 150 free(zOut); 168 - return TH_OK; 151 + return JIM_OK; 169 152 } 170 153 171 154 /* 172 155 ** TH command: date 173 156 ** 174 157 ** Return a string which is the current time and date. If the 175 158 ** -local option is used, the date appears using localtime instead 176 159 ** of UTC. 177 160 */ 178 -static int dateCmd( 179 - Th_Interp *interp, 180 - void *p, 181 - int argc, 182 - const char **argv, 183 - int *argl 184 -){ 161 +static int dateCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 162 +{ 185 163 char *zOut; 186 - if( argc>=2 && argl[1]==6 && memcmp(argv[1],"-local",6)==0 ){ 164 + if( argc>=2 && Jim_CompareStringImmediate(interp, argv[1], "-local")) { 187 165 zOut = db_text("??", "SELECT datetime('now','localtime')"); 188 166 }else{ 189 167 zOut = db_text("??", "SELECT datetime('now')"); 190 168 } 191 - Th_SetResult(interp, zOut, -1); 169 + Jim_SetResultString(interp, zOut, -1); 192 170 free(zOut); 193 - return TH_OK; 171 + return JIM_OK; 194 172 } 195 173 196 174 /* 197 175 ** TH command: hascap STRING 198 176 ** 199 177 ** Return true if the user has all of the capabilities listed in STRING. 200 178 */ 201 -static int hascapCmd( 202 - Th_Interp *interp, 203 - void *p, 204 - int argc, 205 - const char **argv, 206 - int *argl 207 -){ 179 +static int hascapCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 180 +{ 208 181 int rc; 182 + const char *str; 183 + int len; 209 184 if( argc!=2 ){ 210 - return Th_WrongNumArgs(interp, "hascap STRING"); 185 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 186 + return JIM_ERR; 211 187 } 212 - rc = login_has_capability((char*)argv[1],argl[1]); 188 + str = Jim_GetString(argv[1], &len); 189 + rc = login_has_capability(str, len); 213 190 if( g.thTrace ){ 214 - Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc); 191 + Th_Trace("[hascap %#h] => %d<br />\n", len, str, rc); 215 192 } 216 - Th_SetResultInt(interp, rc); 217 - return TH_OK; 193 + Jim_SetResultInt(interp, rc); 194 + return JIM_OK; 218 195 } 219 196 220 197 /* 221 198 ** TH command: anycap STRING 222 199 ** 223 200 ** Return true if the user has any one of the capabilities listed in STRING. 224 201 */ 225 -static int anycapCmd( 226 - Th_Interp *interp, 227 - void *p, 228 - int argc, 229 - const char **argv, 230 - int *argl 231 -){ 202 +static int anycapCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 203 +{ 232 204 int rc = 0; 233 205 int i; 206 + const char *str; 207 + int len; 234 208 if( argc!=2 ){ 235 - return Th_WrongNumArgs(interp, "anycap STRING"); 209 + Jim_WrongNumArgs(interp, 1, argv, "STRING"); 210 + return JIM_ERR; 236 211 } 237 - for(i=0; rc==0 && i<argl[1]; i++){ 238 - rc = login_has_capability((char*)&argv[1][i],1); 212 + str = Jim_GetString(argv[1], &len); 213 + for(i=0; rc==0 && i<len; i++){ 214 + rc = login_has_capability(&str[i],1); 239 215 } 240 216 if( g.thTrace ){ 241 - Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc); 217 + Th_Trace("[hascap %#h] => %d<br />\n", len, str, rc); 242 218 } 243 - Th_SetResultInt(interp, rc); 244 - return TH_OK; 219 + Jim_SetResultInt(interp, rc); 220 + return JIM_OK; 245 221 } 246 222 247 223 /* 248 224 ** TH1 command: combobox NAME TEXT-LIST NUMLINES 249 225 ** 250 226 ** Generate an HTML combobox. NAME is both the name of the 251 227 ** CGI parameter and the name of a variable that contains the 252 228 ** currently selected value. TEXT-LIST is a list of possible 253 229 ** values for the combobox. NUMLINES is 1 for a true combobox. 254 230 ** If NUMLINES is greater than one then the display is a listbox 255 231 ** with the number of lines given. 256 232 */ 257 -static int comboboxCmd( 258 - Th_Interp *interp, 259 - void *p, 260 - int argc, 261 - const char **argv, 262 - int *argl 263 -){ 233 +static int comboboxCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 234 +{ 264 235 if( argc!=4 ){ 265 - return Th_WrongNumArgs(interp, "combobox NAME TEXT-LIST NUMLINES"); 236 + Jim_WrongNumArgs(interp, 1, argv, "NAME TEXT-LIST NUMLINES"); 237 + return JIM_ERR; 266 238 } 267 239 if( enableOutput ){ 268 - int height; 269 - Blob name; 270 - int nValue; 271 - const char *zValue; 240 + long height; 272 241 char *z, *zH; 273 242 int nElem; 274 - int *aszElem; 275 - char **azElem; 276 243 int i; 244 + Jim_Obj *objPtr; 245 + Jim_Obj *varObjPtr; 277 246 278 - if( Th_ToInt(interp, argv[3], argl[3], &height) ) return TH_ERROR; 279 - Th_SplitList(interp, argv[2], argl[2], &azElem, &aszElem, &nElem); 280 - blob_init(&name, (char*)argv[1], argl[1]); 281 - zValue = Th_Fetch(blob_str(&name), &nValue); 247 + if( Jim_GetLong(interp, argv[3], &height) ) return JIM_ERR; 248 + nElem = Jim_ListLength(interp, argv[2]); 249 + 250 + varObjPtr = Jim_GetVariable(g.interp, argv[1], JIM_NONE); 282 251 z = mprintf("<select name=\"%z\" size=\"%d\">", 283 - htmlize(blob_buffer(&name), blob_size(&name)), height); 252 + htmlize(Jim_String(varObjPtr), Jim_Length(varObjPtr)), height); 284 253 sendText(z, -1, 0); 285 254 free(z); 286 - blob_reset(&name); 287 255 for(i=0; i<nElem; i++){ 288 - zH = htmlize((char*)azElem[i], aszElem[i]); 289 - if( zValue && aszElem[i]==nValue 290 - && memcmp(zValue, azElem[i], nValue)==0 ){ 256 + Jim_ListIndex(interp, argv[2], i, &objPtr, JIM_NONE); 257 + zH = htmlize(Jim_String(objPtr), Jim_Length(objPtr)); 258 + if( varObjPtr && Jim_StringEqObj(varObjPtr, objPtr)) { 291 259 z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>", 292 260 zH, zH); 293 261 }else{ 294 262 z = mprintf("<option value=\"%s\">%s</option>", zH, zH); 295 263 } 296 264 free(zH); 297 265 sendText(z, -1, 0); 298 266 free(z); 299 267 } 300 268 sendText("</select>", -1, 0); 301 - Th_Free(interp, azElem); 302 269 } 303 - return TH_OK; 270 + return JIM_OK; 304 271 } 305 272 306 273 /* 307 274 ** TH1 command: linecount STRING MAX MIN 308 275 ** 309 276 ** Return one more than the number of \n characters in STRING. But 310 277 ** never return less than MIN or more than MAX. 311 278 */ 312 -static int linecntCmd( 313 - Th_Interp *interp, 314 - void *p, 315 - int argc, 316 - const char **argv, 317 - int *argl 318 -){ 279 +static int linecntCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 280 +{ 319 281 const char *z; 320 282 int size, n, i; 321 - int iMin, iMax; 283 + jim_wide iMin, iMax; 322 284 if( argc!=4 ){ 323 - return Th_WrongNumArgs(interp, "linecount STRING MAX MIN"); 285 + Jim_WrongNumArgs(interp, 1, argv, "STRING MAX MIN"); 286 + return JIM_ERR; 324 287 } 325 - if( Th_ToInt(interp, argv[2], argl[2], &iMax) ) return TH_ERROR; 326 - if( Th_ToInt(interp, argv[3], argl[3], &iMin) ) return TH_ERROR; 327 - z = argv[1]; 328 - size = argl[1]; 288 + if( Jim_GetWide(interp, argv[2], &iMax) ) return JIM_ERR; 289 + if( Jim_GetWide(interp, argv[3], &iMin) ) return JIM_ERR; 290 + z = Jim_GetString(argv[1], &size); 329 291 for(n=1, i=0; i<size; i++){ 330 292 if( z[i]=='\n' ){ 331 293 n++; 332 294 if( n>=iMax ) break; 333 295 } 334 296 } 335 297 if( n<iMin ) n = iMin; 336 298 if( n>iMax ) n = iMax; 337 - Th_SetResultInt(interp, n); 338 - return TH_OK; 299 + Jim_SetResultInt(interp, n); 300 + return JIM_OK; 339 301 } 340 302 341 303 /* 342 304 ** TH1 command: repository ?BOOLEAN? 343 305 ** 344 306 ** Return the fully qualified file name of the open repository or an empty 345 307 ** string if one is not currently open. Optionally, it will attempt to open 346 308 ** the repository if the boolean argument is non-zero. 347 309 */ 348 -static int repositoryCmd( 349 - Th_Interp *interp, 350 - void *p, 351 - int argc, 352 - const char **argv, 353 - int *argl 354 -){ 355 - int openRepository; 310 +static int repositoryCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 311 +{ 312 + long openRepository; 356 313 357 314 if( argc!=1 && argc!=2 ){ 358 - return Th_WrongNumArgs(interp, "repository ?BOOLEAN?"); 315 + Jim_WrongNumArgs(interp, 1, argv, "BOOLEAN"); 316 + return JIM_ERR; 359 317 } 360 318 if( argc==2 ){ 361 - if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){ 362 - return TH_ERROR; 319 + if( Jim_GetLong(interp, argv[1], &openRepository) != JIM_OK){ 320 + return JIM_ERR; 363 321 } 364 322 if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0); 365 323 } 366 - Th_SetResult(interp, g.zRepositoryName, -1); 367 - return TH_OK; 324 + Jim_SetResultString(interp, g.zRepositoryName, -1); 325 + return JIM_OK; 368 326 } 369 327 370 328 /* 371 329 ** Make sure the interpreter has been initialized. Initialize it if 372 330 ** it has not been already. 373 331 ** 374 332 ** The interpreter is stored in the g.interp global variable. 375 333 */ 376 334 void Th_FossilInit(void){ 377 335 static struct _Command { 378 336 const char *zName; 379 - Th_CommandProc xProc; 380 - void *pContext; 337 + Jim_CmdProc xProc; 381 338 } aCommand[] = { 382 - {"anycap", anycapCmd, 0}, 383 - {"combobox", comboboxCmd, 0}, 384 - {"enable_output", enableOutputCmd, 0}, 385 - {"linecount", linecntCmd, 0}, 386 - {"hascap", hascapCmd, 0}, 387 - {"htmlize", htmlizeCmd, 0}, 388 - {"date", dateCmd, 0}, 389 - {"html", putsCmd, 0}, 390 - {"puts", putsCmd, (void*)1}, 391 - {"wiki", wikiCmd, 0}, 392 - {"repository", repositoryCmd, 0}, 393 - {0, 0, 0} 339 + {"anycap", anycapCmd, }, 340 + {"combobox", comboboxCmd, }, 341 + {"enable_output", enableOutputCmd, }, 342 + {"linecount", linecntCmd, }, 343 + {"hascap", hascapCmd, }, 344 + {"htmlize", htmlizeCmd, }, 345 + {"date", dateCmd, }, 346 + {"html", htmlCmd, }, 347 + {"puts", putsCmd, }, 348 + {"wiki", wikiCmd, }, 349 + {"repository", repositoryCmd, }, 350 + {0, 0} 394 351 }; 395 352 if( g.interp==0 ){ 396 353 int i; 397 - g.interp = Th_CreateInterp(&vtab); 398 - th_register_language(g.interp); /* Basic scripting commands. */ 354 + /* Create and initialize the interpreter */ 355 + g.interp = Jim_CreateInterp(); 356 + Jim_RegisterCoreCommands(g.interp); 357 + 358 + /* Register static extensions */ 359 + Jim_InitStaticExtensions(g.interp); 360 + 399 361 #ifdef FOSSIL_ENABLE_TCL 400 - if( getenv("TH1_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){ 401 - th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ 362 + if( getenv("FOSSIL_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){ 363 + register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ 402 364 } 403 365 #endif 404 366 for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){ 405 367 if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; 406 - Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc, 407 - aCommand[i].pContext, 0); 368 + Jim_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc, NULL, 369 + NULL); 408 370 } 409 371 } 410 372 } 411 373 412 374 /* 413 375 ** Store a string value in a variable in the interpreter. 414 376 */ 415 377 void Th_Store(const char *zName, const char *zValue){ 416 378 Th_FossilInit(); 417 379 if( zValue ){ 418 380 if( g.thTrace ){ 419 381 Th_Trace("set %h {%h}<br />\n", zName, zValue); 420 382 } 421 - Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue)); 383 + Jim_SetVariableStrWithStr(g.interp, zName, zValue); 422 384 } 423 385 } 424 386 425 387 /* 426 388 ** Unset a variable. 427 389 */ 428 390 void Th_Unstore(const char *zName){ 429 391 if( g.interp ){ 430 - Th_UnsetVar(g.interp, (char*)zName, -1); 392 + Jim_Obj *nameObjPtr = Jim_NewStringObj(g.interp, zName, -1); 393 + Jim_UnsetVariable(g.interp, nameObjPtr, JIM_NONE); 394 + Jim_FreeNewObj(g.interp, nameObjPtr); 431 395 } 432 396 } 433 397 434 398 /* 435 -** Retrieve a string value from the interpreter. If no such 399 +** Retrieve a string value (variable) from the interpreter. If no such 436 400 ** variable exists, return NULL. 437 401 */ 438 -char *Th_Fetch(const char *zName, int *pSize){ 439 - int rc; 402 +const char *Th_Fetch(const char *zName){ 403 + Jim_Obj *objPtr; 404 + 440 405 Th_FossilInit(); 441 - rc = Th_GetVar(g.interp, (char*)zName, -1); 442 - if( rc==TH_OK ){ 443 - return (char*)Th_GetResult(g.interp, pSize); 444 - }else{ 445 - return 0; 446 - } 406 + 407 + objPtr = Jim_GetVariableStr(g.interp, zName, JIM_NONE); 408 + 409 + return objPtr ? Jim_String(objPtr) : NULL; 410 +} 411 + 412 +/** 413 + * Like Th_Fetch() except the variable name may not be null terminated. 414 + * Instead, the length of the name is supplied as 'namelen'. 415 + */ 416 +const char *Th_GetVar(Jim_Interp *interp, const char *name, int namelen){ 417 + Jim_Obj *nameObjPtr, *varObjPtr; 418 + 419 + nameObjPtr = Jim_NewStringObj(interp, name, namelen); 420 + Jim_IncrRefCount(nameObjPtr); 421 + varObjPtr = Jim_GetVariable(interp, nameObjPtr, 0); 422 + Jim_DecrRefCount(interp, nameObjPtr); 423 + 424 + return varObjPtr ? Jim_String(varObjPtr) : NULL; 447 425 } 448 426 449 427 /* 450 428 ** Return true if the string begins with the TH1 begin-script 451 429 ** tag: <th1>. 452 430 */ 453 431 static int isBeginScriptTag(const char *z){ 432 + /* XXX: Should we also allow <tcl>? */ 454 433 return z[0]=='<' 455 434 && (z[1]=='t' || z[1]=='T') 456 435 && (z[2]=='h' || z[2]=='H') 457 436 && z[3]=='1' 458 437 && z[4]=='>'; 459 438 } 460 439 461 440 /* 462 441 ** Return true if the string begins with the TH1 end-script 463 442 ** tag: </th1>. 464 443 */ 465 444 static int isEndScriptTag(const char *z){ 445 + /* XXX: Should we also allow </tcl>? */ 466 446 return z[0]=='<' 467 447 && z[1]=='/' 468 448 && (z[2]=='t' || z[2]=='T') 469 449 && (z[3]=='h' || z[3]=='H') 470 450 && z[4]=='1' 471 451 && z[5]=='>'; 472 452 } ................................................................................ 511 491 ** 512 492 ** This routine processes the template and writes the results 513 493 ** on either stdout or into CGI. 514 494 */ 515 495 int Th_Render(const char *z){ 516 496 int i = 0; 517 497 int n; 518 - int rc = TH_OK; 519 - char *zResult; 498 + int rc = JIM_OK; 499 + const char *zResult; 520 500 Th_FossilInit(); 521 501 while( z[i] ){ 522 502 if( z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){ 523 503 const char *zVar; 524 504 int nVar; 525 505 int encode = 1; 526 506 sendText(z, i, 0); ................................................................................ 530 510 nVar = n-2; 531 511 }else{ 532 512 /* Variables of the form $aaa are output raw */ 533 513 zVar = &z[i+1]; 534 514 nVar = n; 535 515 encode = 0; 536 516 } 537 - rc = Th_GetVar(g.interp, (char*)zVar, nVar); 517 + zResult = Th_GetVar(g.interp, zVar, nVar); 538 518 z += i+1+n; 539 519 i = 0; 540 - zResult = (char*)Th_GetResult(g.interp, &n); 541 - sendText((char*)zResult, n, encode); 520 + if (zResult) { 521 + sendText(zResult, -1, encode); 522 + } 542 523 }else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){ 524 + Jim_Obj *objPtr; 543 525 sendText(z, i, 0); 544 526 z += i+5; 545 527 for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){} 546 - rc = Th_Eval(g.interp, 0, (const char*)z, i); 547 - if( rc!=TH_OK ) break; 528 + /* XXX: Would be nice to record the source location in case of error */ 529 + objPtr = Jim_NewStringObj(g.interp, z, i); 530 + rc = Jim_EvalObj(g.interp, objPtr); 531 + if( rc!=JIM_OK ) break; 548 532 z += i; 549 533 if( z[0] ){ z += 6; } 550 534 i = 0; 551 535 }else{ 552 536 i++; 553 537 } 554 538 } 555 - if( rc==TH_ERROR ){ 539 + if( rc==JIM_ERR ){ 556 540 sendText("<hr><p class=\"thmainError\">ERROR: ", -1, 0); 557 - zResult = (char*)Th_GetResult(g.interp, &n); 558 - sendText((char*)zResult, n, 1); 541 + sendTextObj(Jim_GetResult(g.interp), 1); 559 542 sendText("</p>", -1, 0); 560 543 }else{ 561 544 sendText(z, i, 0); 562 545 } 563 546 return rc; 564 547 } 565 548 566 549 /* 567 -** COMMAND: test-th-render 550 +** COMMAND: test-script-render 568 551 */ 569 -void test_th_render(void){ 552 +void test_script_render(void){ 570 553 Blob in; 571 554 if( g.argc<3 ){ 572 555 usage("FILE"); 573 556 } 574 557 db_open_config(0); /* Needed for global "tcl" setting. */ 575 558 blob_zero(&in); 576 559 blob_read_from_file(&in, g.argv[2]); 577 560 Th_Render(blob_str(&in)); 578 561 }
Changes to src/th_tcl.c.
4 4 ** known as the "2-Clause License" or "FreeBSD License".) 5 5 ** 6 6 ** This program is distributed in the hope that it will be useful, 7 7 ** but without any warranty; without even the implied warranty of 8 8 ** merchantability or fitness for a particular purpose. 9 9 ** 10 10 ******************************************************************************* 11 -** This file contains code used to bridge the TH1 and Tcl scripting languages. 11 +** This file contains code used to bridge the Jim and Tcl scripting languages. 12 12 */ 13 13 14 14 #include "config.h" 15 15 16 16 #ifdef FOSSIL_ENABLE_TCL 17 17 18 -#include "th.h" 18 +#include "jim.h" 19 19 #include "tcl.h" 20 20 21 21 /* 22 22 ** Are we being compiled against Tcl 8.6 or higher? 23 23 */ 24 24 #if (TCL_MAJOR_VERSION > 8) || \ 25 25 ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 6)) ................................................................................ 28 28 ** Tcl_EvalObjv instead of invoking the objProc directly. 29 29 */ 30 30 #define USE_TCL_EVALOBJV 1 31 31 #endif 32 32 33 33 /* 34 34 ** These macros are designed to reduce the redundant code required to marshal 35 -** arguments from TH1 to Tcl. 35 +** arguments from Jim to Tcl. 36 36 */ 37 37 #define USE_ARGV_TO_OBJV() \ 38 38 int objc; \ 39 39 Tcl_Obj **objv; \ 40 40 int i; 41 41 42 -#define COPY_ARGV_TO_OBJV() \ 43 - objc = argc-1; \ 44 - objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \ 45 - for(i=1; i<argc; i++){ \ 46 - objv[i-1] = Tcl_NewStringObj(argv[i], argl[i]); \ 47 - Tcl_IncrRefCount(objv[i-1]); \ 42 +#define COPY_ARGV_TO_OBJV() \ 43 + objc = argc-1; \ 44 + objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \ 45 + for(i=1; i<argc; i++){ \ 46 + objv[i-1] = Tcl_NewStringObj(Jim_String(argv[i]), Jim_Length(argv[i])); \ 47 + Tcl_IncrRefCount(objv[i-1]); \ 48 48 } 49 49 50 50 #define FREE_ARGV_TO_OBJV() \ 51 51 for(i=1; i<argc; i++){ \ 52 52 Tcl_DecrRefCount(objv[i-1]); \ 53 53 } \ 54 54 ckfree((char *)objv); ................................................................................ 57 57 ** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl 58 58 ** context. 59 59 */ 60 60 #define GET_CTX_TCL_INTERP(ctx) \ 61 61 ((struct TclContext *)(ctx))->interp 62 62 63 63 /* 64 -** Creates and initializes a Tcl interpreter for use with the specified TH1 64 +** Creates and initializes a Tcl interpreter for use with the specified Jim 65 65 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied 66 66 ** by the caller. This must be declared here because quite a few functions in 67 67 ** this file need to use it before it can be defined. 68 68 */ 69 -static int createTclInterp(Th_Interp *interp, void *pContext); 69 +static int createTclInterp(Jim_Interp *interp, void *pContext); 70 70 71 71 /* 72 72 ** Returns the Tcl interpreter result as a string with the associated length. 73 73 ** If the Tcl interpreter or the Tcl result are NULL, the length will be 0. 74 74 ** If the length pointer is NULL, the length will not be stored. 75 75 */ 76 76 static char *getTclResult( ................................................................................ 87 87 if( pN ) *pN = 0; 88 88 return 0; 89 89 } 90 90 return Tcl_GetStringFromObj(resultPtr, pN); 91 91 } 92 92 93 93 /* 94 -** Tcl context information used by TH1. This structure definition has been 94 +** Tcl context information used by Jim. This structure definition has been 95 95 ** copied from and should be kept in sync with the one in "main.c". 96 96 */ 97 97 struct TclContext { 98 98 int argc; 99 99 char **argv; 100 100 Tcl_Interp *interp; 101 101 }; ................................................................................ 102 102 103 103 /* 104 104 ** Syntax: 105 105 ** 106 106 ** tclEval arg ?arg ...? 107 107 */ 108 108 static int tclEval_command( 109 - Th_Interp *interp, 110 - void *ctx, 109 + Jim_Interp *interp, 111 110 int argc, 112 - const char **argv, 113 - int *argl 111 + Jim_Obj *const *argv 114 112 ){ 115 113 Tcl_Interp *tclInterp; 116 114 Tcl_Obj *objPtr; 117 115 int rc; 118 116 int nResult; 119 117 const char *zResult; 118 + void *ctx = Jim_CmdPrivData(interp); 120 119 121 - if ( createTclInterp(interp, ctx)!=TH_OK ){ 122 - return TH_ERROR; 120 + if ( createTclInterp(interp, ctx)!=JIM_OK ){ 121 + return JIM_ERR; 123 122 } 124 123 if( argc<2 ){ 125 - return Th_WrongNumArgs(interp, "tclEval arg ?arg ...?"); 124 + Jim_WrongNumArgs(interp, 1, argv, "arg ?arg ...?"); 125 + return JIM_ERR; 126 126 } 127 127 tclInterp = GET_CTX_TCL_INTERP(ctx); 128 128 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){ 129 - Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0); 130 - return TH_ERROR; 129 + Jim_SetResultString(interp, "invalid Tcl interpreter", -1); 130 + return JIM_ERR; 131 131 } 132 132 Tcl_Preserve((ClientData)tclInterp); 133 133 if( argc==2 ){ 134 - objPtr = Tcl_NewStringObj(argv[1], argl[1]); 134 + objPtr = Tcl_NewStringObj(Jim_String(argv[1]), Jim_Length(argv[1])); 135 135 Tcl_IncrRefCount(objPtr); 136 136 rc = Tcl_EvalObjEx(tclInterp, objPtr, 0); 137 137 Tcl_DecrRefCount(objPtr); 138 138 }else{ 139 139 USE_ARGV_TO_OBJV(); 140 140 COPY_ARGV_TO_OBJV(); 141 141 objPtr = Tcl_ConcatObj(objc, objv); 142 142 Tcl_IncrRefCount(objPtr); 143 143 rc = Tcl_EvalObjEx(tclInterp, objPtr, 0); 144 144 Tcl_DecrRefCount(objPtr); 145 145 FREE_ARGV_TO_OBJV(); 146 146 } 147 147 zResult = getTclResult(tclInterp, &nResult); 148 - Th_SetResult(interp, zResult, nResult); 148 + Jim_SetResultString(interp, zResult, nResult); 149 149 Tcl_Release((ClientData)tclInterp); 150 150 return rc; 151 151 } 152 152 153 153 /* 154 154 ** Syntax: 155 155 ** 156 156 ** tclExpr arg ?arg ...? 157 157 */ 158 158 static int tclExpr_command( 159 - Th_Interp *interp, 160 - void *ctx, 159 + Jim_Interp *interp, 161 160 int argc, 162 - const char **argv, 163 - int *argl 161 + Jim_Obj *const *argv 164 162 ){ 165 163 Tcl_Interp *tclInterp; 166 164 Tcl_Obj *objPtr; 167 165 Tcl_Obj *resultObjPtr; 168 166 int rc; 169 167 int nResult; 170 168 const char *zResult; 169 + void *ctx = Jim_CmdPrivData(interp); 171 170 172 - if ( createTclInterp(interp, ctx)!=TH_OK ){ 173 - return TH_ERROR; 171 + if ( createTclInterp(interp, ctx)!=JIM_OK ){ 172 + return JIM_ERR; 174 173 } 175 174 if( argc<2 ){ 176 - return Th_WrongNumArgs(interp, "tclExpr arg ?arg ...?"); 175 + Jim_WrongNumArgs(interp, 1, argv, "arg ?arg ...?"); 176 + return JIM_ERR; 177 177 } 178 178 tclInterp = GET_CTX_TCL_INTERP(ctx); 179 179 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){ 180 - Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0); 181 - return TH_ERROR; 180 + Jim_SetResultString(interp, "invalid Tcl interpreter", -1); 181 + return JIM_ERR; 182 182 } 183 183 Tcl_Preserve((ClientData)tclInterp); 184 184 if( argc==2 ){ 185 - objPtr = Tcl_NewStringObj(argv[1], argl[1]); 185 + objPtr = Tcl_NewStringObj(Jim_String(argv[1]), Jim_Length(argv[1])); 186 186 Tcl_IncrRefCount(objPtr); 187 187 rc = Tcl_ExprObj(tclInterp, objPtr, &resultObjPtr); 188 188 Tcl_DecrRefCount(objPtr); 189 189 }else{ 190 190 USE_ARGV_TO_OBJV(); 191 191 COPY_ARGV_TO_OBJV(); 192 192 objPtr = Tcl_ConcatObj(objc, objv); ................................................................................ 196 196 FREE_ARGV_TO_OBJV(); 197 197 } 198 198 if( rc==TCL_OK ){ 199 199 zResult = Tcl_GetStringFromObj(resultObjPtr, &nResult); 200 200 }else{ 201 201 zResult = getTclResult(tclInterp, &nResult); 202 202 } 203 - Th_SetResult(interp, zResult, nResult); 203 + Jim_SetResultString(interp, zResult, nResult); 204 204 if( rc==TCL_OK ) Tcl_DecrRefCount(resultObjPtr); 205 205 Tcl_Release((ClientData)tclInterp); 206 206 return rc; 207 207 } 208 208 209 209 /* 210 210 ** Syntax: 211 211 ** 212 212 ** tclInvoke command ?arg ...? 213 213 */ 214 214 static int tclInvoke_command( 215 - Th_Interp *interp, 216 - void *ctx, 215 + Jim_Interp *interp, 217 216 int argc, 218 - const char **argv, 219 - int *argl 217 + Jim_Obj *const *argv 220 218 ){ 221 219 Tcl_Interp *tclInterp; 222 220 #ifndef USE_TCL_EVALOBJV 223 221 Tcl_Command command; 224 222 Tcl_CmdInfo cmdInfo; 225 223 #endif 226 224 int rc; 227 225 int nResult; 228 226 const char *zResult; 227 + void *ctx = Jim_CmdPrivData(interp); 229 228 #ifndef USE_TCL_EVALOBJV 230 229 Tcl_Obj *objPtr; 231 230 #endif 232 231 USE_ARGV_TO_OBJV(); 233 232 234 - if ( createTclInterp(interp, ctx)!=TH_OK ){ 235 - return TH_ERROR; 233 + if ( createTclInterp(interp, ctx)!=JIM_OK ){ 234 + return JIM_ERR; 236 235 } 237 236 if( argc<2 ){ 238 - return Th_WrongNumArgs(interp, "tclInvoke command ?arg ...?"); 237 + Jim_WrongNumArgs(interp, 1, argv, "command ?arg ...?"); 238 + return JIM_ERR; 239 239 } 240 240 tclInterp = GET_CTX_TCL_INTERP(ctx); 241 241 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){ 242 - Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0); 243 - return TH_ERROR; 242 + Jim_SetResultString(interp, "invalid Tcl interpreter", -1); 243 + return JIM_ERR; 244 244 } 245 245 Tcl_Preserve((ClientData)tclInterp); 246 246 #ifndef USE_TCL_EVALOBJV 247 - objPtr = Tcl_NewStringObj(argv[1], argl[1]); 247 + objPtr = Tcl_NewStringObj(Jim_String(argv[1]), Jim_Length(argv[1])); 248 248 Tcl_IncrRefCount(objPtr); 249 249 command = Tcl_GetCommandFromObj(tclInterp, objPtr); 250 250 if( !command || Tcl_GetCommandInfoFromToken(command,&cmdInfo)==0 ){ 251 - Th_ErrorMessage(interp, "Tcl command not found:", argv[1], argl[1]); 251 + Jim_SetResultFormatted(interp, "Tcl command not found: %#s", argv[1]); 252 252 Tcl_DecrRefCount(objPtr); 253 253 Tcl_Release((ClientData)tclInterp); 254 - return TH_ERROR; 254 + return JIM_ERR; 255 255 } 256 256 if( !cmdInfo.objProc ){ 257 - Th_ErrorMessage(interp, "Cannot invoke Tcl command:", argv[1], argl[1]); 257 + Jim_SetResultFormatted(interp, "Cannot invoke command not found: %#s", 258 + argv[1]); 258 259 Tcl_DecrRefCount(objPtr); 259 260 Tcl_Release((ClientData)tclInterp); 260 - return TH_ERROR; 261 + return JIM_ERR; 261 262 } 262 263 Tcl_DecrRefCount(objPtr); 263 264 #endif 264 265 COPY_ARGV_TO_OBJV(); 265 266 #ifdef USE_TCL_EVALOBJV 266 267 rc = Tcl_EvalObjv(tclInterp, objc, objv, 0); 267 268 #else 268 269 Tcl_ResetResult(tclInterp); 269 270 rc = cmdInfo.objProc(cmdInfo.objClientData, tclInterp, objc, objv); 270 271 #endif 271 272 FREE_ARGV_TO_OBJV(); 272 273 zResult = getTclResult(tclInterp, &nResult); 273 - Th_SetResult(interp, zResult, nResult); 274 + Jim_SetResultString(interp, zResult, nResult); 274 275 Tcl_Release((ClientData)tclInterp); 275 276 return rc; 276 277 } 277 278 278 279 /* 279 280 ** Syntax: 280 281 ** 281 -** th1Eval arg 282 +** bridgeEval arg 282 283 */ 283 -static int Th1EvalObjCmd( 284 +static int BridgeEvalObjCmd( 284 285 ClientData clientData, 285 286 Tcl_Interp *interp, 286 287 int objc, 287 288 Tcl_Obj *CONST objv[] 288 289 ){ 289 - Th_Interp *th1Interp; 290 + Jim_Interp *jimInterp; 290 291 int nArg; 291 292 const char *arg; 292 293 int rc; 294 + Jim_Obj *argObj; 295 + Jim_Obj *resultObj; 293 296 294 297 if( objc!=2 ){ 295 298 Tcl_WrongNumArgs(interp, 1, objv, "arg"); 296 299 return TCL_ERROR; 297 300 } 298 - th1Interp = (Th_Interp *)clientData; 299 - if( !th1Interp ){ 300 - Tcl_AppendResult(interp, "invalid TH1 interpreter", NULL); 301 + jimInterp = (Jim_Interp *)clientData; 302 + if( !jimInterp ){ 303 + Tcl_AppendResult(interp, "invalid bridge interpreter", NULL); 301 304 return TCL_ERROR; 302 305 } 303 306 arg = Tcl_GetStringFromObj(objv[1], &nArg); 304 - rc = Th_Eval(th1Interp, 0, arg, nArg); 305 - arg = Th_GetResult(th1Interp, &nArg); 307 + argObj = Jim_NewStringObj(jimInterp, arg, nArg); 308 + Jim_IncrRefCount(argObj); 309 + rc = Jim_EvalObj(jimInterp, argObj); 310 + Jim_DecrRefCount(jimInterp, argObj); 311 + resultObj = Jim_GetResult(jimInterp); 312 + arg = Jim_GetString(resultObj, &nArg); 306 313 Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg)); 307 314 return rc; 308 315 } 309 316 310 317 /* 311 318 ** Syntax: 312 319 ** 313 -** th1Expr arg 320 +** bridgeExpr arg 314 321 */ 315 -static int Th1ExprObjCmd( 322 +static int BridgeExprObjCmd( 316 323 ClientData clientData, 317 324 Tcl_Interp *interp, 318 325 int objc, 319 326 Tcl_Obj *CONST objv[] 320 327 ){ 321 - Th_Interp *th1Interp; 328 + Jim_Interp *jimInterp; 322 329 int nArg; 323 330 const char *arg; 324 331 int rc; 332 + Jim_Obj *argObj; 333 + Jim_Obj *resultObj; 325 334 326 335 if( objc!=2 ){ 327 336 Tcl_WrongNumArgs(interp, 1, objv, "arg"); 328 337 return TCL_ERROR; 329 338 } 330 - th1Interp = (Th_Interp *)clientData; 331 - if( !th1Interp ){ 332 - Tcl_AppendResult(interp, "invalid TH1 interpreter", NULL); 339 + jimInterp = (Jim_Interp *)clientData; 340 + if( !jimInterp ){ 341 + Tcl_AppendResult(interp, "invalid bridge interpreter", NULL); 333 342 return TCL_ERROR; 334 343 } 335 344 arg = Tcl_GetStringFromObj(objv[1], &nArg); 336 - rc = Th_Expr(th1Interp, arg, nArg); 337 - arg = Th_GetResult(th1Interp, &nArg); 338 - Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg)); 345 + argObj = Jim_NewStringObj(jimInterp, arg, nArg); 346 + Jim_IncrRefCount(argObj); 347 + rc = Jim_EvalExpression(jimInterp, argObj, &resultObj); 348 + Jim_DecrRefCount(jimInterp, argObj); 349 + if (rc == JIM_OK) { 350 + arg = Jim_GetString(resultObj, &nArg); 351 + Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg)); 352 + } 339 353 return rc; 340 354 } 341 355 342 356 /* 343 357 ** Array of Tcl integration commands. Used when adding or removing the Tcl 344 -** integration commands from TH1. 358 +** integration commands from Jim. 345 359 */ 346 360 static struct _Command { 347 361 const char *zName; 348 - Th_CommandProc xProc; 362 + Jim_CmdProc xProc; 349 363 void *pContext; 350 364 } aCommand[] = { 351 365 {"tclEval", tclEval_command, 0}, 352 366 {"tclExpr", tclExpr_command, 0}, 353 367 {"tclInvoke", tclInvoke_command, 0}, 354 368 {0, 0, 0} 355 369 }; 356 370 357 371 /* 358 372 ** Called if the Tcl interpreter is deleted. Removes the Tcl integration 359 -** commands from the TH1 interpreter. 373 +** commands from the Jim interpreter. 360 374 */ 361 -static void Th1DeleteProc( 375 +static void BridgeDeleteProc( 362 376 ClientData clientData, 363 377 Tcl_Interp *interp 364 378 ){ 365 379 int i; 366 - Th_Interp *th1Interp = (Th_Interp *)clientData; 367 - if( !th1Interp ) return; 380 + Jim_Interp *jimInterp = (Jim_Interp *)clientData; 381 + if( !jimInterp ) return; 368 382 /* Remove the Tcl integration commands. */ 369 383 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ 370 - Th_RenameCommand(th1Interp, aCommand[i].zName, -1, NULL, 0); 384 + Jim_DeleteCommand(jimInterp, aCommand[i].zName); 371 385 } 372 386 } 373 387 374 388 /* 375 -** Creates and initializes a Tcl interpreter for use with the specified TH1 389 +** Creates and initializes a Tcl interpreter for use with the specified Jim 376 390 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied 377 391 ** by the caller. 378 392 */ 379 393 static int createTclInterp( 380 - Th_Interp *interp, 394 + Jim_Interp *interp, 381 395 void *pContext 382 396 ){ 383 397 struct TclContext *tclContext = (struct TclContext *)pContext; 384 398 Tcl_Interp *tclInterp; 385 399 386 400 if ( !tclContext ){ 387 - Th_ErrorMessage(interp, 388 - "Invalid Tcl context", (const char *)"", 0); 389 - return TH_ERROR; 401 + Jim_SetResultString(interp, "Invalid Tcl context", -1); 402 + return JIM_ERR; 390 403 } 391 404 if ( tclContext->interp ){ 392 - return TH_OK; 405 + return JIM_OK; 393 406 } 394 407 if ( tclContext->argc>0 && tclContext->argv ) { 395 408 Tcl_FindExecutable(tclContext->argv[0]); 396 409 } 397 410 tclInterp = tclContext->interp = Tcl_CreateInterp(); 398 411 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){ 399 - Th_ErrorMessage(interp, 400 - "Could not create Tcl interpreter", (const char *)"", 0); 401 - return TH_ERROR; 412 + Jim_SetResultString(interp, "Could not create Tcl interpreter", -1); 413 + return JIM_ERR; 402 414 } 403 415 if( Tcl_Init(tclInterp)!=TCL_OK ){ 404 - Th_ErrorMessage(interp, 405 - "Tcl initialization error:", Tcl_GetStringResult(tclInterp), -1); 416 + Jim_SetResultFormatted(interp, "Tcl initialization error: %s", 417 + Tcl_GetStringResult(tclInterp)); 406 418 Tcl_DeleteInterp(tclInterp); 407 419 tclContext->interp = tclInterp = 0; 408 - return TH_ERROR; 420 + return JIM_ERR; 409 421 } 410 - /* Add the TH1 integration commands to Tcl. */ 411 - Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp); 412 - Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL); 413 - Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL); 414 - return TH_OK; 422 + /* Add the Jim integration commands to Tcl. */ 423 + Tcl_CallWhenDeleted(tclInterp, BridgeDeleteProc, interp); 424 + Tcl_CreateObjCommand(tclInterp, "bridgeEval", BridgeEvalObjCmd, interp, NULL); 425 + Tcl_CreateObjCommand(tclInterp, "bridgeExpr", BridgeExprObjCmd, interp, NULL); 426 + return JIM_OK; 415 427 } 416 428 417 429 /* 418 430 ** Register the Tcl language commands with interpreter interp. 419 431 ** Usually this is called soon after interpreter creation. 420 432 */ 421 -int th_register_tcl( 422 - Th_Interp *interp, 433 +int register_tcl( 434 + Jim_Interp *interp, 423 435 void *pContext 424 436 ){ 425 437 int i; 426 - /* Add the Tcl integration commands to TH1. */ 438 + /* Add the Tcl integration commands to Jim. */ 427 439 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ 428 440 void *ctx; 429 441 if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; 430 442 ctx = aCommand[i].pContext; 431 443 /* Use Tcl interpreter for context? */ 432 444 if( !ctx ) ctx = pContext; 433 - Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0); 445 + Jim_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, NULL); 434 446 } 435 - return TH_OK; 447 + return JIM_OK; 436 448 } 437 449 438 450 #endif /* FOSSIL_ENABLE_TCL */
Changes to src/tkt.c.
96 96 ** using the CONCEALED table so that the content legable. 97 97 ** Otherwise, db_reveal() is a no-op and the content remains 98 98 ** obscured. 99 99 */ 100 100 static void initializeVariablesFromDb(void){ 101 101 const char *zName; 102 102 Stmt q; 103 - int i, n, size, j; 103 + int i, n, j; 104 104 105 105 zName = PD("name","-none-"); 106 106 db_prepare(&q, "SELECT datetime(tkt_mtime,'localtime') AS tkt_datetime, *" 107 107 " FROM ticket WHERE tkt_uuid GLOB '%q*'", zName); 108 108 if( db_step(&q)==SQLITE_ROW ){ 109 109 n = db_column_count(&q); 110 110 for(i=0; i<n; i++){ ................................................................................ 118 118 } 119 119 for(j=0; j<nField; j++){ 120 120 if( fossil_strcmp(azField[j],zName)==0 ){ 121 121 azValue[j] = mprintf("%s", zVal); 122 122 break; 123 123 } 124 124 } 125 - if( Th_Fetch(zName, &size)==0 ){ 125 + if( Th_Fetch(zName)==0 ){ 126 126 Th_Store(zName, zVal); 127 127 } 128 128 free(zRevealed); 129 129 } 130 130 }else{ 131 131 db_finalize(&q); 132 132 db_prepare(&q, "PRAGMA table_info(ticket)"); 133 - if( Th_Fetch("tkt_uuid",&size)==0 ){ 133 + if( Th_Fetch("tkt_uuid")==0 ){ 134 134 Th_Store("tkt_uuid",zName); 135 135 } 136 136 while( db_step(&q)==SQLITE_ROW ){ 137 137 const char *zField = db_column_text(&q, 1); 138 - if( Th_Fetch(zField, &size)==0 ){ 138 + if( Th_Fetch(zField)==0 ){ 139 139 Th_Store(zField, ""); 140 140 } 141 141 } 142 - if( Th_Fetch("tkt_datetime",&size)==0 ){ 142 + if( Th_Fetch("tkt_datetime")==0 ){ 143 143 Th_Store("tkt_datetime",""); 144 144 } 145 145 } 146 146 db_finalize(&q); 147 147 } 148 148 149 149 /* ................................................................................ 238 238 /* 239 239 ** Create the subscript interpreter and load the "common" code. 240 240 */ 241 241 void ticket_init(void){ 242 242 const char *zConfig; 243 243 Th_FossilInit(); 244 244 zConfig = ticket_common_code(); 245 - Th_Eval(g.interp, 0, zConfig, -1); 245 + Jim_Eval(g.interp, zConfig); 246 246 } 247 247 248 248 /* 249 249 ** Recreate the ticket table. 250 250 */ 251 251 void ticket_create_table(int separateConnection){ 252 252 const char *zSql; ................................................................................ 371 371 ** TH command: append_field FIELD STRING 372 372 ** 373 373 ** FIELD is the name of a database column to which we might want 374 374 ** to append text. STRING is the text to be appended to that 375 375 ** column. The append does not actually occur until the 376 376 ** submit_ticket command is run. 377 377 */ 378 -static int appendRemarkCmd( 379 - Th_Interp *interp, 380 - void *p, 381 - int argc, 382 - const char **argv, 383 - int *argl 384 -){ 378 +static int appendRemarkCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 379 +{ 385 380 int idx; 381 + const char *str; 382 + int len; 386 383 387 384 if( argc!=3 ){ 388 - return Th_WrongNumArgs(interp, "append_field FIELD STRING"); 385 + Jim_WrongNumArgs(interp, 1, argv, "FIELD STRING"); 386 + return JIM_ERR; 389 387 } 388 + str = Jim_GetString(argv[1], &len); 390 389 if( g.thTrace ){ 391 390 Th_Trace("append_field %#h {%#h}<br />\n", 392 - argl[1], argv[1], argl[2], argv[2]); 391 + len, str, Jim_Length(argv[2]), Jim_String(argv[2])); 393 392 } 394 393 for(idx=0; idx<nField; idx++){ 395 - if( strncmp(azField[idx], argv[1], argl[1])==0 396 - && azField[idx][argl[1]]==0 ){ 394 + if( strncmp(azField[idx], str, len)==0 395 + && azField[idx][len]==0 ){ 397 396 break; 398 397 } 399 398 } 400 399 if( idx>=nField ){ 401 - Th_ErrorMessage(g.interp, "no such TICKET column: ", argv[1], argl[1]); 402 - return TH_ERROR; 400 + Jim_SetResultFormatted(g.interp, "no such TICKET column: %#s", argv[1]); 401 + return JIM_ERR; 403 402 } 404 - azAppend[idx] = mprintf("%.*s", argl[2], argv[2]); 405 - return TH_OK; 403 + azAppend[idx] = mprintf("%.*s", Jim_Length(argv[2]), Jim_String(argv[2])); 404 + return JIM_OK; 406 405 } 407 406 408 407 /* 409 408 ** Subscript command: submit_ticket 410 409 ** 411 410 ** Construct and submit a new ticket artifact. The fields of the artifact 412 411 ** are the names of the columns in the TICKET table. The content is 413 412 ** taken from TH variables. If the content is unchanged, the field is 414 413 ** omitted from the artifact. Fields whose names begin with "private_" 415 414 ** are concealed using the db_conceal() function. 416 415 */ 417 -static int submitTicketCmd( 418 - Th_Interp *interp, 419 - void *pUuid, 420 - int argc, 421 - const char **argv, 422 - int *argl 423 -){ 416 +static int submitTicketCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 417 +{ 424 418 char *zDate; 419 + void *pUuid = Jim_CmdPrivData(interp); 425 420 const char *zUuid; 426 421 int i; 427 422 int rid; 428 423 Blob tktchng, cksum; 429 424 430 425 login_verify_csrf_secret(); 431 426 zUuid = (const char *)pUuid; ................................................................................ 439 434 fossilize(azAppend[i], -1)); 440 435 } 441 436 } 442 437 for(i=0; i<nField; i++){ 443 438 const char *zValue; 444 439 int nValue; 445 440 if( azAppend[i] ) continue; 446 - zValue = Th_Fetch(azField[i], &nValue); 441 + zValue = Th_Fetch(azField[i]); 447 442 if( zValue ){ 443 + nValue = strlen(zValue); 448 444 while( nValue>0 && fossil_isspace(zValue[nValue-1]) ){ nValue--; } 449 445 if( strncmp(zValue, azValue[i], nValue) || strlen(azValue[i])!=nValue ){ 450 446 if( strncmp(azField[i], "private_", 8)==0 ){ 451 447 zValue = db_conceal(zValue, nValue); 452 448 blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue); 453 449 }else{ 454 450 blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue); ................................................................................ 470 466 blob_appendf(&tktchng, "Z %b\n", &cksum); 471 467 if( g.zPath[0]=='d' ){ 472 468 /* If called from /debug_tktnew or /debug_tktedit... */ 473 469 @ <font color="blue"> 474 470 @ <p>Ticket artifact that would have been submitted:</p> 475 471 @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote> 476 472 @ <hr /></font> 477 - return TH_OK; 473 + return JIM_OK; 478 474 }else if( g.thTrace ){ 479 475 Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n" 480 476 "}<br />\n", 481 477 blob_str(&tktchng)); 482 478 }else{ 483 479 rid = content_put(&tktchng); 484 480 if( rid==0 ){ ................................................................................ 485 481 fossil_panic("trouble committing ticket: %s", g.zErrMsg); 486 482 } 487 483 manifest_crosslink_begin(); 488 484 manifest_crosslink(rid, &tktchng); 489 485 assert( blob_is_reset(&tktchng) ); 490 486 manifest_crosslink_end(); 491 487 } 492 - return TH_RETURN; 488 + return JIM_RETURN; 493 489 } 494 490 495 491 496 492 /* 497 493 ** WEBPAGE: tktnew 498 494 ** WEBPAGE: debug_tktnew 499 495 ** ................................................................................ 525 521 if( P("date_override") && g.perm.Setup ){ 526 522 @ <input type="hidden" name="date_override" value="%h(P("date_override"))"> 527 523 } 528 524 @ </p> 529 525 zScript = ticket_newpage_code(); 530 526 Th_Store("login", g.zLogin); 531 527 Th_Store("date", db_text(0, "SELECT datetime('now')")); 532 - Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, 533 - (void*)&zNewUuid, 0); 528 + Jim_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void *)&zNewUuid, NULL); 534 529 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); 535 - if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){ 530 + if( Th_Render(zScript)==JIM_RETURN && !g.thTrace && zNewUuid ){ 536 531 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid)); 537 532 return; 538 533 } 539 534 @ </form> 540 535 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); 541 536 style_footer(); 542 537 } ................................................................................ 592 587 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><p> 593 588 @ <input type="hidden" name="name" value="%s(zName)" /> 594 589 login_insert_csrf_secret(); 595 590 @ </p> 596 591 zScript = ticket_editpage_code(); 597 592 Th_Store("login", g.zLogin); 598 593 Th_Store("date", db_text(0, "SELECT datetime('now')")); 599 - Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); 600 - Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); 594 + Jim_CreateCommand(g.interp, "append_field", appendRemarkCmd, NULL, NULL); 595 + Jim_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName, NULL); 601 596 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1); 602 - if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){ 597 + if( Th_Render(zScript)==JIM_RETURN && !g.thTrace && zName ){ 603 598 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName)); 604 599 return; 605 600 } 606 601 @ </form> 607 602 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); 608 603 style_footer(); 609 604 }
Changes to src/xfer.c.
789 789 ** from a server without authorization. 790 790 */ 791 791 static void server_private_xfer_not_authorized(void){ 792 792 @ error not\sauthorized\sto\ssync\sprivate\scontent 793 793 } 794 794 795 795 /* 796 -** Run the specified TH1 script, if any, and returns the return code or TH_OK 796 +** Run the specified TH1 script, if any, and returns the return code or JIM_OK 797 797 ** when there is no script. 798 798 */ 799 799 static int run_script(const char *zScript){ 800 800 if( !zScript ){ 801 - return TH_OK; /* No script, return success. */ 801 + return JIM_OK; /* No script, return success. */ 802 802 } 803 803 Th_FossilInit(); /* Make sure TH1 is ready. */ 804 - return Th_Eval(g.interp, 0, zScript, -1); 804 + return Jim_Eval(g.interp, zScript); 805 805 } 806 806 807 807 /* 808 808 ** Run the pre-transfer TH1 script, if any, and returns the return code. 809 809 */ 810 810 static int run_common_script(void){ 811 811 return run_script(db_get("xfer-common-script", 0)); ................................................................................ 870 870 g.xferPanic = 1; 871 871 872 872 db_begin_transaction(); 873 873 db_multi_exec( 874 874 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" 875 875 ); 876 876 manifest_crosslink_begin(); 877 - if( run_common_script()==TH_ERROR ){ 877 + if( run_common_script()!=JIM_OK ){ 878 878 cgi_reset_content(); 879 - @ error common\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0)) 879 + @ error common\sscript\sfailed:\s%F(Jim_String(Jim_GetResult(g.interp))) 880 880 nErr++; 881 881 } 882 882 while( blob_line(xfer.pIn, &xfer.line) ){ 883 883 if( blob_buffer(&xfer.line)[0]=='#' ) continue; 884 884 if( blob_size(&xfer.line)==0 ) continue; 885 885 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); 886 886 ................................................................................ 1188 1188 { 1189 1189 cgi_reset_content(); 1190 1190 @ error bad\scommand:\s%F(blob_str(&xfer.line)) 1191 1191 } 1192 1192 blobarray_reset(xfer.aToken, xfer.nToken); 1193 1193 } 1194 1194 if( isPush ){ 1195 - if( run_push_script()==TH_ERROR ){ 1195 + if( run_push_script()!=JIM_OK ){ 1196 1196 cgi_reset_content(); 1197 - @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0)) 1197 + @ error push\sscript\sfailed:\s%F(Jim_String(Jim_GetResult(g.interp))) 1198 1198 nErr++; 1199 1199 } 1200 1200 request_phantoms(&xfer, 500); 1201 1201 } 1202 1202 if( isClone && nGimme==0 ){ 1203 1203 /* The initial "clone" message from client to server contains no 1204 1204 ** "gimme" cards. On that initial message, send the client an "igot"
Changes to test/th1-tcl.test.
22 22 23 23 ############################################################################### 24 24 25 25 set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test. 26 26 27 27 ############################################################################### 28 28 29 -fossil test-th-render [file nativename [file join $dir th1-tcl1.txt]] 29 +fossil test-script-render [file nativename [file join $dir th1-tcl1.txt]] 30 30 31 31 test th1-tcl-1 {[regexp -- {^\d+ 32 32 \d+ 33 33 \d+ 34 34 via Tcl invoke 35 35 4 36 36 4 ................................................................................ 46 46 \d+ 47 47 one_word 48 48 three words now 49 49 $} [string map [list \r\n \n] $RESULT]]} 50 50 51 51 ############################################################################### 52 52 53 -fossil test-th-render [file nativename [file join $dir th1-tcl2.txt]] 53 +fossil test-script-render [file nativename [file join $dir th1-tcl2.txt]] 54 54 55 55 test th1-tcl-2 {[regexp -- {^\d+ 56 56 $} [string map [list \r\n \n] $RESULT]]} 57 57 58 58 ############################################################################### 59 59 60 -fossil test-th-render [file nativename [file join $dir th1-tcl3.txt]] 60 +fossil test-script-render [file nativename [file join $dir th1-tcl3.txt]] 61 61 62 62 test th1-tcl-3 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 63 63 invalid command name "bad_command"</p>}} 64 64 65 65 ############################################################################### 66 66 67 -fossil test-th-render [file nativename [file join $dir th1-tcl4.txt]] 67 +fossil test-script-render [file nativename [file join $dir th1-tcl4.txt]] 68 68 69 69 test th1-tcl-4 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 70 70 divide by zero</p>}} 71 71 72 72 ############################################################################### 73 73 74 -fossil test-th-render [file nativename [file join $dir th1-tcl5.txt]] 74 +fossil test-script-render [file nativename [file join $dir th1-tcl5.txt]] 75 75 76 76 test th1-tcl-5 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 77 77 Tcl command not found: bad_command</p>} || $RESULT eq {<hr><p\ 78 78 class="thmainError">ERROR: invalid command name "bad_command"</p>}} 79 79 80 80 ############################################################################### 81 81 82 -fossil test-th-render [file nativename [file join $dir th1-tcl6.txt]] 82 +fossil test-script-render [file nativename [file join $dir th1-tcl6.txt]] 83 83 84 84 test th1-tcl-6 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 85 85 no such command: bad_command</p>}} 86 86 87 87 ############################################################################### 88 88 89 -fossil test-th-render [file nativename [file join $dir th1-tcl7.txt]] 89 +fossil test-script-render [file nativename [file join $dir th1-tcl7.txt]] 90 90 91 91 test th1-tcl-7 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 92 92 syntax error in expression: "2**0"</p>}} 93 93 94 94 ############################################################################### 95 95 96 -fossil test-th-render [file nativename [file join $dir th1-tcl8.txt]] 96 +fossil test-script-render [file nativename [file join $dir th1-tcl8.txt]] 97 97 98 98 test th1-tcl-8 {$RESULT eq {<hr><p class="thmainError">ERROR:\ 99 99 Cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr><p\ 100 100 class="thmainError">ERROR: tailcall can only be called from a proc or\ 101 101 lambda</p>}} 102 102
Changes to test/th1-tcl1.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 set channel stdout; tclInvoke set channel $channel 8 8 proc doOut {msg} {puts $msg; puts \n} 9 9 doOut [tclEval clock seconds] 10 10 doOut [tclEval {set x [clock seconds]}] 11 11 tclEval {puts $channel "[clock seconds]"} 12 12 tclInvoke puts $channel "via Tcl invoke" 13 13 doOut [tclExpr 2+2] 14 14 doOut [tclExpr 2 + 2] 15 15 doOut [tclInvoke set x "two words"] 16 16 doOut [tclInvoke eval set y one_word] 17 17 doOut [tclInvoke eval {set z "three words now"}] 18 18 doOut [set x [tclEval {set x [clock seconds]}]] 19 - doOut [tclInvoke th1Eval {set y "two words"}] 20 - doOut [set z [tclInvoke th1Expr {2+2}]] 19 + doOut [tclInvoke bridgeEval {set y "two words"}] 20 + doOut [set z [tclInvoke bridgeExpr {2+2}]] 21 21 doOut $x 22 22 doOut $y 23 23 doOut $z 24 24 doOut [tclEval set x] 25 25 doOut [tclEval set y] 26 26 doOut [tclEval set z] 27 27 </th1>
Changes to test/th1-tcl2.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 # NOTE: This test requires that the SQLite package be available for the Tcl 8 8 # interpreter that is linked to the Fossil executable. 9 9 # 10 10 tclInvoke set repository_name [repository 1] 11 11 proc doOut {msg} {puts $msg; puts \n} 12 12 doOut [tclEval {
Changes to test/th1-tcl3.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 8 doOut [tclEval bad_command] 9 9 </th1>
Changes to test/th1-tcl4.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 8 doOut [tclExpr 2/0] 9 9 </th1>
Changes to test/th1-tcl5.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 8 doOut [tclInvoke bad_command] 9 9 </th1>
Changes to test/th1-tcl6.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 - doOut [tclEval th1Eval bad_command] 8 + doOut [tclEval bridgeEval bad_command] 9 9 </th1>
Changes to test/th1-tcl7.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 8 9 9 # 10 10 # BUGBUG: Attempting to divide by zero will crash TH1 with the error: 11 11 # "child killed: floating-point exception" 12 12 # 13 - # doOut [tclEval th1Expr 2/0] 13 + # doOut [tclEval bridgeExpr 2/0] 14 14 15 15 # 16 16 # NOTE: For now, just cause an expression syntax error. 17 17 # 18 - doOut [tclEval th1Expr 2**0] 18 + doOut [tclEval bridgeExpr 2**0] 19 19 </th1>
Changes to test/th1-tcl8.txt.
1 1 <th1> 2 2 # 3 - # This is a "TH1 fragment" used to test the Tcl integration features of TH1. 4 - # The corresponding test file executes this file using the test-th-render 5 - # Fossil command. 3 + # This is a "script fragment" used to test the Tcl integration features of 4 + # Fossil. The corresponding test file executes this file using the 5 + # test-script-render Fossil command. 6 6 # 7 7 proc doOut {msg} {puts $msg; puts \n} 8 8 9 9 if {[tclInvoke set tcl_version] >= 8.6} { 10 10 doOut [tclInvoke tailcall set x 1] 11 11 } else { 12 12 doOut "This test requires Tcl 8.6 or higher." 13 13 } 14 14 </th1>
Changes to win/Makefile.PellesCGMake.
143 143 mkindex.exe $(TRANSLATEDSRC) >$@ 144 144 145 145 # extracting version info from manifest 146 146 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION 147 147 version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@ 148 148 149 149 # generate the simplified headers 150 -headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h 151 - makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h 150 +headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/jim.h VERSION.h 151 + makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/jim.h VERSION.h 152 152 echo Done >$@ 153 153 154 154 # compile C sources with relevant options 155 155 156 156 $(TRANSLATEDOBJ): %_.obj: %_.c %.h 157 157 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 158 158 159 159 $(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h 160 160 $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@" 161 161 162 162 $(SQLITESHELLOBJ): %.obj: $(SRCDIR)%.c 163 163 $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@" 164 164 165 -$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h 165 +$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)jim.h 166 166 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 167 167 168 168 $(ZLIBOBJ): %.obj: $(ZLIBSRCDIR)%.c 169 169 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 170 170 171 171 # create the windows resource with icon and version info 172 172 $(RESOURCE): %.res: ../win/%.rc ../win/*.ico
Changes to win/Makefile.dmc.
670 670 $(OBJDIR)\zip$O : zip_.c zip.h 671 671 $(TCC) -o$@ -c zip_.c 672 672 673 673 zip_.c : $(SRCDIR)\zip.c 674 674 +translate$E $** > $@ 675 675 676 676 headers: makeheaders$E page_index.h VERSION.h 677 - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h 677 + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\jim.h VERSION.h 678 +$(SRCDIR)\sqlite3.h $(SRCDIR)\jim.h VERSION.h $(SRCDIR)\cson_amalgamation.h 678 679 @copy /Y nul: headers
Changes to win/Makefile.mingw.
516 516 setup: $(OBJDIR) $(APPNAME) 517 517 $(MAKENSIS) ./fossil.nsi 518 518 519 519 520 520 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 521 521 $(MKINDEX) $(TRANS_SRC) >$@ 522 522 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 523 - $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 523 + $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/jim.h $(OBJDIR)/VERSION.h 524 524 echo Done >$(OBJDIR)/headers 525 525 526 526 $(OBJDIR)/headers: Makefile 527 527 Makefile: 528 528 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate 529 529 $(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c 530 530
Changes to win/Makefile.mingw.mistachkin.
487 487 # the repository after running the tests. 488 488 test: $(OBJDIR) $(APPNAME) 489 489 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) 490 490 491 491 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) 492 492 $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h 493 493 494 -EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o $(OBJDIR)/cson_amalgamation.o 494 +EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/jimtcl.o $(OBJDIR)/cson_amalgamation.o 495 495 496 496 ifdef FOSSIL_ENABLE_TCL 497 497 EXTRAOBJ += $(OBJDIR)/th_tcl.o 498 498 endif 499 499 500 500 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o 501 501 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.o ................................................................................ 516 516 setup: $(OBJDIR) $(APPNAME) 517 517 $(MAKENSIS) ./fossil.nsi 518 518 519 519 520 520 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 521 521 $(MKINDEX) $(TRANS_SRC) >$@ 522 522 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 523 - $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 523 + $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/jim.h $(OBJDIR)/VERSION.h 524 524 echo Done >$(OBJDIR)/headers 525 525 526 526 $(OBJDIR)/headers: Makefile 527 527 Makefile: 528 528 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate 529 529 $(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c 530 530 ................................................................................ 1190 1190 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE 1191 1191 1192 1192 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h 1193 1193 1194 1194 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h 1195 1195 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o 1196 1196 1197 -$(OBJDIR)/th.o: $(SRCDIR)/th.c 1198 - $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o 1199 - 1200 -$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c 1201 - $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o 1197 +$(OBJDIR)/jimtcl.o: $(SRCDIR)/../autosetup/jimsh0.c 1198 + $(XTCC) -I$(SRCDIR) -DJIM_BOOTSTRAP_LIB_ONLY -c $(SRCDIR)/../autosetup/jimsh0.c -o $(OBJDIR)/jimtcl.o 1202 1199 1203 1200 ifdef FOSSIL_ENABLE_TCL 1204 1201 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c 1205 1202 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o 1206 1203 endif 1207 1204
Changes to win/Makefile.msc.
776 776 $(OX)\zip$O : zip_.c zip.h 777 777 $(TCC) /Fo$@ -c zip_.c 778 778 779 779 zip_.c : $(SRCDIR)\zip.c 780 780 translate$E $** > $@ 781 781 782 782 headers: makeheaders$E page_index.h VERSION.h 783 - makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h 783 + makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\jim.h VERSION.h $(SRCDIR)\cson_amalgamation.h 784 784 @copy /Y nul: headers