Fossil

Check-in [4c84ee3bac]
Login

Check-in [4c84ee3bac]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sqlite3-compat
Files: files | file ages | folders
SHA1: 4c84ee3bac3976ccd2916d8c211c90e9f3ad4e20
User & Date: jan.nijtmans 2014-10-05 22:41:00.000
Context
2014-10-05
23:11
Only use SQLITE_TESTCTRL_EXPLAIN_STMT/SQLITE_STMTSTATUS_VM_STEP when necessary/supported ... (check-in: 99d52b38fb user: jan.nijtmans tags: sqlite3-compat)
22:41
merge trunk ... (check-in: 4c84ee3bac user: jan.nijtmans tags: sqlite3-compat)
20:11
Update the built-in SQLite to the latest 3.8.7 beta from upstream. ... (check-in: c001fa0edf user: drh tags: trunk)
2014-06-05
08:12
Compatibility back to SQLite 3.7.17 (when configuring with --disable-internal-sqlite) ... (check-in: b6670e0545 user: jan.nijtmans tags: sqlite3-compat)
Changes
Unified Diff Ignore Whitespace Patch
Added .fossil-settings/encoding-glob.




>
>
1
2
compat/zlib/contrib/dotzlib/DotZLib/*.cs
win/fossil.rc
Added Dockerfile.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
###
#   Dockerfile for Fossil
###
FROM fedora:21

### Now install some additional parts we will need for the build
# RUN yum update -y && yum clean all
RUN yum install -y gcc make zlib-devel openssl-devel tcl-devel && yum clean all
RUN groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil

### If you want to build "release", change the next line accordingly.
ENV FOSSIL_INSTALL_VERSION trunk

RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
RUN cd fossil-src && ./configure --lineedit=0 --json --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make;
RUN cp fossil-src/fossil /usr/bin
RUN rm -rf fossil-src
RUN chmod a+rx /usr/bin/fossil
RUN mkdir -p /opt/fossil
RUN chown fossil:fossil /opt/fossil

### Build is done, remove modules no longer needed
RUN yum remove -y gcc make zlib-devel openssl-devel tcl-devel && yum clean all

USER fossil

ENV HOME /opt/fossil

RUN fossil new --empty -A admin /opt/fossil/repository.fossil
RUN fossil user password -R /opt/fossil/repository.fossil admin admin
RUN fossil cache init -R /opt/fossil/repository.fossil

EXPOSE 8080

CMD ["/usr/bin/fossil", "server", "/opt/fossil/repository.fossil"]
Changes to Makefile.classic.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39




40
41
42
43
44

45
46
47
48
49





50
51
52
53
54
55
56
BCC = gcc

#### The suffix to add to final executable file.  When cross-compiling
#    to windows, make this ".exe".  Otherwise leave it blank.
#
E =

#### C Compile and options for use in building executables that 
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
#TCC = gcc -O6
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
TCC = gcc -g -Os -Wall





# To add support for HTTPS
TCC += -DFOSSIL_ENABLE_SSL

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no

#    other dependencies.  We sometimes add the -static option here
#    so that we can build a static executable that will run in a
#    chroot jail.
#
LIB = -lz $(LDFLAGS)






# If using HTTPS:
LIB += -lcrypto -lssl

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#







|









>
>
>
>




|
>
|
|
|

|
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
BCC = gcc

#### The suffix to add to final executable file.  When cross-compiling
#    to windows, make this ".exe".  Otherwise leave it blank.
#
E =

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
#TCC = gcc -O6
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
TCC = gcc -g -Os -Wall

# To use the included miniz library
# FOSSIL_ENABLE_MINIZ = 1
# TCC += -DFOSSIL_ENABLE_MINIZ

# To add support for HTTPS
TCC += -DFOSSIL_ENABLE_SSL

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library unless the miniz
#    library in the source tree is being used.  There are no other
#    required dependencies.  We sometimes add the -static option
#    here so that we can build a static executable that will run in
#    a chroot jail.
#
ZLIB_LIB.0 = -lz
ZLIB_LIB.1 = 
ZLIB_LIB.  = $(ZLIB_LIB.0)

# If using zlib:
LIB = $(ZLIB_LIB.$(FOSSIL_ENABLE_MINIZ)) $(LDFLAGS)

# If using HTTPS:
LIB += -lcrypto -lssl

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
Changes to Makefile.in.
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
TCLSH = tclsh

LIB =	@LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC +=	@EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
INSTALLDIR = $(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@


include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile







|


>





35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
TCLSH = tclsh

LIB =	@LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC +=	@EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H
INSTALLDIR = $(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@
FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@

include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile
Changes to VERSION.
1
1.29
|
1
1.30
Changes to auto.def.
1
2
3
4
5
6
7

8


9
10
11
12
13
14
15

16
17
18
19
20
21
22
# System autoconfiguration. Try: ./configure --help

use cc cc-lib

options {
    with-openssl:path|auto|none
                         => {Look for openssl in the given path, or auto or none}

    with-zlib:path       => {Look for zlib in the given path}


    with-tcl:path        => {Enable Tcl integration, with Tcl in the specified path}
    with-tcl-stubs=0     => {Enable Tcl integration via stubs library mechanism}
    with-tcl-private-stubs=0
                         => {Enable Tcl integration via private stubs mechanism}
    internal-sqlite=1    => {Don't use the internal SQLite, use the system one}
    static=0             => {Link a static executable}
    lineedit=1           => {Disable line editing}

    fossil-debug=0       => {Build with fossil debugging enabled}
    json=0               => {Build with fossil JSON API enabled}
}

# sqlite wants these types if possible
cc-with {-includes {stdint.h inttypes.h}} {
    cc-check-types uint32_t uint16_t int16_t uint8_t






|
>

>
>







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# System autoconfiguration. Try: ./configure --help

use cc cc-lib

options {
    with-openssl:path|auto|none
                         => {Look for OpenSSL in the given path, or auto or none}
    with-miniz=0         => {Use miniz from the source tree}
    with-zlib:path       => {Look for zlib in the given path}
    with-th1-docs=0      => {Enable TH1 for embedded documentation pages}
    with-th1-hooks=0     => {Enable TH1 hooks for commands and web pages}
    with-tcl:path        => {Enable Tcl integration, with Tcl in the specified path}
    with-tcl-stubs=0     => {Enable Tcl integration via stubs library mechanism}
    with-tcl-private-stubs=0
                         => {Enable Tcl integration via private stubs mechanism}
    internal-sqlite=1    => {Don't use the internal SQLite, use the system one}
    static=0             => {Link a static executable}
    lineedit=1           => {Disable line editing}
    fusefs=1             => {Disable the Fuse Filesystem}
    fossil-debug=0       => {Build with fossil debugging enabled}
    json=0               => {Build with fossil JSON API enabled}
}

# sqlite wants these types if possible
cc-with {-includes {stdint.h inttypes.h}} {
    cc-check-types uint32_t uint16_t int16_t uint8_t
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82













83
84
85
86

87
88
89
90
91

92
93
94
95
96
97
98

if {[string match *-solaris* [get-define host]]} {
    define-append EXTRA_CFLAGS -D_XOPEN_SOURCE=500
}

if {[opt-bool fossil-debug]} {
    define-append EXTRA_CFLAGS -DFOSSIL_DEBUG

}

if {[opt-bool json]} {
    # Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON
    # is required in the CFLAGS because json*.c
    # have #ifdef guards around the whole file without
    # reading config.h first.
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
    define FOSSIL_ENABLE_JSON













}

#if {[opt-bool markdown]} {
#    # no-op.  Markdown is now enabled by default.

#}

if {[opt-bool static]} {
    # XXX: This will not work on all systems.
    define-append EXTRA_LDFLAGS -static

}

set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {
    set tclprivatestubs [opt-bool with-tcl-private-stubs]
    # Note parse-tclconfig-sh is in autosetup/local.tcl
    if {$tclpath eq "1"} {







>









>
>
>
>
>
>
>
>
>
>
>
>
>




>





>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

if {[string match *-solaris* [get-define host]]} {
    define-append EXTRA_CFLAGS -D_XOPEN_SOURCE=500
}

if {[opt-bool fossil-debug]} {
    define-append EXTRA_CFLAGS -DFOSSIL_DEBUG
    msg-result "Debugging support enabled"
}

if {[opt-bool json]} {
    # Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON
    # is required in the CFLAGS because json*.c
    # have #ifdef guards around the whole file without
    # reading config.h first.
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
    define FOSSIL_ENABLE_JSON
    msg-result "JSON support enabled"
}

if {[opt-bool with-th1-docs]} {
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_DOCS
    define FOSSIL_ENABLE_TH1_DOCS
    msg-result "TH1 embedded documentation support enabled"
}

if {[opt-bool with-th1-hooks]} {
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS
    define FOSSIL_ENABLE_TH1_HOOKS
    msg-result "TH1 hooks support enabled"
}

#if {[opt-bool markdown]} {
#    # no-op.  Markdown is now enabled by default.
#    msg-result "Markdown support enabled"
#}

if {[opt-bool static]} {
    # XXX: This will not work on all systems.
    define-append EXTRA_LDFLAGS -static
    msg-result "Trying to link statically"
}

set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {
    set tclprivatestubs [opt-bool with-tcl-private-stubs]
    # Note parse-tclconfig-sh is in autosetup/local.tcl
    if {$tclpath eq "1"} {
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
        define-append LIBS $libs
    }
    define-append EXTRA_CFLAGS $cflags
    define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
    define FOSSIL_ENABLE_TCL
}

# Helper for openssl checking
proc check-for-openssl {msg {cflags {}}} {
    msg-checking "Checking for $msg..."
    set rc 0
    msg-quiet cc-with [list -cflags $cflags -libs {-lssl -lcrypto}] {
        if {[cc-check-includes openssl/ssl.h] && [cc-check-functions SSL_new]} {
            incr rc
        }







|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
        define-append LIBS $libs
    }
    define-append EXTRA_CFLAGS $cflags
    define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
    define FOSSIL_ENABLE_TCL
}

# Helper for OpenSSL checking
proc check-for-openssl {msg {cflags {}}} {
    msg-checking "Checking for $msg..."
    set rc 0
    msg-quiet cc-with [list -cflags $cflags -libs {-lssl -lcrypto}] {
        if {[cc-check-includes openssl/ssl.h] && [cc-check-functions SSL_new]} {
            incr rc
        }
214
215
216
217
218
219
220




221
222
223
224
225
226

227
228
229

230
231
232
233
234
235

236
237
238

239
240
241
242
243
244
245
246
247
248
249
250
251
252


253
254
255
256

257
258
259
260
261
262
263
264









265
266
267
            }
        }
    } else {
        user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
    }
}





# Check for zlib, using the given location if specified
set zlibpath [opt-val with-zlib]
if {$zlibpath ne ""} {
    cc-with [list -cflags "-I$zlibpath -L$zlibpath"]
    define-append EXTRA_CFLAGS -I$zlibpath
    define-append EXTRA_LDFLAGS -L$zlibpath

}
if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} {
    user-error "zlib not found please install it or specify the location with --with-zlib"

}

if {[opt-bool lineedit]} {
    # Need readline-compatible line editing
    cc-with {-includes stdio.h} {
        if {[cc-check-includes readline/readline.h] && [cc-check-function-in-lib readline readline]} {

            msg-result "Using readline for line editing"
        } elseif {[cc-check-includes editline/readline.h] && [cc-check-function-in-lib readline edit]} {
            define-feature editline

            msg-result "Using editline for line editing"
        }
    }
}

# Network functions require libraries on some systems
cc-check-function-in-lib gethostbyname nsl
if {![cc-check-function-in-lib socket {socket network}]} {
    # Last resort, may be Windows
    if {[string match *mingw* [get-define host]]} {
        define-append LIBS -lwsock32
    }
}
cc-check-function-in-lib iconv iconv



# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
if {![cc-check-functions getloadavg]} {
  define FOSSIL_OMIT_LOAD_AVERAGE 1

}

# Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars
if {![cc-check-functions getpassphrase]} {
    # Haiku needs this
    cc-check-function-in-lib getpass bsd
}
cc-check-function-in-lib dlopen dl










make-template Makefile.in
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}







>
>
>
>
|
|
|
|
|
|
>
|
|
|
>






>



>














>
>




>








>
>
>
>
>
>
>
>
>



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
            }
        }
    } else {
        user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
    }
}

if {[opt-bool with-miniz]} {
  define FOSSIL_ENABLE_MINIZ 1
  msg-result "Using miniz for compression"
} else {
  # Check for zlib, using the given location if specified
  set zlibpath [opt-val with-zlib]
  if {$zlibpath ne ""} {
      cc-with [list -cflags "-I$zlibpath -L$zlibpath"]
      define-append EXTRA_CFLAGS -I$zlibpath
      define-append EXTRA_LDFLAGS -L$zlibpath
      msg-result "Using zlib from $zlibpath"
  }
  if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} {
      user-error "zlib not found please install it or specify the location with --with-zlib"
  }
}

if {[opt-bool lineedit]} {
    # Need readline-compatible line editing
    cc-with {-includes stdio.h} {
        if {[cc-check-includes readline/readline.h] && [cc-check-function-in-lib readline readline]} {
            define-append EXTRA_CFLAGS -DHAVE_READLINE
            msg-result "Using readline for line editing"
        } elseif {[cc-check-includes editline/readline.h] && [cc-check-function-in-lib readline edit]} {
            define-feature editline
            define-append EXTRA_CFLAGS -DHAVE_EDITLINE
            msg-result "Using editline for line editing"
        }
    }
}

# Network functions require libraries on some systems
cc-check-function-in-lib gethostbyname nsl
if {![cc-check-function-in-lib socket {socket network}]} {
    # Last resort, may be Windows
    if {[string match *mingw* [get-define host]]} {
        define-append LIBS -lwsock32
    }
}
cc-check-function-in-lib iconv iconv
cc-check-functions utime
cc-check-functions usleep

# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
if {![cc-check-functions getloadavg]} {
  define FOSSIL_OMIT_LOAD_AVERAGE 1
  msg-result "Load average support unavailable"
}

# Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars
if {![cc-check-functions getpassphrase]} {
    # Haiku needs this
    cc-check-function-in-lib getpass bsd
}
cc-check-function-in-lib dlopen dl

# Check for the FuseFS library
if {[opt-bool fusefs]} {
  if {[cc-check-function-in-lib fuse_mount fuse]} {
     define FOSSIL_HAVE_FUSEFS 1
     define-append LIBS -lfuse
     msg-result "FuseFS support enabled"
  }
}

make-template Makefile.in
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
Changes to autosetup/autosetup.
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
		}
	}
}

# Load module source in the global scope by executing the given command
proc automf_load {args} {
	if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
		autosetup-full-error [error-dump $msg $opts]
	}
}

# Initial settings
set autosetup(exe) $::argv0
set autosetup(istcl) 1
set autosetup(start) [clock millis]







|







923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
		}
	}
}

# Load module source in the global scope by executing the given command
proc automf_load {args} {
	if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
		autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
	}
}

# Initial settings
set autosetup(exe) $::argv0
set autosetup(istcl) 1
set autosetup(start) [clock millis]
1704
1705
1706
1707
1708
1709
1710


1711
1712
1713

1714
1715

1716
1717
1718













1719
1720
1721
1722
1723
1724
1725
		#puts "Skipping $info(file):$info(line)"
	}
	return $msg
}

# Given the return from [catch {...} msg opts], returns an appropriate
# error message. A nice one for Jim and a less-nice one for Tcl.


#
# This is designed for developer errors, e.g. in module code
#

proc error-dump {msg opts} {
	if {$::autosetup(istcl)} {

		return "Error: [dict get $opts -errorinfo]"
	} else {
		return "Error: $msg\n[stackdump $opts(-errorinfo)]"













	}
}
}

# ----- module text-formatting -----

set modsource(text-formatting) {







>
>

|

>
|

>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>







1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
		#puts "Skipping $info(file):$info(line)"
	}
	return $msg
}

# Given the return from [catch {...} msg opts], returns an appropriate
# error message. A nice one for Jim and a less-nice one for Tcl.
# If 'fulltrace' is set, a full stack trace is provided.
# Otherwise a simple message is provided.
#
# This is designed for developer errors, e.g. in module code or auto.def code
#
#
proc error-dump {msg opts fulltrace} {
	if {$::autosetup(istcl)} {
		if {$fulltrace} {
			return "Error: [dict get $opts -errorinfo]"
		} else {
			return "Error: $msg"
		}
	} else {
		lassign $opts(-errorinfo) p f l
		if {$f ne ""} {
			set result "$f:$l: Error: "
		}
		append result "$msg\n"
		if {$fulltrace} {
			append result [stackdump $opts(-errorinfo)]
		}

		# Remove the trailing newline
		string trim $result
	}
}
}

# ----- module text-formatting -----

set modsource(text-formatting) {
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
##################################################################
#
# Entry/Exit
#
if {$autosetup(debug)} {
	main $argv
}
if {[catch {main $argv} msg] == 1} {
	show-notices
	puts stderr [error-stacktrace $msg]
	if {!$autosetup(debug) && !$autosetup(istcl)} {
		puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
	}
	exit 1
}







|

|
|




1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
##################################################################
#
# Entry/Exit
#
if {$autosetup(debug)} {
	main $argv
}
if {[catch {main $argv} msg opts] == 1} {
	show-notices
	autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
	if {!$autosetup(debug)} {
		puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
	}
	exit 1
}
Changes to autosetup/cc-shared.tcl.
92
93
94
95
96
97
98









99
100
101
102
103
		# XXX: These haven't been tested
		define SHOBJ_CFLAGS "+O3 +z"
		define SHOBJ_LDFLAGS -b
		define SH_CFLAGS +z
		define SH_LINKFLAGS -Wl,+s
		define LD_LIBRARY_PATH SHLIB_PATH
	}









}

if {![is-defined SHOBJ_LDFLAGS_R]} {
	define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
}







>
>
>
>
>
>
>
>
>





92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		# XXX: These haven't been tested
		define SHOBJ_CFLAGS "+O3 +z"
		define SHOBJ_LDFLAGS -b
		define SH_CFLAGS +z
		define SH_LINKFLAGS -Wl,+s
		define LD_LIBRARY_PATH SHLIB_PATH
	}
	*-*-haiku {
		define SHOBJ_CFLAGS ""
		define SHOBJ_LDFLAGS -shared
		define SH_CFLAGS ""
		define SH_LDFLAGS -shared
		define SH_LINKFLAGS ""
		define SH_SOPREFIX ""
		define LD_LIBRARY_PATH LIBRARY_PATH
	}
}

if {![is-defined SHOBJ_LDFLAGS_R]} {
	define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
}
Changes to autosetup/cc.tcl.
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
			-declare {
				lappend new($name) $value
			}
			-libs {
				# Note that new libraries are added before previous libraries
				set new($name) [list {*}$value {*}$new($name)]
			}
			-link - -lang {
				set new($name) $value
			}
			-source - -sourcefile - -code {
				# XXX: These probably are only valid directly from cctest
				set new($name) $value
			}
			default {







|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
			-declare {
				lappend new($name) $value
			}
			-libs {
				# Note that new libraries are added before previous libraries
				set new($name) [list {*}$value {*}$new($name)]
			}
			-link - -lang - -nooutput {
				set new($name) $value
			}
			-source - -sourcefile - -code {
				# XXX: These probably are only valid directly from cctest
				set new($name) $value
			}
			default {
426
427
428
429
430
431
432

433
434
435
436
437
438
439
## -declare code       Code to declare before main()
## -link 1             Don't just compile, link too
## -lang c|c++         Use the C (default) or C++ compiler
## -libs liblist       List of libraries to link, e.g. {-ldl -lm}
## -code code          Code to compile in the body of main()
## -source code        Compile a complete program. Ignore -includes, -declare and -code
## -sourcefile file    Shorthand for -source [readfile [get-define srcdir]/$file]

#
# Unless -source or -sourcefile is specified, the C program looks like:
#
## #include <firstinclude>   /* same for remaining includes in the list */
##
## declare-code              /* any code in -declare, verbatim */
##







>







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
## -declare code       Code to declare before main()
## -link 1             Don't just compile, link too
## -lang c|c++         Use the C (default) or C++ compiler
## -libs liblist       List of libraries to link, e.g. {-ldl -lm}
## -code code          Code to compile in the body of main()
## -source code        Compile a complete program. Ignore -includes, -declare and -code
## -sourcefile file    Shorthand for -source [readfile [get-define srcdir]/$file]
## -nooutput 1         Treat any compiler output (e.g. a warning) as an error
#
# Unless -source or -sourcefile is specified, the C program looks like:
#
## #include <firstinclude>   /* same for remaining includes in the list */
##
## declare-code              /* any code in -declare, verbatim */
##
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
		}
		return $ok
	}

	writefile $src $lines\n

	set ok 1
	if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} {

		configlog "Failed: [join $cmdline]"
		configlog $result
		configlog "============"
		configlog "The failed code was:"
		configlog $lines
		configlog "============"
		set ok 0







|
>







520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
		}
		return $ok
	}

	writefile $src $lines\n

	set ok 1
	set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
	if {$err || ($opts(-nooutput) && [string length $result])} {
		configlog "Failed: [join $cmdline]"
		configlog $result
		configlog "============"
		configlog "The failed code was:"
		configlog $lines
		configlog "============"
		set ok 0
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
if {[get-define CC] eq ""} {
	user-error "Could not find a C compiler. Tried: [join $try ", "]"
}

define CCACHE [find-an-executable [get-env CCACHE ccache]]

# Initial cctest settings
cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}}
set autosetup(cc-include-deps) {}

msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
if {[get-define CXX] ne "false"} {
	msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]"
}
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"

# On Darwin, we prefer to use -gstabs to avoid creating .dSYM directories
# but some compilers don't support -gstabs, so test for it here.
switch -glob -- [get-define host] {
	*-*-darwin* {
		if {[cctest -cflags {-gstabs}]} {
			define cc-default-debug -gstabs
		}
	}
}

if {![cc-check-includes stdlib.h]} {
	user-error "Compiler does not work. See config.log"
}







|








|
|


|
|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
if {[get-define CC] eq ""} {
	user-error "Could not find a C compiler. Tried: [join $try ", "]"
}

define CCACHE [find-an-executable [get-env CCACHE ccache]]

# Initial cctest settings
cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
set autosetup(cc-include-deps) {}

msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
if {[get-define CXX] ne "false"} {
	msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]"
}
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"

# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
# but some compilers may not support it, so test here.
switch -glob -- [get-define host] {
	*-*-darwin* {
		if {[cctest -cflags {-g0}]} {
			define cc-default-debug -g0
		}
	}
}

if {![cc-check-includes stdlib.h]} {
	user-error "Compiler does not work. See config.log"
}
Changes to autosetup/config.guess.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#! /bin/sh
# Attempt to guess a canonical system name.
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
#   Free Software Foundation, Inc.

timestamp='2010-09-24'

# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.



# Originally written by Per Bothner.  Please send patches (context
# diff format) to <config-patches@gnu.org> and include a ChangeLog
# entry.
#
# This script attempts to guess a canonical system name similar to
# config.sub.  If it succeeds, it prints the system name on stdout, and
# exits with 0.  Otherwise, it exits with 1.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD




me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
Usage: $0 [OPTION]

Output the configuration name of the system \`$me' is run on.

Operation modes:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.guess ($timestamp)

Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."



<
<
|

|



|








|
<
<




|
|
>
|
|
<
<
<
<
<
<



>
>
>



















<
<
|







1
2


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


19
20
21
22
23
24
25
26
27






28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52


53
54
55
56
57
58
59
60
#! /bin/sh
# Attempt to guess a canonical system name.


#   Copyright 1992-2014 Free Software Foundation, Inc.

timestamp='2014-03-23'

# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.


#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program.  This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner.






#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches with a ChangeLog entry to config-patches@gnu.org.


me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
Usage: $0 [OPTION]

Output the configuration name of the system \`$me' is run on.

Operation modes:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.guess ($timestamp)

Originally written by Per Bothner.


Copyright 1992-2014 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
done

if test $# != 0; then
  echo "$me: too many arguments$help" >&2
  exit 1
fi

trap 'exit 1' HUP INT TERM

# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.

# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.

# Portable tmp directory creation inspired by the Autoconf team.

set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" HUP INT PIPE TERM ;
: ${TMPDIR=/tmp} ;
 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;







|













|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
done

if test $# != 0; then
  echo "$me: too many arguments$help" >&2
  exit 1
fi

trap 'exit 1' 1 2 15

# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.

# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.

# Portable tmp directory creation inspired by the Autoconf team.

set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
135
136
137
138
139
140
141





















142
143
144
145
146
147
148
149
150
151
152
153
154
155
	PATH=$PATH:/.attbin ; export PATH
fi

UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown






















# Note: order is significant - the case branches are not exclusive.

case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
    *:NetBSD:*:*)
	# NetBSD (nbsd) targets should (where applicable) match one or
	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
	# switched to ELF, *-*-netbsd* would select the old
	# object file format.  This provides both forward
	# compatibility and a consistent mechanism for selecting the
	# object file format.
	#
	# Note: NetBSD doesn't particularly care about the vendor







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
	PATH=$PATH:/.attbin ; export PATH
fi

UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown

case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
	# If the system lacks a compiler, then just pick glibc.
	# We could probably try harder.
	LIBC=gnu

	eval $set_cc_for_build
	cat <<-EOF > $dummy.c
	#include <features.h>
	#if defined(__UCLIBC__)
	LIBC=uclibc
	#elif defined(__dietlibc__)
	LIBC=dietlibc
	#else
	LIBC=gnu
	#endif
	EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
	;;
esac

# Note: order is significant - the case branches are not exclusive.

case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
    *:NetBSD:*:*)
	# NetBSD (nbsd) targets should (where applicable) match one or
	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
	# switched to ELF, *-*-netbsd* would select the old
	# object file format.  This provides both forward
	# compatibility and a consistent mechanism for selecting the
	# object file format.
	#
	# Note: NetBSD doesn't particularly care about the vendor
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204




205
206
207
208
209
210
211
		    # Return netbsd for either.  FIX?
		    os=netbsd
		else
		    os=netbsdelf
		fi
		;;
	    *)
	        os=netbsd
		;;
	esac
	# The OS release
	# Debian GNU/NetBSD machines have a different userland, and
	# thus, need a distinct triplet. However, they do not need
	# kernel version information, so it can be replaced with a
	# suitable tag, in the style of linux-gnu.
	case "${UNAME_VERSION}" in
	    Debian*)
		release='-gnu'
		;;
	    *)
		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
		;;
	esac
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
	# contains redundant information, the shorter form:
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
	echo "${machine}-${os}${release}"
	exit ;;




    *:OpenBSD:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
	exit ;;
    *:ekkoBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
	exit ;;







|




















>
>
>
>







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
		    # Return netbsd for either.  FIX?
		    os=netbsd
		else
		    os=netbsdelf
		fi
		;;
	    *)
		os=netbsd
		;;
	esac
	# The OS release
	# Debian GNU/NetBSD machines have a different userland, and
	# thus, need a distinct triplet. However, they do not need
	# kernel version information, so it can be replaced with a
	# suitable tag, in the style of linux-gnu.
	case "${UNAME_VERSION}" in
	    Debian*)
		release='-gnu'
		;;
	    *)
		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
		;;
	esac
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
	# contains redundant information, the shorter form:
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
	echo "${machine}-${os}${release}"
	exit ;;
    *:Bitrig:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
	exit ;;
    *:OpenBSD:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
	exit ;;
    *:ekkoBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
	exit ;;
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	exit ;;
    alpha:OSF1:*:*)
	case $UNAME_RELEASE in
	*4.0)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
		;;
	*5.*)
	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
		;;
	esac
	# According to Compaq, /usr/sbin/psrinfo has been available on
	# OSF/1 and Tru64 systems produced since 1995.  I hope that
	# covers most systems running today.  This code pipes the CPU
	# types through head -n 1, so we only detect the type of CPU 0.
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
	exit ;;
    alpha:OSF1:*:*)
	case $UNAME_RELEASE in
	*4.0)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
		;;
	*5.*)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
		;;
	esac
	# According to Compaq, /usr/sbin/psrinfo has been available on
	# OSF/1 and Tru64 systems produced since 1995.  I hope that
	# covers most systems running today.  This code pipes the CPU
	# types through head -n 1, so we only detect the type of CPU 0.
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
266
267
268
269
270
271
272

273


274
275
276
277
278
279
280
	esac
	# A Pn.n version is a patched version.
	# A Vn.n version is a released version.
	# A Tn.n version is a released field test version.
	# A Xn.n version is an unreleased experimental baselevel.
	# 1.2 uses "1.2" for uname -r.
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`

	exit ;;


    Alpha\ *:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# Should we change UNAME_MACHINE based on the output of uname instead
	# of the specific Alpha model?
	echo alpha-pc-interix
	exit ;;
    21064:Windows_NT:50:3)







>
|
>
>







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
	esac
	# A Pn.n version is a patched version.
	# A Vn.n version is a released version.
	# A Tn.n version is a released field test version.
	# A Xn.n version is an unreleased experimental baselevel.
	# 1.2 uses "1.2" for uname -r.
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
	exitcode=$?
	trap '' 0
	exit $exitcode ;;
    Alpha\ *:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# Should we change UNAME_MACHINE based on the output of uname instead
	# of the specific Alpha model?
	echo alpha-pc-interix
	exit ;;
    21064:Windows_NT:50:3)
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    *:OS/390:*:*)
	echo i370-ibm-openedition
	exit ;;
    *:z/VM:*:*)
	echo s390-ibm-zvmoe
	exit ;;
    *:OS400:*:*)
        echo powerpc-ibm-os400
	exit ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
	echo arm-acorn-riscix${UNAME_RELEASE}
	exit ;;
    arm:riscos:*:*|arm:RISCOS:*:*)
	echo arm-unknown-riscos
	exit ;;
    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
	echo hppa1.1-hitachi-hiuxmpp
	exit ;;
    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.







|




|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
    *:OS/390:*:*)
	echo i370-ibm-openedition
	exit ;;
    *:z/VM:*:*)
	echo s390-ibm-zvmoe
	exit ;;
    *:OS400:*:*)
	echo powerpc-ibm-os400
	exit ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
	echo arm-acorn-riscix${UNAME_RELEASE}
	exit ;;
    arm*:riscos:*:*|arm*:RISCOS:*:*)
	echo arm-unknown-riscos
	exit ;;
    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
	echo hppa1.1-hitachi-hiuxmpp
	exit ;;
    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
    # "atarist" or "atariste" at least should have a processor
    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
    # to the lowercase version "mint" (or "freemint").  Finally
    # the system name "TOS" denotes a system which is actually not
    # MiNT.  But MiNT is downward compatible to TOS, so this should
    # be no problem.
    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
        exit ;;
    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
        echo m68k-milan-mint${UNAME_RELEASE}
        exit ;;
    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
        echo m68k-hades-mint${UNAME_RELEASE}
        exit ;;
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
        echo m68k-unknown-mint${UNAME_RELEASE}
        exit ;;
    m68k:machten:*:*)
	echo m68k-apple-machten${UNAME_RELEASE}
	exit ;;
    powerpc:machten:*:*)
	echo powerpc-apple-machten${UNAME_RELEASE}
	exit ;;
    RISC*:Mach:*:*)







|



|

|


|
|

|
|

|
|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    # "atarist" or "atariste" at least should have a processor
    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
    # to the lowercase version "mint" (or "freemint").  Finally
    # the system name "TOS" denotes a system which is actually not
    # MiNT.  But MiNT is downward compatible to TOS, so this should
    # be no problem.
    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
	echo m68k-milan-mint${UNAME_RELEASE}
	exit ;;
    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
	echo m68k-hades-mint${UNAME_RELEASE}
	exit ;;
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
	echo m68k-unknown-mint${UNAME_RELEASE}
	exit ;;
    m68k:machten:*:*)
	echo m68k-apple-machten${UNAME_RELEASE}
	exit ;;
    powerpc:machten:*:*)
	echo powerpc-apple-machten${UNAME_RELEASE}
	exit ;;
    RISC*:Mach:*:*)
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    m88k:*:4*:R4*)
	echo m88k-motorola-sysv4
	exit ;;
    m88k:*:3*:R3*)
	echo m88k-motorola-sysv3
	exit ;;
    AViiON:dgux:*:*)
        # DG/UX returns AViiON for all architectures
        UNAME_PROCESSOR=`/usr/bin/uname -p`
	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
	then
	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
	       [ ${TARGET_BINARY_INTERFACE}x = x ]
	    then
		echo m88k-dg-dgux${UNAME_RELEASE}
	    else
		echo m88k-dg-dguxbcs${UNAME_RELEASE}
	    fi
	else
	    echo i586-dg-dgux${UNAME_RELEASE}
	fi
 	exit ;;
    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
	echo m88k-dolphin-sysv3
	exit ;;
    M88*:*:R3*:*)
	# Delta 88k system running SVR3
	echo m88k-motorola-sysv3
	exit ;;







|
|












|







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
    m88k:*:4*:R4*)
	echo m88k-motorola-sysv4
	exit ;;
    m88k:*:3*:R3*)
	echo m88k-motorola-sysv3
	exit ;;
    AViiON:dgux:*:*)
	# DG/UX returns AViiON for all architectures
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
	then
	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
	       [ ${TARGET_BINARY_INTERFACE}x = x ]
	    then
		echo m88k-dg-dgux${UNAME_RELEASE}
	    else
		echo m88k-dg-dguxbcs${UNAME_RELEASE}
	    fi
	else
	    echo i586-dg-dgux${UNAME_RELEASE}
	fi
	exit ;;
    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
	echo m88k-dolphin-sysv3
	exit ;;
    M88*:*:R3*:*)
	# Delta 88k system running SVR3
	echo m88k-motorola-sysv3
	exit ;;
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	case "${UNAME_MACHINE}" in
	    9000/31? )            HP_ARCH=m68000 ;;
	    9000/[34]?? )         HP_ARCH=m68k ;;
	    9000/[678][0-9][0-9])
		if [ -x /usr/bin/getconf ]; then
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
                    case "${sc_cpu_version}" in
                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
                      532)                      # CPU_PA_RISC2_0
                        case "${sc_kernel_bits}" in
                          32) HP_ARCH="hppa2.0n" ;;
                          64) HP_ARCH="hppa2.0w" ;;
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
                        esac ;;
                    esac
		fi
		if [ "${HP_ARCH}" = "" ]; then
		    eval $set_cc_for_build
		    sed 's/^              //' << EOF >$dummy.c

              #define _HPUX_SOURCE
              #include <stdlib.h>
              #include <unistd.h>

              int main ()
              {
              #if defined(_SC_KERNEL_BITS)
                  long bits = sysconf(_SC_KERNEL_BITS);
              #endif
                  long cpu  = sysconf (_SC_CPU_VERSION);

                  switch (cpu)
              	{
              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
              	case CPU_PA_RISC2_0:
              #if defined(_SC_KERNEL_BITS)
              	    switch (bits)
              		{
              		case 64: puts ("hppa2.0w"); break;
              		case 32: puts ("hppa2.0n"); break;
              		default: puts ("hppa2.0"); break;
              		} break;
              #else  /* !defined(_SC_KERNEL_BITS) */
              	    puts ("hppa2.0"); break;
              #endif
              	default: puts ("hppa1.0"); break;
              	}
                  exit (0);
              }
EOF
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
		    test -z "$HP_ARCH" && HP_ARCH=hppa
		fi ;;
	esac
	if [ ${HP_ARCH} = "hppa2.0w" ]
	then







|
|
|
|
|
|
|
|

|
|



|

|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	case "${UNAME_MACHINE}" in
	    9000/31? )            HP_ARCH=m68000 ;;
	    9000/[34]?? )         HP_ARCH=m68k ;;
	    9000/[678][0-9][0-9])
		if [ -x /usr/bin/getconf ]; then
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
		    case "${sc_cpu_version}" in
		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
		      532)                      # CPU_PA_RISC2_0
			case "${sc_kernel_bits}" in
			  32) HP_ARCH="hppa2.0n" ;;
			  64) HP_ARCH="hppa2.0w" ;;
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
			esac ;;
		    esac
		fi
		if [ "${HP_ARCH}" = "" ]; then
		    eval $set_cc_for_build
		    sed 's/^		//' << EOF >$dummy.c

		#define _HPUX_SOURCE
		#include <stdlib.h>
		#include <unistd.h>

		int main ()
		{
		#if defined(_SC_KERNEL_BITS)
		    long bits = sysconf(_SC_KERNEL_BITS);
		#endif
		    long cpu  = sysconf (_SC_CPU_VERSION);

		    switch (cpu)
			{
			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
			case CPU_PA_RISC2_0:
		#if defined(_SC_KERNEL_BITS)
			    switch (bits)
				{
				case 64: puts ("hppa2.0w"); break;
				case 32: puts ("hppa2.0n"); break;
				default: puts ("hppa2.0"); break;
				} break;
		#else  /* !defined(_SC_KERNEL_BITS) */
			    puts ("hppa2.0"); break;
		#endif
			default: puts ("hppa1.0"); break;
			}
		    exit (0);
		}
EOF
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
		    test -z "$HP_ARCH" && HP_ARCH=hppa
		fi ;;
	esac
	if [ ${HP_ARCH} = "hppa2.0w" ]
	then
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
	fi
	exit ;;
    parisc*:Lites*:*:*)
	echo hppa1.1-hp-lites
	exit ;;
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
	echo c1-convex-bsd
        exit ;;
    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
        exit ;;
    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
	echo c34-convex-bsd
        exit ;;
    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
	echo c38-convex-bsd
        exit ;;
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
	echo c4-convex-bsd
        exit ;;
    CRAY*Y-MP:*:*:*)
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*[A-Z]90:*:*:*)
	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \







|





|


|


|


|







747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
	fi
	exit ;;
    parisc*:Lites*:*:*)
	echo hppa1.1-hp-lites
	exit ;;
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
	echo c1-convex-bsd
	exit ;;
    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
	exit ;;
    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
	echo c34-convex-bsd
	exit ;;
    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
	echo c38-convex-bsd
	exit ;;
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
	echo c4-convex-bsd
	exit ;;
    CRAY*Y-MP:*:*:*)
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*[A-Z]90:*:*:*)
	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803



804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    *:UNICOS/mp:*:*)
	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
        exit ;;
    5000:UNIX_System_V:4.*:*)
        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
	exit ;;
    sparc*:BSD/OS:*:*)
	echo sparc-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:BSD/OS:*:*)
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:FreeBSD:*:*)

	case ${UNAME_MACHINE} in
	    pc98)
		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	    amd64)
		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	    *)
		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	esac
	exit ;;
    i*:CYGWIN*:*)
	echo ${UNAME_MACHINE}-pc-cygwin
	exit ;;



    *:MINGW*:*)
	echo ${UNAME_MACHINE}-pc-mingw32
	exit ;;
    i*:MSYS*:*) 
	echo ${UNAME_MACHINE}-pc-msys 
	exit ;; 
    i*:windows32*:*)
    	# uname -m includes "-pc" on this system.
    	echo ${UNAME_MACHINE}-mingw32
	exit ;;
    i*:PW*:*)
	echo ${UNAME_MACHINE}-pc-pw32
	exit ;;
    *:Interix*:*)
    	case ${UNAME_MACHINE} in
	    x86)
		echo i586-pc-interix${UNAME_RELEASE}
		exit ;;
	    authenticamd | genuineintel | EM64T)
		echo x86_64-unknown-interix${UNAME_RELEASE}
		exit ;;
	    IA64)







|
|
|
|

|
|
|











>
|
<
<



|





>
>
>



|
|
|

|
|





|







786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813


814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    *:UNICOS/mp:*:*)
	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    5000:UNIX_System_V:4.*:*)
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
	exit ;;
    sparc*:BSD/OS:*:*)
	echo sparc-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:BSD/OS:*:*)
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:FreeBSD:*:*)
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	case ${UNAME_PROCESSOR} in


	    amd64)
		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	    *)
		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	esac
	exit ;;
    i*:CYGWIN*:*)
	echo ${UNAME_MACHINE}-pc-cygwin
	exit ;;
    *:MINGW64*:*)
	echo ${UNAME_MACHINE}-pc-mingw64
	exit ;;
    *:MINGW*:*)
	echo ${UNAME_MACHINE}-pc-mingw32
	exit ;;
    *:MSYS*:*)
	echo ${UNAME_MACHINE}-pc-msys
	exit ;;
    i*:windows32*:*)
	# uname -m includes "-pc" on this system.
	echo ${UNAME_MACHINE}-mingw32
	exit ;;
    i*:PW*:*)
	echo ${UNAME_MACHINE}-pc-pw32
	exit ;;
    *:Interix*:*)
	case ${UNAME_MACHINE} in
	    x86)
		echo i586-pc-interix${UNAME_RELEASE}
		exit ;;
	    authenticamd | genuineintel | EM64T)
		echo x86_64-unknown-interix${UNAME_RELEASE}
		exit ;;
	    IA64)
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863







864
865
866
867
868
869
870
871
872
873
874
875
876



877
878
879
880
881
882
883
884



885



886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938



939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961






962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
	echo powerpcle-unknown-cygwin
	exit ;;
    prep*:SunOS:5.*:*)
	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    *:GNU:*:*)
	# the GNU system
	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
	exit ;;
    *:GNU/*:*:*)
	# other systems with GNU libc and userland
	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
	exit ;;
    i*86:Minix:*:*)
	echo ${UNAME_MACHINE}-pc-minix
	exit ;;







    alpha:Linux:*:*)
	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
	  EV5)   UNAME_MACHINE=alphaev5 ;;
	  EV56)  UNAME_MACHINE=alphaev56 ;;
	  PCA56) UNAME_MACHINE=alphapca56 ;;
	  PCA57) UNAME_MACHINE=alphapca56 ;;
	  EV6)   UNAME_MACHINE=alphaev6 ;;
	  EV67)  UNAME_MACHINE=alphaev67 ;;
	  EV68*) UNAME_MACHINE=alphaev68 ;;
        esac
	objdump --private-headers /bin/sh | grep -q ld.so.1
	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}



	exit ;;
    arm*:Linux:*:*)
	eval $set_cc_for_build
	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_EABI__
	then
	    echo ${UNAME_MACHINE}-unknown-linux-gnu
	else



	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi



	fi
	exit ;;
    avr32*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    cris:Linux:*:*)
	echo cris-axis-linux-gnu
	exit ;;
    crisv32:Linux:*:*)
	echo crisv32-axis-linux-gnu
	exit ;;
    frv:Linux:*:*)
    	echo frv-unknown-linux-gnu
	exit ;;
    i*86:Linux:*:*)
	LIBC=gnu
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#ifdef __dietlibc__
	LIBC=dietlibc
	#endif
EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
	exit ;;
    ia64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    m32r*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    m68*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    mips:Linux:*:* | mips64:Linux:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#undef CPU
	#undef ${UNAME_MACHINE}
	#undef ${UNAME_MACHINE}el
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	CPU=${UNAME_MACHINE}el
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	CPU=${UNAME_MACHINE}
	#else
	CPU=
	#endif
	#endif
EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
	;;



    or32:Linux:*:*)
	echo or32-unknown-linux-gnu
	exit ;;
    padre:Linux:*:*)
	echo sparc-unknown-linux-gnu
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
	echo hppa64-unknown-linux-gnu
	exit ;;
    parisc:Linux:*:* | hppa:Linux:*:*)
	# Look for CPU level
	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
	  *)    echo hppa-unknown-linux-gnu ;;
	esac
	exit ;;
    ppc64:Linux:*:*)
	echo powerpc64-unknown-linux-gnu
	exit ;;
    ppc:Linux:*:*)
	echo powerpc-unknown-linux-gnu
	exit ;;






    s390:Linux:*:* | s390x:Linux:*:*)
	echo ${UNAME_MACHINE}-ibm-linux
	exit ;;
    sh64*:Linux:*:*)
    	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    sh*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    sparc:Linux:*:* | sparc64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    tile*:Linux:*:*)
	echo ${UNAME_MACHINE}-tilera-linux-gnu
	exit ;;
    vax:Linux:*:*)
	echo ${UNAME_MACHINE}-dec-linux-gnu
	exit ;;
    x86_64:Linux:*:*)
	echo x86_64-unknown-linux-gnu
	exit ;;
    xtensa*:Linux:*:*)
    	echo ${UNAME_MACHINE}-unknown-linux-gnu
	exit ;;
    i*86:DYNIX/ptx:4*:*)
	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
	# earlier versions are messed up and put the nodename in both
	# sysname and nodename.
	echo i386-sequent-sysv4
	exit ;;
    i*86:UNIX_SV:4.2MP:2.*)
        # Unixware is an offshoot of SVR4, but it has its own version
        # number series starting with 2...
        # I am not positive that other SVR4 systems won't match this,
	# I just have to hope.  -- rms.
        # Use sysv4.2uw... so that sysv4* matches it.
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
	exit ;;
    i*86:OS/2:*:*)
	# If we were able to find `uname', then EMX Unix compatibility
	# is probably installed.
	echo ${UNAME_MACHINE}-pc-os2-emx
	exit ;;







|



|




>
>
>
>
>
>
>









|

|
|
>
>
>






|

>
>
>
|
>
>
>



|


|


|


|

|
|
<
<
<
|
|
<
<
|


|


|


|


















|

>
>
>
|
|


|


|




|
|
|



|


|

>
>
>
>
>
>

|


|


|


|


|


|


|


|








|
|
|

|







870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939



940
941


942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
	echo powerpcle-unknown-cygwin
	exit ;;
    prep*:SunOS:5.*:*)
	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    *:GNU:*:*)
	# the GNU system
	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
	exit ;;
    *:GNU/*:*:*)
	# other systems with GNU libc and userland
	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
	exit ;;
    i*86:Minix:*:*)
	echo ${UNAME_MACHINE}-pc-minix
	exit ;;
    aarch64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    aarch64_be:Linux:*:*)
	UNAME_MACHINE=aarch64_be
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    alpha:Linux:*:*)
	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
	  EV5)   UNAME_MACHINE=alphaev5 ;;
	  EV56)  UNAME_MACHINE=alphaev56 ;;
	  PCA56) UNAME_MACHINE=alphapca56 ;;
	  PCA57) UNAME_MACHINE=alphapca56 ;;
	  EV6)   UNAME_MACHINE=alphaev6 ;;
	  EV67)  UNAME_MACHINE=alphaev67 ;;
	  EV68*) UNAME_MACHINE=alphaev68 ;;
	esac
	objdump --private-headers /bin/sh | grep -q ld.so.1
	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    arc:Linux:*:* | arceb:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    arm*:Linux:*:*)
	eval $set_cc_for_build
	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_EABI__
	then
	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	else
	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
		| grep -q __ARM_PCS_VFP
	    then
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
	    else
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
	    fi
	fi
	exit ;;
    avr32*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    cris:Linux:*:*)
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
	exit ;;
    crisv32:Linux:*:*)
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
	exit ;;
    frv:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    hexagon:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}



	exit ;;
    i*86:Linux:*:*)


	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
	exit ;;
    ia64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    m32r*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    m68*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    mips:Linux:*:* | mips64:Linux:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#undef CPU
	#undef ${UNAME_MACHINE}
	#undef ${UNAME_MACHINE}el
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	CPU=${UNAME_MACHINE}el
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	CPU=${UNAME_MACHINE}
	#else
	CPU=
	#endif
	#endif
EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
	;;
    openrisc*:Linux:*:*)
	echo or1k-unknown-linux-${LIBC}
	exit ;;
    or32:Linux:*:* | or1k*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    padre:Linux:*:*)
	echo sparc-unknown-linux-${LIBC}
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
	echo hppa64-unknown-linux-${LIBC}
	exit ;;
    parisc:Linux:*:* | hppa:Linux:*:*)
	# Look for CPU level
	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
	  *)    echo hppa-unknown-linux-${LIBC} ;;
	esac
	exit ;;
    ppc64:Linux:*:*)
	echo powerpc64-unknown-linux-${LIBC}
	exit ;;
    ppc:Linux:*:*)
	echo powerpc-unknown-linux-${LIBC}
	exit ;;
    ppc64le:Linux:*:*)
	echo powerpc64le-unknown-linux-${LIBC}
	exit ;;
    ppcle:Linux:*:*)
	echo powerpcle-unknown-linux-${LIBC}
	exit ;;
    s390:Linux:*:* | s390x:Linux:*:*)
	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
	exit ;;
    sh64*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    sh*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    sparc:Linux:*:* | sparc64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    tile*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    vax:Linux:*:*)
	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
	exit ;;
    x86_64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    xtensa*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    i*86:DYNIX/ptx:4*:*)
	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
	# earlier versions are messed up and put the nodename in both
	# sysname and nodename.
	echo i386-sequent-sysv4
	exit ;;
    i*86:UNIX_SV:4.2MP:2.*)
	# Unixware is an offshoot of SVR4, but it has its own version
	# number series starting with 2...
	# I am not positive that other SVR4 systems won't match this,
	# I just have to hope.  -- rms.
	# Use sysv4.2uw... so that sysv4* matches it.
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
	exit ;;
    i*86:OS/2:*:*)
	# If we were able to find `uname', then EMX Unix compatibility
	# is probably installed.
	echo ${UNAME_MACHINE}-pc-os2-emx
	exit ;;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
	else
		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
	fi
	exit ;;
    i*86:*:5:[678]*)
    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
	case `/bin/uname -X | grep "^Machine"` in
	    *486*)	     UNAME_MACHINE=i486 ;;
	    *Pentium)	     UNAME_MACHINE=i586 ;;
	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
	esac
	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
	exit ;;







|







1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
	else
		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
	fi
	exit ;;
    i*86:*:5:[678]*)
	# UnixWare 7.x, OpenUNIX and OpenServer 6.
	case `/bin/uname -X | grep "^Machine"` in
	    *486*)	     UNAME_MACHINE=i486 ;;
	    *Pentium)	     UNAME_MACHINE=i586 ;;
	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
	esac
	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
	exit ;;
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
	else
		echo ${UNAME_MACHINE}-pc-sysv32
	fi
	exit ;;
    pc:*:*:*)
	# Left here for compatibility:
        # uname -m prints for DJGPP always 'pc', but it prints nothing about
        # the processor, so we play safe by assuming i586.
	# Note: whatever this is, it MUST be the same as what config.sub
	# prints for the "djgpp" host, or else GDB configury will decide that
	# this is a cross-build.
	echo i586-pc-msdosdjgpp
        exit ;;
    Intel:Mach:3*:*)
	echo i386-pc-mach3
	exit ;;
    paragon:*:*:*)
	echo i860-intel-osf1
	exit ;;
    i860:*:4.*:*) # i860-SVR4







|
|




|







1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
	else
		echo ${UNAME_MACHINE}-pc-sysv32
	fi
	exit ;;
    pc:*:*:*)
	# Left here for compatibility:
	# uname -m prints for DJGPP always 'pc', but it prints nothing about
	# the processor, so we play safe by assuming i586.
	# Note: whatever this is, it MUST be the same as what config.sub
	# prints for the "djgpp" host, or else GDB configury will decide that
	# this is a cross-build.
	echo i586-pc-msdosdjgpp
	exit ;;
    Intel:Mach:3*:*)
	echo i386-pc-mach3
	exit ;;
    paragon:*:*:*)
	echo i860-intel-osf1
	exit ;;
    i860:*:4.*:*) # i860-SVR4
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
	test -r /etc/.relid \
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
          && { echo i486-ncr-sysv4; exit; } ;;
    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
	OS_REL='.3'
	test -r /etc/.relid \
	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \







|
|







1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
	test -r /etc/.relid \
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4; exit; } ;;
    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
	OS_REL='.3'
	test -r /etc/.relid \
	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit ;;
    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
                      # says <Richard.M.Bartel@ccMail.Census.GOV>
        echo i586-unisys-sysv4
        exit ;;
    *:UNIX_System_V:4*:FTX*)
	# From Gerald Hewes <hewes@openmarket.com>.
	# How about differentiating between stratus architectures? -djm
	echo hppa1.1-stratus-sysv4
	exit ;;
    *:*:*:FTX*)
	# From seanf@swdc.stratus.com.







|
|
|
|







1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit ;;
    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
			# says <Richard.M.Bartel@ccMail.Census.GOV>
	echo i586-unisys-sysv4
	exit ;;
    *:UNIX_System_V:4*:FTX*)
	# From Gerald Hewes <hewes@openmarket.com>.
	# How about differentiating between stratus architectures? -djm
	echo hppa1.1-stratus-sysv4
	exit ;;
    *:*:*:FTX*)
	# From seanf@swdc.stratus.com.
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187



1188
1189
1190
1191
1192
1193
1194
	echo m68k-apple-aux${UNAME_RELEASE}
	exit ;;
    news*:NEWS-OS:6*:*)
	echo mips-sony-newsos6
	exit ;;
    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
	if [ -d /usr/nec ]; then
	        echo mips-nec-sysv${UNAME_RELEASE}
	else
	        echo mips-unknown-sysv${UNAME_RELEASE}
	fi
        exit ;;
    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
	echo powerpc-be-beos
	exit ;;
    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
	echo powerpc-apple-beos
	exit ;;
    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
	echo i586-pc-beos
	exit ;;
    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
	echo i586-pc-haiku
	exit ;;



    SX-4:SUPER-UX:*:*)
	echo sx4-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-5:SUPER-UX:*:*)
	echo sx5-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-6:SUPER-UX:*:*)







|

|

|












>
>
>







1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
	echo m68k-apple-aux${UNAME_RELEASE}
	exit ;;
    news*:NEWS-OS:6*:*)
	echo mips-sony-newsos6
	exit ;;
    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
	if [ -d /usr/nec ]; then
		echo mips-nec-sysv${UNAME_RELEASE}
	else
		echo mips-unknown-sysv${UNAME_RELEASE}
	fi
	exit ;;
    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
	echo powerpc-be-beos
	exit ;;
    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
	echo powerpc-apple-beos
	exit ;;
    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
	echo i586-pc-beos
	exit ;;
    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
	echo i586-pc-haiku
	exit ;;
    x86_64:Haiku:*:*)
	echo x86_64-unknown-haiku
	exit ;;
    SX-4:SUPER-UX:*:*)
	echo sx4-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-5:SUPER-UX:*:*)
	echo sx5-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-6:SUPER-UX:*:*)
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216




1217
1218
1219
1220
1221
1222



1223
1224







1225
1226

1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Rhapsody:*:*)
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Darwin:*:*)
	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
	case $UNAME_PROCESSOR in
	    i386)
		eval $set_cc_for_build




		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
		      grep IS_64BIT_ARCH >/dev/null
		  then
		      UNAME_PROCESSOR="x86_64"



		  fi
		fi ;;







	    unknown) UNAME_PROCESSOR=powerpc ;;
	esac

	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
	exit ;;
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
	UNAME_PROCESSOR=`uname -p`
	if test "$UNAME_PROCESSOR" = "x86"; then
		UNAME_PROCESSOR=i386
		UNAME_MACHINE=pc
	fi
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
	exit ;;
    *:QNX:*:4*)
	echo i386-pc-qnx
	exit ;;
    NEO-?:NONSTOP_KERNEL:*:*)
	echo neo-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSE-?:NONSTOP_KERNEL:*:*)
	echo nse-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSR-?:NONSTOP_KERNEL:*:*)
	echo nsr-tandem-nsk${UNAME_RELEASE}
	exit ;;
    *:NonStop-UX:*:*)
	echo mips-compaq-nonstopux







<
<
|
>
>
>
>
|
|
|
|
|
|
>
>
>
|
|
>
>
>
>
>
>
>
|
<
>
















|







1252
1253
1254
1255
1256
1257
1258


1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Rhapsody:*:*)
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Darwin:*:*)
	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown


	eval $set_cc_for_build
	if test "$UNAME_PROCESSOR" = unknown ; then
	    UNAME_PROCESSOR=powerpc
	fi
	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
		    grep IS_64BIT_ARCH >/dev/null
		then
		    case $UNAME_PROCESSOR in
			i386) UNAME_PROCESSOR=x86_64 ;;
			powerpc) UNAME_PROCESSOR=powerpc64 ;;
		    esac
		fi
	    fi
	elif test "$UNAME_PROCESSOR" = i386 ; then
	    # Avoid executing cc on OS X 10.9, as it ships with a stub
	    # that puts up a graphical alert prompting to install
	    # developer tools.  Any system running Mac OS X 10.7 or
	    # later (Darwin 11 and later) is required to have a 64-bit
	    # processor. This is not true of the ARM version of Darwin
	    # that Apple uses in portable devices.
	    UNAME_PROCESSOR=x86_64

	fi
	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
	exit ;;
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
	UNAME_PROCESSOR=`uname -p`
	if test "$UNAME_PROCESSOR" = "x86"; then
		UNAME_PROCESSOR=i386
		UNAME_MACHINE=pc
	fi
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
	exit ;;
    *:QNX:*:4*)
	echo i386-pc-qnx
	exit ;;
    NEO-?:NONSTOP_KERNEL:*:*)
	echo neo-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSE-*:NONSTOP_KERNEL:*:*)
	echo nse-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSR-?:NONSTOP_KERNEL:*:*)
	echo nsr-tandem-nsk${UNAME_RELEASE}
	exit ;;
    *:NonStop-UX:*:*)
	echo mips-compaq-nonstopux
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
    *:TOPS-20:*:*)
	echo pdp10-unknown-tops20
	exit ;;
    *:ITS:*:*)
	echo pdp10-unknown-its
	exit ;;
    SEI:*:*:SEIUX)
        echo mips-sei-seiux${UNAME_RELEASE}
	exit ;;
    *:DragonFly:*:*)
	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
	exit ;;
    *:*VMS:*:*)
    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
	case "${UNAME_MACHINE}" in
	    A*) echo alpha-dec-vms ; exit ;;
	    I*) echo ia64-dec-vms ; exit ;;
	    V*) echo vax-dec-vms ; exit ;;
	esac ;;
    *:XENIX:*:SysV)
	echo i386-pc-xenix
	exit ;;
    i*86:skyos:*:*)
	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
	exit ;;
    i*86:rdos:*:*)
	echo ${UNAME_MACHINE}-pc-rdos
	exit ;;
    i*86:AROS:*:*)
	echo ${UNAME_MACHINE}-pc-aros
	exit ;;
esac

#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2

eval $set_cc_for_build
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
     I don't know....  */
  printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
  printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
          "4"
#else
	  ""
#endif
         ); exit (0);
#endif
#endif

#if defined (__arm) && defined (__acorn) && defined (__unix)
  printf ("arm-acorn-riscix\n"); exit (0);
#endif

#if defined (hp300) && !defined (hpux)
  printf ("m68k-hp-bsd\n"); exit (0);
#endif

#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
  int version;
  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
  if (version < 4)
    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
  else
    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
  exit (0);
#endif

#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
  printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
  printf ("ns32k-encore-mach\n"); exit (0);
#else
  printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif

#if defined (__386BSD__)
  printf ("i386-pc-bsd\n"); exit (0);
#endif

#if defined (sequent)
#if defined (i386)
  printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
  printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif

#if defined (_SEQUENT_)
    struct utsname un;

    uname(&un);

    if (strncmp(un.version, "V2", 2) == 0) {
	printf ("i386-sequent-ptx2\n"); exit (0);
    }
    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
	printf ("i386-sequent-ptx1\n"); exit (0);
    }
    printf ("i386-sequent-ptx\n"); exit (0);

#endif

#if defined (vax)
# if !defined (ultrix)
#  include <sys/param.h>
#  if defined (BSD)
#   if BSD == 43
      printf ("vax-dec-bsd4.3\n"); exit (0);
#   else
#    if BSD == 199006
      printf ("vax-dec-bsd4.3reno\n"); exit (0);
#    else
      printf ("vax-dec-bsd\n"); exit (0);
#    endif
#   endif
#  else
    printf ("vax-dec-bsd\n"); exit (0);
#  endif
# else
    printf ("vax-dec-ultrix\n"); exit (0);
# endif
#endif

#if defined (alliant) && defined (i860)
  printf ("i860-alliant-bsd\n"); exit (0);
#endif

  exit (1);
}
EOF

$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
	{ echo "$SYSTEM_NAME"; exit; }

# Apollos put the system type in the environment.

test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }

# Convex versions that predate uname can use getsysinfo(1)

if [ -x /usr/convex/getsysinfo ]
then
    case `getsysinfo -f cpu_type` in
    c1*)
	echo c1-convex-bsd
	exit ;;
    c2*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
	exit ;;
    c34*)
	echo c34-convex-bsd
	exit ;;
    c38*)
	echo c38-convex-bsd
	exit ;;
    c4*)
	echo c4-convex-bsd
	exit ;;
    esac
fi

cat >&2 <<EOF
$0: unable to guess system type

This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from







|





|

















<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<







1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368

1369


1370

































































































































1371















1372

1373
1374
1375
1376
1377
1378
1379
    *:TOPS-20:*:*)
	echo pdp10-unknown-tops20
	exit ;;
    *:ITS:*:*)
	echo pdp10-unknown-its
	exit ;;
    SEI:*:*:SEIUX)
	echo mips-sei-seiux${UNAME_RELEASE}
	exit ;;
    *:DragonFly:*:*)
	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
	exit ;;
    *:*VMS:*:*)
	UNAME_MACHINE=`(uname -p) 2>/dev/null`
	case "${UNAME_MACHINE}" in
	    A*) echo alpha-dec-vms ; exit ;;
	    I*) echo ia64-dec-vms ; exit ;;
	    V*) echo vax-dec-vms ; exit ;;
	esac ;;
    *:XENIX:*:SysV)
	echo i386-pc-xenix
	exit ;;
    i*86:skyos:*:*)
	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
	exit ;;
    i*86:rdos:*:*)
	echo ${UNAME_MACHINE}-pc-rdos
	exit ;;
    i*86:AROS:*:*)
	echo ${UNAME_MACHINE}-pc-aros
	exit ;;

    x86_64:VMkernel:*:*)


	echo ${UNAME_MACHINE}-unknown-esx

































































































































	exit ;;















esac


cat >&2 <<EOF
$0: unable to guess system type

This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
Changes to autosetup/config.sub.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39
40
41
42
#! /bin/sh
# Configuration validation subroutine script.
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
#   Free Software Foundation, Inc.

timestamp='2010-09-11'

# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine.  It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.




# Please send patches to <config-patches@gnu.org>.  Submit a context
# diff and a properly formatted GNU ChangeLog entry.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.

# You can get the latest version of this script from:


<
<
|

|

<
<
<
<
|
|
|


|
|
|
|


|
<
<




|
>
>


|
<







1
2


3
4
5
6




7
8
9
10
11
12
13
14
15
16
17
18


19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
#! /bin/sh
# Configuration validation subroutine script.


#   Copyright 1992-2014 Free Software Foundation, Inc.

timestamp='2014-05-01'





# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.


#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program.  This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").


# Please send patches with a ChangeLog entry to config-patches@gnu.org.

#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.

# You can get the latest version of this script from:
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.sub ($timestamp)

Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."








<
<
|







64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.sub ($timestamp)



Copyright 1992-2014 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."

121
122
123
124
125
126
127
128
129
130
131
132
133
134




135
136
137
138
139
140
141
esac

# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
  knetbsd*-gnu* | netbsd*-gnu* | \
  kopensolaris*-gnu* | \
  storm-chaos* | os2-emx* | rtmk-nova*)
    os=-$maybe_os
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
    ;;




  *)
    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
    if [ $basic_machine != $1 ]
    then os=`echo $1 | sed 's/.*-/-/'`
    else os=; fi
    ;;
esac







|






>
>
>
>







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
esac

# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
  knetbsd*-gnu* | netbsd*-gnu* | \
  kopensolaris*-gnu* | \
  storm-chaos* | os2-emx* | rtmk-nova*)
    os=-$maybe_os
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
    ;;
  android-linux)
    os=-linux-android
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
    ;;
  *)
    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
    if [ $basic_machine != $1 ]
    then os=`echo $1 | sed 's/.*-/-/'`
    else os=; fi
    ;;
esac
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
		;;
	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
	-apple | -axis | -knuth | -cray | -microblaze)
		os=
		basic_machine=$1
		;;
        -bluegene*)
	        os=-cnk
		;;
	-sim | -cisco | -oki | -wec | -winbond)
		os=
		basic_machine=$1
		;;
	-scout)
		;;
	-wrs)
		os=-vxworks
		basic_machine=$1
		;;
	-chorusos*)
		os=-chorusos
		basic_machine=$1
		;;
 	-chorusrdb)
 		os=-chorusrdb
		basic_machine=$1
 		;;
	-hiux*)
		os=-hiuxwe2
		;;
	-sco6)
		os=-sco5v6
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;







|



|
|















|
|

|







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
		;;
	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
	-apple | -axis | -knuth | -cray | -microblaze*)
		os=
		basic_machine=$1
		;;
	-bluegene*)
		os=-cnk
		;;
	-sim | -cisco | -oki | -wec | -winbond)
		os=
		basic_machine=$1
		;;
	-scout)
		;;
	-wrs)
		os=-vxworks
		basic_machine=$1
		;;
	-chorusos*)
		os=-chorusos
		basic_machine=$1
		;;
	-chorusrdb)
		os=-chorusrdb
		basic_machine=$1
		;;
	-hiux*)
		os=-hiuxwe2
		;;
	-sco6)
		os=-sco5v6
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
219
220
221
222
223
224
225






226
227
228
229
230
231
232
		;;
	-clix*)
		basic_machine=clipper-intergraph
		;;
	-isc*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;






	-lynx*)
		os=-lynxos
		;;
	-ptx*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
		;;
	-windowsnt*)







>
>
>
>
>
>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
		;;
	-clix*)
		basic_machine=clipper-intergraph
		;;
	-isc*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-lynx*178)
		os=-lynxos178
		;;
	-lynx*5)
		os=-lynxos5
		;;
	-lynx*)
		os=-lynxos
		;;
	-ptx*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
		;;
	-windowsnt*)
243
244
245
246
247
248
249

250
251
252

253


254
255
256

257
258

259
260


261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

277
278

279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326















327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346

347
348
349
350
351
352
353
354

355
356


357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373

374
375

376
377

378
379
380
381
382
383
384


385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409

# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
	# Recognize the basic CPU types without company name.
	# Some are omitted here because they have special meanings below.
	1750a | 580 \
	| a29k \

	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
	| am33_2.0 \

	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \


	| bfin \
	| c4x | clipper \
	| d10v | d30v | dlx | dsp16xx \

	| fido | fr30 | frv \
	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \

	| i370 | i860 | i960 | ia64 \
	| ip2k | iq2000 \


	| lm32 \
	| m32c | m32r | m32rle | m68000 | m68k | m88k \
	| maxq | mb | microblaze | mcore | mep | metag \
	| mips | mipsbe | mipseb | mipsel | mipsle \
	| mips16 \
	| mips64 | mips64el \
	| mips64octeon | mips64octeonel \
	| mips64orion | mips64orionel \
	| mips64r5900 | mips64r5900el \
	| mips64vr | mips64vrel \
	| mips64vr4100 | mips64vr4100el \
	| mips64vr4300 | mips64vr4300el \
	| mips64vr5000 | mips64vr5000el \
	| mips64vr5900 | mips64vr5900el \
	| mipsisa32 | mipsisa32el \
	| mipsisa32r2 | mipsisa32r2el \

	| mipsisa64 | mipsisa64el \
	| mipsisa64r2 | mipsisa64r2el \

	| mipsisa64sb1 | mipsisa64sb1el \
	| mipsisa64sr71k | mipsisa64sr71kel \

	| mipstx39 | mipstx39el \
	| mn10200 | mn10300 \
	| moxie \
	| mt \
	| msp430 \
	| nds32 | nds32le | nds32be \
	| nios | nios2 \
	| ns16k | ns32k \
	| or32 \
	| pdp10 | pdp11 | pj | pjl \
	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
	| pyramid \
	| rx \
	| score \
	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
	| sh64 | sh64le \
	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
	| spu | strongarm \
	| tahoe | thumb | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
	| ubicom32 \
	| v850 | v850e \
	| we32k \
	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
	| z8k | z80)
		basic_machine=$basic_machine-unknown
		;;
	c54x)
		basic_machine=tic54x-unknown
		;;
	c55x)
		basic_machine=tic55x-unknown
		;;
	c6x)
		basic_machine=tic6x-unknown
		;;
	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
		# Motorola 68HC11/12.
		basic_machine=$basic_machine-unknown
		os=-none
		;;
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
		;;
	ms1)
		basic_machine=mt-unknown
		;;
















	# We use `pc' rather than `unknown'
	# because (1) that's what they normally are, and
	# (2) the word "unknown" tends to confuse beginning users.
	i*86 | x86_64)
	  basic_machine=$basic_machine-pc
	  ;;
	# Object if more than one company name word.
	*-*-*)
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
		exit 1
		;;
	# Recognize the basic CPU types with company name.
	580-* \
	| a29k-* \

	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
	| avr-* | avr32-* \

	| bfin-* | bs2000-* \
	| c[123]* | c30-* | [cjt]90-* | c4x-* \
	| clipper-* | craynv-* | cydra-* \
	| d10v-* | d30v-* | dlx-* \
	| elxsi-* \
	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
	| h8300-* | h8500-* \
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \

	| i*86-* | i860-* | i960-* | ia64-* \
	| ip2k-* | iq2000-* \


	| lm32-* \
	| m32c-* | m32r-* | m32rle-* \
	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \

	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
	| mips16-* \
	| mips64-* | mips64el-* \
	| mips64octeon-* | mips64octeonel-* \
	| mips64orion-* | mips64orionel-* \
	| mips64r5900-* | mips64r5900el-* \
	| mips64vr-* | mips64vrel-* \
	| mips64vr4100-* | mips64vr4100el-* \
	| mips64vr4300-* | mips64vr4300el-* \
	| mips64vr5000-* | mips64vr5000el-* \
	| mips64vr5900-* | mips64vr5900el-* \
	| mipsisa32-* | mipsisa32el-* \
	| mipsisa32r2-* | mipsisa32r2el-* \

	| mipsisa64-* | mipsisa64el-* \
	| mipsisa64r2-* | mipsisa64r2el-* \

	| mipsisa64sb1-* | mipsisa64sb1el-* \
	| mipsisa64sr71k-* | mipsisa64sr71kel-* \

	| mipstx39-* | mipstx39el-* \
	| mmix-* \
	| mt-* \
	| msp430-* \
	| nds32-* | nds32le-* | nds32be-* \
	| nios-* | nios2-* \
	| none-* | np1-* | ns16k-* | ns32k-* \


	| orion-* \
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
	| pyramid-* \
	| romp-* | rs6000-* | rx-* \
	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
	| sparclite-* \
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
	| tahoe-* | thumb-* \
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
	| tile-* | tilegx-* \
	| tron-* \
	| ubicom32-* \
	| v850-* | v850e-* | vax-* \

	| we32k-* \
	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
	| xstormy16-* | xtensa*-* \
	| ymp-* \
	| z8k-* | z80-*)
		;;
	# Recognize the basic CPU types without company name, with glob match.
	xtensa*)
		basic_machine=$basic_machine-unknown







>



>
|
>
>

|

>


>


>
>


|













>


>


>






|

|

|

|





|
|

|

|












|
<








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>


|


>


|





>


>
>



|
>













>


>


>





|

>
>


|

|




|
|

|


|
>

|







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447

# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
	# Recognize the basic CPU types without company name.
	# Some are omitted here because they have special meanings below.
	1750a | 580 \
	| a29k \
	| aarch64 | aarch64_be \
	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
	| am33_2.0 \
	| arc | arceb \
	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
	| avr | avr32 \
	| be32 | be64 \
	| bfin \
	| c4x | c8051 | clipper \
	| d10v | d30v | dlx | dsp16xx \
	| epiphany \
	| fido | fr30 | frv \
	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
	| hexagon \
	| i370 | i860 | i960 | ia64 \
	| ip2k | iq2000 \
	| k1om \
	| le32 | le64 \
	| lm32 \
	| m32c | m32r | m32rle | m68000 | m68k | m88k \
	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
	| mips | mipsbe | mipseb | mipsel | mipsle \
	| mips16 \
	| mips64 | mips64el \
	| mips64octeon | mips64octeonel \
	| mips64orion | mips64orionel \
	| mips64r5900 | mips64r5900el \
	| mips64vr | mips64vrel \
	| mips64vr4100 | mips64vr4100el \
	| mips64vr4300 | mips64vr4300el \
	| mips64vr5000 | mips64vr5000el \
	| mips64vr5900 | mips64vr5900el \
	| mipsisa32 | mipsisa32el \
	| mipsisa32r2 | mipsisa32r2el \
	| mipsisa32r6 | mipsisa32r6el \
	| mipsisa64 | mipsisa64el \
	| mipsisa64r2 | mipsisa64r2el \
	| mipsisa64r6 | mipsisa64r6el \
	| mipsisa64sb1 | mipsisa64sb1el \
	| mipsisa64sr71k | mipsisa64sr71kel \
	| mipsr5900 | mipsr5900el \
	| mipstx39 | mipstx39el \
	| mn10200 | mn10300 \
	| moxie \
	| mt \
	| msp430 \
	| nds32 | nds32le | nds32be \
	| nios | nios2 | nios2eb | nios2el \
	| ns16k | ns32k \
	| open8 | or1k | or1knd | or32 \
	| pdp10 | pdp11 | pj | pjl \
	| powerpc | powerpc64 | powerpc64le | powerpcle \
	| pyramid \
	| rl78 | rx \
	| score \
	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
	| sh64 | sh64le \
	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
	| spu \
	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
	| ubicom32 \
	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
	| we32k \
	| x86 | xc16x | xstormy16 | xtensa \
	| z8k | z80)
		basic_machine=$basic_machine-unknown
		;;
	c54x)
		basic_machine=tic54x-unknown
		;;
	c55x)
		basic_machine=tic55x-unknown
		;;
	c6x)
		basic_machine=tic6x-unknown
		;;
	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)

		basic_machine=$basic_machine-unknown
		os=-none
		;;
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
		;;
	ms1)
		basic_machine=mt-unknown
		;;

	strongarm | thumb | xscale)
		basic_machine=arm-unknown
		;;
	xgate)
		basic_machine=$basic_machine-unknown
		os=-none
		;;
	xscaleeb)
		basic_machine=armeb-unknown
		;;

	xscaleel)
		basic_machine=armel-unknown
		;;

	# We use `pc' rather than `unknown'
	# because (1) that's what they normally are, and
	# (2) the word "unknown" tends to confuse beginning users.
	i*86 | x86_64)
	  basic_machine=$basic_machine-pc
	  ;;
	# Object if more than one company name word.
	*-*-*)
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
		exit 1
		;;
	# Recognize the basic CPU types with company name.
	580-* \
	| a29k-* \
	| aarch64-* | aarch64_be-* \
	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
	| avr-* | avr32-* \
	| be32-* | be64-* \
	| bfin-* | bs2000-* \
	| c[123]* | c30-* | [cjt]90-* | c4x-* \
	| c8051-* | clipper-* | craynv-* | cydra-* \
	| d10v-* | d30v-* | dlx-* \
	| elxsi-* \
	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
	| h8300-* | h8500-* \
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
	| hexagon-* \
	| i*86-* | i860-* | i960-* | ia64-* \
	| ip2k-* | iq2000-* \
	| k1om-* \
	| le32-* | le64-* \
	| lm32-* \
	| m32c-* | m32r-* | m32rle-* \
	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
	| microblaze-* | microblazeel-* \
	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
	| mips16-* \
	| mips64-* | mips64el-* \
	| mips64octeon-* | mips64octeonel-* \
	| mips64orion-* | mips64orionel-* \
	| mips64r5900-* | mips64r5900el-* \
	| mips64vr-* | mips64vrel-* \
	| mips64vr4100-* | mips64vr4100el-* \
	| mips64vr4300-* | mips64vr4300el-* \
	| mips64vr5000-* | mips64vr5000el-* \
	| mips64vr5900-* | mips64vr5900el-* \
	| mipsisa32-* | mipsisa32el-* \
	| mipsisa32r2-* | mipsisa32r2el-* \
	| mipsisa32r6-* | mipsisa32r6el-* \
	| mipsisa64-* | mipsisa64el-* \
	| mipsisa64r2-* | mipsisa64r2el-* \
	| mipsisa64r6-* | mipsisa64r6el-* \
	| mipsisa64sb1-* | mipsisa64sb1el-* \
	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
	| mipsr5900-* | mipsr5900el-* \
	| mipstx39-* | mipstx39el-* \
	| mmix-* \
	| mt-* \
	| msp430-* \
	| nds32-* | nds32le-* | nds32be-* \
	| nios-* | nios2-* | nios2eb-* | nios2el-* \
	| none-* | np1-* | ns16k-* | ns32k-* \
	| open8-* \
	| or1k*-* \
	| orion-* \
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
	| pyramid-* \
	| rl78-* | romp-* | rs6000-* | rx-* \
	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
	| sparclite-* \
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
	| tahoe-* \
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
	| tile*-* \
	| tron-* \
	| ubicom32-* \
	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
	| vax-* \
	| we32k-* \
	| x86-* | x86_64-* | xc16x-* | xps100-* \
	| xstormy16-* | xtensa*-* \
	| ymp-* \
	| z8k-* | z80-*)
		;;
	# Recognize the basic CPU types without company name, with glob match.
	xtensa*)
		basic_machine=$basic_machine-unknown
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
	3b*)
		basic_machine=we32k-att
		;;
	a29khif)
		basic_machine=a29k-amd
		os=-udi
		;;
    	abacus)
		basic_machine=abacus-unknown
		;;
	adobe68k)
		basic_machine=m68010-adobe
		os=-scout
		;;
	alliant | fx80)







|







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	3b*)
		basic_machine=we32k-att
		;;
	a29khif)
		basic_machine=a29k-amd
		os=-udi
		;;
	abacus)
		basic_machine=abacus-unknown
		;;
	adobe68k)
		basic_machine=m68010-adobe
		os=-scout
		;;
	alliant | fx80)
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
	c6x-*)
		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	c90)
		basic_machine=c90-cray
		os=-unicos
		;;
        cegcc)
		basic_machine=arm-unknown
		os=-cegcc
		;;
	convex-c1)
		basic_machine=c1-convex
		os=-bsd
		;;







|







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
	c6x-*)
		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	c90)
		basic_machine=c90-cray
		os=-unicos
		;;
	cegcc)
		basic_machine=arm-unknown
		os=-cegcc
		;;
	convex-c1)
		basic_machine=c1-convex
		os=-bsd
		;;
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
		basic_machine=j90-cray
		os=-unicos
		;;
	craynv)
		basic_machine=craynv-cray
		os=-unicosmp
		;;
	cr16)
		basic_machine=cr16-unknown
		os=-elf
		;;
	crds | unos)
		basic_machine=m68k-crds
		;;
	crisv32 | crisv32-* | etraxfs*)







|







573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
		basic_machine=j90-cray
		os=-unicos
		;;
	craynv)
		basic_machine=craynv-cray
		os=-unicosmp
		;;
	cr16 | cr16-*)
		basic_machine=cr16-unknown
		os=-elf
		;;
	crds | unos)
		basic_machine=m68k-crds
		;;
	crisv32 | crisv32-* | etraxfs*)
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
	hppro)
		basic_machine=hppa1.1-hp
		os=-proelf
		;;
	i370-ibm* | ibm*)
		basic_machine=i370-ibm
		;;
# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
	i*86v32)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv32
		;;
	i*86v4*)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv4







<







731
732
733
734
735
736
737

738
739
740
741
742
743
744
	hppro)
		basic_machine=hppa1.1-hp
		os=-proelf
		;;
	i370-ibm* | ibm*)
		basic_machine=i370-ibm
		;;

	i*86v32)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv32
		;;
	i*86v4*)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv4
751
752
753
754
755
756
757
758
759
760




761
762
763
764
765
766
767
768
769
		basic_machine=mips-mips
		os=-sysv
		;;
	merlin)
		basic_machine=ns32k-utek
		os=-sysv
		;;
        microblaze)
		basic_machine=microblaze-xilinx
		;;




	mingw32)
		basic_machine=i386-pc
		os=-mingw32
		;;
	mingw32ce)
		basic_machine=arm-unknown
		os=-mingw32ce
		;;
	miniframe)







|


>
>
>
>

|







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
		basic_machine=mips-mips
		os=-sysv
		;;
	merlin)
		basic_machine=ns32k-utek
		os=-sysv
		;;
	microblaze*)
		basic_machine=microblaze-xilinx
		;;
	mingw64)
		basic_machine=x86_64-pc
		os=-mingw64
		;;
	mingw32)
		basic_machine=i686-pc
		os=-mingw32
		;;
	mingw32ce)
		basic_machine=arm-unknown
		os=-mingw32ce
		;;
	miniframe)
790
791
792
793
794
795
796




797
798
799
800
801

802
803
804
805
806
807
808
809
810
811
	msdos)
		basic_machine=i386-pc
		os=-msdos
		;;
	ms1-*)
		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
		;;




	mvs)
		basic_machine=i370-ibm
		os=-mvs
		;;
	msys) 

		basic_machine=i386-pc 
		os=-msys 
	 ;; 
	ncr3000)
		basic_machine=i486-ncr
		os=-sysv4
		;;
	netbsd386)
		basic_machine=i386-unknown
		os=-netbsd







>
>
>
>




<
>
|
|
|







831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
	msdos)
		basic_machine=i386-pc
		os=-msdos
		;;
	ms1-*)
		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
		;;
	msys)
		basic_machine=i686-pc
		os=-msys
		;;
	mvs)
		basic_machine=i370-ibm
		os=-mvs
		;;

	nacl)
		basic_machine=le32-unknown
		os=-nacl
		;;
	ncr3000)
		basic_machine=i486-ncr
		os=-sysv4
		;;
	netbsd386)
		basic_machine=i386-unknown
		os=-netbsd
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
	nonstopux)
		basic_machine=mips-compaq
		os=-nonstopux
		;;
	np1)
		basic_machine=np1-gould
		;;
        neo-tandem)
		basic_machine=neo-tandem
		;;
        nse-tandem)
		basic_machine=nse-tandem
		;;
	nsr-tandem)
		basic_machine=nsr-tandem
		;;
	op50n-* | op60c-*)
		basic_machine=hppa1.1-oki







|


|







907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
	nonstopux)
		basic_machine=mips-compaq
		os=-nonstopux
		;;
	np1)
		basic_machine=np1-gould
		;;
	neo-tandem)
		basic_machine=neo-tandem
		;;
	nse-tandem)
		basic_machine=nse-tandem
		;;
	nsr-tandem)
		basic_machine=nsr-tandem
		;;
	op50n-* | op60c-*)
		basic_machine=hppa1.1-oki
950
951
952
953
954
955
956
957
958

959
960
961
962
963
964
965
966
		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pn)
		basic_machine=pn-gould
		;;
	power)	basic_machine=power-ibm
		;;
	ppc)	basic_machine=powerpc-unknown
		;;

	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ppcle | powerpclittle | ppc-le | powerpc-little)
		basic_machine=powerpcle-unknown
		;;
	ppcle-* | powerpclittle-*)
		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;







|

>
|







995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pn)
		basic_machine=pn-gould
		;;
	power)	basic_machine=power-ibm
		;;
	ppc | ppcbe)	basic_machine=powerpc-unknown
		;;
	ppc-* | ppcbe-*)
		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ppcle | powerpclittle | ppc-le | powerpc-little)
		basic_machine=powerpcle-unknown
		;;
	ppcle-* | powerpclittle-*)
		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
977
978
979
980
981
982
983


984


985
986
987
988
989
990
991
	ps2)
		basic_machine=i386-ibm
		;;
	pw32)
		basic_machine=i586-unknown
		os=-pw32
		;;


	rdos)


		basic_machine=i386-pc
		os=-rdos
		;;
	rom68k)
		basic_machine=m68k-rom68k
		os=-coff
		;;







>
>
|
>
>







1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
	ps2)
		basic_machine=i386-ibm
		;;
	pw32)
		basic_machine=i586-unknown
		os=-pw32
		;;
	rdos | rdos64)
		basic_machine=x86_64-pc
		os=-rdos
		;;
	rdos32)
		basic_machine=i386-pc
		os=-rdos
		;;
	rom68k)
		basic_machine=m68k-rom68k
		os=-coff
		;;
1046
1047
1048
1049
1050
1051
1052



1053
1054
1055
1056
1057
1058
1059
	st2000)
		basic_machine=m68k-tandem
		;;
	stratus)
		basic_machine=i860-stratus
		os=-sysv4
		;;



	sun2)
		basic_machine=m68000-sun
		;;
	sun2os3)
		basic_machine=m68000-sun
		os=-sunos3
		;;







>
>
>







1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
	st2000)
		basic_machine=m68k-tandem
		;;
	stratus)
		basic_machine=i860-stratus
		os=-sysv4
		;;
	strongarm-* | thumb-*)
		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	sun2)
		basic_machine=m68000-sun
		;;
	sun2os3)
		basic_machine=m68000-sun
		os=-sunos3
		;;
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
		basic_machine=alphaev5-cray
		os=-unicos
		;;
	t90)
		basic_machine=t90-cray
		os=-unicos
		;;
        # This must be matched before tile*.
        tilegx*)
		basic_machine=tilegx-unknown
		os=-linux-gnu
		;;
	tile*)
		basic_machine=tile-unknown
		os=-linux-gnu
		;;
	tx39)
		basic_machine=mipstx39-unknown
		;;
	tx39el)
		basic_machine=mipstx39el-unknown







<
<
<
<
<

|







1155
1156
1157
1158
1159
1160
1161





1162
1163
1164
1165
1166
1167
1168
1169
1170
		basic_machine=alphaev5-cray
		os=-unicos
		;;
	t90)
		basic_machine=t90-cray
		os=-unicos
		;;





	tile*)
		basic_machine=$basic_machine-unknown
		os=-linux-gnu
		;;
	tx39)
		basic_machine=mipstx39-unknown
		;;
	tx39el)
		basic_machine=mipstx39el-unknown
1178
1179
1180
1181
1182
1183
1184



1185
1186
1187
1188
1189
1190
1191
	xbox)
		basic_machine=i686-pc
		os=-mingw32
		;;
	xps | xps100)
		basic_machine=xps100-honeywell
		;;



	ymp)
		basic_machine=ymp-cray
		os=-unicos
		;;
	z8k-*-coff)
		basic_machine=z8k-unknown
		os=-sim







>
>
>







1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
	xbox)
		basic_machine=i686-pc
		os=-mingw32
		;;
	xps | xps100)
		basic_machine=xps100-honeywell
		;;
	xscale-* | xscalee[bl]-*)
		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
		;;
	ymp)
		basic_machine=ymp-cray
		os=-unicos
		;;
	z8k-*-coff)
		basic_machine=z8k-unknown
		os=-sim
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
esac

# Decode manufacturer-specific aliases for certain operating systems.

if [ x"$os" != x"" ]
then
case $os in
        # First match some system type aliases
        # that might get confused with valid system types.
	# -solaris* is a basic system type, with this one exception.
        -auroraux)
	        os=-auroraux
		;;
	-solaris1 | -solaris1.*)
		os=`echo $os | sed -e 's|solaris1|sunos4|'`
		;;
	-solaris)
		os=-solaris2
		;;







|
|

|
|







1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
esac

# Decode manufacturer-specific aliases for certain operating systems.

if [ x"$os" != x"" ]
then
case $os in
	# First match some system type aliases
	# that might get confused with valid system types.
	# -solaris* is a basic system type, with this one exception.
	-auroraux)
		os=-auroraux
		;;
	-solaris1 | -solaris1.*)
		os=`echo $os | sed -e 's|solaris1|sunos4|'`
		;;
	-solaris)
		os=-solaris2
		;;
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
	# First accept the basic system types.
	# The portable systems comes first.
	# Each alternative MUST END IN A *, to match a version number.
	# -sysv* is not here because it comes later, after sysvr4.
	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
	      | -sym* | -kopensolaris* \
	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
	      | -aos* | -aros* \
	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
	      | -openbsd* | -solidbsd* \
	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
	      | -chorusos* | -chorusrdb* | -cegcc* \
	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
	      | -mingw32* | -linux-gnu* | -linux-android* \
	      | -linux-newlib* | -linux-uclibc* \
	      | -uxpv* | -beos* | -mpeix* | -udk* \
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
	# Remember, each alternative MUST END IN *, to match a version number.
		;;
	-qnx*)
		case $basic_machine in
		    x86-* | i*86-*)
			;;
		    *)







|





|






|
|







|







1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
	# First accept the basic system types.
	# The portable systems comes first.
	# Each alternative MUST END IN A *, to match a version number.
	# -sysv* is not here because it comes later, after sysvr4.
	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
	      | -sym* | -kopensolaris* | -plan9* \
	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
	      | -aos* | -aros* \
	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
	      | -bitrig* | -openbsd* | -solidbsd* \
	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
	      | -chorusos* | -chorusrdb* | -cegcc* \
	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
	      | -uxpv* | -beos* | -mpeix* | -udk* \
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
	# Remember, each alternative MUST END IN *, to match a version number.
		;;
	-qnx*)
		case $basic_machine in
		    x86-* | i*86-*)
			;;
		    *)
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
		;;
	-sunos6*)
		os=`echo $os | sed -e 's|sunos6|solaris3|'`
		;;
	-opened*)
		os=-openedition
		;;
        -os400*)
		os=-os400
		;;
	-wince*)
		os=-wince
		;;
	-osfrose*)
		os=-osfrose







|







1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
		;;
	-sunos6*)
		os=`echo $os | sed -e 's|sunos6|solaris3|'`
		;;
	-opened*)
		os=-openedition
		;;
	-os400*)
		os=-os400
		;;
	-wince*)
		os=-wince
		;;
	-osfrose*)
		os=-osfrose
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
	# Preserve the version number of sinix5.
	-sinix5.*)
		os=`echo $os | sed -e 's|sinix|sysv|'`
		;;
	-sinix*)
		os=-sysv4
		;;
        -tpf*)
		os=-tpf
		;;
	-triton*)
		os=-sysv3
		;;
	-oss*)
		os=-sysv3







|







1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
	# Preserve the version number of sinix5.
	-sinix5.*)
		os=`echo $os | sed -e 's|sinix|sysv|'`
		;;
	-sinix*)
		os=-sysv4
		;;
	-tpf*)
		os=-tpf
		;;
	-triton*)
		os=-sysv3
		;;
	-oss*)
		os=-sysv3
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
		;;
	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
		os=-mint
		;;
	-aros*)
		os=-aros
		;;
	-kaos*)
		os=-kaos
		;;
	-zvmoe)
		os=-zvmoe
		;;
	-dicos*)
		os=-dicos
		;;
        -nacl*)
	        ;;
	-none)
		;;
	*)
		# Get rid of the `-' at the beginning of $os.
		os=`echo $os | sed 's/[^-]*-//'`
		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
		exit 1







<
<
<






|
|







1500
1501
1502
1503
1504
1505
1506



1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
		;;
	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
		os=-mint
		;;
	-aros*)
		os=-aros
		;;



	-zvmoe)
		os=-zvmoe
		;;
	-dicos*)
		os=-dicos
		;;
	-nacl*)
		;;
	-none)
		;;
	*)
		# Get rid of the `-' at the beginning of $os.
		os=`echo $os | sed 's/[^-]*-//'`
		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
		exit 1
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505






1506
1507
1508
1509
1510
1511
1512
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system.  Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.

case $basic_machine in
        score-*)
		os=-elf
		;;
        spu-*)
		os=-elf
		;;
	*-acorn)
		os=-riscix1.2
		;;
	arm*-rebel)
		os=-linux
		;;
	arm*-semi)
		os=-aout
		;;
        c4x-* | tic4x-*)
        	os=-coff






		;;
	tic54x-*)
		os=-coff
		;;
	tic55x-*)
		os=-coff
		;;







|


|











|
|
>
>
>
>
>
>







1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system.  Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.

case $basic_machine in
	score-*)
		os=-elf
		;;
	spu-*)
		os=-elf
		;;
	*-acorn)
		os=-riscix1.2
		;;
	arm*-rebel)
		os=-linux
		;;
	arm*-semi)
		os=-aout
		;;
	c4x-* | tic4x-*)
		os=-coff
		;;
	c8051-*)
		os=-elf
		;;
	hexagon-*)
		os=-elf
		;;
	tic54x-*)
		os=-coff
		;;
	tic55x-*)
		os=-coff
		;;
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
		os=-domain
		;;
	i386-sun)
		os=-sunos4.0.2
		;;
	m68000-sun)
		os=-sunos3
		# This also exists in the configure program, but was not the
		# default.
		# os=-sunos4
		;;
	m68*-cisco)
		os=-aout
		;;
        mep-*)
		os=-elf
		;;
	mips*-cisco)
		os=-elf
		;;
	mips*-*)
		os=-elf







<
<
<




|







1581
1582
1583
1584
1585
1586
1587



1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
		os=-domain
		;;
	i386-sun)
		os=-sunos4.0.2
		;;
	m68000-sun)
		os=-sunos3



		;;
	m68*-cisco)
		os=-aout
		;;
	mep-*)
		os=-elf
		;;
	mips*-cisco)
		os=-elf
		;;
	mips*-*)
		os=-elf
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
		;;
	*-haiku)
		os=-haiku
		;;
	*-ibm)
		os=-aix
		;;
    	*-knuth)
		os=-mmixware
		;;
	*-wec)
		os=-proelf
		;;
	*-winbond)
		os=-proelf







|







1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
		;;
	*-haiku)
		os=-haiku
		;;
	*-ibm)
		os=-aix
		;;
	*-knuth)
		os=-mmixware
		;;
	*-wec)
		os=-proelf
		;;
	*-winbond)
		os=-proelf
Changes to autosetup/jimsh0.c.
1
2
3
4
5
6
7
8
/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
#define _GNU_SOURCE
#define JIM_TCL_COMPAT
#define JIM_REFERENCES
#define JIM_ANSIC
#define JIM_REGEXP
#define HAVE_NO_AUTOCONF
#define _JIMAUTOCONF_H
|







1
2
3
4
5
6
7
8
/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
#define _GNU_SOURCE
#define JIM_TCL_COMPAT
#define JIM_REFERENCES
#define JIM_ANSIC
#define JIM_REGEXP
#define HAVE_NO_AUTOCONF
#define _JIMAUTOCONF_H
40
41
42
43
44
45
46

47
48
49
50




51
52
53
54
55
56
57
#define HAVE_VFORK
#define HAVE_WAITPID
#define HAVE_ISATTY
#define HAVE_SYS_TIME_H
#define HAVE_DIRENT_H
#define HAVE_UNISTD_H
#endif

#ifndef JIM_WIN32COMPAT_H
#define JIM_WIN32COMPAT_H








#if defined(_WIN32) || defined(WIN32)

#define HAVE_DLOPEN
void *dlopen(const char *path, int mode);
int dlclose(void *handle);







>




>
>
>
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#define HAVE_VFORK
#define HAVE_WAITPID
#define HAVE_ISATTY
#define HAVE_SYS_TIME_H
#define HAVE_DIRENT_H
#define HAVE_UNISTD_H
#endif
#define JIM_VERSION 75
#ifndef JIM_WIN32COMPAT_H
#define JIM_WIN32COMPAT_H



#ifdef __cplusplus
extern "C" {
#endif


#if defined(_WIN32) || defined(WIN32)

#define HAVE_DLOPEN
void *dlopen(const char *path, int mode);
int dlclose(void *handle);
103
104
105
106
107
108
109





110
111
112




113
114
115
116





117
118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137
138




139
140
141
142
143
144
145
	struct dirent       result; 
	char                *name;  
} DIR;

DIR *opendir(const char *name);
int closedir(DIR *dir);
struct dirent *readdir(DIR *dir);





#endif 

#endif 





#endif
#ifndef UTF8_UTIL_H
#define UTF8_UTIL_H







#define MAX_UTF8_LEN 4

int utf8_fromunicode(char *p, unsigned uc);

#ifndef JIM_UTF8
#include <ctype.h>


#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)

#define utf8_upper(C) toupper(C)
#define utf8_title(C) toupper(C)
#define utf8_lower(C) tolower(C)
#define utf8_index(C, I) (I)
#define utf8_charlen(C) 1
#define utf8_prev_len(S, L) 1

#else

#endif





#endif

#ifndef __JIM__H
#define __JIM__H

#ifdef __cplusplus







>
>
>
>
>
|


>
>
>
>




>
>
>
>
>












>










>
>
>
>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	struct dirent       result; 
	char                *name;  
} DIR;

DIR *opendir(const char *name);
int closedir(DIR *dir);
struct dirent *readdir(DIR *dir);

#elif defined(__MINGW32__)

#define strtod __strtod

#endif

#endif 

#ifdef __cplusplus
}
#endif

#endif
#ifndef UTF8_UTIL_H
#define UTF8_UTIL_H

#ifdef __cplusplus
extern "C" {
#endif



#define MAX_UTF8_LEN 4

int utf8_fromunicode(char *p, unsigned uc);

#ifndef JIM_UTF8
#include <ctype.h>


#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
#define utf8_getchars(CP, C) (*(CP) = (C), 1)
#define utf8_upper(C) toupper(C)
#define utf8_title(C) toupper(C)
#define utf8_lower(C) tolower(C)
#define utf8_index(C, I) (I)
#define utf8_charlen(C) 1
#define utf8_prev_len(S, L) 1

#else

#endif

#ifdef __cplusplus
}
#endif

#endif

#ifndef __JIM__H
#define __JIM__H

#ifdef __cplusplus
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#    define strtoull strtoul
#  endif
#endif

#define UCHAR(c) ((unsigned char)(c))


#define JIM_VERSION 74

#define JIM_OK 0
#define JIM_ERR 1
#define JIM_RETURN 2
#define JIM_BREAK 3
#define JIM_CONTINUE 4
#define JIM_SIGNAL 5
#define JIM_EXIT 6

#define JIM_EVAL 7

#define JIM_MAX_CALLFRAME_DEPTH 1000 
#define JIM_MAX_EVAL_DEPTH 2000 

#define JIM_NONE 0    
#define JIM_ERRMSG 1    

#define JIM_UNSHARED 4 
#define JIM_MUSTEXIST 8    


#define JIM_GLOBAL_ONLY 0x100


#define JIM_SUBST_NOVAR 1 
#define JIM_SUBST_NOCMD 2 
#define JIM_SUBST_NOESC 4 
#define JIM_SUBST_FLAG 128 


#define JIM_NOTUSED(V) ((void) V)


#define JIM_ENUM_ABBREV 2    


#define JIM_CASESENS    0   
#define JIM_NOCASE      1   


#define JIM_PATH_LEN 1024


#ifdef JIM_CRLF
#define JIM_NL "\r\n"
#else
#define JIM_NL "\n"
#endif

#define JIM_LIBPATH "auto_path"
#define JIM_INTERACTIVE "tcl_interactive"


typedef struct Jim_Stack {
    int len;







<
<













|
|

|
|
|
|
|







<
<
<
<
<
<








<
<
<
|
<







207
208
209
210
211
212
213


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241






242
243
244
245
246
247
248
249



250

251
252
253
254
255
256
257
#    define strtoull strtoul
#  endif
#endif

#define UCHAR(c) ((unsigned char)(c))




#define JIM_OK 0
#define JIM_ERR 1
#define JIM_RETURN 2
#define JIM_BREAK 3
#define JIM_CONTINUE 4
#define JIM_SIGNAL 5
#define JIM_EXIT 6

#define JIM_EVAL 7

#define JIM_MAX_CALLFRAME_DEPTH 1000 
#define JIM_MAX_EVAL_DEPTH 2000 


#define JIM_PRIV_FLAG_SHIFT 20

#define JIM_NONE 0              
#define JIM_ERRMSG 1            
#define JIM_ENUM_ABBREV 2       
#define JIM_UNSHARED 4          
#define JIM_MUSTEXIST 8         


#define JIM_SUBST_NOVAR 1 
#define JIM_SUBST_NOCMD 2 
#define JIM_SUBST_NOESC 4 
#define JIM_SUBST_FLAG 128 








#define JIM_CASESENS    0   
#define JIM_NOCASE      1   


#define JIM_PATH_LEN 1024





#define JIM_NOTUSED(V) ((void) V)


#define JIM_LIBPATH "auto_path"
#define JIM_INTERACTIVE "tcl_interactive"


typedef struct Jim_Stack {
    int len;
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} Jim_HashTableType;

typedef struct Jim_HashTable {
    Jim_HashEntry **table;
    const Jim_HashTableType *type;

    unsigned int size;
    unsigned int sizemask;
    unsigned int used;
    unsigned int collisions;
    void *privdata;
} Jim_HashTable;

typedef struct Jim_HashTableIterator {
    Jim_HashTable *ht;
    int index;
    Jim_HashEntry *entry, *nextEntry;

} Jim_HashTableIterator;


#define JIM_HT_INITIAL_SIZE     16


#define Jim_FreeEntryVal(ht, entry) \
    if ((ht)->type->valDestructor) \
        (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)

#define Jim_SetHashVal(ht, entry, _val_) do { \
    if ((ht)->type->valDup) \
        entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
    else \
        entry->u.val = (_val_); \
} while(0)

#define Jim_FreeEntryKey(ht, entry) \
    if ((ht)->type->keyDestructor) \
        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)

#define Jim_SetHashKey(ht, entry, _key_) do { \
    if ((ht)->type->keyDup) \
        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
    else \
        entry->key = (void *)(_key_); \
} while(0)

#define Jim_CompareHashKeys(ht, key1, key2) \
    (((ht)->type->keyCompare) ? \
        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
        (key1) == (key2))

#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)

#define Jim_GetHashEntryKey(he) ((he)->key)
#define Jim_GetHashEntryVal(he) ((he)->val)
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
#define Jim_GetHashTableSize(ht) ((ht)->size)
#define Jim_GetHashTableUsed(ht) ((ht)->used)


typedef struct Jim_Obj {
    char *bytes; 







>




|




<

>












|

|








|

|




|


|


|







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} Jim_HashTableType;

typedef struct Jim_HashTable {
    Jim_HashEntry **table;
    const Jim_HashTableType *type;
    void *privdata;
    unsigned int size;
    unsigned int sizemask;
    unsigned int used;
    unsigned int collisions;
    unsigned int uniq;
} Jim_HashTable;

typedef struct Jim_HashTableIterator {
    Jim_HashTable *ht;

    Jim_HashEntry *entry, *nextEntry;
    int index;
} Jim_HashTableIterator;


#define JIM_HT_INITIAL_SIZE     16


#define Jim_FreeEntryVal(ht, entry) \
    if ((ht)->type->valDestructor) \
        (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)

#define Jim_SetHashVal(ht, entry, _val_) do { \
    if ((ht)->type->valDup) \
        (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
    else \
        (entry)->u.val = (_val_); \
} while(0)

#define Jim_FreeEntryKey(ht, entry) \
    if ((ht)->type->keyDestructor) \
        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)

#define Jim_SetHashKey(ht, entry, _key_) do { \
    if ((ht)->type->keyDup) \
        (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
    else \
        (entry)->key = (void *)(_key_); \
} while(0)

#define Jim_CompareHashKeys(ht, key1, key2) \
    (((ht)->type->keyCompare) ? \
        (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
        (key1) == (key2))

#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)

#define Jim_GetHashEntryKey(he) ((he)->key)
#define Jim_GetHashEntryVal(he) ((he)->u.val)
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
#define Jim_GetHashTableSize(ht) ((ht)->size)
#define Jim_GetHashTableUsed(ht) ((ht)->used)


typedef struct Jim_Obj {
    char *bytes; 
340
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355

356
357
358
359
360
361
362
        
        struct {
            void *ptr1;
            void *ptr2;
        } twoPtrValue;
        
        struct {
            unsigned long callFrameId; 
            struct Jim_Var *varPtr;

            int global; 
        } varValue;
        
        struct {
            unsigned long procEpoch; 
            struct Jim_Obj *nsObj;
            struct Jim_Cmd *cmdPtr;

        } cmdValue;
        
        struct {
            struct Jim_Obj **ele;    
            int len;        
            int maxLen;        
        } listValue;







<

>




<


>







353
354
355
356
357
358
359

360
361
362
363
364
365

366
367
368
369
370
371
372
373
374
375
        
        struct {
            void *ptr1;
            void *ptr2;
        } twoPtrValue;
        
        struct {

            struct Jim_Var *varPtr;
            unsigned long callFrameId; 
            int global; 
        } varValue;
        
        struct {

            struct Jim_Obj *nsObj;
            struct Jim_Cmd *cmdPtr;
            unsigned long procEpoch; 
        } cmdValue;
        
        struct {
            struct Jim_Obj **ele;    
            int len;        
            int maxLen;        
        } listValue;
378
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
        
        struct {
            struct Jim_Obj *varNameObjPtr;
            struct Jim_Obj *indexObjPtr;
        } dictSubstValue;
        
        struct {
            unsigned flags;
            void *compre;       

        } regexpValue;
        struct {
            int line;
            int argc;
        } scriptLineValue;
    } internalRep;
    struct Jim_Obj *prevObjPtr; 







<

>







391
392
393
394
395
396
397

398
399
400
401
402
403
404
405
406
        
        struct {
            struct Jim_Obj *varNameObjPtr;
            struct Jim_Obj *indexObjPtr;
        } dictSubstValue;
        
        struct {

            void *compre;       
            unsigned flags;
        } regexpValue;
        struct {
            int line;
            int argc;
        } scriptLineValue;
    } internalRep;
    struct Jim_Obj *prevObjPtr; 
452
453
454
455
456
457
458



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
    Jim_Obj *procArgsObjPtr; 
    Jim_Obj *procBodyObjPtr; 
    struct Jim_CallFrame *next; 
    Jim_Obj *nsObj;             
    Jim_Obj *fileNameObj;       
    int line;
    Jim_Stack *localCommands; 



} Jim_CallFrame;

typedef struct Jim_Var {
    Jim_Obj *objPtr;
    struct Jim_CallFrame *linkFramePtr;
} Jim_Var;


typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
    Jim_Obj *const *argv);
typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);



typedef struct Jim_Cmd {
    int inUse;           
    int isproc;          
    struct Jim_Cmd *prevCmd;    
    union {
        struct {
            
            Jim_CmdProc cmdProc; 
            Jim_DelCmdProc delProc; 
            void *privData; 
        } native;
        struct {
            
            Jim_Obj *argListObjPtr;
            Jim_Obj *bodyObjPtr;
            Jim_HashTable *staticVars;  







>
>
>








|

|










|
|







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
    Jim_Obj *procArgsObjPtr; 
    Jim_Obj *procBodyObjPtr; 
    struct Jim_CallFrame *next; 
    Jim_Obj *nsObj;             
    Jim_Obj *fileNameObj;       
    int line;
    Jim_Stack *localCommands; 
    int tailcall;            
    struct Jim_Obj *tailcallObj;  
    struct Jim_Cmd *tailcallCmd;  
} Jim_CallFrame;

typedef struct Jim_Var {
    Jim_Obj *objPtr;
    struct Jim_CallFrame *linkFramePtr;
} Jim_Var;


typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
    Jim_Obj *const *argv);
typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);



typedef struct Jim_Cmd {
    int inUse;           
    int isproc;          
    struct Jim_Cmd *prevCmd;    
    union {
        struct {
            
            Jim_CmdProc *cmdProc; 
            Jim_DelCmdProc *delProc; 
            void *privData; 
        } native;
        struct {
            
            Jim_Obj *argListObjPtr;
            Jim_Obj *bodyObjPtr;
            Jim_HashTable *staticVars;  
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
typedef struct Jim_Reference {
    Jim_Obj *objPtr;
    Jim_Obj *finalizerCmdNamePtr;
    char tag[JIM_REFERENCE_TAGLEN+1];
} Jim_Reference;



#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)



#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)

#define JIM_EXPORT


JIM_EXPORT void *Jim_Alloc (int size);
JIM_EXPORT void *Jim_Realloc(void *ptr, int size);
JIM_EXPORT void Jim_Free (void *ptr);
JIM_EXPORT char * Jim_StrDup (const char *s);
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);


JIM_EXPORT char **Jim_GetEnviron(void);
JIM_EXPORT void Jim_SetEnviron(char **env);



JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);


JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script);








<

<
<
<














>







604
605
606
607
608
609
610

611



612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
typedef struct Jim_Reference {
    Jim_Obj *objPtr;
    Jim_Obj *finalizerCmdNamePtr;
    char tag[JIM_REFERENCE_TAGLEN+1];
} Jim_Reference;



#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)



#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)

#define JIM_EXPORT


JIM_EXPORT void *Jim_Alloc (int size);
JIM_EXPORT void *Jim_Realloc(void *ptr, int size);
JIM_EXPORT void Jim_Free (void *ptr);
JIM_EXPORT char * Jim_StrDup (const char *s);
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);


JIM_EXPORT char **Jim_GetEnviron(void);
JIM_EXPORT void Jim_SetEnviron(char **env);
JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);


JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);


JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script);

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp,
        const char *name, Jim_Obj *objPtr);
JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
        const char *name, const char *val);
JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
        Jim_CallFrame *targetCallFrame);
JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
        Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, int flags);
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, int flags);
JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
        const char *name, int flags);
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp,







|
|
<







751
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766
JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp,
        const char *name, Jim_Obj *objPtr);
JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
        const char *name, const char *val);
JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
        Jim_CallFrame *targetCallFrame);
JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
        Jim_Obj *nameObjPtr);

JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, int flags);
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
        Jim_Obj *nameObjPtr, int flags);
JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
        const char *name, int flags);
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp,
803
804
805
806
807
808
809

810
811
812
813
814
815
816
JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
        Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
        Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);



JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
        int *intPtr);


JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,







>







815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
        Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
        Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);


JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
        int *intPtr);


JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849

JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
        double *doublePtr);
JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
        double doubleValue);
JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);


JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
        const char *str);
JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp,
        const char *str);


JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
        Jim_Obj *const *argv, const char *msg);
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
        const char * const *tablePtr, int *indexPtr, const char *name, int flags);
JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len,
        char *stateCharPtr);







<
<
<
<
<
<







843
844
845
846
847
848
849






850
851
852
853
854
855
856

JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
        double *doublePtr);
JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
        double doubleValue);
JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);








JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
        Jim_Obj *const *argv, const char *msg);
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
        const char * const *tablePtr, int *indexPtr, const char *name, int flags);
JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len,
        char *stateCharPtr);
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
JIM_EXPORT void Jim_HistoryAdd(const char *line);
JIM_EXPORT void Jim_HistoryShow(void);


JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
JIM_EXPORT int Jim_CheckSignal(Jim_Interp *interp);

#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)


JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);


JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);



JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);

#ifdef __cplusplus
}







|
>








<







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
JIM_EXPORT void Jim_HistoryAdd(const char *line);
JIM_EXPORT void Jim_HistoryShow(void);


JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
JIM_EXPORT int Jim_IsBigEndian(void);

#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)


JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);


JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);



JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);

#ifdef __cplusplus
}
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959


#define JIM_MODFLAG_HIDDEN   0x0001		
#define JIM_MODFLAG_FULLARGV 0x0002		



typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

typedef struct {
	const char *cmd;				
	const char *args;				
	tclmod_cmd_function *function;	
	short minargs;					
	short maxargs;					
	unsigned short flags;			
} jim_subcmd_type;

const jim_subcmd_type *
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);

int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);

#ifdef __cplusplus
}
#endif

#endif
#ifndef JIMREGEXP_H
#define JIMREGEXP_H

#ifndef _JIMAUTOCONF_H
#error Need jimautoconf.h
#endif

#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)

#include <regex.h>

#else

#include <stdlib.h>


typedef struct {
	int rm_so;
	int rm_eo;
} regmatch_t;









|




|




















<
<
<

<
|
<
|
|


<







915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947



948

949

950
951
952
953

954
955
956
957
958
959
960


#define JIM_MODFLAG_HIDDEN   0x0001		
#define JIM_MODFLAG_FULLARGV 0x0002		



typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

typedef struct {
	const char *cmd;				
	const char *args;				
	jim_subcmd_function *function;	
	short minargs;					
	short maxargs;					
	unsigned short flags;			
} jim_subcmd_type;

const jim_subcmd_type *
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);

int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);

#ifdef __cplusplus
}
#endif

#endif
#ifndef JIMREGEXP_H
#define JIMREGEXP_H






#ifdef __cplusplus

extern "C" {
#endif

#include <stdlib.h>


typedef struct {
	int rm_so;
	int rm_eo;
} regmatch_t;


1018
1019
1020
1021
1022
1023
1024


1025
1026
1027
1028
1029
1030
1031
};

int regcomp(regex_t *preg, const char *regex, int cflags);
int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size);
void regfree(regex_t *preg);



#endif

#endif
int Jim_bootstrapInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
		return JIM_ERR;







>
>







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
};

int regcomp(regex_t *preg, const char *regex, int cflags);
int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size);
void regfree(regex_t *preg);

#ifdef __cplusplus
}
#endif

#endif
int Jim_bootstrapInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
		return JIM_ERR;
1084
1085
1086
1087
1088
1089
1090





1091
1092
1093
1094
1095
1096
1097
"\n"
"\n"
"\n"
"package require readdir\n"
"\n"
"\n"
"proc glob.globdir {dir pattern} {\n"





"	set result {}\n"
"	set files [readdir $dir]\n"
"	lappend files . ..\n"
"\n"
"	foreach name $files {\n"
"		if {[string match $pattern $name]} {\n"
"\n"







>
>
>
>
>







1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
"\n"
"\n"
"\n"
"package require readdir\n"
"\n"
"\n"
"proc glob.globdir {dir pattern} {\n"
"	if {[file exists $dir/$pattern]} {\n"
"\n"
"		return $pattern\n"
"	}\n"
"\n"
"	set result {}\n"
"	set files [readdir $dir]\n"
"	lappend files . ..\n"
"\n"
"	foreach name $files {\n"
"		if {[string match $pattern $name]} {\n"
"\n"
1266
1267
1268
1269
1270
1271
1272


1273
1274
1275
1276
1277
1278
1279
}
int Jim_stdlibInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
		return JIM_ERR;

	return Jim_EvalSource(interp, "stdlib.tcl", 1,


"\n"
"proc lambda {arglist args} {\n"
"	tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
"}\n"
"\n"
"proc lambda.finalizer {name val} {\n"
"	rename $name {}\n"







>
>







1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
}
int Jim_stdlibInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
		return JIM_ERR;

	return Jim_EvalSource(interp, "stdlib.tcl", 1,
"\n"
"\n"
"\n"
"proc lambda {arglist args} {\n"
"	tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
"}\n"
"\n"
"proc lambda.finalizer {name val} {\n"
"	rename $name {}\n"
1295
1296
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328



1329
1330
1331
1332
1333
1334
1335
1336

1337


1338
1339
1340
1341
1342
1343
1344
"proc function {value} {\n"
"	return $value\n"
"}\n"
"\n"
"\n"
"\n"
"\n"
"proc stacktrace {} {\n"
"	set trace {}\n"

"	foreach level [range 1 [info level]] {\n"
"		lassign [info frame -$level] p f l\n"
"		lappend trace $p $f $l\n"
"	}\n"
"	return $trace\n"
"}\n"
"\n"
"\n"
"proc stackdump {stacktrace} {\n"
"	set result {}\n"
"	set count 0\n"
"	foreach {l f p} [lreverse $stacktrace] {\n"
"		if {$count} {\n"
"			append result \\n\n"
"		}\n"
"		incr count\n"
"		if {$p ne \"\"} {\n"
"			append result \"in procedure '$p' \"\n"
"			if {$f ne \"\"} {\n"
"				append result \"called \"\n"
"			}\n"
"		}\n"
"		if {$f ne \"\"} {\n"
"			append result \"at file \\\"$f\\\", line $l\"\n"
"		}\n"



"	}\n"
"	return $result\n"
"}\n"
"\n"
"\n"
"\n"
"proc errorInfo {msg {stacktrace \"\"}} {\n"
"	if {$stacktrace eq \"\"} {\n"

"		set stacktrace [info stacktrace]\n"


"	}\n"
"	lassign $stacktrace p f l\n"
"	if {$f ne \"\"} {\n"
"		set result \"Runtime Error: $f:$l: \"\n"
"	}\n"
"	append result \"$msg\\n\"\n"
"	append result [stackdump $stacktrace]\n"







|

>
|
<
|






<
|

<
<
|
<

|

|



|

>
>
>

|






>

>
>







1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322

1323
1324


1325

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
"proc function {value} {\n"
"	return $value\n"
"}\n"
"\n"
"\n"
"\n"
"\n"
"proc stacktrace {{skip 0}} {\n"
"	set trace {}\n"
"	incr skip\n"
"	foreach level [range $skip [info level]] {\n"

"		lappend trace {*}[info frame -$level]\n"
"	}\n"
"	return $trace\n"
"}\n"
"\n"
"\n"
"proc stackdump {stacktrace} {\n"

"	set lines {}\n"
"	foreach {l f p} [lreverse $stacktrace] {\n"


"		set line {}\n"

"		if {$p ne \"\"} {\n"
"			append line \"in procedure '$p' \"\n"
"			if {$f ne \"\"} {\n"
"				append line \"called \"\n"
"			}\n"
"		}\n"
"		if {$f ne \"\"} {\n"
"			append line \"at file \\\"$f\\\", line $l\"\n"
"		}\n"
"		if {$line ne \"\"} {\n"
"			lappend lines $line\n"
"		}\n"
"	}\n"
"	join $lines \\n\n"
"}\n"
"\n"
"\n"
"\n"
"proc errorInfo {msg {stacktrace \"\"}} {\n"
"	if {$stacktrace eq \"\"} {\n"
"\n"
"		set stacktrace [info stacktrace]\n"
"\n"
"		lappend stacktrace {*}[stacktrace 1]\n"
"	}\n"
"	lassign $stacktrace p f l\n"
"	if {$f ne \"\"} {\n"
"		set result \"Runtime Error: $f:$l: \"\n"
"	}\n"
"	append result \"$msg\\n\"\n"
"	append result [stackdump $stacktrace]\n"
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382






















1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400



























































1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415

1416

1417
1418
1419
1420
1421
1422
1423
"			}\n"
"		}\n"
"	}\n"
"	return \"\"\n"
"}\n"
"\n"
"\n"
"proc {dict with} {dictVar args script} {\n"
"	upvar $dictVar dict\n"
"	set keys {}\n"
"	foreach {n v} [dict get $dict {*}$args] {\n"
"		upvar $n var_$n\n"
"		set var_$n $v\n"
"		lappend keys $n\n"
"	}\n"
"	catch {uplevel 1 $script} msg opts\n"
"	if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
"		foreach n $keys {\n"
"			if {[info exists var_$n]} {\n"
"				dict set dict {*}$args $n [set var_$n]\n"
"			} else {\n"
"				dict unset dict {*}$args $n\n"






















"			}\n"
"		}\n"
"	}\n"
"	return {*}$opts $msg\n"
"}\n"
"\n"
"\n"
"\n"
"proc {dict merge} {dict args} {\n"
"	foreach d $args {\n"
"\n"
"		dict size $d\n"
"		foreach {k v} $d {\n"
"			dict set dict $k $v\n"
"		}\n"
"	}\n"
"	return $dict\n"
"}\n"



























































);
}
int Jim_tclcompatInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
		return JIM_ERR;

	return Jim_EvalSource(interp, "tclcompat.tcl", 1,
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"

"set env [env]\n"

"\n"
"if {[info commands stdout] ne \"\"} {\n"
"\n"
"	foreach p {gets flush close eof seek tell} {\n"
"		proc $p {chan args} {p} {\n"
"			tailcall $chan $p {*}$args\n"
"		}\n"







|
<

|





|


|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>

>







1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
"			}\n"
"		}\n"
"	}\n"
"	return \"\"\n"
"}\n"
"\n"
"\n"
"proc {dict with} {&dictVar {args key} script} {\n"

"	set keys {}\n"
"	foreach {n v} [dict get $dictVar {*}$key] {\n"
"		upvar $n var_$n\n"
"		set var_$n $v\n"
"		lappend keys $n\n"
"	}\n"
"	catch {uplevel 1 $script} msg opts\n"
"	if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
"		foreach n $keys {\n"
"			if {[info exists var_$n]} {\n"
"				dict set dictVar {*}$key $n [set var_$n]\n"
"			} else {\n"
"				dict unset dictVar {*}$key $n\n"
"			}\n"
"		}\n"
"	}\n"
"	return {*}$opts $msg\n"
"}\n"
"\n"
"\n"
"proc {dict update} {&varName args script} {\n"
"	set keys {}\n"
"	foreach {n v} $args {\n"
"		upvar $v var_$v\n"
"		if {[dict exists $varName $n]} {\n"
"			set var_$v [dict get $varName $n]\n"
"		}\n"
"	}\n"
"	catch {uplevel 1 $script} msg opts\n"
"	if {[info exists varName]} {\n"
"		foreach {n v} $args {\n"
"			if {[info exists var_$v]} {\n"
"				dict set varName $n [set var_$v]\n"
"			} else {\n"
"				dict unset varName $n\n"
"			}\n"
"		}\n"
"	}\n"
"	return {*}$opts $msg\n"
"}\n"
"\n"
"\n"
"\n"
"proc {dict merge} {dict args} {\n"
"	foreach d $args {\n"
"\n"
"		dict size $d\n"
"		foreach {k v} $d {\n"
"			dict set dict $k $v\n"
"		}\n"
"	}\n"
"	return $dict\n"
"}\n"
"\n"
"proc {dict replace} {dictionary {args {key value}}} {\n"
"	if {[llength ${key value}] % 2} {\n"
"		tailcall {dict replace}\n"
"	}\n"
"	tailcall dict merge $dictionary ${key value}\n"
"}\n"
"\n"
"\n"
"proc {dict lappend} {varName key {args value}} {\n"
"	upvar $varName dict\n"
"	if {[exists dict] && [dict exists $dict $key]} {\n"
"		set list [dict get $dict $key]\n"
"	}\n"
"	lappend list {*}$value\n"
"	dict set dict $key $list\n"
"}\n"
"\n"
"\n"
"proc {dict append} {varName key {args value}} {\n"
"	upvar $varName dict\n"
"	if {[exists dict] && [dict exists $dict $key]} {\n"
"		set str [dict get $dict $key]\n"
"	}\n"
"	append str {*}$value\n"
"	dict set dict $key $str\n"
"}\n"
"\n"
"\n"
"proc {dict incr} {varName key {increment 1}} {\n"
"	upvar $varName dict\n"
"	if {[exists dict] && [dict exists $dict $key]} {\n"
"		set value [dict get $dict $key]\n"
"	}\n"
"	incr value $increment\n"
"	dict set dict $key $value\n"
"}\n"
"\n"
"\n"
"proc {dict remove} {dictionary {args key}} {\n"
"	foreach k $key {\n"
"		dict unset dictionary $k\n"
"	}\n"
"	return $dictionary\n"
"}\n"
"\n"
"\n"
"proc {dict values} {dictionary {pattern *}} {\n"
"	dict keys [lreverse $dictionary] $pattern\n"
"}\n"
"\n"
"\n"
"proc {dict for} {vars dictionary script} {\n"
"	if {[llength $vars] != 2} {\n"
"		return -code error \"must have exactly two variable names\"\n"
"	}\n"
"	dict size $dictionary\n"
"	tailcall foreach $vars $dictionary $script\n"
"}\n"
);
}
int Jim_tclcompatInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
		return JIM_ERR;

	return Jim_EvalSource(interp, "tclcompat.tcl", 1,
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"set env [env]\n"
"\n"
"\n"
"if {[info commands stdout] ne \"\"} {\n"
"\n"
"	foreach p {gets flush close eof seek tell} {\n"
"		proc $p {chan args} {p} {\n"
"			tailcall $chan $p {*}$args\n"
"		}\n"
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
"					return -code error \"fconfigure: unknown option $n\"\n"
"				}\n"
"			}\n"
"		}\n"
"	}\n"
"}\n"
"\n"
"\n"
"proc case {var args} {\n"
"\n"
"	if {[lindex $args 0] eq \"in\"} {\n"
"		set args [lrange $args 1 end]\n"
"	}\n"
"\n"
"\n"
"	if {[llength $args] == 1} {\n"
"		set args [lindex $args 0]\n"
"	}\n"
"\n"
"\n"
"	if {[llength $args] % 2 != 0} {\n"
"		return -code error \"extra case pattern with no body\"\n"
"	}\n"
"\n"
"\n"
"	local proc case.checker {value pattern} {\n"
"		string match $pattern $value\n"
"	}\n"
"\n"
"	foreach {value action} $args {\n"
"		if {$value eq \"default\"} {\n"
"			set do_action $action\n"
"			continue\n"
"		} elseif {[lsearch -bool -command case.checker $value $var]} {\n"
"			set do_action $action\n"
"			break\n"
"		}\n"
"	}\n"
"\n"
"	if {[info exists do_action]} {\n"
"		set rc [catch [list uplevel 1 $do_action] result opts]\n"
"		if {$rc} {\n"
"			incr opts(-level)\n"
"		}\n"
"		return {*}$opts $result\n"
"	}\n"
"}\n"
"\n"
"\n"
"proc fileevent {args} {\n"
"	tailcall {*}$args\n"
"}\n"
"\n"
"\n"
"\n"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1554
1555
1556
1557
1558
1559
1560









































1561
1562
1563
1564
1565
1566
1567
"					return -code error \"fconfigure: unknown option $n\"\n"
"				}\n"
"			}\n"
"		}\n"
"	}\n"
"}\n"
"\n"









































"\n"
"proc fileevent {args} {\n"
"	tailcall {*}$args\n"
"}\n"
"\n"
"\n"
"\n"
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543












1544
1545
1546
1547
1548
1549
1550
"	try {\n"
"		if {$force ni {{} -force}} {\n"
"			error \"bad option \\\"$force\\\": should be -force\"\n"
"		}\n"
"\n"
"		set in [open $source]\n"
"\n"
"		if {$force eq \"\" && [file exists $target]} {\n"
"			$in close\n"
"			error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"












"		}\n"
"		set out [open $target w]\n"
"		$in copyto $out\n"
"		$out close\n"
"	} on error {msg opts} {\n"
"		incr opts(-level)\n"
"		return {*}$opts $msg\n"







|
|
|
>
>
>
>
>
>
>
>
>
>
>
>







1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
"	try {\n"
"		if {$force ni {{} -force}} {\n"
"			error \"bad option \\\"$force\\\": should be -force\"\n"
"		}\n"
"\n"
"		set in [open $source]\n"
"\n"
"		if {[file exists $target]} {\n"
"			if {$force eq \"\"} {\n"
"				error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
"			}\n"
"\n"
"			if {$source eq $target} {\n"
"				return\n"
"			}\n"
"\n"
"\n"
"			file stat $source ss\n"
"			file stat $target ts\n"
"			if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n"
"				return\n"
"			}\n"
"		}\n"
"		set out [open $target w]\n"
"		$in copyto $out\n"
"		$out close\n"
"	} on error {msg opts} {\n"
"		incr opts(-level)\n"
"		return {*}$opts $msg\n"
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
"		$r close\n"
"		$w close\n"
"		error $error\n"
"	}\n"
"}\n"
"\n"
"\n"
"local proc pid {{chan {}}} {\n"
"	if {$chan eq \"\"} {\n"
"		tailcall upcall pid\n"
"	}\n"
"	if {[catch {$chan tell}]} {\n"
"		return -code error \"can not find channel named \\\"$chan\\\"\"\n"
"	}\n"
"	if {[catch {$chan pid} pids]} {\n"
"		return \"\"\n"
"	}\n"
"	return $pids\n"
"}\n"
"\n"
"\n"
"\n"







|
|


|
|

|







1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
"		$r close\n"
"		$w close\n"
"		error $error\n"
"	}\n"
"}\n"
"\n"
"\n"
"local proc pid {{channelId {}}} {\n"
"	if {$channelId eq \"\"} {\n"
"		tailcall upcall pid\n"
"	}\n"
"	if {[catch {$channelId tell}]} {\n"
"		return -code error \"can not find channel named \\\"$channelId\\\"\"\n"
"	}\n"
"	if {[catch {$channelId pid} pids]} {\n"
"		return \"\"\n"
"	}\n"
"	return $pids\n"
"}\n"
"\n"
"\n"
"\n"
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696




1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
"	}\n"
"	file delete $path\n"
"}\n"
);
}



#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>






#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#else
#define JIM_ANSIC
#endif








<




>
>
>
>







<







1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
"	}\n"
"	file delete $path\n"
"}\n"
);
}



#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <sys/stat.h>
#endif


#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#else
#define JIM_ANSIC
#endif

1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751


typedef struct AioFile
{
    FILE *fp;
    Jim_Obj *filename;
    int type;
    int OpenFlags;              
    int fd;
#ifdef O_NDELAY
    int flags;
#endif
    Jim_Obj *rEvent;
    Jim_Obj *wEvent;
    Jim_Obj *eEvent;
    int addr_family;
} AioFile;

static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);







|

<
<
<







1800
1801
1802
1803
1804
1805
1806
1807
1808



1809
1810
1811
1812
1813
1814
1815


typedef struct AioFile
{
    FILE *fp;
    Jim_Obj *filename;
    int type;
    int openFlags;              
    int fd;



    Jim_Obj *rEvent;
    Jim_Obj *wEvent;
    Jim_Obj *eEvent;
    int addr_family;
} AioFile;

static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796

static void JimAioDelProc(Jim_Interp *interp, void *privData)
{
    AioFile *af = privData;

    JIM_NOTUSED(interp);

    if (!(af->OpenFlags & AIO_KEEPOPEN)) {
        fclose(af->fp);
    }

    Jim_DecrRefCount(interp, af->filename);

#ifdef jim_ext_eventloop
    
    if (af->rEvent) {
        Jim_DeleteFileHandler(interp, af->fp);

    }
    if (af->wEvent) {
        Jim_DeleteFileHandler(interp, af->fp);
    }
    if (af->eEvent) {
        Jim_DeleteFileHandler(interp, af->fp);
    }
#endif
    Jim_Free(af);
}

static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
{
    if (!ferror(af->fp)) {
        return JIM_OK;







<
<
<
<




<
|
>
|
|
|

<
<
|
<







1829
1830
1831
1832
1833
1834
1835




1836
1837
1838
1839

1840
1841
1842
1843
1844
1845


1846

1847
1848
1849
1850
1851
1852
1853

static void JimAioDelProc(Jim_Interp *interp, void *privData)
{
    AioFile *af = privData;

    JIM_NOTUSED(interp);





    Jim_DecrRefCount(interp, af->filename);

#ifdef jim_ext_eventloop
    

    Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
#endif

    if (!(af->openFlags & AIO_KEEPOPEN)) {
        fclose(af->fp);
    }




    Jim_Free(af);
}

static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
{
    if (!ferror(af->fp)) {
        return JIM_OK;
2033
2034
2035
2036
2037
2038
2039






2040




2041









2042
2043
2044
2045
2046
2047
2048

    Jim_SetResultInt(interp, feof(af->fp));
    return JIM_OK;
}

static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{






    Jim_DeleteCommand(interp, Jim_String(argv[0]));




    return JIM_OK;









}

static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);
    int orig = SEEK_SET;
    jim_wide offset;







>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>







2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124

    Jim_SetResultInt(interp, feof(af->fp));
    return JIM_OK;
}

static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc == 3) {
#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
        static const char * const options[] = { "r", "w", NULL };
        enum { OPT_R, OPT_W, };
        int option;
        AioFile *af = Jim_CmdPrivData(interp);

        if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
            return JIM_ERR;
        }
        if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
            return JIM_OK;
        }
        JimAioSetError(interp, NULL);
#else
        Jim_SetResultString(interp, "async close not supported", -1);
#endif
        return JIM_ERR;
    }

    return Jim_DeleteCommand(interp, Jim_String(argv[0]));
}

static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);
    int orig = SEEK_SET;
    jim_wide offset;
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
}

#ifdef O_NDELAY
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);

    int fmode = af->flags;

    if (argc) {
        long nb;

        if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
            return JIM_ERR;
        }
        if (nb) {
            fmode |= O_NDELAY;
        }
        else {
            fmode &= ~O_NDELAY;
        }
        fcntl(af->fd, F_SETFL, fmode);
        af->flags = fmode;
    }
    Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
    return JIM_OK;
}
#endif

static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)







|













|
<







2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188
2189
}

#ifdef O_NDELAY
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);

    int fmode = fcntl(af->fd, F_GETFL);

    if (argc) {
        long nb;

        if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
            return JIM_ERR;
        }
        if (nb) {
            fmode |= O_NDELAY;
        }
        else {
            fmode &= ~O_NDELAY;
        }
        (void)fcntl(af->fd, F_SETFL, fmode);

    }
    Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
    return JIM_OK;
}
#endif

static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
    }
    return JIM_OK;
}

#ifdef jim_ext_eventloop
static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
{
    Jim_Obj *objPtr = clientData;

    Jim_DecrRefCount(interp, objPtr);

}

static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
{
    Jim_Obj *objPtr = clientData;

    return Jim_EvalObjBackground(interp, objPtr);
}

static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
    int argc, Jim_Obj * const *argv)
{
    int scriptlen = 0;

    if (argc == 0) {
        
        if (*scriptHandlerObj) {
            Jim_SetResult(interp, *scriptHandlerObj);
        }
        return JIM_OK;
    }

    if (*scriptHandlerObj) {
        
        Jim_DeleteFileHandler(interp, af->fp);
        *scriptHandlerObj = NULL;
    }

    
    Jim_GetString(argv[0], &scriptlen);
    if (scriptlen == 0) {
        
        return JIM_OK;
    }

    
    Jim_IncrRefCount(argv[0]);
    *scriptHandlerObj = argv[0];

    Jim_CreateFileHandler(interp, af->fp, mask,
        JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer);

    return JIM_OK;
}

static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);







|

|
>




|

|





<
<










|
<



<
|









|







2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242


2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
    }
    return JIM_OK;
}

#ifdef jim_ext_eventloop
static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
{
    Jim_Obj **objPtrPtr = clientData;

    Jim_DecrRefCount(interp, *objPtrPtr);
    *objPtrPtr = NULL;
}

static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
{
    Jim_Obj **objPtrPtr = clientData;

    return Jim_EvalObjBackground(interp, *objPtrPtr);
}

static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
    int argc, Jim_Obj * const *argv)
{


    if (argc == 0) {
        
        if (*scriptHandlerObj) {
            Jim_SetResult(interp, *scriptHandlerObj);
        }
        return JIM_OK;
    }

    if (*scriptHandlerObj) {
        
        Jim_DeleteFileHandler(interp, af->fp, mask);

    }

    

    if (Jim_Length(argv[0]) == 0) {
        
        return JIM_OK;
    }

    
    Jim_IncrRefCount(argv[0]);
    *scriptHandlerObj = argv[0];

    Jim_CreateFileHandler(interp, af->fp, mask,
        JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);

    return JIM_OK;
}

static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
    return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv);
}

static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);

    return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
}
#endif

static const jim_subcmd_type aio_command_table[] = {
    {   "read",
        "?-nonewline? ?len?",
        aio_cmd_read,







|







2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
    return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv);
}

static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);

    return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
}
#endif

static const jim_subcmd_type aio_command_table[] = {
    {   "read",
        "?-nonewline? ?len?",
        aio_cmd_read,
2266
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276

2277
2278
2279
2280
2281
2282
2283
        NULL,
        aio_cmd_eof,
        0,
        0,
        
    },
    {   "close",
        NULL,

        aio_cmd_close,
        0,
        0,

        JIM_MODFLAG_FULLARGV,
        
    },
    {   "seek",
        "offset ?start|current|end",
        aio_cmd_seek,
        1,







<
>


<
>







2338
2339
2340
2341
2342
2343
2344

2345
2346
2347

2348
2349
2350
2351
2352
2353
2354
2355
        NULL,
        aio_cmd_eof,
        0,
        0,
        
    },
    {   "close",

        "?r(ead)|w(rite)?",
        aio_cmd_close,
        0,

        1,
        JIM_MODFLAG_FULLARGV,
        
    },
    {   "seek",
        "offset ?start|current|end",
        aio_cmd_seek,
        1,
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363



2364
2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390

2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431

2432

2433











2434
2435
2436
2437

















































2438
2439
2440
2441

2442
2443
2444
2445
2446
2447
2448
    return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv);
}

static int JimAioOpenCommand(Jim_Interp *interp, int argc,
        Jim_Obj *const *argv)
{
    const char *mode;
    const char *filename;

    if (argc != 2 && argc != 3) {
        Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
        return JIM_ERR;
    }

    mode = (argc == 3) ? Jim_String(argv[2]) : "r";
    filename = Jim_String(argv[1]);

#ifdef jim_ext_tclcompat
    



    if (*filename == '|') {
        Jim_Obj *evalObj[3];

        evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
        evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
        evalObj[2] = Jim_NewStringObj(interp, mode, -1);

        return Jim_EvalObjVector(interp, 3, evalObj);

    }
#endif
    return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
}

static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
    const char *hdlfmt, int family, const char *mode)
{
    AioFile *af;
    char buf[AIO_CMD_LEN];
    int OpenFlags = 0;

    if (filename == NULL) {
        filename = Jim_NewStringObj(interp, hdlfmt, -1);

    }

    Jim_IncrRefCount(filename);

    if (fh == NULL) {

        if (fd < 0) {
            fh = fopen(Jim_String(filename), mode);
        }
        else {
            fh = fdopen(fd, mode);
        }
    }
    else {
        OpenFlags = AIO_KEEPOPEN;

    }

    if (fh == NULL) {
        JimAioSetError(interp, filename);
#if !defined(JIM_ANSIC)
        if (fd >= 0) {
            close(fd);
        }
#endif
        Jim_DecrRefCount(interp, filename);
        return JIM_ERR;

    }

    
    af = Jim_Alloc(sizeof(*af));
    memset(af, 0, sizeof(*af));
    af->fp = fh;
    af->fd = fileno(fh);
    af->filename = filename;
#ifdef FD_CLOEXEC
    if ((OpenFlags & AIO_KEEPOPEN) == 0) {
        fcntl(af->fd, F_SETFD, FD_CLOEXEC);
    }
#endif
    af->OpenFlags = OpenFlags;
#ifdef O_NDELAY
    af->flags = fcntl(af->fd, F_GETFL);
#endif
    af->addr_family = family;
    snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
    Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);


    Jim_SetResultString(interp, buf, -1);













    return JIM_OK;
}



















































FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
{
    Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);


    if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
        return ((AioFile *) cmdPtr->u.native.privData)->fp;
    }
    Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
    return NULL;
}








<







<


|
>
>
>
|
|

|
|
|

|
>










|

|

>





>
|
<
<
<


<
|
|
>
|
<
|
|

|
|
|

|
|
>









|
|


|
<
<
<




>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>







2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467



2468
2469

2470
2471
2472
2473

2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497



2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
    return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv);
}

static int JimAioOpenCommand(Jim_Interp *interp, int argc,
        Jim_Obj *const *argv)
{
    const char *mode;


    if (argc != 2 && argc != 3) {
        Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
        return JIM_ERR;
    }

    mode = (argc == 3) ? Jim_String(argv[2]) : "r";


#ifdef jim_ext_tclcompat
    {
        const char *filename = Jim_String(argv[1]);

        
        if (*filename == '|') {
            Jim_Obj *evalObj[3];

            evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
            evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
            evalObj[2] = Jim_NewStringObj(interp, mode, -1);

            return Jim_EvalObjVector(interp, 3, evalObj);
        }
    }
#endif
    return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
}

static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
    const char *hdlfmt, int family, const char *mode)
{
    AioFile *af;
    char buf[AIO_CMD_LEN];
    int openFlags = 0;

    if (fh) {
        filename = Jim_NewStringObj(interp, hdlfmt, -1);
        openFlags = AIO_KEEPOPEN;
    }

    Jim_IncrRefCount(filename);

    if (fh == NULL) {
#if !defined(JIM_ANSIC)
        if (fd >= 0) {



            fh = fdopen(fd, mode);
        }

        else
#endif
            fh = fopen(Jim_String(filename), mode);


        if (fh == NULL) {
            JimAioSetError(interp, filename);
#if !defined(JIM_ANSIC)
            if (fd >= 0) {
                close(fd);
            }
#endif
            Jim_DecrRefCount(interp, filename);
            return JIM_ERR;
        }
    }

    
    af = Jim_Alloc(sizeof(*af));
    memset(af, 0, sizeof(*af));
    af->fp = fh;
    af->fd = fileno(fh);
    af->filename = filename;
#ifdef FD_CLOEXEC
    if ((openFlags & AIO_KEEPOPEN) == 0) {
        (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
    }
#endif
    af->openFlags = openFlags;



    af->addr_family = family;
    snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
    Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);

    Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));

    return JIM_OK;
}

static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
    const char *hdlfmt, int family, const char *mode[2])
{
    if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
        Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
        Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));

        if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
            Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
            Jim_SetResult(interp, objPtr);
            return JIM_OK;
        }
    }

    
    close(p[0]);
    close(p[1]);
    JimAioSetError(interp, NULL);
    return JIM_ERR;
}


int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
{
#ifdef HAVE_MKSTEMP
    int fd;
    mode_t mask;
    Jim_Obj *filenameObj;

    if (template == NULL) {
        const char *tmpdir = getenv("TMPDIR");
        if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
            tmpdir = "/tmp/";
        }
        filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
        if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
            Jim_AppendString(interp, filenameObj, "/", 1);
        }
        Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
    }
    else {
        filenameObj = Jim_NewStringObj(interp, template, -1);
    }

    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);

    
    fd = mkstemp(filenameObj->bytes);
    umask(mask);
    if (fd < 0) {
        Jim_SetResultString(interp, "Failed to create tempfile", -1);
        Jim_FreeNewObj(interp, filenameObj);
        return -1;
    }

    Jim_SetResult(interp, filenameObj);
    return fd;
#else
    Jim_SetResultString(interp, "tempfile not supported", -1);
    return -1;
#endif
}

FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
{
    Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);

    
    if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
        return ((AioFile *) cmdPtr->u.native.privData)->fp;
    }
    Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
    return NULL;
}

2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
    
    JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
    JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
    JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");

    return JIM_OK;
}


#include <errno.h>
#include <stdio.h>
#include <string.h>


#ifdef HAVE_DIRENT_H







<







2592
2593
2594
2595
2596
2597
2598

2599
2600
2601
2602
2603
2604
2605
    
    JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
    JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
    JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");

    return JIM_OK;
}


#include <errno.h>
#include <stdio.h>
#include <string.h>


#ifdef HAVE_DIRENT_H
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518


2519

2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533




2534
2535
2536
2537
2538
2539
2540
    if (dirPtr == NULL) {
        if (nocomplain) {
            return JIM_OK;
        }
        Jim_SetResultString(interp, strerror(errno), -1);
        return JIM_ERR;
    }
    Jim_SetResultString(interp, strerror(errno), -1);

    Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));

    while ((entryPtr = readdir(dirPtr)) != NULL) {
        if (entryPtr->d_name[0] == '.') {
            if (entryPtr->d_name[1] == '\0') {
                continue;
            }
            if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
                continue;
        }
        Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
                entryPtr->d_name, -1));
    }
    closedir(dirPtr);



    return JIM_OK;

}

int Jim_readdirInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
    return JIM_OK;
}

#include <stdlib.h>
#include <string.h>






static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
    regfree(objPtr->internalRep.regexpValue.compre);
    Jim_Free(objPtr->internalRep.regexpValue.compre);
}








<
|
|

|
|
|
|
|
|
|
|
|
<
|
|

>
>
|
>














>
>
>
>







2627
2628
2629
2630
2631
2632
2633

2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645

2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
    if (dirPtr == NULL) {
        if (nocomplain) {
            return JIM_OK;
        }
        Jim_SetResultString(interp, strerror(errno), -1);
        return JIM_ERR;
    }

    else {
        Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);

        while ((entryPtr = readdir(dirPtr)) != NULL) {
            if (entryPtr->d_name[0] == '.') {
                if (entryPtr->d_name[1] == '\0') {
                    continue;
                }
                if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
                    continue;
            }
            Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));

        }
        closedir(dirPtr);

        Jim_SetResult(interp, listObj);

        return JIM_OK;
    }
}

int Jim_readdirInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
    return JIM_OK;
}

#include <stdlib.h>
#include <string.h>

#if defined(JIM_REGEXP)
#else
    #include <regex.h>
#endif

static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
    regfree(objPtr->internalRep.regexpValue.compre);
    Jim_Free(objPtr->internalRep.regexpValue.compre);
}

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112





















3113

3114
3115
3116

3117
3118
3119
3120
3121

3122
3123


3124
3125
3126
3127

3128
3129
3130
3131
3132
3133
3134
3135
    else if (S_ISSOCK(mode)) {
        return "socket";
    }
#endif
    return "unknown";
}


static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
    jim_wide value)
{
    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
    Jim_Obj *valobj = Jim_NewWideObj(interp, value);

    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
        Jim_FreeObj(interp, nameobj);
        Jim_FreeObj(interp, valobj);
        return JIM_ERR;
    }
    return JIM_OK;
}

static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
    const char *value)
{
    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
    Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);

    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
        Jim_FreeObj(interp, nameobj);
        Jim_FreeObj(interp, valobj);
        return JIM_ERR;
    }
    return JIM_OK;
}

static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
{
    if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {





















        Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);

        return JIM_ERR;
    }
    set_array_int_value(interp, varName, "ino", sb->st_ino);

    set_array_int_value(interp, varName, "mode", sb->st_mode);
    set_array_int_value(interp, varName, "nlink", sb->st_nlink);
    set_array_int_value(interp, varName, "uid", sb->st_uid);
    set_array_int_value(interp, varName, "gid", sb->st_gid);
    set_array_int_value(interp, varName, "size", sb->st_size);

    set_array_int_value(interp, varName, "atime", sb->st_atime);
    set_array_int_value(interp, varName, "mtime", sb->st_mtime);


    set_array_int_value(interp, varName, "ctime", sb->st_ctime);
    set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));

    

    Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));

    return JIM_OK;
}

static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    const char *path = Jim_String(argv[0]);







|
<
<

|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|
>
|
|
|
|
|
>
|
|
>
>
|
<
|
|
>
|







3211
3212
3213
3214
3215
3216
3217
3218


3219
3220

3221




















3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264

3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
    else if (S_ISSOCK(mode)) {
        return "socket";
    }
#endif
    return "unknown";
}

static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)


{
    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));

    Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));




















}

static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
{
    
    Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);

    AppendStatElement(interp, listObj, "dev", sb->st_dev);
    AppendStatElement(interp, listObj, "ino", sb->st_ino);
    AppendStatElement(interp, listObj, "mode", sb->st_mode);
    AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
    AppendStatElement(interp, listObj, "uid", sb->st_uid);
    AppendStatElement(interp, listObj, "gid", sb->st_gid);
    AppendStatElement(interp, listObj, "size", sb->st_size);
    AppendStatElement(interp, listObj, "atime", sb->st_atime);
    AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
    AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));

    
    if (varName) {
        Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
        if (objPtr) {
            if (Jim_DictSize(interp, objPtr) < 0) {
                
                Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
                Jim_FreeNewObj(interp, listObj);
                return JIM_ERR;
            }

            if (Jim_IsShared(objPtr))
                objPtr = Jim_DuplicateObj(interp, objPtr);

            
            Jim_ListAppendList(interp, objPtr, listObj);
            Jim_DictSize(interp, objPtr);
            Jim_InvalidateStringRep(objPtr);

            Jim_FreeNewObj(interp, listObj);
            listObj = objPtr;
        }
        Jim_SetVariable(interp, varName, listObj);

    }

    
    Jim_SetResult(interp, listObj);

    return JIM_OK;
}

static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    const char *path = Jim_String(argv[0]);
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309

3310
3311
3312
3313
3314
3315
3316
    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));

    return JIM_OK;
}

static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
{
    const char *path = Jim_String(filename);
    int rc = access(path, mode);

    Jim_SetResultBool(interp, rc != -1);

    return JIM_OK;
}

static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    return file_access(interp, argv[0], R_OK);
}

static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    return file_access(interp, argv[0], W_OK);
}

static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef X_OK
    return file_access(interp, argv[0], X_OK);
#else

    Jim_SetResultBool(interp, 1);
    return JIM_OK;
#endif
}

static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{







<
<
<
|



















>







3420
3421
3422
3423
3424
3425
3426



3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));

    return JIM_OK;
}

static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
{



    Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);

    return JIM_OK;
}

static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    return file_access(interp, argv[0], R_OK);
}

static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    return file_access(interp, argv[0], W_OK);
}

static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef X_OK
    return file_access(interp, argv[0], X_OK);
#else
    
    Jim_SetResultBool(interp, 1);
    return JIM_OK;
#endif
}

static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
            return JIM_ERR;
        }
        argv++;
    }
    return JIM_OK;
}

#ifdef HAVE_MKSTEMP
static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int fd;
    char *filename;
    const char *template = "/tmp/tcl.tmp.XXXXXX";

    if (argc >= 1) {
        template = Jim_String(argv[0]);
    }
    filename = Jim_StrDup(template);

    fd = mkstemp(filename);
    if (fd < 0) {
        Jim_SetResultString(interp, "Failed to create tempfile", -1);
        return JIM_ERR;
    }
    close(fd);

    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
    return JIM_OK;
}
#endif

static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    const char *source;
    const char *dest;
    int force = 0;








<


<
<
<
|
<
<
|
<
<
<

<




<


<







3545
3546
3547
3548
3549
3550
3551

3552
3553



3554


3555



3556

3557
3558
3559
3560

3561
3562

3563
3564
3565
3566
3567
3568
3569
            return JIM_ERR;
        }
        argv++;
    }
    return JIM_OK;
}


static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{



    int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);






    if (fd < 0) {

        return JIM_ERR;
    }
    close(fd);


    return JIM_OK;
}


static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    const char *source;
    const char *dest;
    int force = 0;

3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495



3496
3497
3498
3499
3500
3501
3502
    if (stat(path, sb) == -1) {
        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    return JIM_OK;
}

#ifndef HAVE_LSTAT
#define lstat stat
#endif

static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
{
    const char *path = Jim_String(filename);

    if (lstat(path, sb) == -1) {
        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    return JIM_OK;
}




static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;







|
<
<
<










>
>
>







3601
3602
3603
3604
3605
3606
3607
3608



3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
    if (stat(path, sb) == -1) {
        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    return JIM_OK;
}

#ifdef HAVE_LSTAT



static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
{
    const char *path = Jim_String(filename);

    if (lstat(path, sb) == -1) {
        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    return JIM_OK;
}
#else
#define file_lstat file_stat
#endif

static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
3617
3618
3619
3620
3621
3622
3623

3624
3625
3626
3627
3628
3629
3630
3631
3632



3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
    return JIM_OK;
}


static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    return StoreStatData(interp, argv[1], &sb);
}




static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    return StoreStatData(interp, argv[1], &sb);
}

static const jim_subcmd_type file_command_table[] = {
    {   "atime",
        "name",
        file_cmd_atime,
        1,







>







|

>
>
>








|







3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
    return JIM_OK;
}

#ifdef HAVE_LSTAT
static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}
#else
#define file_cmd_lstat file_cmd_stat
#endif

static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
    return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}

static const jim_subcmd_type file_command_table[] = {
    {   "atime",
        "name",
        file_cmd_atime,
        1,
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
    {   "mkdir",
        "dir ...",
        file_cmd_mkdir,
        1,
        -1,
        
    },
#ifdef HAVE_MKSTEMP
    {   "tempfile",
        "?template?",
        file_cmd_tempfile,
        0,
        1,
        
    },
#endif
    {   "rename",
        "?-force? source dest",
        file_cmd_rename,
        2,
        3,
        
    },







<







<







3873
3874
3875
3876
3877
3878
3879

3880
3881
3882
3883
3884
3885
3886

3887
3888
3889
3890
3891
3892
3893
    {   "mkdir",
        "dir ...",
        file_cmd_mkdir,
        1,
        -1,
        
    },

    {   "tempfile",
        "?template?",
        file_cmd_tempfile,
        0,
        1,
        
    },

    {   "rename",
        "?-force? source dest",
        file_cmd_rename,
        2,
        3,
        
    },
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785

3786
3787
3788
3789
3790
3791
3792

3793
3794
3795
3796
3797
3798
3799
        "name",
        file_cmd_size,
        1,
        1,
        
    },
    {   "stat",
        "name var",
        file_cmd_stat,
        2,

        2,
        
    },
    {   "lstat",
        "name var",
        file_cmd_lstat,
        2,

        2,
        
    },
    {   "type",
        "name",
        file_cmd_type,
        1,







|

<
>




|

<
>







3904
3905
3906
3907
3908
3909
3910
3911
3912

3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
3925
3926
3927
        "name",
        file_cmd_size,
        1,
        1,
        
    },
    {   "stat",
        "name ?var?",
        file_cmd_stat,

        1,
        2,
        
    },
    {   "lstat",
        "name ?var?",
        file_cmd_lstat,

        1,
        2,
        
    },
    {   "type",
        "name",
        file_cmd_type,
        1,
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856

3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
        return JIM_ERR;
    }
    return JIM_OK;
}

static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    const int cwd_len = 2048;
    char *cwd = malloc(cwd_len);

    if (getcwd(cwd, cwd_len) == NULL) {
        Jim_SetResultString(interp, "Failed to get pwd", -1);

        return JIM_ERR;
    }
#if defined(__MINGW32__) || defined(_MSC_VER)
    {
        
        char *p = cwd;
        while ((p = strchr(p, '\\')) != NULL) {
            *p++ = '/';
        }
    }
#endif

    Jim_SetResultString(interp, cwd, -1);

    free(cwd);
    return JIM_OK;
}

int Jim_fileInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG))
        return JIM_ERR;







<
|

|

>














|







3973
3974
3975
3976
3977
3978
3979

3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
        return JIM_ERR;
    }
    return JIM_OK;
}

static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{

    char *cwd = Jim_Alloc(MAXPATHLEN);

    if (getcwd(cwd, MAXPATHLEN) == NULL) {
        Jim_SetResultString(interp, "Failed to get pwd", -1);
        Jim_Free(cwd);
        return JIM_ERR;
    }
#if defined(__MINGW32__) || defined(_MSC_VER)
    {
        
        char *p = cwd;
        while ((p = strchr(p, '\\')) != NULL) {
            *p++ = '/';
        }
    }
#endif

    Jim_SetResultString(interp, cwd, -1);

    Jim_Free(cwd);
    return JIM_OK;
}

int Jim_fileInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG))
        return JIM_ERR;
3933
3934
3935
3936
3937
3938
3939

3940
3941
3942
3943
3944
3945
3946
    return JIM_OK;
}

int Jim_execInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
    return JIM_OK;
}
#else


#include <errno.h>







>







4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
    return JIM_OK;
}

int Jim_execInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
    return JIM_OK;
}
#else


#include <errno.h>
3976
3977
3978
3979
3980
3981
3982

3983
3984
3985
3986
3987
3988
3989
    static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
        fdtype inputId, fdtype outputId, fdtype errorId);
    static int JimErrno(void);
#else
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/wait.h>


    typedef int fdtype;
    typedef int pidtype;
    #define JimPipe pipe
    #define JimErrno() errno
    #define JIM_BAD_FD -1
    #define JIM_BAD_PID -1







>







4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
    static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
        fdtype inputId, fdtype outputId, fdtype errorId);
    static int JimErrno(void);
#else
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <sys/stat.h>

    typedef int fdtype;
    typedef int pidtype;
    #define JimPipe pipe
    #define JimErrno() errno
    #define JIM_BAD_FD -1
    #define JIM_BAD_PID -1
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
static const char *JimStrError(void);
static char **JimSaveEnv(char **env);
static void JimRestoreEnv(char **env);
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
    pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents);
static fdtype JimOpenForWrite(const char *filename, int append);
static int JimRewindFd(fdtype fd);

static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
{
    Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
}







|







4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
static const char *JimStrError(void);
static char **JimSaveEnv(char **env);
static void JimRestoreEnv(char **env);
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
    pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
static fdtype JimOpenForWrite(const char *filename, int append);
static int JimRewindFd(fdtype fd);

static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
{
    Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
}
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086

4087
4088
4089
4090
4091
4092
4093
        }
    }
    Jim_RemoveTrailingNewline(strObj);
    fclose(fh);
    return JIM_OK;
}

static void JimTrimTrailingNewline(Jim_Interp *interp)
{
    int len;
    const char *p = Jim_GetString(Jim_GetResult(interp), &len);

    if (len > 0 && p[len - 1] == '\n') {
        Jim_SetResultString(interp, p, len - 1);
    }
}

static char **JimBuildEnv(Jim_Interp *interp)
{
#if defined(jim_ext_tclcompat)
    int i;
    int size;
    int num;
    int n;
    char **envptr;
    char *envdata;

    Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);

    if (!objPtr) {
        return Jim_GetEnviron();
    }


    
    num = Jim_ListLength(interp, objPtr);
    if (num % 2) {

        num--;
    }
    size = Jim_Length(objPtr) + 2;

    envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
    envdata = (char *)&envptr[num / 2 + 1];








<
<
<
<
<
<
<
<
<
<


<

















>







4180
4181
4182
4183
4184
4185
4186










4187
4188

4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
        }
    }
    Jim_RemoveTrailingNewline(strObj);
    fclose(fh);
    return JIM_OK;
}











static char **JimBuildEnv(Jim_Interp *interp)
{

    int i;
    int size;
    int num;
    int n;
    char **envptr;
    char *envdata;

    Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);

    if (!objPtr) {
        return Jim_GetEnviron();
    }


    
    num = Jim_ListLength(interp, objPtr);
    if (num % 2) {
        
        num--;
    }
    size = Jim_Length(objPtr) + 2;

    envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
    envdata = (char *)&envptr[num / 2 + 1];

4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
        envdata++;
        n++;
    }
    envptr[n] = NULL;
    *envdata = 0;

    return envptr;
#else
    return Jim_GetEnviron();
#endif
}

static void JimFreeEnv(char **env, char **original_environ)
{
#ifdef jim_ext_tclcompat
    if (env != original_environ) {
        Jim_Free(env);
    }
#endif
}

static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
{
    Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
    int rc = JIM_ERR;








<
<
<




<



<







4226
4227
4228
4229
4230
4231
4232



4233
4234
4235
4236

4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
        envdata++;
        n++;
    }
    envptr[n] = NULL;
    *envdata = 0;

    return envptr;



}

static void JimFreeEnv(char **env, char **original_environ)
{

    if (env != original_environ) {
        Jim_Free(env);
    }

}

static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
{
    Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
    int rc = JIM_ERR;

4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
    Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
    return rc;
}


struct WaitInfo
{
    pidtype pid;                    
    int status;                 
    int flags;                  
};

struct WaitInfoTable {
    struct WaitInfo *info;
    int size;
    int used;
};


#define WI_DETACHED 2

#define WAIT_TABLE_GROW_BY 4








|





|
|
|







4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
    Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
    return rc;
}


struct WaitInfo
{
    pidtype pid;                
    int status;                 
    int flags;                  
};

struct WaitInfoTable {
    struct WaitInfo *info;      
    int size;                   
    int used;                   
};


#define WI_DETACHED 2

#define WAIT_TABLE_GROW_BY 4

4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
    table->size = table->used = 0;

    return table;
}

static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    fdtype outputId;               /* File id for output pipe.  -1
                                 * means command overrode. */
    fdtype errorId;                /* File id for temporary file
                                 * containing error output. */
    pidtype *pidPtr;
    int numPids, result;

    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
        Jim_Obj *listObj;
        int i;








|
<
|
<







4320
4321
4322
4323
4324
4325
4326
4327

4328

4329
4330
4331
4332
4333
4334
4335
    table->size = table->used = 0;

    return table;
}

static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    fdtype outputId;    

    fdtype errorId;     

    pidtype *pidPtr;
    int numPids, result;

    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
        Jim_Obj *listObj;
        int i;

4259
4260
4261
4262
4263
4264
4265

4266
4267
4268
4269
4270


4271
4272
4273
4274
4275
4276
4277
4278
4279

4280
4281




4282
4283
4284
4285
4286
4287
4288
    return result;
}

static void JimReapDetachedPids(struct WaitInfoTable *table)
{
    struct WaitInfo *waitPtr;
    int count;


    if (!table) {
        return;
    }



    for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
        if (waitPtr->flags & WI_DETACHED) {
            int status;
            pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
            if (pid != JIM_BAD_PID) {
                if (waitPtr != &table->info[table->used - 1]) {
                    *waitPtr = table->info[table->used - 1];
                }
                table->used--;

            }
        }




    }
}

static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
{
    int i;








>





>
>
|



|
<
<
|

>


>
>
>
>







4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391


4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
    return result;
}

static void JimReapDetachedPids(struct WaitInfoTable *table)
{
    struct WaitInfo *waitPtr;
    int count;
    int dest;

    if (!table) {
        return;
    }

    waitPtr = table->info;
    dest = 0;
    for (count = table->used; count > 0; waitPtr++, count--) {
        if (waitPtr->flags & WI_DETACHED) {
            int status;
            pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
            if (pid == waitPtr->pid) {


                
                table->used--;
                continue;
            }
        }
        if (waitPtr != &table->info[dest]) {
            table->info[dest] = *waitPtr;
        }
        dest++;
    }
}

static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
{
    int i;

4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
            return pid;
        }
    }

    
    return JIM_BAD_PID;
}


static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
{
    int j;
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);

    for (j = 0; j < numPids; j++) {







<







4419
4420
4421
4422
4423
4424
4425

4426
4427
4428
4429
4430
4431
4432
            return pid;
        }
    }

    
    return JIM_BAD_PID;
}


static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
{
    int j;
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);

    for (j = 0; j < numPids; j++) {
4345
4346
4347
4348
4349
4350
4351

4352
4353
4354
4355
4356
4357
4358
    int numPids = 0;            /* Actual number of processes that exist
                                 * at *pidPtr right now. */
    int cmdCount;               /* Count of number of distinct commands
                                 * found in argc/argv. */
    const char *input = NULL;   /* Describes input for pipeline, depending
                                 * on "inputFile".  NULL means take input
                                 * from stdin/pipe. */


#define FILE_NAME   0           
#define FILE_APPEND 1           
#define FILE_HANDLE 2           
#define FILE_TEXT   3           

    int inputFile = FILE_NAME;  /* 1 means input is name of input file.







>







4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
    int numPids = 0;            /* Actual number of processes that exist
                                 * at *pidPtr right now. */
    int cmdCount;               /* Count of number of distinct commands
                                 * found in argc/argv. */
    const char *input = NULL;   /* Describes input for pipeline, depending
                                 * on "inputFile".  NULL means take input
                                 * from stdin/pipe. */
    int input_len = 0;          

#define FILE_NAME   0           
#define FILE_APPEND 1           
#define FILE_HANDLE 2           
#define FILE_TEXT   3           

    int inputFile = FILE_NAME;  /* 1 means input is name of input file.
4410
4411
4412
4413
4414
4415
4416

4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
        const char *arg = Jim_String(argv[i]);

        if (arg[0] == '<') {
            inputFile = FILE_NAME;
            input = arg + 1;
            if (*input == '<') {
                inputFile = FILE_TEXT;

                input++;
            }
            else if (*input == '@') {
                inputFile = FILE_HANDLE;
                input++;
            }

            if (!*input && ++i < argc) {
                input = Jim_String(argv[i]);
            }
        }
        else if (arg[0] == '>') {
            int dup_error = 0;

            outputFile = FILE_NAME;








>








|







4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
        const char *arg = Jim_String(argv[i]);

        if (arg[0] == '<') {
            inputFile = FILE_NAME;
            input = arg + 1;
            if (*input == '<') {
                inputFile = FILE_TEXT;
                input_len = Jim_Length(argv[i]) - 2;
                input++;
            }
            else if (*input == '@') {
                inputFile = FILE_HANDLE;
                input++;
            }

            if (!*input && ++i < argc) {
                input = Jim_GetString(argv[i], &input_len);
            }
        }
        else if (arg[0] == '>') {
            int dup_error = 0;

            outputFile = FILE_NAME;

4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
    }

    
    save_environ = JimSaveEnv(JimBuildEnv(interp));

    if (input != NULL) {
        if (inputFile == FILE_TEXT) {
            inputId = JimCreateTemp(interp, input);
            if (inputId == JIM_BAD_FD) {
                goto error;
            }
        }
        else if (inputFile == FILE_HANDLE) {
            
            FILE *fh = JimGetAioFilehandle(interp, input);







|







4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
    }

    
    save_environ = JimSaveEnv(JimBuildEnv(interp));

    if (input != NULL) {
        if (inputFile == FILE_TEXT) {
            inputId = JimCreateTemp(interp, input, input_len);
            if (inputId == JIM_BAD_FD) {
                goto error;
            }
        }
        else if (inputFile == FILE_HANDLE) {
            
            FILE *fh = JimGetAioFilehandle(interp, input);
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
            if (errorId == JIM_BAD_FD) {
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
                goto error;
            }
        }
    }
    else if (errFilePtr != NULL) {
        errorId = JimCreateTemp(interp, NULL);
        if (errorId == JIM_BAD_FD) {
            goto error;
        }
        *errFilePtr = JimDupFd(errorId);
    }









|







4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
            if (errorId == JIM_BAD_FD) {
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
                goto error;
            }
        }
    }
    else if (errFilePtr != NULL) {
        errorId = JimCreateTemp(interp, NULL, 0);
        if (errorId == JIM_BAD_FD) {
            goto error;
        }
        *errFilePtr = JimDupFd(errorId);
    }


4623
4624
4625
4626
4627
4628
4629





4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662



4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
                Jim_SetResultErrno(interp, "couldn't create pipe");
                goto error;
            }
            outputId = pipeIds[1];
        }

        






#ifdef __MINGW32__
        pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
        if (pid == JIM_BAD_PID) {
            Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
            goto error;
        }
#else
        if (table->info == NULL) {
            (void)signal(SIGPIPE, SIG_IGN);
        }

        
        if (pipe_dup_err) {
            errorId = outputId;
        }

        pid = vfork();
        if (pid < 0) {
            Jim_SetResultErrno(interp, "couldn't fork child process");
            goto error;
        }
        if (pid == 0) {
            

            if (inputId != -1) dup2(inputId, 0);
            if (outputId != -1) dup2(outputId, 1);
            if (errorId != -1) dup2(errorId, 2);

            for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
                close(i);
            }




            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());

            
            fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
            _exit(127);
        }
#endif

        

        if (table->used == table->size) {







>
>
>
>
>








<
<
<
<
<
<
<
<
<
















>
>
>



|







4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762









4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
                Jim_SetResultErrno(interp, "couldn't create pipe");
                goto error;
            }
            outputId = pipeIds[1];
        }

        
        if (pipe_dup_err) {
            errorId = outputId;
        }

        

#ifdef __MINGW32__
        pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
        if (pid == JIM_BAD_PID) {
            Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
            goto error;
        }
#else









        pid = vfork();
        if (pid < 0) {
            Jim_SetResultErrno(interp, "couldn't fork child process");
            goto error;
        }
        if (pid == 0) {
            

            if (inputId != -1) dup2(inputId, 0);
            if (outputId != -1) dup2(outputId, 1);
            if (errorId != -1) dup2(errorId, 2);

            for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
                close(i);
            }

            
            (void)signal(SIGPIPE, SIG_DFL);

            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());

            
            fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
            _exit(127);
        }
#endif

        

        if (table->used == table->size) {
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780





4781
4782
4783
4784
4785
4786
4787
    if (errorId != JIM_BAD_FD) {
        JimRewindFd(errorId);
        if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
            result = JIM_ERR;
        }
    }

    JimTrimTrailingNewline(interp);

    return result;
}

int Jim_execInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
        return JIM_ERR;





    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
    return JIM_OK;
}

#if defined(__MINGW32__)









|








>
>
>
>
>







4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
    if (errorId != JIM_BAD_FD) {
        JimRewindFd(errorId);
        if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
            result = JIM_ERR;
        }
    }

    Jim_RemoveTrailingNewline(Jim_GetResult(interp));

    return result;
}

int Jim_execInit(Jim_Interp *interp)
{
    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
        return JIM_ERR;

#ifdef SIGPIPE
    (void)signal(SIGPIPE, SIG_IGN);
#endif

    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
    return JIM_OK;
}

#if defined(__MINGW32__)


4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
    }
    GetExitCodeProcess(pid, &ret);
    *status = ret;
    CloseHandle(pid);
    return pid;
}

static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
{
    char name[MAX_PATH];
    HANDLE handle;

    if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
        return JIM_BAD_FD;
    }







|







5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
    }
    GetExitCodeProcess(pid, &ret);
    *status = ret;
    CloseHandle(pid);
    return pid;
}

static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
{
    char name[MAX_PATH];
    HANDLE handle;

    if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
        return JIM_BAD_FD;
    }
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
    if (contents != NULL) {
        
        FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
        if (fh == NULL) {
            goto error;
        }

        if (fwrite(contents, strlen(contents), 1, fh) != 1) {
            fclose(fh);
            goto error;
        }
        fseek(fh, 0, SEEK_SET);
        fclose(fh);
    }
    return handle;







|







5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
    if (contents != NULL) {
        
        FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
        if (fh == NULL) {
            goto error;
        }

        if (fwrite(contents, len, 1, fh) != 1) {
            fclose(fh);
            goto error;
        }
        fseek(fh, 0, SEEK_SET);
        fclose(fh);
    }
    return handle;
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
static pidtype
JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
{
    STARTUPINFO startInfo;
    PROCESS_INFORMATION procInfo;
    HANDLE hProcess, h;
    char execPath[MAX_PATH];
    char *originalName;
    pidtype pid = JIM_BAD_PID;
    Jim_Obj *cmdLineObj;

    if (JimWinFindExecutable(argv[0], execPath) < 0) {
        return JIM_BAD_PID;
    }
    originalName = argv[0];
    argv[0] = execPath;

    hProcess = GetCurrentProcess();
    cmdLineObj = JimWinBuildCommandLine(interp, argv);


    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    startInfo.dwFlags   = STARTF_USESTDHANDLES;
    startInfo.hStdInput	= INVALID_HANDLE_VALUE;
    startInfo.hStdOutput= INVALID_HANDLE_VALUE;
    startInfo.hStdError = INVALID_HANDLE_VALUE;

    if (inputId == JIM_BAD_FD) {
        if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
            CloseHandle(h);
        }







<






<









|







5226
5227
5228
5229
5230
5231
5232

5233
5234
5235
5236
5237
5238

5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
static pidtype
JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
{
    STARTUPINFO startInfo;
    PROCESS_INFORMATION procInfo;
    HANDLE hProcess, h;
    char execPath[MAX_PATH];

    pidtype pid = JIM_BAD_PID;
    Jim_Obj *cmdLineObj;

    if (JimWinFindExecutable(argv[0], execPath) < 0) {
        return JIM_BAD_PID;
    }

    argv[0] = execPath;

    hProcess = GetCurrentProcess();
    cmdLineObj = JimWinBuildCommandLine(interp, argv);


    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    startInfo.dwFlags   = STARTF_USESTDHANDLES;
    startInfo.hStdInput = INVALID_HANDLE_VALUE;
    startInfo.hStdOutput= INVALID_HANDLE_VALUE;
    startInfo.hStdError = INVALID_HANDLE_VALUE;

    if (inputId == JIM_BAD_FD) {
        if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
            CloseHandle(h);
        }
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
}

static int JimRewindFd(int fd)
{
    return lseek(fd, 0L, SEEK_SET);
}

static int JimCreateTemp(Jim_Interp *interp, const char *contents)
{
    char inName[] = "/tmp/tcl.tmp.XXXXXX";

    int fd = mkstemp(inName);
    if (fd == JIM_BAD_FD) {
        Jim_SetResultErrno(interp, "couldn't create temp file");
        return -1;
    }
    unlink(inName);
    if (contents) {
        int length = strlen(contents);
        if (write(fd, contents, length) != length) {
            Jim_SetResultErrno(interp, "couldn't write temp file");
            close(fd);
            return -1;
        }
        lseek(fd, 0L, SEEK_SET);
    }
    return fd;







|

|

<




|

<
|







5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326

5327
5328
5329
5330
5331
5332

5333
5334
5335
5336
5337
5338
5339
5340
}

static int JimRewindFd(int fd)
{
    return lseek(fd, 0L, SEEK_SET);
}

static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
{
    int fd = Jim_MakeTempFile(interp, NULL);


    if (fd == JIM_BAD_FD) {
        Jim_SetResultErrno(interp, "couldn't create temp file");
        return -1;
    }
    unlink(Jim_String(Jim_GetResult(interp)));
    if (contents) {

        if (write(fd, contents, len) != len) {
            Jim_SetResultErrno(interp, "couldn't write temp file");
            close(fd);
            return -1;
        }
        lseek(fd, 0L, SEEK_SET);
    }
    return fd;
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
    JimFreeEnv(Jim_GetEnviron(), env);
    Jim_SetEnviron(env);
}
#endif
#endif



#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>







<







5352
5353
5354
5355
5356
5357
5358

5359
5360
5361
5362
5363
5364
5365
    JimFreeEnv(Jim_GetEnviron(), env);
    Jim_SetEnviron(env);
}
#endif
#endif



#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276



5277
5278
5279
5280
5281
5282
5283
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    
    char buf[100];
    time_t t;
    long seconds;

    const char *format = "%a %b  %d %H:%M:%S %Z %Y";

    if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
        return -1;
    }

    if (argc == 3) {
        format = Jim_String(argv[2]);
    }

    if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
        return JIM_ERR;
    }
    t = seconds;

    strftime(buf, sizeof(buf), format, localtime(&t));




    Jim_SetResultString(interp, buf, -1);

    return JIM_OK;
}

#ifdef HAVE_STRPTIME







|














|
>
>
>







5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    
    char buf[100];
    time_t t;
    long seconds;

    const char *format = "%a %b %d %H:%M:%S %Z %Y";

    if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
        return -1;
    }

    if (argc == 3) {
        format = Jim_String(argv[2]);
    }

    if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
        return JIM_ERR;
    }
    t = seconds;

    if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
        Jim_SetResultString(interp, "format string too long", -1);
        return JIM_ERR;
    }

    Jim_SetResultString(interp, buf, -1);

    return JIM_OK;
}

#ifdef HAVE_STRPTIME
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413

5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429

5430
5431
5432
5433
5434
5435

5436
5437
5438
5439
5440
5441
5442
5443
    if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
    return JIM_OK;
}


#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>


static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    
    Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
    return JIM_OK;
}

static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);


    if (!objPtr) {
        return JIM_OK;
    }

    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
        
        if (Jim_IsList(objPtr)) {
            if (Jim_ListLength(interp, objPtr) % 2 != 0) {
                
                return JIM_ERR;
            }
        }
        else if (Jim_DictSize(interp, objPtr) < 0) {
            
            return JIM_ERR;

        }
        Jim_SetResult(interp, objPtr);
        return JIM_OK;
    }

    

    return Jim_DictValues(interp, objPtr, argv[1]);
}

static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);

    if (!objPtr) {







<

















>





<
|
<
<
|
<
|
<
<
|
<
>
|
|
|
|
|
|
>
|







5511
5512
5513
5514
5515
5516
5517

5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540

5541


5542

5543


5544

5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
    if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
    return JIM_OK;
}


#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>


static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    
    Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
    return JIM_OK;
}

static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
    Jim_Obj *patternObj;

    if (!objPtr) {
        return JIM_OK;
    }


    patternObj = (argc == 1) ? NULL : argv[1];




    


    if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {

        if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
            
            Jim_SetResult(interp, objPtr);
            return JIM_OK;
        }
    }

    
    return Jim_DictValues(interp, objPtr, patternObj);
}

static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);

    if (!objPtr) {
5458
5459
5460
5461
5462
5463
5464





5465
5466
5467
5468
5469
5470
5471
    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
        
        Jim_UnsetVariable(interp, argv[0], JIM_NONE);
        return JIM_OK;
    }

    objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);






    if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
        return JIM_ERR;
    }

    
    resultObj = Jim_NewDictObj(interp, NULL, 0);







>
>
>
>
>







5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
        
        Jim_UnsetVariable(interp, argv[0], JIM_NONE);
        return JIM_OK;
    }

    objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);

    if (objPtr == NULL) {
        
        return JIM_OK;
    }

    if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
        return JIM_ERR;
    }

    
    resultObj = Jim_NewDictObj(interp, NULL, 0);
5495
5496
5497
5498
5499
5500
5501










5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519



5520
5521
5522
5523
5524
5525
5526
        }
    }

    Jim_SetResultInt(interp, len);

    return JIM_OK;
}











static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int i;
    int len;
    Jim_Obj *listObj = argv[1];
    Jim_Obj *dictObj;

    len = Jim_ListLength(interp, listObj);
    if (len % 2) {
        Jim_SetResultString(interp, "list must have an even number of elements", -1);
        return JIM_ERR;
    }

    dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
    if (!dictObj) {
        
        return Jim_SetVariable(interp, argv[0], listObj);



    }

    if (Jim_IsShared(dictObj)) {
        dictObj = Jim_DuplicateObj(interp, dictObj);
    }

    for (i = 0; i < len; i += 2) {







>
>
>
>
>
>
>
>
>
>


















>
>
>







5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
        }
    }

    Jim_SetResultInt(interp, len);

    return JIM_OK;
}

static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
    if (objPtr) {
        return Jim_DictInfo(interp, objPtr);
    }
    Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
    return JIM_ERR;
}

static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int i;
    int len;
    Jim_Obj *listObj = argv[1];
    Jim_Obj *dictObj;

    len = Jim_ListLength(interp, listObj);
    if (len % 2) {
        Jim_SetResultString(interp, "list must have an even number of elements", -1);
        return JIM_ERR;
    }

    dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
    if (!dictObj) {
        
        return Jim_SetVariable(interp, argv[0], listObj);
    }
    else if (Jim_DictSize(interp, dictObj) < 0) {
        return JIM_ERR;
    }

    if (Jim_IsShared(dictObj)) {
        dictObj = Jim_DuplicateObj(interp, dictObj);
    }

    for (i = 0; i < len; i += 2) {
5566
5567
5568
5569
5570
5571
5572







5573
5574
5575
5576
5577
5578
5579
        },
        {       "size",
                "arrayName",
                array_cmd_size,
                1,
                1,
                







        },
        {       "unset",
                "arrayName ?pattern?",
                array_cmd_unset,
                1,
                2,
                







>
>
>
>
>
>
>







5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
        },
        {       "size",
                "arrayName",
                array_cmd_size,
                1,
                1,
                
        },
        {       "stat",
                "arrayName",
                array_cmd_stat,
                1,
                1,
                
        },
        {       "unset",
                "arrayName ?pattern?",
                array_cmd_unset,
                1,
                2,
                
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
Jim_execInit(interp);
Jim_clockInit(interp);
Jim_arrayInit(interp);
Jim_stdlibInit(interp);
Jim_tclcompatInit(interp);
return JIM_OK;
}

#define JIM_OPTIMIZATION        

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <stdarg.h>







<







5754
5755
5756
5757
5758
5759
5760

5761
5762
5763
5764
5765
5766
5767
Jim_execInit(interp);
Jim_clockInit(interp);
Jim_arrayInit(interp);
Jim_stdlibInit(interp);
Jim_tclcompatInit(interp);
return JIM_OK;
}

#define JIM_OPTIMIZATION        

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <stdarg.h>
5669
5670
5671
5672
5673
5674
5675

5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699


#ifdef JIM_MAINTAINER
#define JIM_DEBUG_COMMAND
#define JIM_DEBUG_PANIC
#endif



#define JIM_INTEGER_SPACE 24

const char *jim_tt_name(int type);

#ifdef JIM_DEBUG_PANIC
static void JimPanicDump(int panic_condition, const char *fmt, ...);
#define JimPanic(X) JimPanicDump X
#else
#define JimPanic(X)
#endif


static char JimEmptyStringRep[] = "";

static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
    int flags);
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,







>






|








<
|







5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832

5833
5834
5835
5836
5837
5838
5839
5840


#ifdef JIM_MAINTAINER
#define JIM_DEBUG_COMMAND
#define JIM_DEBUG_PANIC
#endif



#define JIM_INTEGER_SPACE 24

const char *jim_tt_name(int type);

#ifdef JIM_DEBUG_PANIC
static void JimPanicDump(int fail_condition, const char *fmt, ...);
#define JimPanic(X) JimPanicDump X
#else
#define JimPanic(X)
#endif


static char JimEmptyStringRep[] = "";


static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
    int flags);
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
    if (n > 0) {
        n = utf8_strlen(s2, n);
    }
    return n;
}
#endif

static int JimWideToString(char *buf, jim_wide wideValue)
{
    int pos = 0;

    if (wideValue == 0) {
        buf[pos++] = '0';
    }
    else {
        char tmp[JIM_INTEGER_SPACE];
        int num = 0;
        int i;

        if (wideValue < 0) {
            buf[pos++] = '-';
            
            i = wideValue % 10;
            tmp[num++] = (i > 0) ? (10 - i) : -i;
            wideValue /= -10;
        }

        while (wideValue) {
            tmp[num++] = wideValue % 10;
            wideValue /= 10;
        }

        for (i = 0; i < num; i++) {
            buf[pos++] = '0' + tmp[num - i - 1];
        }
    }
    buf[pos] = 0;

    return pos;
}

static int JimCheckConversion(const char *str, const char *endptr)
{
    if (str[0] == '\0' || str == endptr) {
        return JIM_ERR;
    }

    if (endptr[0] != '\0') {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6077
6078
6079
6080
6081
6082
6083


































6084
6085
6086
6087
6088
6089
6090
    if (n > 0) {
        n = utf8_strlen(s2, n);
    }
    return n;
}
#endif



































static int JimCheckConversion(const char *str, const char *endptr)
{
    if (str[0] == '\0' || str == endptr) {
        return JIM_ERR;
    }

    if (endptr[0] != '\0') {
6027
6028
6029
6030
6031
6032
6033

6034
6035
6036
6037
6038
6039
6040
6041
    i += 2;
    
    if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
        
        return i;
    }
    

    return 10;
}

static long jim_strtol(const char *str, char **endptr)
{
    int sign;
    int base;
    int i = JimNumberBase(str, &base, &sign);







>
|







6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
    i += 2;
    
    if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
        
        return i;
    }
    
    *base = 10;
    return 0;
}

static long jim_strtol(const char *str, char **endptr)
{
    int sign;
    int base;
    int i = JimNumberBase(str, &base, &sign);
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
    else {
        *widePtr = jim_strtoull(str, &endptr);
    }

    return JimCheckConversion(str, endptr);
}

int Jim_DoubleToString(char *buf, double doubleValue)
{
    int len;
    int i;

    len = sprintf(buf, "%.12g", doubleValue);

    
    for (i = 0; i < len; i++) {
        if (buf[i] == '.' || buf[i] == 'e') {
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
            char *e = strchr(buf, 'e');
            if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
                
                e += 2;
                memmove(e, e + 1, len - (e - buf));
                return len - 1;
            }
#endif
            return len;
        }
        
        if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
            buf[i] = toupper(UCHAR(buf[i]));
            buf[i + 3] = 0;
            return i + 3;
        }
    }

    buf[i++] = '.';
    buf[i++] = '0';
    buf[i] = '\0';

    return i;
}

int Jim_StringToDouble(const char *str, double *doublePtr)
{
    char *endptr;

    
    errno = 0;








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6191
6192
6193
6194
6195
6196
6197




































6198
6199
6200
6201
6202
6203
6204
    else {
        *widePtr = jim_strtoull(str, &endptr);
    }

    return JimCheckConversion(str, endptr);
}





































int Jim_StringToDouble(const char *str, double *doublePtr)
{
    char *endptr;

    
    errno = 0;

6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
    for (i = 0; i < e; i++) {
        res *= b;
    }
    return res;
}

#ifdef JIM_DEBUG_PANIC
void JimPanicDump(int condition, const char *fmt, ...)
{
    va_list ap;

    if (!condition) {
        return;
    }

    va_start(ap, fmt);

    fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, JIM_NL JIM_NL);
    va_end(ap);

#ifdef HAVE_BACKTRACE
    {
        void *array[40];
        int size, i;
        char **strings;

        size = backtrace(array, 40);
        strings = backtrace_symbols(array, size);
        for (i = 0; i < size; i++)
            fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
        fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
        fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
    }
#endif

    exit(1);
}
#endif








|









|

|











|
|
|







6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
    for (i = 0; i < e; i++) {
        res *= b;
    }
    return res;
}

#ifdef JIM_DEBUG_PANIC
static void JimPanicDump(int condition, const char *fmt, ...)
{
    va_list ap;

    if (!condition) {
        return;
    }

    va_start(ap, fmt);

    fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, "\n\n");
    va_end(ap);

#ifdef HAVE_BACKTRACE
    {
        void *array[40];
        int size, i;
        char **strings;

        size = backtrace(array, 40);
        strings = backtrace_symbols(array, size);
        for (i = 0; i < size; i++)
            fprintf(stderr, "[backtrace] %s\n", strings[i]);
        fprintf(stderr, "[backtrace] Include the above lines and the output\n");
        fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
    }
#endif

    exit(1);
}
#endif

6248
6249
6250
6251
6252
6253
6254

6255
6256
6257
6258
6259
6260
6261
6262





6263
6264
6265
6266
6267
6268
6269

    while (len--)
        h += (h << 3) + *buf++;
    return h;
}




static void JimResetHashTable(Jim_HashTable *ht)
{
    ht->table = NULL;
    ht->size = 0;
    ht->sizemask = 0;
    ht->used = 0;
    ht->collisions = 0;





}

static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
{
    iter->ht = ht;
    iter->index = -1;
    iter->entry = NULL;







>








>
>
>
>
>







6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347

    while (len--)
        h += (h << 3) + *buf++;
    return h;
}




static void JimResetHashTable(Jim_HashTable *ht)
{
    ht->table = NULL;
    ht->size = 0;
    ht->sizemask = 0;
    ht->used = 0;
    ht->collisions = 0;
#ifdef JIM_RANDOMISE_HASH
    ht->uniq = (rand() ^ time(NULL) ^ clock());
#else
    ht->uniq = 0;
#endif
}

static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
{
    iter->ht = ht;
    iter->index = -1;
    iter->entry = NULL;
6297
6298
6299
6300
6301
6302
6303


6304
6305
6306
6307
6308
6309
6310
     if (size <= ht->used)
        return;

    Jim_InitHashTable(&n, ht->type, ht->privdata);
    n.size = realsize;
    n.sizemask = realsize - 1;
    n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));



    
    memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));

    n.used = ht->used;
    for (i = 0; ht->used > 0; i++) {
        Jim_HashEntry *he, *nextHe;







>
>







6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
     if (size <= ht->used)
        return;

    Jim_InitHashTable(&n, ht->type, ht->privdata);
    n.size = realsize;
    n.sizemask = realsize - 1;
    n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
    
    n.uniq = ht->uniq;

    
    memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));

    n.used = ht->used;
    for (i = 0; ht->used > 0; i++) {
        Jim_HashEntry *he, *nextHe;
6353
6354
6355
6356
6357
6358
6359




6360

6361


6362
6363
6364
6365
6366

6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
    int existed;
    Jim_HashEntry *entry;

    entry = JimInsertHashEntry(ht, key, 1);
    if (entry->key) {




        

        Jim_FreeEntryVal(ht, entry);


        existed = 1;
    }
    else {
        
        Jim_SetHashKey(ht, entry, key);

        existed = 0;
    }
    Jim_SetHashVal(ht, entry, val);

    return existed;
}


int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
{







>
>
>
>
|
>
|
>
>





>


<







6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456

6457
6458
6459
6460
6461
6462
6463
int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
    int existed;
    Jim_HashEntry *entry;

    entry = JimInsertHashEntry(ht, key, 1);
    if (entry->key) {
        if (ht->type->valDestructor && ht->type->valDup) {
            void *newval = ht->type->valDup(ht->privdata, val);
            ht->type->valDestructor(ht->privdata, entry->u.val);
            entry->u.val = newval;
        }
        else {
            Jim_FreeEntryVal(ht, entry);
            Jim_SetHashVal(ht, entry, val);
        }
        existed = 1;
    }
    else {
        
        Jim_SetHashKey(ht, entry, key);
        Jim_SetHashVal(ht, entry, val);
        existed = 0;
    }


    return existed;
}


int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
{
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
static unsigned int JimStringCopyHTHashFunction(const void *key)
{
    return Jim_GenHashFunction(key, strlen(key));
}

static void *JimStringCopyHTDup(void *privdata, const void *key)
{
    return strdup(key);
}

static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
{
    return strcmp(key1, key2) == 0;
}








|







6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
static unsigned int JimStringCopyHTHashFunction(const void *key)
{
    return Jim_GenHashFunction(key, strlen(key));
}

static void *JimStringCopyHTDup(void *privdata, const void *key)
{
    return Jim_StrDup(key);
}

static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
{
    return strcmp(key1, key2) == 0;
}

6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645

    for (i = 0; i < stack->len; i++)
        freeFunc(stack->vector[i]);
}



#define JIM_TT_NONE    0           
#define JIM_TT_STR     1          
#define JIM_TT_ESC     2          
#define JIM_TT_VAR     3          
#define JIM_TT_DICTSUGAR   4      
#define JIM_TT_CMD     5          

#define JIM_TT_SEP     6          







|







6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732

    for (i = 0; i < stack->len; i++)
        freeFunc(stack->vector[i]);
}



#define JIM_TT_NONE    0          
#define JIM_TT_STR     1          
#define JIM_TT_ESC     2          
#define JIM_TT_VAR     3          
#define JIM_TT_DICTSUGAR   4      
#define JIM_TT_CMD     5          

#define JIM_TT_SEP     6          
6663
6664
6665
6666
6667
6668
6669





6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726

#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)


#define JIM_PS_DEF 0            
#define JIM_PS_QUOTE 1          
#define JIM_PS_DICTSUGAR 2      






struct JimParserCtx
{
    const char *p;              
    int len;                    
    int linenr;                 
    const char *tstart;
    const char *tend;           
    int tline;                  
    int tt;                     
    int eof;                    
    int state;                  
    int comment;                
    char missing;               
    int missingline;            
};

struct JimParseResult {
    char missing;               
    int line;                   
};

static int JimParseScript(struct JimParserCtx *pc);
static int JimParseSep(struct JimParserCtx *pc);
static int JimParseEol(struct JimParserCtx *pc);
static int JimParseCmd(struct JimParserCtx *pc);
static int JimParseQuote(struct JimParserCtx *pc);
static int JimParseVar(struct JimParserCtx *pc);
static int JimParseBrace(struct JimParserCtx *pc);
static int JimParseStr(struct JimParserCtx *pc);
static int JimParseComment(struct JimParserCtx *pc);
static void JimParseSubCmd(struct JimParserCtx *pc);
static int JimParseSubQuote(struct JimParserCtx *pc);
static void JimParseSubCmd(struct JimParserCtx *pc);
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);

static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
{
    pc->p = prg;
    pc->len = len;
    pc->tstart = NULL;
    pc->tend = NULL;
    pc->tline = 0;
    pc->tt = JIM_TT_NONE;
    pc->eof = 0;
    pc->state = JIM_PS_DEF;
    pc->linenr = linenr;
    pc->comment = 1;
    pc->missing = ' ';
    pc->missingline = linenr;
}

static int JimParseScript(struct JimParserCtx *pc)
{
    while (1) {                 
        if (!pc->len) {
            pc->tstart = pc->p;







>
>
>
>
>













<
<
<
<
|
<
<













<














|
|







6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774




6775


6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788

6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811

#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)


#define JIM_PS_DEF 0            
#define JIM_PS_QUOTE 1          
#define JIM_PS_DICTSUGAR 2      

struct JimParseMissing {
    int ch;             
    int line;           
};

struct JimParserCtx
{
    const char *p;              
    int len;                    
    int linenr;                 
    const char *tstart;
    const char *tend;           
    int tline;                  
    int tt;                     
    int eof;                    
    int state;                  
    int comment;                




    struct JimParseMissing missing;   


};

static int JimParseScript(struct JimParserCtx *pc);
static int JimParseSep(struct JimParserCtx *pc);
static int JimParseEol(struct JimParserCtx *pc);
static int JimParseCmd(struct JimParserCtx *pc);
static int JimParseQuote(struct JimParserCtx *pc);
static int JimParseVar(struct JimParserCtx *pc);
static int JimParseBrace(struct JimParserCtx *pc);
static int JimParseStr(struct JimParserCtx *pc);
static int JimParseComment(struct JimParserCtx *pc);
static void JimParseSubCmd(struct JimParserCtx *pc);
static int JimParseSubQuote(struct JimParserCtx *pc);

static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);

static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
{
    pc->p = prg;
    pc->len = len;
    pc->tstart = NULL;
    pc->tend = NULL;
    pc->tline = 0;
    pc->tt = JIM_TT_NONE;
    pc->eof = 0;
    pc->state = JIM_PS_DEF;
    pc->linenr = linenr;
    pc->comment = 1;
    pc->missing.ch = ' ';
    pc->missing.line = linenr;
}

static int JimParseScript(struct JimParserCtx *pc)
{
    while (1) {                 
        if (!pc->len) {
            pc->tstart = pc->p;
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
            case '\n':
                pc->linenr++;
                break;
        }
        pc->p++;
        pc->len--;
    }
    pc->missing = '{';
    pc->missingline = pc->tline;
    pc->tend = pc->p - 1;
}

static int JimParseSubQuote(struct JimParserCtx *pc)
{
    int tt = JIM_TT_STR;
    int line = pc->tline;







|
|







6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
            case '\n':
                pc->linenr++;
                break;
        }
        pc->p++;
        pc->len--;
    }
    pc->missing.ch = '{';
    pc->missing.line = pc->tline;
    pc->tend = pc->p - 1;
}

static int JimParseSubQuote(struct JimParserCtx *pc)
{
    int tt = JIM_TT_STR;
    int line = pc->tline;
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
            case '$':
                tt = JIM_TT_ESC;
                break;
        }
        pc->p++;
        pc->len--;
    }
    pc->missing = '"';
    pc->missingline = line;
    pc->tend = pc->p - 1;
    return tt;
}

static void JimParseSubCmd(struct JimParserCtx *pc)
{
    int level = 1;







|
|







6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
            case '$':
                tt = JIM_TT_ESC;
                break;
        }
        pc->p++;
        pc->len--;
    }
    pc->missing.ch = '"';
    pc->missing.line = line;
    pc->tend = pc->p - 1;
    return tt;
}

static void JimParseSubCmd(struct JimParserCtx *pc)
{
    int level = 1;
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
                pc->linenr++;
                break;
        }
        startofword = isspace(UCHAR(*pc->p));
        pc->p++;
        pc->len--;
    }
    pc->missing = '[';
    pc->missingline = line;
    pc->tend = pc->p - 1;
}

static int JimParseBrace(struct JimParserCtx *pc)
{
    pc->tstart = pc->p + 1;
    pc->tline = pc->linenr;







|
|







7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
                pc->linenr++;
                break;
        }
        startofword = isspace(UCHAR(*pc->p));
        pc->p++;
        pc->len--;
    }
    pc->missing.ch = '[';
    pc->missing.line = line;
    pc->tend = pc->p - 1;
}

static int JimParseBrace(struct JimParserCtx *pc)
{
    pc->tstart = pc->p + 1;
    pc->tline = pc->linenr;
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133




7134
7135
7136
7137
7138
7139
7140
            return JimParseBrace(pc);
        }
        if (*pc->p == '"') {
            pc->state = JIM_PS_QUOTE;
            pc->p++;
            pc->len--;
            
            pc->missingline = pc->tline;
        }
    }
    pc->tstart = pc->p;
    pc->tline = pc->linenr;
    while (1) {
        if (pc->len == 0) {
            if (pc->state == JIM_PS_QUOTE) {
                pc->missing = '"';
            }
            pc->tend = pc->p - 1;
            pc->tt = JIM_TT_ESC;
            return JIM_OK;
        }
        switch (*pc->p) {
            case '\\':
                if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') {
                    pc->tend = pc->p - 1;
                    pc->tt = JIM_TT_ESC;
                    return JIM_OK;
                }
                if (pc->len >= 2) {
                    if (*(pc->p + 1) == '\n') {
                        pc->linenr++;
                    }
                    pc->p++;
                    pc->len--;
                }




                break;
            case '(':
                
                if (pc->len > 1 && pc->p[1] != '$') {
                    break;
                }
            case ')':







|







|



















>
>
>
>







7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
            return JimParseBrace(pc);
        }
        if (*pc->p == '"') {
            pc->state = JIM_PS_QUOTE;
            pc->p++;
            pc->len--;
            
            pc->missing.line = pc->tline;
        }
    }
    pc->tstart = pc->p;
    pc->tline = pc->linenr;
    while (1) {
        if (pc->len == 0) {
            if (pc->state == JIM_PS_QUOTE) {
                pc->missing.ch = '"';
            }
            pc->tend = pc->p - 1;
            pc->tt = JIM_TT_ESC;
            return JIM_OK;
        }
        switch (*pc->p) {
            case '\\':
                if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') {
                    pc->tend = pc->p - 1;
                    pc->tt = JIM_TT_ESC;
                    return JIM_OK;
                }
                if (pc->len >= 2) {
                    if (*(pc->p + 1) == '\n') {
                        pc->linenr++;
                    }
                    pc->p++;
                    pc->len--;
                }
                else if (pc->len == 1) {
                    
                    pc->missing.ch = '\\';
                }
                break;
            case '(':
                
                if (pc->len > 1 && pc->p[1] != '$') {
                    break;
                }
            case ')':
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198


7199
7200









7201
7202
7203
7204
7205
7206
7207
    }
    return JIM_OK;              
}

static int JimParseComment(struct JimParserCtx *pc)
{
    while (*pc->p) {
        if (*pc->p == '\n') {
            pc->linenr++;
            if (*(pc->p - 1) != '\\') {
                pc->p++;
                pc->len--;


                return JIM_OK;
            }









        }
        pc->p++;
        pc->len--;
    }
    return JIM_OK;
}








|
<
<
|
|
>
>


>
>
>
>
>
>
>
>
>







7276
7277
7278
7279
7280
7281
7282
7283


7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
    }
    return JIM_OK;              
}

static int JimParseComment(struct JimParserCtx *pc)
{
    while (*pc->p) {
        if (*pc->p == '\\') {


            pc->p++;
            pc->len--;
            if (pc->len == 0) {
                pc->missing.ch = '\\';
                return JIM_OK;
            }
            if (*pc->p == '\n') {
                pc->linenr++;
            }
        }
        else if (*pc->p == '\n') {
            pc->p++;
            pc->len--;
            pc->linenr++;
            break;
        }
        pc->p++;
        pc->len--;
    }
    return JIM_OK;
}

7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
    struct JimParserCtx parser;

    JimParserInit(&parser, s, len, 1);
    while (!parser.eof) {
        JimParseScript(&parser);
    }
    if (stateCharPtr) {
        *stateCharPtr = parser.missing;
    }
    return parser.missing == ' ';
}

static int JimParseListSep(struct JimParserCtx *pc);
static int JimParseListStr(struct JimParserCtx *pc);
static int JimParseListQuote(struct JimParserCtx *pc);

static int JimParseList(struct JimParserCtx *pc)







|

|







7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
    struct JimParserCtx parser;

    JimParserInit(&parser, s, len, 1);
    while (!parser.eof) {
        JimParseScript(&parser);
    }
    if (stateCharPtr) {
        *stateCharPtr = parser.missing.ch;
    }
    return parser.missing.ch == ' ';
}

static int JimParseListSep(struct JimParserCtx *pc);
static int JimParseListStr(struct JimParserCtx *pc);
static int JimParseListQuote(struct JimParserCtx *pc);

static int JimParseList(struct JimParserCtx *pc)
7579
7580
7581
7582
7583
7584
7585



7586
7587
7588
7589
7590
7591
7592

7593
7594
7595
7596
7597
7598
7599
    
    if (objPtr->prevObjPtr)
        objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
    if (objPtr->nextObjPtr)
        objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
    if (interp->liveList == objPtr)
        interp->liveList = objPtr->nextObjPtr;



    
    objPtr->prevObjPtr = NULL;
    objPtr->nextObjPtr = interp->freeList;
    if (interp->freeList)
        interp->freeList->prevObjPtr = objPtr;
    interp->freeList = objPtr;
    objPtr->refCount = -1;

}


void Jim_InvalidateStringRep(Jim_Obj *objPtr)
{
    if (objPtr->bytes != NULL) {
        if (objPtr->bytes != JimEmptyStringRep)







>
>
>







>







7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
    
    if (objPtr->prevObjPtr)
        objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
    if (objPtr->nextObjPtr)
        objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
    if (interp->liveList == objPtr)
        interp->liveList = objPtr->nextObjPtr;
#ifdef JIM_DISABLE_OBJECT_POOL
    Jim_Free(objPtr);
#else
    
    objPtr->prevObjPtr = NULL;
    objPtr->nextObjPtr = interp->freeList;
    if (interp->freeList)
        interp->freeList->prevObjPtr = objPtr;
    interp->freeList = objPtr;
    objPtr->refCount = -1;
#endif
}


void Jim_InvalidateStringRep(Jim_Obj *objPtr)
{
    if (objPtr->bytes != NULL) {
        if (objPtr->bytes != JimEmptyStringRep)
7669
7670
7671
7672
7673
7674
7675






7676
7677
7678
7679
7680
7681
7682
    if (objPtr->bytes == NULL) {
        
        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
        objPtr->typePtr->updateStringProc(objPtr);
    }
    return objPtr->bytes;
}







static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);

static const Jim_ObjType dictSubstObjType = {
    "dict-substitution",
    FreeDictSubstInternalRep,







>
>
>
>
>
>







7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
    if (objPtr->bytes == NULL) {
        
        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
        objPtr->typePtr->updateStringProc(objPtr);
    }
    return objPtr->bytes;
}

static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
{
    objPtr->bytes = Jim_StrDup(str);
    objPtr->length = strlen(str);
}

static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);

static const Jim_ObjType dictSubstObjType = {
    "dict-substitution",
    FreeDictSubstInternalRep,
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
};

static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
    JIM_NOTUSED(interp);

    dupPtr->internalRep.strValue.maxLength = srcPtr->length;

    dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
}

static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    if (objPtr->typePtr != &stringObjType) {
        







<







7818
7819
7820
7821
7822
7823
7824

7825
7826
7827
7828
7829
7830
7831
};

static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
    JIM_NOTUSED(interp);

    dupPtr->internalRep.strValue.maxLength = srcPtr->length;

    dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
}

static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    if (objPtr->typePtr != &stringObjType) {
        
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773

7774
7775
7776
7777
7778
7779
7780

    
    if (len == -1)
        len = strlen(s);
    
    if (len == 0) {
        objPtr->bytes = JimEmptyStringRep;
        objPtr->length = 0;
    }
    else {
        objPtr->bytes = Jim_Alloc(len + 1);
        objPtr->length = len;
        memcpy(objPtr->bytes, s, len);
        objPtr->bytes[len] = '\0';
    }


    
    objPtr->typePtr = NULL;
    return objPtr;
}









<



<



>







7866
7867
7868
7869
7870
7871
7872

7873
7874
7875

7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886

    
    if (len == -1)
        len = strlen(s);
    
    if (len == 0) {
        objPtr->bytes = JimEmptyStringRep;

    }
    else {
        objPtr->bytes = Jim_Alloc(len + 1);

        memcpy(objPtr->bytes, s, len);
        objPtr->bytes[len] = '\0';
    }
    objPtr->length = len;

    
    objPtr->typePtr = NULL;
    return objPtr;
}


7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
}

Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
{
    Jim_Obj *objPtr = Jim_NewObj(interp);

    objPtr->bytes = s;
    objPtr->length = len == -1 ? strlen(s) : len;
    objPtr->typePtr = NULL;
    return objPtr;
}

static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
{
    int needlen;







|







7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
}

Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
{
    Jim_Obj *objPtr = Jim_NewObj(interp);

    objPtr->bytes = s;
    objPtr->length = (len == -1) ? strlen(s) : len;
    objPtr->typePtr = NULL;
    return objPtr;
}

static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
{
    int needlen;
7827
7828
7829
7830
7831
7832
7833

7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880



7881
7882
7883
7884
7885

7886
7887
7888
7889
7890
7891
7892
        else {
            objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1);
        }
        objPtr->internalRep.strValue.maxLength = needlen;
    }
    memcpy(objPtr->bytes + objPtr->length, str, len);
    objPtr->bytes[objPtr->length + len] = '\0';

    if (objPtr->internalRep.strValue.charLength >= 0) {
        
        objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
    }
    objPtr->length += len;
}


void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
{
    JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
    SetStringFromAny(interp, objPtr);
    StringAppendString(objPtr, str, len);
}

void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
{
    int len;
    const char *str;

    str = Jim_GetString(appendObjPtr, &len);
    Jim_AppendString(interp, objPtr, str, len);
}

void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
{
    va_list ap;

    SetStringFromAny(interp, objPtr);
    va_start(ap, objPtr);
    while (1) {
        char *s = va_arg(ap, char *);

        if (s == NULL)
            break;
        Jim_AppendString(interp, objPtr, s, -1);
    }
    va_end(ap);
}

int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
{
    const char *aStr, *bStr;
    int aLen, bLen;

    if (aObjPtr == bObjPtr)
        return 1;



    aStr = Jim_GetString(aObjPtr, &aLen);
    bStr = Jim_GetString(bObjPtr, &bLen);
    if (aLen != bLen)
        return 0;
    return JimStringCompare(aStr, aLen, bStr, bLen) == 0;

}

int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
{
    return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
}








>






<











<
<
|










|










<
<
<
|

>
>
>
|
|
|
|
<
>







7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946

7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957


7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979



7980
7981
7982
7983
7984
7985
7986
7987
7988

7989
7990
7991
7992
7993
7994
7995
7996
        else {
            objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1);
        }
        objPtr->internalRep.strValue.maxLength = needlen;
    }
    memcpy(objPtr->bytes + objPtr->length, str, len);
    objPtr->bytes[objPtr->length + len] = '\0';

    if (objPtr->internalRep.strValue.charLength >= 0) {
        
        objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
    }
    objPtr->length += len;
}


void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
{
    JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
    SetStringFromAny(interp, objPtr);
    StringAppendString(objPtr, str, len);
}

void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
{
    int len;


    const char *str = Jim_GetString(appendObjPtr, &len);
    Jim_AppendString(interp, objPtr, str, len);
}

void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
{
    va_list ap;

    SetStringFromAny(interp, objPtr);
    va_start(ap, objPtr);
    while (1) {
        const char *s = va_arg(ap, const char *);

        if (s == NULL)
            break;
        Jim_AppendString(interp, objPtr, s, -1);
    }
    va_end(ap);
}

int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
{



    if (aObjPtr == bObjPtr) {
        return 1;
    }
    else {
        int Alen, Blen;
        const char *sA = Jim_GetString(aObjPtr, &Alen);
        const char *sB = Jim_GetString(bObjPtr, &Blen);

        return Alen == Blen && memcmp(sA, sB, Alen) == 0;

    }
}

int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
{
    return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
}

8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
}

static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
{
    while (*str) {
        int c;
        str += utf8_tounicode(str, &c);
        dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
    }
    *dest = 0;
}

static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
{
    char *buf;







|







8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
}

static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
{
    while (*str) {
        int c;
        str += utf8_tounicode(str, &c);
        dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
    }
    *dest = 0;
}

static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
{
    char *buf;
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
    }
#ifdef JIM_UTF8
    len *= 2;
#endif
    buf = p = Jim_Alloc(len + 1);

    str += utf8_tounicode(str, &c);
    p += utf8_fromunicode(p, utf8_title(c));

    JimStrCopyUpperLower(p, str, 0);

    return Jim_NewStringObjNoAlloc(interp, buf, -1);
}

static const char *utf8_memchr(const char *str, int len, int c)







|







8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
    }
#ifdef JIM_UTF8
    len *= 2;
#endif
    buf = p = Jim_Alloc(len + 1);

    str += utf8_tounicode(str, &c);
    p += utf8_getchars(p, utf8_title(c));

    JimStrCopyUpperLower(p, str, 0);

    return Jim_NewStringObjNoAlloc(interp, buf, -1);
}

static const char *utf8_memchr(const char *str, int len, int c)
8210
8211
8212
8213
8214
8215
8216

8217
8218
8219
8220
8221
8222
8223
    nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);

    if (nontrim == NULL) {
        
        return Jim_NewEmptyStringObj(interp);
    }
    if (nontrim == strObjPtr->bytes + len) {

        return strObjPtr;
    }

    if (Jim_IsShared(strObjPtr)) {
        strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
    }
    else {







>







8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
    nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);

    if (nontrim == NULL) {
        
        return Jim_NewEmptyStringObj(interp);
    }
    if (nontrim == strObjPtr->bytes + len) {
        
        return strObjPtr;
    }

    if (Jim_IsShared(strObjPtr)) {
        strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
    }
    else {
8233
8234
8235
8236
8237
8238
8239

8240
8241
8242
8243
8244
8245
8246
8247
8248









8249
8250
8251
8252
8253
8254
8255
{
    
    Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);

    
    strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);


    if (objPtr != strObjPtr) {
        
        Jim_IncrRefCount(objPtr);
        Jim_DecrRefCount(interp, objPtr);
    }

    return strObjPtr;
}











static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
{
    static const char * const strclassnames[] = {
        "integer", "alpha", "alnum", "ascii", "digit",
        "double", "lower", "upper", "space", "xdigit",
        "control", "print", "graph", "punct",







>
|

<
|





>
>
>
>
>
>
>
>
>







8338
8339
8340
8341
8342
8343
8344
8345
8346
8347

8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
{
    
    Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);

    
    strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);

    
    if (objPtr != strObjPtr && objPtr->refCount == 0) {
        

        Jim_FreeNewObj(interp, objPtr);
    }

    return strObjPtr;
}


#ifdef HAVE_ISASCII
#define jim_isascii isascii
#else
static int jim_isascii(int c)
{
    return !(c & ~0x7f);
}
#endif

static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
{
    static const char * const strclassnames[] = {
        "integer", "alpha", "alnum", "ascii", "digit",
        "double", "lower", "upper", "space", "xdigit",
        "control", "print", "graph", "punct",
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333

8334
8335
8336
8337
8338

8339
8340
8341
8342
8343
8344
8345

    if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
        return JIM_ERR;
    }

    str = Jim_GetString(strObjPtr, &len);
    if (len == 0) {
        Jim_SetResultInt(interp, !strict);
        return JIM_OK;
    }

    switch (strclass) {
        case STR_IS_INTEGER:
            {
                jim_wide w;
                Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
                return JIM_OK;
            }

        case STR_IS_DOUBLE:
            {
                double d;
                Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
                return JIM_OK;
            }

        case STR_IS_ALPHA: isclassfunc = isalpha; break;
        case STR_IS_ALNUM: isclassfunc = isalnum; break;
        case STR_IS_ASCII: isclassfunc = isascii; break;
        case STR_IS_DIGIT: isclassfunc = isdigit; break;
        case STR_IS_LOWER: isclassfunc = islower; break;
        case STR_IS_UPPER: isclassfunc = isupper; break;
        case STR_IS_SPACE: isclassfunc = isspace; break;
        case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
        case STR_IS_CONTROL: isclassfunc = iscntrl; break;
        case STR_IS_PRINT: isclassfunc = isprint; break;
        case STR_IS_GRAPH: isclassfunc = isgraph; break;
        case STR_IS_PUNCT: isclassfunc = ispunct; break;
        default:
            return JIM_ERR;
    }

    for (i = 0; i < len; i++) {
        if (!isclassfunc(str[i])) {
            Jim_SetResultInt(interp, 0);
            return JIM_OK;
        }
    }
    Jim_SetResultInt(interp, 1);
    return JIM_OK;
}



static const Jim_ObjType comparedStringObjType = {
    "compared-string",
    NULL,
    NULL,
    NULL,
    JIM_TYPE_REFERENCES,
};

int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
{
    if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
        return 1;

    else {
        const char *objStr = Jim_String(objPtr);

        if (strcmp(str, objStr) != 0)
            return 0;

        if (objPtr->typePtr != &comparedStringObjType) {
            Jim_FreeIntRep(interp, objPtr);
            objPtr->typePtr = &comparedStringObjType;
        }
        objPtr->internalRep.ptr = (char *)str;  
        return 1;
    }







|







|






|





|















|



|















|

>





>







8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461

    if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
        return JIM_ERR;
    }

    str = Jim_GetString(strObjPtr, &len);
    if (len == 0) {
        Jim_SetResultBool(interp, !strict);
        return JIM_OK;
    }

    switch (strclass) {
        case STR_IS_INTEGER:
            {
                jim_wide w;
                Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
                return JIM_OK;
            }

        case STR_IS_DOUBLE:
            {
                double d;
                Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
                return JIM_OK;
            }

        case STR_IS_ALPHA: isclassfunc = isalpha; break;
        case STR_IS_ALNUM: isclassfunc = isalnum; break;
        case STR_IS_ASCII: isclassfunc = jim_isascii; break;
        case STR_IS_DIGIT: isclassfunc = isdigit; break;
        case STR_IS_LOWER: isclassfunc = islower; break;
        case STR_IS_UPPER: isclassfunc = isupper; break;
        case STR_IS_SPACE: isclassfunc = isspace; break;
        case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
        case STR_IS_CONTROL: isclassfunc = iscntrl; break;
        case STR_IS_PRINT: isclassfunc = isprint; break;
        case STR_IS_GRAPH: isclassfunc = isgraph; break;
        case STR_IS_PUNCT: isclassfunc = ispunct; break;
        default:
            return JIM_ERR;
    }

    for (i = 0; i < len; i++) {
        if (!isclassfunc(str[i])) {
            Jim_SetResultBool(interp, 0);
            return JIM_OK;
        }
    }
    Jim_SetResultBool(interp, 1);
    return JIM_OK;
}



static const Jim_ObjType comparedStringObjType = {
    "compared-string",
    NULL,
    NULL,
    NULL,
    JIM_TYPE_REFERENCES,
};

int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
{
    if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
        return 1;
    }
    else {
        const char *objStr = Jim_String(objPtr);

        if (strcmp(str, objStr) != 0)
            return 0;

        if (objPtr->typePtr != &comparedStringObjType) {
            Jim_FreeIntRep(interp, objPtr);
            objPtr->typePtr = &comparedStringObjType;
        }
        objPtr->internalRep.ptr = (char *)str;  
        return 1;
    }
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397

8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422

8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435

8436
8437
8438
8439
8440
8441


8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
    Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
}

static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *fileNameObj, int lineNumber)
{
    JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
    JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
    Jim_IncrRefCount(fileNameObj);
    objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
    objPtr->internalRep.sourceValue.lineNumber = lineNumber;
    objPtr->typePtr = &sourceObjType;
}


static const Jim_ObjType scriptLineObjType = {
    "scriptline",
    NULL,
    NULL,
    NULL,
    0,

};

static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
{
    Jim_Obj *objPtr;

#ifdef DEBUG_SHOW_SCRIPT
    char buf[100];
    snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc);
    objPtr = Jim_NewStringObj(interp, buf, -1);
#else
    objPtr = Jim_NewEmptyStringObj(interp);
#endif
    objPtr->typePtr = &scriptLineObjType;
    objPtr->internalRep.scriptLineValue.argc = argc;
    objPtr->internalRep.scriptLineValue.line = line;

    return objPtr;
}

#define JIM_CMDSTRUCT_EXPAND -1

static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);


static const Jim_ObjType scriptObjType = {
    "script",
    FreeScriptInternalRep,
    DupScriptInternalRep,
    NULL,
    JIM_TYPE_REFERENCES,
};

typedef struct ScriptToken
{
    int type;
    Jim_Obj *objPtr;

} ScriptToken;

typedef struct ScriptObj
{
    int len;                    
    ScriptToken *token;         


    int substFlags;             
    int inUse;                  /* Used to share a ScriptObj. Currently
                                   only used by Jim_EvalObj() as protection against
                                   shimmering of the currently evaluated object. */
    Jim_Obj *fileNameObj;
    int firstline;              
    int linenr;                 
} ScriptObj;

void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int i;
    struct ScriptObj *script = (void *)objPtr->internalRep.ptr;

    script->inUse--;
    if (script->inUse != 0)
        return;
    for (i = 0; i < script->len; i++) {
        Jim_DecrRefCount(interp, script->token[i].objPtr);
    }
    Jim_Free(script->token);
    Jim_DecrRefCount(interp, script->fileNameObj);
    Jim_Free(script);
}

void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
    JIM_NOTUSED(interp);
    JIM_NOTUSED(srcPtr);

    
    dupPtr->typePtr = NULL;
}

typedef struct
{
    const char *token;          
    int len;                    







|






<





<
>




















<
<


|
>











<

>




<

>
>




<









<
|














<







8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506

8507
8508
8509
8510
8511

8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532


8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547

8548
8549
8550
8551
8552
8553

8554
8555
8556
8557
8558
8559
8560

8561
8562
8563
8564
8565
8566
8567
8568
8569

8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584

8585
8586
8587
8588
8589
8590
8591
    Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
}

static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *fileNameObj, int lineNumber)
{
    JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
    JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
    Jim_IncrRefCount(fileNameObj);
    objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
    objPtr->internalRep.sourceValue.lineNumber = lineNumber;
    objPtr->typePtr = &sourceObjType;
}


static const Jim_ObjType scriptLineObjType = {
    "scriptline",
    NULL,
    NULL,
    NULL,

    JIM_NONE,
};

static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
{
    Jim_Obj *objPtr;

#ifdef DEBUG_SHOW_SCRIPT
    char buf[100];
    snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc);
    objPtr = Jim_NewStringObj(interp, buf, -1);
#else
    objPtr = Jim_NewEmptyStringObj(interp);
#endif
    objPtr->typePtr = &scriptLineObjType;
    objPtr->internalRep.scriptLineValue.argc = argc;
    objPtr->internalRep.scriptLineValue.line = line;

    return objPtr;
}



static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
static int JimParseCheckMissing(Jim_Interp *interp, int ch);

static const Jim_ObjType scriptObjType = {
    "script",
    FreeScriptInternalRep,
    DupScriptInternalRep,
    NULL,
    JIM_TYPE_REFERENCES,
};

typedef struct ScriptToken
{

    Jim_Obj *objPtr;
    int type;
} ScriptToken;

typedef struct ScriptObj
{

    ScriptToken *token;         
    Jim_Obj *fileNameObj;       
    int len;                    
    int substFlags;             
    int inUse;                  /* Used to share a ScriptObj. Currently
                                   only used by Jim_EvalObj() as protection against
                                   shimmering of the currently evaluated object. */

    int firstline;              
    int linenr;                 
} ScriptObj;

void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int i;
    struct ScriptObj *script = (void *)objPtr->internalRep.ptr;


    if (--script->inUse != 0)
        return;
    for (i = 0; i < script->len; i++) {
        Jim_DecrRefCount(interp, script->token[i].objPtr);
    }
    Jim_Free(script->token);
    Jim_DecrRefCount(interp, script->fileNameObj);
    Jim_Free(script);
}

void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
    JIM_NOTUSED(interp);
    JIM_NOTUSED(srcPtr);


    dupPtr->typePtr = NULL;
}

typedef struct
{
    const char *token;          
    int len;                    
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681

























8682
8683
8684
8685
8686
8687
8688

    if (lineargs == 0) {
        token--;
    }

    script->len = token - script->token;

    assert(script->len < count);

#ifdef DEBUG_SHOW_SCRIPT
    printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
    for (i = 0; i < script->len; i++) {
        const ScriptToken *t = &script->token[i];
        printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
    }
#endif

}


























static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
    ParseTokenList *tokenlist)
{
    int i;
    struct ScriptToken *token;








|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825

    if (lineargs == 0) {
        token--;
    }

    script->len = token - script->token;

    JimPanic((script->len >= count, "allocated script array is too short"));

#ifdef DEBUG_SHOW_SCRIPT
    printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
    for (i = 0; i < script->len; i++) {
        const ScriptToken *t = &script->token[i];
        printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
    }
#endif

}

static int JimParseCheckMissing(Jim_Interp *interp, int ch)
{
    const char *msg;

    switch (ch) {
        case '\\':
        case ' ':
            return JIM_OK;

        case '[':
            msg = "unmatched \"[\"";
            break;
        case '{':
            msg = "missing close-brace";
            break;
        case '"':
        default:
            msg = "missing quote";
            break;
    }

    Jim_SetResultString(interp, msg, -1);
    return JIM_ERR;
}

static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
    ParseTokenList *tokenlist)
{
    int i;
    struct ScriptToken *token;

8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711

8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732

8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746

8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770


8771
8772
8773
8774
8775
8776
8777
        Jim_IncrRefCount(token->objPtr);
        token++;
    }

    script->len = i;
}

static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
{
    int scriptTextLen;
    const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
    struct JimParserCtx parser;
    struct ScriptObj *script;
    ParseTokenList tokenlist;
    int line = 1;


    
    if (objPtr->typePtr == &sourceObjType) {
        line = objPtr->internalRep.sourceValue.lineNumber;
    }

    
    ScriptTokenListInit(&tokenlist);

    JimParserInit(&parser, scriptText, scriptTextLen, line);
    while (!parser.eof) {
        JimParseScript(&parser);
        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
            parser.tline);
    }
    if (result && parser.missing != ' ') {
        ScriptTokenListFree(&tokenlist);
        result->missing = parser.missing;
        result->line = parser.missingline;
        return JIM_ERR;
    }


    
    ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);

    
    script = Jim_Alloc(sizeof(*script));
    memset(script, 0, sizeof(*script));
    script->inUse = 1;
    if (objPtr->typePtr == &sourceObjType) {
        script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
    }
    else {
        script->fileNameObj = interp->emptyObj;
    }

    Jim_IncrRefCount(script->fileNameObj);

    ScriptObjAddTokens(interp, script, &tokenlist);

    
    ScriptTokenListFree(&tokenlist);

    
    Jim_FreeIntRep(interp, objPtr);
    Jim_SetIntRepPtr(objPtr, script);
    objPtr->typePtr = &scriptObjType;

    return JIM_OK;
}

ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
    if (objPtr == interp->emptyObj) {
        
        objPtr = interp->nullScriptObj;
    }

    if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
        SetScriptFromAny(interp, objPtr, NULL);


    }
    return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
}

static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
{
    cmdPtr->inUse++;







|







>















<
<
<
<
<
|
>














>












|










|
>
>







8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864





8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
        Jim_IncrRefCount(token->objPtr);
        token++;
    }

    script->len = i;
}

static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
    int scriptTextLen;
    const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
    struct JimParserCtx parser;
    struct ScriptObj *script;
    ParseTokenList tokenlist;
    int line = 1;
    int retcode = JIM_OK;

    
    if (objPtr->typePtr == &sourceObjType) {
        line = objPtr->internalRep.sourceValue.lineNumber;
    }

    
    ScriptTokenListInit(&tokenlist);

    JimParserInit(&parser, scriptText, scriptTextLen, line);
    while (!parser.eof) {
        JimParseScript(&parser);
        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
            parser.tline);
    }






    retcode = JimParseCheckMissing(interp, parser.missing.ch);

    
    ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);

    
    script = Jim_Alloc(sizeof(*script));
    memset(script, 0, sizeof(*script));
    script->inUse = 1;
    if (objPtr->typePtr == &sourceObjType) {
        script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
    }
    else {
        script->fileNameObj = interp->emptyObj;
    }
    script->linenr = parser.missing.line;
    Jim_IncrRefCount(script->fileNameObj);

    ScriptObjAddTokens(interp, script, &tokenlist);

    
    ScriptTokenListFree(&tokenlist);

    
    Jim_FreeIntRep(interp, objPtr);
    Jim_SetIntRepPtr(objPtr, script);
    objPtr->typePtr = &scriptObjType;

    return retcode;
}

ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
    if (objPtr == interp->emptyObj) {
        
        objPtr = interp->nullScriptObj;
    }

    if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
        if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
            return NULL;
        }
    }
    return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
}

static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
{
    cmdPtr->inUse++;
8848
8849
8850
8851
8852
8853
8854
















8855
8856
8857
8858
8859
8860
8861
    else if (Jim_Length(interp->framePtr->nsObj)) {
        
        nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
        Jim_AppendStrings(interp, nsObj, "::", name, NULL);
    }
    return nsObj;
}

















static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
{
    Jim_Obj *objPtr = interp->emptyObj;

    if (name[0] == ':' && name[1] == ':') {
        







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
    else if (Jim_Length(interp->framePtr->nsObj)) {
        
        nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
        Jim_AppendStrings(interp, nsObj, "::", name, NULL);
    }
    return nsObj;
}

Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
{
    Jim_Obj *resultObj;

    const char *name = Jim_String(nameObjPtr);
    if (name[0] == ':' && name[1] == ':') {
        return nameObjPtr;
    }
    Jim_IncrRefCount(nameObjPtr);
    resultObj = Jim_NewStringObj(interp, "::", -1);
    Jim_AppendObj(interp, resultObj, nameObjPtr);
    Jim_DecrRefCount(interp, nameObjPtr);

    return resultObj;
}

static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
{
    Jim_Obj *objPtr = interp->emptyObj;

    if (name[0] == ':' && name[1] == ':') {
        
8875
8876
8877
8878
8879
8880
8881





8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902

    #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))

#else
    
    #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
    #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)





#endif

static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
{
    Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
    if (he) {

        Jim_InterpIncrProcEpoch(interp);
    }

    if (he && interp->local) {
        
        cmd->prevCmd = he->u.val;
        he->u.val = cmd;
    }
    else {
        if (he) {
            
            Jim_DeleteHashEntry(&interp->commands, name);
        }








>
>
>
>
>












|
|







9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060

    #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))

#else
    
    #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
    #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)

Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
{
    return nameObjPtr;
}
#endif

static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
{
    Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
    if (he) {

        Jim_InterpIncrProcEpoch(interp);
    }

    if (he && interp->local) {
        
        cmd->prevCmd = Jim_GetHashEntryVal(he);
        Jim_SetHashVal(&interp->commands, he, cmd);
    }
    else {
        if (he) {
            
            Jim_DeleteHashEntry(&interp->commands, name);
        }

8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
    if (len == 0) {
        return JIM_OK;
    }

    cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
    Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
    for (i = 0; i < len; i++) {
        Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
        Jim_Var *varPtr;
        int subLen;

        Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
        
        subLen = Jim_ListLength(interp, objPtr);
        if (subLen == 1 || subLen == 2) {
            Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
            if (subLen == 1) {
                initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
                if (initObjPtr == NULL) {
                    Jim_SetResultFormatted(interp,
                        "variable for initialization of static \"%#s\" not found in the local context",
                        nameObjPtr);
                    return JIM_ERR;
                }
            }
            else {
                Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
            }
            if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
                return JIM_ERR;
            }

            varPtr = Jim_Alloc(sizeof(*varPtr));
            varPtr->objPtr = initObjPtr;







|



|



|










|







9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
    if (len == 0) {
        return JIM_OK;
    }

    cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
    Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
    for (i = 0; i < len; i++) {
        Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
        Jim_Var *varPtr;
        int subLen;

        objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
        
        subLen = Jim_ListLength(interp, objPtr);
        if (subLen == 1 || subLen == 2) {
            nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
            if (subLen == 1) {
                initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
                if (initObjPtr == NULL) {
                    Jim_SetResultFormatted(interp,
                        "variable for initialization of static \"%#s\" not found in the local context",
                        nameObjPtr);
                    return JIM_ERR;
                }
            }
            else {
                initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
            }
            if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
                return JIM_ERR;
            }

            varPtr = Jim_Alloc(sizeof(*varPtr));
            varPtr->objPtr = initObjPtr;
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
    for (i = 0; i < argListLen; i++) {
        Jim_Obj *argPtr;
        Jim_Obj *nameObjPtr;
        Jim_Obj *defaultObjPtr;
        int len;

        
        Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
        len = Jim_ListLength(interp, argPtr);
        if (len == 0) {
            Jim_SetResultString(interp, "argument with no name", -1);
err:
            JimDecrCmdRefCount(interp, cmdPtr);
            return NULL;
        }
        if (len > 2) {
            Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
            goto err;
        }

        if (len == 2) {
            
            Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
            Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
        }
        else {
            
            nameObjPtr = argPtr;
            defaultObjPtr = NULL;
        }








|














|
|







9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
    for (i = 0; i < argListLen; i++) {
        Jim_Obj *argPtr;
        Jim_Obj *nameObjPtr;
        Jim_Obj *defaultObjPtr;
        int len;

        
        argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
        len = Jim_ListLength(interp, argPtr);
        if (len == 0) {
            Jim_SetResultString(interp, "argument with no name", -1);
err:
            JimDecrCmdRefCount(interp, cmdPtr);
            return NULL;
        }
        if (len > 2) {
            Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
            goto err;
        }

        if (len == 2) {
            
            nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
            defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
        }
        else {
            
            nameObjPtr = argPtr;
            defaultObjPtr = NULL;
        }

9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
        Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
    }
    else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
        Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
    }
    else {
        
        cmdPtr = he->u.val;
        JimIncrCmdRefCount(cmdPtr);
        JimUpdateProcNamespace(interp, cmdPtr, fqnew);
        Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);

        
        Jim_DeleteHashEntry(&interp->commands, fqold);








|







9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
        Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
    }
    else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
        Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
    }
    else {
        
        cmdPtr = Jim_GetHashEntryVal(he);
        JimIncrCmdRefCount(cmdPtr);
        JimUpdateProcNamespace(interp, cmdPtr, fqnew);
        Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);

        
        Jim_DeleteHashEntry(&interp->commands, fqold);

9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
                Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
            }
            return NULL;
        }
#ifdef jim_ext_namespace
found:
#endif
        cmd = (Jim_Cmd *)he->u.val;

        
        Jim_FreeIntRep(interp, objPtr);
        objPtr->typePtr = &commandObjType;
        objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
        objPtr->internalRep.cmdValue.cmdPtr = cmd;
        objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;







|







9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
                Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
            }
            return NULL;
        }
#ifdef jim_ext_namespace
found:
#endif
        cmd = Jim_GetHashEntryVal(he);

        
        Jim_FreeIntRep(interp, objPtr);
        objPtr->typePtr = &commandObjType;
        objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
        objPtr->internalRep.cmdValue.cmdPtr = cmd;
        objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
        }
    }

    
    Jim_FreeIntRep(interp, objPtr);
    objPtr->typePtr = &variableObjType;
    objPtr->internalRep.varValue.callFrameId = framePtr->id;
    objPtr->internalRep.varValue.varPtr = he->u.val;
    objPtr->internalRep.varValue.global = global;
    return JIM_OK;
}


static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);







|







9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
        }
    }

    
    Jim_FreeIntRep(interp, objPtr);
    objPtr->typePtr = &variableObjType;
    objPtr->internalRep.varValue.callFrameId = framePtr->id;
    objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
    objPtr->internalRep.varValue.global = global;
    return JIM_OK;
}


static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
            else {
                framePtr = interp->framePtr;
            }

            retval = Jim_DeleteHashEntry(&framePtr->vars, name);
            if (retval == JIM_OK) {
                
                JimChangeCallFrameId(interp, framePtr);
            }
        }
    }
    if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
        Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
    }
    return retval;







|







9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
            else {
                framePtr = interp->framePtr;
            }

            retval = Jim_DeleteHashEntry(&framePtr->vars, name);
            if (retval == JIM_OK) {
                
                framePtr->id = interp->callFrameEpoch++;
            }
        }
    }
    if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
        Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
    }
    return retval;
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
    dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG);
    if (!dictObjPtr) {
        return NULL;
    }

    ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
    if (ret != JIM_OK) {
        resObjPtr = NULL;
        if (ret < 0) {
            Jim_SetResultFormatted(interp,
                "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
        }
        else {
            Jim_SetResultFormatted(interp,
                "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
        }
    }
    else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
        dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
        if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
            
            JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
        }
        
        Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
    }

    return resObjPtr;
}


static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags)







<
<
|
|
<
<
<
|
|
<

<
<
|
<
<
|
<







9881
9882
9883
9884
9885
9886
9887


9888
9889



9890
9891

9892


9893


9894

9895
9896
9897
9898
9899
9900
9901
    dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG);
    if (!dictObjPtr) {
        return NULL;
    }

    ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
    if (ret != JIM_OK) {


        Jim_SetResultFormatted(interp,
            "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,



            ret < 0 ? "variable isn't" : "no such element in");
    }

    else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {


        


        Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));

    }

    return resObjPtr;
}


static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
9841
9842
9843
9844
9845
9846
9847











9848
9849
9850

9851

9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886

9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922


9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj)
{
    Jim_CallFrame *cf;

    if (interp->freeFramesList) {
        cf = interp->freeFramesList;
        interp->freeFramesList = cf->next;











    }
    else {
        cf = Jim_Alloc(sizeof(*cf));

        cf->vars.table = NULL;

    }

    cf->id = interp->callFrameEpoch++;
    cf->parent = parent;
    cf->level = parent ? parent->level + 1 : 0;
    cf->argv = NULL;
    cf->argc = 0;
    cf->procArgsObjPtr = NULL;
    cf->procBodyObjPtr = NULL;
    cf->next = NULL;
    cf->staticVars = NULL;
    cf->localCommands = NULL;

    cf->nsObj = nsObj;
    Jim_IncrRefCount(nsObj);
    if (cf->vars.table == NULL)
        Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
    return cf;
}


static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
{
    cf->id = interp->callFrameEpoch++;
}

static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
{
    
    if (localCommands) {
        Jim_Obj *cmdNameObj;

        while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
            Jim_HashEntry *he;
            Jim_Obj *fqObjName;


            const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);

            he = Jim_FindHashEntry(&interp->commands, fqname);

            if (he) {
                Jim_Cmd *cmd = he->u.val;
                if (cmd->prevCmd) {
                    Jim_Cmd *prevCmd = cmd->prevCmd;
                    cmd->prevCmd = NULL;

                    
                    JimDecrCmdRefCount(interp, cmd);

                    
                    he->u.val = prevCmd;
                }
                else {
                    Jim_DeleteHashEntry(&interp->commands, fqname);
                    Jim_InterpIncrProcEpoch(interp);
                }
            }
            Jim_DecrRefCount(interp, cmdNameObj);
            JimFreeQualifiedName(interp, fqObjName);
        }
        Jim_FreeStack(localCommands);
        Jim_Free(localCommands);
    }
    return JIM_OK;
}


#define JIM_FCF_NONE 0          
#define JIM_FCF_NOHT 1          
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
{


    if (cf->procArgsObjPtr)
        Jim_DecrRefCount(interp, cf->procArgsObjPtr);
    if (cf->procBodyObjPtr)
        Jim_DecrRefCount(interp, cf->procBodyObjPtr);
    Jim_DecrRefCount(interp, cf->nsObj);
    if (!(flags & JIM_FCF_NOHT))
        Jim_FreeHashTable(&cf->vars);
    else {
        int i;
        Jim_HashEntry **table = cf->vars.table, *he;

        for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
            he = table[i];
            while (he != NULL) {
                Jim_HashEntry *nextEntry = he->next;
                Jim_Var *varPtr = (void *)he->u.val;

                Jim_DecrRefCount(interp, varPtr->objPtr);
                Jim_Free(he->u.val);
                Jim_Free((void *)he->key);      
                Jim_Free(he);
                table[i] = NULL;
                he = nextEntry;
            }
        }
        cf->vars.used = 0;
    }

    JimDeleteLocalProcs(interp, cf->localCommands);

    cf->next = interp->freeFramesList;
    interp->freeFramesList = cf;

}


#ifdef JIM_REFERENCES

static void JimReferencesHTValDestructor(void *interp, void *val)
{







>
>
>
>
>
>
>
>
>
>
>



>
|
>





<
<
<
<
<
<
<
<


|
<



<
<
<
<
<
<









>



|


|








|


|













|
|
|
|
>
>





|









|


|
|







<
<
<


<







9988
9989
9990
9991
9992
9993
9994
9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016








10017
10018
10019

10020
10021
10022






10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097



10098
10099

10100
10101
10102
10103
10104
10105
10106
static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj)
{
    Jim_CallFrame *cf;

    if (interp->freeFramesList) {
        cf = interp->freeFramesList;
        interp->freeFramesList = cf->next;

        cf->argv = NULL;
        cf->argc = 0;
        cf->procArgsObjPtr = NULL;
        cf->procBodyObjPtr = NULL;
        cf->next = NULL;
        cf->staticVars = NULL;
        cf->localCommands = NULL;
        cf->tailcall = 0;
        cf->tailcallObj = NULL;
        cf->tailcallCmd = NULL;
    }
    else {
        cf = Jim_Alloc(sizeof(*cf));
        memset(cf, 0, sizeof(*cf));

        Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
    }

    cf->id = interp->callFrameEpoch++;
    cf->parent = parent;
    cf->level = parent ? parent->level + 1 : 0;








    cf->nsObj = nsObj;
    Jim_IncrRefCount(nsObj);


    return cf;
}







static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
{
    
    if (localCommands) {
        Jim_Obj *cmdNameObj;

        while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
            Jim_HashEntry *he;
            Jim_Obj *fqObjName;
            Jim_HashTable *ht = &interp->commands;

            const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);

            he = Jim_FindHashEntry(ht, fqname);

            if (he) {
                Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
                if (cmd->prevCmd) {
                    Jim_Cmd *prevCmd = cmd->prevCmd;
                    cmd->prevCmd = NULL;

                    
                    JimDecrCmdRefCount(interp, cmd);

                    
                    Jim_SetHashVal(ht, he, prevCmd);
                }
                else {
                    Jim_DeleteHashEntry(ht, fqname);
                    Jim_InterpIncrProcEpoch(interp);
                }
            }
            Jim_DecrRefCount(interp, cmdNameObj);
            JimFreeQualifiedName(interp, fqObjName);
        }
        Jim_FreeStack(localCommands);
        Jim_Free(localCommands);
    }
    return JIM_OK;
}


#define JIM_FCF_FULL 0          
#define JIM_FCF_REUSE 1         
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
 {
    JimDeleteLocalProcs(interp, cf->localCommands);

    if (cf->procArgsObjPtr)
        Jim_DecrRefCount(interp, cf->procArgsObjPtr);
    if (cf->procBodyObjPtr)
        Jim_DecrRefCount(interp, cf->procBodyObjPtr);
    Jim_DecrRefCount(interp, cf->nsObj);
    if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
        Jim_FreeHashTable(&cf->vars);
    else {
        int i;
        Jim_HashEntry **table = cf->vars.table, *he;

        for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
            he = table[i];
            while (he != NULL) {
                Jim_HashEntry *nextEntry = he->next;
                Jim_Var *varPtr = Jim_GetHashEntryVal(he);

                Jim_DecrRefCount(interp, varPtr->objPtr);
                Jim_Free(Jim_GetHashEntryKey(he));
                Jim_Free(varPtr);
                Jim_Free(he);
                table[i] = NULL;
                he = nextEntry;
            }
        }
        cf->vars.used = 0;
    }



    cf->next = interp->freeFramesList;
    interp->freeFramesList = cf;

}


#ifdef JIM_REFERENCES

static void JimReferencesHTValDestructor(void *interp, void *val)
{
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
    "reference",
    NULL,
    NULL,
    UpdateStringOfReference,
    JIM_TYPE_REFERENCES,
};

void UpdateStringOfReference(struct Jim_Obj *objPtr)
{
    int len;
    char buf[JIM_REFERENCE_SPACE + 1];
    Jim_Reference *refPtr;

    refPtr = objPtr->internalRep.refValue.refPtr;
    len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
    objPtr->bytes = Jim_Alloc(len + 1);
    memcpy(objPtr->bytes, buf, len + 1);
    objPtr->length = len;
}

static int isrefchar(int c)
{
    return (c == '_' || isalnum(c));
}








|

<

<

|
<
<
<
|







10173
10174
10175
10176
10177
10178
10179
10180
10181

10182

10183
10184



10185
10186
10187
10188
10189
10190
10191
10192
    "reference",
    NULL,
    NULL,
    UpdateStringOfReference,
    JIM_TYPE_REFERENCES,
};

static void UpdateStringOfReference(struct Jim_Obj *objPtr)
{

    char buf[JIM_REFERENCE_SPACE + 1];


    JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);



    JimSetStringBytes(objPtr, buf);
}

static int isrefchar(int c)
{
    return (c == '_' || isalnum(c));
}

10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
        goto badformat;
    
    he = Jim_FindHashEntry(&interp->references, &value);
    if (he == NULL) {
        Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
        return JIM_ERR;
    }
    refPtr = he->u.val;
    
    Jim_FreeIntRep(interp, objPtr);
    objPtr->typePtr = &referenceObjType;
    objPtr->internalRep.refValue.id = value;
    objPtr->internalRep.refValue.refPtr = refPtr;
    return JIM_OK;








|







10233
10234
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
        goto badformat;
    
    he = Jim_FindHashEntry(&interp->references, &value);
    if (he == NULL) {
        Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
        return JIM_ERR;
    }
    refPtr = Jim_GetHashEntryVal(he);
    
    Jim_FreeIntRep(interp, objPtr);
    objPtr->typePtr = &referenceObjType;
    objPtr->internalRep.refValue.id = value;
    objPtr->internalRep.refValue.refPtr = refPtr;
    return JIM_OK;

10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225

    if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
        Jim_Collect(interp);
    }
}
#endif

static int JimIsBigEndian(void)
{
    union {
        unsigned short s;
        unsigned char c[2];
    } uval = {0x0102};

    return uval.c[0] == 1;







|







10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361
10362
10363
10364

    if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
        Jim_Collect(interp);
    }
}
#endif

int Jim_IsBigEndian(void)
{
    union {
        unsigned short s;
        unsigned char c[2];
    } uval = {0x0102};

    return uval.c[0] == 1;
10267
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284

10285
10286






10287
10288
10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336


10337
10338
10339
10340
10341
10342
10343
10344

10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361
10362
    
    Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
    Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");

    Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
    Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
    Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
    Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian");
    Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
    Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
    Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));

    return i;
}

void Jim_FreeInterp(Jim_Interp *i)
{
    Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;

    Jim_Obj *objPtr, *nextObjPtr;







    Jim_DecrRefCount(i, i->emptyObj);
    Jim_DecrRefCount(i, i->trueObj);
    Jim_DecrRefCount(i, i->falseObj);
    Jim_DecrRefCount(i, i->result);
    Jim_DecrRefCount(i, i->stackTrace);
    Jim_DecrRefCount(i, i->errorProc);
    Jim_DecrRefCount(i, i->unknown);
    Jim_DecrRefCount(i, i->errorFileNameObj);
    Jim_DecrRefCount(i, i->currentScriptObj);
    Jim_DecrRefCount(i, i->nullScriptObj);
    Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
    Jim_FreeHashTable(&i->references);
#endif
    Jim_FreeHashTable(&i->packages);
    Jim_Free(i->prngState);
    Jim_FreeHashTable(&i->assocData);

    
    while (cf) {
        prevcf = cf->parent;
        JimFreeCallFrame(i, cf, JIM_FCF_NONE);
        cf = prevcf;
    }
    if (i->liveList != NULL) {
        objPtr = i->liveList;

        printf(JIM_NL "-------------------------------------" JIM_NL);
        printf("Objects still in the free list:" JIM_NL);
        while (objPtr) {
            const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";

            if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
                printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
            }
            else {
                printf("%p (%d) %-10s: '%s'" JIM_NL,
                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
            }
            if (objPtr->typePtr == &sourceObjType) {
                printf("FILE %s LINE %d" JIM_NL,
                    Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
                    objPtr->internalRep.sourceValue.lineNumber);
            }
            objPtr = objPtr->nextObjPtr;
        }
        printf("-------------------------------------" JIM_NL JIM_NL);
        JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
    }


    
    objPtr = i->freeList;
    while (objPtr) {
        nextObjPtr = objPtr->nextObjPtr;
        Jim_Free(objPtr);
        objPtr = nextObjPtr;
    }
    

    cf = i->freeFramesList;
    while (cf) {
        nextcf = cf->next;
        if (cf->vars.table != NULL)
            Jim_Free(cf->vars.table);
        Jim_Free(cf);
        cf = nextcf;
    }
#ifdef jim_ext_load
    Jim_FreeLoadHandles(i);
#endif

    
    Jim_Free(i);
}

Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
{







|









|
>


>
>
>
>
>
>


















|
<
<
<
<
<



|
|




|



|



|





|


>
>







|
>
|
<
|
|
|

<

<
<
<







10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451





10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489

10490
10491
10492
10493

10494



10495
10496
10497
10498
10499
10500
10501
    
    Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
    Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");

    Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
    Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
    Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
    Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
    Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
    Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
    Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));

    return i;
}

void Jim_FreeInterp(Jim_Interp *i)
{
    Jim_CallFrame *cf, *cfx;

    Jim_Obj *objPtr, *nextObjPtr;

    
    for (cf = i->framePtr; cf; cf = cfx) {
        cfx = cf->parent;
        JimFreeCallFrame(i, cf, JIM_FCF_FULL);
    }

    Jim_DecrRefCount(i, i->emptyObj);
    Jim_DecrRefCount(i, i->trueObj);
    Jim_DecrRefCount(i, i->falseObj);
    Jim_DecrRefCount(i, i->result);
    Jim_DecrRefCount(i, i->stackTrace);
    Jim_DecrRefCount(i, i->errorProc);
    Jim_DecrRefCount(i, i->unknown);
    Jim_DecrRefCount(i, i->errorFileNameObj);
    Jim_DecrRefCount(i, i->currentScriptObj);
    Jim_DecrRefCount(i, i->nullScriptObj);
    Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
    Jim_FreeHashTable(&i->references);
#endif
    Jim_FreeHashTable(&i->packages);
    Jim_Free(i->prngState);
    Jim_FreeHashTable(&i->assocData);

#ifdef JIM_MAINTAINER





    if (i->liveList != NULL) {
        objPtr = i->liveList;

        printf("\n-------------------------------------\n");
        printf("Objects still in the free list:\n");
        while (objPtr) {
            const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";

            if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
                printf("%p (%d) %-10s: '%.20s...'\n",
                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
            }
            else {
                printf("%p (%d) %-10s: '%s'\n",
                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
            }
            if (objPtr->typePtr == &sourceObjType) {
                printf("FILE %s LINE %d\n",
                    Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
                    objPtr->internalRep.sourceValue.lineNumber);
            }
            objPtr = objPtr->nextObjPtr;
        }
        printf("-------------------------------------\n\n");
        JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
    }
#endif

    
    objPtr = i->freeList;
    while (objPtr) {
        nextObjPtr = objPtr->nextObjPtr;
        Jim_Free(objPtr);
        objPtr = nextObjPtr;
    }

    
    for (cf = i->freeFramesList; cf; cf = cfx) {

        cfx = cf->next;
        if (cf->vars.table)
            Jim_FreeHashTable(&cf->vars);
        Jim_Free(cf);

    }




    
    Jim_Free(i);
}

Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
{
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
    Jim_IncrRefCount(stackTraceObj);
    Jim_DecrRefCount(interp, interp->stackTrace);
    interp->stackTrace = stackTraceObj;
    interp->errorFlag = 1;

    len = Jim_ListLength(interp, interp->stackTrace);
    if (len >= 3) {
        Jim_Obj *filenameObj;

        Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE);

        Jim_GetString(filenameObj, &len);

        if (!Jim_Length(filenameObj)) {
            interp->addStackTrace = 1;
        }
    }
}


static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
    Jim_Obj *fileNameObj, int linenr)
{
    if (strcmp(procname, "unknown") == 0) {
        procname = "";
    }







<
<
|
<
<
<
<




<







10586
10587
10588
10589
10590
10591
10592


10593




10594
10595
10596
10597

10598
10599
10600
10601
10602
10603
10604
    Jim_IncrRefCount(stackTraceObj);
    Jim_DecrRefCount(interp, interp->stackTrace);
    interp->stackTrace = stackTraceObj;
    interp->errorFlag = 1;

    len = Jim_ListLength(interp, interp->stackTrace);
    if (len >= 3) {


        if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {




            interp->addStackTrace = 1;
        }
    }
}


static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
    Jim_Obj *fileNameObj, int linenr)
{
    if (strcmp(procname, "unknown") == 0) {
        procname = "";
    }
10483
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493

10494
10495
10496
10497
10498
10499
10500

    
    if (!*procname && Jim_Length(fileNameObj)) {
        
        int len = Jim_ListLength(interp, interp->stackTrace);

        if (len >= 3) {
            Jim_Obj *objPtr;
            if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) {
                
                if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) {

                    
                    ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
                    ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
                    return;
                }
            }
        }







|
|

|
>







10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633

    
    if (!*procname && Jim_Length(fileNameObj)) {
        
        int len = Jim_ListLength(interp, interp->stackTrace);

        if (len >= 3) {
            Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
            if (Jim_Length(objPtr)) {
                
                objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
                if (Jim_Length(objPtr) == 0) {
                    
                    ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
                    ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
                    return;
                }
            }
        }
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
}

void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
{
    Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);

    if (entryPtr != NULL) {
        AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;

        return assocEntryPtr->data;
    }
    return NULL;
}

int Jim_DeleteAssocData(Jim_Interp *interp, const char *key)
{







|
<







10649
10650
10651
10652
10653
10654
10655
10656

10657
10658
10659
10660
10661
10662
10663
}

void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
{
    Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);

    if (entryPtr != NULL) {
        AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);

        return assocEntryPtr->data;
    }
    return NULL;
}

int Jim_DeleteAssocData(Jim_Interp *interp, const char *key)
{
10555
10556
10557
10558
10559
10560
10561
10562
10563


10564







10565






10566




10567





10568

10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
    UpdateStringOfInt,
    JIM_TYPE_NONE,
};


static void UpdateStringOfInt(struct Jim_Obj *objPtr)
{
    int len;
    char buf[JIM_INTEGER_SPACE + 1];










    len = JimWideToString(buf, JimWideValue(objPtr));






    objPtr->bytes = Jim_Alloc(len + 1);




    memcpy(objPtr->bytes, buf, len + 1);





    objPtr->length = len;

}

int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
{
    jim_wide wideValue;
    const char *str;

    if (objPtr->typePtr == &coercedDoubleObjType) {
        
        objPtr->typePtr = &intObjType;







<

>
>

>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>


|







10687
10688
10689
10690
10691
10692
10693

10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
    UpdateStringOfInt,
    JIM_TYPE_NONE,
};


static void UpdateStringOfInt(struct Jim_Obj *objPtr)
{

    char buf[JIM_INTEGER_SPACE + 1];
    jim_wide wideValue = JimWideValue(objPtr);
    int pos = 0;

    if (wideValue == 0) {
        buf[pos++] = '0';
    }
    else {
        char tmp[JIM_INTEGER_SPACE];
        int num = 0;
        int i;

        if (wideValue < 0) {
            buf[pos++] = '-';
            i = wideValue % 10;
            tmp[num++] = (i > 0) ? (10 - i) : -i;
            wideValue /= -10;
        }

        while (wideValue) {
            tmp[num++] = wideValue % 10;
            wideValue /= 10;
        }

        for (i = 0; i < num; i++) {
            buf[pos++] = '0' + tmp[num - i - 1];
        }
    }
    buf[pos] = 0;

    JimSetStringBytes(objPtr, buf);
}

static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
{
    jim_wide wideValue;
    const char *str;

    if (objPtr->typePtr == &coercedDoubleObjType) {
        
        objPtr->typePtr = &intObjType;
10656
10657
10658
10659
10660
10661
10662









10663
10664

10665














10666


10667
10668





10669








10670



10671
10672
10673

10674
10675
10676
10677
10678
10679
10680
10681
    "double",
    NULL,
    NULL,
    UpdateStringOfDouble,
    JIM_TYPE_NONE,
};










void UpdateStringOfDouble(struct Jim_Obj *objPtr)
{

    int len;














    char buf[JIM_DOUBLE_SPACE + 1];



    len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);





    objPtr->bytes = Jim_Alloc(len + 1);








    memcpy(objPtr->bytes, buf, len + 1);



    objPtr->length = len;
}


int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    double doubleValue;
    jim_wide wideValue;
    const char *str;

    str = Jim_String(objPtr);








>
>
>
>
>
>
>
>
>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
|
|
>
|







10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
    "double",
    NULL,
    NULL,
    UpdateStringOfDouble,
    JIM_TYPE_NONE,
};

#ifndef HAVE_ISNAN
#undef isnan
#define isnan(X) ((X) != (X))
#endif
#ifndef HAVE_ISINF
#undef isinf
#define isinf(X) (1.0 / (X) == 0.0)
#endif

static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
{
    double value = objPtr->internalRep.doubleValue;

    if (isnan(value)) {
        JimSetStringBytes(objPtr, "NaN");
        return;
    }
    if (isinf(value)) {
        if (value < 0) {
            JimSetStringBytes(objPtr, "-Inf");
        }
        else {
            JimSetStringBytes(objPtr, "Inf");
        }
        return;
    }
    {
        char buf[JIM_DOUBLE_SPACE + 1];
        int i;
        int len = sprintf(buf, "%.12g", value);

        
        for (i = 0; i < len; i++) {
            if (buf[i] == '.' || buf[i] == 'e') {
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
                char *e = strchr(buf, 'e');
                if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
                    
                    e += 2;
                    memmove(e, e + 1, len - (e - buf));
                }
#endif
                break;
            }
        }
        if (buf[i] == '\0') {
            buf[i++] = '.';
            buf[i++] = '0';
            buf[i] = '\0';
        }
        JimSetStringBytes(objPtr, buf);
    }
}

static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    double doubleValue;
    jim_wide wideValue;
    const char *str;

    str = Jim_String(objPtr);

10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895
10896
10897
            }
        }
        return JIM_ELESTR_SIMPLE;
    }
    return JIM_ELESTR_QUOTE;
}

static int BackslashQuoteString(const char *s, char *q)
{
    char *p = q;

    while (*s) {
        switch (*s) {
            case ' ':
            case '$':
            case '"':
            case '[':
            case ']':
            case '{':







|



|







11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096
            }
        }
        return JIM_ELESTR_SIMPLE;
    }
    return JIM_ELESTR_QUOTE;
}

static int BackslashQuoteString(const char *s, int len, char *q)
{
    char *p = q;

    while (len--) {
        switch (*s) {
            case ' ':
            case '$':
            case '"':
            case '[':
            case ']':
            case '{':
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
                realLength += len + 2;
                break;
            case JIM_ELESTR_QUOTE:
                if (i == 0 && strRep[0] == '#') {
                    *p++ = '\\';
                    realLength++;
                }
                qlen = BackslashQuoteString(strRep, p);
                p += qlen;
                realLength += qlen;
                break;
        }
        
        if (i + 1 != objc) {
            *p++ = ' ';







|







11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
                realLength += len + 2;
                break;
            case JIM_ELESTR_QUOTE:
                if (i == 0 && strRep[0] == '#') {
                    *p++ = '\\';
                    realLength++;
                }
                qlen = BackslashQuoteString(strRep, len, p);
                p += qlen;
                realLength += qlen;
                break;
        }
        
        if (i + 1 != objc) {
            *p++ = ' ';
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
    Jim_Obj *fileNameObj;
    int linenr;

    if (objPtr->typePtr == &listObjType) {
        return JIM_OK;
    }

    if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
        Jim_Obj **listObjPtrPtr;
        int len;
        int i;

        listObjPtrPtr = JimDictPairs(objPtr, &len);
        for (i = 0; i < len; i++) {
            Jim_IncrRefCount(listObjPtrPtr[i]);







|







11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
    Jim_Obj *fileNameObj;
    int linenr;

    if (objPtr->typePtr == &listObjType) {
        return JIM_OK;
    }

    if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
        Jim_Obj **listObjPtrPtr;
        int len;
        int i;

        listObjPtrPtr = JimDictPairs(objPtr, &len);
        for (i = 0; i < len; i++) {
            Jim_IncrRefCount(listObjPtrPtr[i]);
11139
11140
11141
11142
11143
11144
11145

11146
11147
11148
11149
11150

11151
11152
11153
11154
11155
11156
11157
    jmp_buf jmpbuf;
    Jim_Obj *command;
    Jim_Interp *interp;
    enum {
        JIM_LSORT_ASCII,
        JIM_LSORT_NOCASE,
        JIM_LSORT_INTEGER,

        JIM_LSORT_COMMAND
    } type;
    int order;
    int index;
    int indexed;

    int (*subfn)(Jim_Obj **, Jim_Obj **);
};

static struct lsort_info *sort_info;

static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{







>





>







11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356
11357
11358
    jmp_buf jmpbuf;
    Jim_Obj *command;
    Jim_Interp *interp;
    enum {
        JIM_LSORT_ASCII,
        JIM_LSORT_NOCASE,
        JIM_LSORT_INTEGER,
        JIM_LSORT_REAL,
        JIM_LSORT_COMMAND
    } type;
    int order;
    int index;
    int indexed;
    int unique;
    int (*subfn)(Jim_Obj **, Jim_Obj **);
};

static struct lsort_info *sort_info;

static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
11182
11183
11184
11185
11186
11187
11188

















11189
11190
11191
11192
11193
11194
11195
    if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
        Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
        longjmp(sort_info->jmpbuf, JIM_ERR);
    }

    return JimSign(lhs - rhs) * sort_info->order;
}


















static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
    Jim_Obj *compare_script;
    int rc;

    jim_wide ret = 0;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
    if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
        Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
        longjmp(sort_info->jmpbuf, JIM_ERR);
    }

    return JimSign(lhs - rhs) * sort_info->order;
}

static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
    double lhs = 0, rhs = 0;

    if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
        Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
        longjmp(sort_info->jmpbuf, JIM_ERR);
    }
    if (lhs == rhs) {
        return 0;
    }
    if (lhs > rhs) {
        return sort_info->order;
    }
    return -sort_info->order;
}

static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
    Jim_Obj *compare_script;
    int rc;

    jim_wide ret = 0;
11204
11205
11206
11207
11208
11209
11210
























11211
11212
11213
11214
11215
11216
11217
11218
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240



11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257




11258

11259
11260
11261
11262
11263
11264
11265
    if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) {
        longjmp(sort_info->jmpbuf, rc);
    }

    return JimSign(ret) * sort_info->order;
}


























static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
{
    struct lsort_info *prev_info;

    typedef int (qsort_comparator) (const void *, const void *);
    int (*fn) (Jim_Obj **, Jim_Obj **);
    Jim_Obj **vector;
    int len;
    int rc;

    JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
    SetListFromAny(interp, listObjPtr);

    
    prev_info = sort_info;
    sort_info = info;

    vector = listObjPtr->internalRep.listValue.ele;
    len = listObjPtr->internalRep.listValue.len;
    switch (info->type) {
        case JIM_LSORT_ASCII:
            fn = ListSortString;
            break;
        case JIM_LSORT_NOCASE:
            fn = ListSortStringNoCase;
            break;
        case JIM_LSORT_INTEGER:
            fn = ListSortInteger;
            break;



        case JIM_LSORT_COMMAND:
            fn = ListSortCommand;
            break;
        default:
            fn = NULL;          
            JimPanic((1, "ListSort called with invalid sort type"));
    }

    if (info->indexed) {
        
        info->subfn = fn;
        fn = ListSortIndexHelper;
    }

    if ((rc = setjmp(info->jmpbuf)) == 0) {
        qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
    }




    Jim_InvalidateStringRep(listObjPtr);

    sort_info = prev_info;

    return rc;
}

static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
{







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|


















>
>
>
















|
>
>
>
>
|
>







11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
    if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) {
        longjmp(sort_info->jmpbuf, rc);
    }

    return JimSign(ret) * sort_info->order;
}

static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
{
    int src;
    int dst = 0;
    Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;

    for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
        if (comp(&ele[dst], &ele[src]) == 0) {
            
            Jim_DecrRefCount(sort_info->interp, ele[dst]);
        }
        else {
            
            dst++;
        }
        ele[dst] = ele[src];
    }
    
    ele[++dst] = ele[src];

    
    listObjPtr->internalRep.listValue.len = dst;
}


static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
{
    struct lsort_info *prev_info;

    typedef int (qsort_comparator) (const void *, const void *);
    int (*fn) (Jim_Obj **, Jim_Obj **);
    Jim_Obj **vector;
    int len;
    int rc;

    JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
    SetListFromAny(interp, listObjPtr);

    
    prev_info = sort_info;
    sort_info = info;

    vector = listObjPtr->internalRep.listValue.ele;
    len = listObjPtr->internalRep.listValue.len;
    switch (info->type) {
        case JIM_LSORT_ASCII:
            fn = ListSortString;
            break;
        case JIM_LSORT_NOCASE:
            fn = ListSortStringNoCase;
            break;
        case JIM_LSORT_INTEGER:
            fn = ListSortInteger;
            break;
        case JIM_LSORT_REAL:
            fn = ListSortReal;
            break;
        case JIM_LSORT_COMMAND:
            fn = ListSortCommand;
            break;
        default:
            fn = NULL;          
            JimPanic((1, "ListSort called with invalid sort type"));
    }

    if (info->indexed) {
        
        info->subfn = fn;
        fn = ListSortIndexHelper;
    }

    if ((rc = setjmp(info->jmpbuf)) == 0) {
        qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);

        if (info->unique && len > 1) {
            ListRemoveDuplicates(listObjPtr, fn);
        }

        Jim_InvalidateStringRep(listObjPtr);
    }
    sort_info = prev_info;

    return rc;
}

static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
{
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
        idx = listPtr->internalRep.listValue.len + idx;
    Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]);
    listPtr->internalRep.listValue.ele[idx] = newObjPtr;
    Jim_IncrRefCount(newObjPtr);
    return JIM_OK;
}

int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
    Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
{
    Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
    int shared, i, idx;

    varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED);
    if (objPtr == NULL)







|







11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642
11643
11644
        idx = listPtr->internalRep.listValue.len + idx;
    Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]);
    listPtr->internalRep.listValue.ele[idx] = newObjPtr;
    Jim_IncrRefCount(newObjPtr);
    return JIM_OK;
}

int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
    Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
{
    Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
    int shared, i, idx;

    varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED);
    if (objPtr == NULL)
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen)
{
    int i;
    int listLen = Jim_ListLength(interp, listObjPtr);
    Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);

    for (i = 0; i < listLen; ) {
        Jim_Obj *objPtr;

        Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
        Jim_AppendObj(interp, resObjPtr, objPtr);
        if (++i != listLen) {
            Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
        }
    }
    return resObjPtr;
}








<
<
<
|







11678
11679
11680
11681
11682
11683
11684



11685
11686
11687
11688
11689
11690
11691
11692
Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen)
{
    int i;
    int listLen = Jim_ListLength(interp, listObjPtr);
    Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);

    for (i = 0; i < listLen; ) {



        Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
        if (++i != listLen) {
            Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
        }
    }
    return resObjPtr;
}

11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495

11496
11497
11498
11499
11500

11501
11502
11503
11504
11505
11506
11507
    else {
        
        int len = 0, objLen;
        char *bytes, *p;

        
        for (i = 0; i < objc; i++) {
            Jim_GetString(objv[i], &objLen);
            len += objLen;
        }
        if (objc)
            len += objc - 1;
        
        p = bytes = Jim_Alloc(len + 1);
        for (i = 0; i < objc; i++) {
            const char *s = Jim_GetString(objv[i], &objLen);

            
            while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
                s++;
                objLen--;
                len--;
            }
            
            while (objLen && (s[objLen - 1] == ' ' ||
                    s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
                
                if (objLen > 1 && s[objLen - 2] == '\\') {
                    break;
                }
                objLen--;
                len--;
            }
            memcpy(p, s, objLen);
            p += objLen;

            if (objLen && i + 1 != objc) {
                *p++ = ' ';
            }
            else if (i + 1 != objc) {
                len--;

            }
        }
        *p = '\0';
        return Jim_NewStringObjNoAlloc(interp, bytes, len);
    }
}








<
|









|





|
<









>
|
|
<
|
|
>







11708
11709
11710
11711
11712
11713
11714

11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731

11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743

11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
    else {
        
        int len = 0, objLen;
        char *bytes, *p;

        
        for (i = 0; i < objc; i++) {

            len += Jim_Length(objv[i]);
        }
        if (objc)
            len += objc - 1;
        
        p = bytes = Jim_Alloc(len + 1);
        for (i = 0; i < objc; i++) {
            const char *s = Jim_GetString(objv[i], &objLen);

            
            while (objLen && isspace(UCHAR(*s))) {
                s++;
                objLen--;
                len--;
            }
            
            while (objLen && isspace(UCHAR(s[objLen - 1]))) {

                
                if (objLen > 1 && s[objLen - 2] == '\\') {
                    break;
                }
                objLen--;
                len--;
            }
            memcpy(p, s, objLen);
            p += objLen;
            if (i + 1 != objc) {
                if (objLen)
                    *p++ = ' ';

                else {
                    len--;
                }
            }
        }
        *p = '\0';
        return Jim_NewStringObjNoAlloc(interp, bytes, len);
    }
}

11537
11538
11539
11540
11541
11542
11543






11544
11545
11546
11547
11548
11549
11550
11551
11552
11553


11554
11555
11556
11557
11558
11559
11560
    return Jim_GenHashFunction((const unsigned char *)str, len);
}

static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
{
    return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
}







static void JimObjectHTKeyValDestructor(void *interp, void *val)
{
    Jim_DecrRefCount(interp, (Jim_Obj *)val);
}

static const Jim_HashTableType JimDictHashTableType = {
    JimObjectHTHashFunction,    
    NULL,                       
    NULL,                       


    JimObjectHTKeyCompare,      
    JimObjectHTKeyValDestructor,    
    JimObjectHTKeyValDestructor 
};

static const Jim_ObjType dictObjType = {
    "dict",







>
>
>
>
>
>








<
<
>
>







11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803


11804
11805
11806
11807
11808
11809
11810
11811
11812
    return Jim_GenHashFunction((const unsigned char *)str, len);
}

static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
{
    return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
}

static void *JimObjectHTKeyValDup(void *privdata, const void *val)
{
    Jim_IncrRefCount((Jim_Obj *)val);
    return (void *)val;
}

static void JimObjectHTKeyValDestructor(void *interp, void *val)
{
    Jim_DecrRefCount(interp, (Jim_Obj *)val);
}

static const Jim_HashTableType JimDictHashTableType = {
    JimObjectHTHashFunction,    


    JimObjectHTKeyValDup,       
    JimObjectHTKeyValDup,       
    JimObjectHTKeyCompare,      
    JimObjectHTKeyValDestructor,    
    JimObjectHTKeyValDestructor 
};

static const Jim_ObjType dictObjType = {
    "dict",
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
    dupHt = Jim_Alloc(sizeof(*dupHt));
    Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
    if (ht->size != 0)
        Jim_ExpandHashTable(dupHt, ht->size);
    
    JimInitHashTableIterator(ht, &htiter);
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
        const Jim_Obj *keyObjPtr = he->key;
        Jim_Obj *valObjPtr = he->u.val;

        Jim_IncrRefCount((Jim_Obj *)keyObjPtr); 
        Jim_IncrRefCount(valObjPtr);
        Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
    }

    dupPtr->internalRep.ptr = dupHt;
    dupPtr->typePtr = &dictObjType;
}

static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)







<
<
<
<
<
|







11835
11836
11837
11838
11839
11840
11841





11842
11843
11844
11845
11846
11847
11848
11849
    dupHt = Jim_Alloc(sizeof(*dupHt));
    Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
    if (ht->size != 0)
        Jim_ExpandHashTable(dupHt, ht->size);
    
    JimInitHashTableIterator(ht, &htiter);
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {





        Jim_AddHashEntry(dupHt, he->key, he->u.val);
    }

    dupPtr->internalRep.ptr = dupHt;
    dupPtr->typePtr = &dictObjType;
}

static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629

11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642

11643

11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
    ht = dictPtr->internalRep.ptr;

    
    objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
    JimInitHashTableIterator(ht, &htiter);
    i = 0;
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
        objv[i++] = (Jim_Obj *)he->key;
        objv[i++] = he->u.val;
    }
    *len = i;
    return objv;
}

static void UpdateStringOfDict(struct Jim_Obj *objPtr)
{
    
    int len;
    Jim_Obj **objv = JimDictPairs(objPtr, &len);


    JimMakeListStringRep(objPtr, objv, len);

    Jim_Free(objv);
}

static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
    int listlen;

    if (objPtr->typePtr == &dictObjType) {
        return JIM_OK;
    }


    Jim_String(objPtr);


    
    listlen = Jim_ListLength(interp, objPtr);
    if (listlen % 2) {
        Jim_SetResultString(interp, "missing value to go with key", -1);
        return JIM_ERR;
    }
    else {
        
        Jim_HashTable *ht;
        int i;

        ht = Jim_Alloc(sizeof(*ht));
        Jim_InitHashTable(ht, &JimDictHashTableType, interp);

        for (i = 0; i < listlen; i += 2) {
            Jim_Obj *keyObjPtr;
            Jim_Obj *valObjPtr;

            Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
            Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);

            Jim_IncrRefCount(keyObjPtr);
            Jim_IncrRefCount(valObjPtr);

            if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
                Jim_HashEntry *he;

                he = Jim_FindHashEntry(ht, keyObjPtr);
                Jim_DecrRefCount(interp, keyObjPtr);
                
                Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
                he->u.val = valObjPtr;
            }
        }

        Jim_FreeIntRep(interp, objPtr);
        objPtr->typePtr = &dictObjType;
        objPtr->internalRep.ptr = ht;

        return JIM_OK;
    }
}



static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
    Jim_HashTable *ht = objPtr->internalRep.ptr;

    if (valueObjPtr == NULL) {  
        return Jim_DeleteHashEntry(ht, keyObjPtr);
    }
    Jim_IncrRefCount(keyObjPtr);
    Jim_IncrRefCount(valueObjPtr);
    if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
        
        Jim_DecrRefCount(interp, keyObjPtr);
    }
    return JIM_OK;
}

int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
    int retcode;

    JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
        return JIM_ERR;
    }
    retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
    Jim_InvalidateStringRep(objPtr);
    return retcode;
}

Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
{
    Jim_Obj *objPtr;
    int i;








|
|











>













>
|
>
















|
|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<




















<
<
|
<
<
<






<
<




<

|







11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912






11913








11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933


11934



11935
11936
11937
11938
11939
11940


11941
11942
11943
11944

11945
11946
11947
11948
11949
11950
11951
11952
11953
    ht = dictPtr->internalRep.ptr;

    
    objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
    JimInitHashTableIterator(ht, &htiter);
    i = 0;
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
        objv[i++] = Jim_GetHashEntryKey(he);
        objv[i++] = Jim_GetHashEntryVal(he);
    }
    *len = i;
    return objv;
}

static void UpdateStringOfDict(struct Jim_Obj *objPtr)
{
    
    int len;
    Jim_Obj **objv = JimDictPairs(objPtr, &len);

    
    JimMakeListStringRep(objPtr, objv, len);

    Jim_Free(objv);
}

static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
    int listlen;

    if (objPtr->typePtr == &dictObjType) {
        return JIM_OK;
    }

    if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
        Jim_String(objPtr);
    }

    
    listlen = Jim_ListLength(interp, objPtr);
    if (listlen % 2) {
        Jim_SetResultString(interp, "missing value to go with key", -1);
        return JIM_ERR;
    }
    else {
        
        Jim_HashTable *ht;
        int i;

        ht = Jim_Alloc(sizeof(*ht));
        Jim_InitHashTable(ht, &JimDictHashTableType, interp);

        for (i = 0; i < listlen; i += 2) {
            Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
            Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);







            Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);








        }

        Jim_FreeIntRep(interp, objPtr);
        objPtr->typePtr = &dictObjType;
        objPtr->internalRep.ptr = ht;

        return JIM_OK;
    }
}



static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
    Jim_HashTable *ht = objPtr->internalRep.ptr;

    if (valueObjPtr == NULL) {  
        return Jim_DeleteHashEntry(ht, keyObjPtr);
    }


    Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);



    return JIM_OK;
}

int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{


    JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
        return JIM_ERR;
    }

    Jim_InvalidateStringRep(objPtr);
    return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
}

Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
{
    Jim_Obj *objPtr;
    int i;

11842
11843
11844
11845
11846
11847
11848

11849
11850
11851
11852
11853
11854
11855
            if (newObjPtr == NULL) {
                goto err;
            }
            objPtr = Jim_NewDictObj(interp, NULL, 0);
            DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
        }
    }

    Jim_InvalidateStringRep(objPtr);
    Jim_InvalidateStringRep(varObjPtr);
    if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
        goto err;
    }
    Jim_SetResult(interp, varObjPtr);
    return JIM_OK;







>







12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
            if (newObjPtr == NULL) {
                goto err;
            }
            objPtr = Jim_NewDictObj(interp, NULL, 0);
            DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
        }
    }
    
    Jim_InvalidateStringRep(objPtr);
    Jim_InvalidateStringRep(varObjPtr);
    if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
        goto err;
    }
    Jim_SetResult(interp, varObjPtr);
    return JIM_OK;
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878


11879
11880
11881
11882

11883

11884
11885
11886
11887
11888
11889
11890

11891
11892
11893
11894
11895
11896
11897
11898
    "index",
    NULL,
    NULL,
    UpdateStringOfIndex,
    JIM_TYPE_NONE,
};

void UpdateStringOfIndex(struct Jim_Obj *objPtr)
{
    int len;
    char buf[JIM_INTEGER_SPACE + 1];



    if (objPtr->internalRep.intValue >= 0)
        len = sprintf(buf, "%d", objPtr->internalRep.intValue);
    else if (objPtr->internalRep.intValue == -1)
        len = sprintf(buf, "end");

    else {

        len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
    }
    objPtr->bytes = Jim_Alloc(len + 1);
    memcpy(objPtr->bytes, buf, len + 1);
    objPtr->length = len;
}


int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int idx, end = 0;
    const char *str;
    char *endptr;

    
    str = Jim_String(objPtr);







|

|
|
|
>
>
|
|
<
<
>
|
>
|
|
<
<
|
|
|
>
|







12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111


12112
12113
12114
12115
12116


12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
    "index",
    NULL,
    NULL,
    UpdateStringOfIndex,
    JIM_TYPE_NONE,
};

static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
{
    if (objPtr->internalRep.intValue == -1) {
        JimSetStringBytes(objPtr, "end");
    }
    else {
        char buf[JIM_INTEGER_SPACE + 1];
        if (objPtr->internalRep.intValue >= 0) {
            sprintf(buf, "%d", objPtr->internalRep.intValue);


        }
        else {
            
            sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
        }


        JimSetStringBytes(objPtr, buf);
    }
}

static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int idx, end = 0;
    const char *str;
    char *endptr;

    
    str = Jim_String(objPtr);
11956
11957
11958
11959
11960
11961
11962
11963




11964
11965
11966
11967
11968
11969
11970
11971
11972
11973

int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
{
    
    if (objPtr->typePtr == &intObjType) {
        jim_wide val = JimWideValue(objPtr);

        if (!(val < LONG_MIN) && !(val > LONG_MAX)) {




            *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
            return JIM_OK;
        }
    }
    if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
        return JIM_ERR;
    *indexPtr = objPtr->internalRep.intValue;
    return JIM_OK;
}








|
>
>
>
>
|
|
<







12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199

12200
12201
12202
12203
12204
12205
12206

int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
{
    
    if (objPtr->typePtr == &intObjType) {
        jim_wide val = JimWideValue(objPtr);

        if (val < 0)
            *indexPtr = -INT_MAX;
        else if (val > INT_MAX)
            *indexPtr = INT_MAX;
        else
            *indexPtr = (int)val;
        return JIM_OK;

    }
    if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
        return JIM_ERR;
    *indexPtr = objPtr->internalRep.intValue;
    return JIM_OK;
}

11983
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
    "exit",
    "eval",
    NULL
};

#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))

static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);

static const Jim_ObjType returnCodeObjType = {
    "return-code",
    NULL,
    NULL,
    NULL,
    JIM_TYPE_NONE,
};

const char *Jim_ReturnCode(int code)
{
    if (code < 0 || code >= (int)jimReturnCodesSize) {
        return "?";
    }
    else {
        return jimReturnCodes[code];
    }
}

int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int returnCode;
    jim_wide wideValue;

    
    if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
        returnCode = (int)wideValue;







<
<


















|







12216
12217
12218
12219
12220
12221
12222


12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
    "exit",
    "eval",
    NULL
};

#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))



static const Jim_ObjType returnCodeObjType = {
    "return-code",
    NULL,
    NULL,
    NULL,
    JIM_TYPE_NONE,
};

const char *Jim_ReturnCode(int code)
{
    if (code < 0 || code >= (int)jimReturnCodesSize) {
        return "?";
    }
    else {
        return jimReturnCodes[code];
    }
}

static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    int returnCode;
    jim_wide wideValue;

    
    if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
        returnCode = (int)wideValue;
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175

12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208

12209

12210
12211
12212

12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
static Jim_Obj *ExprPop(struct JimExprState *e)
{
    return e->stack[--e->stacklen];
}

static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
{
    int intresult = 0;
    int rc = JIM_OK;
    Jim_Obj *A = ExprPop(e);
    double dA, dC = 0;
    jim_wide wA, wC = 0;

    if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
        intresult = 1;

        switch (e->opcode) {
            case JIM_EXPROP_FUNC_INT:
                wC = wA;
                break;
            case JIM_EXPROP_FUNC_ROUND:

                wC = wA;
                break;
            case JIM_EXPROP_FUNC_DOUBLE:
                dC = wA;
                intresult = 0;
                break;
            case JIM_EXPROP_FUNC_ABS:
                wC = wA >= 0 ? wA : -wA;
                break;
            case JIM_EXPROP_UNARYMINUS:
                wC = -wA;
                break;
            case JIM_EXPROP_UNARYPLUS:
                wC = wA;
                break;
            case JIM_EXPROP_NOT:
                wC = !wA;
                break;
            default:
                abort();
        }
    }
    else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
        switch (e->opcode) {
            case JIM_EXPROP_FUNC_INT:
                wC = dA;
                intresult = 1;
                break;
            case JIM_EXPROP_FUNC_ROUND:
                wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
                intresult = 1;
                break;
            case JIM_EXPROP_FUNC_DOUBLE:

                dC = dA;

                break;
            case JIM_EXPROP_FUNC_ABS:
                dC = dA >= 0 ? dA : -dA;

                break;
            case JIM_EXPROP_UNARYMINUS:
                dC = -dA;
                break;
            case JIM_EXPROP_UNARYPLUS:
                dC = dA;
                break;
            case JIM_EXPROP_NOT:
                wC = !dA;
                intresult = 1;
                break;
            default:
                abort();
        }
    }

    if (rc == JIM_OK) {







|






<
<


<
<

>












<
<
<











<



<


>

>



>



<
<
|



<







12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399


12400
12401


12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415



12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426

12427
12428
12429

12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441


12442
12443
12444
12445

12446
12447
12448
12449
12450
12451
12452
static Jim_Obj *ExprPop(struct JimExprState *e)
{
    return e->stack[--e->stacklen];
}

static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
{
    int intresult = 1;
    int rc = JIM_OK;
    Jim_Obj *A = ExprPop(e);
    double dA, dC = 0;
    jim_wide wA, wC = 0;

    if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {


        switch (e->opcode) {
            case JIM_EXPROP_FUNC_INT:


            case JIM_EXPROP_FUNC_ROUND:
            case JIM_EXPROP_UNARYPLUS:
                wC = wA;
                break;
            case JIM_EXPROP_FUNC_DOUBLE:
                dC = wA;
                intresult = 0;
                break;
            case JIM_EXPROP_FUNC_ABS:
                wC = wA >= 0 ? wA : -wA;
                break;
            case JIM_EXPROP_UNARYMINUS:
                wC = -wA;
                break;



            case JIM_EXPROP_NOT:
                wC = !wA;
                break;
            default:
                abort();
        }
    }
    else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
        switch (e->opcode) {
            case JIM_EXPROP_FUNC_INT:
                wC = dA;

                break;
            case JIM_EXPROP_FUNC_ROUND:
                wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);

                break;
            case JIM_EXPROP_FUNC_DOUBLE:
            case JIM_EXPROP_UNARYPLUS:
                dC = dA;
                intresult = 0;
                break;
            case JIM_EXPROP_FUNC_ABS:
                dC = dA >= 0 ? dA : -dA;
                intresult = 0;
                break;
            case JIM_EXPROP_UNARYMINUS:
                dC = -dA;


                intresult = 0;
                break;
            case JIM_EXPROP_NOT:
                wC = !dA;

                break;
            default:
                abort();
        }
    }

    if (rc == JIM_OK) {
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
    return rc;
}



static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
{
    int intresult = 0;
    int rc = JIM_OK;
    double dA, dB, dC = 0;
    jim_wide wA, wB, wC = 0;

    Jim_Obj *B = ExprPop(e);
    Jim_Obj *A = ExprPop(e);

    if ((A->typePtr != &doubleObjType || A->bytes) &&
        (B->typePtr != &doubleObjType || B->bytes) &&
        JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {

        

        intresult = 1;

        switch (e->opcode) {
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
                wC = JimPowWide(wA, wB);
                break;
            case JIM_EXPROP_ADD:
                wC = wA + wB;







|













<
<







12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
12673


12674
12675
12676
12677
12678
12679
12680
    return rc;
}



static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
{
    int intresult = 1;
    int rc = JIM_OK;
    double dA, dB, dC = 0;
    jim_wide wA, wB, wC = 0;

    Jim_Obj *B = ExprPop(e);
    Jim_Obj *A = ExprPop(e);

    if ((A->typePtr != &doubleObjType || A->bytes) &&
        (B->typePtr != &doubleObjType || B->bytes) &&
        JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {

        



        switch (e->opcode) {
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
                wC = JimPowWide(wA, wB);
                break;
            case JIM_EXPROP_ADD:
                wC = wA + wB;
12499
12500
12501
12502
12503
12504
12505

12506
12507
12508
12509
12510
12511
12512
                wC = wA != wB;
                break;
            default:
                abort();
        }
    }
    else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {

        switch (e->opcode) {
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
#ifdef JIM_MATH_FUNCTIONS
                dC = pow(dA, dB);
#else
                Jim_SetResultString(interp, "unsupported", -1);







>







12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
                wC = wA != wB;
                break;
            default:
                abort();
        }
    }
    else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
        intresult = 0;
        switch (e->opcode) {
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
#ifdef JIM_MATH_FUNCTIONS
                dC = pow(dA, dB);
#else
                Jim_SetResultString(interp, "unsupported", -1);
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
    }
    else {
        

        
        int i = Jim_StringCompareObj(interp, A, B, 0);

        intresult = 1;

        switch (e->opcode) {
            case JIM_EXPROP_LT:
                wC = i < 0;
                break;
            case JIM_EXPROP_GT:
                wC = i > 0;
                break;







<
<







12786
12787
12788
12789
12790
12791
12792


12793
12794
12795
12796
12797
12798
12799
    }
    else {
        

        
        int i = Jim_StringCompareObj(interp, A, B, 0);



        switch (e->opcode) {
            case JIM_EXPROP_LT:
                wC = i < 0;
                break;
            case JIM_EXPROP_GT:
                wC = i > 0;
                break;
12613
12614
12615
12616
12617
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657
12658
12659
static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
{
    int listlen;
    int i;

    listlen = Jim_ListLength(interp, listObjPtr);
    for (i = 0; i < listlen; i++) {
        Jim_Obj *objPtr;

        Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);

        if (Jim_StringEqObj(objPtr, valObj)) {
            return 1;
        }
    }
    return 0;
}

static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
{
    Jim_Obj *B = ExprPop(e);
    Jim_Obj *A = ExprPop(e);

    jim_wide wC;

    switch (e->opcode) {
        case JIM_EXPROP_STREQ:
        case JIM_EXPROP_STRNE: {
            int Alen, Blen;
            const char *sA = Jim_GetString(A, &Alen);
            const char *sB = Jim_GetString(B, &Blen);

            if (e->opcode == JIM_EXPROP_STREQ) {
                wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
            }
            else {
                wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
            }
            break;
        }
        case JIM_EXPROP_STRIN:
            wC = JimSearchList(interp, B, A);
            break;
        case JIM_EXPROP_STRNI:
            wC = !JimSearchList(interp, B, A);
            break;
        default:







<
<
<
<
|















|
<
<
<
|
|
|

<
<
<

<







12833
12834
12835
12836
12837
12838
12839




12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856



12857
12858
12859
12860



12861

12862
12863
12864
12865
12866
12867
12868
static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
{
    int listlen;
    int i;

    listlen = Jim_ListLength(interp, listObjPtr);
    for (i = 0; i < listlen; i++) {




        if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
            return 1;
        }
    }
    return 0;
}

static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
{
    Jim_Obj *B = ExprPop(e);
    Jim_Obj *A = ExprPop(e);

    jim_wide wC;

    switch (e->opcode) {
        case JIM_EXPROP_STREQ:
        case JIM_EXPROP_STRNE:



            wC = Jim_StringEqObj(A, B);
            if (e->opcode == JIM_EXPROP_STRNE) {
                wC = !wC;
            }



            break;

        case JIM_EXPROP_STRIN:
            wC = JimSearchList(interp, B, A);
            break;
        case JIM_EXPROP_STRNI:
            wC = !JimSearchList(interp, B, A);
            break;
        default:
12821
12822
12823
12824
12825
12826
12827

12828
12829
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913

12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928




12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
{
    LAZY_NONE,
    LAZY_OP,
    LAZY_LEFT,
    LAZY_RIGHT
};


#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}

static const struct Jim_ExprOperator Jim_ExprOperators[] = {
    OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),

    OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),

    OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
    OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),

    OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
    OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),

    OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),

    OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
    OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),

    OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
    OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
    OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),

    OPRINIT("&&", 10, 2, NULL, LAZY_OP),
    OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
    OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),

    OPRINIT("||", 9, 2, NULL, LAZY_OP),
    OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
    OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),

    OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
    OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
    OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),

    OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
    OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
    OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),

    OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),

    OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
    OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),

    OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
    OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),

    OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),



    OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
    OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
    OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),

#ifdef JIM_MATH_FUNCTIONS
    OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
    OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
#endif
};
#undef OPRINIT


#define JIM_EXPR_OPERATORS_NUM \
    (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))

static int JimParseExpression(struct JimParserCtx *pc)
{
    
    while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
        if (*pc->p == '\n') {
            pc->linenr++;
        }
        pc->p++;
        pc->len--;
    }





    if (pc->len == 0) {
        pc->tstart = pc->tend = pc->p;
        pc->tline = pc->linenr;
        pc->tt = JIM_TT_EOL;
        pc->eof = 1;
        return JIM_OK;
    }
    switch (*(pc->p)) {
        case '(':
                pc->tt = JIM_TT_SUBEXPR_START;
                goto singlechar;
        case ')':
                pc->tt = JIM_TT_SUBEXPR_END;
                goto singlechar;
        case ',':
            pc->tt = JIM_TT_SUBEXPR_COMMA;
singlechar:
            pc->tstart = pc->tend = pc->p;
            pc->tline = pc->linenr;
            pc->p++;
            pc->len--;
            break;
        case '[':
            return JimParseCmd(pc);
        case '$':
            if (JimParseVar(pc) == JIM_ERR)







>
|


|
|
|

|
|

|
|

|
|

|
|
|
|

|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|

|
|

|
|

|
|
|
|



|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



>















>
>
>
>

|
<














|
<







13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145

13146
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158
13159
13160

13161
13162
13163
13164
13165
13166
13167
{
    LAZY_NONE,
    LAZY_OP,
    LAZY_LEFT,
    LAZY_RIGHT
};

#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}

static const struct Jim_ExprOperator Jim_ExprOperators[] = {
    OPRINIT("*", 110, 2, JimExprOpBin),
    OPRINIT("/", 110, 2, JimExprOpBin),
    OPRINIT("%", 110, 2, JimExprOpIntBin),

    OPRINIT("-", 100, 2, JimExprOpBin),
    OPRINIT("+", 100, 2, JimExprOpBin),

    OPRINIT("<<", 90, 2, JimExprOpIntBin),
    OPRINIT(">>", 90, 2, JimExprOpIntBin),

    OPRINIT("<<<", 90, 2, JimExprOpIntBin),
    OPRINIT(">>>", 90, 2, JimExprOpIntBin),

    OPRINIT("<", 80, 2, JimExprOpBin),
    OPRINIT(">", 80, 2, JimExprOpBin),
    OPRINIT("<=", 80, 2, JimExprOpBin),
    OPRINIT(">=", 80, 2, JimExprOpBin),

    OPRINIT("==", 70, 2, JimExprOpBin),
    OPRINIT("!=", 70, 2, JimExprOpBin),

    OPRINIT("&", 50, 2, JimExprOpIntBin),
    OPRINIT("^", 49, 2, JimExprOpIntBin),
    OPRINIT("|", 48, 2, JimExprOpIntBin),

    OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
    OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
    OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),

    OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
    OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
    OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),

    OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
    OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
    OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),

    OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
    OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
    OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),

    OPRINIT("**", 250, 2, JimExprOpBin),

    OPRINIT("eq", 60, 2, JimExprOpStrBin),
    OPRINIT("ne", 60, 2, JimExprOpStrBin),

    OPRINIT("in", 55, 2, JimExprOpStrBin),
    OPRINIT("ni", 55, 2, JimExprOpStrBin),

    OPRINIT("!", 150, 1, JimExprOpNumUnary),
    OPRINIT("~", 150, 1, JimExprOpIntUnary),
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),



    OPRINIT("int", 200, 1, JimExprOpNumUnary),
    OPRINIT("abs", 200, 1, JimExprOpNumUnary),
    OPRINIT("double", 200, 1, JimExprOpNumUnary),
    OPRINIT("round", 200, 1, JimExprOpNumUnary),
    OPRINIT("rand", 200, 0, JimExprOpNone),
    OPRINIT("srand", 200, 1, JimExprOpIntUnary),

#ifdef JIM_MATH_FUNCTIONS
    OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
    OPRINIT("pow", 200, 2, JimExprOpBin),
#endif
};
#undef OPRINIT
#undef OPRINIT_LAZY

#define JIM_EXPR_OPERATORS_NUM \
    (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))

static int JimParseExpression(struct JimParserCtx *pc)
{
    
    while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
        if (*pc->p == '\n') {
            pc->linenr++;
        }
        pc->p++;
        pc->len--;
    }

    
    pc->tline = pc->linenr;
    pc->tstart = pc->p;

    if (pc->len == 0) {
        pc->tend = pc->p;

        pc->tt = JIM_TT_EOL;
        pc->eof = 1;
        return JIM_OK;
    }
    switch (*(pc->p)) {
        case '(':
                pc->tt = JIM_TT_SUBEXPR_START;
                goto singlechar;
        case ')':
                pc->tt = JIM_TT_SUBEXPR_END;
                goto singlechar;
        case ',':
            pc->tt = JIM_TT_SUBEXPR_COMMA;
singlechar:
            pc->tend = pc->p;

            pc->p++;
            pc->len--;
            break;
        case '[':
            return JimParseCmd(pc);
        case '$':
            if (JimParseVar(pc) == JIM_ERR)
12990
12991
12992
12993
12994
12995
12996
12997
12998
12999
13000
13001
13002
13003
13004

13005
13006
13007
13008
13009
13010
13011
13012
13013
13014
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048
13049
13050
13051

13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
            break;
    }
    return JIM_OK;
}

static int JimParseExprNumber(struct JimParserCtx *pc)
{
    int allowdot = 1;
    int base = 10;

    
    pc->tt = JIM_TT_EXPR_INT;
    pc->tstart = pc->p;
    pc->tline = pc->linenr;


    
    if (pc->p[0] == '0') {
        switch (pc->p[1]) {
            case 'x':
            case 'X':
                base = 16;
                allowdot = 0;
                pc->p += 2;
                pc->len -= 2;
                break;
            case 'o':
            case 'O':
                base = 8;
                allowdot = 0;
                pc->p += 2;
                pc->len -= 2;
                break;
            case 'b':
            case 'B':
                base = 2;
                allowdot = 0;
                pc->p += 2;
                pc->len -= 2;
                break;
        }
    }

    while (isdigit(UCHAR(*pc->p))
        || (base == 16 && isxdigit(UCHAR(*pc->p)))
        || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
        || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
        || (allowdot && *pc->p == '.')
        ) {
        if (*pc->p == '.') {
            allowdot = 0;
            pc->tt = JIM_TT_EXPR_DOUBLE;
        }
        pc->p++;
        pc->len--;
        if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
                || isdigit(UCHAR(pc->p[1])))) {
            pc->p += 2;
            pc->len -= 2;
            pc->tt = JIM_TT_EXPR_DOUBLE;
        }
    }
    pc->tend = pc->p - 1;

    return JIM_OK;
}

static int JimParseExprIrrational(struct JimParserCtx *pc)
{
    const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
    const char **token;

    for (token = Tokens; *token != NULL; token++) {
        int len = strlen(*token);

        if (strncmp(*token, pc->p, len) == 0) {
            pc->tstart = pc->p;
            pc->tend = pc->p + len - 1;
            pc->p += len;
            pc->len -= len;
            pc->tline = pc->linenr;
            pc->tt = JIM_TT_EXPR_DOUBLE;
            return JIM_OK;
        }
    }
    return JIM_ERR;
}








|
<



<
<

>

<
<
<
<
<
<
|
|
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
|
<
<



>





|
|

|
|

|
<
<
|
|
|







13203
13204
13205
13206
13207
13208
13209
13210

13211
13212
13213


13214
13215
13216






13217
13218





13219

13220




13221


13222










13223





13224


13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240


13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
            break;
    }
    return JIM_OK;
}

static int JimParseExprNumber(struct JimParserCtx *pc)
{
    char *end;


    
    pc->tt = JIM_TT_EXPR_INT;



    jim_strtoull(pc->p, (char **)&pc->p);
    






    if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
        if (strtod(pc->tstart, &end)) {  }





        if (end == pc->tstart)

            return JIM_ERR;




        if (end > pc->p) {


            










            pc->tt = JIM_TT_EXPR_DOUBLE;





            pc->p = end;


        }
    }
    pc->tend = pc->p - 1;
    pc->len -= (pc->p - pc->tstart);
    return JIM_OK;
}

static int JimParseExprIrrational(struct JimParserCtx *pc)
{
    const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
    int i;

    for (i = 0; irrationals[i]; i++) {
        const char *irr = irrationals[i];

        if (strncmp(irr, pc->p, 3) == 0) {


            pc->p += 3;
            pc->len -= 3;
            pc->tend = pc->p - 1;
            pc->tt = JIM_TT_EXPR_DOUBLE;
            return JIM_OK;
        }
    }
    return JIM_ERR;
}

13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
            len--;
            p++;
        }
        if (*p != '(') {
            return JIM_ERR;
        }
    }
    pc->tstart = pc->p;
    pc->tend = pc->p + bestLen - 1;
    pc->p += bestLen;
    pc->len -= bestLen;
    pc->tline = pc->linenr;

    pc->tt = bestIdx;
    return JIM_OK;
}

static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
{







<



<







13280
13281
13282
13283
13284
13285
13286

13287
13288
13289

13290
13291
13292
13293
13294
13295
13296
            len--;
            p++;
        }
        if (*p != '(') {
            return JIM_ERR;
        }
    }

    pc->tend = pc->p + bestLen - 1;
    pc->p += bestLen;
    pc->len -= bestLen;


    pc->tt = bestIdx;
    return JIM_OK;
}

static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
{
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624






13625
13626
13627
13628
13629
13630
13631
        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
            parser.tline);
    }

#ifdef DEBUG_SHOW_EXPR_TOKENS
    {
        int i;
        printf("==== Expr Tokens ====\n");
        for (i = 0; i < tokenlist.count; i++) {
            printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
                tokenlist.list[i].len, tokenlist.list[i].token);
        }
    }
#endif







    
    expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);

    
    ScriptTokenListFree(&tokenlist);








|






>
>
>
>
>
>







13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
            parser.tline);
    }

#ifdef DEBUG_SHOW_EXPR_TOKENS
    {
        int i;
        printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
        for (i = 0; i < tokenlist.count; i++) {
            printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
                tokenlist.list[i].len, tokenlist.list[i].token);
        }
    }
#endif

    if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
        ScriptTokenListFree(&tokenlist);
        Jim_DecrRefCount(interp, fileNameObj);
        return JIM_ERR;
    }

    
    expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);

    
    ScriptTokenListFree(&tokenlist);

13668
13669
13670
13671
13672
13673
13674














13675
13676
13677
13678
13679
13680
13681
    if (objPtr->typePtr != &exprObjType) {
        if (SetExprFromAny(interp, objPtr) != JIM_OK) {
            return NULL;
        }
    }
    return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
}















#define JIM_EE_STATICSTACK_LEN 10

int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
{
    ExprByteCode *expr;
    Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];







>
>
>
>
>
>
>
>
>
>
>
>
>
>







13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
    if (objPtr->typePtr != &exprObjType) {
        if (SetExprFromAny(interp, objPtr) != JIM_OK) {
            return NULL;
        }
    }
    return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
}

#ifdef JIM_OPTIMIZATION
static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
{
    if (token->type == JIM_TT_EXPR_INT)
        return token->objPtr;
    else if (token->type == JIM_TT_VAR)
        return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
    else if (token->type == JIM_TT_DICTSUGAR)
        return JimExpandDictSugar(interp, token->objPtr);
    else
        return NULL;
}
#endif

#define JIM_EE_STATICSTACK_LEN 10

int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
{
    ExprByteCode *expr;
    Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708
13709
13710
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789

13790
13791
13792
13793
13794
13795
13796
#ifdef JIM_OPTIMIZATION
    {
        Jim_Obj *objPtr;


        switch (expr->len) {
            case 1:
                if (expr->token[0].type == JIM_TT_EXPR_INT) {
                    *exprResultPtrPtr = expr->token[0].objPtr;
                    Jim_IncrRefCount(*exprResultPtrPtr);
                    return JIM_OK;
                }
                if (expr->token[0].type == JIM_TT_VAR) {
                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
                    if (objPtr) {
                        *exprResultPtrPtr = objPtr;
                        Jim_IncrRefCount(*exprResultPtrPtr);
                        return JIM_OK;
                    }
                }
                break;

            case 2:
                if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
                    jim_wide wideValue;

                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
                    if (objPtr && JimIsWide(objPtr)
                        && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
                        *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
                        Jim_IncrRefCount(*exprResultPtrPtr);
                        return JIM_OK;
                    }
                }
                break;

            case 3:
                if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
                        || expr->token[1].type == JIM_TT_VAR)) {
                    switch (expr->token[2].type) {
                        case JIM_EXPROP_LT:
                        case JIM_EXPROP_LTE:
                        case JIM_EXPROP_GT:
                        case JIM_EXPROP_GTE:
                        case JIM_EXPROP_NUMEQ:
                        case JIM_EXPROP_NUMNE:{
                                
                                jim_wide wideValueA;
                                jim_wide wideValueB;

                                objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
                                if (objPtr && JimIsWide(objPtr)
                                    && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
                                    if (expr->token[1].type == JIM_TT_VAR) {
                                        objPtr =
                                            Jim_GetVariable(interp, expr->token[1].objPtr,
                                            JIM_NONE);
                                    }
                                    else {
                                        objPtr = expr->token[1].objPtr;
                                    }
                                    if (objPtr && JimIsWide(objPtr)
                                        && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
                                        int cmpRes;

                                        switch (expr->token[2].type) {
                                            case JIM_EXPROP_LT:
                                                cmpRes = wideValueA < wideValueB;
                                                break;
                                            case JIM_EXPROP_LTE:
                                                cmpRes = wideValueA <= wideValueB;
                                                break;
                                            case JIM_EXPROP_GT:
                                                cmpRes = wideValueA > wideValueB;
                                                break;
                                            case JIM_EXPROP_GTE:
                                                cmpRes = wideValueA >= wideValueB;
                                                break;
                                            case JIM_EXPROP_NUMEQ:
                                                cmpRes = wideValueA == wideValueB;
                                                break;
                                            case JIM_EXPROP_NUMNE:
                                                cmpRes = wideValueA != wideValueB;
                                                break;
                                            default:   
                                                cmpRes = 0;
                                        }
                                        *exprResultPtrPtr =
                                            cmpRes ? interp->trueObj : interp->falseObj;
                                        Jim_IncrRefCount(*exprResultPtrPtr);
                                        return JIM_OK;
                                    }
                                }
                            }
                    }
                }
                break;
        }
    }

#endif

    expr->inUse++;

    

    if (expr->len > JIM_EE_STATICSTACK_LEN)







|
|
|
<
<
<
<
<
|
<
|
<




|
|

<
|
<
|







|
|
|
<
<
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
<
<
<



>







13884
13885
13886
13887
13888
13889
13890
13891
13892
13893





13894

13895

13896
13897
13898
13899
13900
13901
13902

13903

13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914






13915
13916
13917














13918

13919
13920
13921
13922
13923
13924
13925
13926
13927
13928
13929
13930
13931
13932
13933
13934
13935
13936
13937
13938
13939
13940

13941
13942
13943
13944
13945



13946
13947
13948
13949
13950
13951
13952
13953
13954
13955
13956
#ifdef JIM_OPTIMIZATION
    {
        Jim_Obj *objPtr;


        switch (expr->len) {
            case 1:
                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
                if (objPtr) {
                    Jim_IncrRefCount(objPtr);





                    *exprResultPtrPtr = objPtr;

                    return JIM_OK;

                }
                break;

            case 2:
                if (expr->token[1].type == JIM_EXPROP_NOT) {
                    objPtr = JimExprIntValOrVar(interp, &expr->token[0]);


                    if (objPtr && JimIsWide(objPtr)) {

                        *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
                        Jim_IncrRefCount(*exprResultPtrPtr);
                        return JIM_OK;
                    }
                }
                break;

            case 3:
                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
                if (objPtr && JimIsWide(objPtr)) {
                    Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);






                    if (objPtr2 && JimIsWide(objPtr2)) {
                        jim_wide wideValueA = JimWideValue(objPtr);
                        jim_wide wideValueB = JimWideValue(objPtr2);














                        int cmpRes;

                        switch (expr->token[2].type) {
                            case JIM_EXPROP_LT:
                                cmpRes = wideValueA < wideValueB;
                                break;
                            case JIM_EXPROP_LTE:
                                cmpRes = wideValueA <= wideValueB;
                                break;
                            case JIM_EXPROP_GT:
                                cmpRes = wideValueA > wideValueB;
                                break;
                            case JIM_EXPROP_GTE:
                                cmpRes = wideValueA >= wideValueB;
                                break;
                            case JIM_EXPROP_NUMEQ:
                                cmpRes = wideValueA == wideValueB;
                                break;
                            case JIM_EXPROP_NUMNE:
                                cmpRes = wideValueA != wideValueB;
                                break;
                            default:
                                goto noopt;
                        }

                        *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
                        Jim_IncrRefCount(*exprResultPtrPtr);
                        return JIM_OK;
                    }
                }



                break;
        }
    }
noopt:
#endif

    expr->inUse++;

    

    if (expr->len > JIM_EE_STATICSTACK_LEN)
13955
13956
13957
13958
13959
13960
13961
13962
13963
13964
13965
13966
13967
13968
13969
13970
13971
13972
13973
13974

    JIM_NOTUSED(interp);
    memcpy(newVec, srcPtr->internalRep.ptr, size);
    dupPtr->internalRep.ptr = newVec;
    dupPtr->typePtr = &scanFmtStringObjType;
}

void UpdateStringOfScanFmt(Jim_Obj *objPtr)
{
    char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;

    objPtr->bytes = Jim_StrDup(bytes);
    objPtr->length = strlen(bytes);
}


static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    ScanFmtStringObj *fmtObj;
    char *buffer;







|

|
<
<
<







14115
14116
14117
14118
14119
14120
14121
14122
14123
14124



14125
14126
14127
14128
14129
14130
14131

    JIM_NOTUSED(interp);
    memcpy(newVec, srcPtr->internalRep.ptr, size);
    dupPtr->internalRep.ptr = newVec;
    dupPtr->typePtr = &scanFmtStringObjType;
}

static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
{
    JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);



}


static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
    ScanFmtStringObj *fmtObj;
    char *buffer;
14174
14175
14176
14177
14178
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
    size_t anchor = pos;
    int i;
    Jim_Obj *tmpObj = NULL;

    
    *valObjPtr = 0;
    if (descr->prefix) {
        
        for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
            
            if (isspace(UCHAR(descr->prefix[i])))
                while (pos < strLen && isspace(UCHAR(str[pos])))
                    ++pos;
            else if (descr->prefix[i] != str[pos])
                break;          







<







14331
14332
14333
14334
14335
14336
14337

14338
14339
14340
14341
14342
14343
14344
    size_t anchor = pos;
    int i;
    Jim_Obj *tmpObj = NULL;

    
    *valObjPtr = 0;
    if (descr->prefix) {

        for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
            
            if (isspace(UCHAR(descr->prefix[i])))
                while (pos < strLen && isspace(UCHAR(str[pos])))
                    ++pos;
            else if (descr->prefix[i] != str[pos])
                break;          
14515
14516
14517
14518
14519
14520
14521
14522
14523
















14524
14525
14526



14527
14528
14529

14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545



14546
14547
14548
14549
14550
14551
14552

    return retcode;
}

static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
    int retcode;
    Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);

















    if (cmdPtr == NULL) {
        return JimUnknown(interp, objc, objv);
    }



    if (interp->evalDepth == interp->maxEvalDepth) {
        Jim_SetResultString(interp, "Infinite eval recursion", -1);
        return JIM_ERR;

    }
    interp->evalDepth++;

    
    JimIncrCmdRefCount(cmdPtr);
    Jim_SetEmptyResult(interp);
    if (cmdPtr->isproc) {
        retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
    }
    else {
        interp->cmdPrivData = cmdPtr->u.native.privData;
        retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
    }
    JimDecrCmdRefCount(interp, cmdPtr);
    interp->evalDepth--;




    return retcode;
}

int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
    int i, retcode;








|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>


|
>




<








<


>
>
>







14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681
14682
14683
14684
14685
14686
14687
14688
14689
14690
14691
14692
14693
14694
14695
14696
14697
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709

14710
14711
14712
14713
14714
14715
14716
14717

14718
14719
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729

    return retcode;
}

static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
    int retcode;
    Jim_Cmd *cmdPtr;

#if 0
    printf("invoke");
    int j;
    for (j = 0; j < objc; j++) {
        printf(" '%s'", Jim_String(objv[j]));
    }
    printf("\n");
#endif

    if (interp->framePtr->tailcallCmd) {
        
        cmdPtr = interp->framePtr->tailcallCmd;
        interp->framePtr->tailcallCmd = NULL;
    }
    else {
        cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
        if (cmdPtr == NULL) {
            return JimUnknown(interp, objc, objv);
        }
        JimIncrCmdRefCount(cmdPtr);
    }

    if (interp->evalDepth == interp->maxEvalDepth) {
        Jim_SetResultString(interp, "Infinite eval recursion", -1);
        retcode = JIM_ERR;
        goto out;
    }
    interp->evalDepth++;

    

    Jim_SetEmptyResult(interp);
    if (cmdPtr->isproc) {
        retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
    }
    else {
        interp->cmdPrivData = cmdPtr->u.native.privData;
        retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
    }

    interp->evalDepth--;

out:
    JimDecrCmdRefCount(interp, cmdPtr);

    return retcode;
}

int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
    int i, retcode;

14720
14721
14722
14723
14724
14725
14726





14727
14728
14729
14730
14731
14732
14733
        && token[2].type == JIM_TT_VAR) {
        
        objPtr->typePtr = &interpolatedObjType;
        objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
        objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
        Jim_IncrRefCount(intv[2]);
    }






    s = objPtr->bytes = Jim_Alloc(totlen + 1);
    objPtr->length = totlen;
    for (i = 0; i < tokens; i++) {
        if (intv[i]) {
            memcpy(s, intv[i]->bytes, intv[i]->length);
            s += intv[i]->length;







>
>
>
>
>







14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
        && token[2].type == JIM_TT_VAR) {
        
        objPtr->typePtr = &interpolatedObjType;
        objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
        objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
        Jim_IncrRefCount(intv[2]);
    }
    else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
        
        JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
    }


    s = objPtr->bytes = Jim_Alloc(totlen + 1);
    objPtr->length = totlen;
    for (i = 0; i < tokens; i++) {
        if (intv[i]) {
            memcpy(s, intv[i]->bytes, intv[i]->length);
            s += intv[i]->length;
14775
14776
14777
14778
14779
14780
14781




14782
14783
14784
14785
14786
14787
14788

    if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
        return JimEvalObjList(interp, scriptObjPtr);
    }

    Jim_IncrRefCount(scriptObjPtr);     
    script = Jim_GetScript(interp, scriptObjPtr);





    Jim_SetEmptyResult(interp);

    token = script->token;

#ifdef JIM_OPTIMIZATION
    if (script->len == 0) {







>
>
>
>







14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972
14973
14974

    if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
        return JimEvalObjList(interp, scriptObjPtr);
    }

    Jim_IncrRefCount(scriptObjPtr);     
    script = Jim_GetScript(interp, scriptObjPtr);
    if (script == NULL) {
        Jim_DecrRefCount(interp, scriptObjPtr);
        return JIM_ERR;
    }

    Jim_SetEmptyResult(interp);

    token = script->token;

#ifdef JIM_OPTIMIZATION
    if (script->len == 0) {
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071
15072
15073
15074
15075
15076
15077
15078
    else {
        
        retcode = Jim_EvalObj(interp, scriptObj);
    }

    
    interp->framePtr = interp->framePtr->parent;
    if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
    }
    else {
        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
    }

    return retcode;
}
#endif

static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
{
    Jim_CallFrame *callFramePtr;
    int i, d, retcode, optargs;
    Jim_Stack *localCommands;
    ScriptObj *script;

    
    if (argc - 1 < cmd->u.proc.reqArity ||
        (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
        JimSetProcWrongArgs(interp, argv[0], cmd);
        return JIM_ERR;







<
|
<
<
<
<









<







15235
15236
15237
15238
15239
15240
15241

15242




15243
15244
15245
15246
15247
15248
15249
15250
15251

15252
15253
15254
15255
15256
15257
15258
    else {
        
        retcode = Jim_EvalObj(interp, scriptObj);
    }

    
    interp->framePtr = interp->framePtr->parent;

    JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);





    return retcode;
}
#endif

static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
{
    Jim_CallFrame *callFramePtr;
    int i, d, retcode, optargs;

    ScriptObj *script;

    
    if (argc - 1 < cmd->u.proc.reqArity ||
        (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
        JimSetProcWrongArgs(interp, argv[0], cmd);
        return JIM_ERR;
15148
15149
15150
15151
15152
15153
15154
15155
15156
15157
15158
15159
15160
15161
15162
15163

15164
15165
15166


15167

15168
15169


15170
15171
15172
15173
15174

15175
15176
15177

15178
15179

15180
15181

15182
15183
15184
15185
15186
15187
15188
15189
15190
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
        }
    }

    
    retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);

badargset:
    
    
    localCommands = callFramePtr->localCommands;
    callFramePtr->localCommands = NULL;

    interp->framePtr = interp->framePtr->parent;
    if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
    }

    else {
        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
    }




    
    while (retcode == JIM_EVAL) {


        Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);

        Jim_IncrRefCount(resultScriptObjPtr);
        
        JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));


        retcode = JimEvalObjList(interp, resultScriptObjPtr);
        if (retcode == JIM_RETURN) {

            interp->returnLevel++;
        }

        Jim_DecrRefCount(interp, resultScriptObjPtr);
    }

    
    if (retcode == JIM_RETURN) {
        if (--interp->returnLevel <= 0) {
            retcode = interp->returnCode;
            interp->returnCode = JIM_OK;
            interp->returnLevel = 0;
        }
    }
    else if (retcode == JIM_ERR) {
        interp->addStackTrace++;
        Jim_DecrRefCount(interp, interp->errorProc);
        interp->errorProc = argv[0];
        Jim_IncrRefCount(interp->errorProc);
    }

    
    JimDeleteLocalProcs(interp, localCommands);

    return retcode;
}

int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
{
    int retval;
    Jim_Obj *scriptObjPtr;







|

<
<
<

<
|
|
>
|
|
|
>
>

>
|
|
>
>
|
|
<
|
|
>

|
|
>
|
|
>
|

>















<
<
<







15328
15329
15330
15331
15332
15333
15334
15335
15336



15337

15338
15339
15340
15341
15342
15343
15344
15345
15346
15347
15348
15349
15350
15351
15352
15353

15354
15355
15356
15357
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367
15368
15369
15370
15371
15372
15373
15374
15375
15376
15377
15378
15379
15380
15381



15382
15383
15384
15385
15386
15387
15388
        }
    }

    
    retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);

badargset:

    



    interp->framePtr = interp->framePtr->parent;

    JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);

    if (interp->framePtr->tailcallObj) {
        
        if (interp->framePtr->tailcall++ == 0) {
            
            do {
                Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;

                interp->framePtr->tailcallObj = NULL;

                if (retcode == JIM_EVAL) {
                    retcode = Jim_EvalObjList(interp, tailcallObj);
                    if (retcode == JIM_RETURN) {
                        interp->returnLevel++;
                    }

                }
                Jim_DecrRefCount(interp, tailcallObj);
            } while (interp->framePtr->tailcallObj);

            
            if (interp->framePtr->tailcallCmd) {
                JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
                interp->framePtr->tailcallCmd = NULL;
            }
        }
        interp->framePtr->tailcall--;
    }

    
    if (retcode == JIM_RETURN) {
        if (--interp->returnLevel <= 0) {
            retcode = interp->returnCode;
            interp->returnCode = JIM_OK;
            interp->returnLevel = 0;
        }
    }
    else if (retcode == JIM_ERR) {
        interp->addStackTrace++;
        Jim_DecrRefCount(interp, interp->errorProc);
        interp->errorProc = argv[0];
        Jim_IncrRefCount(interp->errorProc);
    }




    return retcode;
}

int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
{
    int retval;
    Jim_Obj *scriptObjPtr;
15264
15265
15266
15267
15268
15269
15270
15271
15272
15273
15274
15275
15276
15277
15278
    FILE *fp;
    char *buf;
    Jim_Obj *scriptObjPtr;
    Jim_Obj *prevScriptObj;
    struct stat sb;
    int retcode;
    int readlen;
    struct JimParseResult result;

    if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
        Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    if (sb.st_size == 0) {
        fclose(fp);







<







15446
15447
15448
15449
15450
15451
15452

15453
15454
15455
15456
15457
15458
15459
    FILE *fp;
    char *buf;
    Jim_Obj *scriptObjPtr;
    Jim_Obj *prevScriptObj;
    struct stat sb;
    int retcode;
    int readlen;


    if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
        Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
        return JIM_ERR;
    }
    if (sb.st_size == 0) {
        fclose(fp);
15291
15292
15293
15294
15295
15296
15297
15298
15299
15300
15301
15302
15303
15304
15305
15306
15307
15308
15309
15310
15311
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321
15322
15323
15324
15325
    buf[readlen] = 0;

    scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
    JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
    Jim_IncrRefCount(scriptObjPtr);

    
    if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
        const char *msg;
        char linebuf[20];

        switch (result.missing) {
            case '[':
                msg = "unmatched \"[\"";
                break;
            case '{':
                msg = "missing close-brace";
                break;
            case '"':
            default:
                msg = "missing quote";
                break;
        }

        snprintf(linebuf, sizeof(linebuf), "%d", result.line);

        Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
            msg, filename, linebuf);
        Jim_DecrRefCount(interp, scriptObjPtr);
        return JIM_ERR;
    }

    prevScriptObj = interp->currentScriptObj;
    interp->currentScriptObj = scriptObjPtr;








|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<







15472
15473
15474
15475
15476
15477
15478
15479


15480












15481




15482
15483
15484
15485
15486
15487
15488
    buf[readlen] = 0;

    scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
    JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
    Jim_IncrRefCount(scriptObjPtr);

    
    if (Jim_GetScript(interp, scriptObjPtr) == NULL) {


        












        JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));




        Jim_DecrRefCount(interp, scriptObjPtr);
        return JIM_ERR;
    }

    prevScriptObj = interp->currentScriptObj;
    interp->currentScriptObj = scriptObjPtr;

15478
15479
15480
15481
15482
15483
15484
15485
15486
15487
15488
15489
15490
15491
15492
    Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
    Jim_DecrRefCount(interp, objPtr);
}

typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type);

#define JimTrivialMatch(pattern)	(strpbrk((pattern), "*[?\\") == NULL)

static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
    JimHashtableIteratorCallbackType *callback, int type)
{
    Jim_HashEntry *he;
    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);








|







15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
    Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
    Jim_DecrRefCount(interp, objPtr);
}

typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type);

#define JimTrivialMatch(pattern)    (strpbrk((pattern), "*[?\\") == NULL)

static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
    JimHashtableIteratorCallbackType *callback, int type)
{
    Jim_HashEntry *he;
    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);

15513
15514
15515
15516
15517
15518
15519
15520
15521
15522
15523
15524
15525
15526
15527
#define JIM_CMDLIST_COMMANDS 0
#define JIM_CMDLIST_PROCS 1
#define JIM_CMDLIST_CHANNELS 2

static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type)
{
    Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
    Jim_Obj *objPtr;

    if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
        
        return;
    }








|







15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
#define JIM_CMDLIST_COMMANDS 0
#define JIM_CMDLIST_PROCS 1
#define JIM_CMDLIST_CHANNELS 2

static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type)
{
    Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
    Jim_Obj *objPtr;

    if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
        
        return;
    }

15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
#define JIM_VARLIST_VARS 2

#define JIM_VARLIST_VALUES 0x1000

static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type)
{
    Jim_Var *varPtr = (Jim_Var *)he->u.val;

    if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
        if (type & JIM_VARLIST_VALUES) {
            Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
        }
    }







|







15709
15710
15711
15712
15713
15714
15715
15716
15717
15718
15719
15720
15721
15722
15723
#define JIM_VARLIST_VARS 2

#define JIM_VARLIST_VALUES 0x1000

static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
    Jim_HashEntry *he, int type)
{
    Jim_Var *varPtr = Jim_GetHashEntryVal(he);

    if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
        if (type & JIM_VARLIST_VALUES) {
            Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
        }
    }
15868
15869
15870
15871
15872
15873
15874
15875
15876
15877
15878
15879
15880
15881
15882
        int cmpOffset;

        
        expr = JimGetExpression(interp, argv[2]);
        incrScript = Jim_GetScript(interp, argv[3]);

        
        if (incrScript->len != 3 || !expr || expr->len != 3) {
            goto evalstart;
        }
        
        if (incrScript->token[1].type != JIM_TT_ESC ||
            expr->token[0].type != JIM_TT_VAR ||
            (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
            goto evalstart;







|







16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041
16042
16043
16044
16045
        int cmpOffset;

        
        expr = JimGetExpression(interp, argv[2]);
        incrScript = Jim_GetScript(interp, argv[3]);

        
        if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
            goto evalstart;
        }
        
        if (incrScript->token[1].type != JIM_TT_ESC ||
            expr->token[0].type != JIM_TT_VAR ||
            (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
            goto evalstart;
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
{
    return iter->idx >= Jim_ListLength(interp, iter->objPtr);
}


static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
{
    int result = JIM_ERR;
    int i, numargs;
    Jim_ListIter twoiters[2];   
    Jim_ListIter *iters;
    Jim_Obj *script;
    Jim_Obj *resultObj;

    if (argc < 4 || argc % 2 != 0) {







|







16254
16255
16256
16257
16258
16259
16260
16261
16262
16263
16264
16265
16266
16267
16268
{
    return iter->idx >= Jim_ListLength(interp, iter->objPtr);
}


static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
{
    int result = JIM_OK;
    int i, numargs;
    Jim_ListIter twoiters[2];   
    Jim_ListIter *iters;
    Jim_Obj *script;
    Jim_Obj *resultObj;

    if (argc < 4 || argc % 2 != 0) {
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123




16124
16125
16126
16127
16128
16129
16130
    }
    else {
        iters = Jim_Alloc(numargs * sizeof(*iters));
    }
    for (i = 0; i < numargs; i++) {
        JimListIterInit(&iters[i], argv[i + 1]);
        if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
            Jim_SetResultString(interp, "foreach varlist is empty", -1);
            return JIM_ERR;
        }




    }

    if (doMap) {
        resultObj = Jim_NewListObj(interp, NULL, 0);
    }
    else {
        resultObj = interp->emptyObj;







<
|

>
>
>
>







16277
16278
16279
16280
16281
16282
16283

16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295
16296
    }
    else {
        iters = Jim_Alloc(numargs * sizeof(*iters));
    }
    for (i = 0; i < numargs; i++) {
        JimListIterInit(&iters[i], argv[i + 1]);
        if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {

            result = JIM_ERR;
        }
    }
    if (result != JIM_OK) {
        Jim_SetResultString(interp, "foreach varlist is empty", -1);
        return result;
    }

    if (doMap) {
        resultObj = Jim_NewListObj(interp, NULL, 0);
    }
    else {
        resultObj = interp->emptyObj;
16433
16434
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448

static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr, *listObjPtr;
    int i;
    int idx;

    if (argc < 3) {
        Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
        return JIM_ERR;
    }
    objPtr = argv[1];
    Jim_IncrRefCount(objPtr);
    for (i = 2; i < argc; i++) {
        listObjPtr = objPtr;
        if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) {







|
|







16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614

static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr, *listObjPtr;
    int i;
    int idx;

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
        return JIM_ERR;
    }
    objPtr = argv[1];
    Jim_IncrRefCount(objPtr);
    for (i = 2; i < argc; i++) {
        listObjPtr = objPtr;
        if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) {
16550
16551
16552
16553
16554
16555
16556
16557
16558

16559
16560
16561
16562
16563
16564
16565
16566
16567
    }
    if (commandObj) {
        Jim_IncrRefCount(commandObj);
    }

    listlen = Jim_ListLength(interp, argv[0]);
    for (i = 0; i < listlen; i++) {
        Jim_Obj *objPtr;
        int eq = 0;


        Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
        switch (opt_match) {
            case OPT_EXACT:
                eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
                break;

            case OPT_GLOB:
                eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase);







<

>

<







16716
16717
16718
16719
16720
16721
16722

16723
16724
16725

16726
16727
16728
16729
16730
16731
16732
    }
    if (commandObj) {
        Jim_IncrRefCount(commandObj);
    }

    listlen = Jim_ListLength(interp, argv[0]);
    for (i = 0; i < listlen; i++) {

        int eq = 0;
        Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);


        switch (opt_match) {
            case OPT_EXACT:
                eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
                break;

            case OPT_GLOB:
                eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase);
16747
16748
16749
16750
16751
16752
16753

16754
16755
16756
16757
16758
16759
16760
16761
16762
16763
16764
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786

16787
16788
16789
16790
16791
16792
16793
16794
16795
16796
16797
16798
16799
16800
16801
16802
16803
16804
16805



16806
16807
16808
16809
16810
16811



16812
16813
16814
16815
16816
16817
16818
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc < 3) {
        Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
        return JIM_ERR;
    }
    else if (argc == 3) {

        if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
            return JIM_ERR;
        Jim_SetResult(interp, argv[2]);
        return JIM_OK;
    }
    if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
        == JIM_ERR)
        return JIM_ERR;
    return JIM_OK;
}


static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
{
    static const char * const options[] = {
        "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
    };
    enum
    { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
    Jim_Obj *resObj;
    int i;
    int retCode;

    struct lsort_info info;

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "?options? list");
        return JIM_ERR;
    }

    info.type = JIM_LSORT_ASCII;
    info.order = 1;
    info.indexed = 0;

    info.command = NULL;
    info.interp = interp;

    for (i = 1; i < (argc - 1); i++) {
        int option;

        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
            != JIM_OK)
            return JIM_ERR;
        switch (option) {
            case OPT_ASCII:
                info.type = JIM_LSORT_ASCII;
                break;
            case OPT_NOCASE:
                info.type = JIM_LSORT_NOCASE;
                break;
            case OPT_INTEGER:
                info.type = JIM_LSORT_INTEGER;
                break;



            case OPT_INCREASING:
                info.order = 1;
                break;
            case OPT_DECREASING:
                info.order = -1;
                break;



            case OPT_COMMAND:
                if (i >= (argc - 2)) {
                    Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
                    return JIM_ERR;
                }
                info.type = JIM_LSORT_COMMAND;
                info.command = argv[i + 1];







>





|
<
<
<






|


|














>






|












>
>
>






>
>
>







16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925



16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc < 3) {
        Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
        return JIM_ERR;
    }
    else if (argc == 3) {
        
        if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
            return JIM_ERR;
        Jim_SetResult(interp, argv[2]);
        return JIM_OK;
    }
    return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);



}


static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
{
    static const char * const options[] = {
        "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
    };
    enum
    { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
    Jim_Obj *resObj;
    int i;
    int retCode;

    struct lsort_info info;

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "?options? list");
        return JIM_ERR;
    }

    info.type = JIM_LSORT_ASCII;
    info.order = 1;
    info.indexed = 0;
    info.unique = 0;
    info.command = NULL;
    info.interp = interp;

    for (i = 1; i < (argc - 1); i++) {
        int option;

        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
            != JIM_OK)
            return JIM_ERR;
        switch (option) {
            case OPT_ASCII:
                info.type = JIM_LSORT_ASCII;
                break;
            case OPT_NOCASE:
                info.type = JIM_LSORT_NOCASE;
                break;
            case OPT_INTEGER:
                info.type = JIM_LSORT_INTEGER;
                break;
            case OPT_REAL:
                info.type = JIM_LSORT_REAL;
                break;
            case OPT_INCREASING:
                info.order = 1;
                break;
            case OPT_DECREASING:
                info.order = -1;
                break;
            case OPT_UNIQUE:
                info.unique = 1;
                break;
            case OPT_COMMAND:
                if (i >= (argc - 2)) {
                    Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
                    return JIM_ERR;
                }
                info.type = JIM_LSORT_COMMAND;
                info.command = argv[i + 1];
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950



16951
16952
16953
16954
16955
16956
16957
16958
16959

16960
16961
16962
16963
16964
16965
16966


static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc >= 2) {
        int retcode;
        Jim_CallFrame *savedCallFrame, *targetCallFrame;
        Jim_Obj *objPtr;
        const char *str;

        
        savedCallFrame = interp->framePtr;

        
        str = Jim_String(argv[1]);
        if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
            targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
            argc--;
            argv++;
        }
        else {
            targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
        }
        if (targetCallFrame == NULL) {
            return JIM_ERR;
        }
        if (argc < 2) {
            argv--;
            Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
            return JIM_ERR;
        }
        
        interp->framePtr = targetCallFrame;



        if (argc == 2) {
            retcode = Jim_EvalObj(interp, argv[1]);
        }
        else {
            objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
            Jim_IncrRefCount(objPtr);
            retcode = Jim_EvalObj(interp, objPtr);
            Jim_DecrRefCount(interp, objPtr);
        }

        interp->framePtr = savedCallFrame;
        return retcode;
    }
    else {
        Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
        return JIM_ERR;
    }







|








|










<
|




>
>
>




<
<
|
<

>







17088
17089
17090
17091
17092
17093
17094
17095
17096
17097
17098
17099
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112
17113
17114

17115
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126


17127

17128
17129
17130
17131
17132
17133
17134
17135
17136


static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc >= 2) {
        int retcode;
        Jim_CallFrame *savedCallFrame, *targetCallFrame;
        int savedTailcall;
        const char *str;

        
        savedCallFrame = interp->framePtr;

        
        str = Jim_String(argv[1]);
        if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
            targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
            argc--;
            argv++;
        }
        else {
            targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
        }
        if (targetCallFrame == NULL) {
            return JIM_ERR;
        }
        if (argc < 2) {

            Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
            return JIM_ERR;
        }
        
        interp->framePtr = targetCallFrame;
        
        savedTailcall = interp->framePtr->tailcall;
        interp->framePtr->tailcall = 0;
        if (argc == 2) {
            retcode = Jim_EvalObj(interp, argv[1]);
        }
        else {


            retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));

        }
        interp->framePtr->tailcall = savedTailcall;
        interp->framePtr = savedCallFrame;
        return retcode;
    }
    else {
        Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
        return JIM_ERR;
    }
17067
17068
17069
17070
17071
17072
17073






















17074



17075


17076
17077
17078
17079
17080
17081
17082
    }
    return JIM_RETURN;
}


static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{






















    Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));



    return JIM_EVAL;


}

static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *cmdList;
    Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>







17237
17238
17239
17240
17241
17242
17243
17244
17245
17246
17247
17248
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258
17259
17260
17261
17262
17263
17264
17265
17266
17267
17268
17269
17270
17271
17272
17273
17274
17275
17276
17277
17278
17279
    }
    return JIM_RETURN;
}


static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (interp->framePtr->level == 0) {
        Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
        return JIM_ERR;
    }
    else if (argc >= 2) {
        
        Jim_CallFrame *cf = interp->framePtr->parent;

        Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
        if (cmdPtr == NULL) {
            return JIM_ERR;
        }

        JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));

        
        JimIncrCmdRefCount(cmdPtr);
        cf->tailcallCmd = cmdPtr;

        
        JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));

        cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
        Jim_IncrRefCount(cf->tailcallObj);

        
        return JIM_EVAL;
    }
    return JIM_OK;
}

static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *cmdList;
    Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);

17156
17157
17158
17159
17160
17161
17162





17163
17164
17165
17166
17167
17168
17169
    return JIM_ERR;
}


static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int retcode;






    
    interp->local++;
    retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
    interp->local--;









>
>
>
>
>







17353
17354
17355
17356
17357
17358
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370
17371
    return JIM_ERR;
}


static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int retcode;

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
        return JIM_ERR;
    }

    
    interp->local++;
    retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
    interp->local--;


17352
17353
17354
17355
17356
17357
17358
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370
17371
17372
17373
17374
17375
17376
17377
17378
17379
    resultObjPtr = Jim_NewStringObj(interp, "", 0);
    while (strLen) {
        for (i = 0; i < numMaps; i += 2) {
            Jim_Obj *objPtr;
            const char *k;
            int kl;

            Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
            k = Jim_String(objPtr);
            kl = Jim_Utf8Length(interp, objPtr);

            if (strLen >= kl && kl) {
                int rc;
                rc = JimStringCompareLen(str, k, kl, nocase);
                if (rc == 0) {
                    if (noMatchStart) {
                        Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
                        noMatchStart = NULL;
                    }
                    Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
                    Jim_AppendObj(interp, resultObjPtr, objPtr);
                    str += utf8_index(str, kl);
                    strLen -= kl;
                    break;
                }
            }
        }
        if (i == numMaps) {     







|











<
|







17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
17565
17566
17567
17568
17569
17570
17571
17572

17573
17574
17575
17576
17577
17578
17579
17580
    resultObjPtr = Jim_NewStringObj(interp, "", 0);
    while (strLen) {
        for (i = 0; i < numMaps; i += 2) {
            Jim_Obj *objPtr;
            const char *k;
            int kl;

            objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
            k = Jim_String(objPtr);
            kl = Jim_Utf8Length(interp, objPtr);

            if (strLen >= kl && kl) {
                int rc;
                rc = JimStringCompareLen(str, k, kl, nocase);
                if (rc == 0) {
                    if (noMatchStart) {
                        Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
                        noMatchStart = NULL;
                    }

                    Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
                    str += utf8_index(str, kl);
                    strLen -= kl;
                    break;
                }
            }
        }
        if (i == numMaps) {     
17849
17850
17851
17852
17853
17854
17855


17856
17857
17858
17859
17860
17861
17862
17863
17864
17865
17866
17867
    interp->signal_level += sig;
    if (Jim_CheckSignal(interp)) {
        
        exitCode = JIM_SIGNAL;
    }
    else {
        exitCode = Jim_EvalObj(interp, argv[0]);


    }
    interp->signal_level -= sig;

    
    if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
        
        return exitCode;
    }

    if (sig && exitCode == JIM_SIGNAL) {
        
        if (interp->signal_set_result) {







>
>




|







18050
18051
18052
18053
18054
18055
18056
18057
18058
18059
18060
18061
18062
18063
18064
18065
18066
18067
18068
18069
18070
    interp->signal_level += sig;
    if (Jim_CheckSignal(interp)) {
        
        exitCode = JIM_SIGNAL;
    }
    else {
        exitCode = Jim_EvalObj(interp, argv[0]);
        
        interp->errorFlag = 0;
    }
    interp->signal_level -= sig;

    
    if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
        
        return exitCode;
    }

    if (sig && exitCode == JIM_SIGNAL) {
        
        if (interp->signal_set_result) {
18007
18008
18009
18010
18011
18012
18013
18014
18015
18016
18017
18018
18019
18020
18021
    Jim_HashEntry *he;

    listObjPtr = Jim_NewListObj(interp, NULL, 0);

    JimInitHashTableIterator(&interp->references, &htiter);
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
        char buf[JIM_REFERENCE_SPACE + 1];
        Jim_Reference *refPtr = he->u.val;
        const unsigned long *refId = he->key;

        JimFormatReference(buf, refPtr, *refId);
        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
    }
    Jim_SetResult(interp, listObjPtr);
    return JIM_OK;







|







18210
18211
18212
18213
18214
18215
18216
18217
18218
18219
18220
18221
18222
18223
18224
    Jim_HashEntry *he;

    listObjPtr = Jim_NewListObj(interp, NULL, 0);

    JimInitHashTableIterator(&interp->references, &htiter);
    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
        char buf[JIM_REFERENCE_SPACE + 1];
        Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
        const unsigned long *refId = he->key;

        JimFormatReference(buf, refPtr, *refId);
        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
    }
    Jim_SetResult(interp, listObjPtr);
    return JIM_OK;
18041
18042
18043
18044
18045
18046
18047
18048
18049
18050
18051
18052
18053
18054
18055

typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);

static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
{
    Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
    if (type & JIM_DICTMATCH_VALUES) {
        Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
    }
}

static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
    JimDictMatchCallbackType *callback, int type)
{
    Jim_HashEntry *he;







|







18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258

typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);

static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
{
    Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
    if (type & JIM_DICTMATCH_VALUES) {
        Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
    }
}

static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
    JimDictMatchCallbackType *callback, int type)
{
    Jim_HashEntry *he;
18090
18091
18092
18093
18094
18095
18096








































18097
18098
18099
18100
18101
18102
18103


18104
18105
18106
18107


18108
18109
18110
18111
18112
18113
18114
18115
18116
18117
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132
18133
18134
18135
18136
18137
18138
18139
18140
18141
18142
18143

18144

18145


18146

18147
18148
18149
18150
18151
18152
18153



18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
18165
18166
18167
18168
18169
18170
18171
18172
18173
18174
18175
18176
18177
18178
18179
18180
18181
18182
18183
18184
18185
18186
18187

18188
18189
18190
18191
18192
18193
18194
18195

18196
18197
18198
18199
18200
18201
18202
18203
18204
18205
18206
18207
18208
18209



18210





18211
18212
18213
18214
18215
18216
18217
{
    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
        return -1;
    }
    return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
}










































static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr;
    int option;
    static const char * const options[] = {
        "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL


    };
    enum
    {
        OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,


    };

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
        return JIM_ERR;
    }

    if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
        return JIM_ERR;
    }

    switch (option) {
        case OPT_GET:
            if (argc < 3) {
                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
                return JIM_ERR;
            }
            if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
                    JIM_ERRMSG) != JIM_OK) {
                return JIM_ERR;
            }
            Jim_SetResult(interp, objPtr);
            return JIM_OK;

        case OPT_SET:
            if (argc < 5) {
                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
                return JIM_ERR;
            }
            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);

        case OPT_EXIST:
            if (argc < 3) {
                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
                return JIM_ERR;
            }

            Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,

                    &objPtr, JIM_ERRMSG) == JIM_OK);


            return JIM_OK;


        case OPT_UNSET:
            if (argc < 4) {
                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
                return JIM_ERR;
            }
            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);




        case OPT_KEYS:
            if (argc != 3 && argc != 4) {
                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
                return JIM_ERR;
            }
            return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);

        case OPT_SIZE: {
            int size;

            if (argc != 3) {
                Jim_WrongNumArgs(interp, 2, argv, "dictVar");
                return JIM_ERR;
            }

            size = Jim_DictSize(interp, argv[2]);
            if (size < 0) {
                return JIM_ERR;
            }
            Jim_SetResultInt(interp, size);
            return JIM_OK;
        }

        case OPT_MERGE:
            if (argc == 2) {
                return JIM_OK;
            }
            else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
                return JIM_ERR;
            }
            else {
                return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
            }


        case OPT_WITH:
            if (argc < 4) {
                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
                return JIM_ERR;
            }
            else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
                return JIM_ERR;

            }
            else {
                return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
            }

        case OPT_CREATE:
            if (argc % 2) {
                Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
                return JIM_ERR;
            }
            objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
            Jim_SetResult(interp, objPtr);
            return JIM_OK;
    }



    return JIM_ERR;





}


static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    static const char * const options[] = {
        "-nobackslashes", "-nocommands", "-novariables", NULL







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
>
>



|
>
>














|
















|
|
|


>
|
>
|
>
>
|
>






|
>
>
>



|




|
<
<

|


<
|
<


|

<





|


<
<
|
>

|
|
<
<
|
<
<
>

|
<
<









|
>
>
>
|
>
>
>
>
>







18293
18294
18295
18296
18297
18298
18299
18300
18301
18302
18303
18304
18305
18306
18307
18308
18309
18310
18311
18312
18313
18314
18315
18316
18317
18318
18319
18320
18321
18322
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351
18352
18353
18354
18355
18356
18357
18358
18359
18360
18361
18362
18363
18364
18365
18366
18367
18368
18369
18370
18371
18372
18373
18374
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393
18394
18395
18396
18397
18398
18399
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
18411
18412
18413
18414
18415
18416
18417


18418
18419
18420
18421

18422

18423
18424
18425
18426

18427
18428
18429
18430
18431
18432
18433
18434


18435
18436
18437
18438
18439


18440


18441
18442
18443


18444
18445
18446
18447
18448
18449
18450
18451
18452
18453
18454
18455
18456
18457
18458
18459
18460
18461
18462
18463
18464
18465
18466
18467
18468
18469
{
    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
        return -1;
    }
    return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
}

int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
{
    Jim_HashTable *ht;
    unsigned int i;

    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
        return JIM_ERR;
    }

    ht = (Jim_HashTable *)objPtr->internalRep.ptr;

    
    printf("%d entries in table, %d buckets\n", ht->used, ht->size);

    for (i = 0; i < ht->size; i++) {
        Jim_HashEntry *he = ht->table[i];

        if (he) {
            printf("%d: ", i);

            while (he) {
                printf(" %s", Jim_String(he->key));
                he = he->next;
            }
            printf("\n");
        }
    }
    return JIM_OK;
}

static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);

    Jim_AppendString(interp, prefixObj, " ", 1);
    Jim_AppendString(interp, prefixObj, subcmd, -1);

    return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
}


static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr;
    int option;
    static const char * const options[] = {
        "create", "get", "set", "unset", "exists", "keys", "size", "info",
        "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
        "replace", "update", NULL
    };
    enum
    {
        OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
        OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
        OPT_REPLACE, OPT_UPDATE,
    };

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
        return JIM_ERR;
    }

    if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
        return JIM_ERR;
    }

    switch (option) {
        case OPT_GET:
            if (argc < 3) {
                Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
                return JIM_ERR;
            }
            if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
                    JIM_ERRMSG) != JIM_OK) {
                return JIM_ERR;
            }
            Jim_SetResult(interp, objPtr);
            return JIM_OK;

        case OPT_SET:
            if (argc < 5) {
                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
                return JIM_ERR;
            }
            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);

        case OPT_EXISTS:
            if (argc < 4) {
                Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
                return JIM_ERR;
            }
            else {
                int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
                if (rc < 0) {
                    return JIM_ERR;
                }
                Jim_SetResultBool(interp,  rc == JIM_OK);
                return JIM_OK;
            }

        case OPT_UNSET:
            if (argc < 4) {
                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
                return JIM_ERR;
            }
            if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
                return JIM_ERR;
            }
            return JIM_OK;

        case OPT_KEYS:
            if (argc != 3 && argc != 4) {
                Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
                return JIM_ERR;
            }
            return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);

        case OPT_SIZE:


            if (argc != 3) {
                Jim_WrongNumArgs(interp, 2, argv, "dictionary");
                return JIM_ERR;
            }

            else if (Jim_DictSize(interp, argv[2]) < 0) {

                return JIM_ERR;
            }
            Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
            return JIM_OK;


        case OPT_MERGE:
            if (argc == 2) {
                return JIM_OK;
            }
            if (Jim_DictSize(interp, argv[2]) < 0) {
                return JIM_ERR;
            }


            
            break;

        case OPT_UPDATE:
            if (argc < 6 || argc % 2) {


                


                argc = 2;
            }
            break;



        case OPT_CREATE:
            if (argc % 2) {
                Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
                return JIM_ERR;
            }
            objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
            Jim_SetResult(interp, objPtr);
            return JIM_OK;

        case OPT_INFO:
            if (argc != 3) {
                Jim_WrongNumArgs(interp, 2, argv, "dictionary");
                return JIM_ERR;
            }
            return Jim_DictInfo(interp, argv[2]);
    }
    
    return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
}


static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    static const char * const options[] = {
        "-nobackslashes", "-nocommands", "-novariables", NULL
18265
18266
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278
18279
        "script", "source", "stacktrace", "nameofexecutable", "returncodes",
        "references", "alias", NULL
    };
    enum
    { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
        INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
        INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
        INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
    };

#ifdef jim_ext_namespace
    int nons = 0;

    if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
        







|







18517
18518
18519
18520
18521
18522
18523
18524
18525
18526
18527
18528
18529
18530
18531
        "script", "source", "stacktrace", "nameofexecutable", "returncodes",
        "references", "alias", NULL
    };
    enum
    { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
        INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
        INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
        INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
    };

#ifdef jim_ext_namespace
    int nons = 0;

    if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
        
19045
19046
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058
19059
        Jim_SetResultInt(interp, min+r);
        return JIM_OK;
    }
}

static const struct {
    const char *name;
    Jim_CmdProc cmdProc;
} Jim_CoreCommandsTable[] = {
    {"alias", Jim_AliasCoreCommand},
    {"set", Jim_SetCoreCommand},
    {"unset", Jim_UnsetCoreCommand},
    {"puts", Jim_PutsCoreCommand},
    {"+", Jim_AddCoreCommand},
    {"*", Jim_MulCoreCommand},







|







19297
19298
19299
19300
19301
19302
19303
19304
19305
19306
19307
19308
19309
19310
19311
        Jim_SetResultInt(interp, min+r);
        return JIM_OK;
    }
}

static const struct {
    const char *name;
    Jim_CmdProc *cmdProc;
} Jim_CoreCommandsTable[] = {
    {"alias", Jim_AliasCoreCommand},
    {"set", Jim_SetCoreCommand},
    {"unset", Jim_UnsetCoreCommand},
    {"puts", Jim_PutsCoreCommand},
    {"+", Jim_AddCoreCommand},
    {"*", Jim_MulCoreCommand},
19277
19278
19279
19280
19281
19282
19283


19284
19285
19286
19287
19288
19289
19290
        n++;
        extra += l;
    }

    len += extra;
    buf = Jim_Alloc(len + 1);
    len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);



    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
}


#ifndef jim_ext_package
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)







>
>







19529
19530
19531
19532
19533
19534
19535
19536
19537
19538
19539
19540
19541
19542
19543
19544
        n++;
        extra += l;
    }

    len += extra;
    buf = Jim_Alloc(len + 1);
    len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);

    va_end(args);

    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
}


#ifndef jim_ext_package
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
19528
19529
19530
19531
19532
19533
19534
19535
19536
19537
19538
19539
19540
19541
19542
19543
19544
19545
19546
19547
19548
19549
19550
19551
19552
19553
19554
19555
19556
19557
19558
19559
19560
19561
19562
19563
19564
19565
19566
19567
19568
19569
19570
19571
19572
19573
19574
19575
19576
19577
19578
19579
19580
19581
19582
19583
19584
19585
19586
19587
19588
19589
19590
19591
19592
19593
19594
19595
19596
19597
19598
19599
19600
19601
19602
19603
19604
19605
19606
19607
19608
19609
19610
19611
19612
19613
19614
19615
19616
19617
19618
19619
19620
19621
19622
19623
19624
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642
19643
19644
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724
19725
19726
19727
19728
19729
19730
19731
19732
19733
19734
19735
19736
19737
19738
19739
19740
19741
19742
19743
19744
19745
19746
19747
19748
19749
19750
19751
19752
19753
19754
19755

































19756
19757
19758
19759
19760
19761
19762
19763
19764
19765
19766
19767
19768
19769
19770
19771
19772
19773
19774
19775
19776
19777
19778
19779
19780
19781
19782
19783
19784
19785
19786
19787
19788
19789
19790
19791
19792
19793
19794
19795
19796
19797
19798
19799
19800
19801
19802
19803
19804
19805
19806
19807
19808
19809
19810
19811
19812
19813
19814
19815
19816
19817
19818
19819
19820
19821
19822
19823
19824
19825
19826
19827
19828
19829
19830
19831
19832
19833
19834
19835
19836
19837
19838
19839
19840
19841
19842
19843
19844
19845
19846
19847
19848
19849
19850
19851
19852
19853
19854
19855
19856
19857
19858
19859
19860
19861
19862
19863
19864
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876
19877
19878
19879
19880



19881
19882
19883
19884
19885
19886
19887
19888
19889
19890
19891

19892
19893
19894
19895
19896
19897
19898
19899
19900
19901
19902
19903
19904
19905
19906
19907
19908
19909
19910

19911
19912
19913



19914
19915
19916
19917
19918
19919
19920
19921
19922
19923
19924
19925
19926
19927
19928
19929
19930
19931
19932
19933
19934
19935
19936
19937
19938
19939
19940
19941
19942
19943
19944
19945
19946
19947
19948
19949
19950
19951
19952
19953
19954
19955
19956
    }
}

#include <ctype.h>
#include <string.h>


#define JIM_UTF_MAX 3
#define JIM_INTEGER_SPACE 24
#define MAX_FLOAT_WIDTH 320

Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
{
    const char *span, *format, *formatEnd, *msg;
    int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
    static const char * const mixedXPG =
	    "cannot mix \"%\" and \"%n$\" conversion specifiers";
    static const char * const badIndex[2] = {
	"not enough arguments for all format specifiers",
	"\"%n$\" argument index out of range"
    };
    int formatLen;
    Jim_Obj *resultPtr;

    char *num_buffer = NULL;
    int num_buffer_size = 0;

    span = format = Jim_GetString(fmtObjPtr, &formatLen);
    formatEnd = format + formatLen;
    resultPtr = Jim_NewStringObj(interp, "", 0);

    while (format != formatEnd) {
	char *end;
	int gotMinus, sawFlag;
	int gotPrecision, useShort;
	long width, precision;
	int newXpg;
	int ch;
	int step;
	int doubleType;
	char pad = ' ';
	char spec[2*JIM_INTEGER_SPACE + 12];
	char *p;

	int formatted_chars;
	int formatted_bytes;
	const char *formatted_buf;

	step = utf8_tounicode(format, &ch);
	format += step;
	if (ch != '%') {
	    numBytes += step;
	    continue;
	}
	if (numBytes) {
	    Jim_AppendString(interp, resultPtr, span, numBytes);
	    numBytes = 0;
	}


	step = utf8_tounicode(format, &ch);
	if (ch == '%') {
	    span = format;
	    numBytes = step;
	    format += step;
	    continue;
	}


	newXpg = 0;
	if (isdigit(ch)) {
	    int position = strtoul(format, &end, 10);
	    if (*end == '$') {
		newXpg = 1;
		objIndex = position - 1;
		format = end + 1;
		step = utf8_tounicode(format, &ch);
	    }
	}
	if (newXpg) {
	    if (gotSequential) {
		msg = mixedXPG;
		goto errorMsg;
	    }
	    gotXpg = 1;
	} else {
	    if (gotXpg) {
		msg = mixedXPG;
		goto errorMsg;
	    }
	    gotSequential = 1;
	}
	if ((objIndex < 0) || (objIndex >= objc)) {
	    msg = badIndex[gotXpg];
	    goto errorMsg;
	}

	p = spec;
	*p++ = '%';

	gotMinus = 0;
	sawFlag = 1;
	do {
	    switch (ch) {
	    case '-':
		gotMinus = 1;
		break;
	    case '0':
		pad = ch;
		break;
	    case ' ':
	    case '+':
	    case '#':
		break;
	    default:
		sawFlag = 0;
		continue;
	    }
	    *p++ = ch;
	    format += step;
	    step = utf8_tounicode(format, &ch);
	} while (sawFlag);


	width = 0;
	if (isdigit(ch)) {
	    width = strtoul(format, &end, 10);
	    format = end;
	    step = utf8_tounicode(format, &ch);
	} else if (ch == '*') {
	    if (objIndex >= objc - 1) {
		msg = badIndex[gotXpg];
		goto errorMsg;
	    }
	    if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
		goto error;
	    }
	    if (width < 0) {
		width = -width;
		if (!gotMinus) {
		    *p++ = '-';
		    gotMinus = 1;
		}
	    }
	    objIndex++;
	    format += step;
	    step = utf8_tounicode(format, &ch);
	}


	gotPrecision = precision = 0;
	if (ch == '.') {
	    gotPrecision = 1;
	    format += step;
	    step = utf8_tounicode(format, &ch);
	}
	if (isdigit(ch)) {
	    precision = strtoul(format, &end, 10);
	    format = end;
	    step = utf8_tounicode(format, &ch);
	} else if (ch == '*') {
	    if (objIndex >= objc - 1) {
		msg = badIndex[gotXpg];
		goto errorMsg;
	    }
	    if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
		goto error;
	    }


	    if (precision < 0) {
		precision = 0;
	    }
	    objIndex++;
	    format += step;
	    step = utf8_tounicode(format, &ch);
	}


	useShort = 0;
	if (ch == 'h') {
	    useShort = 1;
	    format += step;
	    step = utf8_tounicode(format, &ch);
	} else if (ch == 'l') {
	    
	    format += step;
	    step = utf8_tounicode(format, &ch);
	    if (ch == 'l') {
		format += step;
		step = utf8_tounicode(format, &ch);
	    }
	}

	format += step;
	span = format;


	if (ch == 'i') {
	    ch = 'd';
	}

	doubleType = 0;

	switch (ch) {
	case '\0':
	    msg = "format string ended in middle of field specifier";
	    goto errorMsg;
	case 's': {
	    formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
	    formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
	    if (gotPrecision && (precision < formatted_chars)) {
		
		formatted_chars = precision;
		formatted_bytes = utf8_index(formatted_buf, precision);
	    }
	    break;
	}
	case 'c': {
	    jim_wide code;

	    if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
		goto error;
	    }
	    
	    formatted_bytes = utf8_fromunicode(spec, code);
	    formatted_buf = spec;
	    formatted_chars = 1;

































	    break;
	}

	case 'e':
	case 'E':
	case 'f':
	case 'g':
	case 'G':
	    doubleType = 1;
	    
	case 'd':
	case 'u':
	case 'o':
	case 'x':
	case 'X': {
	    jim_wide w;
	    double d;
	    int length;

	    
	    if (width) {
		p += sprintf(p, "%ld", width);
	    }
	    if (gotPrecision) {
		p += sprintf(p, ".%ld", precision);
	    }

	    
	    if (doubleType) {
		if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
		    goto error;
		}
		length = MAX_FLOAT_WIDTH;
	    }
	    else {
		if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
		    goto error;
		}
		length = JIM_INTEGER_SPACE;
		if (useShort) {
		    *p++ = 'h';
		    if (ch == 'd') {
			w = (short)w;
		    }
		    else {
			w = (unsigned short)w;
		    }
		}
		else {
		    *p++ = 'l';
#ifdef HAVE_LONG_LONG
		    if (sizeof(long long) == sizeof(jim_wide)) {
			*p++ = 'l';
		    }
#endif
		}
	    }

	    *p++ = (char) ch;
	    *p = '\0';

	    
	    if (width > length) {
		length = width;
	    }
	    if (gotPrecision) {
		length += precision;
	    }

	    
	    if (num_buffer_size < length + 1) {
		num_buffer_size = length + 1;
		num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
	    }

	    if (doubleType) {
		snprintf(num_buffer, length + 1, spec, d);
	    }
	    else {
		formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
	    }
	    formatted_chars = formatted_bytes = strlen(num_buffer);
	    formatted_buf = num_buffer;
	    break;
	}

	default: {
	    
	    spec[0] = ch;
	    spec[1] = '\0';
	    Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
	    goto error;
	}
	}

	if (!gotMinus) {
	    while (formatted_chars < width) {
		Jim_AppendString(interp, resultPtr, &pad, 1);
		formatted_chars++;
	    }
	}

	Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);

	while (formatted_chars < width) {
	    Jim_AppendString(interp, resultPtr, &pad, 1);
	    formatted_chars++;
	}

	objIndex += gotSequential;
    }
    if (numBytes) {
	Jim_AppendString(interp, resultPtr, span, numBytes);
    }

    Jim_Free(num_buffer);
    return resultPtr;

  errorMsg:
    Jim_SetResultString(interp, msg, -1);
  error:
    Jim_FreeNewObj(interp, resultPtr);
    Jim_Free(num_buffer);
    return NULL;
}



#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>


#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)



#define REG_MAX_PAREN 100



#define	END	0	
#define	BOL	1	
#define	EOL	2	
#define	ANY	3	
#define	ANYOF	4	
#define	ANYBUT	5	
#define	BRANCH	6	
#define	BACK	7	
#define	EXACTLY	8	
#define	NOTHING	9	
#define	REP		10	
#define	REPMIN	11	
#define	REPX	12	
#define	REPXMIN	13	

#define	WORDA	15	
#define	WORDZ	16	

#define	OPENNC	19	
#define	OPEN	20	
			



#define	CLOSE	(OPEN+REG_MAX_PAREN+1)	
#define	CLOSE_END	(CLOSE+REG_MAX_PAREN)
#define	CLOSENC	(CLOSE-1)	

#define	REG_MAGIC	0xFADED00D


#define	OP(preg, p)	(preg->program[p])
#define	NEXT(preg, p)	(preg->program[p + 1])
#define	OPERAND(p)	((p) + 2)




#define	FAIL(R,M)	{ (R)->err = (M); return (M); }
#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
#define	META	"^$.[()|?{+*"

#define	HASWIDTH	01	
#define	SIMPLE		02	
#define	SPSTART		04	
#define	WORST		0	

#define MAX_REP_COUNT 1000000

static int reg(regex_t *preg, int paren , int *flagp );
static int regpiece(regex_t *preg, int *flagp );
static int regbranch(regex_t *preg, int *flagp );
static int regatom(regex_t *preg, int *flagp );
static int regnode(regex_t *preg, int op );
static int regnext(regex_t *preg, int p );
static void regc(regex_t *preg, int b );
static int reginsert(regex_t *preg, int op, int size, int opnd );
static void regtail_(regex_t *preg, int p, int val, int line );
static void regoptail(regex_t *preg, int p, int val );
#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)

static int reg_range_find(const int *string, int c);
static const char *str_find(const char *string, int c, int nocase);
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);


#ifdef DEBUG







<








|

|
|









|


|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|


|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
<
|

|
|
|

<
|

|
|

|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|

|

|
|
|
|

|


|












>
>
>





<
<
<



>












|






>
|
|

>
>
>
|
|
|













|

|
|
|












|

|







19782
19783
19784
19785
19786
19787
19788

19789
19790
19791
19792
19793
19794
19795
19796
19797
19798
19799
19800
19801
19802
19803
19804
19805
19806
19807
19808
19809
19810
19811
19812
19813
19814
19815
19816
19817
19818
19819
19820
19821
19822
19823
19824
19825
19826
19827
19828
19829
19830
19831
19832
19833
19834
19835
19836
19837
19838
19839
19840
19841
19842
19843
19844
19845
19846
19847
19848
19849
19850
19851
19852
19853
19854
19855
19856
19857
19858
19859
19860
19861
19862
19863
19864
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876
19877
19878
19879
19880
19881
19882
19883
19884
19885
19886
19887
19888
19889
19890
19891
19892
19893
19894
19895
19896
19897
19898
19899
19900
19901
19902
19903
19904
19905
19906
19907
19908
19909
19910
19911
19912
19913
19914
19915
19916
19917
19918
19919
19920
19921
19922
19923
19924
19925
19926
19927
19928
19929
19930
19931
19932
19933
19934
19935
19936
19937
19938
19939
19940
19941
19942
19943
19944
19945
19946
19947
19948
19949
19950
19951
19952
19953
19954
19955
19956
19957
19958
19959
19960
19961
19962
19963
19964
19965
19966
19967
19968
19969
19970
19971
19972
19973
19974
19975
19976
19977
19978
19979
19980
19981
19982
19983
19984
19985
19986
19987
19988
19989
19990
19991
19992
19993
19994
19995
19996
19997
19998
19999
20000
20001
20002
20003
20004
20005
20006
20007
20008
20009
20010
20011
20012
20013
20014
20015
20016
20017
20018
20019
20020
20021
20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035
20036
20037
20038
20039
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049
20050
20051
20052
20053
20054
20055
20056
20057
20058
20059
20060
20061
20062
20063
20064
20065
20066
20067
20068
20069
20070
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080
20081

20082
20083
20084
20085
20086
20087
20088

20089
20090
20091
20092
20093
20094

20095
20096
20097
20098
20099
20100
20101
20102
20103
20104
20105
20106
20107
20108
20109
20110
20111
20112
20113
20114
20115
20116
20117
20118
20119
20120
20121
20122
20123
20124
20125
20126
20127
20128
20129
20130
20131
20132
20133
20134
20135
20136
20137
20138
20139
20140
20141
20142
20143
20144
20145
20146
20147
20148
20149
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161
20162
20163
20164
20165
20166
20167
20168
20169
20170
20171



20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201
20202
20203
20204
20205
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215
20216
20217
20218
20219
20220
20221
20222
20223
20224
20225
20226
20227
20228
20229
20230
20231
20232
20233
20234
20235
20236
20237
20238
20239
20240
20241
20242
20243
20244
    }
}

#include <ctype.h>
#include <string.h>



#define JIM_INTEGER_SPACE 24
#define MAX_FLOAT_WIDTH 320

Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
{
    const char *span, *format, *formatEnd, *msg;
    int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
    static const char * const mixedXPG =
            "cannot mix \"%\" and \"%n$\" conversion specifiers";
    static const char * const badIndex[2] = {
        "not enough arguments for all format specifiers",
        "\"%n$\" argument index out of range"
    };
    int formatLen;
    Jim_Obj *resultPtr;

    char *num_buffer = NULL;
    int num_buffer_size = 0;

    span = format = Jim_GetString(fmtObjPtr, &formatLen);
    formatEnd = format + formatLen;
    resultPtr = Jim_NewEmptyStringObj(interp);

    while (format != formatEnd) {
        char *end;
        int gotMinus, sawFlag;
        int gotPrecision, useShort;
        long width, precision;
        int newXpg;
        int ch;
        int step;
        int doubleType;
        char pad = ' ';
        char spec[2*JIM_INTEGER_SPACE + 12];
        char *p;

        int formatted_chars;
        int formatted_bytes;
        const char *formatted_buf;

        step = utf8_tounicode(format, &ch);
        format += step;
        if (ch != '%') {
            numBytes += step;
            continue;
        }
        if (numBytes) {
            Jim_AppendString(interp, resultPtr, span, numBytes);
            numBytes = 0;
        }


        step = utf8_tounicode(format, &ch);
        if (ch == '%') {
            span = format;
            numBytes = step;
            format += step;
            continue;
        }


        newXpg = 0;
        if (isdigit(ch)) {
            int position = strtoul(format, &end, 10);
            if (*end == '$') {
                newXpg = 1;
                objIndex = position - 1;
                format = end + 1;
                step = utf8_tounicode(format, &ch);
            }
        }
        if (newXpg) {
            if (gotSequential) {
                msg = mixedXPG;
                goto errorMsg;
            }
            gotXpg = 1;
        } else {
            if (gotXpg) {
                msg = mixedXPG;
                goto errorMsg;
            }
            gotSequential = 1;
        }
        if ((objIndex < 0) || (objIndex >= objc)) {
            msg = badIndex[gotXpg];
            goto errorMsg;
        }

        p = spec;
        *p++ = '%';

        gotMinus = 0;
        sawFlag = 1;
        do {
            switch (ch) {
            case '-':
                gotMinus = 1;
                break;
            case '0':
                pad = ch;
                break;
            case ' ':
            case '+':
            case '#':
                break;
            default:
                sawFlag = 0;
                continue;
            }
            *p++ = ch;
            format += step;
            step = utf8_tounicode(format, &ch);
        } while (sawFlag);


        width = 0;
        if (isdigit(ch)) {
            width = strtoul(format, &end, 10);
            format = end;
            step = utf8_tounicode(format, &ch);
        } else if (ch == '*') {
            if (objIndex >= objc - 1) {
                msg = badIndex[gotXpg];
                goto errorMsg;
            }
            if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
                goto error;
            }
            if (width < 0) {
                width = -width;
                if (!gotMinus) {
                    *p++ = '-';
                    gotMinus = 1;
                }
            }
            objIndex++;
            format += step;
            step = utf8_tounicode(format, &ch);
        }


        gotPrecision = precision = 0;
        if (ch == '.') {
            gotPrecision = 1;
            format += step;
            step = utf8_tounicode(format, &ch);
        }
        if (isdigit(ch)) {
            precision = strtoul(format, &end, 10);
            format = end;
            step = utf8_tounicode(format, &ch);
        } else if (ch == '*') {
            if (objIndex >= objc - 1) {
                msg = badIndex[gotXpg];
                goto errorMsg;
            }
            if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
                goto error;
            }


            if (precision < 0) {
                precision = 0;
            }
            objIndex++;
            format += step;
            step = utf8_tounicode(format, &ch);
        }


        useShort = 0;
        if (ch == 'h') {
            useShort = 1;
            format += step;
            step = utf8_tounicode(format, &ch);
        } else if (ch == 'l') {
            
            format += step;
            step = utf8_tounicode(format, &ch);
            if (ch == 'l') {
                format += step;
                step = utf8_tounicode(format, &ch);
            }
        }

        format += step;
        span = format;


        if (ch == 'i') {
            ch = 'd';
        }

        doubleType = 0;

        switch (ch) {
        case '\0':
            msg = "format string ended in middle of field specifier";
            goto errorMsg;
        case 's': {
            formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
            formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
            if (gotPrecision && (precision < formatted_chars)) {
                
                formatted_chars = precision;
                formatted_bytes = utf8_index(formatted_buf, precision);
            }
            break;
        }
        case 'c': {
            jim_wide code;

            if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
                goto error;
            }
            
            formatted_bytes = utf8_getchars(spec, code);
            formatted_buf = spec;
            formatted_chars = 1;
            break;
        }
        case 'b': {
                unsigned jim_wide w;
                int length;
                int i;
                int j;

                if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
                    goto error;
                }
                length = sizeof(w) * 8;


                
                if (num_buffer_size < length + 1) {
                    num_buffer_size = length + 1;
                    num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
                }

                j = 0;
                for (i = length; i > 0; ) {
                        i--;
                    if (w & ((unsigned jim_wide)1 << i)) {
                                num_buffer[j++] = '1';
                        }
                        else if (j || i == 0) {
                                num_buffer[j++] = '0';
                        }
                }
                num_buffer[j] = 0;
                formatted_chars = formatted_bytes = j;
                formatted_buf = num_buffer;
                break;
        }

        case 'e':
        case 'E':
        case 'f':
        case 'g':
        case 'G':
            doubleType = 1;
            
        case 'd':
        case 'u':
        case 'o':
        case 'x':
        case 'X': {
            jim_wide w;
            double d;
            int length;

            
            if (width) {
                p += sprintf(p, "%ld", width);
            }
            if (gotPrecision) {
                p += sprintf(p, ".%ld", precision);
            }

            
            if (doubleType) {
                if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
                    goto error;
                }
                length = MAX_FLOAT_WIDTH;
            }
            else {
                if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
                    goto error;
                }
                length = JIM_INTEGER_SPACE;
                if (useShort) {

                    if (ch == 'd') {
                        w = (short)w;
                    }
                    else {
                        w = (unsigned short)w;
                    }
                }

                *p++ = 'l';
#ifdef HAVE_LONG_LONG
                if (sizeof(long long) == sizeof(jim_wide)) {
                    *p++ = 'l';
                }
#endif

            }

            *p++ = (char) ch;
            *p = '\0';

            
            if (width > length) {
                length = width;
            }
            if (gotPrecision) {
                length += precision;
            }

            
            if (num_buffer_size < length + 1) {
                num_buffer_size = length + 1;
                num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
            }

            if (doubleType) {
                snprintf(num_buffer, length + 1, spec, d);
            }
            else {
                formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
            }
            formatted_chars = formatted_bytes = strlen(num_buffer);
            formatted_buf = num_buffer;
            break;
        }

        default: {
            
            spec[0] = ch;
            spec[1] = '\0';
            Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
            goto error;
        }
        }

        if (!gotMinus) {
            while (formatted_chars < width) {
                Jim_AppendString(interp, resultPtr, &pad, 1);
                formatted_chars++;
            }
        }

        Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);

        while (formatted_chars < width) {
            Jim_AppendString(interp, resultPtr, &pad, 1);
            formatted_chars++;
        }

        objIndex += gotSequential;
    }
    if (numBytes) {
        Jim_AppendString(interp, resultPtr, span, numBytes);
    }

    Jim_Free(num_buffer);
    return resultPtr;

  errorMsg:
    Jim_SetResultString(interp, msg, -1);
  error:
    Jim_FreeNewObj(interp, resultPtr);
    Jim_Free(num_buffer);
    return NULL;
}


#if defined(JIM_REGEXP)
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>






#define REG_MAX_PAREN 100



#define	END	0	
#define	BOL	1	
#define	EOL	2	
#define	ANY	3	
#define	ANYOF	4	
#define	ANYBUT	5	
#define	BRANCH	6	
#define	BACK	7	
#define	EXACTLY	8	
#define	NOTHING	9	
#define	REP	10	
#define	REPMIN	11	
#define	REPX	12	
#define	REPXMIN	13	

#define	WORDA	15	
#define	WORDZ	16	

#define	OPENNC 	1000	
#define	OPEN   	1001	
			



#define	CLOSENC	2000 	
#define	CLOSE	2001 	
#define	CLOSE_END	(CLOSE+REG_MAX_PAREN)

#define	REG_MAGIC	0xFADED00D


#define	OP(preg, p)	(preg->program[p])
#define	NEXT(preg, p)	(preg->program[p + 1])
#define	OPERAND(p)	((p) + 2)




#define	FAIL(R,M)	{ (R)->err = (M); return (M); }
#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
#define	META		"^$.[()|?{+*"

#define	HASWIDTH	1	
#define	SIMPLE		2	
#define	SPSTART		4	
#define	WORST		0	

#define MAX_REP_COUNT 1000000

static int reg(regex_t *preg, int paren , int *flagp );
static int regpiece(regex_t *preg, int *flagp );
static int regbranch(regex_t *preg, int *flagp );
static int regatom(regex_t *preg, int *flagp );
static int regnode(regex_t *preg, int op );
static int regnext(regex_t *preg, int p );
static void regc(regex_t *preg, int b );
static int reginsert(regex_t *preg, int op, int size, int opnd );
static void regtail(regex_t *preg, int p, int val);
static void regoptail(regex_t *preg, int p, int val );
static int regopsize(regex_t *preg, int p );

static int reg_range_find(const int *string, int c);
static const char *str_find(const char *string, int c, int nocase);
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);


#ifdef DEBUG
19983
19984
19985
19986
19987
19988
19989
19990
19991
19992
19993
19994
19995
19996
19997
19998
19999

	if (exp == NULL)
		FAIL(preg, REG_ERR_NULL_ARGUMENT);

	
	preg->cflags = cflags;
	preg->regparse = exp;
	
	preg->program = NULL;
	preg->proglen = 0;

	
	preg->proglen = (strlen(exp) + 1) * 5;
	preg->program = malloc(preg->proglen * sizeof(int));
	if (preg->program == NULL)
		FAIL(preg, REG_ERR_NOMEM);








<
<
<







20271
20272
20273
20274
20275
20276
20277



20278
20279
20280
20281
20282
20283
20284

	if (exp == NULL)
		FAIL(preg, REG_ERR_NULL_ARGUMENT);

	
	preg->cflags = cflags;
	preg->regparse = exp;




	
	preg->proglen = (strlen(exp) + 1) * 5;
	preg->program = malloc(preg->proglen * sizeof(int));
	if (preg->program == NULL)
		FAIL(preg, REG_ERR_NOMEM);

20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161
20162
20163
20164

static int regpiece(regex_t *preg, int *flagp)
{
	int ret;
	char op;
	int next;
	int flags;
	int chain = 0;
	int min;
	int max;

	ret = regatom(preg, &flags);
	if (ret == 0)
		return 0;








<







20435
20436
20437
20438
20439
20440
20441

20442
20443
20444
20445
20446
20447
20448

static int regpiece(regex_t *preg, int *flagp)
{
	int ret;
	char op;
	int next;
	int flags;

	int min;
	int max;

	ret = regatom(preg, &flags);
	if (ret == 0)
		return 0;

20233
20234
20235
20236
20237
20238
20239
20240
20241
20242
20243
20244
20245
20246
20247

	preg->regparse++;
	if (ISMULT(*preg->regparse)) {
		preg->err = REG_ERR_NESTED_COUNT;
		return 0;
	}

	return chain ? chain : ret;
}

static void reg_addrange(regex_t *preg, int lower, int upper)
{
	if (lower > upper) {
		reg_addrange(preg, upper, lower);
	}







|







20517
20518
20519
20520
20521
20522
20523
20524
20525
20526
20527
20528
20529
20530
20531

	preg->regparse++;
	if (ISMULT(*preg->regparse)) {
		preg->err = REG_ERR_NESTED_COUNT;
		return 0;
	}

	return ret;
}

static void reg_addrange(regex_t *preg, int lower, int upper)
{
	if (lower > upper) {
		reg_addrange(preg, upper, lower);
	}
20327
20328
20329
20330
20331
20332
20333

20334
20335
20336
20337
20338
20339
20340
				s += n;
			}
			break;
		case 'U':
			if ((n = parse_hex(s, 8, ch)) > 0) {
				s += n;
			}

		case 'x':
			if ((n = parse_hex(s, 2, ch)) > 0) {
				s += n;
			}
			break;
		case '\0':
			s--;







>







20611
20612
20613
20614
20615
20616
20617
20618
20619
20620
20621
20622
20623
20624
20625
				s += n;
			}
			break;
		case 'U':
			if ((n = parse_hex(s, 8, ch)) > 0) {
				s += n;
			}
			break;
		case 'x':
			if ((n = parse_hex(s, 2, ch)) > 0) {
				s += n;
			}
			break;
		case '\0':
			s--;
20575
20576
20577
20578
20579
20580
20581

20582
20583
20584
20585
20586
20587
20588
}


static int regnode(regex_t *preg, int op)
{
	reg_grow(preg, 2);


	preg->program[preg->p++] = op;
	preg->program[preg->p++] = 0;

	
	return preg->p - 2;
}








>







20860
20861
20862
20863
20864
20865
20866
20867
20868
20869
20870
20871
20872
20873
20874
}


static int regnode(regex_t *preg, int op)
{
	reg_grow(preg, 2);

	
	preg->program[preg->p++] = op;
	preg->program[preg->p++] = 0;

	
	return preg->p - 2;
}

20604
20605
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
20616
20617
20618
	preg->program[opnd] = op;

	preg->p += size;

	return opnd + size;
}

static void regtail_(regex_t *preg, int p, int val, int line )
{
	int scan;
	int temp;
	int offset;

	
	scan = p;







|







20890
20891
20892
20893
20894
20895
20896
20897
20898
20899
20900
20901
20902
20903
20904
	preg->program[opnd] = op;

	preg->p += size;

	return opnd + size;
}

static void regtail(regex_t *preg, int p, int val)
{
	int scan;
	int temp;
	int offset;

	
	scan = p;
20667
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698
20699
20700
20701
20702
20703
20704
20705
20706

	preg->eflags = eflags;
	preg->pmatch = pmatch;
	preg->nmatch = nmatch;
	preg->start = string;	

	
	for (scan = OPERAND(1); scan != 0; ) {
		switch (OP(preg, scan)) {
		case REP:
		case REPMIN:
		case REPX:
		case REPXMIN:
			preg->program[scan + 4] = 0;
			scan += 5;
			break;

		case ANYOF:
		case ANYBUT:
		case EXACTLY:
			scan += 2;
			while (preg->program[scan++]) {
			}
			break;

		case END:
			scan = 0;
			break;

		default:
			scan += 2;
			break;
		}
	}

	
	if (preg->regmust != 0) {
		s = string;
		while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
			if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {







|
|
<
<
<
<
<
|

|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<







20953
20954
20955
20956
20957
20958
20959
20960
20961





20962
20963
20964




20965











20966
20967
20968
20969
20970
20971
20972

	preg->eflags = eflags;
	preg->pmatch = pmatch;
	preg->nmatch = nmatch;
	preg->start = string;	

	
	for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
		int op = OP(preg, scan);





		if (op == END)
			break;
		if (op == REPX || op == REPXMIN)




			preg->program[scan + 4] = 0;











	}

	
	if (preg->regmust != 0) {
		s = string;
		while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
			if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
20948
20949
20950
20951
20952
20953
20954

20955
20956
20957
20958
20959
20960
20961
}


static int regmatch(regex_t *preg, int prog)
{
	int scan;	
	int next;		


	scan = prog;

#ifdef DEBUG
	if (scan != 0 && regnarrate)
		fprintf(stderr, "%s(\n", regprop(scan));
#endif







>







21214
21215
21216
21217
21218
21219
21220
21221
21222
21223
21224
21225
21226
21227
21228
}


static int regmatch(regex_t *preg, int prog)
{
	int scan;	
	int next;		
	const char *save;

	scan = prog;

#ifdef DEBUG
	if (scan != 0 && regnarrate)
		fprintf(stderr, "%s(\n", regprop(scan));
#endif
21036
21037
21038
21039
21040
21041
21042
21043
21044
21045
21046
21047
21048
21049
21050
21051
21052
21053
21054
21055
21056
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066
21067
21068
21069
21070
21071
21072
21073
21074
21075
21076
21077
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102

21103
21104
21105
21106
21107
21108
21109
21110
			}
			preg->reginput += n;
			break;
		case NOTHING:
			break;
		case BACK:
			break;
		case BRANCH: {
				const char *save;

				if (OP(preg, next) != BRANCH)		
					next = OPERAND(scan);	
				else {
					do {
						save = preg->reginput;
						if (regmatch(preg, OPERAND(scan))) {
							return(1);
						}
						preg->reginput = save;
						scan = regnext(preg, scan);
					} while (scan != 0 && OP(preg, scan) == BRANCH);
					return(0);
					
				}
			}
			break;
		case REP:
		case REPMIN:
			return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);

		case REPX:
		case REPXMIN:
			return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);

		case END:
			return(1);	
			break;

		case OPENNC:
		case CLOSENC:
			if (regmatch(preg, next)) {
				return 1;
			}
			return 0;

		default:
			if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
				const char *save;

				save = preg->reginput;

				if (regmatch(preg, next)) {
					int no;
					if (OP(preg, scan) < CLOSE) {
						no = OP(preg, scan) - OPEN;
						if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
							preg->pmatch[no].rm_so = save - preg->start;
						}
					}
					else {
						no = OP(preg, scan) - CLOSE;
						if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
							preg->pmatch[no].rm_eo = save - preg->start;
						}
					}
					return(1);
				} else

					return(0);
			}
			return REG_ERR_INTERNAL;
		}

		scan = next;
	}








|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
<











|
<



|
<
<
<



<
<

<

<

|





|





<
>
|







21303
21304
21305
21306
21307
21308
21309
21310


21311
21312
21313
21314
21315
21316
21317
21318
21319
21320
21321
21322
21323

21324
21325
21326
21327
21328
21329
21330
21331
21332
21333
21334
21335

21336
21337
21338
21339



21340
21341
21342


21343

21344

21345
21346
21347
21348
21349
21350
21351
21352
21353
21354
21355
21356
21357

21358
21359
21360
21361
21362
21363
21364
21365
21366
			}
			preg->reginput += n;
			break;
		case NOTHING:
			break;
		case BACK:
			break;
		case BRANCH:


			if (OP(preg, next) != BRANCH)		
				next = OPERAND(scan);	
			else {
				do {
					save = preg->reginput;
					if (regmatch(preg, OPERAND(scan))) {
						return(1);
					}
					preg->reginput = save;
					scan = regnext(preg, scan);
				} while (scan != 0 && OP(preg, scan) == BRANCH);
				return(0);
				

			}
			break;
		case REP:
		case REPMIN:
			return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);

		case REPX:
		case REPXMIN:
			return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);

		case END:
			return 1;	


		case OPENNC:
		case CLOSENC:
			return regmatch(preg, next);




		default:
			if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {


				save = preg->reginput;

				if (regmatch(preg, next)) {

					if (OP(preg, scan) < CLOSE) {
						int no = OP(preg, scan) - OPEN;
						if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
							preg->pmatch[no].rm_so = save - preg->start;
						}
					}
					else {
						int no = OP(preg, scan) - CLOSE;
						if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
							preg->pmatch[no].rm_eo = save - preg->start;
						}
					}
					return(1);

				}
				return(0);
			}
			return REG_ERR_INTERNAL;
		}

		scan = next;
	}

21179
21180
21181
21182
21183
21184
21185






















21186
21187
21188
21189
21190
21191
21192
		return 0;

	if (OP(preg, p) == BACK)
		return(p-offset);
	else
		return(p+offset);
}
























size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size)
{
	static const char *error_strings[] = {
		"success",
		"no match",







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







21435
21436
21437
21438
21439
21440
21441
21442
21443
21444
21445
21446
21447
21448
21449
21450
21451
21452
21453
21454
21455
21456
21457
21458
21459
21460
21461
21462
21463
21464
21465
21466
21467
21468
21469
21470
		return 0;

	if (OP(preg, p) == BACK)
		return(p-offset);
	else
		return(p+offset);
}

static int regopsize(regex_t *preg, int p )
{
	
	switch (OP(preg, p)) {
		case REP:
		case REPMIN:
		case REPX:
		case REPXMIN:
			return 5;

		case ANYOF:
		case ANYBUT:
		case EXACTLY: {
			int s = p + 2;
			while (preg->program[s++]) {
			}
			return s - p;
		}
	}
	return 2;
}


size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size)
{
	static const char *error_strings[] = {
		"success",
		"no match",
21357
21358
21359
21360
21361
21362
21363

21364
21365
21366
21367
21368
21369
21370
21371
21372




21373
21374
21375
21376
21377
21378
21379
#endif

char *Jim_HistoryGetline(const char *prompt)
{
#ifdef USE_LINENOISE
    return linenoise(prompt);
#else

    char *line = malloc(MAX_LINE_LEN);

    fputs(prompt, stdout);
    fflush(stdout);

    if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
        free(line);
        return NULL;
    }




    return line;
#endif
}

void Jim_HistoryLoad(const char *filename)
{
#ifdef USE_LINENOISE







>









>
>
>
>







21635
21636
21637
21638
21639
21640
21641
21642
21643
21644
21645
21646
21647
21648
21649
21650
21651
21652
21653
21654
21655
21656
21657
21658
21659
21660
21661
21662
#endif

char *Jim_HistoryGetline(const char *prompt)
{
#ifdef USE_LINENOISE
    return linenoise(prompt);
#else
    int len;
    char *line = malloc(MAX_LINE_LEN);

    fputs(prompt, stdout);
    fflush(stdout);

    if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
        free(line);
        return NULL;
    }
    len = strlen(line);
    if (len && line[len - 1] == '\n') {
        line[len - 1] = '\0';
    }
    return line;
#endif
}

void Jim_HistoryLoad(const char *filename)
{
#ifdef USE_LINENOISE
21420
21421
21422
21423
21424
21425
21426
21427
21428
21429
21430
21431
21432
21433
21434
        int history_len = strlen(home) + sizeof("/.jim_history");
        history_file = Jim_Alloc(history_len);
        snprintf(history_file, history_len, "%s/.jim_history", home);
        Jim_HistoryLoad(history_file);
    }
#endif

    printf("Welcome to Jim version %d.%d" JIM_NL,
        JIM_VERSION / 100, JIM_VERSION % 100);
    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");

    while (1) {
        Jim_Obj *scriptObjPtr;
        const char *result;
        int reslen;







|







21703
21704
21705
21706
21707
21708
21709
21710
21711
21712
21713
21714
21715
21716
21717
        int history_len = strlen(home) + sizeof("/.jim_history");
        history_file = Jim_Alloc(history_len);
        snprintf(history_file, history_len, "%s/.jim_history", home);
        Jim_HistoryLoad(history_file);
    }
#endif

    printf("Welcome to Jim version %d.%d\n",
        JIM_VERSION / 100, JIM_VERSION % 100);
    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");

    while (1) {
        Jim_Obj *scriptObjPtr;
        const char *result;
        int reslen;
21532
21533
21534
21535
21536
21537
21538






21539
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596

        Jim_ListAppendElement(interp, listObj, obj);
    }

    Jim_SetVariableStr(interp, "argv", listObj);
    Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
}







int main(int argc, char *const argv[])
{
    int retcode;
    Jim_Interp *interp;

    if (argc > 1 && strcmp(argv[1], "--version") == 0) {
        printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
        return 0;
    }

    
    interp = Jim_CreateInterp();
    Jim_RegisterCoreCommands(interp);

    
    if (Jim_InitStaticExtensions(interp) != JIM_OK) {
        Jim_MakeErrorMessage(interp);
        fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
    }

    Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
    retcode = Jim_initjimshInit(interp);

    if (argc == 1) {
        if (retcode == JIM_ERR) {
            Jim_MakeErrorMessage(interp);
            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
        }
        if (retcode != JIM_EXIT) {
            JimSetArgv(interp, 0, NULL);
            retcode = Jim_InteractivePrompt(interp);
        }
    }
    else {
        if (argc > 2 && strcmp(argv[1], "-e") == 0) {
            JimSetArgv(interp, argc - 3, argv + 3);
            retcode = Jim_Eval(interp, argv[2]);
            if (retcode != JIM_ERR) {
                printf("%s\n", Jim_String(Jim_GetResult(interp)));
            }
        }
        else {
            Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
            JimSetArgv(interp, argc - 2, argv + 2);
            retcode = Jim_EvalFile(interp, argv[1]);
        }
        if (retcode == JIM_ERR) {
            Jim_MakeErrorMessage(interp);
            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
        }
    }
    if (retcode == JIM_EXIT) {
        retcode = Jim_GetExitCode(interp);
    }
    else if (retcode == JIM_ERR) {
        retcode = 1;







>
>
>
>
>
>

















|
<








|
<




















|
<







21815
21816
21817
21818
21819
21820
21821
21822
21823
21824
21825
21826
21827
21828
21829
21830
21831
21832
21833
21834
21835
21836
21837
21838
21839
21840
21841
21842
21843
21844
21845

21846
21847
21848
21849
21850
21851
21852
21853
21854

21855
21856
21857
21858
21859
21860
21861
21862
21863
21864
21865
21866
21867
21868
21869
21870
21871
21872
21873
21874
21875

21876
21877
21878
21879
21880
21881
21882

        Jim_ListAppendElement(interp, listObj, obj);
    }

    Jim_SetVariableStr(interp, "argv", listObj);
    Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
}

static void JimPrintErrorMessage(Jim_Interp *interp)
{
    Jim_MakeErrorMessage(interp);
    fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
}

int main(int argc, char *const argv[])
{
    int retcode;
    Jim_Interp *interp;

    if (argc > 1 && strcmp(argv[1], "--version") == 0) {
        printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
        return 0;
    }

    
    interp = Jim_CreateInterp();
    Jim_RegisterCoreCommands(interp);

    
    if (Jim_InitStaticExtensions(interp) != JIM_OK) {
        JimPrintErrorMessage(interp);

    }

    Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
    retcode = Jim_initjimshInit(interp);

    if (argc == 1) {
        if (retcode == JIM_ERR) {
            JimPrintErrorMessage(interp);

        }
        if (retcode != JIM_EXIT) {
            JimSetArgv(interp, 0, NULL);
            retcode = Jim_InteractivePrompt(interp);
        }
    }
    else {
        if (argc > 2 && strcmp(argv[1], "-e") == 0) {
            JimSetArgv(interp, argc - 3, argv + 3);
            retcode = Jim_Eval(interp, argv[2]);
            if (retcode != JIM_ERR) {
                printf("%s\n", Jim_String(Jim_GetResult(interp)));
            }
        }
        else {
            Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
            JimSetArgv(interp, argc - 2, argv + 2);
            retcode = Jim_EvalFile(interp, argv[1]);
        }
        if (retcode == JIM_ERR) {
            JimPrintErrorMessage(interp);

        }
    }
    if (retcode == JIM_EXIT) {
        retcode = Jim_GetExitCode(interp);
    }
    else if (retcode == JIM_ERR) {
        retcode = 1;
Changes to autosetup/local.tcl.
24
25
26
27
28
29
30



































































































































































































		if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} {
			set value [regsub -all {\$\{.*\}} $value ""]
			set tclconfig($name) [string trim $value ']
		}
	}
	return [array get tclconfig]
}










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
		if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} {
			set value [regsub -all {\$\{.*\}} $value ""]
			set tclconfig($name) [string trim $value ']
		}
	}
	return [array get tclconfig]
}

# The complex extension checking is done here.

global withinfo
global extdb

# Final determination of module status
dict set extdb status {}

# Returns 1 if the extension has the attribute
proc ext-has {ext attr} {
    expr {$attr in [dict get $::extdb attrs $ext]}
}

# Returns an entry from the extension 'info' table, or $default otherwise
proc ext-get {ext key {default {}}} {
    if {[dict exists $::extdb info $ext $key]} {
        return [dict get $::extdb info $ext $key]
    } else {
        return $default
    }
}

# Set the status of the extension to the given value, and returns the value
proc ext-set-status {ext value} {
    dict set ::extdb status $ext $value
    return $value
}

# Returns the status of the extension, or ? if unknown
proc ext-get-status {ext} {
    if {[dict exists $::extdb status $ext]} {
        return [dict get $::extdb status $ext]
    }
    return ?
}

proc check-extension-status {ext required} {
    global withinfo

    set status [ext-get-status $ext]

    if {$ext in $withinfo(without)} {
        # Disabled without further ado
        msg-result "Extension $ext...disabled"
        return [ext-set-status $ext n]
    }

    if {$status in {m y n}} {
        return $status
    }

    # required is "required" if this extension *must* be enabled
    # required is "wanted" if it is not fatal for this extension
    # not to be enabled

    array set depinfo {m 0 y 0 n 0}

    # Check direct dependencies
    if [ext-get $ext check 1] {
        # "check" conditions are met
    } else {
        # not met
        incr depinfo(n)
    }

    if {$depinfo(n) == 0} {
        # Now extension dependencies
        foreach i [ext-get $ext dep] {
            set status [check-extension-status $i $required]
            #puts "$ext: dep $i $required => $status"
            incr depinfo($status)
            if {$depinfo(n)} {
                break
            }
        }
    }

    #parray depinfo

    if {$depinfo(n)} {
        msg-checking "Extension $ext..."
        if {$required eq "required"} {
            user-error "dependencies not met"
        }
        msg-result "disabled (dependencies)"
        return [ext-set-status $ext n]
    }

    # Selected as a module?
    if {$ext in $withinfo(mod)} {
        if {[ext-has $ext tcl]} {
            # Easy, a Tcl module
            msg-result "Extension $ext...tcl"
        } elseif {[ext-has $ext static]} {
            user-error "Extension $ext can't be a module"
        } else {
            msg-result "Extension $ext...module"
            foreach i [ext-get $ext libdep] {
                define-append LDLIBS_$ext [get-define $i ""]
            }
        }
        return [ext-set-status $ext m]
    }

    # Selected as a static extension?
    if {[ext-has $ext shared]} {
        user-error "Extension $ext can only be selected as a module"
    } elseif {$ext in $withinfo(ext) || $required eq "$required"} {
        msg-result "Extension $ext...enabled"
    } elseif {$ext in $withinfo(maybe)} {
        msg-result "Extension $ext...enabled (default)"
    } else {
        # Could be selected, but isn't (yet)
        return [ext-set-status $ext x]
    }
    foreach i [ext-get $ext libdep] {
        define-append LDLIBS [get-define $i ""]
    }
    return [ext-set-status $ext y]
}

# Examines the user options (the $withinfo array)
# and the extension database ($extdb) to determine
# what is selected, and in what way.
#
# The results are available via ext-get-status
# And a dictionary is returned containing four keys:
#   static-c     extensions which are static C
#   static-tcl   extensions which are static Tcl
#   module-c     extensions which are C modules
#   module-tcl   extensions which are Tcl modules
proc check-extensions {} {
    global extdb withinfo

    # Check valid extension names
    foreach i [concat $withinfo(ext) $withinfo(mod)] {
        if {![dict exists $extdb attrs $i]} {
            user-error "Unknown extension: $i"
        }
    }

    set extlist [lsort [dict keys [dict get $extdb attrs]]]

    set withinfo(maybe) {}

    # Now work out the default status. We have.
    # normal case, include !optional if possible
    # --without=default, don't include optional
    if {$withinfo(nodefault)} {
        lappend withinfo(maybe) stdlib
    } else {
        foreach i $extlist {
            if {![ext-has $i optional]} {
                lappend withinfo(maybe) $i
            }
        }
    }

    foreach i $extlist {
        define LDLIBS_$i ""
    }

    foreach i [concat $withinfo(ext) $withinfo(mod)] {
        check-extension-status $i required
    }
    foreach i $withinfo(maybe) {
        check-extension-status $i wanted
    }

    array set extinfo {static-c {} static-tcl {} module-c {} module-tcl {}}

    foreach i $extlist {
        set status [ext-get-status $i]
        set tcl [ext-has $i tcl]
        switch $status,$tcl {
            y,1 {
                define jim_ext_$i
                lappend extinfo(static-tcl) $i
            }
            y,0 {
                define jim_ext_$i
                lappend extinfo(static-c) $i
                # If there are any static C++ extensions, jimsh must be linked using
                # the C++ compiler
                if {[ext-has $i cpp]} {
                    define HAVE_CXX_EXTENSIONS
                }
            }
            m,1 { lappend extinfo(module-tcl) $i }
            m,0 { lappend extinfo(module-c) $i }
        }
    }
    return [array get extinfo]
}
Added setup/fossil.iss.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
;
; Copyright (c) 2014 D. Richard Hipp
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the Simplified BSD License (also
; known as the "2-Clause License" or "FreeBSD License".)
;
; This program is distributed in the hope that it will be useful,
; but without any warranty; without even the implied warranty of
; merchantability or fitness for a particular purpose.
;
; Author contact information:
;   drh@hwaci.com
;   http://www.hwaci.com/drh/
;

[Setup]
ArchitecturesAllowed=x86 x64
AlwaysShowComponentsList=false
AppCopyright=Copyright (c) D. Richard Hipp.  All rights reserved.
AppID={{f1c25a1f-3954-4e1a-ac36-4314c52f057c}
AppName=Fossil
AppPublisher=Fossil Development Team
AppPublisherURL=http://www.fossil-scm.org/
AppSupportURL=http://www.fossil-scm.org/
AppUpdatesURL=http://www.fossil-scm.org/
AppVerName=Fossil v{#AppVersion}
AppVersion={#AppVersion}
AppComments=Simple, high-reliability, distributed software configuration management system.
AppReadmeFile=http://www.fossil-scm.org/index.html/doc/tip/www/quickstart.wiki
DefaultDirName={pf}\Fossil
DefaultGroupName=Fossil
OutputBaseFilename=fossil-win32-{#AppVersion}
OutputManifestFile=fossil-win32-{#AppVersion}-manifest.txt
SetupLogging=true
UninstallFilesDir={app}\uninstall
VersionInfoVersion={#AppVersion}

[Components]
Name: Application; Description: Core application.; Types: custom compact full; Flags: fixed

[Dirs]
Name: {app}\bin

[Files]
Components: Application; Source: ..\fossil.exe; DestDir: {app}\bin; Flags: restartreplace uninsrestartdelete

[Registry]
Components: Application; Root: HKLM32; SubKey: Software\Fossil; ValueType: string; ValueName: Install_Dir; ValueData: {app}; Flags: uninsdeletekeyifempty uninsdeletevalue
Name change from fossil.nsi to setup/fossil.nsi.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
DirText "Choose a directory to install in to:"

; The stuff to install
Section "Fossil (required)"
  ; Set output path to the installation directory.
  SetOutPath $INSTDIR
  ; Put file there
  File ".\fossil.exe"
  ; Write the installation path into the registry
  WriteRegStr HKLM SOFTWARE\Fossil "Install_Dir" "$INSTDIR"
  ; Write the uninstall keys for Windows
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Fossil" "DisplayName" "Fossil (remove only)"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Fossil" "UninstallString" '"$INSTDIR\uninstall.exe"'
  WriteUninstaller "uninstall.exe"
SectionEnd







|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
DirText "Choose a directory to install in to:"

; The stuff to install
Section "Fossil (required)"
  ; Set output path to the installation directory.
  SetOutPath $INSTDIR
  ; Put file there
  File "..\fossil.exe"
  ; Write the installation path into the registry
  WriteRegStr HKLM SOFTWARE\Fossil "Install_Dir" "$INSTDIR"
  ; Write the uninstall keys for Windows
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Fossil" "DisplayName" "Fossil (remove only)"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Fossil" "UninstallString" '"$INSTDIR\uninstall.exe"'
  WriteUninstaller "uninstall.exe"
SectionEnd
Changes to src/add.c.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
     "_FOSSIL_-wal",
     "_FOSSIL_-shm",
     ".fslckout",
     ".fslckout-journal",
     ".fslckout-wal",
     ".fslckout-shm",

     /* The use of ".fos" as the name of the checkout database is 
     ** deprecated.  Use ".fslckout" instead.  At some point, the following
     ** entries should be removed.  2012-02-04 */
     ".fos",
     ".fos-journal",
     ".fos-wal",
     ".fos-shm",
  };







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
     "_FOSSIL_-wal",
     "_FOSSIL_-shm",
     ".fslckout",
     ".fslckout-journal",
     ".fslckout-wal",
     ".fslckout-shm",

     /* The use of ".fos" as the name of the checkout database is
     ** deprecated.  Use ".fslckout" instead.  At some point, the following
     ** entries should be removed.  2012-02-04 */
     ".fos",
     ".fos-journal",
     ".fos-wal",
     ".fos-shm",
  };
121
122
123
124
125
126
127




128
129
130
131
132
133
134
**
** Show all reserved filenames for the current check-out.
*/
void test_reserved_names(void){
  int i;
  const char *z;
  int omitRepo = find_option("omitrepo",0,0)!=0;




  db_must_be_within_tree();
  for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
    fossil_print("%3d: %s\n", i, z);
  }
  fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
}








>
>
>
>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
**
** Show all reserved filenames for the current check-out.
*/
void test_reserved_names(void){
  int i;
  const char *z;
  int omitRepo = find_option("omitrepo",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  db_must_be_within_tree();
  for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
    fossil_print("%3d: %s\n", i, z);
  }
  fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
}

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  const char *zRepo;        /* Name of the repository database file */
  int nAdd = 0;             /* Number of files added */
  int i;                    /* Loop counter */
  const char *zReserved;    /* Name of a reserved file */
  Blob repoName;            /* Treename of the repository */
  Stmt loop;                /* SQL to loop over all files to add */
  int (*xCmp)(const char*,const char*);
 
  if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
    blob_zero(&repoName);
    zRepo = "";
  }else{
    zRepo = blob_str(&repoName);
  }
  if( filenames_are_case_sensitive() ){







|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  const char *zRepo;        /* Name of the repository database file */
  int nAdd = 0;             /* Number of files added */
  int i;                    /* Loop counter */
  const char *zReserved;    /* Name of a reserved file */
  Blob repoName;            /* Treename of the repository */
  Stmt loop;                /* SQL to loop over all files to add */
  int (*xCmp)(const char*,const char*);

  if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
    blob_zero(&repoName);
    zRepo = "";
  }else{
    zRepo = blob_str(&repoName);
  }
  if( filenames_are_case_sensitive() ){
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
** The --case-sensitive option determines whether or not filenames should
** be treated case sensitive or not. If the option is not given, the default
** depends on the global setting, or the operating system default, if not set.
**
** Options:
**
**    --case-sensitive <BOOL> override case-sensitive setting
**    --dotfiles              include files beginning with a dot (".")   
**    -f|--force              Add files without prompting
**    --ignore <CSG>          ignore files matching patterns from the 
**                            comma separated list of glob patterns.
**    --clean <CSG>           also ignore files matching patterns from
**                            the comma separated list of glob patterns.
** 
** See also: addremove, rm
*/
void add_cmd(void){
  int i;                     /* Loop counter */
  int vid;                   /* Currently checked out version */
  int nRoot;                 /* Full path characters in g.zLocalRoot */
  const char *zCleanFlag;    /* The --clean option or clean-glob setting */
  const char *zIgnoreFlag;   /* The --ignore option or ignore-glob setting */
  Glob *pIgnore, *pClean;    /* Ignore everything matching the glob patterns */
  unsigned scanFlags = 0;    /* Flags passed to vfile_scan() */
  int forceFlag;

  zCleanFlag = find_option("clean",0,1);
  zIgnoreFlag = find_option("ignore",0,1);
  forceFlag = find_option("force","f",0)!=0;
  if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
  capture_case_sensitive_option();



  db_must_be_within_tree();
  if( zCleanFlag==0 ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  pClean = glob_create(zCleanFlag);
  pIgnore = glob_create(zIgnoreFlag);
  nRoot = strlen(g.zLocalRoot);
  
  /* Load the names of all files that are to be added into sfile temp table */
  for(i=2; i<g.argc; i++){
    char *zName;
    int isDir;
    Blob fullName;

    /* file_tree_name() throws a fatal error if g.argv[i] is outside of the







|

|



|
















|
>
>
>














|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
** The --case-sensitive option determines whether or not filenames should
** be treated case sensitive or not. If the option is not given, the default
** depends on the global setting, or the operating system default, if not set.
**
** Options:
**
**    --case-sensitive <BOOL> override case-sensitive setting
**    --dotfiles              include files beginning with a dot (".")
**    -f|--force              Add files without prompting
**    --ignore <CSG>          ignore files matching patterns from the
**                            comma separated list of glob patterns.
**    --clean <CSG>           also ignore files matching patterns from
**                            the comma separated list of glob patterns.
**
** See also: addremove, rm
*/
void add_cmd(void){
  int i;                     /* Loop counter */
  int vid;                   /* Currently checked out version */
  int nRoot;                 /* Full path characters in g.zLocalRoot */
  const char *zCleanFlag;    /* The --clean option or clean-glob setting */
  const char *zIgnoreFlag;   /* The --ignore option or ignore-glob setting */
  Glob *pIgnore, *pClean;    /* Ignore everything matching the glob patterns */
  unsigned scanFlags = 0;    /* Flags passed to vfile_scan() */
  int forceFlag;

  zCleanFlag = find_option("clean",0,1);
  zIgnoreFlag = find_option("ignore",0,1);
  forceFlag = find_option("force","f",0)!=0;
  if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;

  /* We should be done with options.. */
  verify_all_options();

  db_must_be_within_tree();
  if( zCleanFlag==0 ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  pClean = glob_create(zCleanFlag);
  pIgnore = glob_create(zIgnoreFlag);
  nRoot = strlen(g.zLocalRoot);

  /* Load the names of all files that are to be added into sfile temp table */
  for(i=2; i<g.argc; i++){
    char *zName;
    int isDir;
    Blob fullName;

    /* file_tree_name() throws a fatal error if g.argv[i] is outside of the
343
344
345
346
347
348
349


350
351
352
353
354
355
356
357
**
** See also: addremove, add
*/
void delete_cmd(void){
  int i;
  Stmt loop;



  capture_case_sensitive_option();
  db_must_be_within_tree();
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  for(i=2; i<g.argc; i++){
    Blob treeName;
    char *zTreeName;







>
>
|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
**
** See also: addremove, add
*/
void delete_cmd(void){
  int i;
  Stmt loop;

  /* We should be done with options.. */
  verify_all_options();

  db_must_be_within_tree();
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  for(i=2; i<g.argc; i++){
    Blob treeName;
    char *zTreeName;
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
       "     OR (pathname>'%q/' %s AND pathname<'%q0' %s))"
       "    AND NOT deleted",
       zTreeName, filename_collation(), zTreeName,
       filename_collation(), zTreeName, filename_collation()
    );
    blob_reset(&treeName);
  }
  
  db_prepare(&loop, "SELECT x FROM sfile");
  while( db_step(&loop)==SQLITE_ROW ){
    fossil_print("DELETED %s\n", db_column_text(&loop, 0));
  }
  db_finalize(&loop);
  db_multi_exec(
    "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"







|







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
       "     OR (pathname>'%q/' %s AND pathname<'%q0' %s))"
       "    AND NOT deleted",
       zTreeName, filename_collation(), zTreeName,
       filename_collation(), zTreeName, filename_collation()
    );
    blob_reset(&treeName);
  }

  db_prepare(&loop, "SELECT x FROM sfile");
  while( db_step(&loop)==SQLITE_ROW ){
    fossil_print("DELETED %s\n", db_column_text(&loop, 0));
  }
  db_finalize(&loop);
  db_multi_exec(
    "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
#else
      caseSensitive = 1;  /* Unix */
#endif
      caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
    }
    if( !caseSensitive && g.localOpen ){
      db_multi_exec(
         "CREATE INDEX IF NOT EXISTS vfile_nocase"
         "  ON vfile(pathname COLLATE nocase)"

      );
    }
  }
  return caseSensitive;
}

/*







|
|
>







440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
#else
      caseSensitive = 1;  /* Unix */
#endif
      caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
    }
    if( !caseSensitive && g.localOpen ){
      db_multi_exec(
         "CREATE INDEX IF NOT EXISTS %s.vfile_nocase"
         "  ON vfile(pathname COLLATE nocase)",
         db_name("localdb")
      );
    }
  }
  return caseSensitive;
}

/*
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
** --case-sensitive option with the "case-sensitive" setting and the
** --clean option with the "clean-glob" setting. See the documentation
** on the "settings" command for further information.
**
** The -n|--dry-run option shows what would happen without actually doing anything.
**
** This command can be used to track third party software.
** 
** Options: 
**   --case-sensitive <BOOL> override case-sensitive setting
**   --dotfiles              include files beginning with a dot (".")
**   --ignore <CSG>          ignore files matching patterns from the
**                           comma separated list of glob patterns.
**   --clean <CSG>           also ignore files matching patterns from
**                           the comma separated list of glob patterns.
**   -n|--dry-run            If given, display instead of run actions







|
|







490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
** --case-sensitive option with the "case-sensitive" setting and the
** --clean option with the "clean-glob" setting. See the documentation
** on the "settings" command for further information.
**
** The -n|--dry-run option shows what would happen without actually doing anything.
**
** This command can be used to track third party software.
**
** Options:
**   --case-sensitive <BOOL> override case-sensitive setting
**   --dotfiles              include files beginning with a dot (".")
**   --ignore <CSG>          ignore files matching patterns from the
**                           comma separated list of glob patterns.
**   --clean <CSG>           also ignore files matching patterns from
**                           the comma separated list of glob patterns.
**   -n|--dry-run            If given, display instead of run actions
508
509
510
511
512
513
514
515



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  int nAdd = 0;
  int nDelete = 0;
  Glob *pIgnore, *pClean;

  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }
  capture_case_sensitive_option();



  db_must_be_within_tree();
  if( zCleanFlag==0 ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  db_begin_transaction();

  /* step 1:  
  ** Populate the temp table "sfile" with the names of all unmanaged
  ** files currently in the check-out, except for files that match the
  ** --ignore or ignore-glob patterns and dot-files.  Then add all of
  ** the files in the sfile temp table to the set of managed files.
  */
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());







|
>
>
>










|







518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  int nAdd = 0;
  int nDelete = 0;
  Glob *pIgnore, *pClean;

  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }

  /* We should be done with options.. */
  verify_all_options();

  db_must_be_within_tree();
  if( zCleanFlag==0 ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  db_begin_transaction();

  /* step 1:
  ** Populate the temp table "sfile" with the names of all unmanaged
  ** files currently in the check-out, except for files that match the
  ** --ignore or ignore-glob patterns and dot-files.  Then add all of
  ** the files in the sfile temp table to the set of managed files.
  */
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  db_prepare(&q,
      "SELECT pathname, %Q || pathname, deleted FROM vfile"
      " WHERE NOT deleted"
      " ORDER BY 1",
      g.zLocalRoot
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char * zFile;
    const char * zPath;

    zFile = db_column_text(&q, 0);
    zPath = db_column_text(&q, 1);
    if( !file_wd_isfile_or_link(zPath) ){
      if( !dryRunFlag ){
        db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
      }







|
|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  db_prepare(&q,
      "SELECT pathname, %Q || pathname, deleted FROM vfile"
      " WHERE NOT deleted"
      " ORDER BY 1",
      g.zLocalRoot
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFile;
    const char *zPath;

    zFile = db_column_text(&q, 0);
    zPath = db_column_text(&q, 1);
    if( !file_wd_isfile_or_link(zPath) ){
      if( !dryRunFlag ){
        db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
      }
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
*/
static void mv_one_file(int vid, const char *zOrig, const char *zNew){
  int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
                         zNew, filename_collation());
  if( x>=0 ){
    if( x==0 ){
      fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
                   " is currently under management", zOrig, zNew, zNew); 
    }else{
      fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
                   "not yet been committed", zOrig, zNew, zNew);
    }
  }
  fossil_print("RENAME %s %s\n", zOrig, zNew);
  db_multi_exec(







|







590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
*/
static void mv_one_file(int vid, const char *zOrig, const char *zNew){
  int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
                         zNew, filename_collation());
  if( x>=0 ){
    if( x==0 ){
      fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
                   " is currently under management", zOrig, zNew, zNew);
    }else{
      fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
                   "not yet been committed", zOrig, zNew, zNew);
    }
  }
  fossil_print("RENAME %s %s\n", zOrig, zNew);
  db_multi_exec(
616
617
618
619
620
621
622
623
624




625
626
627
628
629
630
631
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;
  Stmt q;

  capture_case_sensitive_option();
  db_must_be_within_tree();




  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("no checkout rename files in");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
  }







<

>
>
>
>







629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;
  Stmt q;


  db_must_be_within_tree();

  /* We should be done with options.. */
  verify_all_options();

  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("no checkout rename files in");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
  }
Changes to src/allrepo.c.
105
106
107
108
109
110
111


112
113
114
115
116
117
118
**               line options supported by the extra command itself, if any
**               are present, are passed along verbatim.
**
**    ignore     Arguments are repositories that should be ignored by
**               subsequent clean, extras, list, pull, push, rebuild, and
**               sync operations.  The -c|--ckout option causes the listed
**               local checkouts to be ignored instead.


**
**    list | ls  Display the location of all repositories.  The -c|--ckout
**               option causes all local checkouts to be listed instead.
**
**    pull       Run a "pull" operation on all repositories.  Only the
**               --verbose option is supported.
**







>
>







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
**               line options supported by the extra command itself, if any
**               are present, are passed along verbatim.
**
**    ignore     Arguments are repositories that should be ignored by
**               subsequent clean, extras, list, pull, push, rebuild, and
**               sync operations.  The -c|--ckout option causes the listed
**               local checkouts to be ignored instead.
**
**    info       Run the "info" command on all repositories.
**
**    list | ls  Display the location of all repositories.  The -c|--ckout
**               option causes all local checkouts to be listed instead.
**
**    pull       Run a "pull" operation on all repositories.  Only the
**               --verbose option is supported.
**
153
154
155
156
157
158
159

160
161
162
163
164
165
166
  int useCheckouts = 0;
  int quiet = 0;
  int dryRunFlag = 0;
  int showFile = find_option("showfile",0,0)!=0;
  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;
  int nToDel = 0;


  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }

  if( g.argc<3 ){







>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  int useCheckouts = 0;
  int quiet = 0;
  int dryRunFlag = 0;
  int showFile = find_option("showfile",0,0)!=0;
  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;
  int nToDel = 0;
  int showLabel = 0;

  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }

  if( g.argc<3 ){
256
257
258
259
260
261
262




263
264
265
266
267
268

269
270

271
272
273
274
275
276
277

278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304






305
306
307
308
309
310
311
      }else{
        db_multi_exec("%s", zSql);
      }
      fossil_free(zSql);
    }
    db_end_transaction(0);
    return;




  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "changes clean extras ignore list ls push pull rebuild sync");
  }
  verify_all_options();
  zFossil = quoteFilename(g.nameOfExe);

  if( useCheckouts ){
    db_prepare(&q,

       "SELECT DISTINCT substr(name, 7), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 6)=='ckout:'"
       " ORDER BY 1"
    );
  }else{
    db_prepare(&q,

       "SELECT DISTINCT substr(name, 6), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 5)=='repo:'"
       " ORDER BY 1"
    );
  }
  db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");

  while( db_step(&q)==SQLITE_ROW ){
    const char *zFilename = db_column_text(&q, 0);
    if( file_access(zFilename, F_OK)
     || !file_is_canonical(zFilename)
     || (useCheckouts && file_isdir(zFilename)!=1)
    ){
      db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }else if( showFile ){
      fossil_print("%s: %s\n", useCheckouts ? "checkout" : "repository",
                   zFilename);
    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s%s",
                      zFossil, zCmd, zQFilename, blob_str(&extra));






    if( !quiet || dryRunFlag ){
      fossil_print("%s\n", zSyscmd);
      fflush(stdout);
    }
    rc = dryRunFlag ? 0 : fossil_system(zSyscmd);
    free(zSyscmd);
    free(zQFilename);







>
>
>
>






>

|
>






|
>







>




















>
>
>
>
>
>







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
      }else{
        db_multi_exec("%s", zSql);
      }
      fossil_free(zSql);
    }
    db_end_transaction(0);
    return;
  }else if( strncmp(zCmd, "info", n)==0 ){
    zCmd = "info";
    showLabel = 1;
    quiet = 1;
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "changes clean extras ignore list ls push pull rebuild sync");
  }
  verify_all_options();
  zFossil = quoteFilename(g.nameOfExe);
  db_multi_exec("CREATE TEMP TABLE repolist(name,tag);");
  if( useCheckouts ){
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT DISTINCT substr(name, 7), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 6)=='ckout:'"
       " ORDER BY 1"
    );
  }else{
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT DISTINCT substr(name, 6), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 5)=='repo:'"
       " ORDER BY 1"
    );
  }
  db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");
  db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFilename = db_column_text(&q, 0);
    if( file_access(zFilename, F_OK)
     || !file_is_canonical(zFilename)
     || (useCheckouts && file_isdir(zFilename)!=1)
    ){
      db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }else if( showFile ){
      fossil_print("%s: %s\n", useCheckouts ? "checkout" : "repository",
                   zFilename);
    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s%s",
                      zFossil, zCmd, zQFilename, blob_str(&extra));
    if( showLabel ){
      int len = (int)strlen(zFilename);
      int nStar = 80 - (len + 15);
      if( nStar<2 ) nStar = 1;
      fossil_print("%.13c %s %.*c\n", '*', zFilename, nStar, '*');
    }
    if( !quiet || dryRunFlag ){
      fossil_print("%s\n", zSyscmd);
      fflush(stdout);
    }
    rc = dryRunFlag ? 0 : fossil_system(zSyscmd);
    free(zSyscmd);
    free(zQFilename);
Changes to src/attach.c.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
**    tkt=TICKETUUID
**    page=WIKIPAGE
**
** List attachments.
** Either one of tkt= or page= are supplied or neither.  If neither
** are given, all attachments are listed.  If one is given, only
** attachments for the designated ticket or wiki page are shown.
** TICKETUUID must be complete 
*/
void attachlist_page(void){
  const char *zPage = P("page");
  const char *zTkt = P("tkt");
  Blob sql;
  Stmt q;








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
**    tkt=TICKETUUID
**    page=WIKIPAGE
**
** List attachments.
** Either one of tkt= or page= are supplied or neither.  If neither
** are given, all attachments are listed.  If one is given, only
** attachments for the designated ticket or wiki page are shown.
** TICKETUUID must be complete
*/
void attachlist_page(void){
  const char *zPage = P("page");
  const char *zTkt = P("tkt");
  Blob sql;
  Stmt q;

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  );
  if( zPage ){
    if( g.perm.RdWiki==0 ) login_needed();
    style_header("Attachments To %h", zPage);
    blob_appendf(&sql, " WHERE target=%Q", zPage);
  }else if( zTkt ){
    if( g.perm.RdTkt==0 ) login_needed();
    style_header("Attachments To Ticket %.10s", zTkt);
    blob_appendf(&sql, " WHERE target GLOB '%q*'", zTkt);
  }else{
    if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
    style_header("All Attachments");
  }
  blob_appendf(&sql, " ORDER BY mtime DESC");
  db_prepare(&q, "%s", blob_str(&sql));







|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  );
  if( zPage ){
    if( g.perm.RdWiki==0 ) login_needed();
    style_header("Attachments To %h", zPage);
    blob_appendf(&sql, " WHERE target=%Q", zPage);
  }else if( zTkt ){
    if( g.perm.RdTkt==0 ) login_needed();
    style_header("Attachments To Ticket %S", zTkt);
    blob_appendf(&sql, " WHERE target GLOB '%q*'", zTkt);
  }else{
    if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
    style_header("All Attachments");
  }
  blob_appendf(&sql, " ORDER BY mtime DESC");
  db_prepare(&q, "%s", blob_str(&sql));
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    const char *zUser = db_column_text(&q, 5);
    const char *zUuid = db_column_text(&q, 6);
    int attachid = db_column_int(&q, 7);
    const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
    int i;
    char *zUrlTail;
    for(i=0; zFilename[i]; i++){
      if( zFilename[i]=='/' && zFilename[i+1]!=0 ){ 
        zFilename = &zFilename[i+1];
        i = -1;
      }
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
    }else{







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    const char *zUser = db_column_text(&q, 5);
    const char *zUuid = db_column_text(&q, 6);
    int attachid = db_column_int(&q, 7);
    const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
    int i;
    char *zUrlTail;
    for(i=0; zFilename[i]; i++){
      if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
        zFilename = &zFilename[i+1];
        i = -1;
      }
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
    }else{
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    }
    zTarget = zPage;
    zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
                           g.zTop, zPage, zPage);
  }else{
    if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
    if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
      zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag" 
                        " WHERE tagname GLOB 'tkt-%q*'", zTkt);
      if( zTkt==0 ) fossil_redirect_home();
    }
    zTarget = zTkt;
    zTargetType = mprintf("Ticket <a href=\"%s/tktview/%s\">%S</a>",
                          g.zTop, zTkt, zTkt);
  }







|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    }
    zTarget = zPage;
    zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
                           g.zTop, zPage, zPage);
  }else{
    if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
    if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
      zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
                        " WHERE tagname GLOB 'tkt-%q*'", zTkt);
      if( zTkt==0 ) fossil_redirect_home();
    }
    zTarget = zTkt;
    zTargetType = mprintf("Ticket <a href=\"%s/tktview/%s\">%S</a>",
                          g.zTop, zTkt, zTkt);
  }
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    manifest_destroy(pManifest);
    blob_init(&content, aContent, szContent);
    if( pManifest ){
      blob_compress(&content, &content);
      addCompress = 1;
    }
    needModerator =
         (zTkt!=0 && g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1) ||
         (zPage!=0 && g.perm.ModWiki==0 && db_get_boolean("modreq-wiki",0)==1);
    rid = content_put_ex(&content, 0, 0, 0, needModerator);
    zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
    blob_zero(&manifest);
    for(i=n=0; zName[i]; i++){
      if( zName[i]=='/' || zName[i]=='\\' ) n = i;
    }
    zName += n;







|
|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    manifest_destroy(pManifest);
    blob_init(&content, aContent, szContent);
    if( pManifest ){
      blob_compress(&content, &content);
      addCompress = 1;
    }
    needModerator =
         (zTkt!=0 && ticket_need_moderation(0)) ||
         (zPage!=0 && wiki_need_moderation(0));
    rid = content_put_ex(&content, 0, 0, 0, needModerator);
    zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
    blob_zero(&manifest);
    for(i=n=0; zName[i]; i++){
      if( zName[i]=='/' || zName[i]=='\\' ) n = i;
    }
    zName += n;
363
364
365
366
367
368
369


370
371
372
373
374
375
376
  const char *zWikiName = 0;     /* Wiki page name when attached to Wiki */
  const char *zTktUuid = 0;      /* Ticket ID when attached to a ticket */
  int modPending;                /* True if awaiting moderation */
  const char *zModAction;        /* Moderation action or NULL */
  int isModerator;               /* TRUE if user is the moderator */
  const char *zMime;             /* MIME Type */
  Blob attach;                   /* Content of the attachment */



  login_check_credentials();
  if( !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
  rid = name_to_rid_www("name");
  if( rid==0 ){ fossil_redirect_home(); }
  zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
#if 0







>
>







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  const char *zWikiName = 0;     /* Wiki page name when attached to Wiki */
  const char *zTktUuid = 0;      /* Ticket ID when attached to a ticket */
  int modPending;                /* True if awaiting moderation */
  const char *zModAction;        /* Moderation action or NULL */
  int isModerator;               /* TRUE if user is the moderator */
  const char *zMime;             /* MIME Type */
  Blob attach;                   /* Content of the attachment */
  int fShowContent = 0;
  const char *zLn = P("ln");

  login_check_credentials();
  if( !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
  rid = name_to_rid_www("name");
  if( rid==0 ){ fossil_redirect_home(); }
  zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
#if 0
389
390
391
392
393
394
395


396
397
398
399
400
401
402
  pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
  if( pAttach==0 ) fossil_redirect_home();
  zTarget = pAttach->zAttachTarget;
  zSrc = pAttach->zAttachSrc;
  ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc);
  zName = pAttach->zAttachName;
  zDesc = pAttach->zComment;


  if( validate16(zTarget, strlen(zTarget))
   && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%s'", zTarget)
  ){
    zTktUuid = zTarget;
    if( !g.perm.RdTkt ){ login_needed(); return; }
    if( g.perm.WrTkt ){
      style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);







>
>







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
  if( pAttach==0 ) fossil_redirect_home();
  zTarget = pAttach->zAttachTarget;
  zSrc = pAttach->zAttachSrc;
  ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc);
  zName = pAttach->zAttachName;
  zDesc = pAttach->zComment;
  zMime = mimetype_from_name(zName);
  fShowContent = zMime ? strncmp(zMime,"text/", 5)==0 : 0;
  if( validate16(zTarget, strlen(zTarget))
   && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%s'", zTarget)
  ){
    zTktUuid = zTarget;
    if( !g.perm.RdTkt ){ login_needed(); return; }
    if( g.perm.WrTkt ){
      style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468





469
470
471
472
473
474
475
  ){
    form_begin(0, "%R/ainfo/%s", zUuid);
    @ <p>Confirm you want to delete the attachment shown below.
    @ <input type="submit" name="confirm" value="Confirm">
    @ </form>
  }

  isModerator = g.perm.Admin || 
                (zTktUuid && g.perm.ModTkt) ||
                (zWikiName && g.perm.ModWiki);
  if( isModerator && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      if( zTktUuid ){
        cgi_redirectf("%R/tktview/%s", zTktUuid);
      }else{
        cgi_redirectf("%R/wiki?name=%t", zWikiName);
      }
      return;
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Attachment Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);






  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){
    @ (%d(rid))







|


















>
>
>
>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  ){
    form_begin(0, "%R/ainfo/%s", zUuid);
    @ <p>Confirm you want to delete the attachment shown below.
    @ <input type="submit" name="confirm" value="Confirm">
    @ </form>
  }

  isModerator = g.perm.Admin ||
                (zTktUuid && g.perm.ModTkt) ||
                (zWikiName && g.perm.ModWiki);
  if( isModerator && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      if( zTktUuid ){
        cgi_redirectf("%R/tktview/%s", zTktUuid);
      }else{
        cgi_redirectf("%R/wiki?name=%t", zWikiName);
      }
      return;
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Attachment Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
  if(fShowContent){
    style_submenu_element("Line Numbers", "Line Numbers",
                          "%R/ainfo/%s%s",zUuid,
                          ((zLn&&*zLn) ? "" : "?ln=0"));
  }

  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){
    @ (%d(rid))
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
  hyperlink_to_user(pAttach->zUser, zDate, "</td></tr>");
  @ <tr><th>Artifact&nbsp;Attached:</th>
  @ <td>%z(href("%R/artifact/%s",zSrc))%s(zSrc)</a>
  if( g.perm.Setup ){
    @ (%d(ridSrc))
  }
  @ <tr><th>Filename:</th><td>%h(zName)</td></tr>
  zMime = mimetype_from_name(zName);
  if( g.perm.Setup ){
    @ <tr><th>MIME-Type:</th><td>%h(zMime)</td></tr>
  }
  @ <tr><th valign="top">Description:</th><td valign="top">%h(zDesc)</td></tr>
  @ </table>
  
  if( isModerator && modPending ){
    @ <div class="section">Moderation</div>
    @ <blockquote>
    form_begin(0, "%R/ainfo/%s", zUuid);
    @ <label><input type="radio" name="modaction" value="delete">
    @ Delete this change</label><br />
    @ <label><input type="radio" name="modaction" value="approve">
    @ Approve this change</label><br />
    @ <input type="submit" value="Submit">
    @ </form>
    @ </blockquote>
  }

  @ <div class="section">Content Appended</div>
  @ <blockquote>
  blob_zero(&attach);
  if( zMime==0 || strncmp(zMime,"text/", 5)==0 ){
    const char *z;
    const char *zLn = P("ln");
    content_get(ridSrc, &attach);
    blob_to_utf8_no_bom(&attach, 0);
    z = blob_str(&attach);
    if( zLn ){
      output_text_with_line_numbers(z, zLn);
    }else{
      @ <pre>







<





|
















|

<







501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
  hyperlink_to_user(pAttach->zUser, zDate, "</td></tr>");
  @ <tr><th>Artifact&nbsp;Attached:</th>
  @ <td>%z(href("%R/artifact/%s",zSrc))%s(zSrc)</a>
  if( g.perm.Setup ){
    @ (%d(ridSrc))
  }
  @ <tr><th>Filename:</th><td>%h(zName)</td></tr>

  if( g.perm.Setup ){
    @ <tr><th>MIME-Type:</th><td>%h(zMime)</td></tr>
  }
  @ <tr><th valign="top">Description:</th><td valign="top">%h(zDesc)</td></tr>
  @ </table>

  if( isModerator && modPending ){
    @ <div class="section">Moderation</div>
    @ <blockquote>
    form_begin(0, "%R/ainfo/%s", zUuid);
    @ <label><input type="radio" name="modaction" value="delete">
    @ Delete this change</label><br />
    @ <label><input type="radio" name="modaction" value="approve">
    @ Approve this change</label><br />
    @ <input type="submit" value="Submit">
    @ </form>
    @ </blockquote>
  }

  @ <div class="section">Content Appended</div>
  @ <blockquote>
  blob_zero(&attach);
  if( fShowContent ){
    const char *z;

    content_get(ridSrc, &attach);
    blob_to_utf8_no_bom(&attach, 0);
    z = blob_str(&attach);
    if( zLn ){
      output_text_with_line_numbers(z, zLn);
    }else{
      @ <pre>
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  int cnt = 0;
  Stmt q;
  db_prepare(&q,
     "SELECT datetime(mtime%s), filename, user,"
     "       (SELECT uuid FROM blob WHERE rid=attachid), src"
     "  FROM attachment"
     " WHERE isLatest AND src!='' AND target=%Q"
     " ORDER BY mtime DESC", 
     timeline_utc(), zTarget
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zDate = db_column_text(&q, 0);
    const char *zFile = db_column_text(&q, 1);
    const char *zUser = db_column_text(&q, 2);
    const char *zUuid = db_column_text(&q, 3);







|







562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  int cnt = 0;
  Stmt q;
  db_prepare(&q,
     "SELECT datetime(mtime%s), filename, user,"
     "       (SELECT uuid FROM blob WHERE rid=attachid), src"
     "  FROM attachment"
     " WHERE isLatest AND src!='' AND target=%Q"
     " ORDER BY mtime DESC",
     timeline_utc(), zTarget
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zDate = db_column_text(&q, 0);
    const char *zFile = db_column_text(&q, 1);
    const char *zUser = db_column_text(&q, 2);
    const char *zUuid = db_column_text(&q, 3);
580
581
582
583
584
585
586
587
588
    @ [%z(href("%R/ainfo/%s",zUuid))details</a>]
    @ </li>
  }
  if( cnt ){
    @ </ul>
  }
  db_finalize(&q);
  
}







|

587
588
589
590
591
592
593
594
595
    @ [%z(href("%R/ainfo/%s",zUuid))details</a>]
    @ </li>
  }
  if( cnt ){
    @ </ul>
  }
  db_finalize(&q);

}
Changes to src/bisect.c.
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  db_finalize(&q);
  db_prepare(&q,
    "SELECT bilog.seq, bilog.stat,"
    "       substr(blob.uuid,1,16), datetime(event.mtime)"
    "  FROM bilog, blob, event"
    " WHERE blob.rid=bilog.rid AND event.objid=bilog.rid"
    "   AND event.type='ci'"
    " ORDER BY %s",
    (sortByCkinTime ? "event.mtime DESC" : "bilog.rowid ASC")
  );
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("%3d %-7s %s %s\n",
        db_column_int(&q, 0),
        db_column_text(&q, 1),
        db_column_text(&q, 3),
        db_column_text(&q, 2));







|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  db_finalize(&q);
  db_prepare(&q,
    "SELECT bilog.seq, bilog.stat,"
    "       substr(blob.uuid,1,16), datetime(event.mtime)"
    "  FROM bilog, blob, event"
    " WHERE blob.rid=bilog.rid AND event.objid=bilog.rid"
    "   AND event.type='ci'"
    " ORDER BY %s bilog.rowid ASC",
    (sortByCkinTime ? "event.mtime DESC, " : "")
  );
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("%3d %-7s %s %s\n",
        db_column_int(&q, 0),
        db_column_text(&q, 1),
        db_column_text(&q, 3),
        db_column_text(&q, 2));
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    if( g.argc==3 ){
      unsigned int i;
      for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
        char *z = mprintf("bisect-%s", aBisectOption[i].zName);
        fossil_print("  %-15s  %-6s  ", aBisectOption[i].zName,
               db_lget(z, (char*)aBisectOption[i].zDefault));
        fossil_free(z);
        comment_print(aBisectOption[i].zDesc, 27, 79);
      }
    }else if( g.argc==4 || g.argc==5 ){
      unsigned int i;
      n = strlen(g.argv[3]);
      for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
        if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
          char *z = mprintf("bisect-%s", aBisectOption[i].zName);
          if( g.argc==5 ){
            db_lset(z, g.argv[4]);
          }
          fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
          fossil_free(z);
          break;







|





|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    if( g.argc==3 ){
      unsigned int i;
      for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
        char *z = mprintf("bisect-%s", aBisectOption[i].zName);
        fossil_print("  %-15s  %-6s  ", aBisectOption[i].zName,
               db_lget(z, (char*)aBisectOption[i].zDefault));
        fossil_free(z);
        comment_print(aBisectOption[i].zDesc, 0, 27, -1, g.comFmtFlags);
      }
    }else if( g.argc==4 || g.argc==5 ){
      unsigned int i;
      n = strlen(g.argv[3]);
      for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
        if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
          char *z = mprintf("bisect-%s", aBisectOption[i].zName);
          if( g.argc==5 ){
            db_lset(z, g.argv[4]);
          }
          fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
          fossil_free(z);
          break;
Changes to src/blob.c.
15
16
17
18
19
20
21




22

23
24
25
26
27
28
29
**
*******************************************************************************
**
** A Blob is a variable-length containers for arbitrary string
** or binary data.
*/
#include "config.h"




#include <zlib.h>

#include "blob.h"

#if INTERFACE
/*
** A Blob can hold a string or a binary object of arbitrary size.  The
** size changes as necessary.
*/







>
>
>
>
|
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
**
*******************************************************************************
**
** A Blob is a variable-length containers for arbitrary string
** or binary data.
*/
#include "config.h"
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif
#include "blob.h"

#if INTERFACE
/*
** A Blob can hold a string or a binary object of arbitrary size.  The
** size changes as necessary.
*/
1002
1003
1004
1005
1006
1007
1008























































1009
1010
1011
1012
1013
1014
1015
  for(i=j=0; z[i]; i++){
    if( z[i]!='\r' ) z[j++] = z[i];
    else if( z[i+1]!='\n' ) z[j++] = '\n';
  }
  z[j] = 0;
  p->nUsed = j;
}
























































/*
** Shell-escape the given string.  Append the result to a blob.
*/
void shell_escape(Blob *pBlob, const char *zIn){
  int n = blob_size(pBlob);
  int k = strlen(zIn);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
  for(i=j=0; z[i]; i++){
    if( z[i]!='\r' ) z[j++] = z[i];
    else if( z[i+1]!='\n' ) z[j++] = '\n';
  }
  z[j] = 0;
  p->nUsed = j;
}

/*
** Convert blob from cp1252 to UTF-8. As cp1252 is a superset
** of iso8859-1, this is useful on UNIX as well.
**
** This table contains the character translations for 0x80..0xA0.
*/

static const unsigned short cp1252[32] = {
  0x20ac,   0x81, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
  0x02C6, 0x2030, 0x0160, 0x2039, 0x0152,   0x8D, 0x017D,   0x8F,
    0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
   0x2DC, 0x2122, 0x0161, 0x203A, 0x0153,   0x9D, 0x017E, 0x0178
};

void blob_cp1252_to_utf8(Blob *p){
  unsigned char *z = (unsigned char *)p->aData;
  int j   = p->nUsed;
  int i, n;
  for(i=n=0; i<j; i++){
    if( z[i]>=0x80 ){
      if( (z[i]<0xa0) && (cp1252[z[i]&0x1f]>=0x800) ){
        n++;
      }
      n++;
    }
  }
  j += n;
  if( j>=p->nAlloc ){
    blob_resize(p, j);
    z = (unsigned char *)p->aData;
  }
  p->nUsed = j;
  z[j] = 0;
  while( j>i ){
    if( z[--i]>=0x80 ){
      if( z[i]<0xa0 ){
        unsigned short sym = cp1252[z[i]&0x1f];
        if( sym>=0x800 ){
          z[--j] = 0x80 | (sym&0x3f);
          z[--j] = 0x80 | ((sym>>6)&0x3f);
          z[--j] = 0xe0 | (sym>>12);
        }else{
          z[--j] = 0x80 | (sym&0x3f);
          z[--j] = 0xc0 | (sym>>6);
        }
      }else{
        z[--j] = 0x80 | (z[i]&0x3f);
        z[--j] = 0xC0 | (z[i]>>6);
      }
    }else{
      z[--j] = z[i];
    }
  }
}

/*
** Shell-escape the given string.  Append the result to a blob.
*/
void shell_escape(Blob *pBlob, const char *zIn){
  int n = blob_size(pBlob);
  int k = strlen(zIn);
Changes to src/branch.c.
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  }


  /* Commit */
  db_end_transaction(0);

  /* Do an autosync push, if requested */
  if( !isPrivate ) autosync(SYNC_PUSH);
}

/*
** Prepare a query that will list branches.
**
** If (which<0) then the query pulls only closed branches. If
** (which>0) then the query pulls all (closed and opened)







|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  }


  /* Commit */
  db_end_transaction(0);

  /* Do an autosync push, if requested */
  if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1));
}

/*
** Prepare a query that will list branches.
**
** If (which<0) then the query pulls only closed branches. If
** (which>0) then the query pulls all (closed and opened)
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
** Options:
**    -R|--repository FILE       Run commands on repository FILE
*/
void branch_cmd(void){
  int n;
  const char *zCmd = "list";
  db_find_and_open_repository(0, 0);
  if( g.argc<2 ){
    usage("new|list|ls ...");
  }
  if( g.argc>=3 ) zCmd = g.argv[2];
  n = strlen(zCmd);
  if( strncmp(zCmd,"new",n)==0 ){
    branch_new();
  }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
    Stmt q;
    int vid;







<
<
<







250
251
252
253
254
255
256



257
258
259
260
261
262
263
** Options:
**    -R|--repository FILE       Run commands on repository FILE
*/
void branch_cmd(void){
  int n;
  const char *zCmd = "list";
  db_find_and_open_repository(0, 0);



  if( g.argc>=3 ) zCmd = g.argv[2];
  n = strlen(zCmd);
  if( strncmp(zCmd,"new",n)==0 ){
    branch_new();
  }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
    Stmt q;
    int vid;
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  @ The presence of open leaves presumably means
  @ that the branch is still being extended with new check-ins.</li>
  @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
  @ closed branch</a></div> is a branch with only
  @ <div class="sideboxDescribed">%z(href("leaves?closed"))
  @ closed leaves</a></div>.
  @ Closed branches are fixed and do not change (unless they are first
  @ reopened)</li>
  @ </ol>
  style_sidebox_end();

  branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
  cnt = 0;
  while( db_step(&q)==SQLITE_ROW ){
    const char *zBr = db_column_text(&q, 0);







|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  @ The presence of open leaves presumably means
  @ that the branch is still being extended with new check-ins.</li>
  @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
  @ closed branch</a></div> is a branch with only
  @ <div class="sideboxDescribed">%z(href("leaves?closed"))
  @ closed leaves</a></div>.
  @ Closed branches are fixed and do not change (unless they are first
  @ reopened).</li>
  @ </ol>
  style_sidebox_end();

  branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
  cnt = 0;
  while( db_step(&q)==SQLITE_ROW ){
    const char *zBr = db_column_text(&q, 0);
Changes to src/browse.c.
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( zCI ){
    @ <h2>Files of check-in [%z(href("vinfo?name=%s",zUuid))%.10s(zUuid)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix);
    if( nD==0 ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
                            zUuid);
    }
  }else{







|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( zCI ){
    @ <h2>Files of check-in [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix);
    if( nD==0 ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
                            zUuid);
    }
  }else{
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
                            zUuid);
    }
  }
  if( linkTrunk ){
    style_submenu_element("Trunk", "Trunk", "%s",
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if ( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( !showDirOnly ){
    style_submenu_element("Flat-View", "Flat-View", "%s",
                          url_render(&sURI, "type", "flat", 0, 0));
  }







|







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
                            zUuid);
    }
  }
  if( linkTrunk ){
    style_submenu_element("Trunk", "Trunk", "%s",
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( !showDirOnly ){
    style_submenu_element("Flat-View", "Flat-View", "%s",
                          url_render(&sURI, "type", "flat", 0, 0));
  }
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  char *zClass;
  const char *zExt = strrchr(zFilename, '.');
  int isExt = zExt && zExt!=zFilename && zExt[1];
  int i;
  for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
  if( isExt ){
    zClass = mprintf("file file-%s", zExt+1);
    for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
  }else{
    zClass = mprintf("file");
  }
  return zClass;
}

/*
** Look at all file containing in the version "vid".  Construct a
** temporary table named "fileage" that contains the file-id for each
** files, the pathname, the check-in where the file was added, and the
** mtime on that checkin. If zGlob and *zGlob then only files matching
** the given glob are computed.
*/
int compute_fileage(int vid, char const * zGlob){
  Manifest *pManifest;
  ManifestFile *pFile;
  int nFile = 0;
  double vmtime;
  Stmt ins;
  Stmt q1, q2, q3;
  Stmt upd;







|













|







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  char *zClass;
  const char *zExt = strrchr(zFilename, '.');
  int isExt = zExt && zExt!=zFilename && zExt[1];
  int i;
  for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
  if( isExt ){
    zClass = mprintf("file file-%s", zExt+1);
    for( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
  }else{
    zClass = mprintf("file");
  }
  return zClass;
}

/*
** Look at all file containing in the version "vid".  Construct a
** temporary table named "fileage" that contains the file-id for each
** files, the pathname, the check-in where the file was added, and the
** mtime on that checkin. If zGlob and *zGlob then only files matching
** the given glob are computed.
*/
int compute_fileage(int vid, const char* zGlob){
  Manifest *pManifest;
  ManifestFile *pFile;
  int nFile = 0;
  double vmtime;
  Stmt ins;
  Stmt q1, q2, q3;
  Stmt upd;
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
**   glob=STRING    Only shows files matching this glob pattern
**                  (e.g. *.c or *.txt).
*/
void fileage_page(void){
  int rid;
  const char *zName;
  char *zBaseTime;
  char const * zGlob;
  Stmt q;
  double baseTime;
  int lastMid = -1;
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = P("name");
  if( zName==0 ) zName = "tip";







|







815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
**   glob=STRING    Only shows files matching this glob pattern
**                  (e.g. *.c or *.txt).
*/
void fileage_page(void){
  int rid;
  const char *zName;
  char *zBaseTime;
  const char *zGlob;
  Stmt q;
  double baseTime;
  int lastMid = -1;
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = P("name");
  if( zName==0 ) zName = "tip";
Changes to src/cache.c.
60
61
62
63
64
65
66

67
68
69
70
71
72
73
  rc = sqlite3_open(zDbName, &db);
  fossil_free(zDbName);
  if( rc ){
    sqlite3_close(db);
    return 0;
  }
  rc = sqlite3_exec(db, 

     "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
     "CREATE TABLE IF NOT EXISTS cache("
       "key TEXT PRIMARY KEY,"     /* Key used to access the cache */
       "id INT REFERENCES blob,"   /* The cache content */
       "sz INT,"                   /* Size of content in bytes */
       "tm INT,"                   /* Last access time (unix timestampe) */
       "nref INT"                  /* Number of uses */







>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  rc = sqlite3_open(zDbName, &db);
  fossil_free(zDbName);
  if( rc ){
    sqlite3_close(db);
    return 0;
  }
  rc = sqlite3_exec(db, 
     "PRAGMA page_size=8192;"
     "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
     "CREATE TABLE IF NOT EXISTS cache("
       "key TEXT PRIMARY KEY,"     /* Key used to access the cache */
       "id INT REFERENCES blob,"   /* The cache content */
       "sz INT,"                   /* Size of content in bytes */
       "tm INT,"                   /* Last access time (unix timestampe) */
       "nref INT"                  /* Number of uses */
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
** Usage: %fossil cache SUBCOMMAND
**
** Manage the cache used for potentially expensive web pages such as
** /zip and /tarball.   SUBCOMMAND an be:
**
**    clear        Remove all entries from the cache.
**
**    init         Create the cache file it it does not already exists.
**
**    list         List the keys and content sizes and other stats for
**                 all entries currently in the cache
**
**    status       Show a summary of cache status.
**
** The cache is stored in a file that is distinct from the repository
** but that is held in the same directory as the repository.  To cache
** file can be deleted in order to completely disable the cache.







|

|







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
** Usage: %fossil cache SUBCOMMAND
**
** Manage the cache used for potentially expensive web pages such as
** /zip and /tarball.   SUBCOMMAND an be:
**
**    clear        Remove all entries from the cache.
**
**    init         Create the cache file if it does not already exists.
**
**    list|ls      List the keys and content sizes and other stats for
**                 all entries currently in the cache
**
**    status       Show a summary of cache status.
**
** The cache is stored in a file that is distinct from the repository
** but that is held in the same directory as the repository.  To cache
** file can be deleted in order to completely disable the cache.
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    if( db ){
      sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0);
      sqlite3_close(db);
      fossil_print("cache cleared\n");
    }else{
      fossil_print("nothing to clear; cache does not exist\n");
    }
  }else if( strncmp(zCmd, "list", nCmd)==0 ){
    db = cacheOpen(0);
    if( db==0 ){
      fossil_print("cache does not exist\n");
    }else{
      int nEntry = 0;
      char *zDbName = cacheName();
      cache_register_sizename(db);







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    if( db ){
      sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0);
      sqlite3_close(db);
      fossil_print("cache cleared\n");
    }else{
      fossil_print("nothing to clear; cache does not exist\n");
    }
  }else if(( strncmp(zCmd, "list", nCmd)==0 ) || ( strncmp(zCmd, "ls", nCmd)==0 )){
    db = cacheOpen(0);
    if( db==0 ){
      fossil_print("cache does not exist\n");
    }else{
      int nEntry = 0;
      char *zDbName = cacheName();
      cache_register_sizename(db);
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366


























         "SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
         "  FROM cache"
         " ORDER BY tm DESC"
    );
    if( pStmt ){
      @ <ol>
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        @ <li><p>%h(sqlite3_column_text(pStmt,0))<br>

        @ size: %s(sqlite3_column_text(pStmt,1))
        @ hit-count: %d(sqlite3_column_int(pStmt,2))
        @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
      }
      sqlite3_finalize(pStmt);
      @ </ol>
    }
    zDbName = cacheName();
    bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName));
    @ <p>cache-file name: %h(zDbName)</p>
    @ <p>cache-file size: %s(zBuf)</p>
    fossil_free(zDbName);
    sqlite3_close(db);
  }
  style_footer();
}

































|
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
         "SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
         "  FROM cache"
         " ORDER BY tm DESC"
    );
    if( pStmt ){
      @ <ol>
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        const unsigned char *zName = sqlite3_column_text(pStmt,0);
        @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
        @ size: %s(sqlite3_column_text(pStmt,1))
        @ hit-count: %d(sqlite3_column_int(pStmt,2))
        @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
      }
      sqlite3_finalize(pStmt);
      @ </ol>
    }
    zDbName = cacheName();
    bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName));
    @ <p>cache-file name: %h(zDbName)</p>
    @ <p>cache-file size: %s(zBuf)</p>
    fossil_free(zDbName);
    sqlite3_close(db);
  }
  style_footer();
}

/*
** WEBPAGE: cacheget
**
** Usage:  /cacheget?key=KEY
**
** Download a single entry for the cache, identified by KEY.
** This page is normally a hyperlink from the /cachestat page.
*/
void cache_getpage(void){
  const char *zKey;
  Blob content;

  login_check_credentials();
  if( !g.perm.Setup ){ login_needed(); return; }
  zKey = PD("key","");
  blob_zero(&content);
  if( cache_read(&content, zKey)==0 ){
    style_header("Cache Download Error");
    @ The cache does not contain any entry with this key: "%h(zKey)"
    style_footer();
    return;
  }
  cgi_set_content(&content);
  cgi_set_content_type("application/x-compressed");
}
Changes to src/captcha.c.
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
}

/*
** Translate a captcha seed value into the captcha password string.
** The returned string is static and overwritten on each call to
** this function.
*/
char const *captcha_decode(unsigned int seed){
  const char *zSecret;
  const char *z;
  Blob b;
  static char zRes[20];

  zSecret = db_get("captcha-secret", 0);
  if( zSecret==0 ){







|







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
}

/*
** Translate a captcha seed value into the captcha password string.
** The returned string is static and overwritten on each call to
** this function.
*/
const char *captcha_decode(unsigned int seed){
  const char *zSecret;
  const char *z;
  Blob b;
  static char zRes[20];

  zSecret = db_get("captcha-secret", 0);
  if( zSecret==0 ){
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  if( strlen(zEntered)!=8 ) return 0;
  for(i=0; i<8; i++){
    char c = zEntered[i];
    if( c>='A' && c<='F' ) c += 'a' - 'A';
    if( c=='O' ) c = '0';
    z[i] = c;
  }
  if( memcmp(zDecode,z,8)!=0 ) return 0;
  return 1;
}

/*
** Generate a captcha display together with the necessary hidden parameter
** for the seed and the entry box into which the user will type the text of
** the captcha.  This is typically done at the very bottom of a form.







|







515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  if( strlen(zEntered)!=8 ) return 0;
  for(i=0; i<8; i++){
    char c = zEntered[i];
    if( c>='A' && c<='F' ) c += 'a' - 'A';
    if( c=='O' ) c = '0';
    z[i] = c;
  }
  if( strncmp(zDecode,z,8)!=0 ) return 0;
  return 1;
}

/*
** Generate a captcha display together with the necessary hidden parameter
** for the seed and the entry box into which the user will type the text of
** the captcha.  This is typically done at the very bottom of a form.
Changes to src/cgi.c.
304
305
306
307
308
309
310

311
312
313
314
315
316
317
  }
#endif

  if( g.fullHttpReply ){
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
    fprintf(g.httpOut, "Connection: close\r\n");

  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
  }







>







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  }
#endif

  if( g.fullHttpReply ){
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
    fprintf(g.httpOut, "Connection: close\r\n");
    fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
  }
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
                                    unsigned int * n ){
    if( ! state || !dest || !n ) return cson_rc.ArgError;
    else {
      CgiPostReadState * st = (CgiPostReadState *)state;
      if( st->pos >= st->len ){
        *n = 0;
        return 0;
      } else if( !*n || ((st->pos + *n) > st->len) ){
        return cson_rc.RangeError;
      }else{
        unsigned int rsz = (unsigned int)fread( dest, 1, *n, st->fh );
        if( ! rsz ){
          *n = rsz;
          return feof(st->fh) ? 0 : cson_rc.IOError;
        }else{







|







749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
                                    unsigned int * n ){
    if( ! state || !dest || !n ) return cson_rc.ArgError;
    else {
      CgiPostReadState * st = (CgiPostReadState *)state;
      if( st->pos >= st->len ){
        *n = 0;
        return 0;
      }else if( !*n || ((st->pos + *n) > st->len) ){
        return cson_rc.RangeError;
      }else{
        unsigned int rsz = (unsigned int)fread( dest, 1, *n, st->fh );
        if( ! rsz ){
          *n = rsz;
          return feof(st->fh) ? 0 : cson_rc.IOError;
        }else{
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
    malformed_request("incorrect transport_flip");
  }
  cgi_trace(zLine);
  zToken = extract_token(zLine, &z);
  if( zToken && strlen(zToken)==0 ){
    /* look for path to fossil */
    if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
      if ( zCmd==0 ){
        malformed_request("missing fossil command");
      }else{
        /* no new command so exit */
        fossil_exit(0);
      }
    }
    cgi_trace(zLine);







|







1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
    malformed_request("incorrect transport_flip");
  }
  cgi_trace(zLine);
  zToken = extract_token(zLine, &z);
  if( zToken && strlen(zToken)==0 ){
    /* look for path to fossil */
    if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
      if( zCmd==0 ){
        malformed_request("missing fossil command");
      }else{
        /* no new command so exit */
        fossil_exit(0);
      }
    }
    cgi_trace(zLine);
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
** and subsequent code handles the actual generation of the webpage.
*/
void cgi_handle_scgi_request(void){
  char *zHdr;
  char *zToFree;
  int nHdr = 0;
  int nRead;
  int n, m;
  char c;

  while( (c = fgetc(g.httpIn))!=EOF && fossil_isdigit(c) ){
    nHdr = nHdr*10 + c - '0';
  }
  if( nHdr<16 ) malformed_request("SCGI header too short");
  zToFree = zHdr = fossil_malloc(nHdr);
  nRead = (int)fread(zHdr, 1, nHdr, g.httpIn);
  if( nRead<nHdr ) malformed_request("cannot read entire SCGI header");
  nHdr = nRead;
  while( nHdr ){







|
<

|
|







1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
** and subsequent code handles the actual generation of the webpage.
*/
void cgi_handle_scgi_request(void){
  char *zHdr;
  char *zToFree;
  int nHdr = 0;
  int nRead;
  int c, n, m;


  while( (c = fgetc(g.httpIn))!=EOF && fossil_isdigit((char)c) ){
    nHdr = nHdr*10 + (char)c - '0';
  }
  if( nHdr<16 ) malformed_request("SCGI header too short");
  zToFree = zHdr = fossil_malloc(nHdr);
  nRead = (int)fread(zHdr, 1, nHdr, g.httpIn);
  if( nRead<nHdr ) malformed_request("cannot read entire SCGI header");
  nHdr = nRead;
  while( nHdr ){
1624
1625
1626
1627
1628
1629
1630


1631
1632
1633
1634
1635
1636
1637

#if INTERFACE
/*
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST      0x0001     /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_SCGI           0x0002     /* SCGI instead of HTTP */



#endif /* INTERFACE */

/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/







>
>







1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639

#if INTERFACE
/*
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST      0x0001     /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_SCGI           0x0002     /* SCGI instead of HTTP */
#define HTTP_SERVER_HAD_REPOSITORY 0x0004     /* Was the repository open? */
#define HTTP_SERVER_HAD_CHECKOUT   0x0008     /* Was a checkout open? */

#endif /* INTERFACE */

/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
  fossil_print("Listening for %s requests on TCP port %d\n",
     (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP",  iPort);
  fflush(stdout);
  if( zBrowser ){
    zBrowser = mprintf(zBrowser, iPort);
#if defined(__CYGWIN__)
    /* On Cygwin, we can do better than "echo" */
    if( memcmp(zBrowser, "echo ", 5)==0 ){
      wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
      wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
      if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
        fossil_warning("cannot start browser\n");
      }
    }else
#endif







|







1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
  fossil_print("Listening for %s requests on TCP port %d\n",
     (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP",  iPort);
  fflush(stdout);
  if( zBrowser ){
    zBrowser = mprintf(zBrowser, iPort);
#if defined(__CYGWIN__)
    /* On Cygwin, we can do better than "echo" */
    if( strncmp(zBrowser, "echo ", 5)==0 ){
      wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
      wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
      if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
        fossil_warning("cannot start browser\n");
      }
    }else
#endif
Changes to src/checkin.c.
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
        if( missingIsFatal ){
          fossil_warning("missing file: %s", zDisplayName);
          nErr++;
        }
      }
    }else if( isNew ){
      blob_appendf(report, "ADDED      %s\n", zDisplayName);
    }else if( isDeleted ){
      blob_appendf(report, "DELETED    %s\n", zDisplayName);
    }else if( isChnged ){
      if( isChnged==2 ){
        blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
      }else if( isChnged==3 ){
        blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
      }else if( isChnged==4 ){
        blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName);







<
<







99
100
101
102
103
104
105


106
107
108
109
110
111
112
        if( missingIsFatal ){
          fossil_warning("missing file: %s", zDisplayName);
          nErr++;
        }
      }
    }else if( isNew ){
      blob_appendf(report, "ADDED      %s\n", zDisplayName);


    }else if( isChnged ){
      if( isChnged==2 ){
        blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
      }else if( isChnged==3 ){
        blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
      }else if( isChnged==4 ){
        blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName);
157
158
159
160
161
162
163

























164
165
166
167
168
169
170
  int relativePaths = db_get_boolean("relative-paths", 1);
  int absPathOption = find_option("abs-paths", 0, 0)!=0;
  int relPathOption = find_option("rel-paths", 0, 0)!=0;
  if( absPathOption ){ relativePaths = 0; }
  if( relPathOption ){ relativePaths = 1; }
  return relativePaths;
}


























/*
** COMMAND: changes
**
** Usage: %fossil changes ?OPTIONS?
**
** Report on the edit status of all files in the current checkout.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  int relativePaths = db_get_boolean("relative-paths", 1);
  int absPathOption = find_option("abs-paths", 0, 0)!=0;
  int relPathOption = find_option("rel-paths", 0, 0)!=0;
  if( absPathOption ){ relativePaths = 0; }
  if( relPathOption ){ relativePaths = 1; }
  return relativePaths;
}

void print_changes(
  int useSha1sum,     /* Verify file status using SHA1 hashing rather
                         than relying on file mtimes. */
  int showHdr,        /* Identify the repository if there are changes */
  int verboseFlag,    /* Say "(none)" if there are no changes */
  int cwdRelative     /* Report relative to the current working dir */
){
  Blob report;
  int vid;
  blob_zero(&report);

  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
  status_report(&report, "", 0, cwdRelative);
  if( verboseFlag && blob_size(&report)==0 ){
    blob_append(&report, "  (none)\n", -1);
  }
  if( showHdr && blob_size(&report)>0 ){
    fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
                 g.zLocalRoot);
  }
  blob_write_to_file(&report, "-");
  blob_reset(&report);
}

/*
** COMMAND: changes
**
** Usage: %fossil changes ?OPTIONS?
**
** Report on the edit status of all files in the current checkout.
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
**                      than relying on file mtimes.
**    --header          Identify the repository if there are changes
**    -v|--verbose      Say "(none)" if there are no changes
**
** See also: extras, ls, status
*/
void changes_cmd(void){
  Blob report;
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verboseFlag = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  blob_zero(&report);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
  status_report(&report, "", 0, cwdRelative);
  if( verboseFlag && blob_size(&report)==0 ){
    blob_append(&report, "  (none)\n", -1);
  }
  if( showHdr && blob_size(&report)>0 ){
    fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
                 g.zLocalRoot);
  }
  blob_write_to_file(&report, "-");
  blob_reset(&report);

}

/*
** COMMAND: status
**
** Usage: %fossil status ?OPTIONS?
**







<
<






<
<
<
<
<
<
|
|
<
|
|
<
<
>







203
204
205
206
207
208
209


210
211
212
213
214
215






216
217

218
219


220
221
222
223
224
225
226
227
**                      than relying on file mtimes.
**    --header          Identify the repository if there are changes
**    -v|--verbose      Say "(none)" if there are no changes
**
** See also: extras, ls, status
*/
void changes_cmd(void){


  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verboseFlag = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();






  
  /* We should be done with options.. */

  verify_all_options();



  print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
}

/*
** COMMAND: status
**
** Usage: %fossil status ?OPTIONS?
**
225
226
227
228
229
230
231




232
233





234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**
** See also: changes, extras, ls
*/
void status_cmd(void){
  int vid;




  db_must_be_within_tree();
       /* 012345678901234 */





  fossil_print("repository:   %s\n", db_repository_filename());
  fossil_print("local-root:   %s\n", g.zLocalRoot);
  if( g.zConfigDbName ){
    fossil_print("config-db:    %s\n", g.zConfigDbName);
  }
  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }
  db_record_repository_filename(0);
  changes_cmd();
}

/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS? ?VERSION? ?FILENAMES?
**







>
>
>
>


>
>
>
>
>









|
|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**
** See also: changes, extras, ls
*/
void status_cmd(void){
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verboseFlag = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
       /* 012345678901234 */
  cwdRelative = determine_cwd_relative_option();
  
  /* We should be done with options.. */
  verify_all_options();

  fossil_print("repository:   %s\n", db_repository_filename());
  fossil_print("local-root:   %s\n", g.zLocalRoot);
  if( g.zConfigDbName ){
    fossil_print("config-db:    %s\n", g.zConfigDbName);
  }
  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }
  db_record_repository_filename(0); 
  print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
}

/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS? ?VERSION? ?FILENAMES?
**
449
450
451
452
453
454
455
456
457
458




459
460
461
462
463
464
465
  int showHdr = find_option("header",0,0)!=0;
  int cwdRelative = 0;
  Glob *pIgnore;
  Blob rewrittenPathname;
  const char *zPathname, *zDisplayName;

  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
  capture_case_sensitive_option();
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();




  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  pIgnore = glob_create(zIgnoreFlag);
  locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
  glob_free(pIgnore);
  db_prepare(&q,







<


>
>
>
>







471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
  int showHdr = find_option("header",0,0)!=0;
  int cwdRelative = 0;
  Glob *pIgnore;
  Blob rewrittenPathname;
  const char *zPathname, *zDisplayName;

  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;

  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  
  /* We should be done with options.. */
  verify_all_options();

  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  pIgnore = glob_create(zIgnoreFlag);
  locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
  glob_free(pIgnore);
  db_prepare(&q,
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
  if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED;
  zIgnoreFlag = find_option("ignore",0,1);
  verboseFlag = find_option("verbose","v",0)!=0;
  zKeepFlag = find_option("keep",0,1);
  zCleanFlag = find_option("clean",0,1);
  capture_case_sensitive_option();
  db_must_be_within_tree();
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  if( zKeepFlag==0 ){
    zKeepFlag = db_get("keep-glob", 0);
  }







<







593
594
595
596
597
598
599

600
601
602
603
604
605
606
  if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
  if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED;
  zIgnoreFlag = find_option("ignore",0,1);
  verboseFlag = find_option("verbose","v",0)!=0;
  zKeepFlag = find_option("keep",0,1);
  zCleanFlag = find_option("clean",0,1);

  db_must_be_within_tree();
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  if( zKeepFlag==0 ){
    zKeepFlag = db_get("keep-glob", 0);
  }
825
826
827
828
829
830
831












832

833
834
835
836
837
838
839
    "#\n", -1
  );
  blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : login_name());
  if( p->zBranch && p->zBranch[0] ){
    blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
  }else{
    char *zTags = info_tags_of_checkin(parent_rid, 1);












    if( zTags )  blob_appendf(&prompt, "# tags: %z\n#\n", zTags);

  }
  status_report(&prompt, "# ", 1, 0);
  if( g.markPrivate ){
    blob_append(&prompt,
      "# PRIVATE BRANCH: This check-in will be private and will not sync to\n"
      "# repositories.\n"
      "#\n", -1







>
>
>
>
>
>
>
>
>
>
>
>
|
>







849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
    "#\n", -1
  );
  blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : login_name());
  if( p->zBranch && p->zBranch[0] ){
    blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
  }else{
    char *zTags = info_tags_of_checkin(parent_rid, 1);
    if( zTags || p->azTag ){
      blob_append(&prompt, "# tags: ", 8);
      if(zTags){
        blob_appendf(&prompt, "%z%s", zTags, p->azTag ? ", " : "");
      }
      if(p->azTag){
        int i = 0;
        for( ; p->azTag[i]; ++i ){
          blob_appendf(&prompt, "%s%s", p->azTag[i],
                       p->azTag[i+1] ? ", " : "");
        }
      }
      blob_appendf(&prompt, "\n#\n");
    }
  }
  status_report(&prompt, "# ", 1, 0);
  if( g.markPrivate ){
    blob_append(&prompt,
      "# PRIVATE BRANCH: This check-in will be private and will not sync to\n"
      "# repositories.\n"
      "#\n", -1
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  b = db_exists(
    "SELECT 1 FROM event"
    " WHERE datetime(mtime)>=%Q"
    "   AND type='ci' AND objid=%d",
    zDate, rid
  );
  if( b ){
    fossil_fatal("ancestor check-in [%.10s] (%s) is not older (clock skew?)"
                 " Use --allow-older to override.", zUuid, zDate);
  }
#endif
}

/*
** zDate should be a valid date string.  Convert this string into the







|







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  b = db_exists(
    "SELECT 1 FROM event"
    " WHERE datetime(mtime)>=%Q"
    "   AND type='ci' AND objid=%d",
    zDate, rid
  );
  if( b ){
    fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
                 " Use --allow-older to override.", zUuid, zDate);
  }
#endif
}

/*
** zDate should be a valid date string.  Convert this string into the
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
      }
      zDisable = "\"crnl-glob\" and \"encoding-glob\" settings";
    }else if( fHasInvalidUtf8 ){
      if( encodingOk ){
        return 0; /* We don't want encoding warnings for this file. */
      }
      zWarning = "invalid UTF-8";
      zConvert = ""; /* Possible conversion to UTF-8 not yet implemented. */
      zDisable = "\"encoding-glob\" setting";
    }else if( fHasAnyCr ){
      if( crnlOk ){
        return 0; /* We don't want CR/NL warnings for this file. */
      }
      if( fHasLoneCrOnly ){
        zWarning = "CR line endings";







<







1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
      }
      zDisable = "\"crnl-glob\" and \"encoding-glob\" settings";
    }else if( fHasInvalidUtf8 ){
      if( encodingOk ){
        return 0; /* We don't want encoding warnings for this file. */
      }
      zWarning = "invalid UTF-8";

      zDisable = "\"encoding-glob\" setting";
    }else if( fHasAnyCr ){
      if( crnlOk ){
        return 0; /* We don't want CR/NL warnings for this file. */
      }
      if( fHasLoneCrOnly ){
        zWarning = "CR line endings";
1339
1340
1341
1342
1343
1344
1345


1346
1347
1348
1349
1350
1351
1352
        fossil_warning("cannot open %s for writing", zFilename);
      }else{
        if( fUnicode ) {
          int bomSize;
          const unsigned char *bom = get_utf8_bom(&bomSize);
          fwrite(bom, 1, bomSize, f);
          blob_to_utf8_no_bom(p, 0);


        }
        if( fHasAnyCr ){
          blob_to_lf_only(p);
        }
        fwrite(blob_buffer(p), 1, blob_size(p), f);
        fclose(f);
      }







>
>







1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
        fossil_warning("cannot open %s for writing", zFilename);
      }else{
        if( fUnicode ) {
          int bomSize;
          const unsigned char *bom = get_utf8_bom(&bomSize);
          fwrite(bom, 1, bomSize, f);
          blob_to_utf8_no_bom(p, 0);
        }else if( fHasInvalidUtf8 ){
          blob_cp1252_to_utf8(p);
        }
        if( fHasAnyCr ){
          blob_to_lf_only(p);
        }
        fwrite(blob_buffer(p), 1, blob_size(p), f);
        fclose(f);
      }
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
** The --branch option followed by a branch name causes the new
** check-in to be placed in a newly-created branch with the name
** passed to the --branch option.
**
** Use the --branchcolor option followed by a color name (ex:
** '#ffc0c0') to specify the background color of entries in the new
** branch when shown in the web timeline interface.  The use of
** the --branchcolor option is not recommend.  Instead, let Fossil
** choose the branch color automatically.
**
** The --bgcolor option works like --branchcolor but only sets the
** background color for a single check-in.  Subsequent check-ins revert
** to the default color.
**
** A check-in is not permitted to fork unless the --allow-fork option







|







1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
** The --branch option followed by a branch name causes the new
** check-in to be placed in a newly-created branch with the name
** passed to the --branch option.
**
** Use the --branchcolor option followed by a color name (ex:
** '#ffc0c0') to specify the background color of entries in the new
** branch when shown in the web timeline interface.  The use of
** the --branchcolor option is not recommended.  Instead, let Fossil
** choose the branch color automatically.
**
** The --bgcolor option works like --branchcolor but only sets the
** background color for a single check-in.  Subsequent check-ins revert
** to the default color.
**
** A check-in is not permitted to fork unless the --allow-fork option
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
    g.markPrivate = 1;
  }

  /*
  ** Autosync if autosync is enabled and this is not a private check-in.
  */
  if( !g.markPrivate ){
    if( autosync(SYNC_PULL) ){
      prompt_user("continue in spite of sync failure (y/N)? ", &ans);
      cReply = blob_str(&ans)[0];
      if( cReply!='y' && cReply!='Y' ){
        fossil_exit(1);
      }
    }
  }







|







1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
    g.markPrivate = 1;
  }

  /*
  ** Autosync if autosync is enabled and this is not a private check-in.
  */
  if( !g.markPrivate ){
    if( autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1)) ){
      prompt_user("continue in spite of sync failure (y/N)? ", &ans);
      cReply = blob_str(&ans)[0];
      if( cReply!='y' && cReply!='Y' ){
        fossil_exit(1);
      }
    }
  }
1674
1675
1676
1677
1678
1679
1680
1681

1682


1683
1684
1685







1686
1687
1688
1689
1690
1691
1692
  }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
    && g.markPrivate==0 && !is_a_leaf(vid)
  ){
    fossil_fatal("would fork.  \"update\" first or use --allow-fork.");
  }

  /*
  ** Do not allow a commit against a closed leaf

  */


  if( db_exists("SELECT 1 FROM tagxref"
                " WHERE tagid=%d AND rid=%d AND tagtype>0",
                TAG_CLOSED, vid) ){







    fossil_fatal("cannot commit against a closed leaf");
  }

  if( useCksum ) vfile_aggregate_checksum_disk(vid, &cksum1);
  if( zComment ){
    blob_zero(&comment);
    blob_append(&comment, zComment, -1);







|
>

>
>
|

|
>
>
>
>
>
>
>







1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
  }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
    && g.markPrivate==0 && !is_a_leaf(vid)
  ){
    fossil_fatal("would fork.  \"update\" first or use --allow-fork.");
  }

  /*
  ** Do not allow a commit against a closed leaf unless the commit
  ** ends up on a different branch.
  */
  if( 
      /* parent checkin has the "closed" tag... */
      db_exists("SELECT 1 FROM tagxref"
                " WHERE tagid=%d AND rid=%d AND tagtype>0",
                TAG_CLOSED, vid)
      /* ... and the new checkin has no --branch option or the --branch
      ** option does not actually change the branch */
   && (sCiInfo.zBranch==0
       || db_exists("SELECT 1 FROM tagxref"
                    " WHERE tagid=%d AND rid=%d AND tagtype>0"
                    "   AND value=%Q", TAG_BRANCH, vid, sCiInfo.zBranch))
  ){
    fossil_fatal("cannot commit against a closed leaf");
  }

  if( useCksum ) vfile_aggregate_checksum_disk(vid, &cksum1);
  if( zComment ){
    blob_zero(&comment);
    blob_append(&comment, zComment, -1);
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
  if( dryRunFlag ){
    db_end_transaction(1);
    exit(1);
  }
  db_end_transaction(0);

  if( !g.markPrivate ){
    autosync(SYNC_PUSH|SYNC_PULL);
  }
  if( count_nonbranch_children(vid)>1 ){
    fossil_print("**** warning: a fork has occurred *****\n");
  }
}







|





1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
  if( dryRunFlag ){
    db_end_transaction(1);
    exit(1);
  }
  db_end_transaction(0);

  if( !g.markPrivate ){
    autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1));
  }
  if( count_nonbranch_children(vid)>1 ){
    fossil_print("**** warning: a fork has occurred *****\n");
  }
}
Changes to src/checkout.c.
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    fossil_fatal(g.zErrMsg);
  }
  vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
  if( vid==0 ){
    fossil_fatal("no such check-in: %s", g.argv[2]);
  }
  if( !is_a_version(vid) ){
    fossil_fatal("object [%.10s] is not a check-in", blob_str(&uuid));
  }
  if( load_vfile_from_rid(vid) && !forceMissingFlag ){
    fossil_fatal("missing content, unable to checkout");
  };
  return vid;
}








|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    fossil_fatal(g.zErrMsg);
  }
  vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
  if( vid==0 ){
    fossil_fatal("no such check-in: %s", g.argv[2]);
  }
  if( !is_a_version(vid) ){
    fossil_fatal("object [%S] is not a check-in", blob_str(&uuid));
  }
  if( load_vfile_from_rid(vid) && !forceMissingFlag ){
    fossil_fatal("missing content, unable to checkout");
  };
  return vid;
}

135
136
137
138
139
140
141
142
143
144
145



146
147
148
149
150
151
152
  Blob manifest;
  Blob hash;

  if( db_get_boolean("manifest",0) ){
    blob_zero(&manifest);
    content_get(vid, &manifest);
    zManFile = mprintf("%smanifest", g.zLocalRoot);
    blob_write_to_file(&manifest, zManFile);
    free(zManFile);
    blob_zero(&hash);
    sha1sum_blob(&manifest, &hash);



    zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
    blob_append(&hash, "\n", 1);
    blob_write_to_file(&hash, zManFile);
    free(zManFile);
    blob_reset(&hash);
  }else{
    if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){







<
<


>
>
>







135
136
137
138
139
140
141


142
143
144
145
146
147
148
149
150
151
152
153
  Blob manifest;
  Blob hash;

  if( db_get_boolean("manifest",0) ){
    blob_zero(&manifest);
    content_get(vid, &manifest);
    zManFile = mprintf("%smanifest", g.zLocalRoot);


    blob_zero(&hash);
    sha1sum_blob(&manifest, &hash);
    sterilize_manifest(&manifest);
    blob_write_to_file(&manifest, zManFile);
    free(zManFile);
    zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
    blob_append(&hash, "\n", 1);
    blob_write_to_file(&hash, zManFile);
    free(zManFile);
    blob_reset(&hash);
  }else{
    if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
199
200
201
202
203
204
205




206
207
208
209
210
211
212
  db_must_be_within_tree();
  db_begin_transaction();
  forceFlag = find_option("force","f",0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  keepFlag = find_option("keep",0,0)!=0;
  latestFlag = find_option("latest",0,0)!=0;
  promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;




  if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
     usage("VERSION|--latest ?--force? ?--keep?");
  }
  if( !forceFlag && unsaved_changes(0) ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }
  if( forceFlag ){







>
>
>
>







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  db_must_be_within_tree();
  db_begin_transaction();
  forceFlag = find_option("force","f",0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  keepFlag = find_option("keep",0,0)!=0;
  latestFlag = find_option("latest",0,0)!=0;
  promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;

  /* We should be done with options.. */
  verify_all_options();

  if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
     usage("VERSION|--latest ?--force? ?--keep?");
  }
  if( !forceFlag && unsaved_changes(0) ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }
  if( forceFlag ){
290
291
292
293
294
295
296




297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
**   --force|-f  necessary to close a check out with uncommitted changes
**
** See also: open
*/
void close_cmd(void){
  int forceFlag = find_option("force","f",0)!=0;
  db_must_be_within_tree();




  if( !forceFlag && unsaved_changes(0) ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }
  if( !forceFlag
   && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
                db_name("localdb"))
   && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
  ){
    fossil_fatal("closing the checkout will delete your stash");
  }
  if( db_is_writeable("repository") ){
    char * zUnset = mprintf("ckout:%q", g.zLocalRoot);
    db_unset(zUnset, 1);
    fossil_free(zUnset);
  }
  unlink_local_database(1);
  db_close(1);
  unlink_local_database(0);
}







>
>
>
>











|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
**   --force|-f  necessary to close a check out with uncommitted changes
**
** See also: open
*/
void close_cmd(void){
  int forceFlag = find_option("force","f",0)!=0;
  db_must_be_within_tree();

  /* We should be done with options.. */
  verify_all_options();

  if( !forceFlag && unsaved_changes(0) ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }
  if( !forceFlag
   && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
                db_name("localdb"))
   && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
  ){
    fossil_fatal("closing the checkout will delete your stash");
  }
  if( db_is_writeable("repository") ){
    char *zUnset = mprintf("ckout:%q", g.zLocalRoot);
    db_unset(zUnset, 1);
    fossil_free(zUnset);
  }
  unlink_local_database(1);
  db_close(1);
  unlink_local_database(0);
}
Changes to src/clone.c.
125
126
127
128
129
130
131




132
133
134
135
136
137
138

  if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
  zHttpAuth = find_option("httpauth","B",1);
  zDefaultUser = find_option("admin-user","A",1);
  clone_ssh_find_options();
  url_proxy_options();




  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_fatal("file already exists: %s", g.argv[3]);
  }







>
>
>
>







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

  if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
  zHttpAuth = find_option("httpauth","B",1);
  zDefaultUser = find_option("admin-user","A",1);
  clone_ssh_find_options();
  url_proxy_options();
  
  /* We should be done with options.. */
  verify_all_options();

  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_fatal("file already exists: %s", g.argv[3]);
  }
193
194
195
196
197
198
199

200
201
202
203
204
205
206
    }
    db_open_repository(g.argv[3]);
  }
  db_begin_transaction();
  fossil_print("Rebuilding repository meta-data...\n");
  rebuild_db(0, 1, 0);
  fossil_print("project-id: %s\n", db_get("project-code", 0));

  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
  db_end_transaction(0);
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,







>







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    }
    db_open_repository(g.argv[3]);
  }
  db_begin_transaction();
  fossil_print("Rebuilding repository meta-data...\n");
  rebuild_db(0, 1, 0);
  fossil_print("project-id: %s\n", db_get("project-code", 0));
  fossil_print("server-id:  %s\n", db_get("server-code", 0));
  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
  db_end_transaction(0);
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
232
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
}

/*
** Get the HTTP Authorization preference from db.
*/
char *get_httpauth(void){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
  return unobscure(db_get(zKey, 0));
  free(zKey);

}

/*
** Set the HTTP Authorization preference in db.
*/
void set_httpauth(const char *zHttpAuth){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);







|

>







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
}

/*
** Get the HTTP Authorization preference from db.
*/
char *get_httpauth(void){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
  char * rc = unobscure(db_get(zKey, 0));
  free(zKey);
  return rc;
}

/*
** Set the HTTP Authorization preference in db.
*/
void set_httpauth(const char *zHttpAuth){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
Changes to src/comformat.c.
17
18
19
20
21
22
23

































































































































































































































24
25



26
27
28
29
30
31
32
33




34
35
36
37
38
39
40



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
**
** This file contains code used to format and print comments or other
** text on a TTY.
*/
#include "config.h"
#include "comformat.h"
#include <assert.h>


































































































































































































































/*



** Given a comment string zText, format that string for printing
** on a TTY.  Assume that the output cursors is indent spaces from
** the left margin and that a single line can contain no more than
** lineLength characters.  Indent all subsequent lines by indent.
**
** Return the number of newlines that are output.
*/
int comment_print(const char *zText, int indent, int lineLength){




  int tlen = lineLength - indent;
  int si, sk, i, k;
  int doIndent = 0;
  char *zBuf;
  char zBuffer[400];
  int lineCnt = 0;




  if( zText==0 ) zText = "(NULL)";
  if( tlen<=0 ){
    tlen = strlen(zText);
  }
  if( tlen >= (sizeof(zBuffer)) ){
    zBuf = fossil_malloc(tlen+1);
  }else{
    zBuf = zBuffer;
  }
  for(;;){
    while( fossil_isspace(zText[0]) ){ zText++; }
    if( zText[0]==0 ){
      if( doIndent==0 ){
        fossil_print("\n");
        lineCnt = 1;
      }
      if( zBuf!=zBuffer) fossil_free(zBuf);
      return lineCnt;
    }
    for(sk=si=i=k=0; zText[i] && k<tlen; i++){
      char c = zText[i];
      if( fossil_isspace(c) ){
        si = i;
        sk = k;
        if( k==0 || zBuf[k-1]!=' ' ){
          zBuf[k++] = ' ';
        }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
|
|
|
|

|

|
>
>
>
>
|






>
>
>

|
|

|
|













|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
**
** This file contains code used to format and print comments or other
** text on a TTY.
*/
#include "config.h"
#include "comformat.h"
#include <assert.h>
#ifdef _WIN32
# include <windows.h>
#else
# include <termios.h>
# if defined(TIOCGWINSZ)
#  include <sys/ioctl.h>
# endif
#endif

#if INTERFACE
#define COMMENT_PRINT_NONE       ((u32)0x00000000) /* No flags. */
#define COMMENT_PRINT_LEGACY     ((u32)0x00000001) /* Use legacy algorithm. */
#define COMMENT_PRINT_TRIM_CRLF  ((u32)0x00000002) /* Trim leading CR/LF. */
#define COMMENT_PRINT_TRIM_SPACE ((u32)0x00000004) /* Trim leading/trailing. */
#define COMMENT_PRINT_WORD_BREAK ((u32)0x00000008) /* Break lines on words. */
#define COMMENT_PRINT_ORIG_BREAK ((u32)0x00000010) /* Break before original. */
#define COMMENT_PRINT_DEFAULT    (COMMENT_PRINT_LEGACY) /* Defaults. */
#endif

/*
** This is the previous value used by most external callers when they
** needed to specify a default maximum line length to be used with the
** comment_print() function.
*/
#ifndef COMMENT_LEGACY_LINE_LENGTH
# define COMMENT_LEGACY_LINE_LENGTH    (78)
#endif

/*
** This is the number of spaces to print when a tab character is seen.
*/
#ifndef COMMENT_TAB_WIDTH
# define COMMENT_TAB_WIDTH             (8)
#endif

/*
** This function sets the maximum number of characters to print per line
** based on the detected terminal line width, if available; otherwise, it
** uses the legacy default terminal line width minus the amount to indent.
**
** Zero is returned to indicate any failure.  One is returned to indicate
** the successful detection of the terminal line width.  Negative one is
** returned to indicate the terminal line width is using the hard-coded
** legacy default value.
*/
static int comment_set_maxchars(
  int indent,
  int *pMaxChars
){
#if defined(_WIN32)
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
  if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
    *pMaxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
    return 1;
  }
  return 0;
#elif defined(TIOCGWINSZ)
  struct winsize w;
  memset(&w, 0, sizeof(struct winsize));
  if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
    *pMaxChars = w.ws_col - indent;
    return 1;
  }
  return 0;
#else
  /*
  ** Fallback to using more-or-less the "legacy semantics" of hard-coding
  ** the maximum line length to a value reasonable for the vast majority
  ** of supported systems.
  */
  *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
  return -1;
#endif
}

/*
** This function checks the current line being printed against the original
** comment text.  Upon matching, it emits a new line and updates the provided
** character and line counts, if applicable.
*/
static int comment_check_orig(
  const char *zOrigText, /* [in] Original comment text ONLY, may be NULL. */
  const char *zLine,     /* [in] The comment line to print. */
  int *pCharCnt,         /* [in/out] Pointer to the line character count. */
  int *pLineCnt          /* [in/out] Pointer to the total line count. */
){
  if( zOrigText && fossil_strcmp(zLine, zOrigText)==0 ){
    fossil_print("\n");
    if( pCharCnt ) *pCharCnt = 0;
    if( pLineCnt ) (*pLineCnt)++;
    return 1;
  }
  return 0;
}

/*
** This function scans the specified comment line starting just after the
** initial index and returns the index of the next spacing character -OR-
** zero if such a character cannot be found.  For the purposes of this
** algorithm, the NUL character is treated the same as a spacing character.
*/
static int comment_next_space(
  const char *zLine, /* [in] The comment line being printed. */
  int index          /* [in] The current character index being handled. */
){
  int nextIndex = index + 1;
  for(;;){
    char c = zLine[nextIndex];
    if( c==0 || fossil_isspace(c) ){
      return nextIndex;
    }
    nextIndex++;
  }
  return 0; /* NOT REACHED */
}

/*
** This function is called when printing a logical comment line to perform
** the necessary indenting.
*/
static void comment_print_indent(
  const char *zLine, /* [in] The comment line being printed. */
  int indent,        /* [in] Number of spaces to indent, zero for none. */
  int trimCrLf,      /* [in] Non-zero to trim leading/trailing CR/LF. */
  int trimSpace,     /* [in] Non-zero to trim leading/trailing spaces. */
  int *piIndex       /* [in/out] Pointer to first non-space character. */
){
  if( indent>0 ){
    fossil_print("%*s", indent, "");
  }
  if( zLine && piIndex ){
    int index = *piIndex;
    if( trimCrLf ){
      while( zLine[index]=='\r' || zLine[index]=='\n' ){ index++; }
    }
    if( trimSpace ){
      while( fossil_isspace(zLine[index]) ){ index++; }
    }
    *piIndex = index;
  }
}

/*
** This function prints one logical line of a comment, stopping when it hits
** a new line -OR- runs out of space on the logical line.
*/
static void comment_print_line(
  const char *zOrigText, /* [in] Original comment text ONLY, may be NULL. */
  const char *zLine,     /* [in] The comment line to print. */
  int origIndent,        /* [in] Number of spaces to indent before the original
                         **      comment. */
  int indent,            /* [in] Number of spaces to indent, before the line
                         **      to print. */
  int lineChars,         /* [in] Maximum number of characters to print. */
  int trimCrLf,          /* [in] Non-zero to trim leading/trailing CR/LF. */
  int trimSpace,         /* [in] Non-zero to trim leading/trailing spaces. */
  int wordBreak,         /* [in] Non-zero to try breaking on word boundaries. */
  int origBreak,         /* [in] Non-zero to break before original comment. */
  int *pLineCnt,         /* [in/out] Pointer to the total line count. */
  const char **pzLine    /* [out] Pointer to the end of the logical line. */
){
  int index = 0, charCnt = 0, lineCnt = 0, maxChars;
  if( !zLine ) return;
  if( lineChars<=0 ) return;
  comment_print_indent(zLine, indent, trimCrLf, trimSpace, &index);
  maxChars = lineChars;
  for(;;){
    int useChars = 1;
    char c = zLine[index];
    if( c==0 ){
      break;
    }else{
      if( origBreak && index>0 ){
        const char *zCurrent = &zLine[index];
        if( comment_check_orig(zOrigText, zCurrent, &charCnt, &lineCnt) ){
          comment_print_indent(zCurrent, origIndent, trimCrLf, trimSpace,
                               &index);
          maxChars = lineChars;
        }
      }
      index++;
    }
    if( c=='\n' ){
      lineCnt++;
      charCnt = 0;
      useChars = 0;
    }else if( c=='\t' ){
      int nextIndex = comment_next_space(zLine, index);
      if( nextIndex<=0 || (nextIndex-index)>maxChars ){
        break;
      }
      charCnt++;
      useChars = COMMENT_TAB_WIDTH;
      if( maxChars<useChars ){
        fossil_print(" ");
        break;
      }
    }else if( wordBreak && fossil_isspace(c) ){
      int nextIndex = comment_next_space(zLine, index);
      if( nextIndex<=0 || (nextIndex-index)>maxChars ){
        break;
      }
      charCnt++;
    }else{
      charCnt++;
    }
    assert( c!='\n' || charCnt==0 );
    fossil_print("%c", c);
    maxChars -= useChars;
    if( maxChars==0 ) break;
    assert( maxChars>0 );
    if( c=='\n' ) break;
  }
  if( charCnt>0 ){
    fossil_print("\n");
    lineCnt++;
  }
  if( pLineCnt ){
    *pLineCnt += lineCnt;
  }
  if( pzLine ){
    *pzLine = zLine + index;
  }
}

/*
** This is the legacy comment printing algorithm.  It is being retained
** for backward compatibility.
**
** Given a comment string, format that string for printing on a TTY.
** Assume that the output cursors is indent spaces from the left margin
** and that a single line can contain no more than 'width' characters.
** Indent all subsequent lines by 'indent'.
**
** Returns the number of new lines emitted.
*/
static int comment_print_legacy(
  const char *zText, /* The comment text to be printed. */
  int indent,        /* Number of spaces to indent each non-initial line. */
  int width          /* Maximum number of characters per line. */
){
  int maxChars = width - indent;
  int si, sk, i, k;
  int doIndent = 0;
  char *zBuf;
  char zBuffer[400];
  int lineCnt = 0;

  if( width<0 ){
    comment_set_maxchars(indent, &maxChars);
  }
  if( zText==0 ) zText = "(NULL)";
  if( maxChars<=0 ){
    maxChars = strlen(zText);
  }
  if( maxChars >= (sizeof(zBuffer)) ){
    zBuf = fossil_malloc(maxChars+1);
  }else{
    zBuf = zBuffer;
  }
  for(;;){
    while( fossil_isspace(zText[0]) ){ zText++; }
    if( zText[0]==0 ){
      if( doIndent==0 ){
        fossil_print("\n");
        lineCnt = 1;
      }
      if( zBuf!=zBuffer) fossil_free(zBuf);
      return lineCnt;
    }
    for(sk=si=i=k=0; zText[i] && k<maxChars; i++){
      char c = zText[i];
      if( fossil_isspace(c) ){
        si = i;
        sk = k;
        if( k==0 || zBuf[k-1]!=' ' ){
          zBuf[k++] = ' ';
        }
87
88
89
90
91
92
93
94



95























































































96




















97
98





99






























100
101
102



























103


104

105



106
    }
    fossil_print("%s\n", zBuf);
    lineCnt++;
  }
}

/*
** Test the comment printing



**























































































** COMMAND: test-comment-format




















*/
void test_comment_format(void){





  int indent;






























  if( g.argc!=4 ){
    usage("PREFIX TEXT");
  }



























  indent = strlen(g.argv[2]) + 1;


  fossil_print("%s ", g.argv[2]);

  fossil_print("(%d lines output)\n", comment_print(g.argv[3], indent, 79));



}







|
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
|
>
>
>

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    }
    fossil_print("%s\n", zBuf);
    lineCnt++;
  }
}

/*
** This is the comment printing function.  The comment printing algorithm
** contained within it attempts to preserve the formatting present within
** the comment string itself while honoring line width limitations.  There
** are several flags that modify the default behavior of this function:
**
**         COMMENT_PRINT_LEGACY: Forces use of the legacy comment printing
**                               algorithm.  For backward compatibility,
**                               this is the default.
**
**      COMMENT_PRINT_TRIM_CRLF: Trims leading and trailing carriage-returns
**                               and line-feeds where they do not materially
**                               impact pre-existing formatting (i.e. at the
**                               start of the comment string -AND- right
**                               before line indentation).  This flag does
**                               not apply to the legacy comment printing
**                               algorithm.  This flag may be combined with
**                               COMMENT_PRINT_TRIM_SPACE.
**
**     COMMENT_PRINT_TRIM_SPACE: Trims leading and trailing spaces where they
**                               do not materially impact the pre-existing
**                               formatting (i.e. at the start of the comment
**                               string -AND- right before line indentation).
**                               This flag does not apply to the legacy
**                               comment printing algorithm.  This flag may
**                               be combined with COMMENT_PRINT_TRIM_CRLF.
**
**     COMMENT_PRINT_WORD_BREAK: Attempts to break lines on word boundaries
**                               while honoring the logical line length.
**                               If this flag is not specified, honoring the
**                               logical line length may result in breaking
**                               lines in the middle of words.  This flag
**                               does not apply to the legacy comment
**                               printing algorithm.
**
**     COMMENT_PRINT_ORIG_BREAK: Looks for the original comment text within
**                               the text being printed.  Upon matching, a
**                               new line will be emitted, thus preserving
**                               more of the pre-existing formatting.
**
** Given a comment string, format that string for printing on a TTY.
** Assume that the output cursors is indent spaces from the left margin
** and that a single line can contain no more than 'width' characters.
** Indent all subsequent lines by 'indent'.
**
** Returns the number of new lines emitted.
*/
int comment_print(
  const char *zText,     /* The comment text to be printed. */
  const char *zOrigText, /* Original comment text ONLY, may be NULL. */
  int indent,            /* Spaces to indent each non-initial line. */
  int width,             /* Maximum number of characters per line. */
  int flags              /* Zero or more "COMMENT_PRINT_*" flags. */
){
  int maxChars = width - indent;
  int legacy = flags & COMMENT_PRINT_LEGACY;
  int trimCrLf = flags & COMMENT_PRINT_TRIM_CRLF;
  int trimSpace = flags & COMMENT_PRINT_TRIM_SPACE;
  int wordBreak = flags & COMMENT_PRINT_WORD_BREAK;
  int origBreak = flags & COMMENT_PRINT_ORIG_BREAK;
  int lineCnt = 0;
  const char *zLine;

  if( legacy ){
    return comment_print_legacy(zText, indent, width);
  }
  if( width<0 ){
    comment_set_maxchars(indent, &maxChars);
  }
  if( zText==0 ) zText = "(NULL)";
  if( maxChars<=0 ){
    maxChars = strlen(zText);
  }
  if( trimSpace ){
    while( fossil_isspace(zText[0]) ){ zText++; }
  }
  if( zText[0]==0 ){
    fossil_print("\n");
    lineCnt++;
    return lineCnt;
  }
  zLine = zText;
  for(;;){
    comment_print_line(zOrigText, zLine, indent, zLine>zText ? indent : 0,
                       maxChars, trimCrLf, trimSpace, wordBreak, origBreak,
                       &lineCnt, &zLine);
    if( !zLine || !zLine[0] ) break;
  }
  return lineCnt;
}

/*
**
** COMMAND: test-comment-format
**
** Usage: %fossil test-comment-format ?OPTIONS? PREFIX TEXT ?ORIGTEXT?
**
** Test comment formatting and printing.  Use for testing only.
**
** Options:
**   --file           The comment text is really just a file name to
**                    read it from.
**   --decode         Decode the text using the same method used when
**                    handling the value of a C-card from a manifest.
**   --legacy         Use the legacy comment printing algorithm.
**   --trimcrlf       Enable trimming of leading/trailing CR/LF.
**   --trimspace      Enable trimming of leading/trailing spaces.
**   --wordbreak      Attempt to break lines on word boundaries.
**   --origbreak      Attempt to break when the original comment text
**                    is detected.
**   --indent         Number of spaces to indent (default (-1) is to
**                    auto-detect).  Zero means no indent.
**   -W|--width <num> Width of lines (default (-1) is to auto-detect).
**                    Zero means no limit.
*/
void test_comment_format(void){
  const char *zWidth;
  const char *zIndent;
  const char *zPrefix;
  char *zText;
  char *zOrigText;
  int indent, width;
  int fromFile = find_option("file", 0, 0)!=0;
  int decode = find_option("decode", 0, 0)!=0;
  int flags = COMMENT_PRINT_NONE;
  if( find_option("legacy", 0, 0) ){
    flags |= COMMENT_PRINT_LEGACY;
  }
  if( find_option("trimcrlf", 0, 0) ){
    flags |= COMMENT_PRINT_TRIM_CRLF;
  }
  if( find_option("trimspace", 0, 0) ){
    flags |= COMMENT_PRINT_TRIM_SPACE;
  }
  if( find_option("wordbreak", 0, 0) ){
    flags |= COMMENT_PRINT_WORD_BREAK;
  }
  if( find_option("origbreak", 0, 0) ){
    flags |= COMMENT_PRINT_ORIG_BREAK;
  }
  zWidth = find_option("width","W",1);
  if( zWidth ){
    width = atoi(zWidth);
  }else{
    width = -1; /* automatic */
  }
  zIndent = find_option("indent",0,1);
  if( zIndent ){
    indent = atoi(zIndent);
  }else{
    indent = -1; /* automatic */
  }
  if( g.argc!=4 && g.argc!=5 ){
    usage("?OPTIONS? PREFIX TEXT ?ORIGTEXT?");
  }
  zPrefix = g.argv[2];
  zText = g.argv[3];
  if( g.argc==5 ){
    zOrigText = g.argv[4];
  }else{
    zOrigText = 0;
  }
  if( fromFile ){
    Blob fileData;
    blob_read_from_file(&fileData, zText);
    zText = mprintf("%s", blob_str(&fileData));
    blob_reset(&fileData);
    if( zOrigText ){
      blob_read_from_file(&fileData, zOrigText);
      zOrigText = mprintf("%s", blob_str(&fileData));
      blob_reset(&fileData);
    }
  }
  if( decode ){
    zText = mprintf(fromFile ? "%z" : "%s", zText);
    defossilize(zText);
    if( zOrigText ){
      zOrigText = mprintf(fromFile ? "%z" : "%s", zOrigText);
      defossilize(zOrigText);
    }
  }
  if( indent<0 ){
    indent = strlen(zPrefix);
  }
  if( zPrefix && *zPrefix ){
    fossil_print("%s", zPrefix);
  }
  fossil_print("(%d lines output)\n",
               comment_print(zText, zOrigText, indent, width, flags));
  if( zOrigText && zOrigText!=g.argv[4] ) fossil_free(zOrigText);
  if( zText && zText!=g.argv[3] ) fossil_free(zText);
}
Changes to src/config.h.
22
23
24
25
26
27
28





29
30
31
32
33
34
35
** some linux distributions, and possibly other unixes as well.
*/
#define _LARGE_FILE       1
#ifndef _FILE_OFFSET_BITS
#  define _FILE_OFFSET_BITS 64
#endif
#define _LARGEFILE_SOURCE 1






/* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */
#if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T)
#  define _USE_32BIT_TIME_T
#endif

#ifdef HAVE_AUTOCONFIG_H







>
>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** some linux distributions, and possibly other unixes as well.
*/
#define _LARGE_FILE       1
#ifndef _FILE_OFFSET_BITS
#  define _FILE_OFFSET_BITS 64
#endif
#define _LARGEFILE_SOURCE 1

/* Needed for various definitions... */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif

/* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */
#if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T)
#  define _USE_32BIT_TIME_T
#endif

#ifdef HAVE_AUTOCONFIG_H
Changes to src/configure.c.
95
96
97
98
99
100
101






102
103
104
105
106
107
108
  { "index-page",             CONFIGSET_SKIN },
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "timeline-plaintext",     CONFIGSET_SKIN },
  { "adunit",                 CONFIGSET_SKIN },
  { "adunit-omit-if-admin",   CONFIGSET_SKIN },
  { "adunit-omit-if-user",    CONFIGSET_SKIN },






  { "th1-setup",              CONFIGSET_TH1 },
  { "th1-uri-regexp",         CONFIGSET_TH1 },

#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_TH1 },
  { "tcl-setup",              CONFIGSET_TH1 },
#endif







>
>
>
>
>
>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  { "index-page",             CONFIGSET_SKIN },
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "timeline-plaintext",     CONFIGSET_SKIN },
  { "adunit",                 CONFIGSET_SKIN },
  { "adunit-omit-if-admin",   CONFIGSET_SKIN },
  { "adunit-omit-if-user",    CONFIGSET_SKIN },
#ifdef FOSSIL_ENABLE_TH1_DOCS
  { "th1-docs",               CONFIGSET_TH1 },
#endif
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  { "th1-hooks",              CONFIGSET_TH1 },
#endif
  { "th1-setup",              CONFIGSET_TH1 },
  { "th1-uri-regexp",         CONFIGSET_TH1 },

#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_TH1 },
  { "tcl-setup",              CONFIGSET_TH1 },
#endif
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  int i;
  int n = strlen(zName);
  if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
    zName++;
    n -= 2;
  }
  for(i=0; i<count(aConfig); i++){
    if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
      int m = aConfig[i].groupMask;
      if( !g.perm.Admin ){
        m &= ~CONFIGSET_USER;
      }
      if( !g.perm.RdAddr ){
        m &= ~CONFIGSET_ADDR;
      }







|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  int i;
  int n = strlen(zName);
  if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
    zName++;
    n -= 2;
  }
  for(i=0; i<count(aConfig); i++){
    if( strncmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
      int m = aConfig[i].groupMask;
      if( !g.perm.Admin ){
        m &= ~CONFIGSET_USER;
      }
      if( !g.perm.RdAddr ){
        m &= ~CONFIGSET_ADDR;
      }
Changes to src/content.c.
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
    rc = 1;
  }
  db_reset(&q);
  if( rc ){
    const char *zCFType = "control artifact";
    char *zSrc;
    char *zDate;
    char *zErrType = "MISSING";
    if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
      if( flags & MISSING_SHUNNED ) return 0;
      zErrType = "SHUNNED";
    }
    switch( p->type ){
      case CFTYPE_MANIFEST:   zCFType = "check-in";    break;
      case CFTYPE_CLUSTER:    zCFType = "cluster";     break;







|







1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
    rc = 1;
  }
  db_reset(&q);
  if( rc ){
    const char *zCFType = "control artifact";
    char *zSrc;
    char *zDate;
    const char *zErrType = "MISSING";
    if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
      if( flags & MISSING_SHUNNED ) return 0;
      zErrType = "SHUNNED";
    }
    switch( p->type ){
      case CFTYPE_MANIFEST:   zCFType = "check-in";    break;
      case CFTYPE_CLUSTER:    zCFType = "cluster";     break;
Changes to src/db.c.
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

/*
** Execute a query.  Return the first column of the first row
** of the result set as a string.  Space to hold the string is
** obtained from malloc().  If the result set is empty, return
** zDefault instead.
*/
char *db_text(char const *zDefault, const char *zSql, ...){
  va_list ap;
  Stmt s;
  char *z;
  va_start(ap, zSql);
  db_vprepare(&s, 0, zSql, ap);
  va_end(ap);
  if( db_step(&s)==SQLITE_ROW ){







|







626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

/*
** Execute a query.  Return the first column of the first row
** of the result set as a string.  Space to hold the string is
** obtained from malloc().  If the result set is empty, return
** zDefault instead.
*/
char *db_text(const char *zDefault, const char *zSql, ...){
  va_list ap;
  Stmt s;
  char *z;
  va_start(ap, zSql);
  db_vprepare(&s, 0, zSql, ap);
  va_end(ap);
  if( db_step(&s)==SQLITE_ROW ){
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
** Open a database file.  Return a pointer to the new database
** connection.  An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
  int rc;
  sqlite3 *db;

#if defined(__CYGWIN__) && USE_SYSTEM_SQLITE+0!=1
  zDbName = fossil_utf8_to_filename(zDbName);
#endif
  if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
  rc = sqlite3_open_v2(
       zDbName, &db,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       g.zVfsName
  );
  if( rc!=SQLITE_OK ){







<
<
<







713
714
715
716
717
718
719



720
721
722
723
724
725
726
** Open a database file.  Return a pointer to the new database
** connection.  An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
  int rc;
  sqlite3 *db;




  if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
  rc = sqlite3_open_v2(
       zDbName, &db,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       g.zVfsName
  );
  if( rc!=SQLITE_OK ){
783
784
785
786
787
788
789























790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806



807
808
809
810
811
812
813
    if( pWasAttached ) *pWasAttached = 0;
  }else{
    assert( g.zMainDbType!=0 );
    db_attach(zDbName, zLabel);
    if( pWasAttached ) *pWasAttached = 1;
  }
}
























/*
** Open the user database in "~/.fossil".  Create the database anew if
** it does not already exist.
**
** If the useAttach flag is 0 (the usual case) then the user database is
** opened on a separate database connection g.dbConfig.  This prevents
** the ~/.fossil database from becoming locked on long check-in or sync
** operations which hold an exclusive transaction.  In a few cases, though,
** it is convenient for the ~/.fossil to be attached to the main database
** connection so that we can join between the various databases.  In that
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  char *zHome;
  if( g.zConfigDbName ) return;



#if defined(_WIN32) || defined(__CYGWIN__)
  zHome = fossil_getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = fossil_getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = fossil_getenv("HOMEDRIVE");
      zHome = fossil_getenv("HOMEPATH");







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|
>
>
>







780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
    if( pWasAttached ) *pWasAttached = 0;
  }else{
    assert( g.zMainDbType!=0 );
    db_attach(zDbName, zLabel);
    if( pWasAttached ) *pWasAttached = 1;
  }
}

/*
** Close the user database.
*/
void db_close_config(){
  if( g.useAttach ){
    db_detach("configdb");
    g.useAttach = 0;
    g.zConfigDbName = 0;
  }else if( g.dbConfig ){
    sqlite3_wal_checkpoint(g.dbConfig, 0);
    sqlite3_close(g.dbConfig);
    g.dbConfig = 0;
    g.zConfigDbType = 0;
    g.zConfigDbName = 0;
  }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
    sqlite3_wal_checkpoint(g.db, 0);
    sqlite3_close(g.db);
    g.db = 0;
    g.zMainDbType = 0;
    g.zConfigDbName = 0;
  }
}

/*
** Open the user database in "~/.fossil".  Create the database anew if
** it does not already exist.
**
** If the useAttach flag is 0 (the usual case) then the user database is
** opened on a separate database connection g.dbConfig.  This prevents
** the ~/.fossil database from becoming locked on long check-in or sync
** operations which hold an exclusive transaction.  In a few cases, though,
** it is convenient for the ~/.fossil to be attached to the main database
** connection so that we can join between the various databases.  In that
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  char *zHome;
  if( g.zConfigDbName ){
    if( useAttach==g.useAttach ) return;
    db_close_config();
  }
#if defined(_WIN32) || defined(__CYGWIN__)
  zHome = fossil_getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = fossil_getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = fossil_getenv("HOMEDRIVE");
      zHome = fossil_getenv("HOMEPATH");
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
** is found, it is attached to the open database connection too.
*/
int db_open_local(const char *zDbName){
  int i, n;
  char zPwd[2000];
  static const char aDbName[][10] = { "_FOSSIL_", ".fslckout", ".fos" };

  if( g.localOpen) return 1;
  file_getcwd(zPwd, sizeof(zPwd)-20);
  n = strlen(zPwd);
  while( n>0 ){
    for(i=0; i<count(aDbName); i++){
      sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "/%s", aDbName[i]);
      if( isValidLocalDb(zPwd) ){
        /* Found a valid checkout database file */







|







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
** is found, it is attached to the open database connection too.
*/
int db_open_local(const char *zDbName){
  int i, n;
  char zPwd[2000];
  static const char aDbName[][10] = { "_FOSSIL_", ".fslckout", ".fos" };

  if( g.localOpen ) return 1;
  file_getcwd(zPwd, sizeof(zPwd)-20);
  n = strlen(zPwd);
  while( n>0 ){
    for(i=0; i<count(aDbName); i++){
      sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "/%s", aDbName[i]);
      if( isValidLocalDb(zPwd) ){
        /* Found a valid checkout database file */
1043
1044
1045
1046
1047
1048
1049
1050



1051
1052
1053
1054
1055
1056
1057
** Try to find the repository and open it.  Use the -R or --repository
** option to locate the repository.  If no such option is available, then
** use the repository of the open checkout if there is one.
**
** Error out if the repository cannot be opened.
*/
void db_find_and_open_repository(int bFlags, int nArgUsed){
  const char *zRep = find_option("repository", "R", 1);



  if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
    zRep = g.argv[nArgUsed];
  }
  if( zRep==0 ){
    if( db_open_local(0)==0 ){
      goto rep_not_found;
    }







|
>
>
>







1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
** Try to find the repository and open it.  Use the -R or --repository
** option to locate the repository.  If no such option is available, then
** use the repository of the open checkout if there is one.
**
** Error out if the repository cannot be opened.
*/
void db_find_and_open_repository(int bFlags, int nArgUsed){
  const char *zRep = find_repository_option();
  if( zRep && file_isdir(zRep)==1 ){
    goto rep_not_found;
  }
  if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
    zRep = g.argv[nArgUsed];
  }
  if( zRep==0 ){
    if( db_open_local(0)==0 ){
      goto rep_not_found;
    }
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218



1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
  db_end_transaction(1);
  pStmt = 0;
  if( reportErrors ){
    while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
      fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
    }
  }
  g.repositoryOpen = 0;
  g.localOpen = 0;
  g.zConfigDbName = NULL;
  sqlite3_wal_checkpoint(g.db, 0);
  sqlite3_close(g.db);
  g.db = 0;
  g.zMainDbType = 0;



  if( g.dbConfig ){
    sqlite3_close(g.dbConfig);

    g.dbConfig = 0;
    g.zConfigDbType = 0;
  }
}


/*
** Create a new empty repository database with the given name.
**
** Only the schema is initialized.  The required VAR tables entries







|
|
<
|
|
|
|
>
>
>
|
<
>
|
|
<







1231
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
  db_end_transaction(1);
  pStmt = 0;
  if( reportErrors ){
    while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
      fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
    }
  }
  db_close_config();
  if( g.db ){

    sqlite3_wal_checkpoint(g.db, 0);
    sqlite3_close(g.db);
    g.db = 0;
    g.zMainDbType = 0;
  }
  g.repositoryOpen = 0;
  g.localOpen = 0;
  assert( g.dbConfig==0 );

  assert( g.useAttach==0 );
  assert( g.zConfigDbName==0 );
  assert( g.zConfigDbType==0 );

}


/*
** Create a new empty repository database with the given name.
**
** Only the schema is initialized.  The required VAR tables entries
1282
1283
1284
1285
1286
1287
1288
































1289
1290
1291
1292
1293
1294
1295
       "INSERT OR IGNORE INTO user(login,pw,cap,info)"
       "   VALUES('developer','','dei','Dev');"
       "INSERT OR IGNORE INTO user(login,pw,cap,info)"
       "   VALUES('reader','','kptw','Reader');"
    );
  }
}

































/*
** Return a pointer to a string that contains the RHS of an IN operator
** that will select CONFIG table names that are in the list of control
** settings.
*/
const char *db_setting_inop_rhs(){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
       "INSERT OR IGNORE INTO user(login,pw,cap,info)"
       "   VALUES('developer','','dei','Dev');"
       "INSERT OR IGNORE INTO user(login,pw,cap,info)"
       "   VALUES('reader','','kptw','Reader');"
    );
  }
}

/*
** This function sets the server and project codes if they do not already
** exist.  Currently, it should be called only by the db_initial_setup()
** or cmd_webserver() functions, the latter being used to facilitate more
** robust integration with "canned image" environments (e.g. Docker).
*/
void db_setup_server_and_project_codes(
  int optional
){
  if( !optional ){
    db_multi_exec(
        "INSERT INTO config(name,value,mtime)"
        " VALUES('server-code', lower(hex(randomblob(20))),now());"
        "INSERT INTO config(name,value,mtime)"
        " VALUES('project-code', lower(hex(randomblob(20))),now());"
    );
  }else{
    if( db_get("server-code", 0)==0 ) {
      db_multi_exec(
          "INSERT INTO config(name,value,mtime)"
          " VALUES('server-code', lower(hex(randomblob(20))),now());"
      );
    }
    if( db_get("project-code", 0)==0 ) {
      db_multi_exec(
          "INSERT INTO config(name,value,mtime)"
          " VALUES('project-code', lower(hex(randomblob(20))),now());"
      );
    }
  }
}

/*
** Return a pointer to a string that contains the RHS of an IN operator
** that will select CONFIG table names that are in the list of control
** settings.
*/
const char *db_setting_inop_rhs(){
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
  Blob hash;
  Blob manifest;

  db_set("content-schema", CONTENT_SCHEMA, 0);
  db_set("aux-schema", AUX_SCHEMA, 0);
  db_set("rebuilt", get_version(), 0);
  if( makeServerCodes ){
    db_multi_exec(
      "INSERT INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))),now());"
      "INSERT INTO config(name,value,mtime)"
      " VALUES('project-code', lower(hex(randomblob(20))),now());"
    );
  }
  if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
  if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
  if( !db_is_global("timeline-plaintext") ){
    db_set_int("timeline-plaintext", 1, 0);
  }
  db_create_default_users(0, zDefaultUser);







<
<
<
<
|
<







1394
1395
1396
1397
1398
1399
1400




1401

1402
1403
1404
1405
1406
1407
1408
  Blob hash;
  Blob manifest;

  db_set("content-schema", CONTENT_SCHEMA, 0);
  db_set("aux-schema", AUX_SCHEMA, 0);
  db_set("rebuilt", get_version(), 0);
  if( makeServerCodes ){




    db_setup_server_and_project_codes(0);

  }
  if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
  if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
  if( !db_is_global("timeline-plaintext") ){
    db_set_int("timeline-plaintext", 1, 0);
  }
  db_create_default_users(0, zDefaultUser);
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477

1478
1479
1480
1481
1482
1483
1484
** default users "anonymous", "nobody", "reader", "developer", and their
** associated permissions will be copied.
**
** Options:
**    --template      FILE      copy settings from repository file
**    --admin-user|-A USERNAME  select given USERNAME as admin user
**    --date-override DATETIME  use DATETIME as time of the initial checkin
**                              (overrides --empty as well)
**    --empty                   Do not create an initial empty checkin.
**
** See also: clone
*/
void create_repository_cmd(void){
  char *zPassword;
  const char *zTemplate;      /* Repository from which to copy settings */
  const char *zDate;          /* Date of the initial check-in */
  const char *zDefaultUser;   /* Optional name of the default user */
  char const *zCreateEmpty;   /* --empty flag set? */

  zTemplate = find_option("template",0,1);
  zDate = find_option("date-override",0,1);
  zDefaultUser = find_option("admin-user","A",1);
  zCreateEmpty = find_option("empty", 0, 0);
  if( !zDate && !zCreateEmpty ){
    zDate = "now";

  }
  if( g.argc!=3 ){
    usage("REPOSITORY-NAME");
  }
  db_create_repository(g.argv[2]);
  db_open_repository(g.argv[2]);
  db_open_config(0);
  if( zTemplate ) db_attach(zTemplate, "settingSrc");
  db_begin_transaction();
  db_initial_setup(zTemplate, zDate, zDefaultUser, 1);
  db_end_transaction(0);
  if( zTemplate ) db_detach("settingSrc");

  fossil_print("project-id: %s\n", db_get("project-code", 0));
  fossil_print("server-id:  %s\n", db_get("server-code", 0));

  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (initial password is \"%s\")\n",
               g.zLogin, zPassword);
}

/*
** SQL functions for debugging.







|
|








|




|
|
|
>
|








|


>
|
|
>







1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
** default users "anonymous", "nobody", "reader", "developer", and their
** associated permissions will be copied.
**
** Options:
**    --template      FILE      copy settings from repository file
**    --admin-user|-A USERNAME  select given USERNAME as admin user
**    --date-override DATETIME  use DATETIME as time of the initial checkin
**                              (default: do not create an initial checkin)
**    --empty                   create repository without project-id/server-id
**
** See also: clone
*/
void create_repository_cmd(void){
  char *zPassword;
  const char *zTemplate;      /* Repository from which to copy settings */
  const char *zDate;          /* Date of the initial check-in */
  const char *zDefaultUser;   /* Optional name of the default user */
  int makeServerCodes;

  zTemplate = find_option("template",0,1);
  zDate = find_option("date-override",0,1);
  zDefaultUser = find_option("admin-user","A",1);
  makeServerCodes = find_option("empty", 0, 0)==0;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=3 ){
    usage("REPOSITORY-NAME");
  }
  db_create_repository(g.argv[2]);
  db_open_repository(g.argv[2]);
  db_open_config(0);
  if( zTemplate ) db_attach(zTemplate, "settingSrc");
  db_begin_transaction();
  db_initial_setup(zTemplate, zDate, zDefaultUser, makeServerCodes);
  db_end_transaction(0);
  if( zTemplate ) db_detach("settingSrc");
  if( makeServerCodes ){
    fossil_print("project-id: %s\n", db_get("project-code", 0));
    fossil_print("server-id:  %s\n", db_get("server-code", 0));
  }
  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (initial password is \"%s\")\n",
               g.zLogin, zPassword);
}

/*
** SQL functions for debugging.
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
}

/*
** Returns non-0 if the database (which must be open) table identified
** by zTableName has a column named zColName (case-sensitive), else
** returns 0.
*/
int db_table_has_column( char const *zTableName, char const *zColName ){
  Stmt q = empty_Stmt;
  int rc = 0;
  db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
  while(SQLITE_ROW == db_step(&q)){
    /* Columns: (cid, name, type, notnull, dflt_value, pk) */
    char const * zCol = db_column_text(&q, 1);
    if(0==fossil_strcmp(zColName, zCol)){
      rc = 1;
      break;
    }
  }
  db_finalize(&q);
  return rc;
}







|





|
|







1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
}

/*
** Returns non-0 if the database (which must be open) table identified
** by zTableName has a column named zColName (case-sensitive), else
** returns 0.
*/
int db_table_has_column(const char *zTableName, const char *zColName){
  Stmt q = empty_Stmt;
  int rc = 0;
  db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
  while(SQLITE_ROW == db_step(&q)){
    /* Columns: (cid, name, type, notnull, dflt_value, pk) */
    const char *zCol = db_column_text(&q, 1);
    if( 0==fossil_strcmp(zColName, zCol) ){
      rc = 1;
      break;
    }
  }
  db_finalize(&q);
  return rc;
}
1944
1945
1946
1947
1948
1949
1950



1951
1952
1953
1954
1955
1956

1957

1958




1959
1960
1961

1962

1963
1964
1965

1966




1967
1968
1969
1970
1971
1972




1973
1974
1975

1976

1977
1978
1979
1980
1981
1982
1983
** as follows:
**
**       ckout:%s
**
** Where %s is the checkout root.  The value is the repository file.
*/
void db_record_repository_filename(const char *zName){



  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_repository_filename();
  }
  file_canonical_name(zName, &full, 0);

  db_swap_connections();

  db_multi_exec(




     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)

  );

  if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);

    db_multi_exec(




      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );
    db_swap_connections();
    db_optional_sql("repository",




        "REPLACE INTO config(name,value,mtime)"
        "VALUES('ckout:%q',1,now())",
        blob_str(&localRoot)

    );

    blob_reset(&localRoot);
  }else{
    db_swap_connections();
  }
  blob_reset(&full);
}








>
>
>






>

>

>
>
>
>

|
<
>

>



>

>
>
>
>

|
|



>
>
>
>

|
<
>

>







2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
** as follows:
**
**       ckout:%s
**
** Where %s is the checkout root.  The value is the repository file.
*/
void db_record_repository_filename(const char *zName){
  const char *zCollation;
  char *zRepoSetting;
  char *zCkoutSetting;
  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_repository_filename();
  }
  file_canonical_name(zName, &full, 0);
  zCollation = filename_collation();
  db_swap_connections();
  zRepoSetting = mprintf("repo:%q", blob_str(&full));
  db_multi_exec(
     "DELETE FROM global_config WHERE name %s = '%s';",
     zCollation, zRepoSetting
  );
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('%s',1);",

     zRepoSetting
  );
  fossil_free(zRepoSetting);
  if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);
    zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
    db_multi_exec(
       "DELETE FROM global_config WHERE name %s = '%s';",
       zCollation, zCkoutSetting
    );
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('%s','%q');",
      zCkoutSetting, blob_str(&full)
    );
    db_swap_connections();
    db_optional_sql("repository",
        "DELETE FROM config WHERE name %s = '%s';",
        zCollation, zCkoutSetting
    );
    db_optional_sql("repository",
        "REPLACE INTO config(name,value,mtime)"
        "VALUES('%s',1,now());",

        zCkoutSetting
    );
    fossil_free(zCkoutSetting);
    blob_reset(&localRoot);
  }else{
    db_swap_connections();
  }
  blob_reset(&full);
}

2012
2013
2014
2015
2016
2017
2018




2019
2020
2021
2022
2023
2024
2025
  static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };

  url_proxy_options();
  emptyFlag = find_option("empty",0,0)!=0;
  keepFlag = find_option("keep",0,0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  allowNested = find_option("nested",0,0)!=0;




  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local(0) ){
    fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
  }
  db_open_repository(g.argv[2]);







>
>
>
>







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
  static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };

  url_proxy_options();
  emptyFlag = find_option("empty",0,0)!=0;
  keepFlag = find_option("keep",0,0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  allowNested = find_option("nested",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local(0) ){
    fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
  }
  db_open_repository(g.argv[2]);
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(g.argv[2]);
  db_lset_int("checkout", 0);
  oldArgv = g.argv;
  oldArgc = g.argc;
  azNewArgv[0] = g.argv[0];
  g.argv = azNewArgv;
  if( !emptyFlag){
    g.argc = 3;
    if( oldArgc==4 ){
      azNewArgv[g.argc-1] = oldArgv[3];
    }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){
      azNewArgv[g.argc-1] = "--latest";
    }else{
      azNewArgv[g.argc-1] = db_get("main-branch", "trunk");







|







2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(g.argv[2]);
  db_lset_int("checkout", 0);
  oldArgv = g.argv;
  oldArgc = g.argc;
  azNewArgv[0] = g.argv[0];
  g.argv = azNewArgv;
  if( !emptyFlag ){
    g.argc = 3;
    if( oldArgc==4 ){
      azNewArgv[g.argc-1] = oldArgv[3];
    }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){
      azNewArgv[g.argc-1] = "--latest";
    }else{
      azNewArgv[g.argc-1] = db_get("main-branch", "trunk");
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
** width is the length for the edit field on the behavior page, 0
** is used for on/off checkboxes.
** The behaviour page doesn't use a special layout. It lists all
** set-commands and displays the 'set'-help as info.
*/
#if INTERFACE
struct stControlSettings {
  char const *name;     /* Name of the setting */
  char const *var;      /* Internal variable name used by db_set() */
  int width;            /* Width of display.  0 for boolean values. */
  int versionable;      /* Is this setting versionable? */
  int forceTextArea;    /* Force using a text area for display? */
  char const *def;      /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
  { "access-log",       0,              0, 0, 0, "off"                 },
  { "allow-symlinks",   0,              0, 1, 0, "off"                 },
  { "auto-captcha",     "autocaptcha",  0, 0, 0, "on"                  },
  { "auto-hyperlink",   0,              0, 0, 0, "on",                 },
  { "auto-shun",        0,              0, 0, 0, "on"                  },
  { "autosync",         0,              0, 0, 0, "on"                  },

  { "binary-glob",      0,             40, 1, 0, ""                    },
  { "clearsign",        0,              0, 0, 0, "off"                 },
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
    defined(__APPLE__)
  { "case-sensitive",   0,              0, 0, 0, "off"                 },
#else
  { "case-sensitive",   0,              0, 0, 0, "on"                  },







|
|



|









>







2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
** width is the length for the edit field on the behavior page, 0
** is used for on/off checkboxes.
** The behaviour page doesn't use a special layout. It lists all
** set-commands and displays the 'set'-help as info.
*/
#if INTERFACE
struct stControlSettings {
  const char *name;     /* Name of the setting */
  const char *var;      /* Internal variable name used by db_set() */
  int width;            /* Width of display.  0 for boolean values. */
  int versionable;      /* Is this setting versionable? */
  int forceTextArea;    /* Force using a text area for display? */
  const char *def;      /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
  { "access-log",       0,              0, 0, 0, "off"                 },
  { "allow-symlinks",   0,              0, 1, 0, "off"                 },
  { "auto-captcha",     "autocaptcha",  0, 0, 0, "on"                  },
  { "auto-hyperlink",   0,              0, 0, 0, "on",                 },
  { "auto-shun",        0,              0, 0, 0, "on"                  },
  { "autosync",         0,              0, 0, 0, "on"                  },
  { "autosync-tries",   0,             16, 0, 0, "1"                   },
  { "binary-glob",      0,             40, 1, 0, ""                    },
  { "clearsign",        0,              0, 0, 0, "off"                 },
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
    defined(__APPLE__)
  { "case-sensitive",   0,              0, 0, 0, "off"                 },
#else
  { "case-sensitive",   0,              0, 0, 0, "on"                  },
2166
2167
2168
2169
2170
2171
2172
2173
2174






2175
2176
2177
2178
2179
2180
2181
2182
2183
  { "repo-cksum",       0,              0, 0, 0, "on"                  },
  { "self-register",    0,              0, 0, 0, "off"                 },
  { "ssh-command",      0,             40, 0, 0, ""                    },
  { "ssl-ca-location",  0,             40, 0, 0, ""                    },
  { "ssl-identity",     0,             40, 0, 0, ""                    },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",              0,              0, 0, 0, "off"                 },
  { "tcl-setup",        0,             40, 0, 1, ""                    },
#endif






  { "th1-setup",        0,             40, 0, 1, ""                    },
  { "th1-uri-regexp",   0,             40, 0, 0, ""                    },
  { "web-browser",      0,             32, 0, 0, ""                    },
  { "white-foreground", 0,              0, 0, 0, "off"                 },
  { 0,0,0,0,0,0 }
};

/*
** COMMAND: settings







|

>
>
>
>
>
>
|
|







2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
  { "repo-cksum",       0,              0, 0, 0, "on"                  },
  { "self-register",    0,              0, 0, 0, "off"                 },
  { "ssh-command",      0,             40, 0, 0, ""                    },
  { "ssl-ca-location",  0,             40, 0, 0, ""                    },
  { "ssl-identity",     0,             40, 0, 0, ""                    },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",              0,              0, 0, 0, "off"                 },
  { "tcl-setup",        0,             40, 1, 1, ""                    },
#endif
#ifdef FOSSIL_ENABLE_TH1_DOCS
  { "th1-docs",         0,              0, 0, 0, "off"                 },
#endif
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  { "th1-hooks",        0,              0, 0, 0, "off"                 },
#endif
  { "th1-setup",        0,             40, 1, 1, ""                    },
  { "th1-uri-regexp",   0,             40, 1, 0, ""                    },
  { "web-browser",      0,             32, 0, 0, ""                    },
  { "white-foreground", 0,              0, 0, 0, "off"                 },
  { 0,0,0,0,0,0 }
};

/*
** COMMAND: settings
2219
2220
2221
2222
2223
2224
2225





2226
2227
2228
2229
2230
2231
2232
**                     Default: on
**
**    autosync         If enabled, automatically pull prior to commit
**                     or update and automatically push after commit or
**                     tag or branch creation.  If the value is "pullonly"
**                     then only pull operations occur automatically.
**                     Default: on





**
**    binary-glob      The VALUE is a comma or newline-separated list of
**     (versionable)   GLOB patterns that should be treated as binary files
**                     for committing and merging purposes.  Example: *.jpg
**
**    case-sensitive   If TRUE, the files whose names differ only in case
**                     are considered distinct.  If FALSE files whose names







>
>
>
>
>







2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
**                     Default: on
**
**    autosync         If enabled, automatically pull prior to commit
**                     or update and automatically push after commit or
**                     tag or branch creation.  If the value is "pullonly"
**                     then only pull operations occur automatically.
**                     Default: on
**
**    autosync-tries   If autosync is enabled setting this to a value greater
**                     than zero will cause autosync to try no more than this
**                     number of attempts if there is a sync failure.
**                     Default: 1
**
**    binary-glob      The VALUE is a comma or newline-separated list of
**     (versionable)   GLOB patterns that should be treated as binary files
**                     for committing and merging purposes.  Example: *.jpg
**
**    case-sensitive   If TRUE, the files whose names differ only in case
**                     are considered distinct.  If FALSE files whose names
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376














2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
**                     Tcl integration commands will be added to the TH1
**                     interpreter, allowing arbitrary Tcl expressions and
**                     scripts to be evaluated from TH1.  Additionally, the Tcl
**                     interpreter will be able to evaluate arbitrary TH1
**                     expressions and scripts. Default: off.
**
**    tcl-setup        This is the setup script to be evaluated after creating
**                     and initializing the Tcl interpreter.  By default, this
**                     is empty and no extra setup is performed.
**














**    th1-setup        This is the setup script to be evaluated after creating
**                     and initializing the TH1 interpreter.  By default, this
**                     is empty and no extra setup is performed.
**
**    th1-uri-regexp   Specify which URI's are allowed in HTTP requests from
**                     TH1 scripts.  If empty, no HTTP requests are allowed
**                     whatsoever.  The default is an empty string.
**
**    web-browser      A shell command used to launch your preferred
**                     web browser when given a URL as an argument.
**                     Defaults to "start" on windows, "open" on Mac,
**                     and "firefox" on Unix.
**







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



|







2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
**                     Tcl integration commands will be added to the TH1
**                     interpreter, allowing arbitrary Tcl expressions and
**                     scripts to be evaluated from TH1.  Additionally, the Tcl
**                     interpreter will be able to evaluate arbitrary TH1
**                     expressions and scripts. Default: off.
**
**    tcl-setup        This is the setup script to be evaluated after creating
**     (versionable)   and initializing the Tcl interpreter.  By default, this
**                     is empty and no extra setup is performed.
**
**    th1-docs         WARNING: If enabled (and Fossil was compiled with TH1
**                     support for embedded documentation files), this allows
**                     embedded documentation files to contain arbitrary TH1
**                     scripts that are evaluated on the server.  If native
**                     Tcl integration is also enabled, this setting has the
**                     potential to allow anybody with check-in privileges to
**                     do almost anything that the associated operating system
**                     user account could do.  Extreme caution should be used
**                     when enabling this setting.  Default: off.
**
**    th1-hooks        If enabled (and Fossil was compiled with support for TH1
**                     hooks), special TH1 commands will be called before and
**                     after any Fossil command or web page. Default: off.
**
**    th1-setup        This is the setup script to be evaluated after creating
**     (versionable)   and initializing the TH1 interpreter.  By default, this
**                     is empty and no extra setup is performed.
**
**    th1-uri-regexp   Specify which URI's are allowed in HTTP requests from
**     (versionable)   TH1 scripts.  If empty, no HTTP requests are allowed
**                     whatsoever.  The default is an empty string.
**
**    web-browser      A shell command used to launch your preferred
**                     web browser when given a URL as an argument.
**                     Defaults to "start" on windows, "open" on Mac,
**                     and "firefox" on Unix.
**
2422
2423
2424
2425
2426
2427
2428















2429
2430
2431
2432


2433
2434



2435


2436
2437
2438
2439
2440
2441
2442
    if( !ctrlSettings[i].name ){
      fossil_fatal("no such setting: %s", zName);
    }
    isManifest = fossil_strcmp(ctrlSettings[i].name, "manifest")==0;
    if( isManifest && globalFlag ){
      fossil_fatal("cannot set 'manifest' globally");
    }















    if( unsetFlag ){
      db_unset(ctrlSettings[i].name, globalFlag);
    }else if( g.argc==4 ){
      db_set(ctrlSettings[i].name, g.argv[3], globalFlag);


    }else{
      isManifest = 0;



      print_setting(&ctrlSettings[i], db_open_local(0));


    }
    if( isManifest && g.localOpen ){
      manifest_to_disk(db_lget_int("checkout", 0));
    }
  }else{
    usage("?PROPERTY? ?VALUE? ?-global?");
  }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>
>


>
>
>
|
>
>







2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
    if( !ctrlSettings[i].name ){
      fossil_fatal("no such setting: %s", zName);
    }
    isManifest = fossil_strcmp(ctrlSettings[i].name, "manifest")==0;
    if( isManifest && globalFlag ){
      fossil_fatal("cannot set 'manifest' globally");
    }
    if( unsetFlag || g.argc==4 ){
      if( ctrlSettings[i+1].name
       && strncmp(ctrlSettings[i+1].name, zName, n)==0
       && ctrlSettings[i].name[n]!=0
      ){
        fossil_print("ambiguous property prefix: %s\nMatching properties:\n",
                     zName);
        while( ctrlSettings[i].name
            && strncmp(ctrlSettings[i].name, zName, n)==0
        ){
          fossil_print("%s\n", ctrlSettings[i].name);
          i++;
        }
        fossil_exit(1);
      }else{
        if( unsetFlag ){
          db_unset(ctrlSettings[i].name, globalFlag);
        }else{
          db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
        }
      }
    }else{
      isManifest = 0;
      while( ctrlSettings[i].name
            && strncmp(ctrlSettings[i].name, zName, n)==0
      ){
        print_setting(&ctrlSettings[i], db_open_local(0));
        i++;
      }
    }
    if( isManifest && g.localOpen ){
      manifest_to_disk(db_lget_int("checkout", 0));
    }
  }else{
    usage("?PROPERTY? ?VALUE? ?-global?");
  }
Changes to src/descendants.c.
128
129
130
131
132
133
134





135
136
137
138
139
140
141
      }
    }
    db_finalize(&ins);
    db_finalize(&isBr);
    db_finalize(&q1);
    bag_clear(&pending);
    bag_clear(&seen);





  }
  if( closeMode==1 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"
      "    WHERE tagxref.rid=leaves.rid "
      "      AND tagxref.tagid=%d"







>
>
>
>
>







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
      }
    }
    db_finalize(&ins);
    db_finalize(&isBr);
    db_finalize(&q1);
    bag_clear(&pending);
    bag_clear(&seen);
  }else{
    db_multi_exec(
      "INSERT INTO leaves"
      "  SELECT leaf.rid FROM leaf"
    );
  }
  if( closeMode==1 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"
      "    WHERE tagxref.rid=leaves.rid "
      "      AND tagxref.tagid=%d"
325
326
327
328
329
330
331



332
333
334
335
336
337

338
339













340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
**
** Find all leaf descendants of the baseline specified or if the argument
** is omitted, of the baseline currently checked out.
**
** Options:
**    -R|--repository FILE       Extract info from repository FILE



**
** See also: finfo, info, leaves
*/
void descendants_cmd(void){
  Stmt q;
  int base;


  db_find_and_open_repository(0,0);













  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_typed_rid(g.argv[2], "ci");
  }
  if( base==0 ) return;
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, -20, 79, 0);
  db_finalize(&q);
}

/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?
**
** Find leaves of all branches.  By default show only open leaves.
** The -a|--all flag causes all leaves (closed and open) to be shown.
** The -c|--closed flag shows only closed leaves.
**
** The --recompute flag causes the content of the "leaf" table in the
** repository database to be recomputed.
**
** Options:
**   -a|--all         show ALL leaves
**   -c|--closed      show only closed leaves
**   --bybranch       order output by branch name
**   --recompute      recompute the "leaf" table in the repository DB
**   -W|--width <num> With of lines (default 79). Must be >39 or 0

**                    (= no limit, resulting in a single line per entry).
**
** See also: descendants, finfo, info, branch
*/
void leaves_cmd(void){
  Stmt q;
  Blob sql;
  int showAll = find_option("all", "a", 0)!=0;







>
>
>





|
>


>
>
>
>
>
>
>
>
>
>
>
>
>













|




















|
>
|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
**
** Find all leaf descendants of the baseline specified or if the argument
** is omitted, of the baseline currently checked out.
**
** Options:
**    -R|--repository FILE       Extract info from repository FILE
**    -W|--width <num>           Width of lines (default is to auto-detect).
**                               Must be >20 or 0 (= no limit, resulting in a
**                               single line per entry).
**
** See also: finfo, info, leaves
*/
void descendants_cmd(void){
  Stmt q;
  int base, width;
  const char *zWidth;

  db_find_and_open_repository(0,0);
  zWidth = find_option("width","W",1);
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = -1;
  }

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_typed_rid(g.argv[2], "ci");
  }
  if( base==0 ) return;
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, -20, width, 0);
  db_finalize(&q);
}

/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?
**
** Find leaves of all branches.  By default show only open leaves.
** The -a|--all flag causes all leaves (closed and open) to be shown.
** The -c|--closed flag shows only closed leaves.
**
** The --recompute flag causes the content of the "leaf" table in the
** repository database to be recomputed.
**
** Options:
**   -a|--all         show ALL leaves
**   -c|--closed      show only closed leaves
**   --bybranch       order output by branch name
**   --recompute      recompute the "leaf" table in the repository DB
**   -W|--width <num> Width of lines (default is to auto-detect). Must be
**                    >39 or 0 (= no limit, resulting in a single line per
**                    entry).
**
** See also: descendants, finfo, info, branch
*/
void leaves_cmd(void){
  Stmt q;
  Blob sql;
  int showAll = find_option("all", "a", 0)!=0;
390
391
392
393
394
395
396
397
398
399




400
401
402
403
404
405
406

  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=39) ){
      fossil_fatal("-W|--width value must be >39 or 0");
    }
  }else{
    width = 79;
  }
  db_find_and_open_repository(0,0);




  if( recomputeFlag ) leaf_rebuild();
  blob_zero(&sql);
  blob_append(&sql, timeline_query_for_tty(), -1);
  blob_appendf(&sql, " AND blob.rid IN leaf");
  if( showClosed ){
    blob_appendf(&sql," AND %z", leaf_is_closed_sql("blob.rid"));
  }else if( !showAll ){







|


>
>
>
>







413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=39) ){
      fossil_fatal("-W|--width value must be >39 or 0");
    }
  }else{
    width = -1;
  }
  db_find_and_open_repository(0,0);
  
  /* We should be done with options.. */
  verify_all_options();

  if( recomputeFlag ) leaf_rebuild();
  blob_zero(&sql);
  blob_append(&sql, timeline_query_for_tty(), -1);
  blob_appendf(&sql, " AND blob.rid IN leaf");
  if( showClosed ){
    blob_appendf(&sql," AND %z", leaf_is_closed_sql("blob.rid"));
  }else if( !showAll ){
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
      fossil_print("*** %s ***\n", zBr);
      fossil_free(zLastBr);
      zLastBr = fossil_strdup(zBr);
    }
    n++;
    sqlite3_snprintf(sizeof(zLineNo), zLineNo, "(%d)", n);
    fossil_print("%6s ", zLineNo);
    z = mprintf("%s [%.10s] %s", zDate, zId, zCom);
    comment_print(z, 7, width);
    fossil_free(z);
  }
  fossil_free(zLastBr);
  db_finalize(&q);
}

/*







|
|







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
      fossil_print("*** %s ***\n", zBr);
      fossil_free(zLastBr);
      zLastBr = fossil_strdup(zBr);
    }
    n++;
    sqlite3_snprintf(sizeof(zLineNo), zLineNo, "(%d)", n);
    fossil_print("%6s ", zLineNo);
    z = mprintf("%s [%S] %s", zDate, zId, zCom);
    comment_print(z, zCom, 7, width, g.comFmtFlags);
    fossil_free(z);
  }
  fossil_free(zLastBr);
  db_finalize(&q);
}

/*
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
    if( usesFlags & USESFILE_DELETE ){
      db_bind_int(&ins, ":rid", mid);
      db_step(&ins);
      db_reset(&ins);
    }
  }
  db_finalize(&q);
  db_prepare(&q, "SELECT cid FROM plink WHERE pid=:rid");

  while( (rid = bag_first(&pending))!=0 ){
    bag_remove(&pending, rid);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int mid = db_column_int(&q, 0);
      if( bag_find(&seen, mid) ) continue;







|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
    if( usesFlags & USESFILE_DELETE ){
      db_bind_int(&ins, ":rid", mid);
      db_step(&ins);
      db_reset(&ins);
    }
  }
  db_finalize(&q);
  db_prepare(&q, "SELECT cid FROM plink WHERE pid=:rid AND isprim");

  while( (rid = bag_first(&pending))!=0 ){
    bag_remove(&pending, rid);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int mid = db_column_int(&q, 0);
      if( bag_find(&seen, mid) ) continue;
Changes to src/diff.c.
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){
  blob_appendf(pOut,
    "<td><div class=\"diff%scol\">\n"
    "<pre>\n"
    "%s"
    "</pre>\n"
    "</div></td>\n",
    col % 3 ? (col == SBS_MKR ? "mkr" : "txt") : "ln",
    blob_str(pCol)
  );
}

/*
** Append a separator line to column iCol
*/







|







592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){
  blob_appendf(pOut,
    "<td><div class=\"diff%scol\">\n"
    "<pre>\n"
    "%s"
    "</pre>\n"
    "</div></td>\n",
    (col % 3) ? (col == SBS_MKR ? "mkr" : "txt") : "ln",
    blob_str(pCol)
  );
}

/*
** Append a separator line to column iCol
*/
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325

  if( showLog ){
    char *zLink = href("%R/finfo?name=%t&ci=%s",zFilename,zCI);
    @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
    @ <ol>
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
      @ check-in %z(href("%R/info/%s",p->zMUuid))%.10s(p->zMUuid)</a>
      @ artifact %z(href("%R/artifact/%s",p->zFUuid))%.10s(p->zFUuid)</a>
      @ </span>
#if 0
      if( i>0 ){
        char *zLink = xhref("target='infowindow'",
                            "%R/fdiff?v1=%S&v2=%S&sbs=1",
                            p->zFUuid,ann.aVers[0].zFUuid);
        @ %z(zLink)[diff-to-top]</a>







|
|







2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325

  if( showLog ){
    char *zLink = href("%R/finfo?name=%t&ci=%s",zFilename,zCI);
    @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
    @ <ol>
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
      @ check-in %z(href("%R/info/%s",p->zMUuid))%S(p->zMUuid)</a>
      @ artifact %z(href("%R/artifact/%s",p->zFUuid))%S(p->zFUuid)</a>
      @ </span>
#if 0
      if( i>0 ){
        char *zLink = xhref("target='infowindow'",
                            "%R/fdiff?v1=%S&v2=%S&sbs=1",
                            p->zFUuid,ann.aVers[0].zFUuid);
        @ %z(zLink)[diff-to-top]</a>
2432
2433
2434
2435
2436
2437
2438




2439
2440
2441
2442
2443
2444
2445
    annFlags = DIFF_IGNORE_EOLWS;
  }
  if( find_option("ignore-all-space","w",0)!=0 ){
    annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
  }
  fileVers = find_option("filevers",0,0)!=0;
  db_must_be_within_tree();




  if( g.argc<3 ) {
    usage("FILENAME");
  }
  file_tree_name(g.argv[2], &treename, 1);
  zFilename = blob_str(&treename);
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
  if( fnid==0 ){







>
>
>
>







2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
    annFlags = DIFF_IGNORE_EOLWS;
  }
  if( find_option("ignore-all-space","w",0)!=0 ){
    annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
  }
  fileVers = find_option("filevers",0,0)!=0;
  db_must_be_within_tree();
 
  /* We should be done with options.. */
  verify_all_options();

  if( g.argc<3 ) {
    usage("FILENAME");
  }
  file_tree_name(g.argv[2], &treename, 1);
  zFilename = blob_str(&treename);
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
  if( fnid==0 ){
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
    fossil_fatal("unable to find manifest");
  }
  annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR);
  annotate_file(&ann, fnid, mid, iLimit, annFlags);
  if( showLog ){
    struct AnnVers *p;
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      fossil_print("version %3d: %s %.10s file %.10s\n",
                   i+1, p->zDate, p->zMUuid, p->zFUuid);
    }
    fossil_print("---------------------------------------------------\n");
  }
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;
    struct AnnVers *p;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
    p = ann.aVers + iVers;
    if( bBlame ){
      if( iVers>=0 ){
        fossil_print("%.10s %s %13.13s: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
      }else{
        fossil_print("%35s  %.*s\n", "", n, z);
      }
    }else{
      if( iVers>=0 ){
        fossil_print("%.10s %s %5d: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
      }else{
        fossil_print("%21s %5d: %.*s\n",
             "", i+1, n, z);
      }
    }
  }
}







|













|






|








2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
    fossil_fatal("unable to find manifest");
  }
  annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR);
  annotate_file(&ann, fnid, mid, iLimit, annFlags);
  if( showLog ){
    struct AnnVers *p;
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      fossil_print("version %3d: %s %S file %S\n",
                   i+1, p->zDate, p->zMUuid, p->zFUuid);
    }
    fossil_print("---------------------------------------------------\n");
  }
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;
    struct AnnVers *p;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
    p = ann.aVers + iVers;
    if( bBlame ){
      if( iVers>=0 ){
        fossil_print("%S %s %13.13s: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
      }else{
        fossil_print("%35s  %.*s\n", "", n, z);
      }
    }else{
      if( iVers>=0 ){
        fossil_print("%S %s %5d: %.*s\n",
             fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
      }else{
        fossil_print("%21s %5d: %.*s\n",
             "", i+1, n, z);
      }
    }
  }
}
Changes to src/diffcmd.c.
26
27
28
29
30
31
32





33
34
35
36
37
38
39
*/
#if defined(_WIN32)
#  define NULL_DEVICE "NUL"
#else
#  define NULL_DEVICE "/dev/null"
#endif






/*
** Print the "Index:" message that patches wants to see at the top of a diff.
*/
void diff_print_index(const char *zFile, u64 diffFlags){
  if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
    char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
    fossil_print("%s", z);







>
>
>
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
*/
#if defined(_WIN32)
#  define NULL_DEVICE "NUL"
#else
#  define NULL_DEVICE "/dev/null"
#endif

/*
** Used when the name for the diff is unknown.
*/
#define DIFF_NO_NAME  "(unknown)"

/*
** Print the "Index:" message that patches wants to see at the top of a diff.
*/
void diff_print_index(const char *zFile, u64 diffFlags){
  if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
    char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
    fossil_print("%s", z);
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3);
    int srcid = db_column_int(&q, 4);
    int isLink = db_column_int(&q, 5);
    char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
    char *zToFree = zFullName;
    int showDiff = 1;
    if( isDeleted ){
      fossil_print("DELETED  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
    }else if( file_access(zFullName, F_OK) ){
      fossil_print("MISSING  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; }







|
|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3);
    int srcid = db_column_int(&q, 4);
    int isLink = db_column_int(&q, 5);
    char *zToFree = mprintf("%s%s", g.zLocalRoot, zPathname);
    const char *zFullName = zToFree;
    int showDiff = 1;
    if( isDeleted ){
      fossil_print("DELETED  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
    }else if( file_access(zFullName, F_OK) ){
      fossil_print("MISSING  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; }
487
488
489
490
491
492
493
494







495
496
497
498
499
500
501
  const char *zBinGlob,
  int fIncludeBinary,
  u64 diffFlags
){
  Blob f1, f2;
  int isBin1, isBin2;
  int rid;
  const char *zName =  pFrom ? pFrom->zName : pTo->zName;







  if( diffFlags & DIFF_BRIEF ) return;
  diff_print_index(zName, diffFlags);
  if( pFrom ){
    rid = uuid_to_rid(pFrom->zUuid, 0);
    content_get(rid, &f1);
  }else{
    blob_zero(&f1);







|
>
>
>
>
>
>
>







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  const char *zBinGlob,
  int fIncludeBinary,
  u64 diffFlags
){
  Blob f1, f2;
  int isBin1, isBin2;
  int rid;
  const char *zName;
  if( pFrom ){
    zName = pFrom->zName;
  }else if( pTo ){
    zName = pTo->zName;
  }else{
    zName = DIFF_NO_NAME;
  }
  if( diffFlags & DIFF_BRIEF ) return;
  diff_print_index(zName, diffFlags);
  if( pFrom ){
    rid = uuid_to_rid(pFrom->zUuid, 0);
    content_get(rid, &f1);
  }else{
    blob_zero(&f1);
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  if( zTempFile ){
    blob_write_to_file(&script, zTempFile);
    fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
  }else{
#if defined(FOSSIL_ENABLE_TCL)
    Th_FossilInit(TH_INIT_DEFAULT);
    if( evaluateTclWithEvents(g.interp, &g.tcl, blob_str(&script),
                              blob_size(&script), 1)==TCL_OK ){
      blob_reset(&script);
      return;
    }
    /*
     * If evaluation of the Tcl script fails, the reason may be that Tk
     * could not be found by the loaded Tcl, or that Tcl cannot be loaded
     * dynamically (e.g. x64 Tcl with x86 Fossil).  Therefore, fallback







|







1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
  if( zTempFile ){
    blob_write_to_file(&script, zTempFile);
    fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
  }else{
#if defined(FOSSIL_ENABLE_TCL)
    Th_FossilInit(TH_INIT_DEFAULT);
    if( evaluateTclWithEvents(g.interp, &g.tcl, blob_str(&script),
                              blob_size(&script), 1, 0)==TCL_OK ){
      blob_reset(&script);
      return;
    }
    /*
     * If evaluation of the Tcl script fails, the reason may be that Tk
     * could not be found by the loaded Tcl, or that Tcl cannot be loaded
     * dynamically (e.g. x64 Tcl with x86 Fossil).  Therefore, fallback
Changes to src/doc.c.
254
255
256
257
258
259
260

261
262
263
264
265
266
267
    { "t",          1, "application/x-troff"               },
    { "tar",        3, "application/x-tar"                 },
    { "tcl",        3, "application/x-tcl"                 },
    { "tex",        3, "application/x-tex"                 },
    { "texi",       4, "application/x-texinfo"             },
    { "texinfo",    7, "application/x-texinfo"             },
    { "tgz",        3, "application/x-tar-gz"              },

    { "tif",        3, "image/tiff"                        },
    { "tiff",       4, "image/tiff"                        },
    { "tr",         2, "application/x-troff"               },
    { "tsi",        3, "audio/TSP-audio"                   },
    { "tsp",        3, "application/dsptype"               },
    { "tsv",        3, "text/tab-separated-values"         },
    { "txt",        3, "text/plain"                        },







>







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    { "t",          1, "application/x-troff"               },
    { "tar",        3, "application/x-tar"                 },
    { "tcl",        3, "application/x-tcl"                 },
    { "tex",        3, "application/x-tex"                 },
    { "texi",       4, "application/x-texinfo"             },
    { "texinfo",    7, "application/x-texinfo"             },
    { "tgz",        3, "application/x-tar-gz"              },
    { "th1",        3, "application/x-th1"                 },
    { "tif",        3, "image/tiff"                        },
    { "tiff",       4, "image/tiff"                        },
    { "tr",         2, "application/x-troff"               },
    { "tsi",        3, "audio/TSP-audio"                   },
    { "tsp",        3, "application/dsptype"               },
    { "tsv",        3, "text/tab-separated-values"         },
    { "txt",        3, "text/plain"                        },
522
523
524
525
526
527
528









529
530
531
532
533
534
535
    style_footer();
  }else if( fossil_strcmp(zMime, "text/plain")==0 ){
    style_header("Documentation");
    @ <blockquote><pre>
    @ %h(blob_str(&filebody))
    @ </pre></blockquote>
    style_footer();









  }else{
    cgi_set_content_type(zMime);
    cgi_set_content(&filebody);
  }
  return;

doc_not_found:







>
>
>
>
>
>
>
>
>







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
    style_footer();
  }else if( fossil_strcmp(zMime, "text/plain")==0 ){
    style_header("Documentation");
    @ <blockquote><pre>
    @ %h(blob_str(&filebody))
    @ </pre></blockquote>
    style_footer();
#ifdef FOSSIL_ENABLE_TH1_DOCS
  }else if( db_get_boolean("th1-docs", 0) &&
            fossil_strcmp(zMime, "application/x-th1")==0 ){
    char *zHtml = htmlize(zName, -1);
    style_header(zHtml);
    Th_Render(blob_str(&filebody));
    style_footer();
    fossil_free(zHtml);
#endif
  }else{
    cgi_set_content_type(zMime);
    cgi_set_content(&filebody);
  }
  return;

doc_not_found:
Changes to src/file.c.
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
**                        a boolean: "yes", "no", "true", "false", etc.
*/
void cmd_test_tree_name(void){
  int i;
  Blob x;
  db_find_and_open_repository(0,0);
  blob_zero(&x);
  capture_case_sensitive_option();
  for(i=2; i<g.argc; i++){
    if( file_tree_name(g.argv[i], &x, 1) ){
      fossil_print("%s\n", blob_buffer(&x));
      blob_reset(&x);
    }
  }
}







<







1100
1101
1102
1103
1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
**                        a boolean: "yes", "no", "true", "false", etc.
*/
void cmd_test_tree_name(void){
  int i;
  Blob x;
  db_find_and_open_repository(0,0);
  blob_zero(&x);

  for(i=2; i<g.argc; i++){
    if( file_tree_name(g.argv[i], &x, 1) ){
      fossil_print("%s\n", blob_buffer(&x));
      blob_reset(&x);
    }
  }
}
Changes to src/finfo.c.
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66



67
68
69
70
71
72
73
**   -l|--log             select log mode (the default)
**   -n|--limit N         display the first N changes. N=0 means no limit.
**   --offset P           skip P changes
**   -p|--print           select print mode
**   -r|--revision R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s|--status          select status mode (print a status indicator for FILE)
**   -W|--width <num>     With of lines (default 79). Must be >22 or 0

**                        (= no limit, resulting in a single line per entry).
**
** See also: artifact, cat, descendants, info, leaves
*/
void finfo_cmd(void){
  capture_case_sensitive_option();
  db_must_be_within_tree();
  if( find_option("status","s",0) ){
    Stmt q;
    Blob line;
    Blob fname;
    int vid;




    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_fatal("no checkout to finfo files in");
    }
    vfile_check_signature(vid, CKSIG_ENOTFILE);







|
>
|




<






>
>
>







47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
**   -l|--log             select log mode (the default)
**   -n|--limit N         display the first N changes. N=0 means no limit.
**   --offset P           skip P changes
**   -p|--print           select print mode
**   -r|--revision R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s|--status          select status mode (print a status indicator for FILE)
**   -W|--width <num>     Width of lines (default is to auto-detect). Must be
**                        >22 or 0 (= no limit, resulting in a single line per
**                        entry).
**
** See also: artifact, cat, descendants, info, leaves
*/
void finfo_cmd(void){

  db_must_be_within_tree();
  if( find_option("status","s",0) ){
    Stmt q;
    Blob line;
    Blob fname;
    int vid;

    /* We should be done with options.. */
    verify_all_options();

    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_fatal("no checkout to finfo files in");
    }
    vfile_check_signature(vid, CKSIG_ENOTFILE);
112
113
114
115
116
117
118



119
120
121
122
123
124
125
    fossil_print("%s\n", blob_str(&line));
    blob_reset(&fname);
    blob_reset(&line);
  }else if( find_option("print","p",0) ){
    Blob record;
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);




    file_tree_name(g.argv[2], &fname, 1);
    if( zRevision ){
      historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                       &fname, filename_collation());







>
>
>







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
    fossil_print("%s\n", blob_str(&line));
    blob_reset(&fname);
    blob_reset(&line);
  }else if( find_option("print","p",0) ){
    Blob record;
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);

    /* We should be done with options.. */
    verify_all_options();

    file_tree_name(g.argv[2], &fname, 1);
    if( zRevision ){
      historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                       &fname, filename_collation());
144
145
146
147
148
149
150
151
152
153
154


155
156
157







158
159
160
161
162
163
164

    if( find_option("log","l",0) ){
      /* this is the default, no-op */
    }
    zLimit = find_option("limit","n",1);
    zWidth = find_option("width","W",1);
    iLimit = zLimit ? atoi(zLimit) : -1;
    iWidth = zWidth ? atoi(zWidth) : 79;
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);


    if( (iWidth!=0) && (iWidth<=22) ){
      fossil_fatal("-W|--width value must be >22 or 0");
    }







    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
    if( rid==0 ){







<



>
>
|
|
|
>
>
>
>
>
>
>







150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

    if( find_option("log","l",0) ){
      /* this is the default, no-op */
    }
    zLimit = find_option("limit","n",1);
    zWidth = find_option("width","W",1);
    iLimit = zLimit ? atoi(zLimit) : -1;

    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( zWidth ){
      iWidth = atoi(zWidth);
      if( (iWidth!=0) && (iWidth<=22) ){
        fossil_fatal("-W|--width value must be >22 or 0");
      }
    }else{
      iWidth = -1;
    }

    /* We should be done with options.. */
    verify_all_options();

    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
    if( rid==0 ){
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
      const char *zCom = db_column_text(&q, 3);
      const char *zUser = db_column_text(&q, 4);
      const char *zBr = db_column_text(&q, 5);
      char *zOut;
      if( zBr==0 ) zBr = "trunk";
      if( iBrief ){
        fossil_print("%s ", zDate);
        zOut = sqlite3_mprintf(
           "[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)",
           zCiUuid, zCom, zUser, zFileUuid, zBr);
        comment_print(zOut, 11, iWidth);
        sqlite3_free(zOut);
      }else{
        blob_reset(&line);
        blob_appendf(&line, "%.10s ", zCiUuid);
        blob_appendf(&line, "%.10s ", zDate);
        blob_appendf(&line, "%8.8s ", zUser);
        blob_appendf(&line, "%8.8s ", zBr);
        blob_appendf(&line,"%-39.39s", zCom );
        comment_print(blob_str(&line), 0, iWidth);
      }
    }
    db_finalize(&q);
    blob_reset(&fname);
  }
}








|
|

|
|







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
      const char *zCom = db_column_text(&q, 3);
      const char *zUser = db_column_text(&q, 4);
      const char *zBr = db_column_text(&q, 5);
      char *zOut;
      if( zBr==0 ) zBr = "trunk";
      if( iBrief ){
        fossil_print("%s ", zDate);
        zOut = mprintf(
           "[%S] %s (user: %s, artifact: [%S], branch: %s)",
           zCiUuid, zCom, zUser, zFileUuid, zBr);
        comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
        fossil_free(zOut);
      }else{
        blob_reset(&line);
        blob_appendf(&line, "%.10s ", zCiUuid);
        blob_appendf(&line, "%.10s ", zDate);
        blob_appendf(&line, "%8.8s ", zUser);
        blob_appendf(&line, "%8.8s ", zBr);
        blob_appendf(&line,"%-39.39s", zCom );
        comment_print(blob_str(&line), zCom, 0, iWidth, g.comFmtFlags);
      }
    }
    db_finalize(&q);
    blob_reset(&fname);
  }
}

234
235
236
237
238
239
240




241
242
243
244
245
246
247
void cat_cmd(void){
  int i;
  int rc;
  Blob content, fname;
  const char *zRev;
  db_find_and_open_repository(0, 0);
  zRev = find_option("r","r",1);




  for(i=2; i<g.argc; i++){
    file_tree_name(g.argv[i], &fname, 1);
    blob_zero(&content);
    rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,0);
    if( rc==0 ){
      fossil_fatal("no such file: %s", g.argv[i]);
    }







>
>
>
>







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
void cat_cmd(void){
  int i;
  int rc;
  Blob content, fname;
  const char *zRev;
  db_find_and_open_repository(0, 0);
  zRev = find_option("r","r",1);
  
  /* We should be done with options.. */
  verify_all_options();

  for(i=2; i<g.argc; i++){
    file_tree_name(g.argv[i], &fname, 1);
    blob_zero(&content);
    rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,0);
    if( rc==0 ){
      fossil_fatal("no such file: %s", g.argv[i]);
    }
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  blob_reset(&sql);
  blob_zero(&title);
  if( baseCheckin ){
    char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
    char *zLink = href("%R/info/%s", zUuid);
    blob_appendf(&title, "Ancestors of file ");
    hyperlinked_path(zFilename, &title, zUuid, "tree", "");
    blob_appendf(&title, " from check-in %z%.10s</a>", zLink, zUuid);
    fossil_free(zUuid);
  }else{
    blob_appendf(&title, "History of files named ");
    hyperlinked_path(zFilename, &title, 0, "tree", "");
  }
  @ <h2>%b(&title)</h2>
  blob_reset(&title);







|







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  blob_reset(&sql);
  blob_zero(&title);
  if( baseCheckin ){
    char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
    char *zLink = href("%R/info/%s", zUuid);
    blob_appendf(&title, "Ancestors of file ");
    hyperlinked_path(zFilename, &title, zUuid, "tree", "");
    blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
    fossil_free(zUuid);
  }else{
    blob_appendf(&title, "History of files named ");
    hyperlinked_path(zFilename, &title, 0, "tree", "");
  }
  @ <h2>%b(&title)</h2>
  blob_reset(&title);
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
    if( uBg ){
      zBgClr = hash_color(zUser);
    }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
      zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
    }
    gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,
                         zUuid, 0);
    if( memcmp(zDate, zPrevDate, 10) ){
      sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
      @ <tr><td>
      @   <div class="divider">%s(zPrevDate)</div>
      @ </td><td></td><td></td></tr>
    }
    memcpy(zTime, &zDate[11], 5);
    zTime[5] = 0;







|







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
    if( uBg ){
      zBgClr = hash_color(zUser);
    }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
      zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
    }
    gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,
                         zUuid, 0);
    if( strncmp(zDate, zPrevDate, 10) ){
      sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
      @ <tr><td>
      @   <div class="divider">%s(zPrevDate)</div>
      @ </td><td></td><td></td></tr>
    }
    memcpy(zTime, &zDate[11], 5);
    zTime[5] = 0;
Added src/fusefs.c.


















































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
** Copyright (c) 2014 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@sqlite.org
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This module implements the userspace side of a Fuse Filesystem that
** contains all check-ins for a fossil repository.  
**
** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS.
** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for
** the Fuse Filesystem, of course.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include "fusefs.h"
#ifdef FOSSIL_HAVE_FUSEFS

#define FUSE_USE_VERSION 26
#include <fuse.h>

/*
** Global state information about the archive
*/
static struct sGlobal {
  /* A cache of a single check-in manifest */
  int rid;                  /* rid for the cached manifest */
  char *zSymName;           /* Symbolic name corresponding to rid */
  Manifest *pMan;           /* The cached manifest */
  /* A cache of a single file within a single check-in */
  int iFileRid;             /* Check-in ID for the cached file */
  ManifestFile *pFile;      /* Name of a cached file */
  Blob content;             /* Content of the cached file */
  /* Parsed path */
  char *az[3];              /* 0=type, 1=id, 2=path */
} fusefs;

/*
** Clear the fusefs.sz[] array.
*/
static void fusefs_clear_path(void){
  int i;
  for(i=0; i<count(fusefs.az); i++){
    fossil_free(fusefs.az[i]);
    fusefs.az[i] = 0;
  }
}

/*
** Split of the input path into 0, 1, 2, or 3 elements in fusefs.az[].
** Return the number of elements.
**
** Any prior path parse is deleted.
*/
static int fusefs_parse_path(const char *zPath){
  int i, j;
  fusefs_clear_path();
  if( strcmp(zPath,"/")==0 ) return 0;
  for(i=0, j=1; i<2 && zPath[j]; i++){
    int jStart = j;
    while( zPath[j] && zPath[j]!='/' ){ j++; }
    fusefs.az[i] = mprintf("%.*s", j-jStart, &zPath[jStart]);
    if( zPath[j] ) j++;
  }
  if( zPath[j] ) fusefs.az[i++] = fossil_strdup(&zPath[j]);
  return i;
}

/*
** Reclaim memory used by the fusefs local variable.
*/
static void fusefs_reset(void){
  blob_reset(&fusefs.content);
  manifest_destroy(fusefs.pMan);
  fusefs.pMan = 0;
  fossil_free(fusefs.zSymName);
  fusefs.zSymName = 0;
  fusefs.pFile = 0;
}

/*
** Load manifest rid into the cache.
*/
static void fusefs_load_rid(int rid, const char *zSymName){
  if( fusefs.rid==rid && fusefs.pMan!=0 ) return;
  fusefs_reset();
  fusefs.zSymName = fossil_strdup(zSymName);
  fusefs.pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
  fusefs.rid = rid;
}

/*
** Locate the rid corresponding to a symbolic name
*/
static int fusefs_name_to_rid(const char *zSymName){
  if( fusefs.rid>0 && strcmp(zSymName, fusefs.zSymName)==0 ){
    return fusefs.rid;
  }else{
    return symbolic_name_to_rid(zSymName, "ci");
  }
}


/*
** Implementation of stat()
*/
static int fusefs_getattr(const char *zPath, struct stat *stbuf){
  int n, rid;
  ManifestFile *pFile;
  char *zDir;
  stbuf->st_uid = getuid();
  stbuf->st_gid = getgid();
  n = fusefs_parse_path(zPath);
  if( n==0 ){
    stbuf->st_mode = S_IFDIR | 0555;
    stbuf->st_nlink = 2;
    return 0;
  }
  if( strcmp(fusefs.az[0],"checkins")!=0 ) return -ENOENT;
  if( n==1 ){
    stbuf->st_mode = S_IFDIR | 0111;
    stbuf->st_nlink = 2;
    return 0;
  }
  rid = fusefs_name_to_rid(fusefs.az[1]);
  if( rid<=0 ) return -ENOENT;
  if( n==2 ){
    stbuf->st_mode = S_IFDIR | 0555;
    stbuf->st_nlink = 2;
    return 0;
  }
  fusefs_load_rid(rid, fusefs.az[1]);
  if( fusefs.pMan==0 ) return -ENOENT;
  stbuf->st_mtime = (fusefs.pMan->rDate - 2440587.5)*86400.0;
  pFile = manifest_file_seek(fusefs.pMan, fusefs.az[2], 0);
  if( pFile ){
    static Stmt q;
    stbuf->st_mode = S_IFREG |
              (manifest_file_mperm(pFile)==PERM_EXE ? 0555 : 0444);
    stbuf->st_nlink = 1;
    db_static_prepare(&q, "SELECT size FROM blob WHERE uuid=$uuid");
    db_bind_text(&q, "$uuid", pFile->zUuid);
    if( db_step(&q)==SQLITE_ROW ){
      stbuf->st_size = db_column_int(&q, 0);
    }
    db_reset(&q);
    return 0;
  }
  zDir = mprintf("%s/", fusefs.az[2]);
  pFile = manifest_file_seek(fusefs.pMan, zDir, 1);
  fossil_free(zDir);
  if( pFile==0 ) return -ENOENT;
  n = (int)strlen(fusefs.az[2]);
  if( strncmp(fusefs.az[2], pFile->zName, n)!=0 ) return -ENOENT;
  if( pFile->zName[n]!='/' ) return -ENOENT;
  stbuf->st_mode = S_IFDIR | 0555;
  stbuf->st_nlink = 2;
  return 0;
}

/*
** Implementation of readdir()
*/
static int fusefs_readdir(
  const char *zPath,
  void *buf,
  fuse_fill_dir_t filler,
  off_t offset,
  struct fuse_file_info *fi
){
  int n, rid;
  ManifestFile *pFile;
  const char *zPrev = "";
  int nPrev = 0;
  char *z;
  int cnt = 0;
  n = fusefs_parse_path(zPath);
  if( n==0 ){
    filler(buf, ".", NULL, 0);
    filler(buf, "..", NULL, 0);
    filler(buf, "checkins", NULL, 0);    
    return 0;
  }
  if( strcmp(fusefs.az[0],"checkins")!=0 ) return -ENOENT;
  if( n==1 ) return -ENOENT;
  rid = fusefs_name_to_rid(fusefs.az[1]);
  if( rid<=0 ) return -ENOENT;
  fusefs_load_rid(rid, fusefs.az[1]);
  if( fusefs.pMan==0 ) return -ENOENT;
  filler(buf, ".", NULL, 0);
  filler(buf, "..", NULL, 0);
  manifest_file_rewind(fusefs.pMan);
  if( n==2 ){
    while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){
      if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue;
      zPrev = pFile->zName;
      for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
      z = mprintf("%.*s", nPrev, zPrev);
      filler(buf, z, NULL, 0);
      fossil_free(z);
      cnt++;
    }
  }else{
    char *zBase = mprintf("%s/", fusefs.az[2]);
    int nBase = (int)strlen(zBase);
    while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){
      if( strcmp(pFile->zName, zBase)>=0 ) break;
    }
    while( pFile && strncmp(zBase, pFile->zName, nBase)==0 ){
      if( nPrev==0 || strncmp(pFile->zName+nBase, zPrev, nPrev)!=0 ){
        zPrev = pFile->zName+nBase;
        for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
        if( zPrev[nPrev]=='/' ){
          z = mprintf("%.*s", nPrev, zPrev);
          filler(buf, z, NULL, 0);
          fossil_free(z);
        }else{
          filler(buf, zPrev, NULL, 0);
          nPrev = 0;
        }
        cnt++;
      }
      pFile = manifest_file_next(fusefs.pMan, 0);
    }
    fossil_free(zBase);
  }
  return cnt>0 ? 0 : -ENOENT;
}


/*
** Implementation of read()
*/
static int fusefs_read(
  const char *zPath,
  char *buf,
  size_t size,
  off_t offset,
  struct fuse_file_info *fi
){
  int n, rid;
  n = fusefs_parse_path(zPath);
  if( n<3 ) return -ENOENT;
  if( strcmp(fusefs.az[0], "checkins")!=0 ) return -ENOENT;
  rid = fusefs_name_to_rid(fusefs.az[1]);
  if( rid<=0 ) return -ENOENT;
  fusefs_load_rid(rid, fusefs.az[1]);
  if( fusefs.pFile!=0 && strcmp(fusefs.az[2], fusefs.pFile->zName)!=0 ){
    fusefs.pFile = 0;
    blob_reset(&fusefs.content);
  }
  fusefs.pFile = manifest_file_seek(fusefs.pMan, fusefs.az[2], 0);
  if( fusefs.pFile==0 ) return -ENOENT;
  rid = uuid_to_rid(fusefs.pFile->zUuid, 0);
  blob_reset(&fusefs.content);
  content_get(rid, &fusefs.content);
  if( offset>blob_size(&fusefs.content) ) return 0;
  if( offset+size>blob_size(&fusefs.content) ){
    size = blob_size(&fusefs.content) - offset;
  }
  memcpy(buf, blob_buffer(&fusefs.content)+offset, size);
  return size;
}  

static struct fuse_operations fusefs_methods = {
  .getattr = fusefs_getattr,
  .readdir = fusefs_readdir,
  .read    = fusefs_read,
};
#endif /* FOSSIL_HAVE_FUSEFS */

/*
** COMMAND: fusefs
**
** Usage: %fossil fusefs [--debug] DIRECTORY
**
** This command uses the Fuse Filesystem to mount a directory at
** DIRECTORY that contains the content of all check-ins in the
** repository.  The names of files are DIRECTORY/checkins/VERSION/PATH
** where DIRECTORY is the root of the mount, VERSION is any valid
** check-in name (examples: "trunk" or "tip" or a tag or any unique 
** prefix of a SHA1 hash, etc) and PATH is the pathname of the file
** in the checkin.  If DIRECTORY does not exist, then an attempt is
** made to create it.
**
** The DIRECTORY/checkins directory is not searchable so one cannot
** do "ls DIRECTORY/checkins" to get a listing of all possible checkin
** names.  There are countless variations on checkin names and it is
** impractical to list them all.  But all other directories are searchable
** and so the "ls" command will work everywhere else in the fusefs
** file hierarchy.
**
** The FuseFS typically only works on Linux, and then only on Linux
** systems that have the right kernel drivers and have install the
** appropriate support libraries.
**
** After stopping the "fossil fusefs" command, it might also be necessary
** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
** again.
*/
void fusefs_cmd(void){
#ifndef FOSSIL_HAVE_FUSEFS
  fossil_fatal("this build of fossil does not support the fuse filesystem");
#else
  char *zMountPoint;
  char *azNewArgv[5];
  int i;
  int doDebug = find_option("debug","d",0)!=0;

  db_find_and_open_repository(0,0);
  verify_all_options();
  blob_init(&fusefs.content, 0, 0);
  if( g.argc!=3 ) usage("DIRECTORY");
  zMountPoint = g.argv[2];
  if( file_mkdir(zMountPoint, 0) ){
    fossil_fatal("cannot make directory [%s]", zMountPoint);
  }
  azNewArgv[0] = g.argv[0];
  azNewArgv[1] = doDebug ? "-d" : "-f";
  azNewArgv[2] = "-s";
  azNewArgv[3] = zMountPoint;
  azNewArgv[4] = 0;
  g.localOpen = 0;   /* Prevent tags like "current" and "prev" */
  fuse_main(4, azNewArgv, &fusefs_methods, NULL);
  fusefs_reset();
  fusefs_clear_path();
#endif
}
Changes to src/glob.c.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
** themselves.
**
** This routine makes no effort to free the memory space it uses, which
** currently consists of a blob object and its contents.
*/
char *glob_expr(const char *zVal, const char *zGlobList){
  Blob expr;
  char *zSep = "(";
  int nTerm = 0;
  int i;
  int cTerm;

  if( zGlobList==0 || zGlobList[0]==0 ) return "0";
  blob_zero(&expr);
  while( zGlobList[0] ){







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
** themselves.
**
** This routine makes no effort to free the memory space it uses, which
** currently consists of a blob object and its contents.
*/
char *glob_expr(const char *zVal, const char *zGlobList){
  Blob expr;
  const char *zSep = "(";
  int nTerm = 0;
  int i;
  int cTerm;

  if( zGlobList==0 || zGlobList[0]==0 ) return "0";
  blob_zero(&expr);
  while( zGlobList[0] ){
Changes to src/graph.c.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
*/
struct GraphRow {
  int rid;                    /* The rid for the check-in */
  i8 nParent;                 /* Number of parents */
  int *aParent;               /* Array of parents.  0 element is primary .*/
  char *zBranch;              /* Branch name */
  char *zBgClr;               /* Background Color */
  char zUuid[17];             /* Check-in for file ID */

  GraphRow *pNext;            /* Next row down in the list of all rows */
  GraphRow *pPrev;            /* Previous row */
  
  int idx;                    /* Row index.  First is 1.  0 used for "none" */
  int idxTop;                 /* Direct descendent highest up on the graph */
  GraphRow *pChild;           /* Child immediately above this node */







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
*/
struct GraphRow {
  int rid;                    /* The rid for the check-in */
  i8 nParent;                 /* Number of parents */
  int *aParent;               /* Array of parents.  0 element is primary .*/
  char *zBranch;              /* Branch name */
  char *zBgClr;               /* Background Color */
  char zUuid[41];             /* Check-in for file ID */

  GraphRow *pNext;            /* Next row down in the list of all rows */
  GraphRow *pPrev;            /* Previous row */
  
  int idx;                    /* Row index.  First is 1.  0 used for "none" */
  int idxTop;                 /* Direct descendent highest up on the graph */
  GraphRow *pChild;           /* Child immediately above this node */
Changes to src/gzip.c.
19
20
21
22
23
24
25




26

27
28
29
30
31
32
33
** file.  The GZIP format is described in RFC-1952.
**
** State information is stored in static variables, so this implementation
** can only be building up a single GZIP file at a time.
*/
#include "config.h"
#include <assert.h>




#include <zlib.h>

#include "gzip.h"

/*
** State information for the GZIP file under construction.
*/
struct gzip_state {
  int eState;           /* 0: idle   1: header  2: compressing */







>
>
>
>
|
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
** file.  The GZIP format is described in RFC-1952.
**
** State information is stored in static variables, so this implementation
** can only be building up a single GZIP file at a time.
*/
#include "config.h"
#include <assert.h>
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif
#include "gzip.h"

/*
** State information for the GZIP file under construction.
*/
struct gzip_state {
  int eState;           /* 0: idle   1: header  2: compressing */
Changes to src/http.c.
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  }else{
    /* Password failure while doing a sync from the command-line interface */
    url_prompt_for_password();
    zPw = g.url.passwd;
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash it it isn't already a SHA1 hash.
  */
  /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
  if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);

  blob_append(&pw, zPw, -1);
  sha1sum_blob(&pw, &sig);
  blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  }else{
    /* Password failure while doing a sync from the command-line interface */
    url_prompt_for_password();
    zPw = g.url.passwd;
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash if it isn't already a SHA1 hash.
  */
  /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
  if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);

  blob_append(&pw, zPw, -1);
  sha1sum_blob(&pw, &sig);
  blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
Changes to src/http_socket.c.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
** This file manages low-level client socket communications.  The socket
** might be for a simple HTTP request or for an encrypted HTTPS request.
**
** This file implements a singleton.  A single client socket may be active
** at a time.  State information is stored in static variables.  The identity
** of the server is held in global variables that are set by url_parse().
**
** Low-level sockets are abstracted out into this module because they 
** are handled different on Unix and windows.
*/

#include "config.h"
#include "http_socket.h"
#if defined(_WIN32)
#  include <winsock2.h>







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
** This file manages low-level client socket communications.  The socket
** might be for a simple HTTP request or for an encrypted HTTPS request.
**
** This file implements a singleton.  A single client socket may be active
** at a time.  State information is stored in static variables.  The identity
** of the server is held in global variables that are set by url_parse().
**
** Low-level sockets are abstracted out into this module because they
** are handled different on Unix and windows.
*/

#include "config.h"
#include "http_socket.h"
#if defined(_WIN32)
#  include <winsock2.h>
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  free(socketErrMsg);
  socketErrMsg = 0;
}

/*
** Set the socket error message.
*/
void socket_set_errmsg(char *zFormat, ...){
  va_list ap;
  socket_clear_errmsg();
  va_start(ap, zFormat);
  socketErrMsg = vmprintf(zFormat, ap);
  va_end(ap);
}








|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  free(socketErrMsg);
  socketErrMsg = 0;
}

/*
** Set the socket error message.
*/
void socket_set_errmsg(const char *zFormat, ...){
  va_list ap;
  socket_clear_errmsg();
  va_start(ap, zFormat);
  socketErrMsg = vmprintf(zFormat, ap);
  va_end(ap);
}

Changes to src/http_ssl.c.
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  free(sslErrMsg);
  sslErrMsg = 0;
}

/*
** Set the SSL error message.
*/
void ssl_set_errmsg(char *zFormat, ...){
  va_list ap;
  ssl_clear_errmsg();
  va_start(ap, zFormat);
  sslErrMsg = vmprintf(zFormat, ap);
  va_end(ap);
}








|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  free(sslErrMsg);
  sslErrMsg = 0;
}

/*
** Set the SSL error message.
*/
void ssl_set_errmsg(const char *zFormat, ...){
  va_list ap;
  ssl_clear_errmsg();
  va_start(ap, zFormat);
  sslErrMsg = vmprintf(zFormat, ap);
  va_end(ap);
}

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
** display a warning message explaining what to do next.
*/
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
  fossil_warning("The remote server requested a client certificate for "
    "authentication. Specify the pathname to a file containing the PEM "
    "encoded certificate and private key with the --ssl-identity option "
    "or the ssl-identity setting.");
  return 0; /* no cert available */    
}

/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
void ssl_global_init(void){
  const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
  const char *identityFile;
  
  if( sslIsInit==0 ){
    SSL_library_init();
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();    
    sslCtx = SSL_CTX_new(SSLv23_client_method());
    /* Disable SSLv2 */
    SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);
    
    /* Set up acceptable CA root certificates */
    zCaSetting = db_get("ssl-ca-location", 0);
    if( zCaSetting==0 || zCaSetting[0]=='\0' ){
      /* CA location not specified, use platform's default certificate store */
      X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
    }else{
      /* User has specified a CA location, make sure it exists and use it */







|









|




|



|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
** display a warning message explaining what to do next.
*/
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
  fossil_warning("The remote server requested a client certificate for "
    "authentication. Specify the pathname to a file containing the PEM "
    "encoded certificate and private key with the --ssl-identity option "
    "or the ssl-identity setting.");
  return 0; /* no cert available */
}

/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
void ssl_global_init(void){
  const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
  const char *identityFile;

  if( sslIsInit==0 ){
    SSL_library_init();
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();
    sslCtx = SSL_CTX_new(SSLv23_client_method());
    /* Disable SSLv2 */
    SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);

    /* Set up acceptable CA root certificates */
    zCaSetting = db_get("ssl-ca-location", 0);
    if( zCaSetting==0 || zCaSetting[0]=='\0' ){
      /* CA location not specified, use platform's default certificate store */
      X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
    }else{
      /* User has specified a CA location, make sure it exists and use it */
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
        }
      }
      if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
        fossil_fatal("Failed to use CA root certificates from "
          "ssl-ca-location '%s'", zCaSetting);
      }
    }
    
    /* Load client SSL identity, preferring the filename specified on the
    ** command line */
    if( g.zSSLIdentity!=0 ){
      identityFile = g.zSSLIdentity;
    }else{
      identityFile = db_get("ssl-identity", 0);
    }







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
        }
      }
      if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
        fossil_fatal("Failed to use CA root certificates from "
          "ssl-ca-location '%s'", zCaSetting);
      }
    }

    /* Load client SSL identity, preferring the filename specified on the
    ** command line */
    if( g.zSSLIdentity!=0 ){
      identityFile = g.zSSLIdentity;
    }else{
      identityFile = db_get("ssl-identity", 0);
    }
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    SSL_CTX_free(sslCtx);
    ssl_clear_errmsg();
    sslIsInit = 0;
  }
}

/*
** Close the currently open SSL connection.  If no connection is open, 
** this routine is a no-op.
*/
void ssl_close(void){
  if( iBio!=NULL ){
    (void)BIO_reset(iBio);
    BIO_free_all(iBio);
  }







|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    SSL_CTX_free(sslCtx);
    ssl_clear_errmsg();
    sslIsInit = 0;
  }
}

/*
** Close the currently open SSL connection.  If no connection is open,
** this routine is a no-op.
*/
void ssl_close(void){
  if( iBio!=NULL ){
    (void)BIO_reset(iBio);
    BIO_free_all(iBio);
  }
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

    iBio = BIO_new_ssl(sslCtx, 1);
    BIO_push(iBio, sBio);
  }else{
    iBio = BIO_new_ssl_connect(sslCtx);
  }
  if( iBio==NULL ) {
    ssl_set_errmsg("SSL: cannot open SSL (%s)", 
                    ERR_reason_error_string(ERR_get_error()));
    return 1;
  }
  BIO_get_ssl(iBio, &ssl);

#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
  if( !SSL_set_tlsext_host_name(ssl, (pUrlData->useProxy?pUrlData->hostname:pUrlData->name)) ){
    fossil_warning("WARNING: failed to set server name indication (SNI), "
                  "continuing without it.\n");
  }
#endif

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

  if( !pUrlData->useProxy ){
    BIO_set_conn_hostname(iBio, pUrlData->name);
    BIO_set_conn_int_port(iBio, &pUrlData->port);
    if( BIO_do_connect(iBio)<=0 ){
      ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", 
          pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
      ssl_close();
      return 1;
    }
  }
  
  if( BIO_do_handshake(iBio)<=0 ) {
    ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)", 
        pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
        pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
        ERR_reason_error_string(ERR_get_error()));
    ssl_close();
    return 1;
  }
  /* Check if certificate is valid */
  cert = SSL_get_peer_certificate(ssl);

  if ( cert==NULL ){
    ssl_set_errmsg("No SSL certificate was presented by the peer");
    ssl_close();
    return 1;
  }

  if( trusted<=0 && (e = SSL_get_verify_result(ssl)) != X509_V_OK ){
    char *desc, *prompt;
    char *warning = "";
    Blob ans;
    char cReply;
    BIO *mem;
    unsigned char md[32];
    unsigned int mdLength = 31;
    
    mem = BIO_new(BIO_s_mem());
    X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
    BIO_puts(mem, "\n\nIssued By:\n\n");
    X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
    BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
    if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
      int j;
      for( j = 0; j < mdLength; ++j ) {
        BIO_printf(mem, " %02x", md[j]);
      }
    }
    BIO_write(mem, "", 1); /* nul-terminate mem buffer */
    BIO_get_mem_data(mem, &desc);
    
    if( hasSavedCertificate ){
      warning = "WARNING: Certificate doesn't match the "
                "saved certificate for this host!";
    }
    prompt = mprintf("\nSSL verification failed: %s\n"
        "Certificate received: \n\n%s\n\n%s\n"
        "Either:\n"







|


















|





|

|

















|





|













|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

    iBio = BIO_new_ssl(sslCtx, 1);
    BIO_push(iBio, sBio);
  }else{
    iBio = BIO_new_ssl_connect(sslCtx);
  }
  if( iBio==NULL ) {
    ssl_set_errmsg("SSL: cannot open SSL (%s)",
                    ERR_reason_error_string(ERR_get_error()));
    return 1;
  }
  BIO_get_ssl(iBio, &ssl);

#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
  if( !SSL_set_tlsext_host_name(ssl, (pUrlData->useProxy?pUrlData->hostname:pUrlData->name)) ){
    fossil_warning("WARNING: failed to set server name indication (SNI), "
                  "continuing without it.\n");
  }
#endif

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

  if( !pUrlData->useProxy ){
    BIO_set_conn_hostname(iBio, pUrlData->name);
    BIO_set_conn_int_port(iBio, &pUrlData->port);
    if( BIO_do_connect(iBio)<=0 ){
      ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
          pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
      ssl_close();
      return 1;
    }
  }

  if( BIO_do_handshake(iBio)<=0 ) {
    ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
        pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
        pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
        ERR_reason_error_string(ERR_get_error()));
    ssl_close();
    return 1;
  }
  /* Check if certificate is valid */
  cert = SSL_get_peer_certificate(ssl);

  if ( cert==NULL ){
    ssl_set_errmsg("No SSL certificate was presented by the peer");
    ssl_close();
    return 1;
  }

  if( trusted<=0 && (e = SSL_get_verify_result(ssl)) != X509_V_OK ){
    char *desc, *prompt;
    const char *warning = "";
    Blob ans;
    char cReply;
    BIO *mem;
    unsigned char md[32];
    unsigned int mdLength = 31;

    mem = BIO_new(BIO_s_mem());
    X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
    BIO_puts(mem, "\n\nIssued By:\n\n");
    X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
    BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
    if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
      int j;
      for( j = 0; j < mdLength; ++j ) {
        BIO_printf(mem, " %02x", md[j]);
      }
    }
    BIO_write(mem, "", 1); /* nul-terminate mem buffer */
    BIO_get_mem_data(mem, &desc);

    if( hasSavedCertificate ){
      warning = "WARNING: Certificate doesn't match the "
                "saved certificate for this host!";
    }
    prompt = mprintf("\nSSL verification failed: %s\n"
        "Certificate received: \n\n%s\n\n%s\n"
        "Either:\n"
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  BIO_get_mem_data(mem, &zCert);
  zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set(zHost, zCert, 1);
  free(zHost);
  zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set_int(zHost, trusted, 1);
  free(zHost);
  BIO_free(mem);  
}

/*
** Get certificate for pUrlData->urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){







|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  BIO_get_mem_data(mem, &zCert);
  zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set(zHost, zCert, 1);
  free(zHost);
  zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set_int(zHost, trusted, 1);
  free(zHost);
  BIO_free(mem);
}

/*
** Get certificate for pUrlData->urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
    free(zHost);
  }

  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
  free(zCert);
  BIO_free(mem);  
  return cert;
}

/*
** Send content out over the SSL connection.
*/
size_t ssl_send(void *NotUsed, void *pContent, size_t N){







|







441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
    free(zHost);
  }

  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
  free(zCert);
  BIO_free(mem);
  return cert;
}

/*
** Send content out over the SSL connection.
*/
size_t ssl_send(void *NotUsed, void *pContent, size_t N){
Changes to src/http_transport.c.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    transport.nRcvd = 0;
  }
}

/*
** Default SSH command
*/
#ifdef __MINGW32__
static char zDefaultSshCmd[] = "ssh -T";
#else
static char zDefaultSshCmd[] = "ssh -e none -T";
#endif

/*
** SSH initialization of the transport layer
*/
int transport_ssh_open(UrlData *pUrlData){
  /* For SSH we need to create and run SSH fossil http 
  ** to talk to the remote machine.
  */
  const char *zSsh;  /* The base SSH command */
  Blob zCmd;         /* The SSH command */
  char *zHost;       /* The host name to contact */
  int n;             /* Size of prefix string */

  socket_ssh_resolve_addr(pUrlData);
  zSsh = db_get("ssh-command", zDefaultSshCmd);
  blob_init(&zCmd, zSsh, -1);
  if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
#ifdef __MINGW32__
    blob_appendf(&zCmd, " -P %d", pUrlData->port);
#else
    blob_appendf(&zCmd, " -p %d", pUrlData->port);
#endif
  }
  if( g.fSshTrace ){
    fossil_force_newline();







|
|




















|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    transport.nRcvd = 0;
  }
}

/*
** Default SSH command
*/
#ifdef _WIN32
static char zDefaultSshCmd[] = "plink -ssh -T";
#else
static char zDefaultSshCmd[] = "ssh -e none -T";
#endif

/*
** SSH initialization of the transport layer
*/
int transport_ssh_open(UrlData *pUrlData){
  /* For SSH we need to create and run SSH fossil http 
  ** to talk to the remote machine.
  */
  const char *zSsh;  /* The base SSH command */
  Blob zCmd;         /* The SSH command */
  char *zHost;       /* The host name to contact */
  int n;             /* Size of prefix string */

  socket_ssh_resolve_addr(pUrlData);
  zSsh = db_get("ssh-command", zDefaultSshCmd);
  blob_init(&zCmd, zSsh, -1);
  if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
#ifdef _WIN32
    blob_appendf(&zCmd, " -P %d", pUrlData->port);
#else
    blob_appendf(&zCmd, " -p %d", pUrlData->port);
#endif
  }
  if( g.fSshTrace ){
    fossil_force_newline();
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
** This routine is called when the outbound message is complete and
** it is time to being receiving a reply.
*/
void transport_flip(UrlData *pUrlData){
  if( pUrlData->isFile ){
    char *zCmd;
    fclose(transport.pFile);
    zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
       g.nameOfExe, pUrlData->name, transport.zOutFile, transport.zInFile
    );
    fossil_system(zCmd);
    free(zCmd);
    transport.pFile = fossil_fopen(transport.zInFile, "rb");
  }
}








|
|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
** This routine is called when the outbound message is complete and
** it is time to being receiving a reply.
*/
void transport_flip(UrlData *pUrlData){
  if( pUrlData->isFile ){
    char *zCmd;
    fclose(transport.pFile);
    zCmd = mprintf("\"%s\" http \"%s\" \"%s\" 127.0.0.1 \"%s\" --localauth",
       g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name
    );
    fossil_system(zCmd);
    free(zCmd);
    transport.pFile = fossil_fopen(transport.zInFile, "rb");
  }
}

Changes to src/import.c.
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  return fossil_strcmp(pA->zName, pB->zName);
}

/*
** Compare two strings for sorting.
*/
static int string_cmp(const void *pLeft, const void *pRight){
  const char *zLeft = *(char const **)pLeft;
  const char *zRight = *(char const **)pRight;
  return fossil_strcmp(zLeft, zRight);
}

/* Forward reference */
static void import_prior_files(void);

/*







|
|







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  return fossil_strcmp(pA->zName, pB->zName);
}

/*
** Compare two strings for sorting.
*/
static int string_cmp(const void *pLeft, const void *pRight){
  const char *zLeft = *(const char **)pLeft;
  const char *zRight = *(const char **)pRight;
  return fossil_strcmp(zLeft, zRight);
}

/* Forward reference */
static void import_prior_files(void);

/*
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
** Do not search past the mx-th file.
*/
static ImportFile *import_find_file(const char *zName, int *pI, int mx){
  int i = *pI;
  int nName = strlen(zName);
  while( i<mx ){
    const char *z = gg.aFile[i].zName;
    if( memcmp(zName, z, nName)==0 && (z[nName]==0 || z[nName]=='/') ){
      *pI = i+1;
      return &gg.aFile[i];
    }
    i++;
  }
  return 0;
}







|







441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
** Do not search past the mx-th file.
*/
static ImportFile *import_find_file(const char *zName, int *pI, int mx){
  int i = *pI;
  int nName = strlen(zName);
  while( i<mx ){
    const char *z = gg.aFile[i].zName;
    if( strncmp(zName, z, nName)==0 && (z[nName]==0 || z[nName]=='/') ){
      *pI = i+1;
      return &gg.aFile[i];
    }
    i++;
  }
  return 0;
}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  char *zFrom;
  char *zTo;
  char zLine[1000];

  gg.xFinish = finish_noop;
  while( fgets(zLine, sizeof(zLine), pIn) ){
    if( zLine[0]=='\n' || zLine[0]=='#' ) continue;
    if( memcmp(zLine, "blob", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_blob;
    }else
    if( memcmp(zLine, "commit ", 7)==0 ){
      gg.xFinish();
      gg.xFinish = finish_commit;
      trim_newline(&zLine[7]);
      z = &zLine[7];

      /* The argument to the "commit" line might match either of these
      ** patterns:







|



|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  char *zFrom;
  char *zTo;
  char zLine[1000];

  gg.xFinish = finish_noop;
  while( fgets(zLine, sizeof(zLine), pIn) ){
    if( zLine[0]=='\n' || zLine[0]=='#' ) continue;
    if( strncmp(zLine, "blob", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_blob;
    }else
    if( strncmp(zLine, "commit ", 7)==0 ){
      gg.xFinish();
      gg.xFinish = finish_commit;
      trim_newline(&zLine[7]);
      z = &zLine[7];

      /* The argument to the "commit" line might match either of these
      ** patterns:
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
      ** of pattern B with the same TAGNAME, then only put the tag on the
      ** last commit that holds that tag.
      **
      ** None of the above is explained in the git-fast-export
      ** documentation.  We had to figure it out via trial and error.
      */
      for(i=strlen(z)-1; i>=0 && z[i]!='/'; i--){}
      gg.tagCommit = memcmp(&z[i-4], "tags", 4)==0;  /* True for pattern B */
      if( z[i+1]!=0 ) z += i+1;
      if( fossil_strcmp(z, "master")==0 ) z = "trunk";
      gg.zBranch = fossil_strdup(z);
      gg.fromLoaded = 0;
    }else
    if( memcmp(zLine, "tag ", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_tag;
      trim_newline(&zLine[4]);
      gg.zTag = fossil_strdup(&zLine[4]);
    }else
    if( memcmp(zLine, "reset ", 4)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "checkpoint", 10)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "feature", 7)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "option", 6)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "progress ", 9)==0 ){
      gg.xFinish();
      trim_newline(&zLine[9]);
      fossil_print("%s\n", &zLine[9]);
      fflush(stdout);
    }else
    if( memcmp(zLine, "data ", 5)==0 ){
      fossil_free(gg.aData); gg.aData = 0;
      gg.nData = atoi(&zLine[5]);
      if( gg.nData ){
        int got;
        gg.aData = fossil_malloc( gg.nData+1 );
        got = fread(gg.aData, 1, gg.nData, pIn);
        if( got!=gg.nData ){
          fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
        }
        gg.aData[got] = 0;
        if( gg.zComment==0 && gg.xFinish==finish_commit ){
          gg.zComment = gg.aData;
          gg.aData = 0;
          gg.nData = 0;
        }
      }
    }else
    if( memcmp(zLine, "author ", 7)==0 ){
      /* No-op */
    }else
    if( memcmp(zLine, "mark ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zMark);
      gg.zMark = fossil_strdup(&zLine[5]);
    }else
    if( memcmp(zLine, "tagger ", 7)==0 || memcmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      for(i=0; zLine[i] && zLine[i]!='<'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      z = &zLine[i+1];
      for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      zLine[i] = 0;
      fossil_free(gg.zUser);
      gg.zUser = fossil_strdup(z);
      secSince1970 = 0;
      for(i=i+2; fossil_isdigit(zLine[i]); i++){
        secSince1970 = secSince1970*10 + zLine[i] - '0';
      }
      fossil_free(gg.zDate);
      gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
      gg.zDate[10] = 'T';
    }else
    if( memcmp(zLine, "from ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zFromMark);
      gg.zFromMark = fossil_strdup(&zLine[5]);
      fossil_free(gg.zFrom);
      gg.zFrom = resolve_committish(&zLine[5]);
    }else
    if( memcmp(zLine, "merge ", 6)==0 ){
      trim_newline(&zLine[6]);
      if( gg.nMerge>=gg.nMergeAlloc ){
        gg.nMergeAlloc = gg.nMergeAlloc*2 + 10;
        gg.azMerge = fossil_realloc(gg.azMerge, gg.nMergeAlloc*sizeof(char*));
      }
      gg.azMerge[gg.nMerge] = resolve_committish(&zLine[6]);
      if( gg.azMerge[gg.nMerge] ) gg.nMerge++;
    }else
    if( memcmp(zLine, "M ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zPerm = next_token(&z);
      zUuid = next_token(&z);
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      pFile = import_find_file(zName, &i, gg.nFile);
      if( pFile==0 ){
        pFile = import_add_file();
        pFile->zName = fossil_strdup(zName);
      }
      pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
      pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
      fossil_free(pFile->zUuid);
      pFile->zUuid = resolve_committish(zUuid);
      pFile->isFrom = 0;
    }else
    if( memcmp(zLine, "D ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
        if( pFile->isFrom==0 ) continue;
        fossil_free(pFile->zName);
        fossil_free(pFile->zPrior);
        fossil_free(pFile->zUuid);
        *pFile = gg.aFile[--gg.nFile];
        i--;
      }
    }else
    if( memcmp(zLine, "C ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      mx = gg.nFile;







|





|





|


|


|


|


|





|

















|


|




|

















|






|








|


















|














|







515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
      ** of pattern B with the same TAGNAME, then only put the tag on the
      ** last commit that holds that tag.
      **
      ** None of the above is explained in the git-fast-export
      ** documentation.  We had to figure it out via trial and error.
      */
      for(i=strlen(z)-1; i>=0 && z[i]!='/'; i--){}
      gg.tagCommit = strncmp(&z[i-4], "tags", 4)==0;  /* True for pattern B */
      if( z[i+1]!=0 ) z += i+1;
      if( fossil_strcmp(z, "master")==0 ) z = "trunk";
      gg.zBranch = fossil_strdup(z);
      gg.fromLoaded = 0;
    }else
    if( strncmp(zLine, "tag ", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_tag;
      trim_newline(&zLine[4]);
      gg.zTag = fossil_strdup(&zLine[4]);
    }else
    if( strncmp(zLine, "reset ", 4)==0 ){
      gg.xFinish();
    }else
    if( strncmp(zLine, "checkpoint", 10)==0 ){
      gg.xFinish();
    }else
    if( strncmp(zLine, "feature", 7)==0 ){
      gg.xFinish();
    }else
    if( strncmp(zLine, "option", 6)==0 ){
      gg.xFinish();
    }else
    if( strncmp(zLine, "progress ", 9)==0 ){
      gg.xFinish();
      trim_newline(&zLine[9]);
      fossil_print("%s\n", &zLine[9]);
      fflush(stdout);
    }else
    if( strncmp(zLine, "data ", 5)==0 ){
      fossil_free(gg.aData); gg.aData = 0;
      gg.nData = atoi(&zLine[5]);
      if( gg.nData ){
        int got;
        gg.aData = fossil_malloc( gg.nData+1 );
        got = fread(gg.aData, 1, gg.nData, pIn);
        if( got!=gg.nData ){
          fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
        }
        gg.aData[got] = 0;
        if( gg.zComment==0 && gg.xFinish==finish_commit ){
          gg.zComment = gg.aData;
          gg.aData = 0;
          gg.nData = 0;
        }
      }
    }else
    if( strncmp(zLine, "author ", 7)==0 ){
      /* No-op */
    }else
    if( strncmp(zLine, "mark ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zMark);
      gg.zMark = fossil_strdup(&zLine[5]);
    }else
    if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      for(i=0; zLine[i] && zLine[i]!='<'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      z = &zLine[i+1];
      for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      zLine[i] = 0;
      fossil_free(gg.zUser);
      gg.zUser = fossil_strdup(z);
      secSince1970 = 0;
      for(i=i+2; fossil_isdigit(zLine[i]); i++){
        secSince1970 = secSince1970*10 + zLine[i] - '0';
      }
      fossil_free(gg.zDate);
      gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
      gg.zDate[10] = 'T';
    }else
    if( strncmp(zLine, "from ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zFromMark);
      gg.zFromMark = fossil_strdup(&zLine[5]);
      fossil_free(gg.zFrom);
      gg.zFrom = resolve_committish(&zLine[5]);
    }else
    if( strncmp(zLine, "merge ", 6)==0 ){
      trim_newline(&zLine[6]);
      if( gg.nMerge>=gg.nMergeAlloc ){
        gg.nMergeAlloc = gg.nMergeAlloc*2 + 10;
        gg.azMerge = fossil_realloc(gg.azMerge, gg.nMergeAlloc*sizeof(char*));
      }
      gg.azMerge[gg.nMerge] = resolve_committish(&zLine[6]);
      if( gg.azMerge[gg.nMerge] ) gg.nMerge++;
    }else
    if( strncmp(zLine, "M ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zPerm = next_token(&z);
      zUuid = next_token(&z);
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      pFile = import_find_file(zName, &i, gg.nFile);
      if( pFile==0 ){
        pFile = import_add_file();
        pFile->zName = fossil_strdup(zName);
      }
      pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
      pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
      fossil_free(pFile->zUuid);
      pFile->zUuid = resolve_committish(zUuid);
      pFile->isFrom = 0;
    }else
    if( strncmp(zLine, "D ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
        if( pFile->isFrom==0 ) continue;
        fossil_free(pFile->zName);
        fossil_free(pFile->zPrior);
        fossil_free(pFile->zUuid);
        *pFile = gg.aFile[--gg.nFile];
        i--;
      }
    }else
    if( strncmp(zLine, "C ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      mx = gg.nFile;
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
        }
        pNew->isExe = pFile->isExe;
        pNew->isLink = pFile->isLink;
        pNew->zUuid = fossil_strdup(pFile->zUuid);
        pNew->isFrom = 0;
      }
    }else
    if( memcmp(zLine, "R ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      nFrom = strlen(zFrom);







|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
        }
        pNew->isExe = pFile->isExe;
        pNew->isLink = pFile->isLink;
        pNew->zUuid = fossil_strdup(pFile->zUuid);
        pNew->isFrom = 0;
      }
    }else
    if( strncmp(zLine, "R ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      nFrom = strlen(zFrom);
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
        pNew->isFrom = 0;
        gg.nFile--;
        *pFile = *pNew;
        memset(pNew, 0, sizeof(*pNew));
      }
      fossil_fatal("cannot handle R records, use --full-tree");
    }else
    if( memcmp(zLine, "deleteall", 9)==0 ){
      gg.fromLoaded = 1;
    }else
    if( memcmp(zLine, "N ", 2)==0 ){
      /* No-op */
    }else

    {
      goto malformed_line;
    }
  }







|


|







691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
        pNew->isFrom = 0;
        gg.nFile--;
        *pFile = *pNew;
        memset(pNew, 0, sizeof(*pNew));
      }
      fossil_fatal("cannot handle R records, use --full-tree");
    }else
    if( strncmp(zLine, "deleteall", 9)==0 ){
      gg.fromLoaded = 1;
    }else
    if( strncmp(zLine, "N ", 2)==0 ){
      /* No-op */
    }else

    {
      goto malformed_line;
    }
  }
Changes to src/info.c.
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  zTags = info_tags_of_checkin(rid, 0);
  if( zTags && zTags[0] ){
    fossil_print("tags:         %s\n", zTags);
  }
  free(zTags);
  if( zComment ){
    fossil_print("comment:      ");
    comment_print(zComment, 14, 79);
    free(zComment);
  }
}

/*
** Print information about the URLs used to access a repository and
** checkouts in a repository.







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  zTags = info_tags_of_checkin(rid, 0);
  if( zTags && zTags[0] ){
    fossil_print("tags:         %s\n", zTags);
  }
  free(zTags);
  if( zComment ){
    fossil_print("comment:      ");
    comment_print(zComment, 0, 14, -1, g.comFmtFlags);
    free(zComment);
  }
}

/*
** Print information about the URLs used to access a repository and
** checkouts in a repository.
195
196
197
198
199
200
201




202
203
204
205

206
207
208
209
210
211
212
*/
void info_cmd(void){
  i64 fsize;
  int verboseFlag = find_option("verbose","v",0)!=0;
  if( !verboseFlag ){
    verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
  }




  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);

    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
    extraRepoInfo();
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){







>
>
>
>


<

>







195
196
197
198
199
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216
*/
void info_cmd(void){
  i64 fsize;
  int verboseFlag = find_option("verbose","v",0)!=0;
  if( !verboseFlag ){
    verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
  }

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);

    db_open_repository(g.argv[2]);
    db_record_repository_filename(g.argv[2]);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
    extraRepoInfo();
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     timeline_utc(), timeline_utc(), rid, rid
  );
  sideBySide = !is_false(PD("sbs","1"));
  if( db_step(&q1)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q1, 0);
    char *zTitle = mprintf("Check-in [%.10s]", zUuid);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zComment;
    const char *zDate;
    const char *zOrigDate;

    style_header(zTitle);







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     timeline_utc(), timeline_utc(), rid, rid
  );
  sideBySide = !is_false(PD("sbs","1"));
  if( db_step(&q1)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q1, 0);
    char *zTitle = mprintf("Check-in [%S]", zUuid);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zComment;
    const char *zDate;
    const char *zOrigDate;

    style_header(zTitle);
758
759
760
761
762
763
764






765
766




767
768
769
770
771
772
773
    @ No such object: %h(P("name"))
    style_footer();
    return;
  }
  if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);






      cgi_redirectf("%R/wiki?name=%T", pWiki->zWikiTitle);
      /*NOTREACHED*/




    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Update of \"%h\"", pWiki->zWikiTitle);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);







>
>
>
>
>
>
|
|
>
>
>
>







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
    @ No such object: %h(P("name"))
    style_footer();
    return;
  }
  if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the wiki page still exists; if not, we cannot
      ** redirect to it.
      */
      if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)"
                    " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){
        cgi_redirectf("%R/wiki?name=%T", pWiki->zWikiTitle);
        /*NOTREACHED*/
      }else{
        cgi_redirectf("%R/modreq");
        /*NOTREACHED*/
      }
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Update of \"%h\"", pWiki->zWikiTitle);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
985
986
987
988
989
990
991


992
993
994
995
996
997
998
  zFrom = P("from");
  zTo = P("to");
  if(zGlob && !*zGlob){
    zGlob = NULL;
  }
  diffFlags = construct_diff_flags(verboseFlag, sideBySide);
  zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";


  if( sideBySide || verboseFlag ){
    style_submenu_element("Hide Diff", "hidediff",
                          "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
                          zFrom, zTo,
                          zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
  }
  if( !sideBySide ){







>
>







999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
  zFrom = P("from");
  zTo = P("to");
  if(zGlob && !*zGlob){
    zGlob = NULL;
  }
  diffFlags = construct_diff_flags(verboseFlag, sideBySide);
  zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  style_submenu_element("Path","path",
                        "%R/timeline?me=%T&you=%T", zFrom, zTo);
  if( sideBySide || verboseFlag ){
    style_submenu_element("Hide Diff", "hidediff",
                          "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
                          zFrom, zTo,
                          zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
  }
  if( !sideBySide ){
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
      cmp = +1;
    }else if( pFileTo==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
    }
    if( cmp<0 ){
      if(!zGlob || strglob(zGlob, pFileFrom->zName)){
        append_file_change_line(pFileFrom->zName,
                                pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
      }
      pFileFrom = manifest_file_next(pFrom, 0);
    }else if( cmp>0 ){
      if(!zGlob || strglob(zGlob, pFileTo->zName)){
        append_file_change_line(pFileTo->zName,
                                0, pFileTo->zUuid, 0, diffFlags, pRe,
                                manifest_file_mperm(pFileTo));
      }
      pFileTo = manifest_file_next(pTo, 0);
    }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }else{
      if(!zGlob || (strglob(zGlob, pFileFrom->zName)
                || strglob(zGlob, pFileTo->zName))){
        append_file_change_line(pFileFrom->zName,
                                pFileFrom->zUuid,
                                pFileTo->zUuid, 0, diffFlags, pRe,
                                manifest_file_mperm(pFileTo));
      }
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);







|





|









|
|







1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
      cmp = +1;
    }else if( pFileTo==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
    }
    if( cmp<0 ){
      if( !zGlob || sqlite3_strglob(zGlob, pFileFrom->zName)==0 ){
        append_file_change_line(pFileFrom->zName,
                                pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
      }
      pFileFrom = manifest_file_next(pFrom, 0);
    }else if( cmp>0 ){
      if( !zGlob || sqlite3_strglob(zGlob, pFileTo->zName)==0 ){
        append_file_change_line(pFileTo->zName,
                                0, pFileTo->zUuid, 0, diffFlags, pRe,
                                manifest_file_mperm(pFileTo));
      }
      pFileTo = manifest_file_next(pTo, 0);
    }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }else{
      if(!zGlob || (sqlite3_strglob(zGlob, pFileFrom->zName)==0
                || sqlite3_strglob(zGlob, pFileTo->zName)==0) ){
        append_file_change_line(pFileFrom->zName,
                                pFileFrom->zUuid,
                                pFileTo->zUuid, 0, diffFlags, pRe,
                                manifest_file_mperm(pFileTo));
      }
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
1103
1104
1105
1106
1107
1108
1109






1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
#define OBJTYPE_WIKI       0x0004
#define OBJTYPE_TICKET     0x0008
#define OBJTYPE_ATTACHMENT 0x0010
#define OBJTYPE_EVENT      0x0020
#define OBJTYPE_TAG        0x0040
#define OBJTYPE_SYMLINK    0x0080
#define OBJTYPE_EXE        0x0100






#endif

/*
** Write a description of an object to the www reply.
**
** If the object is a file then mention:
**
**     * It's artifact ID
**     * All its filenames
**     * The check-in it was part of, with times and users
**
** If the object is a manifest, then mention:
**
**     * It's artifact ID
**     * date of check-in
**     * Comment & user
*/
int object_description(
  int rid,                 /* The artifact ID */
  int linkToView,          /* Add viewer link if true */
  Blob *pDownloadName      /* Fill with an appropriate download name */
){
  Stmt q;
  int cnt = 0;
  int nWiki = 0;
  int objType = 0;
  char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);

  char *prevName = 0;

  db_prepare(&q,
    "SELECT filename.name, datetime(event.mtime),"
    "       coalesce(event.ecomment,event.comment),"
    "       coalesce(event.euser,event.user),"
    "       b.uuid, mlink.mperm,"







>
>
>
>
>
>



















|







|







1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
#define OBJTYPE_WIKI       0x0004
#define OBJTYPE_TICKET     0x0008
#define OBJTYPE_ATTACHMENT 0x0010
#define OBJTYPE_EVENT      0x0020
#define OBJTYPE_TAG        0x0040
#define OBJTYPE_SYMLINK    0x0080
#define OBJTYPE_EXE        0x0100

/*
** Possible flags for the second parameter to
** object_description()
*/
#define OBJDESC_DETAIL      0x0001   /* more detail */
#endif

/*
** Write a description of an object to the www reply.
**
** If the object is a file then mention:
**
**     * It's artifact ID
**     * All its filenames
**     * The check-in it was part of, with times and users
**
** If the object is a manifest, then mention:
**
**     * It's artifact ID
**     * date of check-in
**     * Comment & user
*/
int object_description(
  int rid,                 /* The artifact ID */
  u32 objdescFlags,        /* Flags to control display */
  Blob *pDownloadName      /* Fill with an appropriate download name */
){
  Stmt q;
  int cnt = 0;
  int nWiki = 0;
  int objType = 0;
  char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  int showDetail = (objdescFlags & OBJDESC_DETAIL)!=0;
  char *prevName = 0;

  db_prepare(&q,
    "SELECT filename.name, datetime(event.mtime),"
    "       coalesce(event.ecomment,event.comment),"
    "       coalesce(event.euser,event.user),"
    "       b.uuid, mlink.mperm,"
1158
1159
1160
1161
1162
1163
1164
1165








1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179

1180

1181
1182

1183
1184



1185
1186



1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
    const char *zName = db_column_text(&q, 0);
    const char *zDate = db_column_text(&q, 1);
    const char *zCom = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    const char *zVers = db_column_text(&q, 4);
    int mPerm = db_column_int(&q, 5);
    const char *zBr = db_column_text(&q, 6);
    if( !prevName || fossil_strcmp(zName, prevName) ) {








      if( prevName ) {
        @ </ul>
      }
      if( mPerm==PERM_LNK ){
        @ <li>Symbolic link
        objType |= OBJTYPE_SYMLINK;
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
        objType |= OBJTYPE_EXE;
      }else{
        @ <li>File
      }
      objType |= OBJTYPE_CONTENT;
      @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>

      @ <ul>

      prevName = fossil_strdup(zName);
    }

    @ <li>
    hyperlink_to_date(zDate,"");



    @ - part of checkin
    hyperlink_to_uuid(zVers);



    if( zBr && zBr[0] ){
      @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
    }
    @ - %!w(zCom) (user:
    hyperlink_to_user(zUser,zDate,")");
    if( g.perm.Hyperlink ){
      @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a>
      @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%T&checkin=%s",zName,zVers))
      @ [blame]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
  if( prevName ){
    @ </ul>
  }
  @ </ul>
  free(prevName);
  db_finalize(&q);
  db_prepare(&q,
    "SELECT substr(tagname, 6, 10000), datetime(event.mtime),"







|
>
>
>
>
>
>
>
>














>
|
>


>
|
|
>
>
>
|
|
>
>
>



|













|







1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
    const char *zName = db_column_text(&q, 0);
    const char *zDate = db_column_text(&q, 1);
    const char *zCom = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    const char *zVers = db_column_text(&q, 4);
    int mPerm = db_column_int(&q, 5);
    const char *zBr = db_column_text(&q, 6);
    int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0;
    if( sameFilename && !showDetail ){
      if( cnt==1 ){
        @ %z(href("%R/whatis/%s",zUuid))[more...]</a>
      }
      cnt++;
      continue;
    }
    if( !sameFilename ){
      if( prevName ) {
        @ </ul>
      }
      if( mPerm==PERM_LNK ){
        @ <li>Symbolic link
        objType |= OBJTYPE_SYMLINK;
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
        objType |= OBJTYPE_EXE;
      }else{
        @ <li>File
      }
      objType |= OBJTYPE_CONTENT;
      @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
      if( showDetail ){
        @ <ul>
      }
      prevName = fossil_strdup(zName);
    }
    if( showDetail ){
      @ <li>
      hyperlink_to_date(zDate,"");
      @ &mdash; part of check-in
      hyperlink_to_uuid(zVers);
    }else{
      @ &mdash; part of checkin
      hyperlink_to_uuid(zVers);
      @ at
      hyperlink_to_date(zDate,"");
    }
    if( zBr && zBr[0] ){
      @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
    }
    @ &mdash; %!w(zCom) (user:
    hyperlink_to_user(zUser,zDate,")");
    if( g.perm.Hyperlink ){
      @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a>
      @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%T&checkin=%s",zName,zVers))
      @ [blame]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
  if( prevName && showDetail ){
    @ </ul>
  }
  @ </ul>
  free(prevName);
  db_finalize(&q);
  db_prepare(&q,
    "SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345




1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
  }
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }
  }else if( linkToView && g.perm.Hyperlink ){
    @ %z(href("%R/artifact/%s",zUuid))[view]</a>
  }
  return objType;
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN&regex=REGEX
**
** Two arguments, v1 and v2, identify the files to be diffed.  Show the
** difference between the two artifacts.  Show diff side by side unless sbs
** is 0.  Generate plaintext if "patch" is present.




*/
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  char *zV1;
  char *zV2;
  const char *zRe;
  const char *zW;      /* URL param for ignoring whitespace */
  ReCompiled *pRe = 0;
  u64 diffFlags;


  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  v1 = name_to_rid_www("v1");
  v2 = name_to_rid_www("v2");
  if( v1==0 || v2==0 ) fossil_redirect_home();
  zRe = P("regex");
  if( zRe ) re_compile(&pRe, zRe, 0);

  isPatch = P("patch")!=0;
  if( isPatch ){
    Blob c1, c2, *pOut;
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");
    diffFlags = 4;
    content_get(v1, &c1);







<
<












>
>
>
>











>








>







1364
1365
1366
1367
1368
1369
1370


1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
  }
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }


  }
  return objType;
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN&regex=REGEX
**
** Two arguments, v1 and v2, identify the files to be diffed.  Show the
** difference between the two artifacts.  Show diff side by side unless sbs
** is 0.  Generate plaintext if "patch" is present.
**
** Additional parameters:
**
**      verbose      Show more detail when describing artifacts
*/
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  char *zV1;
  char *zV2;
  const char *zRe;
  const char *zW;      /* URL param for ignoring whitespace */
  ReCompiled *pRe = 0;
  u64 diffFlags;
  u32 objdescFlags = 0;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  v1 = name_to_rid_www("v1");
  v2 = name_to_rid_www("v2");
  if( v1==0 || v2==0 ) fossil_redirect_home();
  zRe = P("regex");
  if( zRe ) re_compile(&pRe, zRe, 0);
  if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
  isPatch = P("patch")!=0;
  if( isPatch ){
    Blob c1, c2, *pOut;
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");
    diffFlags = 4;
    content_get(v1, &c1);
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  if( P("smhdr")!=0 ){
    @ <h2>Differences From Artifact
    @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To
    @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2>
  }else{
    @ <h2>Differences From
    @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);
    @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);
  }
  if( pRe ){
    @ <b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b>
  }
  @ <hr />
  append_diff(zV1, zV2, diffFlags, pRe);







|

|







1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
  if( P("smhdr")!=0 ){
    @ <h2>Differences From Artifact
    @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To
    @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2>
  }else{
    @ <h2>Differences From
    @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2>
    object_description(v1, objdescFlags, 0);
    @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2>
    object_description(v2, objdescFlags, 0);
  }
  if( pRe ){
    @ <b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b>
  }
  @ <hr />
  append_diff(zV1, zV2, diffFlags, pRe);
1519
1520
1521
1522
1523
1524
1525




1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538

/*
** WEBPAGE: hexdump
** URL: /hexdump?name=ARTIFACTID
**
** Show the complete content of a file identified by ARTIFACTID
** as preformatted text.




*/
void hexdump_page(void){
  int rid;
  Blob content;
  Blob downloadName;
  char *zUuid;


  rid = name_to_rid_www("name");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);







>
>
>
>






>







1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586

/*
** WEBPAGE: hexdump
** URL: /hexdump?name=ARTIFACTID
**
** Show the complete content of a file identified by ARTIFACTID
** as preformatted text.
**
** Other parameters:
**
**     verbose              Show more detail when describing the object
*/
void hexdump_page(void){
  int rid;
  Blob content;
  Blob downloadName;
  char *zUuid;
  u32 objdescFlags = 0;

  rid = name_to_rid_www("name");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1562
1563
1564



























1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
  zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);

  object_description(rid, 0, &downloadName);
  style_submenu_element("Download", "Download",
        "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
  @ <hr />
  content_get(rid, &content);
  @ <blockquote><pre>
  hexdump(&content);
  @ </pre></blockquote>
  style_footer();
}




























/*
** Look for "ci" and "filename" query parameters.  If found, try to
** use them to extract the record ID of an artifact for the file.
*/
int artifact_from_ci_and_filename(void){
  const char *zFilename;
  const char *zCI;
  int cirid;
  Manifest *pManifest;
  ManifestFile *pFile;

  zCI = P("ci");







>
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
  zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);
  if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
  object_description(rid, objdescFlags, &downloadName);
  style_submenu_element("Download", "Download",
        "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
  @ <hr />
  content_get(rid, &content);
  @ <blockquote><pre>
  hexdump(&content);
  @ </pre></blockquote>
  style_footer();
}

/*
** Attempt to lookup the specified checkin and file name into an rid.
*/
int artifact_from_ci_and_filename(
  const char *zCI,
  const char *zFilename
){
  int cirid;
  Manifest *pManifest;
  ManifestFile *pFile;

  if( zCI==0 ) return 0;
  if( zFilename==0 ) return 0;
  cirid = name_to_rid(zCI);
  pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
  if( pManifest==0 ) return 0;
  manifest_file_rewind(pManifest);
  while( (pFile = manifest_file_next(pManifest,0))!=0 ){
    if( fossil_strcmp(zFilename, pFile->zName)==0 ){
      int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
      manifest_destroy(pManifest);
      return rid;
    }
  }
  return 0;
}

/*
** Look for "ci" and "filename" query parameters.  If found, try to
** use them to extract the record ID of an artifact for the file.
*/
int artifact_from_ci_and_filename_www(void){
  const char *zFilename;
  const char *zCI;
  int cirid;
  Manifest *pManifest;
  ManifestFile *pFile;

  zCI = P("ci");
1646
1647
1648
1649
1650
1651
1652

1653

1654
1655

1656
1657
1658
1659
1660
1661

1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675



1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
  if( iStart ){
    @ <script>gebi('topln').scrollIntoView(true);</script>
  }
}


/*

** WEBPAGE: artifact

** URL: /artifact/ARTIFACTID
** URL: /artifact?ci=CHECKIN&filename=PATH

**
** Additional query parameters:
**
**   ln              - show line numbers
**   ln=N            - highlight line number N
**   ln=M-N          - highlight lines M through N inclusive

**
** Show the complete content of a file identified by ARTIFACTID
** as preformatted text.

*/
void artifact_page(void){
  int rid = 0;
  Blob content;
  const char *zMime;
  Blob downloadName;
  int renderAsWiki = 0;
  int renderAsHtml = 0;
  int objType;
  int asText;
  const char *zUuid;




  if( P("ci") && P("filename") ){
    rid = artifact_from_ci_and_filename();
  }
  if( rid==0 ){
    rid = name_to_rid_www("name");
  }

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }

  style_header("Artifact Content");
  zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);
  objType = object_description(rid, 0, &downloadName);
  style_submenu_element("Download", "Download",
          "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid);
  if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
    style_submenu_element("Checkins Using", "Checkins Using",
          "%R/timeline?n=200&uf=%s",zUuid);
  }
  asText = P("txt")!=0;







>

>
|

>






>

|
|
>











>
>
>


|


















>
|







|







1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
  if( iStart ){
    @ <script>gebi('topln').scrollIntoView(true);</script>
  }
}


/*
** WEBPAGE: whatis
** WEBPAGE: artifact
**
** URL: /artifact/SHA1HASH
** URL: /artifact?ci=CHECKIN&filename=PATH
** URL: /whatis/SHA1HASH
**
** Additional query parameters:
**
**   ln              - show line numbers
**   ln=N            - highlight line number N
**   ln=M-N          - highlight lines M through N inclusive
**   verbose         - show more detail in the description
**
** The /artifact page show the complete content of a file
** identified by SHA1HASH as preformatted text.  The
** /whatis page shows only a description of the file.
*/
void artifact_page(void){
  int rid = 0;
  Blob content;
  const char *zMime;
  Blob downloadName;
  int renderAsWiki = 0;
  int renderAsHtml = 0;
  int objType;
  int asText;
  const char *zUuid;
  u32 objdescFlags = 0;
  int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
  const char *zLn = P("ln");

  if( P("ci") && P("filename") ){
    rid = artifact_from_ci_and_filename_www();
  }
  if( rid==0 ){
    rid = name_to_rid_www("name");
  }

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
  style_header(descOnly ? "Artifact Description" : "Artifact Content");
  zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);
  objType = object_description(rid, objdescFlags, &downloadName);
  style_submenu_element("Download", "Download",
          "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid);
  if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
    style_submenu_element("Checkins Using", "Checkins Using",
          "%R/timeline?n=200&uf=%s",zUuid);
  }
  asText = P("txt")!=0;
1732
1733
1734
1735
1736
1737
1738






1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
                              "%s/artifact/%s?txt=1", g.zTop, zUuid);
      }
    }
  }
  if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){
    style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid);
  }






  @ <hr />
  content_get(rid, &content);
  if( renderAsWiki ){
    wiki_render_by_mimetype(&content, zMime);
  }else if( renderAsHtml ){
    @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
    @   width="100%%" frameborder="0" marginwidth="0" marginheight="0"
    @   sandbox="allow-same-origin"
    @   onload="this.height = this.contentDocument.documentElement.scrollHeight;">
    @ </iframe>
  }else{
    style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
    blob_to_utf8_no_bom(&content, 0);
    zMime = mimetype_from_content(&content);
    @ <blockquote>
    if( zMime==0 ){
      const char *zLn = P("ln");
      const char *z;
      z = blob_str(&content);
      if( zLn ){
        output_text_with_line_numbers(z, zLn);
      }else{
        @ <pre>
        @ %h(z)
        @ </pre>
      }
    }else if( strncmp(zMime, "image/", 6)==0 ){
      @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" />
      style_submenu_element("Image", "Image",
                            "%R/raw/%s?m=%s", zUuid, zMime);
    }else{
      @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
    }
    @ </blockquote>

  }
  style_footer();
}

/*
** WEBPAGE: tinfo
** URL: /tinfo?name=ARTIFACTID







>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
                              "%s/artifact/%s?txt=1", g.zTop, zUuid);
      }
    }
  }
  if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){
    style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid);
  }
  if( descOnly ){
    style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid);
  }else{
    style_submenu_element("Line Numbers", "Line Numbers",
                          "%R/info/%s%s",zUuid,
                          ((zLn&&*zLn) ? "" : "?ln=0"));
    @ <hr />
    content_get(rid, &content);
    if( renderAsWiki ){
      wiki_render_by_mimetype(&content, zMime);
    }else if( renderAsHtml ){
      @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
      @   width="100%%" frameborder="0" marginwidth="0" marginheight="0"
      @   sandbox="allow-same-origin"
      @   onload="this.height = this.contentDocument.documentElement.scrollHeight;">
      @ </iframe>
    }else{
      style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
      blob_to_utf8_no_bom(&content, 0);
      zMime = mimetype_from_content(&content);
      @ <blockquote>
      if( zMime==0 ){

        const char *z;
        z = blob_str(&content);
        if( zLn ){
          output_text_with_line_numbers(z, zLn);
        }else{
          @ <pre>
          @ %h(z)
          @ </pre>
        }
      }else if( strncmp(zMime, "image/", 6)==0 ){
        @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" />
        style_submenu_element("Image", "Image",
                              "%R/raw/%s?m=%s", zUuid, zMime);
      }else{
        @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
      }
      @ </blockquote>
    }
  }
  style_footer();
}

/*
** WEBPAGE: tinfo
** URL: /tinfo?name=ARTIFACTID
1806
1807
1808
1809
1810
1811
1812






1813
1814




1815
1816
1817
1818
1819
1820
1821
  pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
  if( pTktChng==0 ) fossil_redirect_home();
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
  if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);






      cgi_redirectf("%R/tktview/%s", zTktName);
      /*NOTREACHED*/




    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  zTktTitle = db_table_has_column( "ticket", "title" )
      ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)







>
>
>
>
>
>
|
|
>
>
>
>







1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
  pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
  if( pTktChng==0 ) fossil_redirect_home();
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
  if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the ticket still exists; if not, we cannot
      ** redirect to it.
      */
      if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'",
                    zTktName) ){
        cgi_redirectf("%R/tktview/%s", zTktName);
        /*NOTREACHED*/
      }else{
        cgi_redirectf("%R/modreq");
        /*NOTREACHED*/
      }
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  zTktTitle = db_table_has_column( "ticket", "title" )
      ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
2071
2072
2073
2074
2075
2076
2077
2078


2079
2080
2081
2082
2083
2084
2085
    @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)"
    @  checked="checked" onclick="gebi('%s(zIdCustom)').select();" />
  }
  @ %h(aColor[i].zCName)</label>&nbsp;
  @ <input type="text" name="%s(zIdCustom)"
  @  id="%s(zIdCustom)" class="checkinUserColor"
  @  value="%h(stdClrFound?"":zDefaultColor)"
  @  onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;" />


  @ </td>
  @ </tr>
  @ </table>
}

/*
** Do a comment comparison.







|
>
>







2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
    @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)"
    @  checked="checked" onclick="gebi('%s(zIdCustom)').select();" />
  }
  @ %h(aColor[i].zCName)</label>&nbsp;
  @ <input type="text" name="%s(zIdCustom)"
  @  id="%s(zIdCustom)" class="checkinUserColor"
  @  value="%h(stdClrFound?"":zDefaultColor)"
  @  onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;"
  @  onload="this.blur();"
  @  onblur="this.parentElement.style.backgroundColor = this.value ? ('#'+this.value.replace('#','')) : '';" />
  @ </td>
  @ </tr>
  @ </table>
}

/*
** Do a comment comparison.
Changes to src/json.c.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
**
*******************************************************************************
**
** Code for the JSON API.
**
** For notes regarding the public JSON interface, please see:
**
** https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/edit
**
**
** Notes for hackers...
**
** Here's how command/page dispatching works: json_page_top() (in HTTP mode) or
** json_cmd_top() (in CLI mode) catch the "json" path/command. Those functions then
** dispatch to a JSON-mode-specific command/page handler with the type fossil_json_f().







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
**
*******************************************************************************
**
** Code for the JSON API.
**
** For notes regarding the public JSON interface, please see:
**
** https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/view
**
**
** Notes for hackers...
**
** Here's how command/page dispatching works: json_page_top() (in HTTP mode) or
** json_cmd_top() (in CLI mode) catch the "json" path/command. Those functions then
** dispatch to a JSON-mode-specific command/page handler with the type fossil_json_f().
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
};



/*
** Returns true (non-0) if fossil appears to be running in JSON mode.
*/
char fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
*/







|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
};



/*
** Returns true (non-0) if fossil appears to be running in JSON mode.
*/
int fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
*/
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
**
** If an entry is found, this function guarantees that it will return
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
char json_getenv_bool(char const * pKey, char dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return cson_value_get_integer(v) ? 1 : 0;
    case CSON_TYPE_STRING: {







|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
**
** If an entry is found, this function guarantees that it will return
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
int json_getenv_bool(char const * pKey, int dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return cson_value_get_integer(v) ? 1 : 0;
    case CSON_TYPE_STRING: {
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1);
}

/*
** The boolean equivalent of json_find_option_cstr().
** If the option is not found, dftl is returned.
*/
char json_find_option_bool(char const * zKey,
                           char const * zCLILong,
                           char const * zCLIShort,
                           char dflt ){
  char rc = -1;
  if(!g.isHTTP){
    if(NULL != find_option(zCLILong ? zCLILong : zKey,
                           zCLIShort, 0)){
      rc = 1;
    }
  }
  if((-1==rc) && fossil_has_json()){







|
|
|
|
|







473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1);
}

/*
** The boolean equivalent of json_find_option_cstr().
** If the option is not found, dftl is returned.
*/
int json_find_option_bool(char const * zKey,
                          char const * zCLILong,
                          char const * zCLIShort,
                          char dflt ){
  int rc = -1;
  if(!g.isHTTP){
    if(NULL != find_option(zCLILong ? zCLILong : zKey,
                           zCLIShort, 0)){
      rc = 1;
    }
  }
  if((-1==rc) && fossil_has_json()){
Changes to src/json_detail.h.
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
** b) We are running in JSON CLI mode, but no POST data has been fed
** in.
**
** Whether or not we need to take args from CLI or POST data makes a
** difference in argument/parameter handling in many JSON routines,
** and thus this distinction.
*/
char fossil_has_json();

enum json_get_changed_files_flags {
    json_get_changed_files_ELIDE_PARENT = 1 << 0
};

#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
#endif /* FOSSIL_ENABLE_JSON */







|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
** b) We are running in JSON CLI mode, but no POST data has been fed
** in.
**
** Whether or not we need to take args from CLI or POST data makes a
** difference in argument/parameter handling in many JSON routines,
** and thus this distinction.
*/
int fossil_has_json();

enum json_get_changed_files_flags {
    json_get_changed_files_ELIDE_PARENT = 1 << 0
};

#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
#endif /* FOSSIL_ENABLE_JSON */
Changes to src/json_wiki.c.
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }

  zMimeType = json_find_option_cstr("mimetype","mimetype","M");

  wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType);
  blob_reset(&content);
  /*
    Our return value here has a race condition: if this operation
    is called concurrently for the same wiki page via two requests,
    payV could reflect the results of the other save operation.
  */
  payV = json_get_wiki_page_by_name(







|







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }

  zMimeType = json_find_option_cstr("mimetype","mimetype","M");

  wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType, 0);
  blob_reset(&content);
  /*
    Our return value here has a race condition: if this operation
    is called concurrently for the same wiki page via two requests,
    payV could reflect the results of the other save operation.
  */
  payV = json_get_wiki_page_by_name(
Changes to src/login.c.
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
** Searches for the user ID matching the given name and password.
** On success it returns a positive value. On error it returns 0.
** On serious (DB-level) error it will probably exit.
**
** zPassword may be either the plain-text form or the encrypted
** form of the user's password.
*/
int login_search_uid(char const *zUsername, char const *zPasswd){
  char * zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
  int const uid =
      db_int(0,
             "SELECT uid FROM user"
             " WHERE login=%Q"
             "   AND length(cap)>0 AND length(pw)>0"
             "   AND login NOT IN ('anonymous','nobody','developer','reader')"
             "   AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))",







|
|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
** Searches for the user ID matching the given name and password.
** On success it returns a positive value. On error it returns 0.
** On serious (DB-level) error it will probably exit.
**
** zPassword may be either the plain-text form or the encrypted
** form of the user's password.
*/
int login_search_uid(const char *zUsername, const char *zPasswd){
  char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
  int const uid =
      db_int(0,
             "SELECT uid FROM user"
             " WHERE login=%Q"
             "   AND length(cap)>0 AND length(pw)>0"
             "   AND login NOT IN ('anonymous','nobody','developer','reader')"
             "   AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))",
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
** Generates a login cookie value for a non-anonymous user.
**
** The zHash parameter must be a random value which must be
** subsequently stored in user.cookie for later validation.
**
** The returned memory should be free()d after use.
*/
char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
  char * zProjCode = db_get("project-code",NULL);
  char *zCode = abbreviated_project_code(zProjCode);
  free(zProjCode);
  assert((zUsername && *zUsername) && "Invalid user data.");
  return mprintf("%s/%z/%s", zHash, zCode, zUsername);
}

/*
** Generates a login cookie for NON-ANONYMOUS users.  Note that this
** function "could" figure out the uid by itself but it currently
** doesn't because the code which calls this already has the uid.
**
** This function also updates the user.cookie, user.ipaddr,
** and user.cexpire fields for the given user.
**
** If zDest is not NULL then the generated cookie is copied to
** *zDdest and ownership is transfered to the caller (who should
** eventually pass it to free()).
*/
void login_set_user_cookie(
  char const * zUsername, /* User's name */
  int uid,                /* User's ID */
  char ** zDest           /* Optional: store generated cookie value. */
){
  const char *zCookieName = login_cookie_name();
  const char *zExpire = db_get("cookie-expire","8766");
  int expires = atoi(zExpire)*3600;
  char *zHash;
  char *zCookie;
  char const *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
  char *zRemoteAddr = ipPrefix(zIpAddr);         /* Abbreviated IP address */

  assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
  zHash = db_text(0,
      "SELECT cookie FROM user"
      " WHERE uid=%d"
      "   AND ipaddr=%Q"







|
|



















|

|






|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
** Generates a login cookie value for a non-anonymous user.
**
** The zHash parameter must be a random value which must be
** subsequently stored in user.cookie for later validation.
**
** The returned memory should be free()d after use.
*/
char *login_gen_user_cookie_value(const char *zUsername, const char *zHash){
  char *zProjCode = db_get("project-code",NULL);
  char *zCode = abbreviated_project_code(zProjCode);
  free(zProjCode);
  assert((zUsername && *zUsername) && "Invalid user data.");
  return mprintf("%s/%z/%s", zHash, zCode, zUsername);
}

/*
** Generates a login cookie for NON-ANONYMOUS users.  Note that this
** function "could" figure out the uid by itself but it currently
** doesn't because the code which calls this already has the uid.
**
** This function also updates the user.cookie, user.ipaddr,
** and user.cexpire fields for the given user.
**
** If zDest is not NULL then the generated cookie is copied to
** *zDdest and ownership is transfered to the caller (who should
** eventually pass it to free()).
*/
void login_set_user_cookie(
  const char *zUsername,  /* User's name */
  int uid,                /* User's ID */
  char **zDest            /* Optional: store generated cookie value. */
){
  const char *zCookieName = login_cookie_name();
  const char *zExpire = db_get("cookie-expire","8766");
  int expires = atoi(zExpire)*3600;
  char *zHash;
  char *zCookie;
  const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
  char *zRemoteAddr = ipPrefix(zIpAddr);         /* Abbreviated IP address */

  assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
  zHash = db_text(0,
      "SELECT cookie FROM user"
      " WHERE uid=%d"
      "   AND ipaddr=%Q"
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
**
** If either zIpAddr or zRemoteAddr are NULL then REMOTE_ADDR
** is used.
**
** If zCookieDest is not NULL then the generated cookie is assigned to
** *zCookieDest and the caller must eventually free() it.
*/
void login_set_anon_cookie(char const * zIpAddr, char ** zCookieDest ){
  char const *zNow;            /* Current time (julian day number) */
  char *zCookie;               /* The login cookie */
  char const *zCookieName;     /* Name of the login cookie */
  Blob b;                      /* Blob used during cookie construction */
  char * zRemoteAddr;     /* Abbreviated IP address */
  if(!zIpAddr){
    zIpAddr = PD("REMOTE_ADDR","nil");
  }
  zRemoteAddr = ipPrefix(zIpAddr);
  zCookieName = login_cookie_name();
  zNow = db_text("0", "SELECT julianday('now')");
  assert( zCookieName && zRemoteAddr && zIpAddr && zNow );







|
|

|

|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
**
** If either zIpAddr or zRemoteAddr are NULL then REMOTE_ADDR
** is used.
**
** If zCookieDest is not NULL then the generated cookie is assigned to
** *zCookieDest and the caller must eventually free() it.
*/
void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
  const char *zNow;            /* Current time (julian day number) */
  char *zCookie;               /* The login cookie */
  const char *zCookieName;     /* Name of the login cookie */
  Blob b;                      /* Blob used during cookie construction */
  char *zRemoteAddr;           /* Abbreviated IP address */
  if(!zIpAddr){
    zIpAddr = PD("REMOTE_ADDR","nil");
  }
  zRemoteAddr = ipPrefix(zIpAddr);
  zCookieName = login_cookie_name();
  zNow = db_text("0", "SELECT julianday('now')");
  assert( zCookieName && zRemoteAddr && zIpAddr && zNow );
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
**
** This is a no-op if g.userUid is 0.
*/
void login_clear_login_data(){
  if(!g.userUid){
    return;
  }else{
    char const * cookie = login_cookie_name();
    /* To logout, change the cookie value to an empty string */
    cgi_set_cookie(cookie, "",
                   login_cookie_path(), -86400);
    db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
                  "  cexpire=0 WHERE uid=%d"
                  "  AND login NOT IN ('anonymous','nobody',"
                  "  'developer','reader')", g.userUid);







|







342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
**
** This is a no-op if g.userUid is 0.
*/
void login_clear_login_data(){
  if(!g.userUid){
    return;
  }else{
    const char *cookie = login_cookie_name();
    /* To logout, change the cookie value to an empty string */
    cgi_set_cookie(cookie, "",
                   login_cookie_path(), -86400);
    db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
                  "  cexpire=0 WHERE uid=%d"
                  "  AND login NOT IN ('anonymous','nobody',"
                  "  'developer','reader')", g.userUid);
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
  @ the login to take.</p>
  if( db_get_boolean("self-register", 0) ){
    @ <p>If you do not have an account, you can
    @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
  }
  if( zAnonPw ){
    unsigned int uSeed = captcha_seed();
    char const *zDecoded = captcha_decode(uSeed);
    int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
    char *zCaptcha = captcha_render(zDecoded);

    @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
    @ Visitors may enter <b>anonymous</b> as the user-ID with
    @ the 8-character hexadecimal password shown below:</p>
    @ <div class="captcha"><table class="captcha"><tr><td><pre>







|







627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
  @ the login to take.</p>
  if( db_get_boolean("self-register", 0) ){
    @ <p>If you do not have an account, you can
    @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
  }
  if( zAnonPw ){
    unsigned int uSeed = captcha_seed();
    const char *zDecoded = captcha_decode(uSeed);
    int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
    char *zCaptcha = captcha_render(zDecoded);

    @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
    @ Visitors may enter <b>anonymous</b> as the user-ID with
    @ the 8-character hexadecimal password shown below:</p>
    @ <div class="captcha"><table class="captcha"><tr><td><pre>
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
**
** Generate the register page.
**
*/
void register_page(void){
  const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
  unsigned int uSeed;
  char const *zDecoded;
  char *zCaptcha;
  if( !db_get_boolean("self-register", 0) ){
    style_header("Registration not possible");
    @ <p>This project does not allow user self-registration. Please contact the
    @ project administrator to obtain an account.</p>
    style_footer();
    return;







|







1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
**
** Generate the register page.
**
*/
void register_page(void){
  const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
  unsigned int uSeed;
  const char *zDecoded;
  char *zCaptcha;
  if( !db_get_boolean("self-register", 0) ){
    style_header("Registration not possible");
    @ <p>This project does not allow user self-registration. Please contact the
    @ project administrator to obtain an account.</p>
    style_footer();
    return;
Changes to src/main.c.
28
29
30
31
32
33
34
35
36
37






38
39
40
41
42
43
44
#include <sys/stat.h>
#include <stdlib.h> /* atexit() */
#if defined(_WIN32)
#  include <windows.h>
#else
#  include <errno.h> /* errno global */
#endif
#include "zlib.h"
#ifdef FOSSIL_ENABLE_SSL
#  include "openssl/opensslv.h"






#endif
#if INTERFACE
#ifdef FOSSIL_ENABLE_TCL
#  include "tcl.h"
#endif
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. */







<

|
>
>
>
>
>
>







28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <sys/stat.h>
#include <stdlib.h> /* atexit() */
#if defined(_WIN32)
#  include <windows.h>
#else
#  include <errno.h> /* errno global */
#endif

#ifdef FOSSIL_ENABLE_SSL
#  include "openssl/crypto.h"
#endif
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif
#if INTERFACE
#ifdef FOSSIL_ENABLE_TCL
#  include "tcl.h"
#endif
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. */
122
123
124
125
126
127
128

129
130
131
132
133
134
135
  const char *zVfsName;   /* The VFS to use for database connections */
  sqlite3 *db;            /* The connection to the databases */
  sqlite3 *dbConfig;      /* Separate connection for global_config table */
  int useAttach;          /* True if global_config is attached to repository */
  const char *zConfigDbName;/* Path of the config database. NULL if not open */
  sqlite3_int64 now;      /* Seconds since 1970 */
  int repositoryOpen;     /* True if the main repository database is open */

  char *zRepositoryName;  /* Name of the repository database */
  const char *zMainDbType;/* "configdb", "localdb", or "repository" */
  const char *zConfigDbType;  /* "configdb", "localdb", or "repository" */
  int localOpen;          /* True if the local database is open */
  char *zLocalRoot;       /* The directory holding the  local database */
  int minPrefix;          /* Number of digits needed for a distinct UUID */
  int fSqlTrace;          /* True if --sqltrace flag is present */







>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  const char *zVfsName;   /* The VFS to use for database connections */
  sqlite3 *db;            /* The connection to the databases */
  sqlite3 *dbConfig;      /* Separate connection for global_config table */
  int useAttach;          /* True if global_config is attached to repository */
  const char *zConfigDbName;/* Path of the config database. NULL if not open */
  sqlite3_int64 now;      /* Seconds since 1970 */
  int repositoryOpen;     /* True if the main repository database is open */
  char *zRepositoryOption; /* Most recent cached repository option value */
  char *zRepositoryName;  /* Name of the repository database */
  const char *zMainDbType;/* "configdb", "localdb", or "repository" */
  const char *zConfigDbType;  /* "configdb", "localdb", or "repository" */
  int localOpen;          /* True if the local database is open */
  char *zLocalRoot;       /* The directory holding the  local database */
  int minPrefix;          /* Number of digits needed for a distinct UUID */
  int fSqlTrace;          /* True if --sqltrace flag is present */
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223



224
225
226
227
228
229
230
  int sslNotAvailable;    /* SSL is not available.  Do not redirect to https: */
  Blob cgiIn;             /* Input to an xfer www method */
  int cgiOutput;          /* Write error and status messages to CGI */
  int xferPanic;          /* Write error messages in XFER protocol */
  int fullHttpReply;      /* True for full HTTP reply.  False for CGI reply */
  Th_Interp *interp;      /* The TH1 interpreter */
  char *th1Setup;         /* The TH1 post-creation setup script, if any */

  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int wikiFlags;          /* Wiki conversion flags applied to %w and %W */
  char isHTTP;            /* True if server/CGI modes, else assume CLI. */
  char javascriptHyperlink; /* If true, set href= using script, not HTML */
  Blob httpHeader;        /* Complete text of the HTTP request header */
  UrlData url;            /* Information about current URL */
#if 0
  /*
  ** NOTE: These members MUST be kept in sync with those in the "UrlData"
  **       structure defined in "url.c".
  */
  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
  char *urlName;          /* Hostname for http: or filename for file: */
  char *urlHostname;      /* The HOST: parameter on http headers */
  char *urlProtocol;      /* "http" or "https" */
  int urlPort;            /* TCP port number for http: or https: */
  int urlDfltPort;        /* The default port for the given protocol */
  char *urlPath;          /* Pathname for http: */
  char *urlUser;          /* User id for http: */
  char *urlPasswd;        /* Password for http: */
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  char *urlFossil;        /* The fossil query parameter on ssh: */
  unsigned urlFlags;      /* Boolean flags controlling URL processing */
  int useProxy;           /* Used to remember that a proxy is in use */
  char *proxyUrlPath;
  int proxyOrigPort;      /* Tunneled port number for https through proxy */
#endif

  const char *zLogin;     /* Login name.  NULL or "" if not logged in. */
  const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
                             ** SSL client identity */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */
  int isHuman;            /* True if access by a human, not a spider or bot */


  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */
  char *zIpAddr;          /* The remote IP address */
  char *zNonce;           /* The nonce used for login */

  /* permissions used by the server */
  struct FossilUserPerms perm;

#ifdef FOSSIL_ENABLE_TCL
  /* all Tcl related context necessary for integration */
  struct TclContext tcl;
#endif

  /* For defense against Cross-site Request Forgery attacks */
  char zCsrfToken[12];    /* Value of the anti-CSRF token */
  int okCsrf;             /* Anti-CSRF token is present and valid */

  int parseCnt[10];       /* Counts of artifacts parsed */
  FILE *fDebug;           /* Write debug information here, if the file exists */



  int thTrace;            /* True to enable TH1 debugging output */
  Blob thLog;             /* Text of the TH1 debugging output */

  int isHome;             /* True if rendering the "home" page */

  /* Storage for the aux() and/or option() SQL function arguments */
  int nAux;                    /* Number of distinct aux() or option() values */







>












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







>




















>
>
>







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

























179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  int sslNotAvailable;    /* SSL is not available.  Do not redirect to https: */
  Blob cgiIn;             /* Input to an xfer www method */
  int cgiOutput;          /* Write error and status messages to CGI */
  int xferPanic;          /* Write error messages in XFER protocol */
  int fullHttpReply;      /* True for full HTTP reply.  False for CGI reply */
  Th_Interp *interp;      /* The TH1 interpreter */
  char *th1Setup;         /* The TH1 post-creation setup script, if any */
  int th1Flags;           /* The TH1 integration state flags */
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int wikiFlags;          /* Wiki conversion flags applied to %w and %W */
  char isHTTP;            /* True if server/CGI modes, else assume CLI. */
  char javascriptHyperlink; /* If true, set href= using script, not HTML */
  Blob httpHeader;        /* Complete text of the HTTP request header */
  UrlData url;            /* Information about current URL */

























  const char *zLogin;     /* Login name.  NULL or "" if not logged in. */
  const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
                             ** SSL client identity */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */
  int isHuman;            /* True if access by a human, not a spider or bot */
  int comFmtFlags;        /* Zero or more "COMMENT_PRINT_*" bit flags */

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */
  char *zIpAddr;          /* The remote IP address */
  char *zNonce;           /* The nonce used for login */

  /* permissions used by the server */
  struct FossilUserPerms perm;

#ifdef FOSSIL_ENABLE_TCL
  /* all Tcl related context necessary for integration */
  struct TclContext tcl;
#endif

  /* For defense against Cross-site Request Forgery attacks */
  char zCsrfToken[12];    /* Value of the anti-CSRF token */
  int okCsrf;             /* Anti-CSRF token is present and valid */

  int parseCnt[10];       /* Counts of artifacts parsed */
  FILE *fDebug;           /* Write debug information here, if the file exists */
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  int fNoThHook;          /* Disable all TH1 command/webpage hooks */
#endif
  int thTrace;            /* True to enable TH1 debugging output */
  Blob thLog;             /* Text of the TH1 debugging output */

  int isHome;             /* True if rendering the "home" page */

  /* Storage for the aux() and/or option() SQL function arguments */
  int nAux;                    /* Number of distinct aux() or option() values */
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
                                  responses and always exit() with
                                  code 0 to avoid an HTTP 500 error.
                               */
    int resultCode;            /* used for passing back specific codes
                               ** from /json callbacks. */
    int errorDetailParanoia;   /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
    cson_output_opt outOpt;    /* formatting options for JSON mode. */
    cson_value * authToken;    /* authentication token */
    char const * jsonp;        /* Name of JSONP function wrapper. */
    unsigned char dispatchDepth /* Tells JSON command dispatching
                                   which argument we are currently
                                   working on. For this purpose, arg#0
                                   is the "json" path/CLI arg.
                                */;
    struct {                   /* "garbage collector" */
      cson_value * v;
      cson_array * a;
    } gc;
    struct {                   /* JSON POST data. */
      cson_value * v;
      cson_array * a;
      int offset;              /* Tells us which PATH_INFO/CLI args
                                  part holds the "json" command, so
                                  that we can account for sub-repos
                                  and path prefixes.  This is handled
                                  differently for CLI and CGI modes.
                               */
      char const * commandStr  /*"command" request param.*/;
    } cmd;
    struct {                   /* JSON POST data. */
      cson_value * v;
      cson_object * o;
    } post;
    struct {                   /* GET/COOKIE params in JSON mode. */
      cson_value * v;
      cson_object * o;
    } param;
    struct {
      cson_value * v;
      cson_object * o;
    } reqPayload;              /* request payload object (if any) */
    cson_array * warnings;     /* response warnings */
    int timerId;               /* fetched from fossil_timer_start() */
  } json;
#endif /* FOSSIL_ENABLE_JSON */
};

/*
** Macro for debugging:







|
|






|
|


|
|






|


|
|


|
|


|
|

|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
                                  responses and always exit() with
                                  code 0 to avoid an HTTP 500 error.
                               */
    int resultCode;            /* used for passing back specific codes
                               ** from /json callbacks. */
    int errorDetailParanoia;   /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
    cson_output_opt outOpt;    /* formatting options for JSON mode. */
    cson_value *authToken;     /* authentication token */
    const char *jsonp;         /* Name of JSONP function wrapper. */
    unsigned char dispatchDepth /* Tells JSON command dispatching
                                   which argument we are currently
                                   working on. For this purpose, arg#0
                                   is the "json" path/CLI arg.
                                */;
    struct {                   /* "garbage collector" */
      cson_value *v;
      cson_array *a;
    } gc;
    struct {                   /* JSON POST data. */
      cson_value *v;
      cson_array *a;
      int offset;              /* Tells us which PATH_INFO/CLI args
                                  part holds the "json" command, so
                                  that we can account for sub-repos
                                  and path prefixes.  This is handled
                                  differently for CLI and CGI modes.
                               */
      const char *commandStr   /*"command" request param.*/;
    } cmd;
    struct {                   /* JSON POST data. */
      cson_value *v;
      cson_object *o;
    } post;
    struct {                   /* GET/COOKIE params in JSON mode. */
      cson_value *v;
      cson_object *o;
    } param;
    struct {
      cson_value *v;
      cson_object *o;
    } reqPayload;              /* request payload object (if any) */
    cson_array *warnings;      /* response warnings */
    int timerId;               /* fetched from fossil_timer_start() */
  } json;
#endif /* FOSSIL_ENABLE_JSON */
};

/*
** Macro for debugging:
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
** defined in the page_index.h header file which is automatically
** generated by mkindex.c program.
*/
static int name_search(
  const char *zName,       /* The name we are looking for */
  const NameMap *aMap,     /* Search in this array */
  int nMap,                /* Number of slots in aMap[] */

  int *pIndex              /* OUT: The index in aMap[] of the match */
){
  int upr, lwr, cnt, m, i;
  int n = strlen(zName);
  lwr = 0;
  upr = nMap-1;
  while( lwr<=upr ){
    int mid, c;
    mid = (upr+lwr)/2;
    c = fossil_strcmp(zName, aMap[mid].zName);
    if( c==0 ){
      *pIndex = mid;
      return 0;
    }else if( c<0 ){
      upr = mid - 1;
    }else{
      lwr = mid + 1;
    }
  }
  for(m=cnt=0, i=upr-2; cnt<2 && i<=upr+3 && i<nMap; i++){
    if( i<0 ) continue;
    if( strncmp(zName, aMap[i].zName, n)==0 ){
      m = i;
      cnt++;
    }
  }
  if( cnt==1 ){
    *pIndex = m;







>




|















|







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
** defined in the page_index.h header file which is automatically
** generated by mkindex.c program.
*/
static int name_search(
  const char *zName,       /* The name we are looking for */
  const NameMap *aMap,     /* Search in this array */
  int nMap,                /* Number of slots in aMap[] */
  int iBegin,              /* Lower bound on the array search */
  int *pIndex              /* OUT: The index in aMap[] of the match */
){
  int upr, lwr, cnt, m, i;
  int n = strlen(zName);
  lwr = iBegin;
  upr = nMap-1;
  while( lwr<=upr ){
    int mid, c;
    mid = (upr+lwr)/2;
    c = fossil_strcmp(zName, aMap[mid].zName);
    if( c==0 ){
      *pIndex = mid;
      return 0;
    }else if( c<0 ){
      upr = mid - 1;
    }else{
      lwr = mid + 1;
    }
  }
  for(m=cnt=0, i=upr-2; cnt<2 && i<=upr+3 && i<nMap; i++){
    if( i<iBegin ) continue;
    if( strncmp(zName, aMap[i].zName, n)==0 ){
      m = i;
      cnt++;
    }
  }
  if( cnt==1 ){
    *pIndex = m;
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  Blob file = empty_blob;   /* Content of the file */
  Blob line = empty_blob;   /* One line of the file */
  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */
  int n;                    /* Number of bytes in one line */
  char *z;                  /* General use string pointer */
  char **newArgv;           /* New expanded g.argv under construction */
  char const * zFileName;   /* input file name */
  FILE *inFile;             /* input FILE */
#if defined(_WIN32)
  wchar_t buf[MAX_PATH];
#endif

  g.argc = argc;
  g.argv = argv;







|







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  Blob file = empty_blob;   /* Content of the file */
  Blob line = empty_blob;   /* One line of the file */
  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */
  int n;                    /* Number of bytes in one line */
  char *z;                  /* General use string pointer */
  char **newArgv;           /* New expanded g.argv under construction */
  const char *zFileName;    /* input file name */
  FILE *inFile;             /* input FILE */
#if defined(_WIN32)
  wchar_t buf[MAX_PATH];
#endif

  g.argc = argc;
  g.argv = argv;
506
507
508
509
510
511
512
513
514
515
516
517
518
519

520
521
522

523
524
525
526
527

528
529
530
531
532

533
534
535
536

537
538
539

540


541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556















557
558
559
560
561
562
563
    zNewArgv[i] = fossil_strdup(argv[i]);
  }
  return zNewArgv;
}
#endif

/*
** Return a name for an SQLite error code
*/
static const char *sqlite_error_code_name(int iCode){
  static char zCode[30];
  switch( iCode & 0xff ){
    case SQLITE_OK:         return "SQLITE_OK";
    case SQLITE_ERROR:      return "SQLITE_ERROR";

    case SQLITE_PERM:       return "SQLITE_PERM";
    case SQLITE_ABORT:      return "SQLITE_ABORT";
    case SQLITE_BUSY:       return "SQLITE_BUSY";

    case SQLITE_NOMEM:      return "SQLITE_NOMEM";
    case SQLITE_READONLY:   return "SQLITE_READONLY";
    case SQLITE_INTERRUPT:  return "SQLITE_INTERRUPT";
    case SQLITE_IOERR:      return "SQLITE_IOERR";
    case SQLITE_CORRUPT:    return "SQLITE_CORRUPT";

    case SQLITE_FULL:       return "SQLITE_FULL";
    case SQLITE_CANTOPEN:   return "SQLITE_CANTOPEN";
    case SQLITE_PROTOCOL:   return "SQLITE_PROTOCOL";
    case SQLITE_EMPTY:      return "SQLITE_EMPTY";
    case SQLITE_SCHEMA:     return "SQLITE_SCHEMA";

    case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
    case SQLITE_MISMATCH:   return "SQLITE_MISMATCH";
    case SQLITE_MISUSE:     return "SQLITE_MISUSE";
    case SQLITE_NOLFS:      return "SQLITE_NOLFS";

    case SQLITE_FORMAT:     return "SQLITE_FORMAT";
    case SQLITE_RANGE:      return "SQLITE_RANGE";
    case SQLITE_NOTADB:     return "SQLITE_NOTADB";

    case SQLITE_WARNING:    return "SQLITE_WARNING";


    default: {
      sqlite3_snprintf(sizeof(zCode),zCode,"error code %d",iCode);
    }
  }
  return zCode;
}

/* Error logs from SQLite */
static void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
#ifdef __APPLE__
  /* Disable the file alias warning on apple products because Time Machine
  ** creates lots of aliases and the warning alarms people. */
  if( iCode==SQLITE_WARNING ) return;
#endif
  if( iCode==SQLITE_SCHEMA ) return;
  fossil_warning("%s: %s", sqlite_error_code_name(iCode), zErrmsg);















}

/*
** This procedure runs first.
*/
#if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
int _dowildcard = -1; /* This turns on command-line globbing in MinGW-w64 */







|

|

|


>



>





>





>




>



>

>
>

|













|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
    zNewArgv[i] = fossil_strdup(argv[i]);
  }
  return zNewArgv;
}
#endif

/*
** Returns a name for a SQLite return code.
*/
static const char *fossil_sqlite_return_code_name(int rc){
  static char zCode[30];
  switch( rc & 0xff ){
    case SQLITE_OK:         return "SQLITE_OK";
    case SQLITE_ERROR:      return "SQLITE_ERROR";
    case SQLITE_INTERNAL:   return "SQLITE_INTERNAL";
    case SQLITE_PERM:       return "SQLITE_PERM";
    case SQLITE_ABORT:      return "SQLITE_ABORT";
    case SQLITE_BUSY:       return "SQLITE_BUSY";
    case SQLITE_LOCKED:     return "SQLITE_LOCKED";
    case SQLITE_NOMEM:      return "SQLITE_NOMEM";
    case SQLITE_READONLY:   return "SQLITE_READONLY";
    case SQLITE_INTERRUPT:  return "SQLITE_INTERRUPT";
    case SQLITE_IOERR:      return "SQLITE_IOERR";
    case SQLITE_CORRUPT:    return "SQLITE_CORRUPT";
    case SQLITE_NOTFOUND:   return "SQLITE_NOTFOUND";
    case SQLITE_FULL:       return "SQLITE_FULL";
    case SQLITE_CANTOPEN:   return "SQLITE_CANTOPEN";
    case SQLITE_PROTOCOL:   return "SQLITE_PROTOCOL";
    case SQLITE_EMPTY:      return "SQLITE_EMPTY";
    case SQLITE_SCHEMA:     return "SQLITE_SCHEMA";
    case SQLITE_TOOBIG:     return "SQLITE_TOOBIG";
    case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
    case SQLITE_MISMATCH:   return "SQLITE_MISMATCH";
    case SQLITE_MISUSE:     return "SQLITE_MISUSE";
    case SQLITE_NOLFS:      return "SQLITE_NOLFS";
    case SQLITE_AUTH:       return "SQLITE_AUTH";
    case SQLITE_FORMAT:     return "SQLITE_FORMAT";
    case SQLITE_RANGE:      return "SQLITE_RANGE";
    case SQLITE_NOTADB:     return "SQLITE_NOTADB";
    case SQLITE_NOTICE:     return "SQLITE_NOTICE";
    case SQLITE_WARNING:    return "SQLITE_WARNING";
    case SQLITE_ROW:        return "SQLITE_ROW";
    case SQLITE_DONE:       return "SQLITE_DONE";
    default: {
      sqlite3_snprintf(sizeof(zCode), zCode, "SQLite return code %d", rc);
    }
  }
  return zCode;
}

/* Error logs from SQLite */
static void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
#ifdef __APPLE__
  /* Disable the file alias warning on apple products because Time Machine
  ** creates lots of aliases and the warning alarms people. */
  if( iCode==SQLITE_WARNING ) return;
#endif
  if( iCode==SQLITE_SCHEMA ) return;
  fossil_warning("%s: %s", fossil_sqlite_return_code_name(iCode), zErrmsg);
}

/*
** This function attempts to find command line options known to contain
** bitwise flags and initializes the associated global variables.  After
** this function executes, all global variables (i.e. in the "g" struct)
** containing option-settable bitwise flag fields must be initialized.
*/
static void fossil_init_flags_from_options(void){
  const char *zValue = find_option("comfmtflags", 0, 1);
  if( zValue ){
    g.comFmtFlags = atoi(zValue);
  }else{
    g.comFmtFlags = COMMENT_PRINT_DEFAULT;
  }
}

/*
** This procedure runs first.
*/
#if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
int _dowildcard = -1; /* This turns on command-line globbing in MinGW-w64 */
572
573
574
575
576
577
578
579


580
581
582
583
584
585
586
  const char *zCmdName = "unknown";
  int idx;
  int rc;
  if( sqlite3_libversion_number()<3007017 ){
    fossil_fatal("Unsuitable SQLite version %s, must be at least 3.7.17",
                 sqlite3_libversion());
  }
  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);


  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);
  g.httpHeader = empty_blob;
#ifdef FOSSIL_ENABLE_JSON
#if defined(NDEBUG)
  g.json.errorDetailParanoia = 2 /* FIXME: make configurable







|
>
>







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  const char *zCmdName = "unknown";
  int idx;
  int rc;
  if( sqlite3_libversion_number()<3007017 ){
    fossil_fatal("Unsuitable SQLite version %s, must be at least 3.7.17",
                 sqlite3_libversion());
  }
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(32); /* SQLITE_CONFIG_EXPLAIN_COMMENTS (old) */
  sqlite3_config(64); /* SQLITE_CONFIG_EXPLAIN_COMMENTS */
  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);
  g.httpHeader = empty_blob;
#ifdef FOSSIL_ENABLE_JSON
#if defined(NDEBUG)
  g.json.errorDetailParanoia = 2 /* FIXME: make configurable
597
598
599
600
601
602
603

604
605
606
607
608
609
610
  expand_args_option(argc, argv);
#ifdef FOSSIL_ENABLE_TCL
  memset(&g.tcl, 0, sizeof(TclContext));
  g.tcl.argc = g.argc;
  g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
#endif
  g.mainTimerId = fossil_timer_start();

  g.zVfsName = find_option("vfs",0,1);
  if( g.zVfsName==0 ){
    g.zVfsName = fossil_getenv("FOSSIL_VFS");
  }
  if( g.zVfsName ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfsName);
    if( pVfs ){







>







609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  expand_args_option(argc, argv);
#ifdef FOSSIL_ENABLE_TCL
  memset(&g.tcl, 0, sizeof(TclContext));
  g.tcl.argc = g.argc;
  g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
#endif
  g.mainTimerId = fossil_timer_start();
  capture_case_sensitive_option();
  g.zVfsName = find_option("vfs",0,1);
  if( g.zVfsName==0 ){
    g.zVfsName = fossil_getenv("FOSSIL_VFS");
  }
  if( g.zVfsName ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfsName);
    if( pVfs ){
643
644
645
646
647
648
649



650
651
652
653

654
655
656
657
658
659
660
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
    g.fSshClient = 0;
    g.zSshCmd = 0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;



    g.zHttpAuth = 0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    g.zErrlog = find_option("errorlog", 0, 1);

    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
    if( zChdir && file_chdir(zChdir, 0) ){
      fossil_fatal("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* --help anywhere on the command line is translated into







>
>
>




>







656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
    g.fSshClient = 0;
    g.zSshCmd = 0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
#endif
    g.zHttpAuth = 0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    g.zErrlog = find_option("errorlog", 0, 1);
    fossil_init_flags_from_options();
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
    if( zChdir && file_chdir(zChdir, 0) ){
      fossil_fatal("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* --help anywhere on the command line is translated into
670
671
672
673
674
675
676
677
678









679
680
681








682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698


























699







700
701
702
703
704
705
706
    }
    zCmdName = g.argv[1];
  }
#ifndef _WIN32
  if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
  /* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */
#endif
  rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
  if( rc==1 ){









    fossil_fatal("%s: unknown command: %s\n"
                 "%s: use \"help\" for more information\n",
                   g.argv[0], zCmdName, g.argv[0]);








  }else if( rc==2 ){
    int i, n;
    Blob couldbe;
    blob_zero(&couldbe);
    n = strlen(zCmdName);
    for(i=0; i<count(aCommand); i++){
      if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
        blob_appendf(&couldbe, " %s", aCommand[i].zName);
      }
    }
    fossil_print("%s: ambiguous command prefix: %s\n"
                 "%s: could be any of:%s\n"
                 "%s: use \"help\" for more information\n",
                 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
    fossil_exit(1);
  }
  atexit( fossil_atexit );


























  aCommand[idx].xFunc();







  fossil_exit(0);
  /*NOT_REACHED*/
  return 0;
}

/*
** Print a usage comment and quit







|

>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>







687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
    }
    zCmdName = g.argv[1];
  }
#ifndef _WIN32
  if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
  /* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */
#endif
  rc = name_search(zCmdName, aCommand, count(aCommand), FOSSIL_FIRST_CMD, &idx);
  if( rc==1 ){
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    if( !g.isHTTP && !g.fNoThHook ){
      rc = Th_CommandHook(zCmdName, 0);
    }else{
      rc = TH_OK;
    }
    if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
      if( rc==TH_OK || rc==TH_RETURN ){
#endif
        fossil_fatal("%s: unknown command: %s\n"
                     "%s: use \"help\" for more information\n",
                     g.argv[0], zCmdName, g.argv[0]);
#ifdef FOSSIL_ENABLE_TH1_HOOKS
      }
      if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
        Th_CommandNotify(zCmdName, 0);
      }
    }
    fossil_exit(0);
#endif
  }else if( rc==2 ){
    int i, n;
    Blob couldbe;
    blob_zero(&couldbe);
    n = strlen(zCmdName);
    for(i=0; i<count(aCommand); i++){
      if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
        blob_appendf(&couldbe, " %s", aCommand[i].zName);
      }
    }
    fossil_print("%s: ambiguous command prefix: %s\n"
                 "%s: could be any of:%s\n"
                 "%s: use \"help\" for more information\n",
                 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
    fossil_exit(1);
  }
  atexit( fossil_atexit );
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  /*
  ** The TH1 return codes from the hook will be handled as follows:
  **
  ** TH_OK: The xFunc() and the TH1 notification will both be executed.
  **
  ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
  **           skipped.  If the xFunc() is being hooked, the error message
  **           will be emitted.
  **
  ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
  **
  ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
  **            skipped.
  **
  ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
  **              executed.
  */
  if( !g.isHTTP && !g.fNoThHook ){
    rc = Th_CommandHook(aCommand[idx].zName, aCommand[idx].cmdFlags);
  }else{
    rc = TH_OK;
  }
  if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
    if( rc==TH_OK || rc==TH_RETURN ){
#endif
      aCommand[idx].xFunc();
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    }
    if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
      Th_CommandNotify(aCommand[idx].zName, aCommand[idx].cmdFlags);
    }
  }
#endif
  fossil_exit(0);
  /*NOT_REACHED*/
  return 0;
}

/*
** Print a usage comment and quit
762
763
764
765
766
767
768














769
770
771
772
773
774
775
      zReturn = g.argv[i+hasArg];
      remove_from_argv(i, 1+hasArg);
      break;
    }
  }
  return zReturn;
}















/*
** Verify that there are no unprocessed command-line options.  If
** Any remaining command-line argument begins with "-" print
** an error message and quit.
*/
void verify_all_options(void){







>
>
>
>
>
>
>
>
>
>
>
>
>
>







829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
      zReturn = g.argv[i+hasArg];
      remove_from_argv(i, 1+hasArg);
      break;
    }
  }
  return zReturn;
}

/*
** Look for a repository command-line option.  If present, [re-]cache it in
** the global state and return the new pointer, freeing any previous value.
** If absent and there is no cached value, return NULL.
*/
const char *find_repository_option(){
  const char *zRepository = find_option("repository", "R", 1);
  if( zRepository ){
    if( g.zRepositoryOption ) fossil_free(g.zRepositoryOption);
    g.zRepositoryOption = mprintf("%s", zRepository);
  }
  return g.zRepositoryOption;
}

/*
** Verify that there are no unprocessed command-line options.  If
** Any remaining command-line argument begins with "-" print
** an error message and quit.
*/
void verify_all_options(void){
869
870
871
872
873
874
875


876
877





878
879
880
881
882
883
884
885
886
887



888

889
890






891
892
893
894
895
896
897
**
** Print the source code version number for the fossil executable.
** If the verbose option is specified, additional details will
** be output about what optional features this binary was compiled
** with
*/
void version_cmd(void){


  fossil_print("This is fossil version %s\n", get_version());
  if(!find_option("verbose","v",0)){





    return;
  }else{
#if defined(FOSSIL_ENABLE_TCL)
    int rc;
    const char *zRc;
#endif
    fossil_print("Compiled on %s %s using %s (%d-bit)\n",
                 __DATE__, __TIME__, COMPILER_NAME, sizeof(void*)*8);
    fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid());
    fossil_print("Schema version %s\n", AUX_SCHEMA);



    fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());

#if defined(FOSSIL_ENABLE_SSL)
    fossil_print("SSL (%s)\n", OPENSSL_VERSION_TEXT);






#endif
#if defined(FOSSIL_ENABLE_TCL)
    Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
    rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
    zRc = Th_ReturnCodeName(rc, 0);
    fossil_print("TCL (Tcl %s, loaded %s: %s)\n",
      TCL_PATCH_LEVEL, zRc, Th_GetResult(g.interp, 0)







>
>

|
>
>
>
>
>










>
>
>

>

|
>
>
>
>
>
>







950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
**
** Print the source code version number for the fossil executable.
** If the verbose option is specified, additional details will
** be output about what optional features this binary was compiled
** with
*/
void version_cmd(void){
  int verboseFlag = 0;

  fossil_print("This is fossil version %s\n", get_version());
  verboseFlag = find_option("verbose","v",0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  if(!verboseFlag){
    return;
  }else{
#if defined(FOSSIL_ENABLE_TCL)
    int rc;
    const char *zRc;
#endif
    fossil_print("Compiled on %s %s using %s (%d-bit)\n",
                 __DATE__, __TIME__, COMPILER_NAME, sizeof(void*)*8);
    fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid());
    fossil_print("Schema version %s\n", AUX_SCHEMA);
#if defined(FOSSIL_ENABLE_MINIZ)
    fossil_print("miniz %s, loaded %s\n", MZ_VERSION, mz_version());
#else
    fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
#endif
#if defined(FOSSIL_ENABLE_SSL)
    fossil_print("SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
#endif
#if defined(FOSSIL_ENABLE_TH1_DOCS)
    fossil_print("TH1_DOCS\n");
#endif
#if defined(FOSSIL_ENABLE_TH1_HOOKS)
    fossil_print("TH1_HOOKS\n");
#endif
#if defined(FOSSIL_ENABLE_TCL)
    Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
    rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
    zRc = Th_ReturnCodeName(rc, 0);
    fossil_print("TCL (Tcl %s, loaded %s: %s)\n",
      TCL_PATCH_LEVEL, zRc, Th_GetResult(g.interp, 0)
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
**    %fossil help --t|-test    Show test commands only
**    %fossil help --x|-aux     Show auxiliary commands only
**    %fossil help --w|-www     Show list of WWW pages
*/
void help_cmd(void){
  int rc, idx, isPage = 0;
  const char *z;
  char const * zCmdOrPage;
  char const * zCmdOrPagePlural;
  if( g.argc<3 ){
    z = g.argv[0];
    fossil_print(
      "Usage: %s help COMMAND\n"
      "Common COMMANDs:  (use \"%s help -a|--all\" for a complete list)\n",
      z, z);
    command_list(0, CMDFLAG_1ST_TIER);







|
|







1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
**    %fossil help --t|-test    Show test commands only
**    %fossil help --x|-aux     Show auxiliary commands only
**    %fossil help --w|-www     Show list of WWW pages
*/
void help_cmd(void){
  int rc, idx, isPage = 0;
  const char *z;
  const char *zCmdOrPage;
  const char *zCmdOrPagePlural;
  if( g.argc<3 ){
    z = g.argv[0];
    fossil_print(
      "Usage: %s help COMMAND\n"
      "Common COMMANDs:  (use \"%s help -a|--all\" for a complete list)\n",
      z, z);
    command_list(0, CMDFLAG_1ST_TIER);
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  if(isPage){
    zCmdOrPage = "page";
    zCmdOrPagePlural = "pages";
  }else{
    zCmdOrPage = "command";
    zCmdOrPagePlural = "commands";
  }
  rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
  if( rc==1 ){
    fossil_print("unknown %s: %s\nAvailable %s:\n",
                 zCmdOrPage, g.argv[2], zCmdOrPagePlural);
    command_list(0, isPage ? CMDFLAG_WEBPAGE : (0xff & ~CMDFLAG_WEBPAGE));
    fossil_exit(1);
  }else if( rc==2 ){
    fossil_print("ambiguous %s prefix: %s\nMatching %s:\n",







|







1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
  if(isPage){
    zCmdOrPage = "page";
    zCmdOrPagePlural = "pages";
  }else{
    zCmdOrPage = "command";
    zCmdOrPagePlural = "commands";
  }
  rc = name_search(g.argv[2], aCommand, count(aCommand), 0, &idx);
  if( rc==1 ){
    fossil_print("unknown %s: %s\nAvailable %s:\n",
                 zCmdOrPage, g.argv[2], zCmdOrPagePlural);
    command_list(0, isPage ? CMDFLAG_WEBPAGE : (0xff & ~CMDFLAG_WEBPAGE));
    fossil_exit(1);
  }else if( rc==2 ){
    fossil_print("ambiguous %s prefix: %s\nMatching %s:\n",
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
}

/*
** WEBPAGE: help
** URL: /help/CMD
*/
void help_page(void){
  const char * zCmd = P("cmd");

  if( zCmd==0 ) zCmd = P("name");
  style_header("Command-line Help");
  if( zCmd ){
    int rc, idx;
    char *z, *s, *d;
    char const * zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
    style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
    @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
    rc = name_search(zCmd, aCommand, count(aCommand), &idx);
    if( rc==1 ){
      @ unknown command: %s(zCmd)
    }else if( rc==2 ){
      @ ambiguous command prefix: %s(zCmd)
    }else{
      z = (char*)aCmdHelp[idx].zText;
      if( z==0 ){







|






|


|







1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
}

/*
** WEBPAGE: help
** URL: /help/CMD
*/
void help_page(void){
  const char *zCmd = P("cmd");

  if( zCmd==0 ) zCmd = P("name");
  style_header("Command-line Help");
  if( zCmd ){
    int rc, idx;
    char *z, *s, *d;
    const char *zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
    style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
    @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
    rc = name_search(zCmd, aCommand, count(aCommand), 0, &idx);
    if( rc==1 ){
      @ unknown command: %s(zCmd)
    }else if( rc==2 ){
      @ ambiguous command prefix: %s(zCmd)
    }else{
      z = (char*)aCmdHelp[idx].zText;
      if( z==0 ){
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
        szFile = 1;
        break;
      }
      if( szFile==0 ){
        if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
        szFile = file_size(zRepo);
      }
      if( szFile<0 ){
        const char *zMimetype;
        assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
        zRepo[j] = 0;
        if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
          fossil_free(zToFree);
          i++;
          continue;
        }
        if( pFileGlob!=0
         && file_isfile(zRepo)
         && glob_match(pFileGlob, zRepo)
         && strglob("*.fossil*",zRepo)==0
         && (zMimetype = mimetype_from_name(zRepo))!=0
         && strcmp(zMimetype, "application/x-fossil-artifact")!=0
        ){
          Blob content;
          blob_read_from_file(&content, zRepo);
          cgi_set_content_type(zMimetype);
          cgi_set_content(&content);







|











|







1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
        szFile = 1;
        break;
      }
      if( szFile==0 ){
        if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
        szFile = file_size(zRepo);
      }
      if( szFile<0 && i>0 ){
        const char *zMimetype;
        assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
        zRepo[j] = 0;
        if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
          fossil_free(zToFree);
          i++;
          continue;
        }
        if( pFileGlob!=0
         && file_isfile(zRepo)
         && glob_match(pFileGlob, zRepo)
         && sqlite3_strglob("*.fossil*",zRepo)!=0
         && (zMimetype = mimetype_from_name(zRepo))!=0
         && strcmp(zMimetype, "application/x-fossil-artifact")!=0
        ){
          Blob content;
          blob_read_from_file(&content, zRepo);
          cgi_set_content_type(zMimetype);
          cgi_set_content(&content);
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523










1524
1525
1526







1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539



























1540







1541
1542
1543
1544
1545
1546
1547
    }
#endif
  }

  /* Locate the method specified by the path and execute the function
  ** that implements that method.
  */
  if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) &&
      name_search("not_found", aWebpage, count(aWebpage), &idx) ){
#ifdef FOSSIL_ENABLE_JSON
    if(g.json.isJsonMode){
      json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
    }else
#endif
    {










      cgi_set_status(404,"Not Found");
      @ <h1>Not Found</h1>
      @ <p>Page not found: %h(g.zPath)</p>







    }
  }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){
#ifdef FOSSIL_ENABLE_JSON
    if(g.json.isJsonMode){
      json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0);
    }else
#endif
    {
      @ <h1>Server Configuration Error</h1>
      @ <p>The database schema on the server is out-of-date.  Please ask
      @ the administrator to run <b>fossil rebuild</b>.</p>
    }
  }else{



























    aWebpage[idx].xFunc();







  }

  /* Return the result.
  */
  cgi_reply();
}








|
<






>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>







1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
    }
#endif
  }

  /* Locate the method specified by the path and execute the function
  ** that implements that method.
  */
  if( name_search(g.zPath, aWebpage, count(aWebpage), 0, &idx) ){

#ifdef FOSSIL_ENABLE_JSON
    if(g.json.isJsonMode){
      json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
    }else
#endif
    {
#ifdef FOSSIL_ENABLE_TH1_HOOKS
      int rc;
      if( !g.fNoThHook ){
        rc = Th_WebpageHook(g.zPath, 0);
      }else{
        rc = TH_OK;
      }
      if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
        if( rc==TH_OK || rc==TH_RETURN ){
#endif
          cgi_set_status(404,"Not Found");
          @ <h1>Not Found</h1>
          @ <p>Page not found: %h(g.zPath)</p>
#ifdef FOSSIL_ENABLE_TH1_HOOKS
        }
        if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
          Th_WebpageNotify(g.zPath, 0);
        }
      }
#endif
    }
  }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){
#ifdef FOSSIL_ENABLE_JSON
    if(g.json.isJsonMode){
      json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0);
    }else
#endif
    {
      @ <h1>Server Configuration Error</h1>
      @ <p>The database schema on the server is out-of-date.  Please ask
      @ the administrator to run <b>fossil rebuild</b>.</p>
    }
  }else{
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    /*
    ** The TH1 return codes from the hook will be handled as follows:
    **
    ** TH_OK: The xFunc() and the TH1 notification will both be executed.
    **
    ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
    **           skipped.  If the xFunc() is being hooked, the error message
    **           will be emitted.
    **
    ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
    **
    ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
    **            skipped.
    **
    ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
    **              executed.
    */
    int rc;
    if( !g.fNoThHook ){
      rc = Th_WebpageHook(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
    }else{
      rc = TH_OK;
    }
    if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
      if( rc==TH_OK || rc==TH_RETURN ){
#endif
        aWebpage[idx].xFunc();
#ifdef FOSSIL_ENABLE_TH1_HOOKS
      }
      if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
        Th_WebpageNotify(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
      }
    }
#endif
  }

  /* Return the result.
  */
  cgi_reply();
}

1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
    redirect_web_page(nRedirect, azRedirect);
  }else{
    process_one_web_page(zNotFound, pFileGlob);
  }
}

/*
** If g.argv[2] exists then it is either the name of a repository
** that will be used by a server, or else it is a directory that
** contains multiple repositories that can be served.  If g.argv[2]
** is a directory, the repositories it contains must be named
** "*.fossil".  If g.argv[2] does not exists, then we must be within
** a check-out and the repository to be served is the repository of
** that check-out.
**
** Open the repository to be served if it is known.  If g.argv[2] is
** a directory full of repositories, then set g.zRepositoryName to
** the name of that directory and the specific repository will be
** opened later by process_one_web_page() based on the content of
** the PATH_INFO variable.
**
** If disallowDir is set, then the directory full of repositories method
** is disallowed.
*/
static void find_server_repository(int disallowDir){
  if( g.argc<3 ){
    db_must_be_within_tree();
  }else if( file_isdir(g.argv[2])==1 ){
    if( disallowDir ){
      fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[2]);
    }else{
      g.zRepositoryName = mprintf("%s", g.argv[2]);
      file_simplify_name(g.zRepositoryName, -1, 0);
    }
  }else{
    db_open_repository(g.argv[2]);
  }
}

/*
** undocumented format:
**
**        fossil http REPOSITORY INFILE OUTFILE IPADDR
**
** The argv==6 form is used by the win32 server only.
**
** COMMAND: http*
**
** Usage: %fossil http REPOSITORY ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin.  The resulting webpage
** is delivered on stdout.  This method is used to launch an HTTP request
** handler from inetd, for example.  The argument is the name of the
** repository.
**
** If REPOSITORY is a directory that contains one or more repositories,







|

|

|



|








|
|

|

|

|



|






|





|







1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
    redirect_web_page(nRedirect, azRedirect);
  }else{
    process_one_web_page(zNotFound, pFileGlob);
  }
}

/*
** If g.argv[arg] exists then it is either the name of a repository
** that will be used by a server, or else it is a directory that
** contains multiple repositories that can be served.  If g.argv[arg]
** is a directory, the repositories it contains must be named
** "*.fossil".  If g.argv[arg] does not exists, then we must be within
** a check-out and the repository to be served is the repository of
** that check-out.
**
** Open the repository to be served if it is known.  If g.argv[arg] is
** a directory full of repositories, then set g.zRepositoryName to
** the name of that directory and the specific repository will be
** opened later by process_one_web_page() based on the content of
** the PATH_INFO variable.
**
** If disallowDir is set, then the directory full of repositories method
** is disallowed.
*/
static void find_server_repository(int disallowDir, int arg){
  if( g.argc<=arg ){
    db_must_be_within_tree();
  }else if( file_isdir(g.argv[arg])==1 ){
    if( disallowDir ){
      fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[arg]);
    }else{
      g.zRepositoryName = mprintf("%s", g.argv[arg]);
      file_simplify_name(g.zRepositoryName, -1, 0);
    }
  }else{
    db_open_repository(g.argv[arg]);
  }
}

/*
** undocumented format:
**
**        fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
**
** The argv==6 form is used by the win32 server only.
**
** COMMAND: http*
**
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin.  The resulting webpage
** is delivered on stdout.  This method is used to launch an HTTP request
** handler from inetd, for example.  The argument is the name of the
** repository.
**
** If REPOSITORY is a directory that contains one or more repositories,
1808
1809
1810
1811
1812
1813
1814




1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
  useSCGI = find_option("scgi", 0, 0)!=0;
  zAltBase = find_option("baseurl", 0, 1);
  if( zAltBase ) set_base_url(zAltBase);
  if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
  zHost = find_option("host", 0, 1);
  if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
  g.cgiOutput = 1;




  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
    fossil_fatal("no repository specified");
  }
  g.fullHttpReply = 1;
  if( g.argc==6 ){
    g.httpIn = fossil_fopen(g.argv[3], "rb");
    g.httpOut = fossil_fopen(g.argv[4], "wb");
    zIpAddr = g.argv[5];

  }else{
    g.httpIn = stdin;
    g.httpOut = stdout;
    zIpAddr = 0;

  }
  if( zIpAddr==0 ){
    zIpAddr = cgi_ssh_remote_addr(0);
    if( zIpAddr && zIpAddr[0] ){
      g.fSshClient |= CGI_SSH_CLIENT;
    }
  }
  find_server_repository(0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( useSCGI ){
    cgi_handle_scgi_request();
  }else if( g.fSshClient & CGI_SSH_CLIENT ){
    ssh_request_loop(zIpAddr, glob_create(zFileGlob));
  }else{
    cgi_handle_http_request(zIpAddr);







>
>
>
>
|



|
|
|
|
>




>







<







1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
  useSCGI = find_option("scgi", 0, 0)!=0;
  zAltBase = find_option("baseurl", 0, 1);
  if( zAltBase ) set_base_url(zAltBase);
  if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
  zHost = find_option("host", 0, 1);
  if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
  g.cgiOutput = 1;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
    fossil_fatal("no repository specified");
  }
  g.fullHttpReply = 1;
  if( g.argc>=5 ){
    g.httpIn = fossil_fopen(g.argv[2], "rb");
    g.httpOut = fossil_fopen(g.argv[3], "wb");
    zIpAddr = g.argv[4];
    find_server_repository(0, 5);
  }else{
    g.httpIn = stdin;
    g.httpOut = stdout;
    zIpAddr = 0;
    find_server_repository(0, 2);
  }
  if( zIpAddr==0 ){
    zIpAddr = cgi_ssh_remote_addr(0);
    if( zIpAddr && zIpAddr[0] ){
      g.fSshClient |= CGI_SSH_CLIENT;
    }
  }

  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( useSCGI ){
    cgi_handle_scgi_request();
  }else if( g.fSshClient & CGI_SSH_CLIENT ){
    ssh_request_loop(zIpAddr, glob_create(zFileGlob));
  }else{
    cgi_handle_http_request(zIpAddr);
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
  const char *zIpAddr;    /* IP address of remote client */

  Th_InitTraceLog();
  login_set_capabilities("sx", 0);
  g.useLocalauth = 1;
  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  zIpAddr = cgi_ssh_remote_addr(0);
  if( zIpAddr && zIpAddr[0] ){
    g.fSshClient |= CGI_SSH_CLIENT;
    ssh_request_loop(zIpAddr, 0);
  }else{







|







2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
  const char *zIpAddr;    /* IP address of remote client */

  Th_InitTraceLog();
  login_set_capabilities("sx", 0);
  g.useLocalauth = 1;
  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0, 2);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  zIpAddr = cgi_ssh_remote_addr(0);
  if( zIpAddr && zIpAddr[0] ){
    g.fSshClient |= CGI_SSH_CLIENT;
    ssh_request_loop(zIpAddr, 0);
  }else{
1974
1975
1976
1977
1978
1979
1980
1981







1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993




1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
  char *zIpAddr = 0;        /* Bind to this IP address */

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
  zStopperFile = find_option("stopper", 0, 1);
#endif

  zFileGlob = find_option("files", 0, 1);







  g.useLocalauth = find_option("localauth", 0, 0)!=0;
  Th_InitTraceLog();
  zPort = find_option("port", "P", 1);
  zNotFound = find_option("notfound", 0, 1);
  zAltBase = find_option("baseurl", 0, 1);
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  if ( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }




  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
  isUiCmd = g.argv[1][0]=='u';
  if( isUiCmd ){
    flags |= HTTP_SERVER_LOCALHOST;
    g.useLocalauth = 1;
  }
  find_server_repository(isUiCmd && zNotFound==0);
  if( zPort ){
    int i;
    for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
    if( i>0 ){
      zIpAddr = mprintf("%.*s", i, zPort);
      zPort += i+1;
    }







|
>
>
>
>
>
>
>









|


>
>
>
>






|







2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
  char *zIpAddr = 0;        /* Bind to this IP address */

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
  zStopperFile = find_option("stopper", 0, 1);
#endif

  zFileGlob = find_option("files-urlenc",0,1);
  if( zFileGlob ){
    char *z = mprintf("%s", zFileGlob);
    dehttpize(z);
    zFileGlob = z;
  }else{
    zFileGlob = find_option("files",0,1);
  }
  g.useLocalauth = find_option("localauth", 0, 0)!=0;
  Th_InitTraceLog();
  zPort = find_option("port", "P", 1);
  zNotFound = find_option("notfound", 0, 1);
  zAltBase = find_option("baseurl", 0, 1);
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
  isUiCmd = g.argv[1][0]=='u';
  if( isUiCmd ){
    flags |= HTTP_SERVER_LOCALHOST;
    g.useLocalauth = 1;
  }
  find_server_repository(isUiCmd && zNotFound==0, 2);
  if( zPort ){
    int i;
    for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
    if( i>0 ){
      zIpAddr = mprintf("%.*s", i, zPort);
      zPort += i+1;
    }
2031
2032
2033
2034
2035
2036
2037




2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066


2067
2068
2069
2070
2071
2072
2073
    zBrowser = db_get("web-browser", "open");
#endif
    if( zIpAddr ){
      zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
    }else{
      zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
    }




  }
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.sslNotAvailable = 1;
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace || g.fSqlTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiOutput = 1;
  find_server_repository(isUiCmd && zNotFound==0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( flags & HTTP_SERVER_SCGI ){
    cgi_handle_scgi_request();
  }else{
    cgi_handle_http_request(0);
  }
  process_one_web_page(zNotFound, glob_create(zFileGlob));
#else
  /* Win32 implementation */
  if( isUiCmd ){
    zBrowser = db_get("web-browser", "start");
    if( zIpAddr ){
      zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
    }else{
      zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
    }


  }
  db_close(1);
  if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
    win32_http_server(iPort, mxPort, zBrowserCmd,
                      zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
  }
#endif







>
>
>
>












|
















>
>







2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
    zBrowser = db_get("web-browser", "open");
#endif
    if( zIpAddr ){
      zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
    }else{
      zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
    }
    if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
    if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  }else{
    db_setup_server_and_project_codes(1);
  }
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.sslNotAvailable = 1;
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace || g.fSqlTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiOutput = 1;
  find_server_repository(isUiCmd && zNotFound==0, 2);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( flags & HTTP_SERVER_SCGI ){
    cgi_handle_scgi_request();
  }else{
    cgi_handle_http_request(0);
  }
  process_one_web_page(zNotFound, glob_create(zFileGlob));
#else
  /* Win32 implementation */
  if( isUiCmd ){
    zBrowser = db_get("web-browser", "start");
    if( zIpAddr ){
      zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
    }else{
      zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
    }
    if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
    if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  }
  db_close(1);
  if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
    win32_http_server(iPort, mxPort, zBrowserCmd,
                      zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
  }
#endif
Changes to src/main.mk.
40
41
42
43
44
45
46

47
48
49
50
51
52
53
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \

  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \







>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
152
153
154
155
156
157
158

159
160
161
162
163
164
165
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \

  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \







>







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
264
265
266
267
268
269
270

271
272
273
274
275
276
277
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \

 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \







>







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398





399
400
401
402
403
404
405
406
407









408







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

426
















































































































427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216



1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid  $(SRCDIR)/../manifest  $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# Setup the options used to compile the included SQLite library.

SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS

# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open






# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)










EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o








$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:	
	# noop

clean:	
	rm -rf $(OBJDIR)/* $(APPNAME)


$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
	$(OBJDIR)/mkindex $(TRANS_SRC) >$@
$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h

	$(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)/cache_.c:$(OBJDIR)/cache.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_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.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_status_.c:$(OBJDIR)/json_status.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)/loadctrl_.c:$(OBJDIR)/loadctrl.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.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)/regexp_.c:$(OBJDIR)/regexp.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)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.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)/winfile_.c:$(OBJDIR)/winfile.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.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
















































































































	touch $(OBJDIR)/headers
$(OBJDIR)/headers: Makefile
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
Makefile:
$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers
$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers
$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers
$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers
$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers
$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers
$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers
$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers
$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers
$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers
$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers
$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers
$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers
$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers
$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers
$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers
$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers
$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers
$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers
$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers
$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers
$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers
$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers
$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers
$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers
$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers
$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers
$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers







$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers
$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers
$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers
$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers
$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers
$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers
$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers
$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers
$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers
$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers
$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers
$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers
$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers
$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers
$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers
$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers
$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers
$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers
$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers
$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers
$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers
$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers
$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers
$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers
$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers
$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers
$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers
$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers
$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers
$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers
$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers
$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers
$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers
$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers
$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers
$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers
$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers
$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers
$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers
$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers
$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers
$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers
$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers
$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers
$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers
$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers
$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers
$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers
$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers
$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers
$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers
$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers
$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers
$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers
$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers
$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers
$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers
$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers
$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers
$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers
$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers
$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers
$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers
$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers
$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers
$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers
$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers
$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers
$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers
$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers
$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers
$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers
$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers
$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers
$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers
$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers
$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers
$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers
$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o





$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all install test clean








>
|











>
>
>
>
>



|

|



>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>







|


|






>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|



>
>
>
>
>
>
>



|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|













|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|






|



















>
>
>










383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid  $(SRCDIR)/../manifest  $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = -DNDEBUG=1 \
                 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS

# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open

# Setup the options used to compile the included miniz library.
MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
                -DMINIZ_NO_TIME \
                -DMINIZ_NO_ARCHIVE_APIS

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1.  If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ.  = $(MINIZ_OBJ.0)


EXTRAOBJ = \
 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
 $(OBJDIR)/shell.o \
 $(OBJDIR)/th.o \
 $(OBJDIR)/th_lang.o \
 $(OBJDIR)/th_tcl.o \
 $(OBJDIR)/cson_amalgamation.o


$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
	rm -rf $(OBJDIR)/* $(APPNAME)


$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
	$(OBJDIR)/mkindex $(TRANS_SRC) >$@
$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
	$(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)/cache_.c:$(OBJDIR)/cache.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)/fusefs_.c:$(OBJDIR)/fusefs.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_config_.c:$(OBJDIR)/json_config.h \
	$(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h \
	$(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \
	$(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.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_status_.c:$(OBJDIR)/json_status.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)/loadctrl_.c:$(OBJDIR)/loadctrl.h \
	$(OBJDIR)/login_.c:$(OBJDIR)/login.h \
	$(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \
	$(OBJDIR)/main_.c:$(OBJDIR)/main.h \
	$(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \
	$(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \
	$(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \
	$(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
	$(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
	$(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
	$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.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)/regexp_.c:$(OBJDIR)/regexp.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)/unicode_.c:$(OBJDIR)/unicode.h \
	$(OBJDIR)/update_.c:$(OBJDIR)/update.h \
	$(OBJDIR)/url_.c:$(OBJDIR)/url.h \
	$(OBJDIR)/user_.c:$(OBJDIR)/user.h \
	$(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
	$(OBJDIR)/util_.c:$(OBJDIR)/util.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)/winfile_.c:$(OBJDIR)/winfile.h \
	$(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
	$(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.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
	touch $(OBJDIR)/headers
$(OBJDIR)/headers: Makefile
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
Makefile:
$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers
$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers
$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers
$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers
$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers
$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers
$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers
$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers
$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers
$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers
$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers
$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers
$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers
$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers
$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers
$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers
$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers
$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers
$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers
$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers
$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers
$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers
$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers
$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers
$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers
$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers
$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers
$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers
$(OBJDIR)/fusefs_.c:	$(SRCDIR)/fusefs.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/fusefs.c >$(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.o:	$(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.h:	$(OBJDIR)/headers
$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers
$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers
$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers
$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers
$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers
$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers
$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers
$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers
$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers
$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers
$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers
$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers
$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers
$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers
$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers
$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers
$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers
$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers
$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers
$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers
$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers
$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers
$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers
$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers
$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers
$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers
$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers
$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers
$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers
$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers
$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers
$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers
$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers
$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers
$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers
$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers
$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers
$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers
$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers
$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers
$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers
$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers
$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers
$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers
$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers
$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers
$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers
$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers
$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers
$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers
$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers
$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers
$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers
$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers
$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers
$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers
$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers
$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers
$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers
$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers
$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers
$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers
$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers
$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers
$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers
$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers
$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers
$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers
$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers
$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers
$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers
$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers
$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers
$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers
$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers
$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers
$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers
$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers
$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o


$(OBJDIR)/miniz.o:	$(SRCDIR)/miniz.c
	$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $(OBJDIR)/miniz.o

$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all install test clean

Changes to src/makeheaders.c.
35
36
37
38
39
40
41


42
43
44
45
46
47
48
49
50
51
52
53
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <memory.h>
#include <sys/stat.h>
#include <assert.h>


#if defined( __MINGW32__) ||  defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__)
#  ifndef WIN32
#    define WIN32
#  endif
# include <string.h>
#else
# include <unistd.h>
#endif

/*
** Macros for debugging.
*/







>
>




<







35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <memory.h>
#include <sys/stat.h>
#include <assert.h>
#include <string.h>

#if defined( __MINGW32__) ||  defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__)
#  ifndef WIN32
#    define WIN32
#  endif

#else
# include <unistd.h>
#endif

/*
** Macros for debugging.
*/
Changes to src/makemake.tcl.
44
45
46
47
48
49
50

51
52
53
54
55
56
57
  diffcmd
  doc
  encode
  event
  export
  file
  finfo

  glob
  graph
  gzip
  http
  http_socket
  http_transport
  import







>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  diffcmd
  doc
  encode
  event
  export
  file
  finfo
  fusefs
  glob
  graph
  gzip
  http
  http_socket
  http_transport
  import
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155








156
157
158
159
160

161
162
163
164
165
166
167
  zip
  http_ssl
}

# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {

  -DSQLITE_OMIT_LOAD_EXTENSION=1
  -DSQLITE_ENABLE_LOCKING_STYLE=0
  -DSQLITE_THREADSAFE=0
  -DSQLITE_DEFAULT_FILE_FORMAT=4
  -DSQLITE_OMIT_DEPRECATED
  -DSQLITE_ENABLE_EXPLAIN_COMMENTS
}
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4
#lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI
#lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096

# Options used to compile the included SQLite shell.
#
set SHELL_OPTIONS {
  -Dmain=sqlite3_shell
  -DSQLITE_OMIT_LOAD_EXTENSION=1
  -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
  -DSQLITE_SHELL_DBNAME_PROC=fossil_open
}









# Options used to compile the included SQLite shell on Windows.
#
set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
lappend SHELL_WIN32_OPTIONS -Daccess=file_access

lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen

# Name of the final application
#
set name fossil








>




















>
>
>
>
>
>
>
>





>







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  zip
  http_ssl
}

# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {
  -DNDEBUG=1
  -DSQLITE_OMIT_LOAD_EXTENSION=1
  -DSQLITE_ENABLE_LOCKING_STYLE=0
  -DSQLITE_THREADSAFE=0
  -DSQLITE_DEFAULT_FILE_FORMAT=4
  -DSQLITE_OMIT_DEPRECATED
  -DSQLITE_ENABLE_EXPLAIN_COMMENTS
}
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4
#lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI
#lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096

# Options used to compile the included SQLite shell.
#
set SHELL_OPTIONS {
  -Dmain=sqlite3_shell
  -DSQLITE_OMIT_LOAD_EXTENSION=1
  -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
  -DSQLITE_SHELL_DBNAME_PROC=fossil_open
}

# miniz (libz drop-in alternative) precompiler flags.
#
set MINIZ_OPTIONS {
  -DMINIZ_NO_STDIO
  -DMINIZ_NO_TIME
  -DMINIZ_NO_ARCHIVE_APIS
}

# Options used to compile the included SQLite shell on Windows.
#
set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
lappend SHELL_WIN32_OPTIONS -Daccess=file_access
lappend SHELL_WIN32_OPTIONS -Dsystem=fossil_system
lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen

# Name of the final application
#
set name fossil

220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
}
writeln "\n"
writeln "APPNAME = $name\$(E)"
writeln "\n"

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n                 "] \
    <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n                "]] {

all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)
	mkdir -p $(INSTALLDIR)
	mv $(APPNAME) $(INSTALLDIR)

$(OBJDIR):







|
>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
}
writeln "\n"
writeln "APPNAME = $name\$(E)"
writeln "\n"

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n                 "] \
    <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n                "] \
    <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n                "]] {
all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)
	mkdir -p $(INSTALLDIR)
	mv $(APPNAME) $(INSTALLDIR)

$(OBJDIR):
258
259
260
261
262
263
264



265
266
267
268
269
270
271
272
273









274
275

276
277
278
279
280

281

282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338



339
340
341
342
343
344
345
		$(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>

# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = <<<SHELL_OPTIONS>>>




# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)










EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \

  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/th_tcl.o \
  $(OBJDIR)/cson_amalgamation.o



$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:	
	# noop

clean:	
	rm -rf $(OBJDIR)/* $(APPNAME)

}]


set mhargs {}
foreach s [lsort $src] {
  append mhargs " \$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
  set extra_h($s) {}
}
append mhargs " \$(SRCDIR)/sqlite3.h"
append mhargs " \$(SRCDIR)/th.h"
#append mhargs " \$(SRCDIR)/cson_amalgamation.h"
append mhargs " \$(OBJDIR)/VERSION.h"

writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
writeln "\t\$(OBJDIR)/makeheaders $mhargs"
writeln "\ttouch \$(OBJDIR)/headers"
writeln "\$(OBJDIR)/headers: Makefile"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
writeln "Makefile:"
set extra_h(main) \$(OBJDIR)/page_index.h

foreach s [lsort $src] {
  writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
  writeln "\t\$(OBJDIR)/translate \$(SRCDIR)/$s.c >\$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h $extra_h($s) \$(SRCDIR)/config.h"
  writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.h:\t\$(OBJDIR)/headers"
}

writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

writeln {



$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#







>
>
>



|

|



>
>
>
>
>
>
>
>
>
|
|
>
|
|
|
|
|
>

>






|


|


<
>



|
|

|
|
|
|
>








|




|




















>
>
>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
		$(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>

# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = <<<SHELL_OPTIONS>>>

# Setup the options used to compile the included miniz library.
MINIZ_OPTIONS = <<<MINIZ_OPTIONS>>>

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1.  If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ.  = $(MINIZ_OBJ.0)
}]

writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) <<<NEXT_LINE>>>
 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
 $(OBJDIR)/shell.o <<<NEXT_LINE>>>
 $(OBJDIR)/th.o <<<NEXT_LINE>>>
 $(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
 $(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
 $(OBJDIR)/cson_amalgamation.o
}]

writeln {
$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
	rm -rf $(OBJDIR)/* $(APPNAME)


}

set mhargs {}
foreach s [lsort $src] {
  append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
  set extra_h($s) { }
}
append mhargs "\$(SRCDIR)/sqlite3.h <<<NEXT_LINE>>>"
append mhargs "\$(SRCDIR)/th.h <<<NEXT_LINE>>>"
#append mhargs "\$(SRCDIR)/cson_amalgamation.h <<<NEXT_LINE>>>"
append mhargs "\$(OBJDIR)/VERSION.h"
set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
writeln "\t\$(OBJDIR)/makeheaders $mhargs"
writeln "\ttouch \$(OBJDIR)/headers"
writeln "\$(OBJDIR)/headers: Makefile"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
writeln "Makefile:"
set extra_h(main) " \$(OBJDIR)/page_index.h "

foreach s [lsort $src] {
  writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
  writeln "\t\$(OBJDIR)/translate \$(SRCDIR)/$s.c >\$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
  writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.h:\t\$(OBJDIR)/headers"
}

writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

writeln {
$(OBJDIR)/miniz.o:	$(SRCDIR)/miniz.c
	$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $(OBJDIR)/miniz.o

$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#
406
407
408
409
410
411
412













413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428




429
430
431
432
433
434
435
436
437
438
439
440
441
442








443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
#### Enable JSON (http://www.json.org) support using "cson"
#
# FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL = 1














#### Enable scripting support via Tcl/Tk
#
# FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
# FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
# FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' sqlite
#
# USE_SYSTEM_SQLITE = 1





#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif









#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







>
>
>
>
>
>
>
>
>
>
>
>
>













|


>
>
>
>














>
>
>
>
>
>
>
>











|
|







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
#### Enable JSON (http://www.json.org) support using "cson"
#
# FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL = 1

#### Automatically build OpenSSL when building Fossil (causes rebuild
#    issues when building incrementally).
#
# FOSSIL_BUILD_SSL = 1

#### Enable TH1 scripts in embedded documentation files
#
# FOSSIL_ENABLE_TH1_DOCS = 1

#### Enable hooks for commands and web pages via TH1
#
# FOSSIL_ENABLE_TH1_HOOKS = 1

#### Enable scripting support via Tcl/Tk
#
# FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
# FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
# FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' SQLite
#
# USE_SYSTEM_SQLITE = 1

#### Use the miniz compression library
#
# FOSSIL_ENABLE_MINIZ = 1

#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif
ifeq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
SSLCONFIG = mingw
else
SSLCONFIG = mingw64
endif
ifndef FOSSIL_ENABLE_MINIZ
SSLCONFIG +=  --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
endif

#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
493
494
495
496
497
498
499
500






501
502
503
504
505
506
507
508
509
510
511
512




513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529






530
531
532
533
534
535
536
537
538
539
540
541












542
543
544
545
546
547
548

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)







#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR)





# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif







# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif













# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS







|
>
>
>
>
>
>











|
>
>
>
>

















>
>
>
>
>
>












>
>
>
>
>
>
>
>
>
>
>
>







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
TCC += -L$(ZLIBDIR) -I$(ZINCDIR)
endif

#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR)

ifndef FOSSIL_ENABLE_MINIZ
RCC += -I$(ZINCDIR)
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif

# With miniz (i.e. instead of zlib)
ifdef FOSSIL_ENABLE_MINIZ
TCC += -DFOSSIL_ENABLE_MINIZ=1
RCC += -DFOSSIL_ENABLE_MINIZ=1
endif

# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif

# With TH1 embedded docs support
ifdef FOSSIL_ENABLE_TH1_DOCS
TCC += -DFOSSIL_ENABLE_TH1_DOCS=1
RCC += -DFOSSIL_ENABLE_TH1_DOCS=1
endif

# With TH1 hook support
ifdef FOSSIL_ENABLE_TH1_HOOKS
TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS
565
566
567
568
569
570
571
572

573
574
575
576


577
578
579
580
581

582
583
584
585
586

587
588
589
590
591
592
593
594
595






596
597
598
599
600
601
602
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# MinGW: If available, use the Unicode capable runtime startup code.

ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif



ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

# OpenSSL: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex -lz







#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32







|
>




>
>




|
>




|
>








|
>
>
>
>
>
>







649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

#### MinGW: If available, use the Unicode capable runtime startup code.
#
ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif

#### SQLite: If enabled, use the system SQLite library.
#
ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

#### OpenSSL: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

#### Tcl: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
LIB += -lz
endif

#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32
610
611
612
613
614
615
616
617




618
619
620
621
622
623
624
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(ProgramFiles)\NSIS\MakeNSIS.exe"





#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line







|
>
>
>
>







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(PROGRAMFILES)\NSIS\MakeNSIS.exe"

#### Inno Setup executable location
#
INNOSETUP = "$(PROGRAMFILES)\Inno Setup 5\ISCC.exe"

#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line
636
637
638
639
640
641
642
643


644
645
646
647
648
649
650
651
652
653
654
655
656

657

658
659
660
661
662
663
664
665
666

667

668
669
670
671
672
673
674
675
676
677
678

679
680
681
682

683
684
685
686
687
688
689
}
writeln "\n"
writeln -nonewline "OBJ ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln "\n"
writeln "APPNAME = ${name}.exe"


writeln {
#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex)
VERSION     = $(subst /,\,$(OBJDIR)/version)

CP          = copy

MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate
MAKEHEADERS = $(OBJDIR)/makeheaders
MKINDEX     = $(OBJDIR)/mkindex
VERSION     = $(OBJDIR)/version

CP          = cp

MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif}

writeln {
all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS

	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else

	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)







|
>
>









|
|
|
|
>

>





|
|
|
|
>

>











>




>







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
}
writeln "\n"
writeln -nonewline "OBJ ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln "\n"
writeln "APPNAME    = ${name}.exe"
writeln "APPTARGETS ="
writeln "LIBTARGETS ="
writeln {
#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\,$(OBJDIR)/version.exe)
CAT         = type
CP          = copy
GREP        = find
MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate.exe
MAKEHEADERS = $(OBJDIR)/makeheaders.exe
MKINDEX     = $(OBJDIR)/mkindex.exe
VERSION     = $(OBJDIR)/version.exe
CAT         = cat
CP          = cp
GREP        = grep
MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif}

writeln {
all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS
	$(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else
	$(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733









734
735

736
737
738
739
740

741

742
743
744
745
746
747




748
749
750
751
752
753
754
755
756
757
758
759
760
761






762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781



782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809



810
811
812
813


814
815
816
817
818


819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838



839
840
841
842
843
844
845
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c

$(OBJDIR)/makeheaders:	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)










EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \

  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/th_tcl.o \
  $(OBJDIR)/cson_amalgamation.o



zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean





openssl:	zlib
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib mingw
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean







$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o zlib
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./fossil.nsi



}

set mhargs {}
foreach s [lsort $src] {
  if {[string length $mhargs] > 0} {append mhargs " \\\n\t\t"}
  append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
  set extra_h($s) {}
}
append mhargs " \\\n\t\t\$(SRCDIR)/sqlite3.h"
append mhargs " \\\n\t\t\$(SRCDIR)/th.h"
append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
writeln "\t\$(MKINDEX) \$(TRANS_SRC) >$@\n"
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
writeln "\t\$(MAKEHEADERS) $mhargs"
writeln "\techo Done >\$(OBJDIR)/headers\n"
writeln "\$(OBJDIR)/headers: Makefile\n"
writeln "Makefile:\n"
set extra_h(main) \$(OBJDIR)/page_index.h

foreach s [lsort $src] {
  writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
  writeln "\t\$(TRANSLATE) \$(SRCDIR)/$s.c >\$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h $extra_h($s) \$(SRCDIR)/config.h"
  writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
}




set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE



set j " \\\n                 "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
set j " \\\n                "
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS $j]\n"



writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"




close $output_file
#
# End of the win/Makefile.mingw output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.dmc output







|
|

|
|

|
|


|












|





>
>
>
>
>
>
>
>
>
|
|
>
|
|
|
|
|
>

>






>
>
>
>
|
|












>
>
>
>
>
>
|


















|
>
>
>






|




|

|




|


|

|




>
>
>
|



>
>





>
>




















>
>
>







805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(TRANSLATE):	$(SRCDIR)/translate.c
	$(BCC) -o $(TRANSLATE) $(SRCDIR)/translate.c

$(MAKEHEADERS):	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(MAKEHEADERS) $(SRCDIR)/makeheaders.c

$(MKINDEX):	$(SRCDIR)/mkindex.c
	$(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1.  If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ.  = $(MINIZ_OBJ.0)
}

writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) <<<NEXT_LINE>>>
 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
 $(OBJDIR)/shell.o <<<NEXT_LINE>>>
 $(OBJDIR)/th.o <<<NEXT_LINE>>>
 $(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
 $(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
 $(OBJDIR)/cson_amalgamation.o
}]

writeln {
zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

ifndef FOSSIL_ENABLE_MINIZ
LIBTARGETS += zlib
endif

openssl:	$(LIBTARGETS)
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG)
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean

APPTARGETS += $(LIBTARGETS)

ifdef FOSSIL_BUILD_SSL
APPTARGETS += openssl
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./setup/fossil.nsi

innosetup: $(OBJDIR) $(APPNAME)
	$(INNOSETUP) ./setup/fossil.iss -DAppVersion=$(shell $(CAT) ./VERSION)
}

set mhargs {}
foreach s [lsort $src] {
  if {[string length $mhargs] > 0} {append mhargs " \\\n\t\t"}
  append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
  set extra_h($s) { }
}
append mhargs " \\\n\t\t\$(SRCDIR)/sqlite3.h"
append mhargs " \\\n\t\t\$(SRCDIR)/th.h"
append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
writeln "\t\$(MKINDEX) \$(TRANS_SRC) >$@\n"
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(MAKEHEADERS) \$(OBJDIR)/VERSION.h"
writeln "\t\$(MAKEHEADERS) $mhargs"
writeln "\techo Done >\$(OBJDIR)/headers\n"
writeln "\$(OBJDIR)/headers: Makefile\n"
writeln "Makefile:\n"
set extra_h(main) " \$(OBJDIR)/page_index.h "

foreach s [lsort $src] {
  writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(TRANSLATE)"
  writeln "\t\$(TRANSLATE) \$(SRCDIR)/$s.c >\$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
  writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
  writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
}

set SQLITE_WIN32_OPTIONS $SQLITE_OPTIONS
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI

set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE

set MINIZ_WIN32_OPTIONS $MINIZ_OPTIONS

set j " \\\n                 "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
set j " \\\n                "
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS $j]\n"
set j " \\\n                "
writeln "MINIZ_OPTIONS = [join $MINIZ_WIN32_OPTIONS $j]\n"

writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

writeln "\$(OBJDIR)/miniz.o:\t\$(SRCDIR)/miniz.c"
writeln "\t\$(XTCC) \$(MINIZ_OPTIONS) -c \$(SRCDIR)/miniz.c -o \$(OBJDIR)/miniz.o\n"

close $output_file
#
# End of the win/Makefile.mingw output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.dmc output
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR) 
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res}
writeln -nonewline "\t+echo "







|







1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res}
writeln -nonewline "\t+echo "
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
	cp $@ $@

VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
	+$** > $@

page_index.h: mkindex$E $(SRC) 
	+$** > $@

clean:
	-del $(OBJDIR)\*.obj
	-del *.obj *_.c *.h *.map

realclean:







|







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099

$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
	cp $@ $@

VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
	+$** > $@

page_index.h: mkindex$E $(SRC)
	+$** > $@

clean:
	-del $(OBJDIR)\*.obj
	-del *.obj *_.c *.h *.map

realclean:
1001
1002
1003
1004
1005
1006
1007








1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019






1020
1021
1022
1023
1024
1025



1026
1027
1028









1029
1030
1031
1032
1033
1034

1035
1036
















1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050




1051
1052
1053
1054
1055
1056
1057
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary

writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################








#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B      = ..
SRCDIR = $B\src
OBJDIR = .
OX     = .
O      = .obj
E      = .exe
P      = .pdb







# Uncomment to enable debug symbols
# DEBUG = 1

# Uncomment to enable JSON API
# FOSSIL_ENABLE_JSON = 1




# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1










# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1g\include

SSLLIBDIR = $(B)\compat\openssl-1.0.1g\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
















!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
!endif

# zlib options
ZINCDIR   = $(B)\compat\zlib
ZLIBDIR   = $(B)\compat\zlib
ZLIB      = zlib.lib

INCL      = /I. /I$(SRCDIR) /I$B\win\include /I$(ZINCDIR)





!ifdef FOSSIL_ENABLE_SSL
INCL      = $(INCL) /I$(SSLINCDIR)
!endif

!ifdef FOSSIL_ENABLE_TCL
INCL      = $(INCL) /I$(TCLINCDIR)







>
>
>
>
>
>
>
>





|
|
|
|
|
|
|
>
>
>
>
>
>






>
>
>



>
>
>
>
>
>
>
>
>





|
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|
>
>
>
>







1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary

writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This Makefile will only function correctly if used from a sub-directory
# that is a direct child of the top-level directory for this project.
#
!if !exist("..\.fossil-settings")
!error "Please change the current directory to the one containing this file."
!endif

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B       = ..
SRCDIR  = $B\src
OBJDIR  = .
OX      = .
O       = .obj
E       = .exe
P       = .pdb

# Perl is only necessary if OpenSSL support is enabled and it must
# be built from source code.  The PERLDIR variable should point to
# the directory containing the main Perl binary (i.e. "perl.exe").
PERLDIR = C:\Perl\bin
PERL    = perl.exe

# Uncomment to enable debug symbols
# DEBUG = 1

# Uncomment to enable JSON API
# FOSSIL_ENABLE_JSON = 1

# Uncomment to enable miniz usage
# FOSSIL_ENABLE_MINIZ = 1

# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to build SSL libraries
# FOSSIL_BUILD_SSL = 1

# Uncomment to enable TH1 scripts in embedded documentation files
# FOSSIL_ENABLE_TH1_DOCS = 1

# Uncomment to enable TH1 hooks
# FOSSIL_ENABLE_TH1_HOOKS = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLDIR    = $(B)\compat\openssl-1.0.1i
SSLINCDIR = $(SSLDIR)\inc32
SSLLIBDIR = $(SSLDIR)\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
!message Using 'x64' platform for OpenSSL...
SSLCONFIG = VC-WIN64A no-asm
SSLSETUP  = ms\do_win64a.bat
SSLNMAKE  = ms\nt.mak all
!elseif "$(PLATFORM)"=="ia64"
!message Using 'ia64' platform for OpenSSL...
SSLCONFIG = VC-WIN64I no-asm
SSLSETUP  = ms\do_win64i.bat
SSLNMAKE  = ms\nt.mak all
!else
!message Assuming 'x86' platform for OpenSSL...
SSLCONFIG = VC-WIN32 no-asm
SSLSETUP  = ms\do_ms.bat
SSLNMAKE  = ms\nt.mak all
!endif
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
!endif

# zlib options
ZINCDIR   = $(B)\compat\zlib
ZLIBDIR   = $(B)\compat\zlib
ZLIB      = zlib.lib

INCL      = /I. /I$(SRCDIR) /I$B\win\include

!ifndef FOSSIL_ENABLE_MINIZ
INCL      = $(INCL) /I$(ZINCDIR)
!endif

!ifdef FOSSIL_ENABLE_SSL
INCL      = $(INCL) /I$(SSLINCDIR)
!endif

!ifdef FOSSIL_ENABLE_TCL
INCL      = $(INCL) /I$(TCLINCDIR)
1066
1067
1068
1069
1070
1071
1072
1073
1074










1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086










1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105




1106
1107
1108
1109
1110
1111
1112
!else
CFLAGS    = $(CFLAGS) /MT /O2
!endif

BCC       = $(CC) $(CFLAGS)
TCC       = $(CC) /c $(CFLAGS) $(MSCDEF) $(INCL)
RCC       = rc /D_WIN32 /D_MSC_VER $(MSCDEF) $(INCL)
LIBS      = $(ZLIB) ws2_32.lib advapi32.lib
LIBDIR    = /LIBPATH:$(ZLIBDIR)











!ifdef FOSSIL_ENABLE_JSON
TCC       = $(TCC) /DFOSSIL_ENABLE_JSON=1
RCC       = $(RCC) /DFOSSIL_ENABLE_JSON=1
!endif

!ifdef FOSSIL_ENABLE_SSL
TCC       = $(TCC) /DFOSSIL_ENABLE_SSL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_SSL=1
LIBS      = $(LIBS) $(SSLLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
!endif











!ifdef FOSSIL_ENABLE_TCL
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC       = $(TCC) /DUSE_TCL_STUBS=1
RCC       = $(RCC) /DUSE_TCL_STUBS=1
!endif
}
regsub -all {[-]D} [join $SQLITE_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
set j " \\\n                 "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"

regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n                "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"





writeln -nonewline "SRC   = "
set i 0
foreach s [lsort $src] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "







|
|
>
>
>
>
>
>
>
>
>
>












>
>
>
>
>
>
>
>
>
>












|






>
>
>
>







1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
!else
CFLAGS    = $(CFLAGS) /MT /O2
!endif

BCC       = $(CC) $(CFLAGS)
TCC       = $(CC) /c $(CFLAGS) $(MSCDEF) $(INCL)
RCC       = rc /D_WIN32 /D_MSC_VER $(MSCDEF) $(INCL)
LIBS      = ws2_32.lib advapi32.lib
LIBDIR    =

!ifndef FOSSIL_ENABLE_MINIZ
LIBS      = $(LIBS) $(ZLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(ZLIBDIR)
!endif

!ifdef FOSSIL_ENABLE_MINIZ
TCC       = $(TCC) /DFOSSIL_ENABLE_MINIZ=1
RCC       = $(RCC) /DFOSSIL_ENABLE_MINIZ=1
!endif

!ifdef FOSSIL_ENABLE_JSON
TCC       = $(TCC) /DFOSSIL_ENABLE_JSON=1
RCC       = $(RCC) /DFOSSIL_ENABLE_JSON=1
!endif

!ifdef FOSSIL_ENABLE_SSL
TCC       = $(TCC) /DFOSSIL_ENABLE_SSL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_SSL=1
LIBS      = $(LIBS) $(SSLLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
!endif

!ifdef FOSSIL_ENABLE_TH1_DOCS
TCC       = $(TCC) /DFOSSIL_ENABLE_TH1_DOCS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TH1_DOCS=1
!endif

!ifdef FOSSIL_ENABLE_TH1_HOOKS
TCC       = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
!endif

!ifdef FOSSIL_ENABLE_TCL
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC       = $(TCC) /DUSE_TCL_STUBS=1
RCC       = $(RCC) /DUSE_TCL_STUBS=1
!endif
}
regsub -all {[-]D} [join $SQLITE_WIN32_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
set j " \\\n                 "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"

regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n                "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"

regsub -all {[-]D} [join $MINIZ_WIN32_OPTIONS { }] {/D} MSC_MINIZ_OPTIONS
set j " \\\n                "
writeln "MINIZ_OPTIONS = [join $MSC_MINIZ_OPTIONS $j]\n"

writeln -nonewline "SRC   = "
set i 0
foreach s [lsort $src] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
1120
1121
1122
1123
1124
1125
1126

1127





1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138





















1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149



1150
1151
1152
1153
1154
1155
1156
foreach s [lsort [concat $src $AdditionalObj]] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "\$(OX)\\$s\$O"; incr i
}

writeln " \\"





writeln -nonewline "        \$(OX)\\fossil.res\n\n"
writeln {
APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)


all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd






















$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
	cd $(OX) 
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc}
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
  writeln "\techo \$(OX)\\$s.obj $redir \$@"
  set redir {>>}
}
set redir {>>}



writeln "\techo \$(LIBS) $redir \$@"
writeln {
$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**







>
|
>
>
>
>
>


|
|
>





|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|









>
>
>







1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
foreach s [lsort [concat $src $AdditionalObj]] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "\$(OX)\\$s\$O"; incr i
}
if {$i > 0} {
  writeln " \\"
}
writeln "!ifdef FOSSIL_ENABLE_MINIZ"
writeln -nonewline "        "
writeln "\$(OX)\\miniz\$O \\"; incr i
writeln "!endif"
writeln -nonewline "        \$(OX)\\fossil.res\n\n"
writeln {
APPNAME    = $(OX)\fossil$(E)
PDBNAME    = $(OX)\fossil$(P)
APPTARGETS =

all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd

!ifdef FOSSIL_ENABLE_SSL
openssl:
	@echo Building OpenSSL from "$(SSLDIR)"...
!if "$(PERLDIR)" != ""
	@set PATH=$(PERLDIR);$(PATH)
!endif
	@pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
	@pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
	@pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
!endif

!ifndef FOSSIL_ENABLE_MINIZ
APPTARGETS = $(APPTARGETS) zlib
!endif

!ifdef FOSSIL_ENABLE_SSL
!ifdef FOSSIL_BUILD_SSL
APPTARGETS = $(APPTARGETS) openssl
!endif
!endif

$(APPNAME) : $(APPTARGETS) translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
	cd $(OX)
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc}
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
  writeln "\techo \$(OX)\\$s.obj $redir \$@"
  set redir {>>}
}
set redir {>>}
writeln "!ifdef FOSSIL_ENABLE_MINIZ"
writeln "\techo \$(OX)\\miniz.obj $redir \$@"
writeln "!endif"
writeln "\techo \$(LIBS) $redir \$@"
writeln {
$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**
1175
1176
1177
1178
1179
1180
1181



1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204

1205

1206

1207

1208
1209
1210
1211
1212
1213
1214

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**




VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 
	$** > $@

clean:
	-del $(OX)\*.obj
	-del *.obj
	-del *_.c
	-del *.h

	-del *.map
	-del *.res
	-del headers
	-del linkopts
	-del vc*.pdb

realclean: clean
	-del $(APPNAME)
	-del $(PDBNAME)
	-del translate$E

	-del mkindex$E

	-del makeheaders$E

	-del mkversion$E


$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h







>
>
>





|







>










>

>

>

>







1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**

$(OX)\miniz$O : $(SRCDIR)\miniz.c
	$(TCC) /Fo$@ -c $(MINIZ_OPTIONS) $(SRCDIR)\miniz.c

VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC)
	$** > $@

clean:
	-del $(OX)\*.obj
	-del *.obj
	-del *_.c
	-del *.h
	-del *.ilk
	-del *.map
	-del *.res
	-del headers
	-del linkopts
	-del vc*.pdb

realclean: clean
	-del $(APPNAME)
	-del $(PDBNAME)
	-del translate$E
	-del translate$P
	-del mkindex$E
	-del mkindex$P
	-del makeheaders$E
	-del makeheaders$P
	-del mkversion$E
	-del mkversion$P

$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
# Begin win/Makefile.PellesCGMake output
#
puts "building ../win/Makefile.PellesCGMake"
set output_file [open ../win/Makefile.PellesCGMake w]
fconfigure $output_file -translation binary

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS { }] \
    <<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"







|







1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
# Begin win/Makefile.PellesCGMake output
#
puts "building ../win/Makefile.PellesCGMake"
set output_file [open ../win/Makefile.PellesCGMake w]
fconfigure $output_file -translation binary

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_WIN32_OPTIONS { }] \
    <<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
#   zlib sources    1.2.5
#   Windows XP SP 2
# and
#   PellesC         6.00.4
#   gmake           3.80
#   zlib sources    1.2.5
#   Windows 7 Home Premium
#  

#  
PellesCDir=c:\Programme\PellesC

# Select between 32/64 bit code, default is 32 bit
#TARGETVERSION=64

ifeq ($(TARGETVERSION),64)
# 64 bit version







|

|







1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
#   zlib sources    1.2.5
#   Windows XP SP 2
# and
#   PellesC         6.00.4
#   gmake           3.80
#   zlib sources    1.2.5
#   Windows 7 Home Premium
#

#
PellesCDir=c:\Programme\PellesC

# Select between 32/64 bit code, default is 32 bit
#TARGETVERSION=64

ifeq ($(TARGETVERSION),64)
# 64 bit version
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362

# define the special utilities files, needed to generate
# the automatically generated source files
UTILS=translate.exe mkindex.exe makeheaders.exe
UTILS_OBJ=$(UTILS:.exe=.obj)
UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))

# define the sqlite files, which need special flags on compile
SQLITESRC=sqlite3.c
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
SQLITEDEFINES=<<<SQLITE_OPTIONS>>>

# define the sqlite shell files, which need special flags on compile
SQLITESHELLSRC=shell.c
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>>

# define the th scripting files, which need special flags on compile
THSRC=th.c th_lang.c







|





|







1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

# define the special utilities files, needed to generate
# the automatically generated source files
UTILS=translate.exe mkindex.exe makeheaders.exe
UTILS_OBJ=$(UTILS:.exe=.obj)
UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))

# define the SQLite files, which need special flags on compile
SQLITESRC=sqlite3.c
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
SQLITEDEFINES=<<<SQLITE_OPTIONS>>>

# define the SQLite shell files, which need special flags on compile
SQLITESHELLSRC=shell.c
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>>

# define the th scripting files, which need special flags on compile
THSRC=th.c th_lang.c
Changes to src/manifest.c.
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
** Remove the PGP signature from the artifact, if there is one.
*/
static void remove_pgp_signature(char **pz, int *pn){
  char *z = *pz;
  int n = *pn;
  int i;
  if( memcmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)!=0 ) return;
  for(i=34; i<n && !after_blank_line(z+i); i++){}
  if( i>=n ) return;
  z += i;
  n -= i;
  *pz = z;
  for(i=n-1; i>=0; i--){
    if( z[i]=='\n' && memcmp(&z[i],"\n-----BEGIN PGP SIGNATURE-", 25)==0 ){
      n = i+1;
      break;
    }
  }
  *pn = n;
  return;
}







|






|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
** Remove the PGP signature from the artifact, if there is one.
*/
static void remove_pgp_signature(char **pz, int *pn){
  char *z = *pz;
  int n = *pn;
  int i;
  if( strncmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)!=0 ) return;
  for(i=34; i<n && !after_blank_line(z+i); i++){}
  if( i>=n ) return;
  z += i;
  n -= i;
  *pz = z;
  for(i=n-1; i>=0; i--){
    if( z[i]=='\n' && strncmp(&z[i],"\n-----BEGIN PGP SIGNATURE-", 25)==0 ){
      n = i+1;
      break;
    }
  }
  *pn = n;
  return;
}
888
889
890
891
892
893
894


895
896
897
898
899
900
901

902



903









904
905
906


907
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
     || p->zWiki
    ){
      SYNTAX("cluster contains a card other than M- or Z-");
    }
    if( !seenZ ) SYNTAX("missing Z-card on cluster");
    p->type = CFTYPE_CLUSTER;
  }else if( p->zEventId ){


    if( p->rDate<=0.0 ) SYNTAX("missing date on event");
    if( p->nFile>0 ) SYNTAX("F-card in event");
    if( p->zRepoCksum ) SYNTAX("R-card in event");
    if( p->zBaseline ) SYNTAX("B-card in event");
    if( p->nField>0 ) SYNTAX("J-card in event");
    if( p->zTicketUuid ) SYNTAX("K-card in event");
    if( p->zWikiTitle!=0 ) SYNTAX("L-card in event");

    if( p->zWiki==0 ) SYNTAX("missing W-card on event");



    if( p->zAttachName ) SYNTAX("A-card in event");









    if( !seenZ ) SYNTAX("missing Z-card on event");
    p->type = CFTYPE_EVENT;
  }else if( hasSelfRefTag || p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline ){


    if( p->rDate<=0.0 ) SYNTAX("missing date on manifest");
    if( p->nField>0 ) SYNTAX("J-card in manifest");
    if( p->zTicketUuid ) SYNTAX("K-card in manifest");
    if( p->zWiki ) SYNTAX("W-card in manifest");
    if( p->zWikiTitle ) SYNTAX("L-card in manifest");
    if( p->zTicketUuid ) SYNTAX("K-card in manifest");
    if( p->zAttachName ) SYNTAX("A-card in manifest");
    p->type = CFTYPE_MANIFEST;
  }else if( p->nField>0 || p->zTicketUuid!=0 ){

    if( p->rDate<=0.0 ) SYNTAX("missing date on ticket");
    if( p->zWiki ) SYNTAX("W-card in ticket");
    if( p->zWikiTitle ) SYNTAX("L-card in ticket");
    if( p->nField==0 ) SYNTAX("missing J-card on ticket");
    if( p->nTag>0 ) SYNTAX("T-card in ticket");
    if( p->zTicketUuid==0 ) SYNTAX("missing K-card on ticket");
    if( p->zUser==0 ) SYNTAX("missing U-card on ticket");
    if( p->zAttachName ) SYNTAX("A-card in ticket");
    if( p->zMimetype) SYNTAX("N-card in ticket");
    if( !seenZ ) SYNTAX("missing Z-card on ticket");
    p->type = CFTYPE_TICKET;
  }else if( p->zWiki!=0 || p->zWikiTitle!=0 ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on wiki");
    if( p->nTag>0 ) SYNTAX("T-card in wiki");
    if( p->zWiki==0 ) SYNTAX("missing W-card on wiki");
    if( p->zWikiTitle==0 ) SYNTAX("missing L-card on wiki");
    if( p->zAttachName ) SYNTAX("A-card in wiki");
    if( !seenZ ) SYNTAX("missing Z-card on wiki");
    p->type = CFTYPE_WIKI;
  }else if( p->zAttachName ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on attachment");
    if( p->nTag>0 ) SYNTAX("T-card in attachment");
    if( !seenZ ) SYNTAX("missing Z-card on attachment");
    p->type = CFTYPE_ATTACHMENT;
  }else{
    if( p->rDate<=0.0 ) SYNTAX("missing date on control");
    if( p->nParent>0 ) SYNTAX("P-card in control");
    if( p->zMimetype ) SYNTAX("N-card in control");
    if( !seenZ ) SYNTAX("missing Z-card on control");
    p->type = CFTYPE_CONTROL;
  }
  md5sum_init();
  if( !isRepeat ) g.parseCnt[p->type]++;
  return p;







>
>


<
<



>

>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
>
>



<
<
<
<


>

<
<

<

<
<

<
<
<
<
|
|
<
<
|
|







<







888
889
890
891
892
893
894
895
896
897
898


899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924




925
926
927
928


929

930


931




932
933


934
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
     || p->zWiki
    ){
      SYNTAX("cluster contains a card other than M- or Z-");
    }
    if( !seenZ ) SYNTAX("missing Z-card on cluster");
    p->type = CFTYPE_CLUSTER;
  }else if( p->zEventId ){
    if( p->zAttachName ) SYNTAX("A-card in event");
    if( p->zBaseline ) SYNTAX("B-card in event");
    if( p->rDate<=0.0 ) SYNTAX("missing date on event");
    if( p->nFile>0 ) SYNTAX("F-card in event");


    if( p->nField>0 ) SYNTAX("J-card in event");
    if( p->zTicketUuid ) SYNTAX("K-card in event");
    if( p->zWikiTitle!=0 ) SYNTAX("L-card in event");
    if( p->zRepoCksum ) SYNTAX("R-card in event");
    if( p->zWiki==0 ) SYNTAX("missing W-card on event");
    if( !seenZ ) SYNTAX("missing Z-card on event");
    p->type = CFTYPE_EVENT;
  }else if( p->zWiki!=0 || p->zWikiTitle!=0 ){
    if( p->zAttachName ) SYNTAX("A-card in wiki");
    if( p->zBaseline ) SYNTAX("B-card in wiki");
    if( p->rDate<=0.0 ) SYNTAX("missing date on wiki");
    if( p->nFile>0 ) SYNTAX("F-card in wiki");
    if( p->nField>0 ) SYNTAX("J-card in wiki");
    if( p->zTicketUuid ) SYNTAX("K-card in wiki");
    if( p->zWikiTitle==0 ) SYNTAX("missing L-card on wiki");
    if( p->zRepoCksum ) SYNTAX("R-card in wiki");
    if( p->nTag>0 ) SYNTAX("T-card in wiki");
    if( p->zWiki==0 ) SYNTAX("missing W-card on wiki");
    if( !seenZ ) SYNTAX("missing Z-card on wiki");
    p->type = CFTYPE_WIKI;
  }else if( hasSelfRefTag || p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline
      || p->nParent>0 ){
    if( p->zAttachName ) SYNTAX("A-card in manifest");
    if( p->rDate<=0.0 ) SYNTAX("missing date on manifest");
    if( p->nField>0 ) SYNTAX("J-card in manifest");
    if( p->zTicketUuid ) SYNTAX("K-card in manifest");




    p->type = CFTYPE_MANIFEST;
  }else if( p->nField>0 || p->zTicketUuid!=0 ){
    if( p->zAttachName ) SYNTAX("A-card in ticket");
    if( p->rDate<=0.0 ) SYNTAX("missing date on ticket");


    if( p->nField==0 ) SYNTAX("missing J-card on ticket");

    if( p->zTicketUuid==0 ) SYNTAX("missing K-card on ticket");


    if( p->zMimetype) SYNTAX("N-card in ticket");




    if( p->nTag>0 ) SYNTAX("T-card in ticket");
    if( p->zUser==0 ) SYNTAX("missing U-card on ticket");


    if( !seenZ ) SYNTAX("missing Z-card on ticket");
    p->type = CFTYPE_TICKET;
  }else if( p->zAttachName ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on attachment");
    if( p->nTag>0 ) SYNTAX("T-card in attachment");
    if( !seenZ ) SYNTAX("missing Z-card on attachment");
    p->type = CFTYPE_ATTACHMENT;
  }else{
    if( p->rDate<=0.0 ) SYNTAX("missing date on control");

    if( p->zMimetype ) SYNTAX("N-card in control");
    if( !seenZ ) SYNTAX("missing Z-card on control");
    p->type = CFTYPE_CONTROL;
  }
  md5sum_init();
  if( !isRepeat ) g.parseCnt[p->type]++;
  return p;
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(ManifestFile *pFile){
  int mperm = PERM_REG;
  if( pFile && pFile->zPerm){
    if( strstr(pFile->zPerm,"x")!=0 )
      mperm = PERM_EXE;
    else if( strstr(pFile->zPerm,"l")!=0 )
      mperm = PERM_LNK;

  }
  return mperm;
}

/*
** Add a single entry to the mlink table.  Also add the filename to
** the filename table if it is not there already.







|

|

>







1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(ManifestFile *pFile){
  int mperm = PERM_REG;
  if( pFile && pFile->zPerm){
    if( strstr(pFile->zPerm,"x")!=0 ){
      mperm = PERM_EXE;
    }else if( strstr(pFile->zPerm,"l")!=0 ){
      mperm = PERM_LNK;
    }
  }
  return mperm;
}

/*
** Add a single entry to the mlink table.  Also add the filename to
** the filename table if it is not there already.
1225
1226
1227
1228
1229
1230
1231
1232




1233
1234
1235
1236
1237
1238
1239
**
** As an optimization, guess that the file we seek is at index p->iFile.
** That will usually be the case.  If it is not found there, then do the
** actual binary search.
**
** Update p->iFile to be the index of the file that is found.
*/
static ManifestFile *manifest_file_seek_base(Manifest *p, const char *zName){




  int lwr, upr;
  int c;
  int i;
  lwr = 0;
  upr = p->nFile - 1;
  if( p->iFile>=lwr && p->iFile<upr ){
    c = fossil_strcmp(p->aFile[p->iFile+1].zName, zName);







|
>
>
>
>







1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
**
** As an optimization, guess that the file we seek is at index p->iFile.
** That will usually be the case.  If it is not found there, then do the
** actual binary search.
**
** Update p->iFile to be the index of the file that is found.
*/
static ManifestFile *manifest_file_seek_base(
  Manifest *p,             /* Manifest to search */
  const char *zName,       /* Name of the file we are looking for */
  int bBest                /* 0: exact match only.  1: closest match */
){
  int lwr, upr;
  int c;
  int i;
  lwr = 0;
  upr = p->nFile - 1;
  if( p->iFile>=lwr && p->iFile<upr ){
    c = fossil_strcmp(p->aFile[p->iFile+1].zName, zName);
1253
1254
1255
1256
1257
1258
1259





1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
    }else if( c>0 ){
      upr = i-1;
    }else{
      p->iFile = i;
      return &p->aFile[i];
    }
  }





  return 0;
}

/*
** Locate a file named zName in the aFile[] array of the given manifest.
** Return a pointer to the appropriate ManifestFile object.  Return NULL
** if not found.
**
** This routine works even if p is a delta-manifest.  The pointer
** returned might be to the baseline.
**
** We assume that filenames are in sorted order and use a binary search.
*/
ManifestFile *manifest_file_seek(Manifest *p, const char *zName){
  ManifestFile *pFile;

  pFile = manifest_file_seek_base(p, zName);
  if( pFile && pFile->zUuid==0 ) return 0;
  if( pFile==0 && p->zBaseline ){
    fetch_baseline(p, 1);
    pFile = manifest_file_seek_base(p->pBaseline, zName);
  }
  return pFile;
}

/*
** Look for a file in a manifest, taking the case-sensitive option
** into account.  If case-sensitive is off, then files in any case
** will match.
*/
ManifestFile *manifest_file_find(Manifest *p, const char *zName){
  int i;
  Manifest *pBase;
  if( filenames_are_case_sensitive() ){
    return manifest_file_seek(p, zName);
  }
  for(i=0; i<p->nFile; i++){
    if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){
      return &p->aFile[i];
    }
  }
  if( p->zBaseline==0 ) return 0;







>
>
>
>
>













|


|



|













|







1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
    }else if( c>0 ){
      upr = i-1;
    }else{
      p->iFile = i;
      return &p->aFile[i];
    }
  }
  if( bBest ){
    if( lwr>=p->nFile ) lwr = p->nFile-1;
    i = (int)strlen(zName);
    if( strncmp(zName, p->aFile[lwr].zName, i)==0 ) return &p->aFile[lwr];
  }
  return 0;
}

/*
** Locate a file named zName in the aFile[] array of the given manifest.
** Return a pointer to the appropriate ManifestFile object.  Return NULL
** if not found.
**
** This routine works even if p is a delta-manifest.  The pointer
** returned might be to the baseline.
**
** We assume that filenames are in sorted order and use a binary search.
*/
ManifestFile *manifest_file_seek(Manifest *p, const char *zName, int bBest){
  ManifestFile *pFile;

  pFile = manifest_file_seek_base(p, zName, p->zBaseline ? 0 : bBest);
  if( pFile && pFile->zUuid==0 ) return 0;
  if( pFile==0 && p->zBaseline ){
    fetch_baseline(p, 1);
    pFile = manifest_file_seek_base(p->pBaseline, zName,bBest);
  }
  return pFile;
}

/*
** Look for a file in a manifest, taking the case-sensitive option
** into account.  If case-sensitive is off, then files in any case
** will match.
*/
ManifestFile *manifest_file_find(Manifest *p, const char *zName){
  int i;
  Manifest *pBase;
  if( filenames_are_case_sensitive() ){
    return manifest_file_seek(p, zName, 0);
  }
  for(i=0; i<p->nFile; i++){
    if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){
      return &p->aFile[i];
    }
  }
  if( p->zBaseline==0 ) return 0;
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

  /* First look at all files in pChild, ignoring its baseline.  This
  ** is where most of the changes will be found.
  */
  for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){
    int mperm = manifest_file_mperm(pChildFile);
    if( pChildFile->zPrior ){
       pParentFile = manifest_file_seek(pParent, pChildFile->zPrior);
       if( pParentFile ){
         /* File with name change */
         add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                       pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
       }else{
         /* File name changed, but the old name is not found in the parent!
         ** Treat this like a new file. */
         add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                       isPublic, mperm);
       }
    }else{
       pParentFile = manifest_file_seek(pParent, pChildFile->zName);
       if( pParentFile==0 ){
         if( pChildFile->zUuid ){
           /* A new file */
           add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                         isPublic, mperm);
         }
       }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0







|











|







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423

  /* First look at all files in pChild, ignoring its baseline.  This
  ** is where most of the changes will be found.
  */
  for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){
    int mperm = manifest_file_mperm(pChildFile);
    if( pChildFile->zPrior ){
       pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
       if( pParentFile ){
         /* File with name change */
         add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                       pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
       }else{
         /* File name changed, but the old name is not found in the parent!
         ** Treat this like a new file. */
         add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                       isPublic, mperm);
       }
    }else{
       pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
       if( pParentFile==0 ){
         if( pChildFile->zUuid ){
           /* A new file */
           add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                         isPublic, mperm);
         }
       }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  if( pParent->zBaseline && pChild->zBaseline ){
    /* Both parent and child are delta manifests.  Look for files that
    ** are deleted or modified in the parent but which reappear or revert
    ** to baseline in the child and show such files as being added or changed
    ** in the child. */
    for(i=0, pParentFile=pParent->aFile; i<pParent->nFile; i++, pParentFile++){
      if( pParentFile->zUuid ){
        pChildFile = manifest_file_seek_base(pChild, pParentFile->zName);
        if( pChildFile==0 ){
          /* The child file reverts to baseline.  Show this as a change */
          pChildFile = manifest_file_seek(pChild, pParentFile->zName);
          if( pChildFile ){
            add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                          pChildFile->zName, 0, isPublic,
                          manifest_file_mperm(pChildFile));
          }
        }
      }else{
        pChildFile = manifest_file_seek(pChild, pParentFile->zName);
        if( pChildFile ){
          /* File resurrected in the child after having been deleted in
          ** the parent.  Show this as an added file. */
          add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                        isPublic, manifest_file_mperm(pChildFile));
        }
      }
    }
  }else if( pChild->zBaseline==0 ){
    /* pChild is a baseline.  Look for files that are present in pParent
    ** but are missing from pChild and mark them as having been deleted. */
    manifest_file_rewind(pParent);
    while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
      pChildFile = manifest_file_seek(pChild, pParentFile->zName);
      if( pChildFile==0 && pParentFile->zUuid!=0 ){
        add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
                      isPublic, 0);
      }
    }
  }
  manifest_cache_insert(*ppOther);







|


|







|













|







1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  if( pParent->zBaseline && pChild->zBaseline ){
    /* Both parent and child are delta manifests.  Look for files that
    ** are deleted or modified in the parent but which reappear or revert
    ** to baseline in the child and show such files as being added or changed
    ** in the child. */
    for(i=0, pParentFile=pParent->aFile; i<pParent->nFile; i++, pParentFile++){
      if( pParentFile->zUuid ){
        pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
        if( pChildFile==0 ){
          /* The child file reverts to baseline.  Show this as a change */
          pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
          if( pChildFile ){
            add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                          pChildFile->zName, 0, isPublic,
                          manifest_file_mperm(pChildFile));
          }
        }
      }else{
        pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
        if( pChildFile ){
          /* File resurrected in the child after having been deleted in
          ** the parent.  Show this as an added file. */
          add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                        isPublic, manifest_file_mperm(pChildFile));
        }
      }
    }
  }else if( pChild->zBaseline==0 ){
    /* pChild is a baseline.  Look for files that are present in pParent
    ** but are missing from pChild and mark them as having been deleted. */
    manifest_file_rewind(pParent);
    while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
      pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
      if( pChildFile==0 && pParentFile->zUuid!=0 ){
        add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
                      isPublic, 0);
      }
    }
  }
  manifest_cache_insert(*ppOther);
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
    }
  }
  db_prepare(&q, "SELECT uuid FROM pending_tkt");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    ticket_rebuild_entry(zUuid);
    if( permitHooks && rc==TH_OK ){
      rc = xfer_run_script(zScript, zUuid);
    }
  }
  db_finalize(&q);
  db_multi_exec("DROP TABLE pending_tkt");

  /* If multiple check-ins happen close together in time, adjust their
  ** times by a few milliseconds to make sure they appear in chronological







|







1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
    }
  }
  db_prepare(&q, "SELECT uuid FROM pending_tkt");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    ticket_rebuild_entry(zUuid);
    if( permitHooks && rc==TH_OK ){
      rc = xfer_run_script(zScript, zUuid, 0);
    }
  }
  db_finalize(&q);
  db_multi_exec("DROP TABLE pending_tkt");

  /* If multiple check-ins happen close together in time, adjust their
  ** times by a few milliseconds to make sure they appear in chronological
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635






































1636
1637
1638
1639
1640
1641
1642
  if( !isNew ){
    for(i=0; i<pManifest->nField; i++){
      if( fossil_strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){
        zNewStatus = pManifest->aField[i].zValue;
      }
    }
    if( zNewStatus ){
      blob_appendf(&comment, "%h ticket [%s|%.10s]: <i>%h</i>",
         zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
      );
      if( pManifest->nField>1 ){
        blob_appendf(&comment, " plus %d other change%s",
          pManifest->nField-1, pManifest->nField==2 ? "" : "s");
      }
      blob_appendf(&brief, "%h ticket [%s|%.10s].",
                   zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid);
    }else{
      zNewStatus = db_text("unknown",
         "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
         zStatusColumn, pManifest->zTicketUuid
      );
      blob_appendf(&comment, "Ticket [%s|%.10s] <i>%h</i> status still %h with "
           "%d other change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle, zNewStatus,
           pManifest->nField, pManifest->nField==1 ? "" : "s"
      );
      fossil_free(zNewStatus);
      blob_appendf(&brief, "Ticket [%s|%.10s]: %d change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, pManifest->nField,
           pManifest->nField==1 ? "" : "s"
      );
    }
  }else{
    blob_appendf(&comment, "New ticket [%s|%.10s] <i>%h</i>.",
      pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
    );
    blob_appendf(&brief, "New ticket [%s|%.10s].", pManifest->zTicketUuid,
        pManifest->zTicketUuid);
  }
  fossil_free(zTitle);
  db_multi_exec(
    "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
    "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
    tktTagId, pManifest->rDate, rid, pManifest->zUser,
    blob_str(&comment), blob_str(&brief)
  );
  blob_reset(&comment);
  blob_reset(&brief);
}







































/*
** This is the comparison function used to sort the tag array.
*/
static int tag_compare(const void *a, const void *b){
  struct TagType *pA = (struct TagType*)a;
  struct TagType *pB = (struct TagType*)b;







|






|






|





|





|


|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
  if( !isNew ){
    for(i=0; i<pManifest->nField; i++){
      if( fossil_strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){
        zNewStatus = pManifest->aField[i].zValue;
      }
    }
    if( zNewStatus ){
      blob_appendf(&comment, "%h ticket [%s|%S]: <i>%h</i>",
         zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
      );
      if( pManifest->nField>1 ){
        blob_appendf(&comment, " plus %d other change%s",
          pManifest->nField-1, pManifest->nField==2 ? "" : "s");
      }
      blob_appendf(&brief, "%h ticket [%s|%S].",
                   zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid);
    }else{
      zNewStatus = db_text("unknown",
         "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
         zStatusColumn, pManifest->zTicketUuid
      );
      blob_appendf(&comment, "Ticket [%s|%S] <i>%h</i> status still %h with "
           "%d other change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle, zNewStatus,
           pManifest->nField, pManifest->nField==1 ? "" : "s"
      );
      fossil_free(zNewStatus);
      blob_appendf(&brief, "Ticket [%s|%S]: %d change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, pManifest->nField,
           pManifest->nField==1 ? "" : "s"
      );
    }
  }else{
    blob_appendf(&comment, "New ticket [%s|%S] <i>%h</i>.",
      pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
    );
    blob_appendf(&brief, "New ticket [%s|%S].", pManifest->zTicketUuid,
        pManifest->zTicketUuid);
  }
  fossil_free(zTitle);
  db_multi_exec(
    "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
    "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
    tktTagId, pManifest->rDate, rid, pManifest->zUser,
    blob_str(&comment), blob_str(&brief)
  );
  blob_reset(&comment);
  blob_reset(&brief);
}

/*
** Add an extra line of text to the end of a manifest to prevent it being
** recognized as a valid manifest.
**
** This routine is called prior to writing out the text of a manifest as
** the "manifest" file in the root of a repository when
** "fossil setting manifest on" is enabled.  That way, if the files of
** the project are imported into a different Fossil project, the manifest
** file will not be interpreted as a control artifact in that other project.
**
** Normally it is sufficient to simply append the extra line of text.
** However, if the manifest is PGP signed then the extra line has to be
** inserted before the PGP signature (thus invalidating the signature).
*/
void sterilize_manifest(Blob *p){
  char *z, *zOrig;
  int n, nOrig;
  static const char zExtraLine[] =
      "# Remove this line to create a well-formed manifest.\n";

  z = zOrig = blob_materialize(p);
  n = nOrig = blob_size(p);
  remove_pgp_signature(&z, &n);
  if( z==zOrig ){
    blob_append(p, zExtraLine, -1);
  }else{
    int iEnd;
    Blob copy;
    memcpy(&copy, p, sizeof(copy));
    blob_init(p, 0, 0);
    iEnd = (int)(&z[n] - zOrig);
    blob_append(p, zOrig, iEnd);
    blob_append(p, zExtraLine, -1);
    blob_append(p, &zOrig[iEnd], -1);
    blob_zero(&copy);
  }
}

/*
** This is the comparison function used to sort the tag array.
*/
static int tag_compare(const void *a, const void *b){
  struct TagType *pA = (struct TagType*)a;
  struct TagType *pB = (struct TagType*)b;
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
    tag_insert(zTag, 1, 0, rid, p->rDate, rid);
    fossil_free(zTag);
    db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
                  p->zTicketUuid);
  }
  if( p->type==CFTYPE_ATTACHMENT ){
    char *zComment = 0;
    char const isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
    char const attachToType = fossil_is_uuid(p->zAttachTarget)
      ? 't' /* attach to ticket */
      : 'w' /* attach to wiki page */;
    db_multi_exec(
       "INSERT INTO attachment(attachid, mtime, src, target,"
                              "filename, comment, user)"
       "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
       rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,







|
|







1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
    tag_insert(zTag, 1, 0, rid, p->rDate, rid);
    fossil_free(zTag);
    db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
                  p->zTicketUuid);
  }
  if( p->type==CFTYPE_ATTACHMENT ){
    char *zComment = 0;
    const char isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
    const char attachToType = fossil_is_uuid(p->zAttachTarget)
      ? 't' /* attach to ticket */
      : 'w' /* attach to wiki page */;
    db_multi_exec(
       "INSERT INTO attachment(attachid, mtime, src, target,"
                              "filename, comment, user)"
       "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
       rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
      }else{
        zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
             p->zAttachName, p->zAttachTarget);
      }
    }else{
      if( isAdd ){
        zComment = mprintf(
             "Add attachment [/artifact/%s|%h] to ticket [%s|%.10s]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from ticket [%s|%.10s]",
             p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }
    }
    db_multi_exec(
        "REPLACE INTO event(type,mtime,objid,user,comment)"
        "VALUES('%c',%.17g,%d,%Q,%Q)",
        attachToType, p->rDate, rid, p->zUser, zComment







|


|







1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
      }else{
        zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
             p->zAttachName, p->zAttachTarget);
      }
    }else{
      if( isAdd ){
        zComment = mprintf(
             "Add attachment [/artifact/%s|%h] to ticket [%s|%S]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from ticket [%s|%S]",
             p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }
    }
    db_multi_exec(
        "REPLACE INTO event(type,mtime,objid,user,comment)"
        "VALUES('%c',%.17g,%d,%Q,%Q)",
        attachToType, p->rDate, rid, p->zUser, zComment
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
    /* Next loop expects tags to be sorted on UUID, so sort it. */
    qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
    for(i=0; i<p->nTag; i++){
      zTagUuid = p->aTag[i].zUuid;
      if( !zTagUuid ) continue;
      if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
        blob_appendf(&comment,
           " Edit [%s|%.10s]:",
           zTagUuid, zTagUuid);
        branchMove = 0;
        if( permitHooks && db_exists("SELECT 1 FROM event, blob"
            " WHERE event.type='ci' AND event.objid=blob.rid"
            " AND blob.uuid='%s'", zTagUuid) ){
          zScript = xfer_commit_code();
          zUuid = zTagUuid;







|







2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
    /* Next loop expects tags to be sorted on UUID, so sort it. */
    qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
    for(i=0; i<p->nTag; i++){
      zTagUuid = p->aTag[i].zUuid;
      if( !zTagUuid ) continue;
      if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
        blob_appendf(&comment,
           " Edit [%s|%S]:",
           zTagUuid, zTagUuid);
        branchMove = 0;
        if( permitHooks && db_exists("SELECT 1 FROM event, blob"
            " WHERE event.type='ci' AND event.objid=blob.rid"
            " AND blob.uuid='%s'", zTagUuid) ){
          zScript = xfer_commit_code();
          zUuid = zTagUuid;
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
    );
    blob_reset(&comment);
  }
  db_end_transaction(0);
  if( permitHooks ){
    rc = xfer_run_common_script();
    if( rc==TH_OK ){
      rc = xfer_run_script(zScript, zUuid);
    }
  }
  if( p->type==CFTYPE_MANIFEST ){
    manifest_cache_insert(p);
  }else{
    manifest_destroy(p);
  }







|







2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
    );
    blob_reset(&comment);
  }
  db_end_transaction(0);
  if( permitHooks ){
    rc = xfer_run_common_script();
    if( rc==TH_OK ){
      rc = xfer_run_script(zScript, zUuid, 0);
    }
  }
  if( p->type==CFTYPE_MANIFEST ){
    manifest_cache_insert(p);
  }else{
    manifest_destroy(p);
  }
Changes to src/markdown.c.
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    j = i;
    while( i<size
     && data[i]!='>'
     && data[i]!='\''
     && data[i]!='"'
     && data[i]!=' '
     && data[i]!='\t'
     && data[i]!='\t'
    ){
      i++;
    }
    if( i>=size ) return 0;
    if( i>j && data[i]=='>' ) return i+1;
    /* one of the forbidden chars has been found */
    *autolink = MKDA_NOT_AUTOLINK;







|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    j = i;
    while( i<size
     && data[i]!='>'
     && data[i]!='\''
     && data[i]!='"'
     && data[i]!=' '
     && data[i]!='\t'
     && data[i]!='\n'
    ){
      i++;
    }
    if( i>=size ) return 0;
    if( i>j && data[i]=='>' ) return i+1;
    /* one of the forbidden chars has been found */
    *autolink = MKDA_NOT_AUTOLINK;
Changes to src/markdown_html.c.
80
81
82
83
84
85
86










87
88
89
90
91
92
93
      i++;
    }
  }
}


/* HTML block tags */











static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){
  char *data = blob_buffer(text);
  size_t first = 0, size = blob_size(text);
  INTER_BLOCK(ob);
  while( first<size && data[first]=='\n' ) first++;
  while( size>first && data[size-1]=='\n' ) size--;







>
>
>
>
>
>
>
>
>
>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
      i++;
    }
  }
}


/* HTML block tags */

static void html_prolog(struct Blob *ob, void *opaque){
  INTER_BLOCK(ob);
  BLOB_APPEND_LITTERAL(ob, "<div class=\"markdown\">\n");
}

static void html_epilog(struct Blob *ob, void *opaque){
  INTER_BLOCK(ob);
  BLOB_APPEND_LITTERAL(ob, "</div>\n");
}

static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){
  char *data = blob_buffer(text);
  size_t first = 0, size = blob_size(text);
  INTER_BLOCK(ob);
  while( first<size && data[first]=='\n' ) first++;
  while( size>first && data[size-1]=='\n' ) size--;
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376

void markdown_to_html(
  struct Blob *input_markdown,
  struct Blob *output_title,
  struct Blob *output_body
){
  struct mkd_renderer html_renderer = {
    0, 0,  /* no prolog or epilog */



    /* block level elements */
    html_blockcode,
    html_blockquote,
    html_raw_block,
    html_header,
    html_hrule,







|
>
>







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388

void markdown_to_html(
  struct Blob *input_markdown,
  struct Blob *output_title,
  struct Blob *output_body
){
  struct mkd_renderer html_renderer = {
    /* prolog and epilog */
    html_prolog,
    html_epilog,

    /* block level elements */
    html_blockcode,
    html_blockquote,
    html_raw_block,
    html_header,
    html_hrule,
395
396
397
398
399
400
401
402
403

404
405
406
407
    /* low level elements */
    0,  /* entities are copied verbatim */
    html_normal_text,

    /* misc. parameters */
    64, /* maximum stack */
    "*_", /* emphasis characters */
    output_title /* opaque data */
  };

  blob_reset(output_title);
  blob_reset(output_body);
  markdown(output_body, input_markdown, &html_renderer);
}







|

>




407
408
409
410
411
412
413
414
415
416
417
418
419
420
    /* low level elements */
    0,  /* entities are copied verbatim */
    html_normal_text,

    /* misc. parameters */
    64, /* maximum stack */
    "*_", /* emphasis characters */
    0 /* opaque data */
  };
  html_renderer.opaque = output_title;
  blob_reset(output_title);
  blob_reset(output_body);
  markdown(output_body, input_markdown, &html_renderer);
}
Changes to src/merge.c.
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    }
    fossil_print("%-*s [%S] by %s on %s\n%*s", 
       indent-1, zLabel,
       db_column_text(&q, 3),
       db_column_text(&q, 1),
       db_column_text(&q, 0),
       indent, "");
    comment_print(zCom, indent, 78);
    fossil_free(zCom);
  }
  db_finalize(&q);
}


/*







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    }
    fossil_print("%-*s [%S] by %s on %s\n%*s", 
       indent-1, zLabel,
       db_column_text(&q, 3),
       db_column_text(&q, 1),
       db_column_text(&q, 0),
       indent, "");
    comment_print(zCom, db_column_text(&q,2), indent, -1, g.comFmtFlags);
    fossil_free(zCom);
  }
  db_finalize(&q);
}


/*
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  zBinGlob = find_option("binary",0,1);
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  forceFlag = find_option("force","f",0)!=0;
  zPivot = find_option("baseline",0,1);
  capture_case_sensitive_option();
  verify_all_options();
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");
  }







<







143
144
145
146
147
148
149

150
151
152
153
154
155
156
  zBinGlob = find_option("binary",0,1);
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  forceFlag = find_option("force","f",0)!=0;
  zPivot = find_option("baseline",0,1);

  verify_all_options();
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");
  }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
      " WHERE event.objid=%d AND blob.rid=%d",
      timeline_utc(), mid, mid
    );
    if( db_step(&q)==SQLITE_ROW ){
      char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
            db_column_text(&q, 0), db_column_text(&q, 1),
            db_column_text(&q, 3), db_column_text(&q, 2));
      comment_print(zCom, 0, 79);
      fossil_free(zCom);
    }
    db_finalize(&q);
  }else{
    usage("?OPTIONS? ?VERSION?");
    return;
  }







|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
      " WHERE event.objid=%d AND blob.rid=%d",
      timeline_utc(), mid, mid
    );
    if( db_step(&q)==SQLITE_ROW ){
      char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
            db_column_text(&q, 0), db_column_text(&q, 1),
            db_column_text(&q, 3), db_column_text(&q, 2));
      comment_print(zCom, db_column_text(&q,2), 0, -1, g.comFmtFlags);
      fossil_free(zCom);
    }
    db_finalize(&q);
  }else{
    usage("?OPTIONS? ?VERSION?");
    return;
  }
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  }
  if( nOverwrite ){
    fossil_warning("WARNING: %d unmanaged files were overwritten",
                   nOverwrite);
  }
  if( dryRunFlag ){
    fossil_warning("REMINDER: this was a dry run -"
                   " no file were actually changed.");
  }

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
  if( pickFlag ){







|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  }
  if( nOverwrite ){
    fossil_warning("WARNING: %d unmanaged files were overwritten",
                   nOverwrite);
  }
  if( dryRunFlag ){
    fossil_warning("REMINDER: this was a dry run -"
                   " no files were actually changed.");
  }

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
  if( pickFlag ){
Changes to src/merge3.c.
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  }
  return i;
}

/*
** Text of boundary markers for merge conflicts.
*/
static char const * const mergeMarker[] = {
 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
  "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
  "======= COMMON ANCESTOR content follows ============================\n",
  "======= MERGED IN content follows ==================================\n",
  ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
};








|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  }
  return i;
}

/*
** Text of boundary markers for merge conflicts.
*/
static const char *const mergeMarker[] = {
 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
  "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
  "======= COMMON ANCESTOR content follows ============================\n",
  "======= MERGED IN content follows ==================================\n",
  ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
};

366
367
368
369
370
371
372




373
374
375
376
377
378
379
**      cp Xup.c Xbase.c
**      # Verify that everything still works
**      fossil commit
**
*/
void delta_3waymerge_cmd(void){
  Blob pivot, v1, v2, merged;




  if( g.argc!=6 ){
    usage("PIVOT V1 V2 MERGED");
  }
  if( blob_read_from_file(&pivot, g.argv[2])<0 ){
    fossil_fatal("cannot read %s\n", g.argv[2]);
  }
  if( blob_read_from_file(&v1, g.argv[3])<0 ){







>
>
>
>







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
**      cp Xup.c Xbase.c
**      # Verify that everything still works
**      fossil commit
**
*/
void delta_3waymerge_cmd(void){
  Blob pivot, v1, v2, merged;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=6 ){
    usage("PIVOT V1 V2 MERGED");
  }
  if( blob_read_from_file(&pivot, g.argv[2])<0 ){
    fossil_fatal("cannot read %s\n", g.argv[2]);
  }
  if( blob_read_from_file(&v1, g.argv[3])<0 ){
Added src/miniz.c.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
   See "unlicense" statement at the end of this file.
   Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt

   Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
   MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).

   * Change History
     10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
       - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug
        would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
        (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
       - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
       - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
         Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
       - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
       - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
       - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
       - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
       - Merged MZ_FORCEINLINE fix from hdeanclark
       - Fix <time.h> include before config #ifdef, thanks emil.brink
       - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
        set it to 1 for real-time compression).
       - Merged in some compiler fixes from paulharris's github repro.
       - Retested this build under Windows (VS 2010, including static analysis), tcc  0.9.26, gcc v4.6 and clang v3.3.
       - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
       - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
       - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
       - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
     5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
     5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
       - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
       - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
       - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
        "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
       - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
       - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
       - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
       - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
       - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
     4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
      level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com> for the feedback/bug report.
     5/28/11 v1.11 - Added statement from unlicense.org
     5/27/11 v1.10 - Substantial compressor optimizations:
      - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
      - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
      - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
      - Refactored the compression code for better readability and maintainability.
      - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
       drop in throughput on some files).
     5/15/11 v1.09 - Initial stable release.

   * Low-level Deflate/Inflate implementation notes:

     Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
     greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
     approximately as well as zlib.

     Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
     coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
     block large enough to hold the entire file.

     The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.

   * zlib-style API notes:

     miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
     zlib replacement in many apps:
        The z_stream struct, optional memory allocation callbacks
        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
        inflateInit/inflateInit2/inflate/inflateEnd
        compress, compress2, compressBound, uncompress
        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
        Supports raw deflate streams or standard zlib streams with adler-32 checking.

     Limitations:
      The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
      I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
      there are no guarantees that miniz.c pulls this off perfectly.

   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
     Alex Evans. Supports 1-4 bytes/pixel images.

   * ZIP archive API notes:

     The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
     get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
     existing archives, create new archives, append new files to existing archives, or clone archive data from
     one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
     or you can specify custom file read/write callbacks.

     - Archive reading: Just call this function to read a single file from a disk archive:

      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
        size_t *pSize, mz_uint zip_flags);

     For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
     directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.

     - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:

     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);

     The locate operation can optionally check file comments too, which (as one example) can be used to identify
     multiple versions of the same file in an archive. This function uses a simple linear search through the central
     directory, so it's not very fast.

     Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
     retrieve detailed info on each file by calling mz_zip_reader_file_stat().

     - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
     to disk and builds an exact image of the central directory in memory. The central directory image is written
     all at once at the end of the archive file when the archive is finalized.

     The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
     which can be useful when the archive will be read from optical media. Also, the writer supports placing
     arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
     readable by any ZIP tool.

     - Archive appending: The simple way to add a single file to an archive is to call this function:

      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
        const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);

     The archive will be created if it doesn't already exist, otherwise it'll be appended to.
     Note the appending is done in-place and is not an atomic operation, so if something goes wrong
     during the operation it's possible the archive could be left without a central directory (although the local
     file headers and file data will be fine, so the archive will be recoverable).

     For more complex archive modification scenarios:
     1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
     preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
     compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
     you're done. This is safe but requires a bunch of temporary disk space or heap memory.

     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
     append new files as needed, then finalize the archive which will write an updated central directory to the
     original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
     possibility that the archive's central directory could be lost with this method if anything goes wrong, though.

     - ZIP archive support limitations:
     No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
     Requires streams capable of seeking.

   * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
     below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.

   * Important: For best perf. be sure to customize the below macros for your target platform:
     #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
     #define MINIZ_LITTLE_ENDIAN 1
     #define MINIZ_HAS_64BIT_REGISTERS 1

   * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
     uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
     (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
*/

#ifndef MINIZ_HEADER_INCLUDED
#define MINIZ_HEADER_INCLUDED

#include <stdlib.h>

// Defines to completely disable specific portions of miniz.c:
// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.

// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
//#define MINIZ_NO_STDIO

// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
// get/set file times, and the C run-time funcs that get/set times won't be called.
// The current downside is the times written to your archives will be from 1979.
//#define MINIZ_NO_TIME

// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
//#define MINIZ_NO_ARCHIVE_APIS

// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
//#define MINIZ_NO_ARCHIVE_WRITING_APIS

// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
//#define MINIZ_NO_ZLIB_APIS

// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES

// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
//#define MINIZ_NO_MALLOC

#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
  // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
  #define MINIZ_NO_TIME
#endif

#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
  #include <time.h>
#endif

#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
#define MINIZ_X86_OR_X64_CPU 1
#endif

#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
#define MINIZ_LITTLE_ENDIAN 1
#endif

#if MINIZ_X86_OR_X64_CPU
// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
#endif

#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
#define MINIZ_HAS_64BIT_REGISTERS 1
#endif

#ifdef __cplusplus
extern "C" {
#endif

// ------------------- zlib-style API Definitions.

// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
typedef unsigned long mz_ulong;

// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
void mz_free(void *p);

#define MZ_ADLER32_INIT (1)
// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);

#define MZ_CRC32_INIT (0)
// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);

// Compression strategies.
enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };

// Method
#define MZ_DEFLATED 8

#ifndef MINIZ_NO_ZLIB_APIS

// Heap allocation callbacks.
// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
typedef void (*mz_free_func)(void *opaque, void *address);
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);

#define MZ_VERSION          "9.1.15"
#define MZ_VERNUM           0x91F0
#define MZ_VER_MAJOR        9
#define MZ_VER_MINOR        1
#define MZ_VER_REVISION     15
#define MZ_VER_SUBREVISION  0

// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };

// Return status codes. MZ_PARAM_ERROR is non-standard.
enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };

// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };

// Window bits
#define MZ_DEFAULT_WINDOW_BITS 15

struct mz_internal_state;

// Compression/decompression stream struct.
typedef struct mz_stream_s
{
  const unsigned char *next_in;     // pointer to next byte to read
  unsigned int avail_in;            // number of bytes available at next_in
  mz_ulong total_in;                // total number of bytes consumed so far

  unsigned char *next_out;          // pointer to next byte to write
  unsigned int avail_out;           // number of bytes that can be written to next_out
  mz_ulong total_out;               // total number of bytes produced so far

  char *msg;                        // error msg (unused)
  struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree

  mz_alloc_func zalloc;             // optional heap allocation function (defaults to malloc)
  mz_free_func zfree;               // optional heap free function (defaults to free)
  void *opaque;                     // heap alloc function user pointer

  int data_type;                    // data_type (unused)
  mz_ulong adler;                   // adler32 of the source or uncompressed data
  mz_ulong reserved;                // not used
} mz_stream;

typedef mz_stream *mz_streamp;

// Returns the version string of miniz.c.
const char *mz_version(void);

// mz_deflateInit() initializes a compressor with default options:
// Parameters:
//  pStream must point to an initialized mz_stream struct.
//  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
//  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
//  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
// Return values:
//  MZ_OK on success.
//  MZ_STREAM_ERROR if the stream is bogus.
//  MZ_PARAM_ERROR if the input parameters are bogus.
//  MZ_MEM_ERROR on out of memory.
int mz_deflateInit(mz_streamp pStream, int level);

// mz_deflateInit2() is like mz_deflate(), except with more control:
// Additional parameters:
//   method must be MZ_DEFLATED
//   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
//   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);

// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
int mz_deflateReset(mz_streamp pStream);

// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
// Parameters:
//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
//   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
// Return values:
//   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
//   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
//   MZ_STREAM_ERROR if the stream is bogus.
//   MZ_PARAM_ERROR if one of the parameters is invalid.
//   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
int mz_deflate(mz_streamp pStream, int flush);

// mz_deflateEnd() deinitializes a compressor:
// Return values:
//  MZ_OK on success.
//  MZ_STREAM_ERROR if the stream is bogus.
int mz_deflateEnd(mz_streamp pStream);

// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);

// Single-call compression functions mz_compress() and mz_compress2():
// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);

// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
mz_ulong mz_compressBound(mz_ulong source_len);

// Initializes a decompressor.
int mz_inflateInit(mz_streamp pStream);

// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
int mz_inflateInit2(mz_streamp pStream, int window_bits);

// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
// Parameters:
//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
//   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
//   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
//   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
// Return values:
//   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
//   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
//   MZ_STREAM_ERROR if the stream is bogus.
//   MZ_DATA_ERROR if the deflate stream is invalid.
//   MZ_PARAM_ERROR if one of the parameters is invalid.
//   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
//   with more input data, or with more room in the output buffer (except when using single call decompression, described above).
int mz_inflate(mz_streamp pStream, int flush);

// Deinitializes a decompressor.
int mz_inflateEnd(mz_streamp pStream);

// Single-call decompression.
// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);

// Returns a string description of the specified error code, or NULL if the error code is invalid.
const char *mz_error(int err);

// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
  typedef unsigned char Byte;
  typedef unsigned int uInt;
  typedef mz_ulong uLong;
  typedef Byte Bytef;
  typedef uInt uIntf;
  typedef char charf;
  typedef int intf;
  typedef void *voidpf;
  typedef uLong uLongf;
  typedef void *voidp;
  typedef void *const voidpc;
  #define Z_NULL                0
  #define Z_NO_FLUSH            MZ_NO_FLUSH
  #define Z_PARTIAL_FLUSH       MZ_PARTIAL_FLUSH
  #define Z_SYNC_FLUSH          MZ_SYNC_FLUSH
  #define Z_FULL_FLUSH          MZ_FULL_FLUSH
  #define Z_FINISH              MZ_FINISH
  #define Z_BLOCK               MZ_BLOCK
  #define Z_OK                  MZ_OK
  #define Z_STREAM_END          MZ_STREAM_END
  #define Z_NEED_DICT           MZ_NEED_DICT
  #define Z_ERRNO               MZ_ERRNO
  #define Z_STREAM_ERROR        MZ_STREAM_ERROR
  #define Z_DATA_ERROR          MZ_DATA_ERROR
  #define Z_MEM_ERROR           MZ_MEM_ERROR
  #define Z_BUF_ERROR           MZ_BUF_ERROR
  #define Z_VERSION_ERROR       MZ_VERSION_ERROR
  #define Z_PARAM_ERROR         MZ_PARAM_ERROR
  #define Z_NO_COMPRESSION      MZ_NO_COMPRESSION
  #define Z_BEST_SPEED          MZ_BEST_SPEED
  #define Z_BEST_COMPRESSION    MZ_BEST_COMPRESSION
  #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
  #define Z_DEFAULT_STRATEGY    MZ_DEFAULT_STRATEGY
  #define Z_FILTERED            MZ_FILTERED
  #define Z_HUFFMAN_ONLY        MZ_HUFFMAN_ONLY
  #define Z_RLE                 MZ_RLE
  #define Z_FIXED               MZ_FIXED
  #define Z_DEFLATED            MZ_DEFLATED
  #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
  #define alloc_func            mz_alloc_func
  #define free_func             mz_free_func
  #define internal_state        mz_internal_state
  #define z_stream              mz_stream
  #define deflateInit           mz_deflateInit
  #define deflateInit2          mz_deflateInit2
  #define deflateReset          mz_deflateReset
  #define deflate               mz_deflate
  #define deflateEnd            mz_deflateEnd
  #define deflateBound          mz_deflateBound
  #define compress              mz_compress
  #define compress2             mz_compress2
  #define compressBound         mz_compressBound
  #define inflateInit           mz_inflateInit
  #define inflateInit2          mz_inflateInit2
  #define inflate               mz_inflate
  #define inflateEnd            mz_inflateEnd
  #define uncompress            mz_uncompress
  #define crc32                 mz_crc32
  #define adler32               mz_adler32
  #define MAX_WBITS             15
  #define MAX_MEM_LEVEL         9
  #define zError                mz_error
  #define ZLIB_VERSION          MZ_VERSION
  #define ZLIB_VERNUM           MZ_VERNUM
  #define ZLIB_VER_MAJOR        MZ_VER_MAJOR
  #define ZLIB_VER_MINOR        MZ_VER_MINOR
  #define ZLIB_VER_REVISION     MZ_VER_REVISION
  #define ZLIB_VER_SUBREVISION  MZ_VER_SUBREVISION
  #define zlibVersion           mz_version
  #define zlib_version          mz_version()
#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES

#endif // MINIZ_NO_ZLIB_APIS

// ------------------- Types and macros

typedef unsigned char mz_uint8;
typedef signed short mz_int16;
typedef unsigned short mz_uint16;
typedef unsigned int mz_uint32;
typedef unsigned int mz_uint;
typedef long long mz_int64;
typedef unsigned long long mz_uint64;
typedef int mz_bool;

#define MZ_FALSE (0)
#define MZ_TRUE (1)

// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
#ifdef _MSC_VER
   #define MZ_MACRO_END while (0, 0)
#else
   #define MZ_MACRO_END while (0)
#endif

// ------------------- ZIP archive reading/writing

#ifndef MINIZ_NO_ARCHIVE_APIS

enum
{
  MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
};

typedef struct
{
  mz_uint32 m_file_index;
  mz_uint32 m_central_dir_ofs;
  mz_uint16 m_version_made_by;
  mz_uint16 m_version_needed;
  mz_uint16 m_bit_flag;
  mz_uint16 m_method;
#ifndef MINIZ_NO_TIME
  time_t m_time;
#endif
  mz_uint32 m_crc32;
  mz_uint64 m_comp_size;
  mz_uint64 m_uncomp_size;
  mz_uint16 m_internal_attr;
  mz_uint32 m_external_attr;
  mz_uint64 m_local_header_ofs;
  mz_uint32 m_comment_size;
  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
} mz_zip_archive_file_stat;

typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);

struct mz_zip_internal_state_tag;
typedef struct mz_zip_internal_state_tag mz_zip_internal_state;

typedef enum
{
  MZ_ZIP_MODE_INVALID = 0,
  MZ_ZIP_MODE_READING = 1,
  MZ_ZIP_MODE_WRITING = 2,
  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
} mz_zip_mode;

typedef struct mz_zip_archive_tag
{
  mz_uint64 m_archive_size;
  mz_uint64 m_central_directory_file_ofs;
  mz_uint m_total_files;
  mz_zip_mode m_zip_mode;

  mz_uint m_file_offset_alignment;

  mz_alloc_func m_pAlloc;
  mz_free_func m_pFree;
  mz_realloc_func m_pRealloc;
  void *m_pAlloc_opaque;

  mz_file_read_func m_pRead;
  mz_file_write_func m_pWrite;
  void *m_pIO_opaque;

  mz_zip_internal_state *m_pState;

} mz_zip_archive;

typedef enum
{
  MZ_ZIP_FLAG_CASE_SENSITIVE                = 0x0100,
  MZ_ZIP_FLAG_IGNORE_PATH                   = 0x0200,
  MZ_ZIP_FLAG_COMPRESSED_DATA               = 0x0400,
  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
} mz_zip_flags;

// ZIP archive reading

// Inits a ZIP archive reader.
// These functions read and validate the archive's central directory.
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);

#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
#endif

// Returns the total number of files in the archive.
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);

// Returns detailed information about an archive file entry.
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);

// Determines if an archive file entry is a directory entry.
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);

// Retrieves the filename of an archive file entry.
// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);

// Attempts to locates a file in the archive's central directory.
// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
// Returns -1 if the file cannot be found.
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);

// Extracts a archive file to a memory buffer using no memory allocation.
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);

// Extracts a archive file to a memory buffer.
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);

// Extracts a archive file to a dynamically allocated heap buffer.
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);

// Extracts a archive file using a callback function to output the file's data.
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);

#ifndef MINIZ_NO_STDIO
// Extracts a archive file to a disk file and sets its last accessed and modified times.
// This function only extracts files, not archive directory records.
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
#endif

// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
mz_bool mz_zip_reader_end(mz_zip_archive *pZip);

// ZIP archive writing

#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

// Inits a ZIP archive writer.
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);

#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
#endif

// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
// the archive is finalized the file's central directory will be hosed.
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);

// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);

#ifndef MINIZ_NO_STDIO
// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
#endif

// Adds a file to an archive by fully cloning the data from another archive.
// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);

// Finalizes the archive by writing the central directory records followed by the end of central directory record.
// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
// An archive must be manually finalized by calling this function for it to be valid.
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);

// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
// Note for the archive to be valid, it must have been finalized before ending.
mz_bool mz_zip_writer_end(mz_zip_archive *pZip);

// Misc. high-level helper functions:

// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);

// Reads a single file from an archive into a heap block.
// Returns NULL on failure.
void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);

#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

#endif // #ifndef MINIZ_NO_ARCHIVE_APIS

// ------------------- Low-level Decompression API Definitions

// Decompression flags used by tinfl_decompress().
// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
enum
{
  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
  TINFL_FLAG_HAS_MORE_INPUT = 2,
  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
  TINFL_FLAG_COMPUTE_ADLER32 = 8
};

// High level decompression functions:
// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
// On entry:
//  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
// On return:
//  Function returns a pointer to the decompressed data, or NULL on failure.
//  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
//  The caller must call mz_free() on the returned block when it's no longer needed.
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);

// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);

// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
// Returns 1 on success or 0 on failure.
typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);

struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;

// Max size of LZ dictionary.
#define TINFL_LZ_DICT_SIZE 32768

// Return status.
typedef enum
{
  TINFL_STATUS_BAD_PARAM = -3,
  TINFL_STATUS_ADLER32_MISMATCH = -2,
  TINFL_STATUS_FAILED = -1,
  TINFL_STATUS_DONE = 0,
  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
  TINFL_STATUS_HAS_MORE_OUTPUT = 2
} tinfl_status;

// Initializes the decompressor to its initial state.
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
#define tinfl_get_adler32(r) (r)->m_check_adler32

// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);

// Internal/private bits follow.
enum
{
  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
};

typedef struct
{
  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
} tinfl_huff_table;

#if MINIZ_HAS_64BIT_REGISTERS
  #define TINFL_USE_64BIT_BITBUF 1
#endif

#if TINFL_USE_64BIT_BITBUF
  typedef mz_uint64 tinfl_bit_buf_t;
  #define TINFL_BITBUF_SIZE (64)
#else
  typedef mz_uint32 tinfl_bit_buf_t;
  #define TINFL_BITBUF_SIZE (32)
#endif

struct tinfl_decompressor_tag
{
  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
  tinfl_bit_buf_t m_bit_buf;
  size_t m_dist_from_out_buf_start;
  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
};

// ------------------- Low-level Compression API Definitions

// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
#define TDEFL_LESS_MEMORY 0

// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
enum
{
  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
};

// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
enum
{
  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
  TDEFL_COMPUTE_ADLER32               = 0x02000,
  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
  TDEFL_RLE_MATCHES                   = 0x10000,
  TDEFL_FILTER_MATCHES                = 0x20000,
  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
};

// High level compression functions:
// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
// On entry:
//  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
//  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
// On return:
//  Function returns a pointer to the compressed data, or NULL on failure.
//  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
//  The caller must free() the returned block when it's no longer needed.
void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);

// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
// Returns 0 on failure.
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);

// Compresses an image to a compressed PNG file in memory.
// On entry:
//  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4.
//  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
//  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
//  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
// On return:
//  Function returns a pointer to the compressed data, or NULL on failure.
//  *pLen_out will be set to the size of the PNG image file.
//  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);

// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);

// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);

enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };

// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
#if TDEFL_LESS_MEMORY
enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
#else
enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
#endif

// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
typedef enum
{
  TDEFL_STATUS_BAD_PARAM = -2,
  TDEFL_STATUS_PUT_BUF_FAILED = -1,
  TDEFL_STATUS_OKAY = 0,
  TDEFL_STATUS_DONE = 1,
} tdefl_status;

// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
typedef enum
{
  TDEFL_NO_FLUSH = 0,
  TDEFL_SYNC_FLUSH = 2,
  TDEFL_FULL_FLUSH = 3,
  TDEFL_FINISH = 4
} tdefl_flush;

// tdefl's compression state structure.
typedef struct
{
  tdefl_put_buf_func_ptr m_pPut_buf_func;
  void *m_pPut_buf_user;
  mz_uint m_flags, m_max_probes[2];
  int m_greedy_parsing;
  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
  tdefl_status m_prev_return_status;
  const void *m_pIn_buf;
  void *m_pOut_buf;
  size_t *m_pIn_buf_size, *m_pOut_buf_size;
  tdefl_flush m_flush;
  const mz_uint8 *m_pSrc;
  size_t m_src_buf_left, m_out_buf_ofs;
  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
} tdefl_compressor;

// Initializes the compressor.
// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);

// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);

// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
// tdefl_compress_buffer() always consumes the entire input buffer.
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);

tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
mz_uint32 tdefl_get_adler32(tdefl_compressor *d);

// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
#ifndef MINIZ_NO_ZLIB_APIS
// Create tdefl_compress() flags given zlib-style compression parameters.
// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
// window_bits may be -15 (raw deflate) or 15 (zlib)
// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
#endif // #ifndef MINIZ_NO_ZLIB_APIS

#ifdef __cplusplus
}
#endif

#endif // MINIZ_HEADER_INCLUDED

// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)

#ifndef MINIZ_HEADER_FILE_ONLY

typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];

#include <string.h>
#include <assert.h>

#define MZ_ASSERT(x) assert(x)

#ifdef MINIZ_NO_MALLOC
  #define MZ_MALLOC(x) NULL
  #define MZ_FREE(x) (void)x, ((void)0)
  #define MZ_REALLOC(p, x) NULL
#else
  #define MZ_MALLOC(x) malloc(x)
  #define MZ_FREE(x) free(x)
  #define MZ_REALLOC(p, x) realloc(p, x)
#endif

#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
  #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
  #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
#else
  #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
  #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
#endif

#ifdef _MSC_VER
  #define MZ_FORCEINLINE __forceinline
#elif defined(__GNUC__)
  #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
#else
  #define MZ_FORCEINLINE inline
#endif

#ifdef __cplusplus
  extern "C" {
#endif

// ------------------- zlib-style API's

mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
{
  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
  if (!ptr) return MZ_ADLER32_INIT;
  while (buf_len) {
    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
    }
    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
  }
  return (s2 << 16) + s1;
}

// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
{
  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
  mz_uint32 crcu32 = (mz_uint32)crc;
  if (!ptr) return MZ_CRC32_INIT;
  crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
  return ~crcu32;
}

void mz_free(void *p)
{
  MZ_FREE(p);
}

#ifndef MINIZ_NO_ZLIB_APIS

static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }

const char *mz_version(void)
{
  return MZ_VERSION;
}

int mz_deflateInit(mz_streamp pStream, int level)
{
  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
}

int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
{
  tdefl_compressor *pComp;
  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);

  if (!pStream) return MZ_STREAM_ERROR;
  if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;

  pStream->data_type = 0;
  pStream->adler = MZ_ADLER32_INIT;
  pStream->msg = NULL;
  pStream->reserved = 0;
  pStream->total_in = 0;
  pStream->total_out = 0;
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
  if (!pStream->zfree) pStream->zfree = def_free_func;

  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
  if (!pComp)
    return MZ_MEM_ERROR;

  pStream->state = (struct mz_internal_state *)pComp;

  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
  {
    mz_deflateEnd(pStream);
    return MZ_PARAM_ERROR;
  }

  return MZ_OK;
}

int mz_deflateReset(mz_streamp pStream)
{
  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
  pStream->total_in = pStream->total_out = 0;
  tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
  return MZ_OK;
}

int mz_deflate(mz_streamp pStream, int flush)
{
  size_t in_bytes, out_bytes;
  mz_ulong orig_total_in, orig_total_out;
  int mz_status = MZ_OK;

  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
  if (!pStream->avail_out) return MZ_BUF_ERROR;

  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;

  if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;

  orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
  for ( ; ; )
  {
    tdefl_status defl_status;
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;

    defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);

    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
    pStream->total_out += (mz_uint)out_bytes;

    if (defl_status < 0)
    {
      mz_status = MZ_STREAM_ERROR;
      break;
    }
    else if (defl_status == TDEFL_STATUS_DONE)
    {
      mz_status = MZ_STREAM_END;
      break;
    }
    else if (!pStream->avail_out)
      break;
    else if ((!pStream->avail_in) && (flush != MZ_FINISH))
    {
      if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
        break;
      return MZ_BUF_ERROR; // Can't make forward progress without some input.
    }
  }
  return mz_status;
}

int mz_deflateEnd(mz_streamp pStream)
{
  if (!pStream) return MZ_STREAM_ERROR;
  if (pStream->state)
  {
    pStream->zfree(pStream->opaque, pStream->state);
    pStream->state = NULL;
  }
  return MZ_OK;
}

mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
{
  (void)pStream;
  // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
}

int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
{
  int status;
  mz_stream stream;
  memset(&stream, 0, sizeof(stream));

  // In case mz_ulong is 64-bits (argh I hate longs).
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;

  stream.next_in = pSource;
  stream.avail_in = (mz_uint32)source_len;
  stream.next_out = pDest;
  stream.avail_out = (mz_uint32)*pDest_len;

  status = mz_deflateInit(&stream, level);
  if (status != MZ_OK) return status;

  status = mz_deflate(&stream, MZ_FINISH);
  if (status != MZ_STREAM_END)
  {
    mz_deflateEnd(&stream);
    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
  }

  *pDest_len = stream.total_out;
  return mz_deflateEnd(&stream);
}

int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
{
  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
}

mz_ulong mz_compressBound(mz_ulong source_len)
{
  return mz_deflateBound(NULL, source_len);
}

typedef struct
{
  tinfl_decompressor m_decomp;
  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
  tinfl_status m_last_status;
} inflate_state;

int mz_inflateInit2(mz_streamp pStream, int window_bits)
{
  inflate_state *pDecomp;
  if (!pStream) return MZ_STREAM_ERROR;
  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;

  pStream->data_type = 0;
  pStream->adler = 0;
  pStream->msg = NULL;
  pStream->total_in = 0;
  pStream->total_out = 0;
  pStream->reserved = 0;
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
  if (!pStream->zfree) pStream->zfree = def_free_func;

  pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
  if (!pDecomp) return MZ_MEM_ERROR;

  pStream->state = (struct mz_internal_state *)pDecomp;

  tinfl_init(&pDecomp->m_decomp);
  pDecomp->m_dict_ofs = 0;
  pDecomp->m_dict_avail = 0;
  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
  pDecomp->m_first_call = 1;
  pDecomp->m_has_flushed = 0;
  pDecomp->m_window_bits = window_bits;

  return MZ_OK;
}

int mz_inflateInit(mz_streamp pStream)
{
   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
}

int mz_inflate(mz_streamp pStream, int flush)
{
  inflate_state* pState;
  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
  size_t in_bytes, out_bytes, orig_avail_in;
  tinfl_status status;

  if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;

  pState = (inflate_state*)pStream->state;
  if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
  orig_avail_in = pStream->avail_in;

  first_call = pState->m_first_call; pState->m_first_call = 0;
  if (pState->m_last_status < 0) return MZ_DATA_ERROR;

  if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
  pState->m_has_flushed |= (flush == MZ_FINISH);

  if ((flush == MZ_FINISH) && (first_call))
  {
    // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
    pState->m_last_status = status;
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;

    if (status < 0)
      return MZ_DATA_ERROR;
    else if (status != TINFL_STATUS_DONE)
    {
      pState->m_last_status = TINFL_STATUS_FAILED;
      return MZ_BUF_ERROR;
    }
    return MZ_STREAM_END;
  }
  // flush != MZ_FINISH then we must assume there's more input.
  if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;

  if (pState->m_dict_avail)
  {
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
    return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
  }

  for ( ; ; )
  {
    in_bytes = pStream->avail_in;
    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;

    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
    pState->m_last_status = status;

    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);

    pState->m_dict_avail = (mz_uint)out_bytes;

    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);

    if (status < 0)
       return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
      return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
    else if (flush == MZ_FINISH)
    {
       // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
       if (status == TINFL_STATUS_DONE)
          return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
       else if (!pStream->avail_out)
          return MZ_BUF_ERROR;
    }
    else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
      break;
  }

  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
}

int mz_inflateEnd(mz_streamp pStream)
{
  if (!pStream)
    return MZ_STREAM_ERROR;
  if (pStream->state)
  {
    pStream->zfree(pStream->opaque, pStream->state);
    pStream->state = NULL;
  }
  return MZ_OK;
}

int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
{
  mz_stream stream;
  int status;
  memset(&stream, 0, sizeof(stream));

  // In case mz_ulong is 64-bits (argh I hate longs).
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;

  stream.next_in = pSource;
  stream.avail_in = (mz_uint32)source_len;
  stream.next_out = pDest;
  stream.avail_out = (mz_uint32)*pDest_len;

  status = mz_inflateInit(&stream);
  if (status != MZ_OK)
    return status;

  status = mz_inflate(&stream, MZ_FINISH);
  if (status != MZ_STREAM_END)
  {
    mz_inflateEnd(&stream);
    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
  }
  *pDest_len = stream.total_out;

  return mz_inflateEnd(&stream);
}

const char *mz_error(int err)
{
  static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
  {
    { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
    { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
  };
  mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
  return NULL;
}

#endif //MINIZ_NO_ZLIB_APIS

// ------------------- Low-level Decompression (completely independent from all compression API's)

#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
#define TINFL_MEMSET(p, c, l) memset(p, c, l)

#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
#define TINFL_CR_FINISH }

// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
#define TINFL_GET_BYTE(state_index, c) do { \
  if (pIn_buf_cur >= pIn_buf_end) { \
    for ( ; ; ) { \
      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
        if (pIn_buf_cur < pIn_buf_end) { \
          c = *pIn_buf_cur++; \
          break; \
        } \
      } else { \
        c = 0; \
        break; \
      } \
    } \
  } else c = *pIn_buf_cur++; } MZ_MACRO_END

#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END

// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
// bit buffer contains >=15 bits (deflate's max. Huffman code size).
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
  do { \
    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
    if (temp >= 0) { \
      code_len = temp >> 9; \
      if ((code_len) && (num_bits >= code_len)) \
      break; \
    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
       code_len = TINFL_FAST_LOOKUP_BITS; \
       do { \
          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
  } while (num_bits < 15);

// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
// The slow path is only executed at the very end of the input buffer.
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
  int temp; mz_uint code_len, c; \
  if (num_bits < 15) { \
    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
    } else { \
       bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
    } \
  } \
  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
    code_len = temp >> 9, temp &= 511; \
  else { \
    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END

tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
{
  static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
  static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
  static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
  static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
  static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
  static const int s_min_table_sizes[3] = { 257, 1, 4 };

  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
  size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;

  // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
  if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }

  num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
  TINFL_CR_BEGIN

  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
  {
    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
    if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
  }

  do
  {
    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
    if (r->m_type == 0)
    {
      TINFL_SKIP_BITS(5, num_bits & 7);
      for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
      if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
      while ((counter) && (num_bits))
      {
        TINFL_GET_BITS(51, dist, 8);
        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
        *pOut_buf_cur++ = (mz_uint8)dist;
        counter--;
      }
      while (counter)
      {
        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
        while (pIn_buf_cur >= pIn_buf_end)
        {
          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
          {
            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
          }
          else
          {
            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
          }
        }
        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
      }
    }
    else if (r->m_type == 3)
    {
      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
    }
    else
    {
      if (r->m_type == 1)
      {
        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
        r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
        for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
      }
      else
      {
        for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
        r->m_table_sizes[2] = 19;
      }
      for ( ; (int)r->m_type >= 0; r->m_type--)
      {
        int tree_next, tree_cur; tinfl_huff_table *pTable;
        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
        if ((65536 != total) && (used_syms > 1))
        {
          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
        }
        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
        {
          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
          cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
          if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
          if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
          {
            tree_cur -= ((rev_code >>= 1) & 1);
            if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
          }
          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
        }
        if (r->m_type == 2)
        {
          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
          {
            mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
            if ((dist == 16) && (!counter))
            {
              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
            }
            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
          }
          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
          {
            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
          }
          TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
        }
      }
      for ( ; ; )
      {
        mz_uint8 *pSrc;
        for ( ; ; )
        {
          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
          {
            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
            if (counter >= 256)
              break;
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
            *pOut_buf_cur++ = (mz_uint8)counter;
          }
          else
          {
            int sym2; mz_uint code_len;
#if TINFL_USE_64BIT_BITBUF
            if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
#else
            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
#endif
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
              code_len = sym2 >> 9;
            else
            {
              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
            }
            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
            if (counter & 256)
              break;

#if !TINFL_USE_64BIT_BITBUF
            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
#endif
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
              code_len = sym2 >> 9;
            else
            {
              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
            }
            bit_buf >>= code_len; num_bits -= code_len;

            pOut_buf_cur[0] = (mz_uint8)counter;
            if (sym2 & 256)
            {
              pOut_buf_cur++;
              counter = sym2;
              break;
            }
            pOut_buf_cur[1] = (mz_uint8)sym2;
            pOut_buf_cur += 2;
          }
        }
        if ((counter &= 511) == 256) break;

        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }

        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }

        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
        {
          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
        }

        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);

        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
        {
          while (counter--)
          {
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
          }
          continue;
        }
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
        else if ((counter >= 9) && (counter <= dist))
        {
          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
          do
          {
            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
            pOut_buf_cur += 8;
          } while ((pSrc += 8) < pSrc_end);
          if ((counter &= 7) < 3)
          {
            if (counter)
            {
              pOut_buf_cur[0] = pSrc[0];
              if (counter > 1)
                pOut_buf_cur[1] = pSrc[1];
              pOut_buf_cur += counter;
            }
            continue;
          }
        }
#endif
        do
        {
          pOut_buf_cur[0] = pSrc[0];
          pOut_buf_cur[1] = pSrc[1];
          pOut_buf_cur[2] = pSrc[2];
          pOut_buf_cur += 3; pSrc += 3;
        } while ((int)(counter -= 3) > 2);
        if ((int)counter > 0)
        {
          pOut_buf_cur[0] = pSrc[0];
          if ((int)counter > 1)
            pOut_buf_cur[1] = pSrc[1];
          pOut_buf_cur += counter;
        }
      }
    }
  } while (!(r->m_final & 1));
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
  {
    TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
  }
  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
  TINFL_CR_FINISH

common_exit:
  r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
  {
    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
    while (buf_len)
    {
      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
      {
        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
      }
      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
    }
    r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
  }
  return status;
}

// Higher level helper functions.
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
{
  tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
  *pOut_len = 0;
  tinfl_init(&decomp);
  for ( ; ; )
  {
    size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
      (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
    {
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
    }
    src_buf_ofs += src_buf_size;
    *pOut_len += dst_buf_size;
    if (status == TINFL_STATUS_DONE) break;
    new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
    if (!pNew_buf)
    {
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
    }
    pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
  }
  return pBuf;
}

size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
{
  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
  status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
}

int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
{
  int result = 0;
  tinfl_decompressor decomp;
  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
  if (!pDict)
    return TINFL_STATUS_FAILED;
  tinfl_init(&decomp);
  for ( ; ; )
  {
    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
    in_buf_ofs += in_buf_size;
    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
      break;
    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
    {
      result = (status == TINFL_STATUS_DONE);
      break;
    }
    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
  }
  MZ_FREE(pDict);
  *pIn_buf_size = in_buf_ofs;
  return result;
}

// ------------------- Low-level Compression (independent from all decompression API's)

// Purposely making these tables static for faster init and thread safety.
static const mz_uint16 s_tdefl_len_sym[256] = {
  257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
  273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
  277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
  279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
  281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
  282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
  283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
  284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };

static const mz_uint8 s_tdefl_len_extra[256] = {
  0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };

static const mz_uint8 s_tdefl_small_dist_sym[512] = {
  0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
  11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
  14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };

static const mz_uint8 s_tdefl_small_dist_extra[512] = {
  0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  7,7,7,7,7,7,7,7 };

static const mz_uint8 s_tdefl_large_dist_sym[128] = {
  0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
  26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
  28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };

static const mz_uint8 s_tdefl_large_dist_extra[128] = {
  0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };

// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
{
  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
  {
    const mz_uint32* pHist = &hist[pass << 8];
    mz_uint offsets[256], cur_ofs = 0;
    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
  }
  return pCur_syms;
}

// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
{
  int root, leaf, next, avbl, used, dpth;
  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
  for (next=1; next < n-1; next++)
  {
    if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
    if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
  }
  A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
  while (avbl>0)
  {
    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
    avbl = 2*used; dpth++; used = 0;
  }
}

// Limits canonical Huffman code table's max code size.
enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
{
  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
  while (total != (1UL << max_code_size))
  {
    pNum_codes[max_code_size]--;
    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
    total--;
  }
}

static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
{
  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
  if (static_table)
  {
    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
  }
  else
  {
    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
    int num_used_syms = 0;
    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
    for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }

    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);

    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;

    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);

    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
      for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
  }

  next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);

  for (i = 0; i < table_len; i++)
  {
    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
  }
}

#define TDEFL_PUT_BITS(b, l) do { \
  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
  while (d->m_bits_in >= 8) { \
    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
      d->m_bit_buffer >>= 8; \
      d->m_bits_in -= 8; \
  } \
} MZ_MACRO_END

#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
  if (rle_repeat_count < 3) { \
    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
  } else { \
    d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
} rle_repeat_count = 0; } }

#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
  if (rle_z_count < 3) { \
    d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
  } else if (rle_z_count <= 10) { \
    d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
  } else { \
    d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
} rle_z_count = 0; } }

static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };

static void tdefl_start_dynamic_block(tdefl_compressor *d)
{
  int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
  mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;

  d->m_huff_count[0][256] = 1;

  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);

  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;

  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
  total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;

  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
  for (i = 0; i < total_code_sizes_to_pack; i++)
  {
    mz_uint8 code_size = code_sizes_to_pack[i];
    if (!code_size)
    {
      TDEFL_RLE_PREV_CODE_SIZE();
      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
    }
    else
    {
      TDEFL_RLE_ZERO_CODE_SIZE();
      if (code_size != prev_code_size)
      {
        TDEFL_RLE_PREV_CODE_SIZE();
        d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
      }
      else if (++rle_repeat_count == 6)
      {
        TDEFL_RLE_PREV_CODE_SIZE();
      }
    }
    prev_code_size = code_size;
  }
  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }

  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);

  TDEFL_PUT_BITS(2, 2);

  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
  TDEFL_PUT_BITS(num_dist_codes - 1, 5);

  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
  for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);

  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
  {
    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
  }
}

static void tdefl_start_static_block(tdefl_compressor *d)
{
  mz_uint i;
  mz_uint8 *p = &d->m_huff_code_sizes[0][0];

  for (i = 0; i <= 143; ++i) *p++ = 8;
  for ( ; i <= 255; ++i) *p++ = 9;
  for ( ; i <= 279; ++i) *p++ = 7;
  for ( ; i <= 287; ++i) *p++ = 8;

  memset(d->m_huff_code_sizes[1], 5, 32);

  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);

  TDEFL_PUT_BITS(1, 2);
}

static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
{
  mz_uint flags;
  mz_uint8 *pLZ_codes;
  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
  mz_uint64 bit_buffer = d->m_bit_buffer;
  mz_uint bits_in = d->m_bits_in;

#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }

  flags = 1;
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
  {
    if (flags == 1)
      flags = *pLZ_codes++ | 0x100;

    if (flags & 1)
    {
      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
      mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;

      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);

      // This sequence coaxes MSVC into using cmov's vs. jmp's.
      s0 = s_tdefl_small_dist_sym[match_dist & 511];
      n0 = s_tdefl_small_dist_extra[match_dist & 511];
      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
      sym = (match_dist < 512) ? s0 : s1;
      num_extra_bits = (match_dist < 512) ? n0 : n1;

      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
    }
    else
    {
      mz_uint lit = *pLZ_codes++;
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);

      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
      {
        flags >>= 1;
        lit = *pLZ_codes++;
        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);

        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
        {
          flags >>= 1;
          lit = *pLZ_codes++;
          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
        }
      }
    }

    if (pOutput_buf >= d->m_pOutput_buf_end)
      return MZ_FALSE;

    *(mz_uint64*)pOutput_buf = bit_buffer;
    pOutput_buf += (bits_in >> 3);
    bit_buffer >>= (bits_in & ~7);
    bits_in &= 7;
  }

#undef TDEFL_PUT_BITS_FAST

  d->m_pOutput_buf = pOutput_buf;
  d->m_bits_in = 0;
  d->m_bit_buffer = 0;

  while (bits_in)
  {
    mz_uint32 n = MZ_MIN(bits_in, 16);
    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
    bit_buffer >>= n;
    bits_in -= n;
  }

  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);

  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
}
#else
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
{
  mz_uint flags;
  mz_uint8 *pLZ_codes;

  flags = 1;
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
  {
    if (flags == 1)
      flags = *pLZ_codes++ | 0x100;
    if (flags & 1)
    {
      mz_uint sym, num_extra_bits;
      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;

      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
      TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);

      if (match_dist < 512)
      {
        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
      }
      else
      {
        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
      }
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
    }
    else
    {
      mz_uint lit = *pLZ_codes++;
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
    }
  }

  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);

  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
}
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS

static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
{
  if (static_block)
    tdefl_start_static_block(d);
  else
    tdefl_start_dynamic_block(d);
  return tdefl_compress_lz_codes(d);
}

static int tdefl_flush_block(tdefl_compressor *d, int flush)
{
  mz_uint saved_bit_buf, saved_bits_in;
  mz_uint8 *pSaved_output_buf;
  mz_bool comp_block_succeeded = MZ_FALSE;
  int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
  mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;

  d->m_pOutput_buf = pOutput_buf_start;
  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;

  MZ_ASSERT(!d->m_output_flush_remaining);
  d->m_output_flush_ofs = 0;
  d->m_output_flush_remaining = 0;

  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);

  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
  {
    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
  }

  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);

  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;

  if (!use_raw_block)
    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));

  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
  {
    mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
    TDEFL_PUT_BITS(0, 2);
    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
    {
      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
    }
    for (i = 0; i < d->m_total_lz_bytes; ++i)
    {
      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
    }
  }
  // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
  else if (!comp_block_succeeded)
  {
    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
    tdefl_compress_block(d, MZ_TRUE);
  }

  if (flush)
  {
    if (flush == TDEFL_FINISH)
    {
      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
      if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
    }
    else
    {
      mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
    }
  }

  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);

  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);

  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;

  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
  {
    if (d->m_pPut_buf_func)
    {
      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
    }
    else if (pOutput_buf_start == d->m_output_buf)
    {
      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
      d->m_out_buf_ofs += bytes_to_copy;
      if ((n -= bytes_to_copy) != 0)
      {
        d->m_output_flush_ofs = bytes_to_copy;
        d->m_output_flush_remaining = n;
      }
    }
    else
    {
      d->m_out_buf_ofs += n;
    }
  }

  return d->m_output_flush_remaining;
}

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
{
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
  const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
  for ( ; ; )
  {
    for ( ; ; )
    {
      if (--num_probes_left == 0) return;
      #define TDEFL_PROBE \
        next_probe_pos = d->m_next[probe_pos]; \
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
        if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
    }
    if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
    do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
                   (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
    if (!probe_len)
    {
      *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
    }
    else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
    {
      *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
    }
  }
}
#else
static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
{
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
  const mz_uint8 *s = d->m_dict + pos, *p, *q;
  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
  for ( ; ; )
  {
    for ( ; ; )
    {
      if (--num_probes_left == 0) return;
      #define TDEFL_PROBE \
        next_probe_pos = d->m_next[probe_pos]; \
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
    }
    if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
    if (probe_len > match_len)
    {
      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
    }
  }
}
#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
static mz_bool tdefl_compress_fast(tdefl_compressor *d)
{
  // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
  mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;

  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
  {
    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
    mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
    d->m_src_buf_left -= num_bytes_to_process;
    lookahead_size += num_bytes_to_process;

    while (num_bytes_to_process)
    {
      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
        memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
      d->m_pSrc += n;
      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
      num_bytes_to_process -= n;
    }

    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;

    while (lookahead_size >= 4)
    {
      mz_uint cur_match_dist, cur_match_len = 1;
      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
      mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
      mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
      mz_uint probe_pos = d->m_hash[hash];
      d->m_hash[hash] = (mz_uint16)lookahead_pos;

      if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
      {
        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
        mz_uint32 probe_len = 32;
        do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
          (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
        if (!probe_len)
          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;

        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
        {
          cur_match_len = 1;
          *pLZ_code_buf++ = (mz_uint8)first_trigram;
          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
          d->m_huff_count[0][(mz_uint8)first_trigram]++;
        }
        else
        {
          mz_uint32 s0, s1;
          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);

          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));

          cur_match_dist--;

          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
          pLZ_code_buf += 3;
          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);

          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;

          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
        }
      }
      else
      {
        *pLZ_code_buf++ = (mz_uint8)first_trigram;
        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
        d->m_huff_count[0][(mz_uint8)first_trigram]++;
      }

      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }

      total_lz_bytes += cur_match_len;
      lookahead_pos += cur_match_len;
      dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
      MZ_ASSERT(lookahead_size >= cur_match_len);
      lookahead_size -= cur_match_len;

      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
      {
        int n;
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
        if ((n = tdefl_flush_block(d, 0)) != 0)
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
      }
    }

    while (lookahead_size)
    {
      mz_uint8 lit = d->m_dict[cur_pos];

      total_lz_bytes++;
      *pLZ_code_buf++ = lit;
      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }

      d->m_huff_count[0][lit]++;

      lookahead_pos++;
      dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
      lookahead_size--;

      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
      {
        int n;
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
        if ((n = tdefl_flush_block(d, 0)) != 0)
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
      }
    }
  }

  d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
  d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
  return MZ_TRUE;
}
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN

static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
{
  d->m_total_lz_bytes++;
  *d->m_pLZ_code_buf++ = lit;
  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
  d->m_huff_count[0][lit]++;
}

static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
{
  mz_uint32 s0, s1;

  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));

  d->m_total_lz_bytes += match_len;

  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);

  match_dist -= 1;
  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;

  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }

  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;

  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
}

static mz_bool tdefl_compress_normal(tdefl_compressor *d)
{
  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
  tdefl_flush flush = d->m_flush;

  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
  {
    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
    {
      mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
      mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
      src_buf_left -= num_bytes_to_process;
      d->m_lookahead_size += num_bytes_to_process;
      while (pSrc != pSrc_end)
      {
        mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
      }
    }
    else
    {
      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
      {
        mz_uint8 c = *pSrc++;
        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
        src_buf_left--;
        d->m_dict[dst_pos] = c;
        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
        {
          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
          mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
        }
      }
    }
    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
      break;

    // Simple lazy/greedy parsing state machine.
    len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
    {
      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
      {
        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
        cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
      }
    }
    else
    {
      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
    }
    if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
    {
      cur_match_dist = cur_match_len = 0;
    }
    if (d->m_saved_match_len)
    {
      if (cur_match_len > d->m_saved_match_len)
      {
        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
        if (cur_match_len >= 128)
        {
          tdefl_record_match(d, cur_match_len, cur_match_dist);
          d->m_saved_match_len = 0; len_to_move = cur_match_len;
        }
        else
        {
          d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
        }
      }
      else
      {
        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
      }
    }
    else if (!cur_match_dist)
      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
    {
      tdefl_record_match(d, cur_match_len, cur_match_dist);
      len_to_move = cur_match_len;
    }
    else
    {
      d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
    }
    // Move the lookahead forward by len_to_move bytes.
    d->m_lookahead_pos += len_to_move;
    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
    d->m_lookahead_size -= len_to_move;
    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
    // Check if it's time to flush the current LZ codes to the internal output buffer.
    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
         ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
    {
      int n;
      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
      if ((n = tdefl_flush_block(d, 0)) != 0)
        return (n < 0) ? MZ_FALSE : MZ_TRUE;
    }
  }

  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
  return MZ_TRUE;
}

static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
{
  if (d->m_pIn_buf_size)
  {
    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
  }

  if (d->m_pOut_buf_size)
  {
    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
    d->m_output_flush_ofs += (mz_uint)n;
    d->m_output_flush_remaining -= (mz_uint)n;
    d->m_out_buf_ofs += n;

    *d->m_pOut_buf_size = d->m_out_buf_ofs;
  }

  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
}

tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
{
  if (!d)
  {
    if (pIn_buf_size) *pIn_buf_size = 0;
    if (pOut_buf_size) *pOut_buf_size = 0;
    return TDEFL_STATUS_BAD_PARAM;
  }

  d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
  d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
  d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
  d->m_out_buf_ofs = 0;
  d->m_flush = flush;

  if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
  {
    if (pIn_buf_size) *pIn_buf_size = 0;
    if (pOut_buf_size) *pOut_buf_size = 0;
    return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
  }
  d->m_wants_to_finish |= (flush == TDEFL_FINISH);

  if ((d->m_output_flush_remaining) || (d->m_finished))
    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
  if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
      ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
      ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
  {
    if (!tdefl_compress_fast(d))
      return d->m_prev_return_status;
  }
  else
#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
  {
    if (!tdefl_compress_normal(d))
      return d->m_prev_return_status;
  }

  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
    d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);

  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
  {
    if (tdefl_flush_block(d, flush) < 0)
      return d->m_prev_return_status;
    d->m_finished = (flush == TDEFL_FINISH);
    if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
  }

  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
}

tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
{
  MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
}

tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
{
  d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
  d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
  d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
  d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
  d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
  d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
  return TDEFL_STATUS_OKAY;
}

tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
{
  return d->m_prev_return_status;
}

mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
{
  return d->m_adler32;
}

mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
{
  tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
  pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
  succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
  MZ_FREE(pComp); return succeeded;
}

typedef struct
{
  size_t m_size, m_capacity;
  mz_uint8 *m_pBuf;
  mz_bool m_expandable;
} tdefl_output_buffer;

static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
{
  tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
  size_t new_size = p->m_size + len;
  if (new_size > p->m_capacity)
  {
    size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
    do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
    pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
    p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
  }
  memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
  return MZ_TRUE;
}

void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
{
  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
  if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
  out_buf.m_expandable = MZ_TRUE;
  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
  *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
}

size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
{
  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
  if (!pOut_buf) return 0;
  out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
  return out_buf.m_size;
}

#ifndef MINIZ_NO_ZLIB_APIS
static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };

// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
{
  mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
  if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;

  if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
  else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
  else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
  else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
  else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;

  return comp_flags;
}
#endif //MINIZ_NO_ZLIB_APIS

#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
#endif

// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
{
  // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
  static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
  tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
  if (!pComp) return NULL;
  MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
  // write dummy header
  for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
  // compress image data
  tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
  for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
  // write real header
  *pLen_out = out_buf.m_size-41;
  {
    static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
    mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
      0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
      (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
    c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
    memcpy(out_buf.m_pBuf, pnghdr, 41);
  }
  // write footer (IDAT CRC-32, followed by IEND chunk)
  if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
  // compute final size of file, grab compressed data buffer and return
  *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
}
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
{
  // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
  return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
}

#ifdef _MSC_VER
#pragma warning (pop)
#endif

// ------------------- .ZIP archive reading

#ifndef MINIZ_NO_ARCHIVE_APIS

#ifdef MINIZ_NO_STDIO
  #define MZ_FILE void *
#else
  #include <stdio.h>
  #include <sys/stat.h>

  #if defined(_MSC_VER) || defined(__MINGW64__)
    static FILE *mz_fopen(const char *pFilename, const char *pMode)
    {
      FILE* pFile = NULL;
      fopen_s(&pFile, pFilename, pMode);
      return pFile;
    }
    static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
    {
      FILE* pFile = NULL;
      if (freopen_s(&pFile, pPath, pMode, pStream))
        return NULL;
      return pFile;
    }
    #ifndef MINIZ_NO_TIME
      #include <sys/utime.h>
    #endif
    #define MZ_FILE FILE
    #define MZ_FOPEN mz_fopen
    #define MZ_FCLOSE fclose
    #define MZ_FREAD fread
    #define MZ_FWRITE fwrite
    #define MZ_FTELL64 _ftelli64
    #define MZ_FSEEK64 _fseeki64
    #define MZ_FILE_STAT_STRUCT _stat
    #define MZ_FILE_STAT _stat
    #define MZ_FFLUSH fflush
    #define MZ_FREOPEN mz_freopen
    #define MZ_DELETE_FILE remove
  #elif defined(__MINGW32__)
    #ifndef MINIZ_NO_TIME
      #include <sys/utime.h>
    #endif
    #define MZ_FILE FILE
    #define MZ_FOPEN(f, m) fopen(f, m)
    #define MZ_FCLOSE fclose
    #define MZ_FREAD fread
    #define MZ_FWRITE fwrite
    #define MZ_FTELL64 ftello64
    #define MZ_FSEEK64 fseeko64
    #define MZ_FILE_STAT_STRUCT _stat
    #define MZ_FILE_STAT _stat
    #define MZ_FFLUSH fflush
    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
    #define MZ_DELETE_FILE remove
  #elif defined(__TINYC__)
    #ifndef MINIZ_NO_TIME
      #include <sys/utime.h>
    #endif
    #define MZ_FILE FILE
    #define MZ_FOPEN(f, m) fopen(f, m)
    #define MZ_FCLOSE fclose
    #define MZ_FREAD fread
    #define MZ_FWRITE fwrite
    #define MZ_FTELL64 ftell
    #define MZ_FSEEK64 fseek
    #define MZ_FILE_STAT_STRUCT stat
    #define MZ_FILE_STAT stat
    #define MZ_FFLUSH fflush
    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
    #define MZ_DELETE_FILE remove
  #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
    #ifndef MINIZ_NO_TIME
      #include <utime.h>
    #endif
    #define MZ_FILE FILE
    #define MZ_FOPEN(f, m) fopen64(f, m)
    #define MZ_FCLOSE fclose
    #define MZ_FREAD fread
    #define MZ_FWRITE fwrite
    #define MZ_FTELL64 ftello64
    #define MZ_FSEEK64 fseeko64
    #define MZ_FILE_STAT_STRUCT stat64
    #define MZ_FILE_STAT stat64
    #define MZ_FFLUSH fflush
    #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
    #define MZ_DELETE_FILE remove
  #else
    #ifndef MINIZ_NO_TIME
      #include <utime.h>
    #endif
    #define MZ_FILE FILE
    #define MZ_FOPEN(f, m) fopen(f, m)
    #define MZ_FCLOSE fclose
    #define MZ_FREAD fread
    #define MZ_FWRITE fwrite
    #define MZ_FTELL64 ftello
    #define MZ_FSEEK64 fseeko
    #define MZ_FILE_STAT_STRUCT stat
    #define MZ_FILE_STAT stat
    #define MZ_FFLUSH fflush
    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
    #define MZ_DELETE_FILE remove
  #endif // #ifdef _MSC_VER
#endif // #ifdef MINIZ_NO_STDIO

#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))

// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
enum
{
  // ZIP archive identifiers and record sizes
  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
  // Central directory header record offsets
  MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
  MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
  // Local directory header offsets
  MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
  MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
  // End of central directory offsets
  MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
};

typedef struct
{
  void *m_p;
  size_t m_size, m_capacity;
  mz_uint m_element_size;
} mz_zip_array;

struct mz_zip_internal_state_tag
{
  mz_zip_array m_central_dir;
  mz_zip_array m_central_dir_offsets;
  mz_zip_array m_sorted_central_dir_offsets;
  MZ_FILE *m_pFile;
  void *m_pMem;
  size_t m_mem_size;
  size_t m_mem_capacity;
};

#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]

static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
{
  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
  memset(pArray, 0, sizeof(mz_zip_array));
}

static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
{
  void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
  if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
  pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
  return MZ_TRUE;
}

static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
{
  if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
  return MZ_TRUE;
}

static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
{
  if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
  pArray->m_size = new_size;
  return MZ_TRUE;
}

static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
{
  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
}

static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
{
  size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
  memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
  return MZ_TRUE;
}

#ifndef MINIZ_NO_TIME
static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
{
  struct tm tm;
  memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
  tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
  return mktime(&tm);
}

static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
{
#ifdef _MSC_VER
  struct tm tm_struct;
  struct tm *tm = &tm_struct;
  errno_t err = localtime_s(tm, &time);
  if (err)
  {
    *pDOS_date = 0; *pDOS_time = 0;
    return;
  }
#else
  struct tm *tm = localtime(&time);
#endif
  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
}
#endif

#ifndef MINIZ_NO_STDIO
static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
{
#ifdef MINIZ_NO_TIME
  (void)pFilename; *pDOS_date = *pDOS_time = 0;
#else
  struct MZ_FILE_STAT_STRUCT file_stat;
  // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
  if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
    return MZ_FALSE;
  mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
#endif // #ifdef MINIZ_NO_TIME
  return MZ_TRUE;
}

#ifndef MINIZ_NO_TIME
static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
{
  struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
  return !utime(pFilename, &t);
}
#endif // #ifndef MINIZ_NO_TIME
#endif // #ifndef MINIZ_NO_STDIO

static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
{
  (void)flags;
  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
    return MZ_FALSE;

  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;

  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
  pZip->m_archive_size = 0;
  pZip->m_central_directory_file_ofs = 0;
  pZip->m_total_files = 0;

  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
    return MZ_FALSE;
  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
  return MZ_TRUE;
}

static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
{
  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
  mz_uint8 l = 0, r = 0;
  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
  pE = pL + MZ_MIN(l_len, r_len);
  while (pL < pE)
  {
    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
      break;
    pL++; pR++;
  }
  return (pL == pE) ? (l_len < r_len) : (l < r);
}

#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END

// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
{
  mz_zip_internal_state *pState = pZip->m_pState;
  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
  const int size = pZip->m_total_files;
  int start = (size - 2) >> 1, end;
  while (start >= 0)
  {
    int child, root = start;
    for ( ; ; )
    {
      if ((child = (root << 1) + 1) >= size)
        break;
      child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
        break;
      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
    }
    start--;
  }

  end = size - 1;
  while (end > 0)
  {
    int child, root = 0;
    MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
    for ( ; ; )
    {
      if ((child = (root << 1) + 1) >= end)
        break;
      child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
        break;
      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
    }
    end--;
  }
}

static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
{
  mz_uint cdir_size, num_this_disk, cdir_disk_index;
  mz_uint64 cdir_ofs;
  mz_int64 cur_file_ofs;
  const mz_uint8 *p;
  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
  mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
  // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  // Find the end of central directory record by scanning the file from the end towards the beginning.
  cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
  for ( ; ; )
  {
    int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
      return MZ_FALSE;
    for (i = n - 4; i >= 0; --i)
      if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
        break;
    if (i >= 0)
    {
      cur_file_ofs += i;
      break;
    }
    if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
      return MZ_FALSE;
    cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
  }
  // Read and verify the end of central directory record.
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
      ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
    return MZ_FALSE;

  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
  if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
    return MZ_FALSE;

  if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
    return MZ_FALSE;

  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
    return MZ_FALSE;

  pZip->m_central_directory_file_ofs = cdir_ofs;

  if (pZip->m_total_files)
  {
     mz_uint i, n;

    // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
    if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
        (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
      return MZ_FALSE;

    if (sort_central_dir)
    {
      if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
        return MZ_FALSE;
    }

    if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
      return MZ_FALSE;

    // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
    p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
    for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
    {
      mz_uint total_header_size, comp_size, decomp_size, disk_index;
      if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
        return MZ_FALSE;
      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
      if (sort_central_dir)
        MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
      comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
      decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
      if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
        return MZ_FALSE;
      disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
      if ((disk_index != num_this_disk) && (disk_index != 1))
        return MZ_FALSE;
      if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
        return MZ_FALSE;
      if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
        return MZ_FALSE;
      n -= total_header_size; p += total_header_size;
    }
  }

  if (sort_central_dir)
    mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);

  return MZ_TRUE;
}

mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
{
  if ((!pZip) || (!pZip->m_pRead))
    return MZ_FALSE;
  if (!mz_zip_reader_init_internal(pZip, flags))
    return MZ_FALSE;
  pZip->m_archive_size = size;
  if (!mz_zip_reader_read_central_dir(pZip, flags))
  {
    mz_zip_reader_end(pZip);
    return MZ_FALSE;
  }
  return MZ_TRUE;
}

static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
{
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
  size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
  return s;
}

mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
{
  if (!mz_zip_reader_init_internal(pZip, flags))
    return MZ_FALSE;
  pZip->m_archive_size = size;
  pZip->m_pRead = mz_zip_mem_read_func;
  pZip->m_pIO_opaque = pZip;
#ifdef __cplusplus
  pZip->m_pState->m_pMem = const_cast<void *>(pMem);
#else
  pZip->m_pState->m_pMem = (void *)pMem;
#endif
  pZip->m_pState->m_mem_size = size;
  if (!mz_zip_reader_read_central_dir(pZip, flags))
  {
    mz_zip_reader_end(pZip);
    return MZ_FALSE;
  }
  return MZ_TRUE;
}

#ifndef MINIZ_NO_STDIO
static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
{
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
    return 0;
  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
}

mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
{
  mz_uint64 file_size;
  MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
  if (!pFile)
    return MZ_FALSE;
  if (MZ_FSEEK64(pFile, 0, SEEK_END))
  {
    MZ_FCLOSE(pFile);
    return MZ_FALSE;
  }
  file_size = MZ_FTELL64(pFile);
  if (!mz_zip_reader_init_internal(pZip, flags))
  {
    MZ_FCLOSE(pFile);
    return MZ_FALSE;
  }
  pZip->m_pRead = mz_zip_file_read_func;
  pZip->m_pIO_opaque = pZip;
  pZip->m_pState->m_pFile = pFile;
  pZip->m_archive_size = file_size;
  if (!mz_zip_reader_read_central_dir(pZip, flags))
  {
    mz_zip_reader_end(pZip);
    return MZ_FALSE;
  }
  return MZ_TRUE;
}
#endif // #ifndef MINIZ_NO_STDIO

mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
{
  return pZip ? pZip->m_total_files : 0;
}

static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
{
  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
    return NULL;
  return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
}

mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
{
  mz_uint m_bit_flag;
  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
  if (!p)
    return MZ_FALSE;
  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
  return (m_bit_flag & 1);
}

mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
{
  mz_uint filename_len, external_attr;
  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
  if (!p)
    return MZ_FALSE;

  // First see if the filename ends with a '/' character.
  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
  if (filename_len)
  {
    if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
      return MZ_TRUE;
  }

  // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
  // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
  // FIXME: Remove this check? Is it necessary - we already check the filename.
  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
  if ((external_attr & 0x10) != 0)
    return MZ_TRUE;

  return MZ_FALSE;
}

mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
{
  mz_uint n;
  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
  if ((!p) || (!pStat))
    return MZ_FALSE;

  // Unpack the central directory record.
  pStat->m_file_index = file_index;
  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
#ifndef MINIZ_NO_TIME
  pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
#endif
  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);

  // Copy as much of the filename and comment as possible.
  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';

  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
  pStat->m_comment_size = n;
  memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';

  return MZ_TRUE;
}

mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
{
  mz_uint n;
  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
  if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
  if (filename_buf_size)
  {
    n = MZ_MIN(n, filename_buf_size - 1);
    memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
    pFilename[n] = '\0';
  }
  return n + 1;
}

static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
{
  mz_uint i;
  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
    return 0 == memcmp(pA, pB, len);
  for (i = 0; i < len; ++i)
    if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
      return MZ_FALSE;
  return MZ_TRUE;
}

static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
{
  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
  mz_uint8 l = 0, r = 0;
  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
  pE = pL + MZ_MIN(l_len, r_len);
  while (pL < pE)
  {
    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
      break;
    pL++; pR++;
  }
  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
}

static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
{
  mz_zip_internal_state *pState = pZip->m_pState;
  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
  const int size = pZip->m_total_files;
  const mz_uint filename_len = (mz_uint)strlen(pFilename);
  int l = 0, h = size - 1;
  while (l <= h)
  {
    int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
    if (!comp)
      return file_index;
    else if (comp < 0)
      l = m + 1;
    else
      h = m - 1;
  }
  return -1;
}

int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
{
  mz_uint file_index; size_t name_len, comment_len;
  if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
    return -1;
  if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
    return mz_zip_reader_locate_file_binary_search(pZip, pName);
  name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
  comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
  for (file_index = 0; file_index < pZip->m_total_files; file_index++)
  {
    const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
    mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
    const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
    if (filename_len < name_len)
      continue;
    if (comment_len)
    {
      mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
      const char *pFile_comment = pFilename + filename_len + file_extra_len;
      if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
        continue;
    }
    if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
    {
      int ofs = filename_len - 1;
      do
      {
        if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
          break;
      } while (--ofs >= 0);
      ofs++;
      pFilename += ofs; filename_len -= ofs;
    }
    if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
      return file_index;
  }
  return -1;
}

mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
{
  int status = TINFL_STATUS_DONE;
  mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
  mz_zip_archive_file_stat file_stat;
  void *pRead_buf;
  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
  tinfl_decompressor inflator;

  if ((buf_size) && (!pBuf))
    return MZ_FALSE;

  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
    return MZ_FALSE;

  // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
  if (!file_stat.m_comp_size)
    return MZ_TRUE;

  // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
  // I'm torn how to handle this case - should it fail instead?
  if (mz_zip_reader_is_file_a_directory(pZip, file_index))
    return MZ_TRUE;

  // Encryption and patch files are not supported.
  if (file_stat.m_bit_flag & (1 | 32))
    return MZ_FALSE;

  // This function only supports stored and deflate.
  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
    return MZ_FALSE;

  // Ensure supplied output buffer is large enough.
  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
  if (buf_size < needed_size)
    return MZ_FALSE;

  // Read and parse the local directory entry.
  cur_file_ofs = file_stat.m_local_header_ofs;
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
    return MZ_FALSE;

  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
    return MZ_FALSE;

  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
  {
    // The file is stored or the caller has requested the compressed data.
    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
      return MZ_FALSE;
    return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
  }

  // Decompress the file either directly from memory or from a file input buffer.
  tinfl_init(&inflator);

  if (pZip->m_pState->m_pMem)
  {
    // Read directly from the archive in memory.
    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
    read_buf_size = read_buf_avail = file_stat.m_comp_size;
    comp_remaining = 0;
  }
  else if (pUser_read_buf)
  {
    // Use a user provided read buffer.
    if (!user_read_buf_size)
      return MZ_FALSE;
    pRead_buf = (mz_uint8 *)pUser_read_buf;
    read_buf_size = user_read_buf_size;
    read_buf_avail = 0;
    comp_remaining = file_stat.m_comp_size;
  }
  else
  {
    // Temporarily allocate a read buffer.
    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
#ifdef _MSC_VER
    if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
#else
    if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
#endif
      return MZ_FALSE;
    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
      return MZ_FALSE;
    read_buf_avail = 0;
    comp_remaining = file_stat.m_comp_size;
  }

  do
  {
    size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
    if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
    {
      read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
      if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
      {
        status = TINFL_STATUS_FAILED;
        break;
      }
      cur_file_ofs += read_buf_avail;
      comp_remaining -= read_buf_avail;
      read_buf_ofs = 0;
    }
    in_buf_size = (size_t)read_buf_avail;
    status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
    read_buf_avail -= in_buf_size;
    read_buf_ofs += in_buf_size;
    out_buf_ofs += out_buf_size;
  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);

  if (status == TINFL_STATUS_DONE)
  {
    // Make sure the entire file was decompressed, and check its CRC.
    if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
      status = TINFL_STATUS_FAILED;
  }

  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);

  return status == TINFL_STATUS_DONE;
}

mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
{
  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
  if (file_index < 0)
    return MZ_FALSE;
  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
}

mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
{
  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
}

mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
{
  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
}

void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
{
  mz_uint64 comp_size, uncomp_size, alloc_size;
  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
  void *pBuf;

  if (pSize)
    *pSize = 0;
  if (!p)
    return NULL;

  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);

  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
#ifdef _MSC_VER
  if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
#else
  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
#endif
    return NULL;
  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
    return NULL;

  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
  {
    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
    return NULL;
  }

  if (pSize) *pSize = (size_t)alloc_size;
  return pBuf;
}

void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
{
  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
  if (file_index < 0)
  {
    if (pSize) *pSize = 0;
    return MZ_FALSE;
  }
  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
}

mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
{
  int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
  mz_zip_archive_file_stat file_stat;
  void *pRead_buf = NULL; void *pWrite_buf = NULL;
  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;

  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
    return MZ_FALSE;

  // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
  if (!file_stat.m_comp_size)
    return MZ_TRUE;

  // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
  // I'm torn how to handle this case - should it fail instead?
  if (mz_zip_reader_is_file_a_directory(pZip, file_index))
    return MZ_TRUE;

  // Encryption and patch files are not supported.
  if (file_stat.m_bit_flag & (1 | 32))
    return MZ_FALSE;

  // This function only supports stored and deflate.
  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
    return MZ_FALSE;

  // Read and parse the local directory entry.
  cur_file_ofs = file_stat.m_local_header_ofs;
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
    return MZ_FALSE;

  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
    return MZ_FALSE;

  // Decompress the file either directly from memory or from a file input buffer.
  if (pZip->m_pState->m_pMem)
  {
    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
    read_buf_size = read_buf_avail = file_stat.m_comp_size;
    comp_remaining = 0;
  }
  else
  {
    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
      return MZ_FALSE;
    read_buf_avail = 0;
    comp_remaining = file_stat.m_comp_size;
  }

  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
  {
    // The file is stored or the caller has requested the compressed data.
    if (pZip->m_pState->m_pMem)
    {
#ifdef _MSC_VER
      if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
#else
      if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
#endif
        return MZ_FALSE;
      if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
        status = TINFL_STATUS_FAILED;
      else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
        file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
      cur_file_ofs += file_stat.m_comp_size;
      out_buf_ofs += file_stat.m_comp_size;
      comp_remaining = 0;
    }
    else
    {
      while (comp_remaining)
      {
        read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
        {
          status = TINFL_STATUS_FAILED;
          break;
        }

        if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
          file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);

        if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
        {
          status = TINFL_STATUS_FAILED;
          break;
        }
        cur_file_ofs += read_buf_avail;
        out_buf_ofs += read_buf_avail;
        comp_remaining -= read_buf_avail;
      }
    }
  }
  else
  {
    tinfl_decompressor inflator;
    tinfl_init(&inflator);

    if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
      status = TINFL_STATUS_FAILED;
    else
    {
      do
      {
        mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
        size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
        {
          read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
          if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
          {
            status = TINFL_STATUS_FAILED;
            break;
          }
          cur_file_ofs += read_buf_avail;
          comp_remaining -= read_buf_avail;
          read_buf_ofs = 0;
        }

        in_buf_size = (size_t)read_buf_avail;
        status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
        read_buf_avail -= in_buf_size;
        read_buf_ofs += in_buf_size;

        if (out_buf_size)
        {
          if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
          {
            status = TINFL_STATUS_FAILED;
            break;
          }
          file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
          if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
          {
            status = TINFL_STATUS_FAILED;
            break;
          }
        }
      } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
    }
  }

  if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
  {
    // Make sure the entire file was decompressed, and check its CRC.
    if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
      status = TINFL_STATUS_FAILED;
  }

  if (!pZip->m_pState->m_pMem)
    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
  if (pWrite_buf)
    pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);

  return status == TINFL_STATUS_DONE;
}

mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
{
  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
  if (file_index < 0)
    return MZ_FALSE;
  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
}

#ifndef MINIZ_NO_STDIO
static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
{
  (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
}

mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
{
  mz_bool status;
  mz_zip_archive_file_stat file_stat;
  MZ_FILE *pFile;
  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
    return MZ_FALSE;
  pFile = MZ_FOPEN(pDst_filename, "wb");
  if (!pFile)
    return MZ_FALSE;
  status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
  if (MZ_FCLOSE(pFile) == EOF)
    return MZ_FALSE;
#ifndef MINIZ_NO_TIME
  if (status)
    mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
#endif
  return status;
}
#endif // #ifndef MINIZ_NO_STDIO

mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
{
  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
    return MZ_FALSE;

  if (pZip->m_pState)
  {
    mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
    mz_zip_array_clear(pZip, &pState->m_central_dir);
    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);

#ifndef MINIZ_NO_STDIO
    if (pState->m_pFile)
    {
      MZ_FCLOSE(pState->m_pFile);
      pState->m_pFile = NULL;
    }
#endif // #ifndef MINIZ_NO_STDIO

    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
  }
  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;

  return MZ_TRUE;
}

#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
{
  int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
  if (file_index < 0)
    return MZ_FALSE;
  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
}
#endif

// ------------------- .ZIP archive writing

#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))

mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
{
  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
    return MZ_FALSE;

  if (pZip->m_file_offset_alignment)
  {
    // Ensure user specified file offset alignment is a power of 2.
    if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
      return MZ_FALSE;
  }

  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;

  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
  pZip->m_archive_size = existing_size;
  pZip->m_central_directory_file_ofs = 0;
  pZip->m_total_files = 0;

  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
    return MZ_FALSE;
  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
  return MZ_TRUE;
}

static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
{
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
  mz_zip_internal_state *pState = pZip->m_pState;
  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
#ifdef _MSC_VER
  if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
#else
  if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
#endif
    return 0;
  if (new_size > pState->m_mem_capacity)
  {
    void *pNew_block;
    size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
    if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
      return 0;
    pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
  }
  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
  pState->m_mem_size = (size_t)new_size;
  return n;
}

mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
{
  pZip->m_pWrite = mz_zip_heap_write_func;
  pZip->m_pIO_opaque = pZip;
  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
    return MZ_FALSE;
  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
  {
    if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
    {
      mz_zip_writer_end(pZip);
      return MZ_FALSE;
    }
    pZip->m_pState->m_mem_capacity = initial_allocation_size;
  }
  return MZ_TRUE;
}

#ifndef MINIZ_NO_STDIO
static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
{
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
    return 0;
  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
}

mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
{
  MZ_FILE *pFile;
  pZip->m_pWrite = mz_zip_file_write_func;
  pZip->m_pIO_opaque = pZip;
  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
    return MZ_FALSE;
  if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
  {
    mz_zip_writer_end(pZip);
    return MZ_FALSE;
  }
  pZip->m_pState->m_pFile = pFile;
  if (size_to_reserve_at_beginning)
  {
    mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
    do
    {
      size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
      {
        mz_zip_writer_end(pZip);
        return MZ_FALSE;
      }
      cur_ofs += n; size_to_reserve_at_beginning -= n;
    } while (size_to_reserve_at_beginning);
  }
  return MZ_TRUE;
}
#endif // #ifndef MINIZ_NO_STDIO

mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
{
  mz_zip_internal_state *pState;
  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
    return MZ_FALSE;
  // No sense in trying to write to an archive that's already at the support max size
  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
    return MZ_FALSE;

  pState = pZip->m_pState;

  if (pState->m_pFile)
  {
#ifdef MINIZ_NO_STDIO
    pFilename; return MZ_FALSE;
#else
    // Archive is being read from stdio - try to reopen as writable.
    if (pZip->m_pIO_opaque != pZip)
      return MZ_FALSE;
    if (!pFilename)
      return MZ_FALSE;
    pZip->m_pWrite = mz_zip_file_write_func;
    if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
    {
      // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
      mz_zip_reader_end(pZip);
      return MZ_FALSE;
    }
#endif // #ifdef MINIZ_NO_STDIO
  }
  else if (pState->m_pMem)
  {
    // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
    if (pZip->m_pIO_opaque != pZip)
      return MZ_FALSE;
    pState->m_mem_capacity = pState->m_mem_size;
    pZip->m_pWrite = mz_zip_heap_write_func;
  }
  // Archive is being read via a user provided read function - make sure the user has specified a write function too.
  else if (!pZip->m_pWrite)
    return MZ_FALSE;

  // Start writing new files at the archive's current central directory location.
  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
  pZip->m_central_directory_file_ofs = 0;

  return MZ_TRUE;
}

mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
{
  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
}

typedef struct
{
  mz_zip_archive *m_pZip;
  mz_uint64 m_cur_archive_file_ofs;
  mz_uint64 m_comp_size;
} mz_zip_writer_add_state;

static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
{
  mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
    return MZ_FALSE;
  pState->m_cur_archive_file_ofs += len;
  pState->m_comp_size += len;
  return MZ_TRUE;
}

static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
{
  (void)pZip;
  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
  return MZ_TRUE;
}

static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
{
  (void)pZip;
  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
  return MZ_TRUE;
}

static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
{
  mz_zip_internal_state *pState = pZip->m_pState;
  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
  size_t orig_central_dir_size = pState->m_central_dir.m_size;
  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];

  // No zip64 support yet
  if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
    return MZ_FALSE;

  if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
    return MZ_FALSE;

  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
  {
    // Try to push the central directory array back into its original state.
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
    return MZ_FALSE;
  }

  return MZ_TRUE;
}

static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
{
  // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
  if (*pArchive_name == '/')
    return MZ_FALSE;
  while (*pArchive_name)
  {
    if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
      return MZ_FALSE;
    pArchive_name++;
  }
  return MZ_TRUE;
}

static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
{
  mz_uint32 n;
  if (!pZip->m_file_offset_alignment)
    return 0;
  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
  return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
}

static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
{
  char buf[4096];
  memset(buf, 0, MZ_MIN(sizeof(buf), n));
  while (n)
  {
    mz_uint32 s = MZ_MIN(sizeof(buf), n);
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
      return MZ_FALSE;
    cur_file_ofs += s; n -= s;
  }
  return MZ_TRUE;
}

mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
{
  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
  size_t archive_name_size;
  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
  tdefl_compressor *pComp = NULL;
  mz_bool store_data_uncompressed;
  mz_zip_internal_state *pState;

  if ((int)level_and_flags < 0)
    level_and_flags = MZ_DEFAULT_LEVEL;
  level = level_and_flags & 0xF;
  store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));

  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
    return MZ_FALSE;

  pState = pZip->m_pState;

  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
    return MZ_FALSE;
  // No zip64 support yet
  if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
    return MZ_FALSE;
  if (!mz_zip_writer_validate_archive_name(pArchive_name))
    return MZ_FALSE;

#ifndef MINIZ_NO_TIME
  {
    time_t cur_time; time(&cur_time);
    mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
  }
#endif // #ifndef MINIZ_NO_TIME

  archive_name_size = strlen(pArchive_name);
  if (archive_name_size > 0xFFFF)
    return MZ_FALSE;

  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);

  // no zip64 support yet
  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
    return MZ_FALSE;

  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
  {
    // Set DOS Subdirectory attribute bit.
    ext_attributes |= 0x10;
    // Subdirectories cannot contain data.
    if ((buf_size) || (uncomp_size))
      return MZ_FALSE;
  }

  // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
  if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
    return MZ_FALSE;

  if ((!store_data_uncompressed) && (buf_size))
  {
    if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
      return MZ_FALSE;
  }

  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
  {
    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
    return MZ_FALSE;
  }
  local_dir_header_ofs += num_alignment_padding_bytes;
  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);

  MZ_CLEAR_OBJ(local_dir_header);
  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
  {
    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
    return MZ_FALSE;
  }
  cur_archive_file_ofs += archive_name_size;

  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
  {
    uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
    uncomp_size = buf_size;
    if (uncomp_size <= 3)
    {
      level = 0;
      store_data_uncompressed = MZ_TRUE;
    }
  }

  if (store_data_uncompressed)
  {
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
      return MZ_FALSE;
    }

    cur_archive_file_ofs += buf_size;
    comp_size = buf_size;

    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
      method = MZ_DEFLATED;
  }
  else if (buf_size)
  {
    mz_zip_writer_add_state state;

    state.m_pZip = pZip;
    state.m_cur_archive_file_ofs = cur_archive_file_ofs;
    state.m_comp_size = 0;

    if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
        (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
      return MZ_FALSE;
    }

    comp_size = state.m_comp_size;
    cur_archive_file_ofs = state.m_cur_archive_file_ofs;

    method = MZ_DEFLATED;
  }

  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
  pComp = NULL;

  // no zip64 support yet
  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
    return MZ_FALSE;

  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
    return MZ_FALSE;

  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
    return MZ_FALSE;

  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
    return MZ_FALSE;

  pZip->m_total_files++;
  pZip->m_archive_size = cur_archive_file_ofs;

  return MZ_TRUE;
}

#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
{
  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
  mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
  size_t archive_name_size;
  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
  MZ_FILE *pSrc_file = NULL;

  if ((int)level_and_flags < 0)
    level_and_flags = MZ_DEFAULT_LEVEL;
  level = level_and_flags & 0xF;

  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
    return MZ_FALSE;
  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
    return MZ_FALSE;
  if (!mz_zip_writer_validate_archive_name(pArchive_name))
    return MZ_FALSE;

  archive_name_size = strlen(pArchive_name);
  if (archive_name_size > 0xFFFF)
    return MZ_FALSE;

  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);

  // no zip64 support yet
  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
    return MZ_FALSE;

  if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
    return MZ_FALSE;

  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
  if (!pSrc_file)
    return MZ_FALSE;
  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
  uncomp_size = MZ_FTELL64(pSrc_file);
  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);

  if (uncomp_size > 0xFFFFFFFF)
  {
    // No zip64 support yet
    MZ_FCLOSE(pSrc_file);
    return MZ_FALSE;
  }
  if (uncomp_size <= 3)
    level = 0;

  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
  {
    MZ_FCLOSE(pSrc_file);
    return MZ_FALSE;
  }
  local_dir_header_ofs += num_alignment_padding_bytes;
  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);

  MZ_CLEAR_OBJ(local_dir_header);
  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
  {
    MZ_FCLOSE(pSrc_file);
    return MZ_FALSE;
  }
  cur_archive_file_ofs += archive_name_size;

  if (uncomp_size)
  {
    mz_uint64 uncomp_remaining = uncomp_size;
    void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
    if (!pRead_buf)
    {
      MZ_FCLOSE(pSrc_file);
      return MZ_FALSE;
    }

    if (!level)
    {
      while (uncomp_remaining)
      {
        mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
        if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
        {
          pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
          MZ_FCLOSE(pSrc_file);
          return MZ_FALSE;
        }
        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
        uncomp_remaining -= n;
        cur_archive_file_ofs += n;
      }
      comp_size = uncomp_size;
    }
    else
    {
      mz_bool result = MZ_FALSE;
      mz_zip_writer_add_state state;
      tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
      if (!pComp)
      {
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
        MZ_FCLOSE(pSrc_file);
        return MZ_FALSE;
      }

      state.m_pZip = pZip;
      state.m_cur_archive_file_ofs = cur_archive_file_ofs;
      state.m_comp_size = 0;

      if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
      {
        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
        MZ_FCLOSE(pSrc_file);
        return MZ_FALSE;
      }

      for ( ; ; )
      {
        size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
        tdefl_status status;

        if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
          break;

        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
        uncomp_remaining -= in_buf_size;

        status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
        if (status == TDEFL_STATUS_DONE)
        {
          result = MZ_TRUE;
          break;
        }
        else if (status != TDEFL_STATUS_OKAY)
          break;
      }

      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);

      if (!result)
      {
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
        MZ_FCLOSE(pSrc_file);
        return MZ_FALSE;
      }

      comp_size = state.m_comp_size;
      cur_archive_file_ofs = state.m_cur_archive_file_ofs;

      method = MZ_DEFLATED;
    }

    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
  }

  MZ_FCLOSE(pSrc_file); pSrc_file = NULL;

  // no zip64 support yet
  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
    return MZ_FALSE;

  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
    return MZ_FALSE;

  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
    return MZ_FALSE;

  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
    return MZ_FALSE;

  pZip->m_total_files++;
  pZip->m_archive_size = cur_archive_file_ofs;

  return MZ_TRUE;
}
#endif // #ifndef MINIZ_NO_STDIO

mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
{
  mz_uint n, bit_flags, num_alignment_padding_bytes;
  mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
  mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
  size_t orig_central_dir_size;
  mz_zip_internal_state *pState;
  void *pBuf; const mz_uint8 *pSrc_central_header;

  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
    return MZ_FALSE;
  if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
    return MZ_FALSE;
  pState = pZip->m_pState;

  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);

  // no zip64 support yet
  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
    return MZ_FALSE;

  cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
  cur_dst_file_ofs = pZip->m_archive_size;

  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
    return MZ_FALSE;
  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;

  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
    return MZ_FALSE;
  cur_dst_file_ofs += num_alignment_padding_bytes;
  local_dir_header_ofs = cur_dst_file_ofs;
  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }

  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
    return MZ_FALSE;
  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;

  n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
  comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);

  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
    return MZ_FALSE;

  while (comp_bytes_remaining)
  {
    n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
      return MZ_FALSE;
    }
    cur_src_file_ofs += n;

    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
      return MZ_FALSE;
    }
    cur_dst_file_ofs += n;

    comp_bytes_remaining -= n;
  }

  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
  if (bit_flags & 8)
  {
    // Copy data descriptor
    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
      return MZ_FALSE;
    }

    n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
    {
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
      return MZ_FALSE;
    }

    cur_src_file_ofs += n;
    cur_dst_file_ofs += n;
  }
  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);

  // no zip64 support yet
  if (cur_dst_file_ofs > 0xFFFFFFFF)
    return MZ_FALSE;

  orig_central_dir_size = pState->m_central_dir.m_size;

  memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
  MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
    return MZ_FALSE;

  n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
  {
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
    return MZ_FALSE;
  }

  if (pState->m_central_dir.m_size > 0xFFFFFFFF)
    return MZ_FALSE;
  n = (mz_uint32)orig_central_dir_size;
  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
  {
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
    return MZ_FALSE;
  }

  pZip->m_total_files++;
  pZip->m_archive_size = cur_dst_file_ofs;

  return MZ_TRUE;
}

mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
{
  mz_zip_internal_state *pState;
  mz_uint64 central_dir_ofs, central_dir_size;
  mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];

  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
    return MZ_FALSE;

  pState = pZip->m_pState;

  // no zip64 support yet
  if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
    return MZ_FALSE;

  central_dir_ofs = 0;
  central_dir_size = 0;
  if (pZip->m_total_files)
  {
    // Write central directory
    central_dir_ofs = pZip->m_archive_size;
    central_dir_size = pState->m_central_dir.m_size;
    pZip->m_central_directory_file_ofs = central_dir_ofs;
    if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
      return MZ_FALSE;
    pZip->m_archive_size += central_dir_size;
  }

  // Write end of central directory record
  MZ_CLEAR_OBJ(hdr);
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);

  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
    return MZ_FALSE;
#ifndef MINIZ_NO_STDIO
  if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
    return MZ_FALSE;
#endif // #ifndef MINIZ_NO_STDIO

  pZip->m_archive_size += sizeof(hdr);

  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
  return MZ_TRUE;
}

mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
{
  if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
    return MZ_FALSE;
  if (pZip->m_pWrite != mz_zip_heap_write_func)
    return MZ_FALSE;
  if (!mz_zip_writer_finalize_archive(pZip))
    return MZ_FALSE;

  *pBuf = pZip->m_pState->m_pMem;
  *pSize = pZip->m_pState->m_mem_size;
  pZip->m_pState->m_pMem = NULL;
  pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
  return MZ_TRUE;
}

mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
{
  mz_zip_internal_state *pState;
  mz_bool status = MZ_TRUE;
  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
    return MZ_FALSE;

  pState = pZip->m_pState;
  pZip->m_pState = NULL;
  mz_zip_array_clear(pZip, &pState->m_central_dir);
  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);

#ifndef MINIZ_NO_STDIO
  if (pState->m_pFile)
  {
    MZ_FCLOSE(pState->m_pFile);
    pState->m_pFile = NULL;
  }
#endif // #ifndef MINIZ_NO_STDIO

  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
  {
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
    pState->m_pMem = NULL;
  }

  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
  return status;
}

#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
{
  mz_bool status, created_new_archive = MZ_FALSE;
  mz_zip_archive zip_archive;
  struct MZ_FILE_STAT_STRUCT file_stat;
  MZ_CLEAR_OBJ(zip_archive);
  if ((int)level_and_flags < 0)
     level_and_flags = MZ_DEFAULT_LEVEL;
  if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
    return MZ_FALSE;
  if (!mz_zip_writer_validate_archive_name(pArchive_name))
    return MZ_FALSE;
  if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
  {
    // Create a new archive.
    if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
      return MZ_FALSE;
    created_new_archive = MZ_TRUE;
  }
  else
  {
    // Append to an existing archive.
    if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
      return MZ_FALSE;
    if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
    {
      mz_zip_reader_end(&zip_archive);
      return MZ_FALSE;
    }
  }
  status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
  // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
  if (!mz_zip_writer_finalize_archive(&zip_archive))
    status = MZ_FALSE;
  if (!mz_zip_writer_end(&zip_archive))
    status = MZ_FALSE;
  if ((!status) && (created_new_archive))
  {
    // It's a new archive and something went wrong, so just delete it.
    int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
    (void)ignoredStatus;
  }
  return status;
}

void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
{
  int file_index;
  mz_zip_archive zip_archive;
  void *p = NULL;

  if (pSize)
    *pSize = 0;

  if ((!pZip_filename) || (!pArchive_name))
    return NULL;

  MZ_CLEAR_OBJ(zip_archive);
  if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
    return NULL;

  if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
    p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);

  mz_zip_reader_end(&zip_archive);
  return p;
}

#endif // #ifndef MINIZ_NO_STDIO

#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

#endif // #ifndef MINIZ_NO_ARCHIVE_APIS

#ifdef __cplusplus
}
#endif

#endif // MINIZ_HEADER_FILE_ONLY

/*
  This is free and unencumbered software released into the public domain.

  Anyone is free to copy, modify, publish, use, compile, sell, or
  distribute this software, either in source code form or as a compiled
  binary, for any purpose, commercial or non-commercial, and by any
  means.

  In jurisdictions that recognize copyright laws, the author or authors
  of this software dedicate any and all copyright interest in the
  software to the public domain. We make this dedication for the benefit
  of the public at large and to the detriment of our heirs and
  successors. We intend this dedication to be an overt act of
  relinquishment in perpetuity of all present and future rights to this
  software under copyright law.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.

  For more information, please refer to <http://unlicense.org/>
*/
Changes to src/mkindex.c.
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
  printf(
    "static const NameMap aCommand[] = {\n"
  );
  for(i=0; i<nFixed /*&& aEntry[i].eType==1*/; i++){
    const char *z = aEntry[i].zPath;
    int n = strlen(z);
    int cmdFlags = (1==aEntry[i].eType) ? 0x01 : 0x08;
    if(0x01==cmdFlags){
      if( z[n-1]=='*' ){
        n--;
        cmdFlags = 0x02;
      }else if( memcmp(z, "test-", 5)==0 ){
        cmdFlags = 0x04;
      }
    }
    if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
    printf("  { \"%s%.*s\",%*s %s,%*s %d },\n",
      (0x08 & cmdFlags) ? "/" : "",
      n, z,
      25-n, "",
      aEntry[i].zFunc,
      (int)(35-strlen(aEntry[i].zFunc)), "",
      cmdFlags
    );
    if( aEntry[i].zIf ) printf("#endif\n");
  }
  printf("};\n");

  for(i=0; i<nFixed; i++){
    char *z = aEntry[i].zHelp;
    if( z && z[0] ){
      if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
      printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
      printf("  \"");
      while( *z ){







|



















>







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  printf(
    "static const NameMap aCommand[] = {\n"
  );
  for(i=0; i<nFixed /*&& aEntry[i].eType==1*/; i++){
    const char *z = aEntry[i].zPath;
    int n = strlen(z);
    int cmdFlags = (1==aEntry[i].eType) ? 0x01 : 0x08;
    if( 0x01==cmdFlags ){
      if( z[n-1]=='*' ){
        n--;
        cmdFlags = 0x02;
      }else if( memcmp(z, "test-", 5)==0 ){
        cmdFlags = 0x04;
      }
    }
    if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
    printf("  { \"%s%.*s\",%*s %s,%*s %d },\n",
      (0x08 & cmdFlags) ? "/" : "",
      n, z,
      25-n, "",
      aEntry[i].zFunc,
      (int)(35-strlen(aEntry[i].zFunc)), "",
      cmdFlags
    );
    if( aEntry[i].zIf ) printf("#endif\n");
  }
  printf("};\n");
  printf("#define FOSSIL_FIRST_CMD (sizeof(aWebpage)/sizeof(aWebpage[0]))\n");
  for(i=0; i<nFixed; i++){
    char *z = aEntry[i].zHelp;
    if( z && z[0] ){
      if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
      printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
      printf("  \"");
      while( *z ){
Changes to src/moderate.c.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

/*
** Create a table to represent pending moderation requests, if the
** table does not already exist.
*/
void moderation_table_create(void){
  db_multi_exec(
     "CREATE TABLE IF NOT EXISTS modreq(\n"
     "  objid INTEGER PRIMARY KEY,\n"        /* Record pending approval */
     "  attachRid INT,\n"                    /* Object attached */
     "  tktid TEXT\n"                        /* Associated ticket id */
     ");\n"
  );
}

/*
** Return TRUE if the modreq table exists
*/
int moderation_table_exists(void){







|



|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

/*
** Create a table to represent pending moderation requests, if the
** table does not already exist.
*/
void moderation_table_create(void){
  db_multi_exec(
     "CREATE TABLE IF NOT EXISTS %s.modreq(\n"
     "  objid INTEGER PRIMARY KEY,\n"        /* Record pending approval */
     "  attachRid INT,\n"                    /* Object attached */
     "  tktid TEXT\n"                        /* Associated ticket id */
     ");\n", db_name("repository")
  );
}

/*
** Return TRUE if the modreq table exists
*/
int moderation_table_exists(void){
Changes to src/name.c.
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
** treat errors as fatal. zName must be a UUID, as described for
** name_to_uuid(). zType is also as described for that function. If
** zName does not resolve, 0 is returned. If it is ambiguous, a
** negative value is returned. On success the rid is returned and
** pUuid (if it is not NULL) is set to the a newly-allocated string,
** the full UUID, which must eventually be free()d by the caller.
*/
int name_to_uuid2(char const *zName, const char *zType, char **pUuid){
  int rid = symbolic_name_to_rid(zName, zType);
  if((rid>0) && pUuid){
    *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }
  return rid;
}








|







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
** treat errors as fatal. zName must be a UUID, as described for
** name_to_uuid(). zType is also as described for that function. If
** zName does not resolve, 0 is returned. If it is ambiguous, a
** negative value is returned. On success the rid is returned and
** pUuid (if it is not NULL) is set to the a newly-allocated string,
** the full UUID, which must eventually be free()d by the caller.
*/
int name_to_uuid2(const char *zName, const char *zType, char **pUuid){
  int rid = symbolic_name_to_rid(zName, zType);
  if((rid>0) && pUuid){
    *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }
  return rid;
}

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    "   SELECT tkt_rid, tkt_uuid, title"
    "     FROM ticket, ticketchng"
    "    WHERE ticket.tkt_id = ticketchng.tkt_id"
    "      AND tkt_uuid GLOB '%q*'"
    " GROUP BY tkt_uuid"
    " ORDER BY tkt_ctime DESC", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0); 
    const char *zUuid = db_column_text(&q, 1);
    const char *zTitle = db_column_text(&q, 2);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul></ul>
    @ Ticket
    hyperlink_to_uuid(zUuid);
    @ - %s(zTitle).
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>
  }
  db_finalize(&q);
  db_prepare(&q,
    "SELECT rid, uuid FROM"
    "  (SELECT tagxref.rid AS rid, substr(tagname, 7) AS uuid"
    "     FROM tagxref, tag WHERE tagxref.tagid = tag.tagid"
    "      AND tagname GLOB 'event-%q*') GROUP BY uuid", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0); 
    const char* zUuid = db_column_text(&q, 1);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>







|




















|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    "   SELECT tkt_rid, tkt_uuid, title"
    "     FROM ticket, ticketchng"
    "    WHERE ticket.tkt_id = ticketchng.tkt_id"
    "      AND tkt_uuid GLOB '%q*'"
    " GROUP BY tkt_uuid"
    " ORDER BY tkt_ctime DESC", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zTitle = db_column_text(&q, 2);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul></ul>
    @ Ticket
    hyperlink_to_uuid(zUuid);
    @ - %s(zTitle).
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>
  }
  db_finalize(&q);
  db_prepare(&q,
    "SELECT rid, uuid FROM"
    "  (SELECT tagxref.rid AS rid, substr(tagname, 7) AS uuid"
    "     FROM tagxref, tag WHERE tagxref.tagid = tag.tagid"
    "      AND tagname GLOB 'event-%q*') GROUP BY uuid", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char* zUuid = db_column_text(&q, 1);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
      case 't':  zType = "Ticket-change";  break;
      case 'g':  zType = "Tag-change";     break;
      default:   zType = "Unknown";        break;
    }
    fossil_print("type:       %s by %s on %s\n", zType, db_column_text(&q,2),
                 db_column_text(&q, 1));
    fossil_print("comment:    ");
    comment_print(db_column_text(&q,3), 12, 78);
  }
  db_finalize(&q);

  /* Check to see if this object is used as a file in a check-in */
  db_prepare(&q,
    "SELECT filename.name, blob.uuid, datetime(event.mtime%s),"
    "       coalesce(euser,user), coalesce(ecomment,comment)"
    "  FROM mlink, filename, blob, event"
    " WHERE mlink.fid=%d"
    "   AND filename.fnid=mlink.fnid"
    "   AND event.objid=mlink.mid"
    "   AND blob.rid=mlink.mid"
    " ORDER BY event.mtime DESC /*sort*/",
    timeline_utc(), rid);
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("file:       %s\n", db_column_text(&q,0));
    fossil_print("            part of [%.10s] by %s on %s\n",
      db_column_text(&q, 1),
      db_column_text(&q, 3),
      db_column_text(&q, 2));
    fossil_print("            ");
    comment_print(db_column_text(&q,4), 12, 78);
  }
  db_finalize(&q);

  /* Check to see if this object is used as an attachment */
  db_prepare(&q,
    "SELECT attachment.filename,"
    "       attachment.comment,"







|
















|




|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
      case 't':  zType = "Ticket-change";  break;
      case 'g':  zType = "Tag-change";     break;
      default:   zType = "Unknown";        break;
    }
    fossil_print("type:       %s by %s on %s\n", zType, db_column_text(&q,2),
                 db_column_text(&q, 1));
    fossil_print("comment:    ");
    comment_print(db_column_text(&q,3), 0, 12, -1, g.comFmtFlags);
  }
  db_finalize(&q);

  /* Check to see if this object is used as a file in a check-in */
  db_prepare(&q,
    "SELECT filename.name, blob.uuid, datetime(event.mtime%s),"
    "       coalesce(euser,user), coalesce(ecomment,comment)"
    "  FROM mlink, filename, blob, event"
    " WHERE mlink.fid=%d"
    "   AND filename.fnid=mlink.fnid"
    "   AND event.objid=mlink.mid"
    "   AND blob.rid=mlink.mid"
    " ORDER BY event.mtime DESC /*sort*/",
    timeline_utc(), rid);
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("file:       %s\n", db_column_text(&q,0));
    fossil_print("            part of [%S] by %s on %s\n",
      db_column_text(&q, 1),
      db_column_text(&q, 3),
      db_column_text(&q, 2));
    fossil_print("            ");
    comment_print(db_column_text(&q,4), 0, 12, -1, g.comFmtFlags);
  }
  db_finalize(&q);

  /* Check to see if this object is used as an attachment */
  db_prepare(&q,
    "SELECT attachment.filename,"
    "       attachment.comment,"
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660

661
662




663

664

665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681

682

683
684
685
686
687
688
689
    }else{
      fossil_print("            via %s\n",
                   db_column_text(&q,7));
    }
    fossil_print("            by user %s on %s\n",
                 db_column_text(&q,2), db_column_text(&q,3));
    fossil_print("            ");
    comment_print(db_column_text(&q,1), 12, 78);
  }
  db_finalize(&q);
}

/*
** COMMAND: whatis*
** Usage: %fossil whatis NAME
**
** Resolve the symbol NAME into its canonical 40-character SHA1-hash
** artifact name and provide a description of what role that artifact
** plays.
*/
void whatis_cmd(void){
  int rid;
  const char *zName;
  int verboseFlag;

  db_find_and_open_repository(0,0);
  verboseFlag = find_option("verbose","v",0)!=0;




  if( g.argc!=3 ) usage("whatis NAME");

  zName = g.argv[2];

  rid = symbolic_name_to_rid(zName, 0);
  if( rid<0 ){
    Stmt q;
    int cnt = 0;
    fossil_print("Ambiguous artifact name prefix: %s\n", zName);
    db_prepare(&q,
       "SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
       zName, zName
    );
    while( db_step(&q)==SQLITE_ROW ){
      if( cnt++ ) fossil_print("%.79c\n", '-');
      whatis_rid(db_column_int(&q, 0), verboseFlag);
    }
    db_finalize(&q);
  }else if( rid==0 ){

    fossil_print("Unknown artifact: %s\n", zName);
  }else{

    whatis_rid(rid, verboseFlag);

  }
}

/*
** COMMAND: test-whatis-all
** Usage: %fossil test-whatis-all
**







|
















>


>
>
>
>
|
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
>
|
>







637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
    }else{
      fossil_print("            via %s\n",
                   db_column_text(&q,7));
    }
    fossil_print("            by user %s on %s\n",
                 db_column_text(&q,2), db_column_text(&q,3));
    fossil_print("            ");
    comment_print(db_column_text(&q,1), 0, 12, -1, g.comFmtFlags);
  }
  db_finalize(&q);
}

/*
** COMMAND: whatis*
** Usage: %fossil whatis NAME
**
** Resolve the symbol NAME into its canonical 40-character SHA1-hash
** artifact name and provide a description of what role that artifact
** plays.
*/
void whatis_cmd(void){
  int rid;
  const char *zName;
  int verboseFlag;
  int i;
  db_find_and_open_repository(0,0);
  verboseFlag = find_option("verbose","v",0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc<3 ) usage("whatis NAME ...");
  for(i=2; i<g.argc; i++){
    zName = g.argv[i];
    if( i>2 ) fossil_print("%.79c\n",'-');
    rid = symbolic_name_to_rid(zName, 0);
    if( rid<0 ){
      Stmt q;
      int cnt = 0;
      fossil_print("name:       %s (ambiguous)\n", zName);
      db_prepare(&q,
         "SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
         zName, zName
      );
      while( db_step(&q)==SQLITE_ROW ){
        if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
        whatis_rid(db_column_int(&q, 0), verboseFlag);
      }
      db_finalize(&q);
    }else if( rid==0 ){
                 /* 0123456789 12 */
      fossil_print("unknown:    %s\n", zName);
    }else{
      fossil_print("name:       %s\n", zName);
      whatis_rid(rid, verboseFlag);
    }
  }
}

/*
** COMMAND: test-whatis-all
** Usage: %fossil test-whatis-all
**
Changes to src/printf.c.
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624







625
626
627
628
629
630
631
        break;
      }
      case etROOT: {
        bufpt = g.zTop ? g.zTop : "";
        length = (int)strlen(bufpt);
        break;
      }
      case etSTRINGID: {
        precision = 16;
        /* Fall through */
      }
      case etSTRING:
      case etDYNSTRING: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        bufpt = va_arg(ap,char*);
        if( bufpt==0 ){
          bufpt = "";
        }else if( xtype==etDYNSTRING ){
          zExtra = bufpt;







        }
        length = StrNLen32(bufpt, limit);
        if( precision>=0 && precision<length ) length = precision;
        break;
      }
      case etBLOB: {
        int limit = flag_alternateform ? va_arg(ap, int) : -1;







|
<
<
<








>
>
>
>
>
>
>







606
607
608
609
610
611
612
613



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
        break;
      }
      case etROOT: {
        bufpt = g.zTop ? g.zTop : "";
        length = (int)strlen(bufpt);
        break;
      }
      case etSTRINGID:



      case etSTRING:
      case etDYNSTRING: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        bufpt = va_arg(ap,char*);
        if( bufpt==0 ){
          bufpt = "";
        }else if( xtype==etDYNSTRING ){
          zExtra = bufpt;
        }else if( xtype==etSTRINGID ){
          precision = 0;
          while( bufpt[precision]>='0' && bufpt[precision]<='9' ){
            precision++;
          }
          if( bufpt[precision]!=0 ) precision++;
          if( precision<10 ) precision=10;
        }
        length = StrNLen32(bufpt, limit);
        if( precision>=0 && precision<length ) length = precision;
        break;
      }
      case etBLOB: {
        int limit = flag_alternateform ? va_arg(ap, int) : -1;
860
861
862
863
864
865
866
867
868




869
870
871
872
873
874
875
  fflush(toStdErr ? stderr : stdout);
}

/*
** Force the standard output cursor to move to the beginning
** of a line, if it is not there already.
*/
void fossil_force_newline(void){
  if( g.cgiOutput==0 && stdoutAtBOL==0 ) fossil_puts("\n", 0);




}

/*
** Indicate that the cursor has moved to the start of a line by means
** other than writing to standard output.
*/
void fossil_new_line_started(void){







|
|
>
>
>
>







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
  fflush(toStdErr ? stderr : stdout);
}

/*
** Force the standard output cursor to move to the beginning
** of a line, if it is not there already.
*/
int fossil_force_newline(void){
  if( g.cgiOutput==0 && stdoutAtBOL==0 ){
    fossil_puts("\n", 0);
    return 1;
  }
  return 0;
}

/*
** Indicate that the cursor has moved to the start of a line by means
** other than writing to standard output.
*/
void fossil_new_line_started(void){
Changes to src/rebuild.c.
576
577
578
579
580
581
582




583
584
585
586
587
588
589
    db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
    if( g.argc!=2 ){
      usage("?REPOSITORY-FILENAME?");
    }
    db_close(1);
    db_open_repository(g.zRepositoryName);
  }




  db_begin_transaction();
  ttyOutput = 1;
  errCnt = rebuild_db(randomizeFlag, 1, doClustering);
  reconstruct_private_table();
  db_multi_exec(
    "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());"
    "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());"







>
>
>
>







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
    if( g.argc!=2 ){
      usage("?REPOSITORY-FILENAME?");
    }
    db_close(1);
    db_open_repository(g.zRepositoryName);
  }
  
  /* We should be done with options.. */
  verify_all_options();

  db_begin_transaction();
  ttyOutput = 1;
  errCnt = rebuild_db(randomizeFlag, 1, doClustering);
  reconstruct_private_table();
  db_multi_exec(
    "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());"
    "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());"
791
792
793
794
795
796
797




798
799
800
801
802
803
804
  int bVerily = find_option("verily",0,0)!=0;
  int bForce = find_option("force", "f", 0)!=0;
  int privateOnly = find_option("private",0,0)!=0;
  int bNeedRebuild = 0;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
  db_close(1);
  db_open_repository(g.zRepositoryName);




  if( !bForce ){
    Blob ans;
    char cReply;
    prompt_user(
         "Scrubbing the repository will permanently delete information.\n"
         "Changes cannot be undone.  Continue (y/N)? ", &ans);
    cReply = blob_str(&ans)[0];







>
>
>
>







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  int bVerily = find_option("verily",0,0)!=0;
  int bForce = find_option("force", "f", 0)!=0;
  int privateOnly = find_option("private",0,0)!=0;
  int bNeedRebuild = 0;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
  db_close(1);
  db_open_repository(g.zRepositoryName);
    
  /* We should be done with options.. */
  verify_all_options();

  if( !bForce ){
    Blob ans;
    char cReply;
    prompt_user(
         "Scrubbing the repository will permanently delete information.\n"
         "Changes cannot be undone.  Continue (y/N)? ", &ans);
    cReply = blob_str(&ans)[0];
913
914
915
916
917
918
919




920
921
922
923
924
925
926
  }
  if( file_isdir(g.argv[3])!=1 ){
    fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
    usage("FILENAME DIRECTORY");
  }
  db_create_repository(g.argv[2]);
  db_open_repository(g.argv[2]);




  db_open_config(0);
  db_begin_transaction();
  db_initial_setup(0, 0, 0, 1);

  fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
  recon_read_dir(g.argv[3]);
  fossil_print("\nBuilding the Fossil repository...\n");







>
>
>
>







921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  }
  if( file_isdir(g.argv[3])!=1 ){
    fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
    usage("FILENAME DIRECTORY");
  }
  db_create_repository(g.argv[2]);
  db_open_repository(g.argv[2]);
  
  /* We should be done with options.. */
  verify_all_options();

  db_open_config(0);
  db_begin_transaction();
  db_initial_setup(0, 0, 0, 1);

  fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
  recon_read_dir(g.argv[3]);
  fossil_print("\nBuilding the Fossil repository...\n");
Changes to src/regexp.c.
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
**
**   -i|--ignore-case    Ignore case
*/
void re_test_grep(void){
  ReCompiled *pRe;
  const char *zErr;
  int ignoreCase = find_option("ignore-case","i",0)!=0;

  if( g.argc<3 ){
    usage("REGEXP [FILE...]");
  }
  zErr = re_compile(&pRe, g.argv[2], ignoreCase);
  if( zErr ) fossil_fatal("%s", zErr);
  if( g.argc==3 ){
    grep(pRe, "-", stdin);







<







766
767
768
769
770
771
772

773
774
775
776
777
778
779
**
**   -i|--ignore-case    Ignore case
*/
void re_test_grep(void){
  ReCompiled *pRe;
  const char *zErr;
  int ignoreCase = find_option("ignore-case","i",0)!=0;

  if( g.argc<3 ){
    usage("REGEXP [FILE...]");
  }
  zErr = re_compile(&pRe, g.argv[2], ignoreCase);
  if( zErr ) fossil_fatal("%s", zErr);
  if( g.argc==3 ){
    grep(pRe, "-", stdin);
Changes to src/report.c.
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

/*
** show all reports, which can be used for ticket show.
** Output is written to stdout as tab delimited table
*/
void rpt_list_reports(void){
  Stmt q;
  char const aRptOutFrmt[] = "%s\t%s\n";

  fossil_print("Available reports:\n");
  fossil_print(aRptOutFrmt,"report number","report title");
  fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
  db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zRn = db_column_text(&q, 0);







|







1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

/*
** show all reports, which can be used for ticket show.
** Output is written to stdout as tab delimited table
*/
void rpt_list_reports(void){
  Stmt q;
  const char aRptOutFrmt[] = "%s\t%s\n";

  fossil_print("Available reports:\n");
  fossil_print(aRptOutFrmt,"report number","report title");
  fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
  db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zRn = db_column_text(&q, 0);
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
  Stmt q;
  char *zSql;
  char *zErr1 = 0;
  char *zErr2 = 0;
  int count = 0;
  int rn;

  if (!zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
    zSql = "SELECT * FROM ticket";
  }else{
    rn = atoi(zRep);
    if( rn ){
      db_prepare(&q,
       "SELECT sqlcode FROM reportfmt WHERE rn=%d", rn);
    }else{







|







1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
  Stmt q;
  char *zSql;
  char *zErr1 = 0;
  char *zErr2 = 0;
  int count = 0;
  int rn;

  if( !zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
    zSql = "SELECT * FROM ticket";
  }else{
    rn = atoi(zRep);
    if( rn ){
      db_prepare(&q,
       "SELECT sqlcode FROM reportfmt WHERE rn=%d", rn);
    }else{
Changes to src/rss.c.
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
/*
** WEBPAGE: timeline.rss
** URL:  /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
**
** Produce an RSS feed of the timeline.
**
** TYPE may be: all, ci (show checkins only), t (show tickets only),
** w (show wiki only). LIMIT is the number of items to show.


**
** tkt=UUID filters for only those events for the specified ticket. tag=TAG
** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
**
** In addition, name=FILENAME filters for a specific file. This may be
** combined with one of the other filters (useful for looking at a specific
** branch).







|
>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
** WEBPAGE: timeline.rss
** URL:  /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
**
** Produce an RSS feed of the timeline.
**
** TYPE may be: all, ci (show checkins only), t (show tickets only),
** w (show wiki only).
**
** LIMIT is the number of items to show.
**
** tkt=UUID filters for only those events for the specified ticket. tag=TAG
** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
**
** In addition, name=FILENAME filters for a specific file. This may be
** combined with one of the other filters (useful for looking at a specific
** branch).
202
203
204
205
206
207
208


209
210
211
212
213
214
215



216
217
218
219
220
221
222
  if( zFreeProjectName != 0 ){
    free( zFreeProjectName );
  }
}

/*
** COMMAND: rss


**
** The CLI variant of the /timeline.rss page, this produces an RSS
** feed of the timeline to stdout. Options:
**
** -type|y FLAG
**    may be: all (default), ci (show checkins only), t (show tickets only),
**    w (show wiki only). LIMIT is the number of items to show.



**
** -tkt UUID
**    Filters for only those events for the specified ticket.
**
** -tag TAG
**    filters for a tag
**







>
>






|
>
>
>







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  if( zFreeProjectName != 0 ){
    free( zFreeProjectName );
  }
}

/*
** COMMAND: rss
**
** Usage: %fossil rss ?OPTIONS?
**
** The CLI variant of the /timeline.rss page, this produces an RSS
** feed of the timeline to stdout. Options:
**
** -type|y FLAG
**    may be: all (default), ci (show checkins only), t (show tickets only),
**    w (show wiki only).
**
** -limit|n LIMIT
**   The maximum number of items to show.
**
** -tkt UUID
**    Filters for only those events for the specified ticket.
**
** -tag TAG
**    filters for a tag
**
263
264
265
266
267
268
269



270
271
272
273
274
275
276
    zType = "all";
  }
  if(!zBaseURL || !*zBaseURL){
    zBaseURL = "URL-PLACEHOLDER";
  }

  db_find_and_open_repository(0, 0);




  blob_zero(&bSQL);
  blob_append( &bSQL, zSQL1, -1 );

  if( zType[0]!='a' ){
    blob_appendf(&bSQL, " AND event.type=%Q", zType);
  }







>
>
>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    zType = "all";
  }
  if(!zBaseURL || !*zBaseURL){
    zBaseURL = "URL-PLACEHOLDER";
  }

  db_find_and_open_repository(0, 0);

  /* We should be done with options.. */
    verify_all_options();

  blob_zero(&bSQL);
  blob_append( &bSQL, zSQL1, -1 );

  if( zType[0]!='a' ){
    blob_appendf(&bSQL, " AND event.type=%Q", zType);
  }
Changes to src/search.c.
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  int i;
  Blob sql = empty_blob;
  Stmt q;
  int iBest;
  char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
                                                     off the end of the
                                                     results. */
  char const * zLimit = find_option("limit","n",1);
  const char *zWidth = find_option("width","W",1);
  int nLimit = zLimit ? atoi(zLimit) : -1000;   /* Max number of matching
                                                   lines/entries to list */
  int width;
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = 79;
  }

  db_must_be_within_tree();
  if( g.argc<2 ) return;
  blob_init(&pattern, g.argv[2], -1);
  for(i=3; i<g.argc; i++){
    blob_appendf(&pattern, " %s", g.argv[i]);







|










|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  int i;
  Blob sql = empty_blob;
  Stmt q;
  int iBest;
  char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
                                                     off the end of the
                                                     results. */
  const char *zLimit = find_option("limit","n",1);
  const char *zWidth = find_option("width","W",1);
  int nLimit = zLimit ? atoi(zLimit) : -1000;   /* Max number of matching
                                                   lines/entries to list */
  int width;
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = -1;
  }

  db_must_be_within_tree();
  if( g.argc<2 ) return;
  blob_init(&pattern, g.argv[2], -1);
  for(i=3; i<g.argc; i++){
    blob_appendf(&pattern, " %s", g.argv[i]);
Changes to src/setup.c.
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  const char *zOldLogin;
  int doWrite;
  int uid, i;
  int higherUser = 0;  /* True if user being edited is SETUP and the */
                       /* user doing the editing is ADMIN.  Disallow editing */
  char *inherit[128];
  int a[128];
  char *oa[128];

  /* Must have ADMIN privileges to access this page
  */
  login_check_credentials();
  if( !g.perm.Admin ){ login_needed(); return; }

  /* Check to see if an ADMIN user is trying to edit a SETUP account.







|







305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  const char *zOldLogin;
  int doWrite;
  int uid, i;
  int higherUser = 0;  /* True if user being edited is SETUP and the */
                       /* user doing the editing is ADMIN.  Disallow editing */
  char *inherit[128];
  int a[128];
  const char *oa[128];

  /* Must have ADMIN privileges to access this page
  */
  login_check_credentials();
  if( !g.perm.Admin ){ login_needed(); return; }

  /* Check to see if an ADMIN user is trying to edit a SETUP account.
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493





































494
495
496
497
498
499
500
  /* figure out inherited permissions */
  memset(inherit, 0, sizeof(inherit));
  if( fossil_strcmp(zLogin, "developer") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
         "<span class=\"ueditInheritDeveloper\">&bull;</span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "reader") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
          "<span class=\"ueditInheritReader\">&bull;</span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "anonymous") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
           "<span class=\"ueditInheritAnonymous\">&bull;</span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "nobody") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
           "<span class=\"ueditInheritNobody\">&bull;</span>";
    }
    free(z2);
  }

  /* Begin generating the page
  */
  style_submenu_element("Cancel", "Cancel", "setup_ulist");
  if( uid ){
    style_header(mprintf("Edit User %h", zLogin));
  }else{
    style_header("Add A New User");
  }
  @ <div class="ueditCapBox">
  @ <form action="%s(g.zPath)" method="post"><div>
  login_insert_csrf_secret();
  if( login_is_special(zLogin) ){
    @ <input type="hidden" name="login" value="%s(zLogin)">
    @ <input type="hidden" name="info" value="">
    @ <input type="hidden" name="pw" value="*">
  }





































  @ <table>
  @ <tr>
  @   <td class="usetupEditLabel">User ID:</td>
  if( uid ){
    @   <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
  }else{
    @   <td>(new user)<input type="hidden" name="id" value="0" /></td>







|








|








|








|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  /* figure out inherited permissions */
  memset(inherit, 0, sizeof(inherit));
  if( fossil_strcmp(zLogin, "developer") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
         "<span class=\"ueditInheritDeveloper\"><sub>[D]</sub></span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "reader") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
          "<span class=\"ueditInheritReader\"><sub>[R]</sub></span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "anonymous") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
           "<span class=\"ueditInheritAnonymous\"><sub>[A]</sub></span>";
    }
    free(z2);
  }
  if( fossil_strcmp(zLogin, "nobody") ){
    char *z1, *z2;
    z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
    while( z1 && *z1 ){
      inherit[0x7f & *(z1++)] =
           "<span class=\"ueditInheritNobody\"><sub>[N]</sub></span>";
    }
    free(z2);
  }

  /* Begin generating the page
  */
  style_submenu_element("Cancel", "Cancel", "setup_ulist");
  if( uid ){
    style_header(mprintf("Edit User %h", zLogin));
  }else{
    style_header("Add A New User");
  }
  @ <div class="ueditCapBox">
  @ <form action="%s(g.zPath)" method="post"><div>
  login_insert_csrf_secret();
  if( login_is_special(zLogin) ){
    @ <input type="hidden" name="login" value="%s(zLogin)">
    @ <input type="hidden" name="info" value="">
    @ <input type="hidden" name="pw" value="*">
  }
  @ <script type='text/javascript'>
  @ function updateCapabilityString(){
  @   /*
  @   ** This function updates the "#usetupEditCapability" span content
  @   ** with the capabilities selected by the interactive user, based
  @   ** upon the state of the capability checkboxes.
  @   */
  @   try {
  @     var inputs = document.getElementsByTagName('input');
  @     if( inputs && inputs.length ){
  @       var output = document.getElementById('usetupEditCapability');
  @       if( output ){
  @         var permsIds = [], x = 0;
  @         for(var i = 0; i < inputs.length; i++){
  @           var e = inputs[i];
  @           if( !e.name || !e.type ) continue;
  @           if( e.type.toLowerCase()!=='checkbox' ) continue;
  @           if( e.name.length===2 && e.name[0]==='a' ){
  @             // looks like a capability checkbox
  @             if( e.checked ){
  @               // grab the second character of the element
  @               // name, which is the textual flag for this
  @               // capability, and then add it to the result
  @               // array.
  @               permsIds[x++] = e.name[1];
  @             }
  @           }
  @         }
  @         permsIds.sort();
  @         output.innerHTML = permsIds.join('');
  @       }
  @     }
  @   } catch (e) {
  @     /* ignore errors */
  @   }
  @ }
  @ </script>
  @ <table>
  @ <tr>
  @   <td class="usetupEditLabel">User ID:</td>
  if( uid ){
    @   <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
  }else{
    @   <td>(new user)<input type="hidden" name="id" value="0" /></td>
514
515
516
517
518
519
520
521

522
523
524

525
526

527
528

529
530

531
532

533
534

535
536

537
538

539
540
541

542
543

544
545

546
547




548
549
550
551
552
553

554
555

556
557
558

559
560

561
562

563
564

565
566

567
568

569
570

571
572

573
574







575
576
577
578
579
580
581
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]
  @ <table border=0><tr><td valign="top">
  if( g.perm.Setup ){
    @  <label><input type="checkbox" name="as"%s(oa['s']) />%s(B('s'))Setup

    @  </label><br />
  }
  @  <label><input type="checkbox" name="aa"%s(oa['a']) />%s(B('a'))Admin

  @  </label><br />
  @  <label><input type="checkbox" name="ad"%s(oa['d']) />%s(B('d'))Delete

  @  </label><br />
  @  <label><input type="checkbox" name="ae"%s(oa['e']) />%s(B('e'))Email

  @  </label><br />
  @  <label><input type="checkbox" name="ap"%s(oa['p']) />%s(B('p'))Password

  @  </label><br />
  @  <label><input type="checkbox" name="ai"%s(oa['i']) />%s(B('i'))Check-In

  @  </label><br />
  @  <label><input type="checkbox" name="ao"%s(oa['o']) />%s(B('o'))Check-Out

  @  </label><br />
  @  <label><input type="checkbox" name="ah"%s(oa['h']) />%s(B('h'))Hyperlinks

  @  </label><br />
  @  <label><input type="checkbox" name="ab"%s(oa['b']) />%s(B('b'))Attachments

  @  </label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="au"%s(oa['u']) />%s(B('u'))Reader

  @  </label><br />
  @  <label><input type="checkbox" name="av"%s(oa['v']) />%s(B('v'))Developer

  @  </label><br />
  @  <label><input type="checkbox" name="ag"%s(oa['g']) />%s(B('g'))Clone

  @  </label><br />
  @  <label><input type="checkbox" name="aj"%s(oa['j']) />%s(B('j'))Read Wiki




  @  </label><br />
  @  <label><input type="checkbox" name="af"%s(oa['f']) />%s(B('f'))New Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="am"%s(oa['m']) />%s(B('m'))Append Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="ak"%s(oa['k']) />%s(B('k'))Write Wiki

  @  </label><br />
  @  <label><input type="checkbox" name="al"%s(oa['l']) />%s(B('l'))Moderate

  @  Wiki</label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="ar"%s(oa['r']) />%s(B('r'))Read Ticket

  @  </label><br />
  @  <label><input type="checkbox" name="an"%s(oa['n']) />%s(B('n'))New Tickets

  @  </label><br />
  @  <label><input type="checkbox" name="ac"%s(oa['c']) />%s(B('c'))Append

  @  To Ticket </label><br />
  @  <label><input type="checkbox" name="aw"%s(oa['w']) />%s(B('w'))Write

  @  Tickets </label><br />
  @  <label><input type="checkbox" name="aq"%s(oa['q']) />%s(B('q'))Moderate

  @  Tickets </label><br />
  @  <label><input type="checkbox" name="at"%s(oa['t']) />%s(B('t'))Ticket

  @  Report </label><br />
  @  <label><input type="checkbox" name="ax"%s(oa['x']) />%s(B('x'))Private

  @  </label><br />
  @  <label><input type="checkbox" name="az"%s(oa['z']) />%s(B('z'))Download

  @  Zip </label>
  @ </td></tr></table>







  @   </td>
  @ </tr>
  if( !login_is_special(zLogin) ){
    @ <tr>
    @   <td align="right">Password:</td>
    if( zPw[0] ){
      /* Obscure the password for all users */







|
>
|

|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|

|
>
|
|
>
|
|
>
|
|
>
>
>
>
|
|
|
<
|
|
>
|
|
>
|

|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|
>
>
>
>
>
>
>







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]
  @ <table border=0><tr><td valign="top">
  if( g.perm.Setup ){
    @  <label><input type="checkbox" name="as"%s(oa['s'])
    @                onchange="updateCapabilityString()"/>
    @  Setup%s(B('s'))</label><br />
  }
  @  <label><input type="checkbox" name="aa"%s(oa['a'])
  @                onchange="updateCapabilityString()" />
  @  Admin%s(B('a'))</label><br />
  @  <label><input type="checkbox" name="ad"%s(oa['d'])
  @                onchange="updateCapabilityString()" />
  @  Delete%s(B('d'))</label><br />
  @  <label><input type="checkbox" name="ae"%s(oa['e'])
  @                onchange="updateCapabilityString()" />
  @  Email%s(B('e'))</label><br />
  @  <label><input type="checkbox" name="ap"%s(oa['p'])
  @                onchange="updateCapabilityString()" />
  @  Password%s(B('p'))</label><br />
  @  <label><input type="checkbox" name="ai"%s(oa['i'])
  @                onchange="updateCapabilityString()" />
  @  Check-In%s(B('i'))</label><br />
  @  <label><input type="checkbox" name="ao"%s(oa['o'])
  @                onchange="updateCapabilityString()" />
  @  Check-Out%s(B('o'))</label><br />
  @  <label><input type="checkbox" name="ah"%s(oa['h'])
  @                onchange="updateCapabilityString()" />
  @  Hyperlinks%s(B('h'))</label><br />
  @  <label><input type="checkbox" name="ab"%s(oa['b'])
  @                onchange="updateCapabilityString()" />
  @  Attachments%s(B('b'))</label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="au"%s(oa['u'])
  @                onchange="updateCapabilityString()" />
  @  Reader%s(B('u'))</label><br />
  @  <label><input type="checkbox" name="av"%s(oa['v'])
  @                onchange="updateCapabilityString()" />
  @  Developer%s(B('v'))</label><br />
  @  <label><input type="checkbox" name="ag"%s(oa['g'])
  @                onchange="updateCapabilityString()" />
  @  Clone%s(B('g'))</label><br />
  @  <label><input type="checkbox" name="aj"%s(oa['j'])
  @                onchange="updateCapabilityString()" />
  @  Read Wiki%s(B('j'))</label><br />
  @  <label><input type="checkbox" name="af"%s(oa['f'])
  @                onchange="updateCapabilityString()" />
  @  New Wiki%s(B('f'))</label><br />
  @  <label><input type="checkbox" name="am"%s(oa['m'])
  @                onchange="updateCapabilityString()" />

  @  Append Wiki%s(B('m'))</label><br />
  @  <label><input type="checkbox" name="ak"%s(oa['k'])
  @                onchange="updateCapabilityString()" />
  @  Write Wiki%s(B('k'))</label><br />
  @  <label><input type="checkbox" name="al"%s(oa['l'])
  @                onchange="updateCapabilityString()" />
  @  Moderate Wiki%s(B('l'))</label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="ar"%s(oa['r'])
  @                onchange="updateCapabilityString()" />
  @  Read Ticket%s(B('r'))</label><br />
  @  <label><input type="checkbox" name="an"%s(oa['n'])
  @                onchange="updateCapabilityString()" />
  @  New Tickets%s(B('n'))</label><br />
  @  <label><input type="checkbox" name="ac"%s(oa['c'])
  @                onchange="updateCapabilityString()" />
  @  Append To Ticket%s(B('c'))</label><br />
  @  <label><input type="checkbox" name="aw"%s(oa['w'])
  @                onchange="updateCapabilityString()" />
  @  Write Tickets%s(B('w'))</label><br />
  @  <label><input type="checkbox" name="aq"%s(oa['q'])
  @                onchange="updateCapabilityString()" />
  @  Moderate Tickets%s(B('q'))</label><br />
  @  <label><input type="checkbox" name="at"%s(oa['t'])
  @                onchange="updateCapabilityString()" />
  @  Ticket Report%s(B('t'))</label><br />
  @  <label><input type="checkbox" name="ax"%s(oa['x'])
  @                onchange="updateCapabilityString()" />
  @  Private%s(B('x'))</label><br />
  @  <label><input type="checkbox" name="az"%s(oa['z'])
  @                onchange="updateCapabilityString()" />
  @  Download Zip%s(B('z'))</label>
  @ </td></tr>
  @ </table>
  @   </td>
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Selected Cap.:</td>
  @   <td>
  @     <span id="usetupEditCapability">(missing JS?)</span>
  @   </td>
  @ </tr>
  if( !login_is_special(zLogin) ){
    @ <tr>
    @   <td align="right">Password:</td>
    if( zPw[0] ){
      /* Obscure the password for all users */
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
    @   <td>&nbsp;</td>
    @   <td><input type="submit" name="submit" value="Apply Changes" /></td>
    @ </tr>
  }
  @ </table>
  @ </div></form>
  @ </div>

  @ <h2>Privileges And Capabilities:</h2>
  @ <ul>
  if( higherUser ){
    @ <li><p class="missingPriv">
    @ User %h(zLogin) has Setup privileges and you only have Admin privileges
    @ so you are not permitted to make changes to %h(zLogin).
    @ </p></li>
    @
  }
  @ <li><p>
  @ The <span class="capability">Setup</span> user can make arbitrary
  @ configuration changes. An <span class="usertype">Admin</span> user
  @ can add other users and change user privileges
  @ and reset user passwords.  Both automatically get all other privileges
  @ listed below.  Use these two settings with discretion.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritNobody"><big>&bull;</big></span>" mark
  @ indicates the privileges of <span class="usertype">nobody</span> that
  @ are available to all users regardless of whether or not they are logged in.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritAnonymous"><big>&bull;</big></span>" mark
  @ indicates the privileges of <span class="usertype">anonymous</span> that
  @ are inherited by all logged-in users.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritDeveloper"><big>&bull;</big></span>" mark
  @ indicates the privileges of <span class="usertype">developer</span> that
  @ are inherited by all users with the
  @ <span class="capability">Developer</span> privilege.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritReader"><big>&bull;</big></span>" mark
  @ indicates the privileges of <span class="usertype">reader</span> that
  @ are inherited by all users with the <span class="capability">Reader</span>
  @ privilege.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Delete</span> privilege give the user the







>


















|





|





|






|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
    @   <td>&nbsp;</td>
    @   <td><input type="submit" name="submit" value="Apply Changes" /></td>
    @ </tr>
  }
  @ </table>
  @ </div></form>
  @ </div>
  @ <script type='text/javascript'>updateCapabilityString();</script>
  @ <h2>Privileges And Capabilities:</h2>
  @ <ul>
  if( higherUser ){
    @ <li><p class="missingPriv">
    @ User %h(zLogin) has Setup privileges and you only have Admin privileges
    @ so you are not permitted to make changes to %h(zLogin).
    @ </p></li>
    @
  }
  @ <li><p>
  @ The <span class="capability">Setup</span> user can make arbitrary
  @ configuration changes. An <span class="usertype">Admin</span> user
  @ can add other users and change user privileges
  @ and reset user passwords.  Both automatically get all other privileges
  @ listed below.  Use these two settings with discretion.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritNobody"><sub>N</sub></span>" subscript suffix
  @ indicates the privileges of <span class="usertype">nobody</span> that
  @ are available to all users regardless of whether or not they are logged in.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritAnonymous"><sub>A</sub></span>" subscript suffix
  @ indicates the privileges of <span class="usertype">anonymous</span> that
  @ are inherited by all logged-in users.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritDeveloper"><sub>D</sub></span>" subscript suffix
  @ indicates the privileges of <span class="usertype">developer</span> that
  @ are inherited by all users with the
  @ <span class="capability">Developer</span> privilege.
  @ </p></li>
  @
  @ <li><p>
  @ The "<span class="ueditInheritReader"><sub>R</sub></span>" subscript suffix
  @ indicates the privileges of <span class="usertype">reader</span> that
  @ are inherited by all users with the <span class="capability">Reader</span>
  @ privilege.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Delete</span> privilege give the user the
Changes to src/shell.c.
29
30
31
32
33
34
35



36
37
38
39
40
41
42
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"



#include <ctype.h>
#include <stdarg.h>

#if !defined(_WIN32) && !defined(WIN32)
# include <signal.h>
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>







>
>
>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
#if SQLITE_USER_AUTHENTICATION
# include "sqlite3userauth.h"
#endif
#include <ctype.h>
#include <stdarg.h>

#if !defined(_WIN32) && !defined(WIN32)
# include <signal.h>
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>
60
61
62
63
64
65
66

67
68
69
70
71
72
73
# define read_history(X)
# define write_history(X)
# define stifle_history(X)
#endif

#if defined(_WIN32) || defined(WIN32)
# include <io.h>

#define isatty(h) _isatty(h)
#ifndef access
# define access(f,m) _access((f),(m))
#endif
#undef popen
#define popen _popen
#undef pclose







>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# define read_history(X)
# define write_history(X)
# define stifle_history(X)
#endif

#if defined(_WIN32) || defined(WIN32)
# include <io.h>
# include <fcntl.h>
#define isatty(h) _isatty(h)
#ifndef access
# define access(f,m) _access((f),(m))
#endif
#undef popen
#define popen _popen
#undef pclose
427
428
429
430
431
432
433





434
435
436
437
438
439
440
441

442
443
444
445

446
447
448
449
450
451
452
453
454
455
456
457
458

459
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478







479
480
481
482
483
484
485
    fflush(stdout);
    zResult = local_getline(zPrior, stdin);
#endif
  }
  return zResult;
}






struct previous_mode_data {
  int valid;        /* Is there legit data in here? */
  int mode;
  int showHeader;
  int colWidth[100];
};

/*

** An pointer to an instance of this structure is passed from
** the main program to the callback.  This is used to communicate
** state and mode information.
*/

struct callback_data {
  sqlite3 *db;           /* The database */
  int echoOn;            /* True to echo input commands */
  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  int statsOn;           /* True to display memory stats before each finalize */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  FILE *traceOut;        /* Output for sqlite3_trace() */
  int nErr;              /* Number of errors seen */
  int mode;              /* An output mode setting */
  int writableSchema;    /* True if PRAGMA writable_schema=ON */
  int showHeader;        /* True to show column names in List or Column mode */

  char *zDestTable;      /* Name of destination table when MODE_Insert */
  char separator[20];    /* Separator character for MODE_List */

  int colWidth[100];     /* Requested width of each column when in column mode*/
  int actualWidth[100];  /* Actual width of each column */
  char nullvalue[20];    /* The text to print when a NULL comes back from
                         ** the database */
  struct previous_mode_data explainPrev;
                         /* Holds the mode information just before
                         ** .explain ON */
  char outfile[FILENAME_MAX]; /* Filename for *out */
  const char *zDbFilename;    /* name of the database file */
  char *zFreeOnClose;         /* Filename to free when closing */
  const char *zVfs;           /* Name of VFS to use */
  sqlite3_stmt *pStmt;   /* Current statement if any. */
  FILE *pLog;            /* Write log output here */
  int *aiIndent;         /* Array of indents used in MODE_Explain */
  int nIndent;           /* Size of array aiIndent[] */
  int iIndent;           /* Index of current op in aiIndent[] */
};








/*
** These are the allowed modes.
*/
#define MODE_Line     0  /* One column per line.  Blank line between records */
#define MODE_Column   1  /* One record per line in neat columns */
#define MODE_List     2  /* One record per line with a separator */
#define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */







>
>
>
>
>
|
|
|
|
|



>
|
<
<

>
|












>


>




<
|
<











>
>
>
>
>
>
>







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452


453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
    fflush(stdout);
    zResult = local_getline(zPrior, stdin);
#endif
  }
  return zResult;
}

/*
** Shell output mode information from before ".explain on", 
** saved so that it can be restored by ".explain off"
*/
typedef struct SavedModeInfo SavedModeInfo;
struct SavedModeInfo {
  int valid;          /* Is there legit data in here? */
  int mode;           /* Mode prior to ".explain on" */
  int showHeader;     /* The ".header" setting prior to ".explain on" */
  int colWidth[100];  /* Column widths prior to ".explain on" */
};

/*
** State information about the database connection is contained in an
** instance of the following structure.


*/
typedef struct ShellState ShellState;
struct ShellState {
  sqlite3 *db;           /* The database */
  int echoOn;            /* True to echo input commands */
  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  int statsOn;           /* True to display memory stats before each finalize */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  FILE *traceOut;        /* Output for sqlite3_trace() */
  int nErr;              /* Number of errors seen */
  int mode;              /* An output mode setting */
  int writableSchema;    /* True if PRAGMA writable_schema=ON */
  int showHeader;        /* True to show column names in List or Column mode */
  unsigned shellFlgs;    /* Various flags */
  char *zDestTable;      /* Name of destination table when MODE_Insert */
  char separator[20];    /* Separator character for MODE_List */
  char newline[20];      /* Record separator in MODE_Csv */
  int colWidth[100];     /* Requested width of each column when in column mode*/
  int actualWidth[100];  /* Actual width of each column */
  char nullvalue[20];    /* The text to print when a NULL comes back from
                         ** the database */

  SavedModeInfo normalMode;/* Holds the mode just before .explain ON */

  char outfile[FILENAME_MAX]; /* Filename for *out */
  const char *zDbFilename;    /* name of the database file */
  char *zFreeOnClose;         /* Filename to free when closing */
  const char *zVfs;           /* Name of VFS to use */
  sqlite3_stmt *pStmt;   /* Current statement if any. */
  FILE *pLog;            /* Write log output here */
  int *aiIndent;         /* Array of indents used in MODE_Explain */
  int nIndent;           /* Size of array aiIndent[] */
  int iIndent;           /* Index of current op in aiIndent[] */
};

/*
** These are the allowed shellFlgs values
*/
#define SHFLG_Scratch     0x00001     /* The --scratch option is used */
#define SHFLG_Pagecache   0x00002     /* The --pagecache option is used */
#define SHFLG_Lookaside   0x00004     /* Lookaside memory is used */

/*
** These are the allowed modes.
*/
#define MODE_Line     0  /* One column per line.  Blank line between records */
#define MODE_Column   1  /* One record per line in neat columns */
#define MODE_List     2  /* One record per line with a separator */
#define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  return 0x3fffffff & (int)(z2 - z);
}

/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  struct callback_data *p = (struct callback_data*)pArg;
  if( p->pLog==0 ) return;
  fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
  fflush(p->pLog);
}

/*
** Output the given string as a hex-encoded blob (eg. X'1234' )







|







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  return 0x3fffffff & (int)(z2 - z);
}

/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  ShellState *p = (ShellState*)pArg;
  if( p->pLog==0 ) return;
  fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
  fflush(p->pLog);
}

/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
};

/*
** Output a single term of CSV.  Actually, p->separator is used for
** the separator, which may or may not be a comma.  p->nullvalue is
** the null value.  Strings are quoted if necessary.

*/
static void output_csv(struct callback_data *p, const char *z, int bSep){
  FILE *out = p->out;
  if( z==0 ){
    fprintf(out,"%s",p->nullvalue);
  }else{
    int i;
    int nSep = strlen30(p->separator);
    for(i=0; z[i]; i++){







|
>

|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
};

/*
** Output a single term of CSV.  Actually, p->separator is used for
** the separator, which may or may not be a comma.  p->nullvalue is
** the null value.  Strings are quoted if necessary.  The separator
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
  FILE *out = p->out;
  if( z==0 ){
    fprintf(out,"%s",p->nullvalue);
  }else{
    int i;
    int nSep = strlen30(p->separator);
    for(i=0; z[i]; i++){
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
  int i;
  struct callback_data *p = (struct callback_data*)pArg;

  switch( p->mode ){
    case MODE_Line: {
      int w = 5;
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int len = strlen30(azCol[i] ? azCol[i] : "");







|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
  int i;
  ShellState *p = (ShellState*)pArg;

  switch( p->mode ){
    case MODE_Line: {
      int w = 5;
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int len = strlen30(azCol[i] ? azCol[i] : "");
851
852
853
854
855
856
857




858
859
860
861
862
863
864
865
866
867
868





869
870
871
872
873
874
875
        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
        if(i<nArg-1) fprintf(p->out, "%s", p->separator);
      }
      fprintf(p->out,"\n");
      break;
    }
    case MODE_Csv: {




      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
        }
        fprintf(p->out,"\n");
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        output_csv(p, azArg[i], i<nArg-1);
      }
      fprintf(p->out,"\n");





      break;
    }
    case MODE_Insert: {
      p->cnt++;
      if( azArg==0 ) break;
      fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
      for(i=0; i<nArg; i++){







>
>
>
>




|

|
|
|
|
|
>
>
>
>
>







868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
        if(i<nArg-1) fprintf(p->out, "%s", p->separator);
      }
      fprintf(p->out,"\n");
      break;
    }
    case MODE_Csv: {
#if defined(WIN32) || defined(_WIN32)
      fflush(p->out);
      _setmode(_fileno(p->out), _O_BINARY);
#endif
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
        }
        fprintf(p->out,"%s",p->newline);
      }
      if( azArg>0 ){
        for(i=0; i<nArg; i++){
          output_csv(p, azArg[i], i<nArg-1);
        }
        fprintf(p->out,"%s",p->newline);
      }
#if defined(WIN32) || defined(_WIN32)
      fflush(p->out);
      _setmode(_fileno(p->out), _O_TEXT);
#endif
      break;
    }
    case MODE_Insert: {
      p->cnt++;
      if( azArg==0 ) break;
      fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
      for(i=0; i<nArg; i++){
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
*/
static int callback(void *pArg, int nArg, char **azArg, char **azCol){
  /* since we don't have type info, call the shell_callback with a NULL value */
  return shell_callback(pArg, nArg, azArg, azCol, NULL);
}

/*
** Set the destination table field of the callback_data structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(struct callback_data *p, const char *zName){
  int i, n;
  int needQuote;
  char *z;

  if( p->zDestTable ){
    free(p->zDestTable);
    p->zDestTable = 0;







|



|







933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
*/
static int callback(void *pArg, int nArg, char **azArg, char **azCol){
  /* since we don't have type info, call the shell_callback with a NULL value */
  return shell_callback(pArg, nArg, azArg, azCol, NULL);
}

/*
** Set the destination table field of the ShellState structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(ShellState *p, const char *zName){
  int i, n;
  int needQuote;
  char *z;

  if( p->zDestTable ){
    free(p->zDestTable);
    p->zDestTable = 0;
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
**
** If the number of columns is 1 and that column contains text "--"
** then write the semicolon on a separate line.  That way, if a 
** "--" comment occurs at the end of the statement, the comment
** won't consume the semicolon terminator.
*/
static int run_table_dump_query(
  struct callback_data *p, /* Query context */
  const char *zSelect,     /* SELECT statement to extract content */
  const char *zFirstRow    /* Print before first row, if not NULL */
){
  sqlite3_stmt *pSelect;
  int rc;
  int nResult;
  int i;







|







1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
**
** If the number of columns is 1 and that column contains text "--"
** then write the semicolon on a separate line.  That way, if a 
** "--" comment occurs at the end of the statement, the comment
** won't consume the semicolon terminator.
*/
static int run_table_dump_query(
  ShellState *p,           /* Query context */
  const char *zSelect,     /* SELECT statement to extract content */
  const char *zFirstRow    /* Print before first row, if not NULL */
){
  sqlite3_stmt *pSelect;
  int rc;
  int nResult;
  int i;
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090

1091
1092
1093
1094
1095

1096
1097
1098
1099

1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
}

/*
** Display memory stats.
*/
static int display_stats(
  sqlite3 *db,                /* Database to query */
  struct callback_data *pArg, /* Pointer to struct callback_data */
  int bReset                  /* True to reset the stats */
){
  int iCur;
  int iHiwtr;

  if( pArg && pArg->out ){
    
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Memory Used:                         %d (max %d) bytes\n", iCur, iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Outstanding Allocations:   %d (max %d)\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.

**    iHiwtr = iCur = -1;
**    sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
**    fprintf(pArg->out, "Number of Pcache Pages Used:         %d (max %d) pages\n", iCur, iHiwtr);
*/

    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Pcache Overflow Bytes:     %d (max %d) bytes\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.

**    iHiwtr = iCur = -1;
**    sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
**    fprintf(pArg->out, "Number of Scratch Allocations Used:  %d (max %d)\n", iCur, iHiwtr);
*/

    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Scratch Overflow Bytes:    %d (max %d) bytes\n", iCur, iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Allocation:                  %d bytes\n", iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Pcache Allocation:           %d bytes\n", iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Scratch Allocation:          %d bytes\n", iHiwtr);
#ifdef YYTRACKMAXSTACKDEPTH
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Deepest Parser Stack:                %d (max %d)\n", iCur, iHiwtr);
#endif
  }

  if( pArg && pArg->out && db ){

    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Successful lookaside attempts:       %d\n", iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Lookaside failures due to size:      %d\n", iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Lookaside failures due to OOM:       %d\n", iHiwtr);

    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Pager Heap Usage:                    %d bytes\n", iCur);    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    fprintf(pArg->out, "Page cache hits:                     %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);







|













<
<
>
|
|
|
<
>



<
<
>
|
|
|
<
>




















>
|
|
|
|
|
|
|
|
|
>







1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110


1111
1112
1113
1114

1115
1116
1117
1118


1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
}

/*
** Display memory stats.
*/
static int display_stats(
  sqlite3 *db,                /* Database to query */
  ShellState *pArg,           /* Pointer to ShellState */
  int bReset                  /* True to reset the stats */
){
  int iCur;
  int iHiwtr;

  if( pArg && pArg->out ){
    
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Memory Used:                         %d (max %d) bytes\n", iCur, iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Outstanding Allocations:   %d (max %d)\n", iCur, iHiwtr);


    if( pArg->shellFlgs & SHFLG_Pagecache ){
      iHiwtr = iCur = -1;
      sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Number of Pcache Pages Used:         %d (max %d) pages\n", iCur, iHiwtr);

    }
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Pcache Overflow Bytes:     %d (max %d) bytes\n", iCur, iHiwtr);


    if( pArg->shellFlgs & SHFLG_Scratch ){
      iHiwtr = iCur = -1;
      sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Number of Scratch Allocations Used:  %d (max %d)\n", iCur, iHiwtr);

    }
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Number of Scratch Overflow Bytes:    %d (max %d) bytes\n", iCur, iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Allocation:                  %d bytes\n", iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Pcache Allocation:           %d bytes\n", iHiwtr);
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Largest Scratch Allocation:          %d bytes\n", iHiwtr);
#ifdef YYTRACKMAXSTACKDEPTH
    iHiwtr = iCur = -1;
    sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Deepest Parser Stack:                %d (max %d)\n", iCur, iHiwtr);
#endif
  }

  if( pArg && pArg->out && db ){
    if( pArg->shellFlgs & SHFLG_Lookaside ){
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Successful lookaside attempts:       %d\n", iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Lookaside failures due to size:      %d\n", iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset);
      fprintf(pArg->out, "Lookaside failures due to OOM:       %d\n", iHiwtr);
    }
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
    fprintf(pArg->out, "Pager Heap Usage:                    %d bytes\n", iCur);    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    fprintf(pArg->out, "Page cache hits:                     %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  if( pArg && pArg->out && db && pArg->pStmt ){
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
    fprintf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    fprintf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
    fprintf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
    if( sqlite3_libversion_number()>=3008000 ){
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
      fprintf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
    }
  }

  return 0;
}

/*
** Parameter azArray points to a zero-terminated array of strings. zStr







<
|
|
<







1174
1175
1176
1177
1178
1179
1180

1181
1182

1183
1184
1185
1186
1187
1188
1189
  if( pArg && pArg->out && db && pArg->pStmt ){
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
    fprintf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    fprintf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
    fprintf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);

    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    fprintf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);

  }

  return 0;
}

/*
** Parameter azArray points to a zero-terminated array of strings. zStr
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
    if( 0==strcmp(zStr, azArray[i]) ) return 1;
  }
  return 0;
}

/*
** If compiled statement pSql appears to be an EXPLAIN statement, allocate
** and populate the callback_data.aiIndent[] array with the number of
** spaces each opcode should be indented before it is output. 
**
** The indenting rules are:
**
**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
**       all opcodes that occur between the p2 jump destination and the opcode
**       itself by 2 spaces.
**
**     * For each "Goto", if the jump destination is earlier in the program
**       and ends on one of:
**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
**       or if the P1 parameter is one instead of zero,
**       then indent all opcodes between the earlier instruction
**       and "Goto" by 2 spaces.
*/
static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
  const char *zSql;               /* The text of the SQL statement */
  const char *z;                  /* Used to check if this is an EXPLAIN */
  int *abYield = 0;               /* True if op is an OP_Yield */
  int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
  int iOp;                        /* Index of operation in p->aiIndent[] */

  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",







|















|







1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
    if( 0==strcmp(zStr, azArray[i]) ) return 1;
  }
  return 0;
}

/*
** If compiled statement pSql appears to be an EXPLAIN statement, allocate
** and populate the ShellState.aiIndent[] array with the number of
** spaces each opcode should be indented before it is output. 
**
** The indenting rules are:
**
**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
**       all opcodes that occur between the p2 jump destination and the opcode
**       itself by 2 spaces.
**
**     * For each "Goto", if the jump destination is earlier in the program
**       and ends on one of:
**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
**       or if the P1 parameter is one instead of zero,
**       then indent all opcodes between the earlier instruction
**       and "Goto" by 2 spaces.
*/
static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
  const char *zSql;               /* The text of the SQL statement */
  const char *z;                  /* Used to check if this is an EXPLAIN */
  int *abYield = 0;               /* True if op is an OP_Yield */
  int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
  int iOp;                        /* Index of operation in p->aiIndent[] */

  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  sqlite3_free(abYield);
  sqlite3_reset(pSql);
}

/*
** Free the array allocated by explain_data_prepare().
*/
static void explain_data_delete(struct callback_data *p){
  sqlite3_free(p->aiIndent);
  p->aiIndent = 0;
  p->nIndent = 0;
  p->iIndent = 0;
}

/*
** Execute a statement or set of statements.  Print 
** any result rows/columns depending on the current mode 
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec() 
** function except it takes a slightly different callback 
** and callback data argument.
*/
static int shell_exec(
  sqlite3 *db,                                /* An open database */
  const char *zSql,                           /* SQL to be evaluated */
  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
                                              /* (not the same as sqlite3_exec) */
  struct callback_data *pArg,                 /* Pointer to struct callback_data */
  char **pzErrMsg                             /* Error msg written here */
){
  sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
  int rc = SQLITE_OK;             /* Return Code */
  int rc2;
  const char *zLeftover;          /* Tail of unprocessed SQL */

  if( pzErrMsg ){







|
















|
|

|
|
|







1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
  sqlite3_free(abYield);
  sqlite3_reset(pSql);
}

/*
** Free the array allocated by explain_data_prepare().
*/
static void explain_data_delete(ShellState *p){
  sqlite3_free(p->aiIndent);
  p->aiIndent = 0;
  p->nIndent = 0;
  p->iIndent = 0;
}

/*
** Execute a statement or set of statements.  Print 
** any result rows/columns depending on the current mode 
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec() 
** function except it takes a slightly different callback 
** and callback data argument.
*/
static int shell_exec(
  sqlite3 *db,                              /* An open database */
  const char *zSql,                         /* SQL to be evaluated */
  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
                                            /* (not the same as sqlite3_exec) */
  ShellState *pArg,                         /* Pointer to ShellState */
  char **pzErrMsg                           /* Error msg written here */
){
  sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
  int rc = SQLITE_OK;             /* Return Code */
  int rc2;
  const char *zLeftover;          /* Tail of unprocessed SQL */

  if( pzErrMsg ){
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
            fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
          }
        }
        sqlite3_finalize(pExplain);
        sqlite3_free(zEQP);
      }

      /* Output TESTCTRL_EXPLAIN text of requested */
      if( pArg && pArg->mode==MODE_Explain ){
        const char *zExplain = 0;
        sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
        if( zExplain && zExplain[0] ){
          fprintf(pArg->out, "%s", zExplain);
        }
      }

      /* If the shell is currently in ".explain" mode, gather the extra
      ** data required to add indents to the output.*/
      if( pArg && pArg->mode==MODE_Explain ){
        explain_data_prepare(pArg, pStmt);
      }

      /* perform the first step.  this will tell us if we







<
<
<
<
<
<
<
<
<







1349
1350
1351
1352
1353
1354
1355









1356
1357
1358
1359
1360
1361
1362
            fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
          }
        }
        sqlite3_finalize(pExplain);
        sqlite3_free(zEQP);
      }










      /* If the shell is currently in ".explain" mode, gather the extra
      ** data required to add indents to the output.*/
      if( pArg && pArg->mode==MODE_Explain ){
        explain_data_prepare(pArg, pStmt);
      }

      /* perform the first step.  this will tell us if we
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  int rc;
  const char *zTable;
  const char *zType;
  const char *zSql;
  const char *zPrepStmt = 0;
  struct callback_data *p = (struct callback_data *)pArg;

  UNUSED_PARAMETER(azCol);
  if( nArg!=3 ) return 1;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
  







|







1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  int rc;
  const char *zTable;
  const char *zType;
  const char *zSql;
  const char *zPrepStmt = 0;
  ShellState *p = (ShellState *)pArg;

  UNUSED_PARAMETER(azCol);
  if( nArg!=3 ) return 1;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
  
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
** Run zQuery.  Use dump_callback() as the callback routine so that
** the contents of the query are output as SQL statements.
**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
  struct callback_data *p, 
  const char *zQuery
){
  int rc;
  char *zErr = 0;
  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  if( rc==SQLITE_CORRUPT ){
    char *zQ2;







|







1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
** Run zQuery.  Use dump_callback() as the callback routine so that
** the contents of the query are output as SQL statements.
**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
  ShellState *p, 
  const char *zQuery
){
  int rc;
  char *zErr = 0;
  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  if( rc==SQLITE_CORRUPT ){
    char *zQ2;
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
  ".bail on|off           Stop after hitting an error.  Default OFF\n"
  ".clone NEWDB           Clone data into NEWDB from the existing database\n"
  ".databases             List names and files of attached databases\n"
  ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
  "                         If TABLE specified, only dump tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".echo on|off           Turn command echo on or off\n"

  ".exit                  Exit this program\n"
  ".explain ?on|off?      Turn output mode suitable for EXPLAIN on or off.\n"
  "                         With no args, it turns EXPLAIN on.\n"

  ".headers on|off        Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".import FILE TABLE     Import data from FILE into TABLE\n"
  ".indices ?TABLE?       Show names of all indices\n"
  "                         If TABLE specified, only show indices for tables\n"
  "                         matching LIKE pattern TABLE.\n"
#ifdef SQLITE_ENABLE_IOTRACE







>



>







1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
  ".bail on|off           Stop after hitting an error.  Default OFF\n"
  ".clone NEWDB           Clone data into NEWDB from the existing database\n"
  ".databases             List names and files of attached databases\n"
  ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
  "                         If TABLE specified, only dump tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".echo on|off           Turn command echo on or off\n"
  ".eqp on|off            Enable or disable automatic EXPLAIN QUERY PLAN\n"
  ".exit                  Exit this program\n"
  ".explain ?on|off?      Turn output mode suitable for EXPLAIN on or off.\n"
  "                         With no args, it turns EXPLAIN on.\n"
  ".fullschema            Show schema and the content of sqlite_stat tables\n"
  ".headers on|off        Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".import FILE TABLE     Import data from FILE into TABLE\n"
  ".indices ?TABLE?       Show names of all indices\n"
  "                         If TABLE specified, only show indices for tables\n"
  "                         matching LIKE pattern TABLE.\n"
#ifdef SQLITE_ENABLE_IOTRACE
1615
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639














1640
















1641






























1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662




1663
1664
1665
1666
1667
1668
1669
  ".quit                  Exit this program\n"
  ".read FILENAME         Execute SQL in FILENAME\n"
  ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"
  ".save FILE             Write in-memory database into FILE\n"
  ".schema ?TABLE?        Show the CREATE statements\n"
  "                         If TABLE specified, only show tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".separator STRING      Change separator used by output mode and .import\n"

  ".shell CMD ARGS...     Run CMD ARGS... in a system shell\n"
  ".show                  Show the current values for various settings\n"
  ".stats on|off          Turn stats on or off\n"
  ".system CMD ARGS...    Run CMD ARGS... in a system shell\n"
  ".tables ?TABLE?        List names of tables\n"
  "                         If TABLE specified, only list tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".timeout MS            Try opening locked tables for MS milliseconds\n"
  ".timer on|off          Turn SQL timer on or off\n"
  ".trace FILE|off        Output each SQL statement as it is run\n"
  ".vfsname ?AUX?         Print the name of the VFS stack\n"
  ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  "                         Negative values right-justify\n"
;

/* Forward reference */
static int process_input(struct callback_data *p, FILE *in);































/*






























** Make sure the database is open.  If it is not, then open it.  If
** the database fails to open, print an error message and exit.
*/
static void open_db(struct callback_data *p, int keepAlive){
  if( p->db==0 ){
    sqlite3_initialize();
    sqlite3_open(p->zDbFilename, &p->db);
    db = p->db;
    if( db && sqlite3_errcode(db)==SQLITE_OK ){
      sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
          shellstaticFunc, 0, 0);
    }
    if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
      fprintf(stderr,"Error: unable to open database \"%s\": %s\n", 
          p->zDbFilename, sqlite3_errmsg(db));
      if( keepAlive ) return;
      exit(1);
    }
#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif




  }
}

/*
** Do C-language style dequoting.
**
**    \t    -> tab







|
>
















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|

















>
>
>
>







1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
  ".quit                  Exit this program\n"
  ".read FILENAME         Execute SQL in FILENAME\n"
  ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"
  ".save FILE             Write in-memory database into FILE\n"
  ".schema ?TABLE?        Show the CREATE statements\n"
  "                         If TABLE specified, only show tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".separator STRING ?NL? Change separator used by output mode and .import\n"
  "                         NL is the end-of-line mark for CSV\n"
  ".shell CMD ARGS...     Run CMD ARGS... in a system shell\n"
  ".show                  Show the current values for various settings\n"
  ".stats on|off          Turn stats on or off\n"
  ".system CMD ARGS...    Run CMD ARGS... in a system shell\n"
  ".tables ?TABLE?        List names of tables\n"
  "                         If TABLE specified, only list tables matching\n"
  "                         LIKE pattern TABLE.\n"
  ".timeout MS            Try opening locked tables for MS milliseconds\n"
  ".timer on|off          Turn SQL timer on or off\n"
  ".trace FILE|off        Output each SQL statement as it is run\n"
  ".vfsname ?AUX?         Print the name of the VFS stack\n"
  ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  "                         Negative values right-justify\n"
;

/* Forward reference */
static int process_input(ShellState *p, FILE *in);
/*
** Implementation of the "readfile(X)" SQL function.  The entire content
** of the file named X is read and returned as a BLOB.  NULL is returned
** if the file does not exist or is unreadable.
*/
static void readfileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName;
  FILE *in;
  long nIn;
  void *pBuf;

  zName = (const char*)sqlite3_value_text(argv[0]);
  if( zName==0 ) return;
  in = fopen(zName, "rb");
  if( in==0 ) return;
  fseek(in, 0, SEEK_END);
  nIn = ftell(in);
  rewind(in);
  pBuf = sqlite3_malloc( nIn );
  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
    sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
  }else{
    sqlite3_free(pBuf);
  }
  fclose(in);
}

/*
** Implementation of the "writefile(X,Y)" SQL function.  The argument Y
** is written into file X.  The number of bytes written is returned.  Or
** NULL is returned if something goes wrong, such as being unable to open
** file X for writing.
*/
static void writefileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  FILE *out;
  const char *z;
  sqlite3_int64 rc;
  const char *zFile;

  zFile = (const char*)sqlite3_value_text(argv[0]);
  if( zFile==0 ) return;
  out = fopen(zFile, "wb");
  if( out==0 ) return;
  z = (const char*)sqlite3_value_blob(argv[1]);
  if( z==0 ){
    rc = 0;
  }else{
    rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
  }
  fclose(out);
  sqlite3_result_int64(context, rc);
}

/*
** Make sure the database is open.  If it is not, then open it.  If
** the database fails to open, print an error message and exit.
*/
static void open_db(ShellState *p, int keepAlive){
  if( p->db==0 ){
    sqlite3_initialize();
    sqlite3_open(p->zDbFilename, &p->db);
    db = p->db;
    if( db && sqlite3_errcode(db)==SQLITE_OK ){
      sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
          shellstaticFunc, 0, 0);
    }
    if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
      fprintf(stderr,"Error: unable to open database \"%s\": %s\n", 
          p->zDbFilename, sqlite3_errmsg(db));
      if( keepAlive ) return;
      exit(1);
    }
#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif
    sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
                            readfileFunc, 0, 0);
    sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
                            writefileFunc, 0, 0);
  }
}

/*
** Do C-language style dequoting.
**
**    \t    -> tab
1815
1816
1817
1818
1819
1820
1821
1822




1823
1824
1825
1826
1827
1828
1829
}

/*
** A routine for handling output from sqlite3_trace().
*/
static void sql_trace_callback(void *pArg, const char *z){
  FILE *f = (FILE*)pArg;
  if( f ) fprintf(f, "%s\n", z);




}

/*
** A no-op routine that runs with the ".breakpoint" doc-command.  This is
** a useful spot to set a debugger breakpoint.
*/
static void test_breakpoint(void){







|
>
>
>
>







1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
}

/*
** A routine for handling output from sqlite3_trace().
*/
static void sql_trace_callback(void *pArg, const char *z){
  FILE *f = (FILE*)pArg;
  if( f ){
    int i = (int)strlen(z);
    while( i>0 && z[i-1]==';' ){ i--; }
    fprintf(f, "%.*s;\n", i, z);
  }
}

/*
** A no-op routine that runs with the ".breakpoint" doc-command.  This is
** a useful spot to set a debugger breakpoint.
*/
static void test_breakpoint(void){
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

/*
** Try to transfer data for table zTable.  If an error is seen while
** moving forward, try to go backwards.  The backwards movement won't
** work for WITHOUT ROWID tables.
*/
static void tryToCloneData(
  struct callback_data *p,
  sqlite3 *newDb,
  const char *zTable
){
  sqlite3_stmt *pQuery = 0; 
  sqlite3_stmt *pInsert = 0;
  char *zQuery = 0;
  char *zInsert = 0;







|







2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033

/*
** Try to transfer data for table zTable.  If an error is seen while
** moving forward, try to go backwards.  The backwards movement won't
** work for WITHOUT ROWID tables.
*/
static void tryToCloneData(
  ShellState *p,
  sqlite3 *newDb,
  const char *zTable
){
  sqlite3_stmt *pQuery = 0; 
  sqlite3_stmt *pInsert = 0;
  char *zQuery = 0;
  char *zInsert = 0;
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
/*
** Try to transfer all rows of the schema that match zWhere.  For
** each row, invoke xForEach() on the object defined by that row.
** If an error is encountered while moving forward through the
** sqlite_master table, try again moving backwards.
*/
static void tryToCloneSchema(
  struct callback_data *p,
  sqlite3 *newDb,
  const char *zWhere,
  void (*xForEach)(struct callback_data*,sqlite3*,const char*)
){
  sqlite3_stmt *pQuery = 0;
  char *zQuery = 0;
  int rc;
  const unsigned char *zName;
  const unsigned char *zSql;
  char *zErrMsg = 0;







|


|







2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
/*
** Try to transfer all rows of the schema that match zWhere.  For
** each row, invoke xForEach() on the object defined by that row.
** If an error is encountered while moving forward through the
** sqlite_master table, try again moving backwards.
*/
static void tryToCloneSchema(
  ShellState *p,
  sqlite3 *newDb,
  const char *zWhere,
  void (*xForEach)(ShellState*,sqlite3*,const char*)
){
  sqlite3_stmt *pQuery = 0;
  char *zQuery = 0;
  int rc;
  const unsigned char *zName;
  const unsigned char *zSql;
  char *zErrMsg = 0;
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
}

/*
** Open a new database file named "zNewDb".  Try to recover as much information
** as possible out of the main database (which might be corrupt) and write it
** into zNewDb.
*/
static void tryToClone(struct callback_data *p, const char *zNewDb){
  int rc;
  sqlite3 *newDb = 0;
  if( access(zNewDb,0)==0 ){
    fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);







|







2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
}

/*
** Open a new database file named "zNewDb".  Try to recover as much information
** as possible out of the main database (which might be corrupt) and write it
** into zNewDb.
*/
static void tryToClone(ShellState *p, const char *zNewDb){
  int rc;
  sqlite3 *newDb = 0;
  if( access(zNewDb,0)==0 ){
    fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
  }
  sqlite3_close(newDb);
}

/*
** Change the output file back to stdout
*/
static void output_reset(struct callback_data *p){
  if( p->outfile[0]=='|' ){
    pclose(p->out);
  }else{
    output_file_close(p->out);
  }
  p->outfile[0] = 0;
  p->out = stdout;
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, struct callback_data *p){
  int i = 1;
  int nArg = 0;
  int n, c;
  int rc = 0;
  char *azArg[50];

  /* Parse the input line into tokens.







|















|







2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
  }
  sqlite3_close(newDb);
}

/*
** Change the output file back to stdout
*/
static void output_reset(ShellState *p){
  if( p->outfile[0]=='|' ){
    pclose(p->out);
  }else{
    output_file_close(p->out);
  }
  p->outfile[0] = 0;
  p->out = stdout;
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
  int i = 1;
  int nArg = 0;
  int n, c;
  int rc = 0;
  char *azArg[50];

  /* Parse the input line into tokens.
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
    }else{
      fprintf(stderr, "Usage: .clone FILENAME\n");
      rc = 1;
    }
  }else

  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 1;
    data.mode = MODE_Column;
    data.colWidth[0] = 3;
    data.colWidth[1] = 15;







|







2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
    }else{
      fprintf(stderr, "Usage: .clone FILENAME\n");
      rc = 1;
    }
  }else

  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 1;
    data.mode = MODE_Column;
    data.colWidth[0] = 3;
    data.colWidth[1] = 15;
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412



















































2413
2414
2415
2416
2417
2418
2419
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
    if(val == 1) {
      if(!p->explainPrev.valid) {
        p->explainPrev.valid = 1;
        p->explainPrev.mode = p->mode;
        p->explainPrev.showHeader = p->showHeader;
        memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
      }
      /* We could put this code under the !p->explainValid
      ** condition so that it does not execute if we are already in
      ** explain mode. However, always executing it allows us an easy
      ** was to reset to explain mode in case the user previously
      ** did an .explain followed by a .width, .mode or .header
      ** command.
      */
      p->mode = MODE_Explain;
      p->showHeader = 1;
      memset(p->colWidth,0,sizeof(p->colWidth));
      p->colWidth[0] = 4;                  /* addr */
      p->colWidth[1] = 13;                 /* opcode */
      p->colWidth[2] = 4;                  /* P1 */
      p->colWidth[3] = 4;                  /* P2 */
      p->colWidth[4] = 4;                  /* P3 */
      p->colWidth[5] = 13;                 /* P4 */
      p->colWidth[6] = 2;                  /* P5 */
      p->colWidth[7] = 13;                  /* Comment */
    }else if (p->explainPrev.valid) {
      p->explainPrev.valid = 0;
      p->mode = p->explainPrev.mode;
      p->showHeader = p->explainPrev.showHeader;
      memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));



















































    }
  }else

  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
    }else{







|
|
|
|
|



















|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
    if(val == 1) {
      if(!p->normalMode.valid) {
        p->normalMode.valid = 1;
        p->normalMode.mode = p->mode;
        p->normalMode.showHeader = p->showHeader;
        memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth));
      }
      /* We could put this code under the !p->explainValid
      ** condition so that it does not execute if we are already in
      ** explain mode. However, always executing it allows us an easy
      ** was to reset to explain mode in case the user previously
      ** did an .explain followed by a .width, .mode or .header
      ** command.
      */
      p->mode = MODE_Explain;
      p->showHeader = 1;
      memset(p->colWidth,0,sizeof(p->colWidth));
      p->colWidth[0] = 4;                  /* addr */
      p->colWidth[1] = 13;                 /* opcode */
      p->colWidth[2] = 4;                  /* P1 */
      p->colWidth[3] = 4;                  /* P2 */
      p->colWidth[4] = 4;                  /* P3 */
      p->colWidth[5] = 13;                 /* P4 */
      p->colWidth[6] = 2;                  /* P5 */
      p->colWidth[7] = 13;                  /* Comment */
    }else if (p->normalMode.valid) {
      p->normalMode.valid = 0;
      p->mode = p->normalMode.mode;
      p->showHeader = p->normalMode.showHeader;
      memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth));
    }
  }else

  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    int doStats = 0;
    if( nArg!=1 ){
      fprintf(stderr, "Usage: .fullschema\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_Semi;
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
       "     FROM sqlite_master UNION ALL"
       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
       "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
       "ORDER BY rowid",
       callback, &data, &zErrMsg
    );
    if( rc==SQLITE_OK ){
      sqlite3_stmt *pStmt;
      rc = sqlite3_prepare_v2(p->db,
               "SELECT rowid FROM sqlite_master"
               " WHERE name GLOB 'sqlite_stat[134]'",
               -1, &pStmt, 0);
      doStats = sqlite3_step(pStmt)==SQLITE_ROW;
      sqlite3_finalize(pStmt);
    }
    if( doStats==0 ){
      fprintf(p->out, "/* No STAT tables available */\n");
    }else{
      fprintf(p->out, "ANALYZE sqlite_master;\n");
      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
                   callback, &data, &zErrMsg);
      data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(p->db, "SELECT * FROM sqlite_stat1",
                 shell_callback, &data,&zErrMsg);
      data.zDestTable = "sqlite_stat3";
      shell_exec(p->db, "SELECT * FROM sqlite_stat3",
                 shell_callback, &data,&zErrMsg);
      data.zDestTable = "sqlite_stat4";
      shell_exec(p->db, "SELECT * FROM sqlite_stat4",
                 shell_callback, &data, &zErrMsg);
      fprintf(p->out, "ANALYZE sqlite_master;\n");
    }
  }else

  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
    }else{
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
        if( z==0 && i==0 ) break;
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){
          fprintf(stderr, "%s:%d: expected %d columns but found %d - "
                          "filling the rest with NULL\n",
                          sCsv.zFile, startLine, nCol, i+1);
          i++;
          while( i<nCol ){ sqlite3_bind_null(pStmt, i); i++; }
        }
      }
      if( sCsv.cTerm==sCsv.cSeparator ){
        do{
          csv_read_one_field(&sCsv);
          i++;
        }while( sCsv.cTerm==sCsv.cSeparator );







|







2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
        if( z==0 && i==0 ) break;
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){
          fprintf(stderr, "%s:%d: expected %d columns but found %d - "
                          "filling the rest with NULL\n",
                          sCsv.zFile, startLine, nCol, i+1);
          i++;
          while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
        }
      }
      if( sCsv.cTerm==sCsv.cSeparator ){
        do{
          csv_read_one_field(&sCsv);
          i++;
        }while( sCsv.cTerm==sCsv.cSeparator );
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
    xCloser(sCsv.in);
    sqlite3_free(sCsv.z);
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
  }else

  if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    if( nArg==1 ){
      rc = sqlite3_exec(p->db,







|







2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
    xCloser(sCsv.in);
    sqlite3_free(sCsv.z);
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
  }else

  if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    if( nArg==1 ){
      rc = sqlite3_exec(p->db,
2696
2697
2698
2699
2700
2701
2702

2703
2704
2705
2706
2707
2708
2709
      p->mode = MODE_Html;
    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
      p->mode = MODE_Tcl;
      sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
      p->mode = MODE_Csv;
      sqlite3_snprintf(sizeof(p->separator), p->separator, ",");

    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
      p->mode = MODE_Insert;
      set_table_name(p, nArg>=3 ? azArg[2] : "table");
    }else {







>







2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
      p->mode = MODE_Html;
    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
      p->mode = MODE_Tcl;
      sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
      p->mode = MODE_Csv;
      sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
      sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
      p->mode = MODE_Insert;
      set_table_name(p, nArg>=3 ? azArg[2] : "table");
    }else {
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
      fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }
    sqlite3_close(pSrc);
  }else

  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_Semi;
    if( nArg==2 ){
      int i;







|







3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
      fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }
    sqlite3_close(pSrc);
  }else

  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_Semi;
    if( nArg==2 ){
      int i;
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955









2956
2957
2958
2959
2960
2961
2962
      }
    }else if( nArg==1 ){
      rc = sqlite3_exec(p->db,
         "SELECT sql FROM "
         "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
         "     FROM sqlite_master UNION ALL"
         "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
         "ORDER BY rowid",
         callback, &data, &zErrMsg
      );
    }else{
      fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
      rc = 1;
      goto meta_command_exit;
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      fprintf(stderr,"Error: querying schema information\n");
      rc = 1;
    }else{
      rc = 0;
    }
  }else










#ifdef SQLITE_DEBUG
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;







|



















>
>
>
>
>
>
>
>
>







3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
      }
    }else if( nArg==1 ){
      rc = sqlite3_exec(p->db,
         "SELECT sql FROM "
         "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
         "     FROM sqlite_master UNION ALL"
         "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
         "ORDER BY rowid",
         callback, &data, &zErrMsg
      );
    }else{
      fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
      rc = 1;
      goto meta_command_exit;
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      fprintf(stderr,"Error: querying schema information\n");
      rc = 1;
    }else{
      rc = 0;
    }
  }else


#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
    extern int sqlite3SelectTrace;
    sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
  }else
#endif


#ifdef SQLITE_DEBUG
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987






2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006

3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027


3028
3029
3030
3031
3032
3033
3034
        fprintf(p->out, "%s", zBuf);
      }
    }
  }else
#endif

  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
    if( nArg==2 ){
      sqlite3_snprintf(sizeof(p->separator), p->separator,
                       "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
    }else{
      fprintf(stderr, "Usage: .separator STRING\n");
      rc = 1;
    }






  }else

  if( c=='s'
   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i;
    if( nArg<2 ){
      fprintf(stderr, "Usage: .system COMMAND\n");
      rc = 1;
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    (void)system(zCmd);
    sqlite3_free(zCmd);

  }else

  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
    int i;
    if( nArg!=1 ){
      fprintf(stderr, "Usage: .show\n");
      rc = 1;
      goto meta_command_exit;
    }
    fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
    fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
    fprintf(p->out,"%9.9s: ", "nullvalue");
      output_c_string(p->out, p->nullvalue);
      fprintf(p->out, "\n");
    fprintf(p->out,"%9.9s: %s\n","output",
            strlen30(p->outfile) ? p->outfile : "stdout");
    fprintf(p->out,"%9.9s: ", "separator");
      output_c_string(p->out, p->separator);


      fprintf(p->out, "\n");
    fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
    fprintf(p->out,"%9.9s: ","width");
    for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
      fprintf(p->out,"%d ",p->colWidth[i]);
    }
    fprintf(p->out,"\n");







|
<
<
<
|


>
>
>
>
>
>






|










|

>











|









>
>







3121
3122
3123
3124
3125
3126
3127
3128



3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
        fprintf(p->out, "%s", zBuf);
      }
    }
  }else
#endif

  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){



      fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
      rc = 1;
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
    }
    if( nArg>=3 ){
      sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
    }
  }else

  if( c=='s'
   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i, x;
    if( nArg<2 ){
      fprintf(stderr, "Usage: .system COMMAND\n");
      rc = 1;
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    x = system(zCmd);
    sqlite3_free(zCmd);
    if( x ) fprintf(stderr, "System command returns %d\n", x);
  }else

  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
    int i;
    if( nArg!=1 ){
      fprintf(stderr, "Usage: .show\n");
      rc = 1;
      goto meta_command_exit;
    }
    fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off");
    fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
    fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
    fprintf(p->out,"%9.9s: ", "nullvalue");
      output_c_string(p->out, p->nullvalue);
      fprintf(p->out, "\n");
    fprintf(p->out,"%9.9s: %s\n","output",
            strlen30(p->outfile) ? p->outfile : "stdout");
    fprintf(p->out,"%9.9s: ", "separator");
      output_c_string(p->out, p->separator);
      fprintf(p->out," ");
      output_c_string(p->out, p->newline);
      fprintf(p->out, "\n");
    fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
    fprintf(p->out,"%9.9s: ","width");
    for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
      fprintf(p->out,"%d ",p->colWidth[i]);
    }
    fprintf(p->out,"\n");
3281
3282
3283
3284
3285
3286
3287

































































3288
3289
3290
3291
3292
3293
3294
      sqlite3_trace(p->db, 0, 0);
    }else{
      sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
    }
#endif
  }else


































































  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
    fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
  }else

  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
      sqlite3_trace(p->db, 0, 0);
    }else{
      sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
    }
#endif
  }else

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){
      fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        fprintf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                    (int)strlen(azArg[3]));
      if( rc ){
        fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_add(p->db, azArg[2],
                            azArg[3], (int)strlen(azArg[3]),
                            booleanValue(azArg[4]));
      if( rc ){
        fprintf(stderr, "User-Add failed: %d\n", rc);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"edit")==0 ){
      if( nArg!=5 ){
        fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_change(p->db, azArg[2],
                              azArg[3], (int)strlen(azArg[3]),
                              booleanValue(azArg[4]));
      if( rc ){
        fprintf(stderr, "User-Edit failed: %d\n", rc);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"delete")==0 ){
      if( nArg!=3 ){
        fprintf(stderr, "Usage: .user delete USER\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_delete(p->db, azArg[2]);
      if( rc ){
        fprintf(stderr, "User-Delete failed: %d\n", rc);
        rc = 1;
      }
    }else{
      fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
      rc = 1;
      goto meta_command_exit;
    }    
  }else
#endif /* SQLITE_USER_AUTHENTICATION */

  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
    fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
  }else

  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
** is interactive - the user is typing it it.  Otherwise, input
** is coming from a file or device.  A prompt is issued and history
** is saved only if input is interactive.  An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
**
** Return the number of errors.
*/
static int process_input(struct callback_data *p, FILE *in){
  char *zLine = 0;          /* A single input line */
  char *zSql = 0;           /* Accumulated SQL text */
  int nLine;                /* Length of current line */
  int nSql = 0;             /* Bytes of zSql[] used */
  int nAlloc = 0;           /* Allocated zSql[] space */
  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  char *zErrMsg;            /* Error message returned */







|







3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
** is interactive - the user is typing it it.  Otherwise, input
** is coming from a file or device.  A prompt is issued and history
** is saved only if input is interactive.  An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
**
** Return the number of errors.
*/
static int process_input(ShellState *p, FILE *in){
  char *zLine = 0;          /* A single input line */
  char *zSql = 0;           /* Accumulated SQL text */
  int nLine;                /* Length of current line */
  int nSql = 0;             /* Bytes of zSql[] used */
  int nAlloc = 0;           /* Allocated zSql[] space */
  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  char *zErrMsg;            /* Error message returned */
3503
3504
3505
3506
3507
3508
3509

3510
3511
3512
3513
3514
3515
3516
      if( p->echoOn ) printf("%s\n", zSql);
      nSql = 0;
    }
  }
  if( nSql ){
    if( !_all_whitespace(zSql) ){
      fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);

    }
    free(zSql);
  }
  free(zLine);
  return errCnt>0;
}








>







3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
      if( p->echoOn ) printf("%s\n", zSql);
      nSql = 0;
    }
  }
  if( nSql ){
    if( !_all_whitespace(zSql) ){
      fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
      errCnt++;
    }
    free(zSql);
  }
  free(zLine);
  return errCnt>0;
}

3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
/*
** Read input from the file given by sqliterc_override.  Or if that
** parameter is NULL, take input from ~/.sqliterc
**
** Returns the number of errors.
*/
static int process_sqliterc(
  struct callback_data *p,        /* Configuration data */
  const char *sqliterc_override   /* Name of config file. NULL to use default */
){
  char *home_dir = NULL;
  const char *sqliterc = sqliterc_override;
  char *zBuf = 0;
  FILE *in = NULL;
  int rc = 0;







|







3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
/*
** Read input from the file given by sqliterc_override.  Or if that
** parameter is NULL, take input from ~/.sqliterc
**
** Returns the number of errors.
*/
static int process_sqliterc(
  ShellState *p,                  /* Configuration data */
  const char *sqliterc_override   /* Name of config file. NULL to use default */
){
  char *home_dir = NULL;
  const char *sqliterc = sqliterc_override;
  char *zBuf = 0;
  FILE *in = NULL;
  int rc = 0;
3633
3634
3635
3636
3637
3638
3639

3640
3641
3642
3643

3644


3645
3646
3647
3648
3649
3650
3651
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"

  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif

  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"


  "   -separator SEP       set output field separator. Default: '|'\n"
  "   -stats               print memory stats before each finalize\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif







>




>

>
>







3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"
  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -newline SEP         set newline character(s) for CSV\n"
  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  "   -scratch SIZE N      use N slots of SZ bytes each for scratch memory\n"
  "   -separator SEP       set output field separator. Default: '|'\n"
  "   -stats               print memory stats before each finalize\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672

3673

3674
3675



3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
  }
  exit(1);
}

/*
** Initialize the state information in data
*/
static void main_init(struct callback_data *data) {
  memset(data, 0, sizeof(*data));
  data->mode = MODE_List;
  memcpy(data->separator,"|", 2);

  data->showHeader = 0;

  sqlite3_config(SQLITE_CONFIG_URI, 1);
  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);



  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
}

/*
** Output text to the console in a font that attracts extra attention.
*/
#ifdef _WIN32
static void printBold(const char *zText){







|



>

>


>
>
>


<







3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905

3906
3907
3908
3909
3910
3911
3912
  }
  exit(1);
}

/*
** Initialize the state information in data
*/
static void main_init(ShellState *data) {
  memset(data, 0, sizeof(*data));
  data->mode = MODE_List;
  memcpy(data->separator,"|", 2);
  memcpy(data->newline,"\r\n", 3);
  data->showHeader = 0;
  data->shellFlgs = SHFLG_Lookaside;
  sqlite3_config(SQLITE_CONFIG_URI, 1);
  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(32); /* SQLITE_CONFIG_EXPLAIN_COMMENTS (old) */
  sqlite3_config(64); /* SQLITE_CONFIG_EXPLAIN_COMMENTS */
  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");

}

/*
** Output text to the console in a font that attracts extra attention.
*/
#ifdef _WIN32
static void printBold(const char *zText){
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
    exit(1);
  }
  return argv[i];
}

int main(int argc, char **argv){
  char *zErrMsg = 0;
  struct callback_data data;
  const char *zInitFile = 0;
  char *zFirstCmd = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;

#if USE_SYSTEM_SQLITE+0!=1







|







3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
    exit(1);
  }
  return argv[i];
}

int main(int argc, char **argv){
  char *zErrMsg = 0;
  ShellState data;
  const char *zInitFile = 0;
  char *zFirstCmd = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;

#if USE_SYSTEM_SQLITE+0!=1
3758
3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770
3771
      fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
      fprintf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
    if( z[1]=='-' ) z++;
    if( strcmp(z,"-separator")==0
     || strcmp(z,"-nullvalue")==0

     || strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing







>







3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
      fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
      fprintf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
    if( z[1]=='-' ) z++;
    if( strcmp(z,"-separator")==0
     || strcmp(z,"-nullvalue")==0
     || strcmp(z,"-newline")==0
     || strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing
3779
3780
3781
3782
3783
3784
3785



























3786
3787
3788
3789
3790
3791
3792
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif



























#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
         int (*xOut)(const char*,void*),
         void *pOutArg,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
    }else if( strcmp(z,"-scratch")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>400000 ) sz = 400000;
      if( sz<2500 ) sz = 2500;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( n>10 ) n = 10;
      if( n<1 ) n = 1;
      sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
      data.shellFlgs |= SHFLG_Scratch;
    }else if( strcmp(z,"-pagecache")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>70000 ) sz = 70000;
      if( sz<800 ) sz = 800;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( n<10 ) n = 10;
      sqlite3_config(SQLITE_CONFIG_PAGECACHE, malloc(n*sz+1), sz, n);
      data.shellFlgs |= SHFLG_Pagecache;
    }else if( strcmp(z,"-lookaside")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( sz<0 ) sz = 0;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( n<0 ) n = 0;
      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
      if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
         int (*xOut)(const char*,void*),
         void *pOutArg,
3867
3868
3869
3870
3871
3872
3873



3874
3875
3876
3877
3878
3879
3880
      data.mode = MODE_Column;
    }else if( strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.separator,",",2);
    }else if( strcmp(z,"-separator")==0 ){
      sqlite3_snprintf(sizeof(data.separator), data.separator,
                       "%s",cmdline_option_value(argc,argv,++i));



    }else if( strcmp(z,"-nullvalue")==0 ){
      sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-header")==0 ){
      data.showHeader = 1;
    }else if( strcmp(z,"-noheader")==0 ){
      data.showHeader = 0;







>
>
>







4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
      data.mode = MODE_Column;
    }else if( strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.separator,",",2);
    }else if( strcmp(z,"-separator")==0 ){
      sqlite3_snprintf(sizeof(data.separator), data.separator,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-newline")==0 ){
      sqlite3_snprintf(sizeof(data.newline), data.newline,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-nullvalue")==0 ){
      sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-header")==0 ){
      data.showHeader = 1;
    }else if( strcmp(z,"-noheader")==0 ){
      data.showHeader = 0;
3891
3892
3893
3894
3895
3896
3897






3898
3899
3900
3901
3902
3903
3904
      return 0;
    }else if( strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
    }else if( strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
      i++;






    }else if( strcmp(z,"-mmap")==0 ){
      i++;
    }else if( strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;







>
>
>
>
>
>







4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
      return 0;
    }else if( strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
    }else if( strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
      i++;
    }else if( strcmp(z,"-scratch")==0 ){
      i+=2;
    }else if( strcmp(z,"-pagecache")==0 ){
      i+=2;
    }else if( strcmp(z,"-lookaside")==0 ){
      i+=2;
    }else if( strcmp(z,"-mmap")==0 ){
      i++;
    }else if( strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;
Changes to src/shun.c.
38
39
40
41
42
43
44




45

46
47
48
49
50
51
52
53
54
55
56
57
58
59



















60
61


62

63
64
65
66
67
68


69
70


71

72
73





74

75

76
77
78



79
80
81
82
83
84
85

86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106













107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132












133
134
135
136
137
138
139
140
141
142
143
144
145
146
147



148









149
150
151
152
153
154
155
/*
** WEBPAGE: shun
*/
void shun_page(void){
  Stmt q;
  int cnt = 0;
  const char *zUuid = P("uuid");




  int nUuid;

  char zCanonical[UUID_SIZE+1];

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
  }
  if( P("rebuild") ){
    db_close(1);
    db_open_repository(g.zRepositoryName);
    db_begin_transaction();
    rebuild_db(0, 0, 0);
    db_end_transaction(0);
  }
  if( zUuid ){



















    nUuid = strlen(zUuid);
    if( nUuid!=40 || !validate16(zUuid, nUuid) ){


      zUuid = 0;

    }else{
      memcpy(zCanonical, zUuid, UUID_SIZE+1);
      canonical16(zCanonical, UUID_SIZE);
      zUuid = zCanonical;
    }
  }


  style_header("Shunned Artifacts");
  if( zUuid && P("sub") ){


    login_verify_csrf_secret();

    db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid);
    if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){





      @ <p class="noMoreShun">Artifact

      @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> is no

      @ longer being shunned.</p>
    }else{
      @ <p class="noMoreShun">Artifact %s(zUuid) will no longer



      @ be shunned.  But it does not exist in the repository.  It
      @ may be necessary to rebuild the repository using the
      @ <b>fossil rebuild</b> command-line before the artifact content
      @ can pulled in from other repositories.</p>
    }
  }
  if( zUuid && P("add") ){

    int rid, tagid;
    login_verify_csrf_secret();

    db_multi_exec(
      "INSERT OR IGNORE INTO shun(uuid,mtime)"
      " VALUES('%s', now())", zUuid);
    @ <p class="shunned">Artifact
    @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> has been
    @ shunned.  It will no longer be pushed.
    @ It will be removed from the repository the next time the repository
    @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
    db_multi_exec("DELETE FROM attachment WHERE src=%Q", zUuid);
    rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
    if( rid ){
      db_multi_exec("DELETE FROM event WHERE objid=%d", rid);
    }
    tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", zUuid);
    if( tagid ){
      db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", zUuid);
      db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
      db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
    }













  }
  @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
  @ artifact content will be purged from the repository the next time the
  @ repository is rebuilt.  A list of shunned artifacts can be seen at the
  @ bottom of this page.</p>
  @
  @ <a name="addshun"></a>
  @ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1
  @ hash of the artifact) in the
  @ following box and press the "Shun" button.  This will cause the artifact
  @ to be removed from the repository and will prevent the artifact from being
  @ readded to the repository by subsequent sync operation.</p>
  @
  @ <p>Note that you must enter the full 40-character artifact ID, not
  @ an abbreviation or a symbolic tag.</p>
  @
  @ <p>Warning:  Shunning should only be used to remove inappropriate content
  @ from the repository.  Inappropriate content includes such things as
  @ spam added to Wiki, files that violate copyright or patent agreements,
  @ or artifacts that by design or accident interfere with the processing
  @ of the repository.  Do not shun artifacts merely to remove them from
  @ sight - set the "hidden" tag on such artifacts instead.</p>
  @
  @ <blockquote>
  @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
  login_insert_csrf_secret();












  @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
  @ <input type="submit" name="add" value="Shun" />
  @ </div></form>
  @ </blockquote>
  @
  @ <a name="delshun"></a>
  @ <p>Enter the UUID of a previous shunned artifact to cause it to be
  @ accepted again in the repository.  The artifact content is not
  @ restored because the content is unknown.  The only change is that
  @ the formerly shunned artifact will be accepted on subsequent sync
  @ operations.</p>
  @
  @ <blockquote>
  @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
  login_insert_csrf_secret();



  @ <input type="text" name="uuid" value="%h(PD("accept", ""))" size="50" />









  @ <input type="submit" name="sub" value="Accept" />
  @ </div></form>
  @ </blockquote>
  @
  @ <p>Press the Rebuild button below to rebuild the repository.  The
  @ content of newly shunned artifacts is not purged until the repository
  @ is rebuilt.  On larger repositories, the rebuild may take minute or







>
>
>
>

>
|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
|
|
|
<
|
|
>
>


>
>

>
|
|
>
>
>
>
>
|
>
|
>
|

|
>
>
>
|
|





>


>
|
|
|
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>







|
|
|
|


|












>
>
>
>
>
>
>
>
>
>
>
>
|





|
|

|





>
>
>
|
>
>
>
>
>
>
>
>
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133





134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/*
** WEBPAGE: shun
*/
void shun_page(void){
  Stmt q;
  int cnt = 0;
  const char *zUuid = P("uuid");
  const char *zShun = P("shun");
  const char *zAccept = P("accept");
  const char *zRcvid = P("rcvid");
  int nRcvid;
  int nUuid;
  int numRows = 3;
  char *zCanonical = 0;

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
  }
  if( P("rebuild") ){
    db_close(1);
    db_open_repository(g.zRepositoryName);
    db_begin_transaction();
    rebuild_db(0, 0, 0);
    db_end_transaction(0);
  }
  if( zUuid ){
    char *p;
    int i = 0;
    int j = 0;
    zCanonical = fossil_malloc(strlen(zUuid)+2);
    while( zUuid[i] ){
      if( fossil_isspace(zUuid[i]) ){
        if( j && zCanonical[j-1] ){
          zCanonical[j] = 0;
          j++;
        }
      }else{
        zCanonical[j] = zUuid[i];
        j++;
      }
      i++;
    }
    zCanonical[j+1] = zCanonical[j] = 0;
    p = zCanonical;
    while( *p ){
      nUuid = strlen(p);
      if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){
        @ <p class="generalError">Error: Bad artifact IDs.</p>
        fossil_free(zCanonical);
        zCanonical = 0;
        break;
      }else{
        canonical16(p, UUID_SIZE);
        p += UUID_SIZE+1;

      }
    }
    zUuid = zCanonical;
  }
  style_header("Shunned Artifacts");
  if( zUuid && P("sub") ){
    const char *p = zUuid;
    int allExist = 1;
    login_verify_csrf_secret();
    while( *p ){
      db_multi_exec("DELETE FROM shun WHERE uuid='%s'", p);
      if( !db_exists("SELECT 1 FROM blob WHERE uuid='%s'", p) ){
        allExist = 0;
      }
      p += UUID_SIZE+1;
    }
    if( allExist ){
      @ <p class="noMoreShun">Artifact(s)<br />
      for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
        @ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
      }
      @ are no longer being shunned.</p>
    }else{
      @ <p class="noMoreShun">Artifact(s)<br />
      for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
        @ %s(p)<br />
      }
      @ will no longer be shunned.  But they may not exist in the repository.
      @ It may be necessary to rebuild the repository using the
      @ <b>fossil rebuild</b> command-line before the artifact content
      @ can pulled in from other repositories.</p>
    }
  }
  if( zUuid && P("add") ){
    const char *p = zUuid;
    int rid, tagid;
    login_verify_csrf_secret();
    while( *p ){
      db_multi_exec(
        "INSERT OR IGNORE INTO shun(uuid,mtime)"
        " VALUES('%s', now())", p);





      db_multi_exec("DELETE FROM attachment WHERE src=%Q", p);
      rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", p);
      if( rid ){
        db_multi_exec("DELETE FROM event WHERE objid=%d", rid);
      }
      tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", p);
      if( tagid ){
        db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
        db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
        db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
      }
      p += UUID_SIZE+1;
    }
    @ <p class="shunned">Artifact(s)<br />
    for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
      @ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
    }
    @ have been shunned.  They will no longer be pushed.
    @ They will be removed from the repository the next time the repository
    @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
  }
  if( zRcvid ){
    nRcvid = atoi(zRcvid);
    numRows = db_int(0, "SELECT min(count(), 10) FROM blob WHERE rcvid=%d", nRcvid);
  }
  @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
  @ artifact content will be purged from the repository the next time the
  @ repository is rebuilt.  A list of shunned artifacts can be seen at the
  @ bottom of this page.</p>
  @
  @ <a name="addshun"></a>
  @ <p>To shun artifacts, enter their artifact IDs (the 40-character SHA1
  @ hash of the artifacts) in the
  @ following box and press the "Shun" button.  This will cause the artifacts
  @ to be removed from the repository and will prevent the artifacts from being
  @ readded to the repository by subsequent sync operation.</p>
  @
  @ <p>Note that you must enter the full 40-character artifact IDs, not
  @ an abbreviation or a symbolic tag.</p>
  @
  @ <p>Warning:  Shunning should only be used to remove inappropriate content
  @ from the repository.  Inappropriate content includes such things as
  @ spam added to Wiki, files that violate copyright or patent agreements,
  @ or artifacts that by design or accident interfere with the processing
  @ of the repository.  Do not shun artifacts merely to remove them from
  @ sight - set the "hidden" tag on such artifacts instead.</p>
  @
  @ <blockquote>
  @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
  login_insert_csrf_secret();
  @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
  if( zShun ){
    if( strlen(zShun) ){
      @ %h(zShun)
    }else if( zRcvid ){
      db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
      while( db_step(&q)==SQLITE_ROW ){
        @ %s(db_column_text(&q, 0))
      }
      db_finalize(&q);
    }
  }
  @ </textarea>
  @ <input type="submit" name="add" value="Shun" />
  @ </div></form>
  @ </blockquote>
  @
  @ <a name="delshun"></a>
  @ <p>Enter the UUIDs of previously shunned artifacts to cause them to be
  @ accepted again in the repository.  The artifacts content is not
  @ restored because the content is unknown.  The only change is that
  @ the formerly shunned artifacts will be accepted on subsequent sync
  @ operations.</p>
  @
  @ <blockquote>
  @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
  login_insert_csrf_secret();
  @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
  if( zAccept ){
    if( strlen(zAccept) ){
      @ %h(zAccept)
    }else if( zRcvid ){
      db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
      while( db_step(&q)==SQLITE_ROW ){
        @ %s(db_column_text(&q, 0))
      }
      db_finalize(&q);
    }
  }
  @ </textarea>
  @ <input type="submit" name="sub" value="Accept" />
  @ </div></form>
  @ </blockquote>
  @
  @ <p>Press the Rebuild button below to rebuild the repository.  The
  @ content of newly shunned artifacts is not purged until the repository
  @ is rebuilt.  On larger repositories, the rebuild may take minute or
179
180
181
182
183
184
185

186
187
188
189
190
191
192
  }
  if( cnt==0 ){
    @ <i>no artifacts are shunned on this server</i>
  }
  db_finalize(&q);
  @ </p></blockquote>
  style_footer();

}

/*
** Remove from the BLOB table all artifacts that are in the SHUN table.
*/
void shun_artifacts(void){
  Stmt q;







>







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  }
  if( cnt==0 ){
    @ <i>no artifacts are shunned on this server</i>
  }
  db_finalize(&q);
  @ </p></blockquote>
  style_footer();
  fossil_free(zCanonical);
}

/*
** Remove from the BLOB table all artifacts that are in the SHUN table.
*/
void shun_artifacts(void){
  Stmt q;
285
286
287
288
289
290
291












292
293
294
295
296
297
298
  Stmt q;

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
  }
  style_header("Content Source %d", rcvid);












  db_prepare(&q,
    "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
    "  FROM rcvfrom LEFT JOIN user USING(uid)"
    " WHERE rcvid=%d",
    rcvid
  );
  @ <table cellspacing="15" cellpadding="0" border="0">







>
>
>
>
>
>
>
>
>
>
>
>







361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  Stmt q;

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
  }
  style_header("Content Source %d", rcvid);
  if( db_exists(
    "SELECT 1 FROM blob WHERE rcvid=%d AND"
    " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
  ){
    style_submenu_element("Shun All", "Shun All", "shun?shun&rcvid=%d#addshun", rcvid);
  }
  if( db_exists(
    "SELECT 1 FROM blob WHERE rcvid=%d AND"
    " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
  ){
    style_submenu_element("Unshun All", "Unshun All", "shun?accept&rcvid=%d#delshun", rcvid);
  }
  db_prepare(&q,
    "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
    "  FROM rcvfrom LEFT JOIN user USING(uid)"
    " WHERE rcvid=%d",
    rcvid
  );
  @ <table cellspacing="15" cellpadding="0" border="0">
Changes to src/skins.c.
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
@ }
@ div.mainmenu a, div.mainmenu a:visited {
@   padding: 3px 10px 3px 10px;
@   color: white;
@   text-decoration: none;
@ }
@ div.submenu a, div.submenu a:visited, a.button,
@ div.sectionmenu>a.button:link, div.sectinmenu>a.button:visited {
@   padding: 2px 8px;
@   color: #000;
@   font-family: Arial;
@   text-decoration: none;
@   margin:auto;
@   border-radius: 5px;
@   background-color: #e0e0e0;







|







768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
@ }
@ div.mainmenu a, div.mainmenu a:visited {
@   padding: 3px 10px 3px 10px;
@   color: white;
@   text-decoration: none;
@ }
@ div.submenu a, div.submenu a:visited, a.button,
@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
@   padding: 2px 8px;
@   color: #000;
@   font-family: Arial;
@   text-decoration: none;
@   margin:auto;
@   border-radius: 5px;
@   background-color: #e0e0e0;
872
873
874
875
876
877
878




879
880
881
882
883
884
885
@ table.report tr td {
@   padding: 3px 5px;
@   cursor: pointer;
@ }
@
@ textarea {
@   font-size: 1em;




@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <base href="$baseurl/$current_page" />
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">







>
>
>
>







872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
@ table.report tr td {
@   padding: 3px 5px;
@   cursor: pointer;
@ }
@
@ textarea {
@   font-size: 1em;
@ }
@
@ .fullsize-text {
@   font-size: 1.25em;
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <base href="$baseurl/$current_page" />
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
Changes to src/sqlcmd.c.
18
19
20
21
22
23
24




25

26
27
28
29
30
31
32
** This module contains the code that initializes the "sqlite3" command-line
** shell against the repository database.  The command-line shell itself
** is a copy of the "shell.c" code from SQLite.  This file contains logic
** to initialize the code in shell.c.
*/
#include "config.h"
#include "sqlcmd.h"




#include <zlib.h>


/*
** Implementation of the "content(X)" SQL function.  Return the complete
** content of artifact identified by X as a blob.
*/
static void sqlcmd_content(
  sqlite3_context *context,







>
>
>
>
|
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
** This module contains the code that initializes the "sqlite3" command-line
** shell against the repository database.  The command-line shell itself
** is a copy of the "shell.c" code from SQLite.  This file contains logic
** to initialize the code in shell.c.
*/
#include "config.h"
#include "sqlcmd.h"
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif

/*
** Implementation of the "content(X)" SQL function.  Return the complete
** content of artifact identified by X as a blob.
*/
static void sqlcmd_content(
  sqlite3_context *context,
Changes to src/sqlite3.c.

more than 10,000 changes

Changes to src/sqlite3.h.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.5"
#define SQLITE_VERSION_NUMBER 3008005
#define SQLITE_SOURCE_ID      "2014-06-04 14:06:34 b1ed4f2a34ba66c29b130f8d13e9092758019212"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|
|
|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.7"
#define SQLITE_VERSION_NUMBER 3008007
#define SQLITE_SOURCE_ID      "2014-10-04 19:31:53 b8f7f19dc06c59de2e194d83e6c052fb7d28c71d"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#endif

/*
** CAPI3REF: Closing A Database Connection
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated.
**
** ^If the database connection is associated with unfinalized prepared
** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
** and unfinished sqlite3_backups, then the database connection becomes
** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is
** finished.  The sqlite3_close_v2() interface is intended for use with
** host languages that are garbage collected, and where the order in which
** destructors are called is arbitrary.
**
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
** [sqlite3_blob_close | close] all [BLOB handles], and 
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object.  ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed.
**
** ^If an [sqlite3] object is destroyed while a transaction is open,
** the transaction is automatically rolled back.
**
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]







|







|












|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#endif

/*
** CAPI3REF: Closing A Database Connection
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated.
**
** ^If the database connection is associated with unfinalized prepared
** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
** and/or unfinished sqlite3_backups, then the database connection becomes
** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is
** finished.  The sqlite3_close_v2() interface is intended for use with
** host languages that are garbage collected, and where the order in which
** destructors are called is arbitrary.
**
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
** [sqlite3_blob_close | close] all [BLOB handles], and 
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object.  ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed.
**
** ^If an [sqlite3] object is destroyed while a transaction is open,
** the transaction is automatically rolled back.
**
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

/*
** CAPI3REF: Result Codes
** KEYWORDS: SQLITE_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE_IOERR_READ | extended result codes],
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
*/
#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */







<
|






|
<







382
383
384
385
386
387
388

389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

/*
** CAPI3REF: Result Codes

** KEYWORDS: {result code definitions}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [extended result code definitions]

*/
#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

/*
** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
**
** In its default configuration, SQLite API routines return one of 26 integer
** [SQLITE_OK | result codes].  However, experience has shown that many of
** these result codes are too coarse-grained.  They do not provide as
** much information about problems as programmers might like.  In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information
** about errors. The extended result codes are enabled or disabled
** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will increase
** over time.  Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
** The SQLITE_OK result code will never be extended.  It will always
** be exactly zero.
*/
#define SQLITE_IOERR_READ              (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ        (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE             (SQLITE_IOERR | (3<<8))
#define SQLITE_IOERR_FSYNC             (SQLITE_IOERR | (4<<8))
#define SQLITE_IOERR_DIR_FSYNC         (SQLITE_IOERR | (5<<8))
#define SQLITE_IOERR_TRUNCATE          (SQLITE_IOERR | (6<<8))







<
|

|
|




|

|
|
|
<
<
<
<
<
<







427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446






447
448
449
450
451
452
453
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

/*
** CAPI3REF: Extended Result Codes

** KEYWORDS: {extended result code definitions}
**
** In its default configuration, SQLite API routines return one of 30 integer
** [result codes].  However, experience has shown that many of
** these result codes are too coarse-grained.  They do not provide as
** much information about problems as programmers might like.  In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information
** about errors. These [extended result codes] are enabled or disabled
** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API.  Or, the extended code for
** the most recent error can be obtained using
** [sqlite3_extended_errcode()].






*/
#define SQLITE_IOERR_READ              (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ        (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE             (SQLITE_IOERR | (3<<8))
#define SQLITE_IOERR_FSYNC             (SQLITE_IOERR | (4<<8))
#define SQLITE_IOERR_DIR_FSYNC         (SQLITE_IOERR | (5<<8))
#define SQLITE_IOERR_TRUNCATE          (SQLITE_IOERR | (6<<8))
502
503
504
505
506
507
508

509
510
511
512
513
514
515
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))


/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.







>







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
#define SQLITE_AUTH_USER               (SQLITE_AUTH | (1<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
** integer opcode.  The third argument is a generic pointer intended to
** point to a structure that may contain arguments or space in which to
** write return values.  Potential uses for xFileControl() might be
** functions to enable blocking locks with timeouts, to change the
** locking strategy (for example to use dot-file locks), to inquire
** about the status of a lock, or to break stale locks.  The SQLite
** core reserves all opcodes less than 100 for its own use.
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts.  VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
** recognize.
**
** The xSectorSize() method returns the sector size of the
** device that underlies the file.  The sector size is the







|







673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
** integer opcode.  The third argument is a generic pointer intended to
** point to a structure that may contain arguments or space in which to
** write return values.  Potential uses for xFileControl() might be
** functions to enable blocking locks with timeouts, to change the
** locking strategy (for example to use dot-file locks), to inquire
** about the status of a lock, or to break stale locks.  The SQLite
** core reserves all opcodes less than 100 for its own use.
** A [file control opcodes | list of opcodes] less than 100 is available.
** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts.  VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
** recognize.
**
** The xSectorSize() method returns the sector size of the
** device that underlies the file.  The sector size is the
754
755
756
757
758
759
760

761
762
763
764
765
766
767
  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
  /* Methods above are valid for version 3 */
  /* Additional methods may be added in future releases */
};

/*
** CAPI3REF: Standard File Control Opcodes

**
** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
** interface.
**
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging.  This
** opcode causes the xFileControl method to write the current state of







>







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
  /* Methods above are valid for version 3 */
  /* Additional methods may be added in future releases */
};

/*
** CAPI3REF: Standard File Control Opcodes
** KEYWORDS: {file control opcodes} {file control opcode}
**
** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
** interface.
**
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging.  This
** opcode causes the xFileControl method to write the current state of
2033
2034
2035
2036
2037
2038
2039
2040

2041

2042


2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058
2059
2060

2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091

2092
2093
2094
2095

2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119


2120
2121
2122
2123
2124
2125
2126
*/
SQLITE_API int sqlite3_complete(const char *sql);
SQLITE_API int sqlite3_complete16(const void *sql);

/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
**
** ^This routine sets a callback function that might be invoked whenever

** an attempt is made to open a database table that another thread

** or process has locked.


**
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
** is returned immediately upon encountering the lock.  ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler().  ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked for this locking event.  ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.

** ^If the callback returns non-zero, then another attempt
** is made to open the database for reading and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
** when there is lock contention. ^If SQLite determines that invoking the busy
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.

** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying
** to promote to an exclusive lock.  The first process cannot proceed
** because it is blocked by the second and the second process cannot
** proceed because it is blocked by the first.  If both processes
** invoke the busy handlers, neither will make any progress.  Therefore,
** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
** will induce the first process to release its read lock and allow
** the second process to proceed.
**
** ^The default busy callback is NULL.
**
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
** when SQLite is in the middle of a large transaction where all the
** changes will not fit into the in-memory cache.  SQLite will
** already hold a RESERVED lock on the database file, but it needs
** to promote this lock to EXCLUSIVE so that it can spill cache
** pages into the database file without harm to concurrent
** readers.  ^If it is unable to promote the lock, then the in-memory
** cache will be left in an inconsistent state and so the error
** code is promoted from the relatively benign [SQLITE_BUSY] to
** the more severe [SQLITE_IOERR_BLOCKED].  ^This error code promotion
** forces an automatic rollback of the changes.  See the
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
** this is important.
**
** ^(There can only be a single busy handler defined for each
** [database connection].  Setting a new busy handler clears any
** previously set handler.)^  ^Note that calling [sqlite3_busy_timeout()]

** will also set or clear the busy handler.
**
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler.  Any such actions

** result in undefined behavior.
** 
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

/*
** CAPI3REF: Set A Busy Timeout
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked.  ^The handler
** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated.  ^After at least "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
**
** ^Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
**
** ^(There can only be a single busy handler for a particular
** [database connection] any any given moment.  If another busy handler
** was defined  (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^


*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);

/*
** CAPI3REF: Convenience Routines For Running Queries
**
** This is a legacy interface that is preserved for backwards compatibility.







|
>
|
>
|
>
>

|






|

|
>

|




|
>













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



>
|


|
>















|





|


>
>







2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072















2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
*/
SQLITE_API int sqlite3_complete(const char *sql);
SQLITE_API int sqlite3_complete16(const void *sql);

/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock.  ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler().  ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked for the same locking event.  ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] is returned
** to the application.
** ^If the callback returns non-zero, then another attempt
** is made to access the database and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
** when there is lock contention. ^If SQLite determines that invoking the busy
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
** to the application instead of invoking the 
** busy handler.
** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying
** to promote to an exclusive lock.  The first process cannot proceed
** because it is blocked by the second and the second process cannot
** proceed because it is blocked by the first.  If both processes
** invoke the busy handlers, neither will make any progress.  Therefore,
** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
** will induce the first process to release its read lock and allow
** the second process to proceed.
**
** ^The default busy callback is NULL.
**















** ^(There can only be a single busy handler defined for each
** [database connection].  Setting a new busy handler clears any
** previously set handler.)^  ^Note that calling [sqlite3_busy_timeout()]
** or evaluating [PRAGMA busy_timeout=N] will change the
** busy handler and thus clear any previously set busy handler.
**
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler.  In other words,
** the busy handler is not reentrant.  Any such actions
** result in undefined behavior.
** 
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

/*
** CAPI3REF: Set A Busy Timeout
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked.  ^The handler
** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated.  ^After at least "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY].
**
** ^Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
**
** ^(There can only be a single busy handler for a particular
** [database connection] at any given moment.  If another busy handler
** was defined  (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^
**
** See also:  [PRAGMA busy_timeout]
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);

/*
** CAPI3REF: Convenience Routines For Running Queries
**
** This is a legacy interface that is preserved for backwards compatibility.
2311
2312
2313
2314
2315
2316
2317




2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346














2347

2348
2349
2350
2351
2352
2353
2354
**
** ^The sqlite3_malloc() routine returns a pointer to a block
** of memory at least N bytes in length, where N is the parameter.
** ^If sqlite3_malloc() is unable to obtain sufficient free
** memory, it returns a NULL pointer.  ^If the parameter N to
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
** a NULL pointer.




**
** ^Calling sqlite3_free() with a pointer previously returned
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
** that it might be reused.  ^The sqlite3_free() routine is
** a no-op if is called with a NULL pointer.  Passing a NULL pointer
** to sqlite3_free() is harmless.  After being freed, memory
** should neither be read nor written.  Even reading previously freed
** memory might result in a segmentation fault or other severe error.
** Memory corruption, a segmentation fault, or other severe error
** might result if sqlite3_free() is called with a non-NULL pointer that
** was not obtained from sqlite3_malloc() or sqlite3_realloc().
**
** ^(The sqlite3_realloc() interface attempts to resize a
** prior memory allocation to be at least N bytes, where N is the
** second parameter.  The memory allocation to be resized is the first
** parameter.)^ ^ If the first parameter to sqlite3_realloc()
** is a NULL pointer then its behavior is identical to calling
** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
** ^If the second parameter to sqlite3_realloc() is zero or
** negative then the behavior is exactly the same as calling
** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
** ^sqlite3_realloc() returns a pointer to a memory allocation
** of at least N bytes in size or NULL if sufficient memory is unavailable.
** ^If M is the size of the prior allocation, then min(N,M) bytes
** of the prior allocation are copied into the beginning of buffer returned
** by sqlite3_realloc() and the prior allocation is freed.
** ^If sqlite3_realloc() returns NULL, then the prior allocation
** is not freed.
**














** ^The memory returned by sqlite3_malloc() and sqlite3_realloc()

** is always aligned to at least an 8 byte boundary, or to a
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
** In SQLite version 3.5.0 and 3.5.1, it was possible to define
** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
** implementation of these routines to be omitted.  That capability







>
>
>
>












|
|
<
|

|
|

|
|
|


|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
**
** ^The sqlite3_malloc() routine returns a pointer to a block
** of memory at least N bytes in length, where N is the parameter.
** ^If sqlite3_malloc() is unable to obtain sufficient free
** memory, it returns a NULL pointer.  ^If the parameter N to
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
** a NULL pointer.
**
** ^The sqlite3_malloc64(N) routine works just like
** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead
** of a signed 32-bit integer.
**
** ^Calling sqlite3_free() with a pointer previously returned
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
** that it might be reused.  ^The sqlite3_free() routine is
** a no-op if is called with a NULL pointer.  Passing a NULL pointer
** to sqlite3_free() is harmless.  After being freed, memory
** should neither be read nor written.  Even reading previously freed
** memory might result in a segmentation fault or other severe error.
** Memory corruption, a segmentation fault, or other severe error
** might result if sqlite3_free() is called with a non-NULL pointer that
** was not obtained from sqlite3_malloc() or sqlite3_realloc().
**
** ^The sqlite3_realloc(X,N) interface attempts to resize a
** prior memory allocation X to be at least N bytes.

** ^If the X parameter to sqlite3_realloc(X,N)
** is a NULL pointer then its behavior is identical to calling
** sqlite3_malloc(N).
** ^If the N parameter to sqlite3_realloc(X,N) is zero or
** negative then the behavior is exactly the same as calling
** sqlite3_free(X).
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
** of at least N bytes in size or NULL if insufficient memory is available.
** ^If M is the size of the prior allocation, then min(N,M) bytes
** of the prior allocation are copied into the beginning of buffer returned
** by sqlite3_realloc(X,N) and the prior allocation is freed.
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
** prior allocation is not freed.
**
** ^The sqlite3_realloc64(X,N) interfaces works the same as
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
** of a 32-bit signed integer.
**
** ^If X is a memory allocation previously obtained from sqlite3_malloc(),
** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then
** sqlite3_msize(X) returns the size of that memory allocation in bytes.
** ^The value returned by sqlite3_msize(X) might be larger than the number
** of bytes requested when X was allocated.  ^If X is a NULL pointer then
** sqlite3_msize(X) returns zero.  If X points to something that is not
** the beginning of memory allocation, or if it points to a formerly
** valid memory allocation that has now been freed, then the behavior
** of sqlite3_msize(X) is undefined and possibly harmful.
**
** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
** sqlite3_malloc64(), and sqlite3_realloc64()
** is always aligned to at least an 8 byte boundary, or to a
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
** In SQLite version 3.5.0 and 3.5.1, it was possible to define
** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
** implementation of these routines to be omitted.  That capability
2368
2369
2370
2371
2372
2373
2374

2375

2376

2377
2378
2379
2380
2381
2382
2383
** not yet been released.
**
** The application must not read or write any part of
** a block of memory after it has been released using
** [sqlite3_free()] or [sqlite3_realloc()].
*/
SQLITE_API void *sqlite3_malloc(int);

SQLITE_API void *sqlite3_realloc(void*, int);

SQLITE_API void sqlite3_free(void*);


/*
** CAPI3REF: Memory Allocator Statistics
**
** SQLite provides these two interfaces for reporting on the status
** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
** routines, which form the built-in memory allocation subsystem.







>

>

>







2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
** not yet been released.
**
** The application must not read or write any part of
** a block of memory after it has been released using
** [sqlite3_free()] or [sqlite3_realloc()].
*/
SQLITE_API void *sqlite3_malloc(int);
SQLITE_API void *sqlite3_malloc64(sqlite3_uint64);
SQLITE_API void *sqlite3_realloc(void*, int);
SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64);
SQLITE_API void sqlite3_free(void*);
SQLITE_API sqlite3_uint64 sqlite3_msize(void*);

/*
** CAPI3REF: Memory Allocator Statistics
**
** SQLite provides these two interfaces for reporting on the status
** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
** routines, which form the built-in memory allocation subsystem.
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
**
** The [sqlite3_set_authorizer | authorizer callback function] must
** return either [SQLITE_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted.  See the
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
** from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */

/*
** CAPI3REF: Authorizer Action Codes
**







|
|







2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
**
** The [sqlite3_set_authorizer | authorizer callback function] must
** return either [SQLITE_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted.  See the
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
** returned from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */

/*
** CAPI3REF: Authorizer Action Codes
**
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
** object.)^ ^(If the database is opened (and/or created) successfully, then
** [SQLITE_OK] is returned.  Otherwise an [error code] is returned.)^ ^The
** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
** an English language description of the error following a failure of any
** of the sqlite3_open() routines.
**
** ^The default encoding for the database will be UTF-8 if
** sqlite3_open() or sqlite3_open_v2() is called and
** UTF-16 in the native byte order if sqlite3_open16() is used.
**
** Whether or not an error occurs when it is opened, resources
** associated with the [database connection] handle should be released by
** passing it to [sqlite3_close()] when it is no longer required.
**
** The sqlite3_open_v2() interface works like sqlite3_open()
** except that it accepts two additional parameters for additional control







|
|
|







2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
** object.)^ ^(If the database is opened (and/or created) successfully, then
** [SQLITE_OK] is returned.  Otherwise an [error code] is returned.)^ ^The
** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
** an English language description of the error following a failure of any
** of the sqlite3_open() routines.
**
** ^The default encoding will be UTF-8 for databases created using
** sqlite3_open() or sqlite3_open_v2().  ^The default encoding for databases
** created using sqlite3_open16() will be UTF-16 in the native byte order.
**
** Whether or not an error occurs when it is opened, resources
** associated with the [database connection] handle should be released by
** passing it to [sqlite3_close()] when it is no longer required.
**
** The sqlite3_open_v2() interface works like sqlite3_open()
** except that it accepts two additional parameters for additional control
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758

2759
2760
2761
2762
2763
2764
2765
2766
** present, is ignored.
**
** ^SQLite uses the path component of the URI as the name of the disk file
** which contains the database. ^If the path begins with a '/' character, 
** then it is interpreted as an absolute path. ^If the path does not begin 
** with a '/' (meaning that the authority section is omitted from the URI)
** then the path is interpreted as a relative path. 
** ^On windows, the first component of an absolute path 
** is a drive specification (e.g. "C:").
**
** [[core URI query parameters]]
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [VFS | custom VFS implementation].

** SQLite interprets the following three query parameters:
**
** <ul>
**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
**     a VFS object that provides the operating system interface that should
**     be used to access the database file on disk. ^If this option is set to
**     an empty string the default VFS object is used. ^Specifying an unknown
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is







|
|




>
|







2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
** present, is ignored.
**
** ^SQLite uses the path component of the URI as the name of the disk file
** which contains the database. ^If the path begins with a '/' character, 
** then it is interpreted as an absolute path. ^If the path does not begin 
** with a '/' (meaning that the authority section is omitted from the URI)
** then the path is interpreted as a relative path. 
** ^(On windows, the first component of an absolute path 
** is a drive specification (e.g. "C:").)^
**
** [[core URI query parameters]]
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [VFS | custom VFS implementation].
** SQLite and its built-in [VFSes] interpret the
** following query parameters:
**
** <ul>
**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
**     a VFS object that provides the operating system interface that should
**     be used to access the database file on disk. ^If this option is set to
**     an empty string the default VFS object is used. ^Specifying an unknown
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
**     a URI filename, its value overrides any behavior requested by setting
**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
**     "1") or "false" (or "off" or "no" or "0") to indicate that the
**     [powersafe overwrite] property does or does not apply to the
**     storage media on which the database file resides.  ^The psow query
**     parameter only works for the built-in unix and Windows VFSes.
**
**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
**     which if set disables file locking in rollback journal modes.  This
**     is useful for accessing a database on a filesystem that does not
**     support locking.  Caution:  Database corruption might result if two
**     or more processes write to the same database and any one of those
**     processes uses nolock=1.







|
<

|
<







2797
2798
2799
2800
2801
2802
2803
2804

2805
2806

2807
2808
2809
2810
2811
2812
2813
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
**     a URI filename, its value overrides any behavior requested by setting
**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
**  <li> <b>psow</b>: ^The psow parameter indicates whether or not the

**     [powersafe overwrite] property does or does not apply to the
**     storage media on which the database file resides.

**
**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
**     which if set disables file locking in rollback journal modes.  This
**     is useful for accessing a database on a filesystem that does not
**     support locking.  Caution:  Database corruption might result if two
**     or more processes write to the same database and any one of those
**     processes uses nolock=1.
3087
3088
3089
3090
3091
3092
3093




3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106

3107
3108
3109
3110
3111
3112
3113
**
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^




** </dl>
*/
#define SQLITE_LIMIT_LENGTH                    0
#define SQLITE_LIMIT_SQL_LENGTH                1
#define SQLITE_LIMIT_COLUMN                    2
#define SQLITE_LIMIT_EXPR_DEPTH                3
#define SQLITE_LIMIT_COMPOUND_SELECT           4
#define SQLITE_LIMIT_VDBE_OP                   5
#define SQLITE_LIMIT_FUNCTION_ARG              6
#define SQLITE_LIMIT_ATTACHED                  7
#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH       8
#define SQLITE_LIMIT_VARIABLE_NUMBER           9
#define SQLITE_LIMIT_TRIGGER_DEPTH            10


/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.







>
>
>
>













>







3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
**
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
**
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
** <dd>The maximum number of auxiliary worker threads that a single
** [prepared statement] may start.</dd>)^
** </dl>
*/
#define SQLITE_LIMIT_LENGTH                    0
#define SQLITE_LIMIT_SQL_LENGTH                1
#define SQLITE_LIMIT_COLUMN                    2
#define SQLITE_LIMIT_EXPR_DEPTH                3
#define SQLITE_LIMIT_COMPOUND_SELECT           4
#define SQLITE_LIMIT_VDBE_OP                   5
#define SQLITE_LIMIT_FUNCTION_ARG              6
#define SQLITE_LIMIT_ATTACHED                  7
#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH       8
#define SQLITE_LIMIT_VARIABLE_NUMBER           9
#define SQLITE_LIMIT_TRIGGER_DEPTH            10
#define SQLITE_LIMIT_WORKER_THREADS           11

/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397








3398
3399
3400
3401
3402
3403
3404
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
** is negative, then the length of the string is
** the number of bytes up to the first zero terminator.
** If the fourth parameter to sqlite3_bind_blob() is negative, then
** the behavior is undefined.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()

** or sqlite3_bind_text16() then that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occur at byte offsets less than 
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
** sqlite3_bind_text(), or sqlite3_bind_text16() fails.  
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.








**
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
** is filled with zeroes.  ^A zeroblob uses a fixed amount of memory
** (just an integer to hold its size) while it is being processed.
** Zeroblobs are intended to serve as placeholders for BLOBs whose
** content is later written using
** [sqlite3_blob_open | incremental BLOB I/O] routines.







>
|






|
|

|
<






>
>
>
>
>
>
>
>







3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404

3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
** is negative, then the length of the string is
** the number of bytes up to the first zero terminator.
** If the fourth parameter to sqlite3_bind_blob() is negative, then
** the behavior is undefined.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occur at byte offsets less than 
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to bind API fails.

** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
** to specify the encoding of the text in the third parameter.  If
** the sixth argument to sqlite3_bind_text64() is not one of the
** allowed values shown above, or if the text encoding is different
** from the encoding specified by the sixth parameter, then the behavior
** is undefined.
**
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
** is filled with zeroes.  ^A zeroblob uses a fixed amount of memory
** (just an integer to hold its size) while it is being processed.
** Zeroblobs are intended to serve as placeholders for BLOBs whose
** content is later written using
** [sqlite3_blob_open | incremental BLOB I/O] routines.
3412
3413
3414
3415
3416
3417
3418



3419
3420
3421
3422
3423
3424
3425


3426
3427
3428
3429
3430
3431


3432
3433
3434
3435
3436
3437
3438
** result is undefined and probably harmful.
**
** ^Bindings are not cleared by the [sqlite3_reset()] routine.
** ^Unbound parameters are interpreted as NULL.
**
** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
** [error code] if anything goes wrong.



** ^[SQLITE_RANGE] is returned if the parameter
** index is out of range.  ^[SQLITE_NOMEM] is returned if malloc() fails.
**
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));


SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));


SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);

/*
** CAPI3REF: Number Of SQL Parameters
**
** ^This routine can be used to find the number of [SQL parameters]







>
>
>







>
>




|

>
>







3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
** result is undefined and probably harmful.
**
** ^Bindings are not cleared by the [sqlite3_reset()] routine.
** ^Unbound parameters are interpreted as NULL.
**
** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
** [error code] if anything goes wrong.
** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB
** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or
** [SQLITE_MAX_LENGTH].
** ^[SQLITE_RANGE] is returned if the parameter
** index is out of range.  ^[SQLITE_NOMEM] is returned if malloc() fails.
**
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
                        void(*)(void*));
SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
                         void(*)(void*), unsigned char encoding);
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);

/*
** CAPI3REF: Number Of SQL Parameters
**
** ^This routine can be used to find the number of [SQL parameters]
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
** extract values from the [sqlite3_value] objects.
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
** object results in undefined behavior.
**
** ^These routines work just like the corresponding [column access functions]
** except that  these routines take a single [protected sqlite3_value] object
** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
**
** ^The sqlite3_value_text16() interface extracts a UTF-16 string
** in the native byte-order of the host machine.  ^The
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**







|







4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
** extract values from the [sqlite3_value] objects.
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
** object results in undefined behavior.
**
** ^These routines work just like the corresponding [column access functions]
** except that these routines take a single [protected sqlite3_value] object
** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
**
** ^The sqlite3_value_text16() interface extracts a UTF-16 string
** in the native byte-order of the host machine.  ^The
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**
4420
4421
4422
4423
4424
4425
4426




4427
4428
4429
4430
4431
4432
4433
** of the application-defined function to be NULL.
**
** ^The sqlite3_result_text(), sqlite3_result_text16(),
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.




** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is negative, then SQLite takes result text from the 2nd parameter
** through the first zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text







>
>
>
>







4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
** of the application-defined function to be NULL.
**
** ^The sqlite3_result_text(), sqlite3_result_text16(),
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.
** ^The sqlite3_result_text64() interface sets the return value of an
** application-defined function to be a text string in an encoding
** specified by the fifth (and last) parameter, which must be one
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is negative, then SQLite takes result text from the 2nd parameter
** through the first zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
4463
4464
4465
4466
4467
4468
4469

4470
4471
4472
4473
4474
4475
4476
4477
4478
4479


4480
4481
4482
4483
4484
4485
4486
** kind of [sqlite3_value] object can be used with this interface.
**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));

SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
SQLITE_API void sqlite3_result_null(sqlite3_context*);
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));


SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);

/*







>










>
>







4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
** kind of [sqlite3_value] object can be used with this interface.
**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*));
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
SQLITE_API void sqlite3_result_null(sqlite3_context*);
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
                           void(*)(void*), unsigned char encoding);
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);

/*
4701
4702
4703
4704
4705
4706
4707







4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726





4727
4728
4729
4730
4731
4732
4733
**
** ^(If this global variable is made to point to a string which is
** the name of a folder (a.k.a. directory), then all temporary files
** created by SQLite when using a built-in [sqlite3_vfs | VFS]
** will be placed in that directory.)^  ^If this variable
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.







**
** It is not safe to read or modify this variable in more than one
** thread at a time.  It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
** thread.
** It is intended that this variable be set once
** as part of process initialization and before any SQLite interface
** routines have been called and that this variable remain unchanged
** thereafter.
**
** ^The [temp_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
** the [temp_store_directory pragma] always assumes that any string
** that this variable points to is held in memory obtained from 
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.





**
** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
** features that require the use of temporary files may fail.  Here is an
** example of how to do this using C++ with the Windows Runtime:
**
** <blockquote><pre>







>
>
>
>
>
>
>



















>
>
>
>
>







4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
**
** ^(If this global variable is made to point to a string which is
** the name of a folder (a.k.a. directory), then all temporary files
** created by SQLite when using a built-in [sqlite3_vfs | VFS]
** will be placed in that directory.)^  ^If this variable
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.
**
** Applications are strongly discouraged from using this global variable.
** It is required to set a temporary folder on Windows Runtime (WinRT).
** But for all other platforms, it is highly recommended that applications
** neither read nor write this variable.  This global variable is a relic
** that exists for backwards compatibility of legacy applications and should
** be avoided in new projects.
**
** It is not safe to read or modify this variable in more than one
** thread at a time.  It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
** thread.
** It is intended that this variable be set once
** as part of process initialization and before any SQLite interface
** routines have been called and that this variable remain unchanged
** thereafter.
**
** ^The [temp_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
** the [temp_store_directory pragma] always assumes that any string
** that this variable points to is held in memory obtained from 
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
** Except when requested by the [temp_store_directory pragma], SQLite
** does not free the memory that sqlite3_temp_directory points to.  If
** the application wants that memory to be freed, it must do
** so itself, taking care to only do so after all [database connection]
** objects have been destroyed.
**
** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
** features that require the use of temporary files may fail.  Here is an
** example of how to do this using C++ with the Windows Runtime:
**
** <blockquote><pre>
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864


5865
5866
5867
5868
5869
5870
5871
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_MEM2
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_LRU2


** </ul>)^
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
** cause sqlite3_mutex_alloc() to create
** a new mutex.  ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction







|


|
>
>







5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_OPEN
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_PMEM
** <li>  SQLITE_MUTEX_STATIC_APP1
** <li>  SQLITE_MUTEX_STATIC_APP2
** </ul>)^
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
** cause sqlite3_mutex_alloc() to create
** a new mutex.  ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
6061
6062
6063
6064
6065
6066
6067



6068
6069
6070
6071
6072
6073
6074
#define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2      4  /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN      4  /* sqlite3BtreeOpen() */
#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */




/*
** CAPI3REF: Retrieve the mutex for a database connection
**
** ^This interface returns a pointer the [sqlite3_mutex] object that 
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.







>
>
>







6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
#define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2      4  /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN      4  /* sqlite3BtreeOpen() */
#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
#define SQLITE_MUTEX_STATIC_APP1      8  /* For use by application */
#define SQLITE_MUTEX_STATIC_APP2      9  /* For use by application */
#define SQLITE_MUTEX_STATIC_APP3     10  /* For use by application */

/*
** CAPI3REF: Retrieve the mutex for a database connection
**
** ^This interface returns a pointer the [sqlite3_mutex] object that 
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162


6163
6164
6165
6166
6167
6168
6169
6170
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22


#define SQLITE_TESTCTRL_LAST                    22

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for







|



>
>
|







6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_ISINIT                  23
#define SQLITE_TESTCTRL_SORTER_MMAP             24
#define SQLITE_TESTCTRL_LAST                    24

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
** <dd>This parameter returns the number of pager cache hits that have







|




|








|







6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
** <dd>This parameter returns the number of pager cache hits that have
7139
7140
7141
7142
7143
7144
7145



7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162




7163
7164
7165
7166
7167
7168
7169
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.



**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.  The use of this interface
** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
**
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
** on [database connection] D to be [checkpointed].  ^If X is NULL or an
** empty string, then a checkpoint is run on all databases of
** connection D.  ^If the database connection D is not in
** [WAL | write-ahead log mode] then this interface is a harmless no-op.




**
** ^The [wal_checkpoint pragma] can be used to invoke this interface
** from SQL.  ^The [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] can be used to cause this interface to be
** run whenever the WAL reaches a certain size threshold.
**
** See also: [sqlite3_wal_checkpoint_v2()]







>
>
>

















>
>
>
>







7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.  The use of this interface
** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
**
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
** on [database connection] D to be [checkpointed].  ^If X is NULL or an
** empty string, then a checkpoint is run on all databases of
** connection D.  ^If the database connection D is not in
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
** or RESET checkpoint.
**
** ^The [wal_checkpoint pragma] can be used to invoke this interface
** from SQL.  ^The [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] can be used to cause this interface to be
** run whenever the WAL reaches a certain size threshold.
**
** See also: [sqlite3_wal_checkpoint_v2()]
7178
7179
7180
7181
7182
7183
7184
7185

7186
7187
7188

7189
7190
7191
7192
7193
7194
7195
7196

7197
7198
7199
7200
7201
7202
7203
** eMode parameter:
**
** <dl>
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
**   Checkpoint as many frames as possible without waiting for any database 
**   readers or writers to finish. Sync the db file if all frames in the log
**   are checkpointed. This mode is the same as calling 
**   sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.

**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
**   This mode blocks (calls the busy-handler callback) until there is no

**   database writer and all readers are reading from the most recent database
**   snapshot. It then checkpoints all frames in the log file and syncs the
**   database file. This call blocks database writers while it is running,
**   but not database readers.
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
**   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
**   checkpointing the log file it blocks (calls the busy-handler callback)

**   until all readers are reading from the database file only. This ensures 
**   that the next client to write to the database file restarts the log file 
**   from the beginning. This call blocks database writers while it is running,
**   but not database readers.
** </dl>
**
** If pnLog is not NULL, then *pnLog is set to the total number of frames in







|
>


|
>







|
>







7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
** eMode parameter:
**
** <dl>
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
**   Checkpoint as many frames as possible without waiting for any database 
**   readers or writers to finish. Sync the db file if all frames in the log
**   are checkpointed. This mode is the same as calling 
**   sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
**   is never invoked.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
**   This mode blocks (it invokes the
**   [sqlite3_busy_handler|busy-handler callback]) until there is no
**   database writer and all readers are reading from the most recent database
**   snapshot. It then checkpoints all frames in the log file and syncs the
**   database file. This call blocks database writers while it is running,
**   but not database readers.
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
**   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
**   checkpointing the log file it blocks (calls the 
**   [sqlite3_busy_handler|busy-handler callback])
**   until all readers are reading from the database file only. This ensures 
**   that the next client to write to the database file restarts the log file 
**   from the beginning. This call blocks database writers while it is running,
**   but not database readers.
** </dl>
**
** If pnLog is not NULL, then *pnLog is set to the total number of frames in
7327
7328
7329
7330
7331
7332
7333

7334
7335
7336
7337
7338
7339
7340
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);

/*
** CAPI3REF: Conflict resolution modes

**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
** is for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that







>







7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);

/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
** is for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that
Changes to src/stash.c.
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537

    if( zWidth ){
      width = atoi(zWidth);
      if( (width!=0) && (width<=46) ){
        fossil_fatal("-W|--width value must be >46 or 0");
      }
    }else{
      width = 79;
    }
    if( !verboseFlag ){
      verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
    }
    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"







|







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537

    if( zWidth ){
      width = atoi(zWidth);
      if( (width!=0) && (width<=46) ){
        fossil_fatal("-W|--width value must be >46 or 0");
      }
    }else{
      width = -1;
    }
    if( !verboseFlag ){
      verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
    }
    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
        stashid,
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 7, width);
      }
      if( verboseFlag ){
        db_bind_int(&q2, "$id", stashid);
        while( db_step(&q2)==SQLITE_ROW ){
          int isAdded = db_column_int(&q2, 0);
          int isRemoved = db_column_int(&q2, 1);
          const char *zOrig = db_column_text(&q2, 2);







|







550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
        stashid,
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 0, 7, width, g.comFmtFlags);
      }
      if( verboseFlag ){
        db_bind_int(&q2, "$id", stashid);
        while( db_step(&q2)==SQLITE_ROW ){
          int isAdded = db_column_int(&q2, 0);
          int isRemoved = db_column_int(&q2, 1);
          const char *zOrig = db_column_text(&q2, 2);
Changes to src/stat.c.
47
48
49
50
51
52
53

54
55
56
57
58
59
60
void stat_page(void){
  i64 t, fsize;
  int n, m;
  int szMax, szAvg;
  const char *zDb;
  int brief;
  char zBuf[100];


  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  brief = P("brief")!=0;
  style_header("Repository Statistics");
  if( g.perm.Admin ){
    style_submenu_element("URLs", "URLs and Checkouts", "urllist");







>







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void stat_page(void){
  i64 t, fsize;
  int n, m;
  int szMax, szAvg;
  const char *zDb;
  int brief;
  char zBuf[100];
  const char *p;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  brief = P("brief")!=0;
  style_header("Repository Statistics");
  if( g.perm.Admin ){
    style_submenu_element("URLs", "URLs and Checkouts", "urllist");
118
119
120
121
122
123
124


125


126
127
128
129
130
131
132
    @ </td></tr>
  }
  @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
  n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
                " + 0.99");
  @ %d(n) days or approximately %.2f(n/365.2425) years.
  @ </td></tr>


  @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>


  @ <tr><th>Fossil&nbsp;Version:</th><td>
  @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
  @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
  @ </td></tr>
  @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
  @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
  @ <tr><th>Repository Rebuilt:</th><td>







>
>
|
>
>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    @ </td></tr>
  }
  @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
  n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
                " + 0.99");
  @ %d(n) days or approximately %.2f(n/365.2425) years.
  @ </td></tr>
  p = db_get("project-code", 0);
  if( p ){
    @ <tr><th>Project&nbsp;ID:</th><td>%h(p)</td></tr>
  }
  @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
  @ <tr><th>Fossil&nbsp;Version:</th><td>
  @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
  @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
  @ </td></tr>
  @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
  @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
  @ <tr><th>Repository Rebuilt:</th><td>
161
162
163
164
165
166
167


168
169




170
171
172
173
174
175
176
  i64 t, fsize;
  int n, m;
  int szMax, szAvg;
  const char *zDb;
  int brief;
  char zBuf[100];
  const int colWidth = -19 /* printf alignment/width for left column */;


  brief = find_option("brief", "b",0)!=0;
  db_find_and_open_repository(0,0);




  fsize = file_size(g.zRepositoryName);
  bigSizeName(sizeof(zBuf), zBuf, fsize);
  fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
  if( !brief ){
    n = db_int(0, "SELECT count(*) FROM blob");
    m = db_int(0, "SELECT count(*) FROM delta");
    fossil_print("%*s%d (stored as %d full text and %d delta blobs)\n",







>
>


>
>
>
>







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  i64 t, fsize;
  int n, m;
  int szMax, szAvg;
  const char *zDb;
  int brief;
  char zBuf[100];
  const int colWidth = -19 /* printf alignment/width for left column */;
  const char *p;

  brief = find_option("brief", "b",0)!=0;
  db_find_and_open_repository(0,0);

  /* We should be done with options.. */
  verify_all_options();

  fsize = file_size(g.zRepositoryName);
  bigSizeName(sizeof(zBuf), zBuf, fsize);
  fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
  if( !brief ){
    n = db_int(0, "SELECT count(*) FROM blob");
    m = db_int(0, "SELECT count(*) FROM delta");
    fossil_print("%*s%d (stored as %d full text and %d delta blobs)\n",
217
218
219
220
221
222
223


224


225
226
227
228
229
230
231
    n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
    fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
  }
  n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
                " + 0.99");
  fossil_print("%*s%d days or approximately %.2f years.\n",
               colWidth, "project-age:", n, n/365.2425);


  fossil_print("%*s%s\n", colWidth, "project-id:", db_get("project-code",""));


  fossil_print("%*s%s %s [%s] (%s)\n",
               colWidth, "fossil-version:",
               MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
               COMPILER_NAME);
  fossil_print("%*s%.19s [%.10s] (%s)\n",
               colWidth, "sqlite-version:",
               sqlite3_sourceid(), &sqlite3_sourceid()[20],







>
>
|
>
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
    fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
  }
  n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
                " + 0.99");
  fossil_print("%*s%d days or approximately %.2f years.\n",
               colWidth, "project-age:", n, n/365.2425);
  p = db_get("project-code", 0);
  if( p ){
    fossil_print("%*s%s\n", colWidth, "project-id:", p);
  }
  fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
  fossil_print("%*s%s %s [%s] (%s)\n",
               colWidth, "fossil-version:",
               MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
               COMPILER_NAME);
  fossil_print("%*s%.19s [%.10s] (%s)\n",
               colWidth, "sqlite-version:",
               sqlite3_sourceid(), &sqlite3_sourceid()[20],
Changes to src/style.c.
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    }
    @ </div>
  }
  style_ad_unit();
  @ <div class="content">
  cgi_destination(CGI_BODY);

  if (sideboxUsed) {
    /* Put the footer at the bottom of the page.
    ** the additional clear/both is needed to extend the content
    ** part to the end of an optional sidebox.
    */
    @ <div class="endContent"></div>
  }
  @ </div>







|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    }
    @ </div>
  }
  style_ad_unit();
  @ <div class="content">
  cgi_destination(CGI_BODY);

  if( sideboxUsed ){
    /* Put the footer at the bottom of the page.
    ** the additional clear/both is needed to extend the content
    ** part to the end of an optional sidebox.
    */
    @ <div class="endContent"></div>
  }
  @ </div>
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/
const struct strctCssDefaults {
  char const * const elementClass;  /* Name of element needed */
  char const * const comment;       /* Comment text */
  char const * const value;         /* CSS text */
} cssDefaultList[] = {
  { "",
    "",
    zDefaultCSS
  },
  { "div.sidebox",
    "The nomenclature sidebox for branches,..",







|
|
|







655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/
const struct strctCssDefaults {
  const char *elementClass;  /* Name of element needed */
  const char *comment;       /* Comment text */
  const char *value;         /* CSS text */
} cssDefaultList[] = {
  { "",
    "",
    zDefaultCSS
  },
  { "div.sidebox",
    "The nomenclature sidebox for branches,..",
932
933
934
935
936
937
938

939
940
941
942

943
944
945
946

947
948
949
950

951
952
953
954
955
956
957
    @   text-align: right;
    @   vertical-align: top;
    @   white-space: nowrap;
  },
  { "span.ueditInheritNobody",
    "color for capabilities, inherited by nobody",
    @   color: green;

  },
  { "span.ueditInheritDeveloper",
    "color for capabilities, inherited by developer",
    @   color: red;

  },
  { "span.ueditInheritReader",
    "color for capabilities, inherited by reader",
    @   color: black;

  },
  { "span.ueditInheritAnonymous",
    "color for capabilities, inherited by anonymous",
    @   color: blue;

  },
  { "span.capability",
    "format for capabilities, mentioned on the user edit page",
    @   font-weight: bold;
  },
  { "span.usertype",
    "format for different user types, mentioned on the user edit page",







>




>




>




>







932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
    @   text-align: right;
    @   vertical-align: top;
    @   white-space: nowrap;
  },
  { "span.ueditInheritNobody",
    "color for capabilities, inherited by nobody",
    @   color: green;
    @   padding: .2em;
  },
  { "span.ueditInheritDeveloper",
    "color for capabilities, inherited by developer",
    @   color: red;
    @   padding: .2em;
  },
  { "span.ueditInheritReader",
    "color for capabilities, inherited by reader",
    @   color: black;
    @   padding: .2em;
  },
  { "span.ueditInheritAnonymous",
    "color for capabilities, inherited by anonymous",
    @   color: blue;
    @   padding: .2em;
  },
  { "span.capability",
    "format for capabilities, mentioned on the user edit page",
    @   font-weight: bold;
  },
  { "span.usertype",
    "format for different user types, mentioned on the user edit page",
1189
1190
1191
1192
1193
1194
1195




1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
  { "tr.row0",
    "even table row color",
    @ /* use default */
  },
  { "tr.row1",
    "odd table row color",
    @ /* Use default */




  },
  { "#canvas", "timeline graph node colors",
    @ color: black;
    @ background-color: white;
  },
  { 0,
    0,
    0
  }
};

/*
** Append all of the default CSS to the CGI output.
*/
void cgi_append_default_css(void) {
  int i;

  for (i=0;cssDefaultList[i].elementClass;i++){
    if (cssDefaultList[i].elementClass[0]){
      cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
                 cssDefaultList[i].comment,
                 cssDefaultList[i].elementClass,
                 cssDefaultList[i].value
                );
    }else{
      cgi_printf("%s",







>
>
>
>

















|
|







1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
  { "tr.row0",
    "even table row color",
    @ /* use default */
  },
  { "tr.row1",
    "odd table row color",
    @ /* Use default */
  },
  { "#usetupEditCapability",
    "format for capabilities string, mentioned on the user edit page",
    @ font-weight: bold;
  },
  { "#canvas", "timeline graph node colors",
    @ color: black;
    @ background-color: white;
  },
  { 0,
    0,
    0
  }
};

/*
** Append all of the default CSS to the CGI output.
*/
void cgi_append_default_css(void) {
  int i;

  for( i=0; cssDefaultList[i].elementClass; i++ ){
    if( cssDefaultList[i].elementClass[0] ){
      cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
                 cssDefaultList[i].comment,
                 cssDefaultList[i].elementClass,
                 cssDefaultList[i].value
                );
    }else{
      cgi_printf("%s",
Changes to src/sync.c.
70
71
72
73
74
75
76
















77



78
79
80
81
82
83
84
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  fossil_print("Autosync:  %s\n", g.url.canonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
















  if( rc ) fossil_warning("Autosync failed");



  return rc;
}

/*
** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  fossil_print("Autosync:  %s\n", g.url.canonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  return rc;
}

/*
** This routine will try a number of times to perform autosync with a
** 0.5 second sleep between attempts; returning the last autosync status.
*/
int autosync_loop(int flags, int nTries){
  int n = 0;
  int rc = 0;
  while( (n==0 || n<nTries) && (rc=autosync(flags)) ){
    if( rc ){
      if( ++n<nTries ){
        fossil_warning("Autosync failed, making another attempt.");
        sqlite3_sleep(500);
      }else{
        fossil_warning("Autosync failed.");
      }
    }
  }
  return rc;
}

/*
** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the
165
166
167
168
169
170
171




172
173
174
175
176
177
178
**
** See also: clone, push, sync, remote-url
*/
void pull_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PULL;
  process_sync_args(&configFlags, &syncFlags);




  client_sync(syncFlags, configFlags, 0);
}

/*
** COMMAND: push
**
** Usage: %fossil push ?URL? ?options?







>
>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
**
** See also: clone, push, sync, remote-url
*/
void pull_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PULL;
  process_sync_args(&configFlags, &syncFlags);
 
  /* We should be done with options.. */
  verify_all_options();

  client_sync(syncFlags, configFlags, 0);
}

/*
** COMMAND: push
**
** Usage: %fossil push ?URL? ?options?
196
197
198
199
200
201
202




203
204
205
206
207
208
209
**
** See also: clone, pull, sync, remote-url
*/
void push_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PUSH;
  process_sync_args(&configFlags, &syncFlags);




  if( db_get_boolean("dont-push",0) ){
    fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
  }
  client_sync(syncFlags, 0, 0);
}









>
>
>
>







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
**
** See also: clone, pull, sync, remote-url
*/
void push_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PUSH;
  process_sync_args(&configFlags, &syncFlags);
  
  /* We should be done with options.. */
  verify_all_options();

  if( db_get_boolean("dont-push",0) ){
    fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
  }
  client_sync(syncFlags, 0, 0);
}


232
233
234
235
236
237
238




239
240
241
242
243
244
245
**
** See also:  clone, push, pull, remote-url
*/
void sync_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
  process_sync_args(&configFlags, &syncFlags);




  if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
  client_sync(syncFlags, configFlags, 0);
  if( (syncFlags & SYNC_PUSH)==0 ){
    fossil_warning("pull only: the 'dont-push' option is set");
  }
}








>
>
>
>







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
**
** See also:  clone, push, pull, remote-url
*/
void sync_cmd(void){
  unsigned configFlags = 0;
  unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
  process_sync_args(&configFlags, &syncFlags);
  
  /* We should be done with options.. */
  verify_all_options();

  if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
  client_sync(syncFlags, configFlags, 0);
  if( (syncFlags & SYNC_PUSH)==0 ){
    fossil_warning("pull only: the 'dont-push' option is set");
  }
}

259
260
261
262
263
264
265




266
267
268
269
270
271
272
** See clone usage for possible URL formats.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
  char *zUrl;
  db_find_and_open_repository(0, 0);




  if( g.argc!=2 && g.argc!=3 ){
    usage("remote-url ?URL|off?");
  }
  if( g.argc==3 ){
    db_unset("last-sync-url", 0);
    db_unset("last-sync-pw", 0);
    db_unset("http-auth", 0);







>
>
>
>







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
** See clone usage for possible URL formats.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
  char *zUrl;
  db_find_and_open_repository(0, 0);

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 ){
    usage("remote-url ?URL|off?");
  }
  if( g.argc==3 ){
    db_unset("last-sync-url", 0);
    db_unset("last-sync-pw", 0);
    db_unset("http-auth", 0);
Changes to src/tag.c.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  pqueuex_init(&queue);
  pqueuex_insert(&queue, pid, 0.0, 0);

  /* Query for children of :pid to which to propagate the tag.
  ** Three returns:  (1) rid of the child.  (2) timestamp of child.
  ** (3) True to propagate or false to block.
  */
  db_prepare(&s, 
     "SELECT cid, plink.mtime,"
     "       coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
     "  FROM plink LEFT JOIN tagxref ON cid=rid AND tagid=%d"
     " WHERE pid=:pid AND isprim",
     tagType==2, tagid
  );
  db_bind_double(&s, ":mtime", mtime);







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  pqueuex_init(&queue);
  pqueuex_insert(&queue, pid, 0.0, 0);

  /* Query for children of :pid to which to propagate the tag.
  ** Three returns:  (1) rid of the child.  (2) timestamp of child.
  ** (3) True to propagate or false to block.
  */
  db_prepare(&s,
     "SELECT cid, plink.mtime,"
     "       coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
     "  FROM plink LEFT JOIN tagxref ON cid=rid AND tagid=%d"
     " WHERE pid=:pid AND isprim",
     tagType==2, tagid
  );
  db_bind_double(&s, ":mtime", mtime);
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  db_bind_double(&s, ":mtime", mtime);
  rc = db_step(&s);
  db_finalize(&s);
  if( rc==SQLITE_ROW ){
    /* Another entry that is more recent already exists.  Do nothing */
    return tagid;
  }
  db_prepare(&s, 
    "REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)"
    " VALUES(%d,%d,%d,%d,%Q,:mtime,%d)",
    tagid, tagtype, srcId, rid, zValue, rid
  );
  db_bind_double(&s, ":mtime", mtime);
  db_step(&s);
  db_finalize(&s);







|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  db_bind_double(&s, ":mtime", mtime);
  rc = db_step(&s);
  db_finalize(&s);
  if( rc==SQLITE_ROW ){
    /* Another entry that is more recent already exists.  Do nothing */
    return tagid;
  }
  db_prepare(&s,
    "REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)"
    " VALUES(%d,%d,%d,%d,%Q,:mtime,%d)",
    tagid, tagtype, srcId, rid, zValue, rid
  );
  db_bind_double(&s, ":mtime", mtime);
  db_step(&s);
  db_finalize(&s);
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    usage("TAGNAME ARTIFACT-ID ?VALUE?");
  }
  zTag = g.argv[2];
  switch( zTag[0] ){
    case '+':  tagtype = 1;  break;
    case '*':  tagtype = 2;  break;
    case '-':  tagtype = 0;  break;
    default:   
      fossil_fatal("tag should begin with '+', '*', or '-'");
      return;
  }
  rid = name_to_rid(g.argv[3]);
  if( rid==0 ){
    fossil_fatal("no such object: %s", g.argv[3]);
  }







|







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    usage("TAGNAME ARTIFACT-ID ?VALUE?");
  }
  zTag = g.argv[2];
  switch( zTag[0] ){
    case '+':  tagtype = 1;  break;
    case '*':  tagtype = 2;  break;
    case '-':  tagtype = 0;  break;
    default:
      fossil_fatal("tag should begin with '+', '*', or '-'");
      return;
  }
  rid = name_to_rid(g.argv[3]);
  if( rid==0 ){
    fossil_fatal("no such object: %s", g.argv[3]);
  }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
**
**     %fossil tag find ?--raw? ?-t|--type TYPE? ?-n|--limit #? TAGNAME
**
**         List all objects that use TAGNAME.  TYPE can be "ci" for
**         checkins or "e" for events. The limit option limits the number
**         of results to the given value.
**
**     %fossil tag list ?--raw? ?CHECK-IN?
**
**         List all tags, or if CHECK-IN is supplied, list
**         all tags and their values for CHECK-IN.
**
** The option --raw allows the manipulation of all types of tags
** used for various internal purposes in fossil. It also shows
** "cancel" tags for the "find" and "list" subcommands. You should







|







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
**
**     %fossil tag find ?--raw? ?-t|--type TYPE? ?-n|--limit #? TAGNAME
**
**         List all objects that use TAGNAME.  TYPE can be "ci" for
**         checkins or "e" for events. The limit option limits the number
**         of results to the given value.
**
**     %fossil tag list|ls ?--raw? ?CHECK-IN?
**
**         List all tags, or if CHECK-IN is supplied, list
**         all tags and their values for CHECK-IN.
**
** The option --raw allows the manipulation of all types of tags
** used for various internal purposes in fossil. It also shows
** "cancel" tags for the "find" and "list" subcommands. You should
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
** will be taken as an artifact or baseline ID and fossil will
** probably complain that no such revision was found. However
**
**   fossil update tag:decaf
**
** will assume that "decaf" is a tag/branch name.
**
** only allow --date-override and --user-override in 
**   %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
**                   --user-override user 
** in order to import history from other scm systems
*/
void tag_cmd(void){
  int n;
  int fRaw = find_option("raw","",0)!=0;
  int fPropagate = find_option("propagate","",0)!=0;
  const char *zPrefix = fRaw ? "" : "sym-";
  char const * zFindLimit = find_option("limit","n",1);
  int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;

  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto tag_cmd_usage;
  }
  n = strlen(g.argv[2]);
  if( n==0 ){







|

|







|
|







376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
** will be taken as an artifact or baseline ID and fossil will
** probably complain that no such revision was found. However
**
**   fossil update tag:decaf
**
** will assume that "decaf" is a tag/branch name.
**
** only allow --date-override and --user-override in
**   %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
**                   --user-override user
** in order to import history from other scm systems
*/
void tag_cmd(void){
  int n;
  int fRaw = find_option("raw","",0)!=0;
  int fPropagate = find_option("propagate","",0)!=0;
  const char *zPrefix = fRaw ? "" : "sym-";
  const char *zFindLimit = find_option("limit","n",1);
  const int nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;

  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto tag_cmd_usage;
  }
  n = strlen(g.argv[2]);
  if( n==0 ){
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
        blob_reset(&sql);
        print_timeline(&q, nFindLimit, 79, 0);
        db_finalize(&q);
      }
    }
  }else

  if( strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;
    if( g.argc==3 ){
      db_prepare(&q, 
        "SELECT tagname FROM tag"
        " WHERE EXISTS(SELECT 1 FROM tagxref"
        "               WHERE tagid=tag.tagid"
        "                 AND tagtype>0)"
        " ORDER BY tagname"
      );
      while( db_step(&q)==SQLITE_ROW ){







|


|







473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
        blob_reset(&sql);
        print_timeline(&q, nFindLimit, 79, 0);
        db_finalize(&q);
      }
    }
  }else

  if(( strncmp(g.argv[2],"list",n)==0 )||( strncmp(g.argv[2],"ls",n)==0 )){
    Stmt q;
    if( g.argc==3 ){
      db_prepare(&q,
        "SELECT tagname FROM tag"
        " WHERE EXISTS(SELECT 1 FROM tagxref"
        "               WHERE tagid=tag.tagid"
        "                 AND tagtype>0)"
        " ORDER BY tagname"
      );
      while( db_step(&q)==SQLITE_ROW ){
Changes to src/tar.c.
15
16
17
18
19
20
21




22

23
24
25
26
27
28
29
**
*******************************************************************************
**
** This file contains code used to generate tarballs.
*/
#include "config.h"
#include <assert.h>




#include <zlib.h>

#include "tar.h"

/*
** State information for the tarball builder.
*/
static struct tarball_t {
  unsigned char *aHdr;      /* Space for building headers */







>
>
>
>
|
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
**
*******************************************************************************
**
** This file contains code used to generate tarballs.
*/
#include "config.h"
#include <assert.h>
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif
#include "tar.h"

/*
** State information for the tarball builder.
*/
static struct tarball_t {
  unsigned char *aHdr;      /* Space for building headers */
485
486
487
488
489
490
491
492
493


494
495
496
497
498
499
500
  pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
  if( pManifest ){
    mTime = (pManifest->rDate - 2440587.5)*86400.0;
    tar_begin(mTime);
    if( db_get_boolean("manifest", 0) ){
      blob_append(&filename, "manifest", -1);
      zName = blob_str(&filename);
      tar_add_file(zName, &mfile, 0, mTime);
      sha1sum_blob(&mfile, &hash);


      blob_reset(&mfile);
      blob_append(&hash, "\n", 1);
      blob_resize(&filename, nPrefix);
      blob_append(&filename, "manifest.uuid", -1);
      zName = blob_str(&filename);
      tar_add_file(zName, &hash, 0, mTime);
      blob_reset(&hash);







<

>
>







490
491
492
493
494
495
496

497
498
499
500
501
502
503
504
505
506
  pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
  if( pManifest ){
    mTime = (pManifest->rDate - 2440587.5)*86400.0;
    tar_begin(mTime);
    if( db_get_boolean("manifest", 0) ){
      blob_append(&filename, "manifest", -1);
      zName = blob_str(&filename);

      sha1sum_blob(&mfile, &hash);
      sterilize_manifest(&mfile);
      tar_add_file(zName, &mfile, 0, mTime);
      blob_reset(&mfile);
      blob_append(&hash, "\n", 1);
      blob_resize(&filename, nPrefix);
      blob_append(&filename, "manifest.uuid", -1);
      zName = blob_str(&filename);
      tar_add_file(zName, &hash, 0, mTime);
      blob_reset(&hash);
524
525
526
527
528
529
530
531
532
533
534
535
536
537




538
539
540
541
542
543
544




545
546
547
548
549
550
551
  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME] [-R|--repository REPO]
**
** Generate a compressed tarball for a specified version.  If the --name
** option is used, its argument becomes the name of the top-level directory
** in the resulting tarball.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.




*/
void tarball_cmd(void){
  int rid;
  Blob tarball;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);




  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2], "ci");
  if( rid==0 ){
    fossil_fatal("Checkin not found: %s", g.argv[2]);
    return;







|






>
>
>
>







>
>
>
>







530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE
**
** Generate a compressed tarball for a specified version.  If the --name
** option is used, its argument becomes the name of the top-level directory
** in the resulting tarball.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** Options:
**   --name DIRECTORYNAME   The name of the top-level directory in the archive
**   -R REPOSITORY          Specify a Fossil repository
*/
void tarball_cmd(void){
  int rid;
  Blob tarball;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2], "ci");
  if( rid==0 ){
    fossil_fatal("Checkin not found: %s", g.argv[2]);
    return;
572
573
574
575
576
577
578
579
580


581
582
583
584
585
586
587
588
589
590
** URL: /tarball/RID.tar.gz
**
** Generate a compressed tarball for a checkin.
** Return that tarball as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=base name of the output file. Defaults to
** something project/version-specific.


**
** - uuid=the version to tar (may be a tag/branch name).
** Defaults to trunk.
**
*/
void tarball_page(void){
  int rid;
  char *zName, *zRid, *zKey;
  int nName, nRid;
  Blob tarball;







|
|
>
>


|







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
** URL: /tarball/RID.tar.gz
**
** Generate a compressed tarball for a checkin.
** Return that tarball as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=NAME[.tar.gz] is base name of the output file. Defaults to
** something project/version-specific. The prefix of the name, up to
** the last '.', are used as the top-most directory name in the tar
** output. 
**
** - uuid=the version to tar (may be a tag/branch name).
** Defaults to "trunk".
**
*/
void tarball_page(void){
  int rid;
  char *zName, *zRid, *zKey;
  int nName, nRid;
  Blob tarball;
612
613
614
615
616
617
618
619









620
621
622
623
624
625
626
627
628
629
630
  }
  rid = name_to_typed_rid(nRid?zRid:zName, "ci");
  if( rid==0 ){
    @ Not found
    return;
  }
  if( nRid==0 && nName>10 ) zName[10] = 0;
  zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);









  blob_zero(&tarball);
  if( cache_read(&tarball, zKey)==0 ){
    tarball_of_checkin(rid, &tarball, zName);
    cache_write(&tarball, zKey);
  }
  free( zName );
  free( zRid );
  free( zKey );
  cgi_set_content(&tarball);
  cgi_set_content_type("application/x-compressed");
}







|
>
>
>
>
>
>
>
>
>











628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  }
  rid = name_to_typed_rid(nRid?zRid:zName, "ci");
  if( rid==0 ){
    @ Not found
    return;
  }
  if( nRid==0 && nName>10 ) zName[10] = 0;
  zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q'"
                    "  FROM blob WHERE rid=%d",zName,rid);
  if( P("debug")!=0 ){
    style_header("Tarball Generator Debug Screen");
    @ zName = "%h(zName)"<br>
    @ rid = %d(rid)<br>
    @ zKey = "%h(zKey)"
    style_footer();
    return;
  }
  blob_zero(&tarball);
  if( cache_read(&tarball, zKey)==0 ){
    tarball_of_checkin(rid, &tarball, zName);
    cache_write(&tarball, zKey);
  }
  free( zName );
  free( zRid );
  free( zKey );
  cgi_set_content(&tarball);
  cgi_set_content_type("application/x-compressed");
}
Changes to src/th.c.
509
510
511
512
513
514
515

516
517
518
519
520
521

522
523
524
525
526
527
528
        case '[': if( nBrace==0 ) nSq++; break;
        case ']': if( nBrace==0 ) nSq--; break;
      }
      iEnd++;
    }
    if( nBrace>0 || nSq>0 ){
      /* Parse error */

      return TH_ERROR;
    }
  }

  if( iEnd>nInput ){
    /* Parse error */

    return TH_ERROR;
  }
  *pnWord = iEnd;
  return TH_OK;
}

/*







>






>







509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
        case '[': if( nBrace==0 ) nSq++; break;
        case ']': if( nBrace==0 ) nSq--; break;
      }
      iEnd++;
    }
    if( nBrace>0 || nSq>0 ){
      /* Parse error */
      Th_SetResult(interp, "parse error", -1);
      return TH_ERROR;
    }
  }

  if( iEnd>nInput ){
    /* Parse error */
    Th_SetResult(interp, "parse error", -1);
    return TH_ERROR;
  }
  *pnWord = iEnd;
  return TH_OK;
}

/*
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783
/*
** These two types are used only by the expression module, where
** the expression module means the Th_Expr() and exprXXX() functions.
*/
typedef struct Operator Operator;
struct Operator {
  const char *zOp;

  int eOp;
  int iPrecedence;
  int eArgType;
};
typedef struct Expr Expr;
struct Expr {
  Operator *pOp;







>







1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
/*
** These two types are used only by the expression module, where
** the expression module means the Th_Expr() and exprXXX() functions.
*/
typedef struct Operator Operator;
struct Operator {
  const char *zOp;
  int nOp;
  int eOp;
  int iPrecedence;
  int eArgType;
};
typedef struct Expr Expr;
struct Expr {
  Operator *pOp;
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
*/
#define ARG_INTEGER 1
#define ARG_NUMBER  2
#define ARG_STRING  3

static Operator aOperator[] = {

  {"(",  OP_OPEN_BRACKET,   -1, 0},
  {")",  OP_CLOSE_BRACKET, -1, 0},

  /* Note: all unary operators have (iPrecedence==1) */
  {"-",  OP_UNARY_MINUS,    1, ARG_NUMBER},
  {"+",  OP_UNARY_PLUS,     1, ARG_NUMBER},
  {"~",  OP_BITWISE_NOT,    1, ARG_INTEGER},
  {"!",  OP_LOGICAL_NOT,    1, ARG_INTEGER},

  /* Binary operators. It is important to the parsing in Th_Expr() that
   * the two-character symbols ("==") appear before the one-character
   * ones ("="). And that the priorities of all binary operators are
   * integers between 2 and 12.
   */
  {"<<", OP_LEFTSHIFT,      4, ARG_INTEGER},
  {">>", OP_RIGHTSHIFT,     4, ARG_INTEGER},
  {"<=", OP_LE,             5, ARG_NUMBER},
  {">=", OP_GE,             5, ARG_NUMBER},
  {"==", OP_EQ,             6, ARG_NUMBER},
  {"!=", OP_NE,             6, ARG_NUMBER},
  {"eq", OP_SEQ,            7, ARG_STRING},
  {"ne", OP_SNE,            7, ARG_STRING},
  {"&&", OP_LOGICAL_AND,   11, ARG_INTEGER},
  {"||", OP_LOGICAL_OR,    12, ARG_INTEGER},

  {"*",  OP_MULTIPLY,       2, ARG_NUMBER},
  {"/",  OP_DIVIDE,         2, ARG_NUMBER},
  {"%",  OP_MODULUS,        2, ARG_INTEGER},
  {"+",  OP_ADD,            3, ARG_NUMBER},
  {"-",  OP_SUBTRACT,       3, ARG_NUMBER},
  {"<",  OP_LT,             5, ARG_NUMBER},
  {">",  OP_GT,             5, ARG_NUMBER},
  {"&",  OP_BITWISE_AND,    8, ARG_INTEGER},
  {"^",  OP_BITWISE_XOR,    9, ARG_INTEGER},
  {"|",  OP_BITWISE_OR,    10, ARG_INTEGER},

  {0,0,0,0}
};

/*
** The first part of the string (zInput,nInput) contains an integer.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextInteger(







|
|


|
|
|
|






|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|







1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
*/
#define ARG_INTEGER 1
#define ARG_NUMBER  2
#define ARG_STRING  3

static Operator aOperator[] = {

  {"(",  1, OP_OPEN_BRACKET,   -1, 0},
  {")",  1, OP_CLOSE_BRACKET, -1, 0},

  /* Note: all unary operators have (iPrecedence==1) */
  {"-",  1, OP_UNARY_MINUS,    1, ARG_NUMBER},
  {"+",  1, OP_UNARY_PLUS,     1, ARG_NUMBER},
  {"~",  1, OP_BITWISE_NOT,    1, ARG_INTEGER},
  {"!",  1, OP_LOGICAL_NOT,    1, ARG_INTEGER},

  /* Binary operators. It is important to the parsing in Th_Expr() that
   * the two-character symbols ("==") appear before the one-character
   * ones ("="). And that the priorities of all binary operators are
   * integers between 2 and 12.
   */
  {"<<", 2, OP_LEFTSHIFT,      4, ARG_INTEGER},
  {">>", 2, OP_RIGHTSHIFT,     4, ARG_INTEGER},
  {"<=", 2, OP_LE,             5, ARG_NUMBER},
  {">=", 2, OP_GE,             5, ARG_NUMBER},
  {"==", 2, OP_EQ,             6, ARG_NUMBER},
  {"!=", 2, OP_NE,             6, ARG_NUMBER},
  {"eq", 2, OP_SEQ,            7, ARG_STRING},
  {"ne", 2, OP_SNE,            7, ARG_STRING},
  {"&&", 2, OP_LOGICAL_AND,   11, ARG_INTEGER},
  {"||", 2, OP_LOGICAL_OR,    12, ARG_INTEGER},

  {"*",  1, OP_MULTIPLY,       2, ARG_NUMBER},
  {"/",  1, OP_DIVIDE,         2, ARG_NUMBER},
  {"%",  1, OP_MODULUS,        2, ARG_INTEGER},
  {"+",  1, OP_ADD,            3, ARG_NUMBER},
  {"-",  1, OP_SUBTRACT,       3, ARG_NUMBER},
  {"<",  1, OP_LT,             5, ARG_NUMBER},
  {">",  1, OP_GT,             5, ARG_NUMBER},
  {"&",  1, OP_BITWISE_AND,    8, ARG_INTEGER},
  {"^",  1, OP_BITWISE_XOR,    9, ARG_INTEGER},
  {"|",  1, OP_BITWISE_OR,    10, ARG_INTEGER},

  {0,0,0,0,0}
};

/*
** The first part of the string (zInput,nInput) contains an integer.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextInteger(
2119
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
      }
    }
  }

  iLeft = 0;
  for(jj=nToken-1; jj>=0; jj--){
    if( apToken[jj] ){
      if( apToken[jj]->pOp && apToken[jj]->pOp->iPrecedence==1 && iLeft>0 ){

        apToken[jj]->pLeft = apToken[iLeft];
        apToken[jj]->pLeft->pParent = apToken[jj];
        apToken[iLeft] = 0;
      }
      iLeft = jj;
    }
  }
  for(i=2; i<=12; i++){
    iLeft = -1;
    for(jj=0; jj<nToken; jj++){
      Expr *pToken = apToken[jj];
      if( apToken[jj] ){
        if( pToken->pOp && !pToken->pLeft && pToken->pOp->iPrecedence==i ){
          int iRight = jj+1;

          iRight = jj+1;
          for(iRight=jj+1; !apToken[iRight] && iRight<nToken; iRight++);
          if( iRight==nToken || iLeft<0 || !ISTERM(iRight) || !ISTERM(iLeft) ){
            return TH_ERROR;
          }
          pToken->pLeft = apToken[iLeft];
          apToken[iLeft] = 0;
          pToken->pLeft->pParent = pToken;
          pToken->pRight = apToken[iRight];







|
>














<
<
|







2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144


2145
2146
2147
2148
2149
2150
2151
2152
      }
    }
  }

  iLeft = 0;
  for(jj=nToken-1; jj>=0; jj--){
    if( apToken[jj] ){
      if( apToken[jj]->pOp && apToken[jj]->pOp->iPrecedence==1
       && iLeft>0 && ISTERM(iLeft) ){
        apToken[jj]->pLeft = apToken[iLeft];
        apToken[jj]->pLeft->pParent = apToken[jj];
        apToken[iLeft] = 0;
      }
      iLeft = jj;
    }
  }
  for(i=2; i<=12; i++){
    iLeft = -1;
    for(jj=0; jj<nToken; jj++){
      Expr *pToken = apToken[jj];
      if( apToken[jj] ){
        if( pToken->pOp && !pToken->pLeft && pToken->pOp->iPrecedence==i ){
          int iRight = jj+1;


          for(; !apToken[iRight] && iRight<nToken; iRight++);
          if( iRight==nToken || iLeft<0 || !ISTERM(iRight) || !ISTERM(iLeft) ){
            return TH_ERROR;
          }
          pToken->pLeft = apToken[iLeft];
          apToken[iLeft] = 0;
          pToken->pLeft->pParent = pToken;
          pToken->pRight = apToken[iRight];
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184
2185
2186
2187
2188
  int nExpr,                /* Number of bytes at zExpr */
  Expr ***papToken,         /* OUT: Array of tokens. */
  int *pnToken              /* OUT: Size of token array */
){
  int i;

  int rc = TH_OK;

  int nToken = 0;
  Expr **apToken = 0;

  for(i=0; rc==TH_OK && i<nExpr; ){
    char c = zExpr[i];
    if( th_isspace(c) ){                                /* White-space     */
      i++;







>







2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
  int nExpr,                /* Number of bytes at zExpr */
  Expr ***papToken,         /* OUT: Array of tokens. */
  int *pnToken              /* OUT: Size of token array */
){
  int i;

  int rc = TH_OK;
  int nNest = 0;
  int nToken = 0;
  Expr **apToken = 0;

  for(i=0; rc==TH_OK && i<nExpr; ){
    char c = zExpr[i];
    if( th_isspace(c) ){                                /* White-space     */
      i++;
2219
2220
2221
2222
2223
2224
2225

2226
2227









2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
            pNew->nValue = iEnd+1-i;
          }
          break;
        }

        default: {
          int j;

          for(j=0; aOperator[j].zOp; j++){
            int nOp;









            if( aOperator[j].iPrecedence==1 && nToken>0 ){
              Expr *pPrev = apToken[nToken-1];
              if( !pPrev->pOp || pPrev->pOp->eOp==OP_CLOSE_BRACKET ){
                continue;
              }
            }
            nOp = th_strlen((const char *)aOperator[j].zOp);
            if( (nExpr-i)>=nOp && 0==memcmp(aOperator[j].zOp, &zExpr[i], nOp) ){
              pNew->pOp = &aOperator[j];
              i += nOp;
              break;
            }
          }
        }
      }







>
|
|
>
>
>
>
>
>
>
>
>
|





<
|







2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254
            pNew->nValue = iEnd+1-i;
          }
          break;
        }

        default: {
          int j;
          const char *zOp;
          for(j=0; (zOp=aOperator[j].zOp); j++){
            int nOp = aOperator[j].nOp;
            int isMatch = 0;
            if( (nExpr-i)>=nOp && 0==memcmp(zOp, &zExpr[i], nOp) ){
              isMatch = 1;
            }
            if( isMatch && aOperator[j].eOp==OP_OPEN_BRACKET ){
              nNest++;
            }else if( isMatch && aOperator[j].eOp==OP_CLOSE_BRACKET ){
              nNest--;
            }
            if( nToken>0 && aOperator[j].iPrecedence==1 ){
              Expr *pPrev = apToken[nToken-1];
              if( !pPrev->pOp || pPrev->pOp->eOp==OP_CLOSE_BRACKET ){
                continue;
              }
            }

            if( isMatch ){
              pNew->pOp = &aOperator[j];
              i += nOp;
              break;
            }
          }
        }
      }
2261
2262
2263
2264
2265
2266
2267




2268
2269
2270
2271
2272
2273
2274
        nToken++;
      }else{
        Th_Free(interp, pNew);
        rc = TH_ERROR;
      }
    }
  }





  *papToken = apToken;
  *pnToken = nToken;
  return rc;
}

/*







>
>
>
>







2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
        nToken++;
      }else{
        Th_Free(interp, pNew);
        rc = TH_ERROR;
      }
    }
  }

  if( nNest!=0 ){
    rc = TH_ERROR;
  }

  *papToken = apToken;
  *pnToken = nToken;
  return rc;
}

/*
Changes to src/th.h.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

#ifdef FOSSIL_ENABLE_TCL
/*
** Interfaces to the full Tcl core library from "th_tcl.c".
*/
int th_register_tcl(Th_Interp *, void *);
int unloadTcl(Th_Interp *, void *);
int evaluateTclWithEvents(Th_Interp *, void *, const char *, int, int);
#endif

/*
** General purpose hash table from th_lang.c.
*/
typedef struct Th_Hash      Th_Hash;
typedef struct Th_HashEntry Th_HashEntry;







|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

#ifdef FOSSIL_ENABLE_TCL
/*
** Interfaces to the full Tcl core library from "th_tcl.c".
*/
int th_register_tcl(Th_Interp *, void *);
int unloadTcl(Th_Interp *, void *);
int evaluateTclWithEvents(Th_Interp *, void *, const char *, int, int, int);
#endif

/*
** General purpose hash table from th_lang.c.
*/
typedef struct Th_Hash      Th_Hash;
typedef struct Th_HashEntry Th_HashEntry;
Changes to src/th_main.c.
26
27
28
29
30
31
32
33
34





35


36
37


























38
39
40
41
42
43
44
/*
** Flag parameters to the Th_FossilInit() routine used to control the
** interpreter creation and initialization process.
*/
#define TH_INIT_NONE        ((u32)0x00000000) /* No flags. */
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
#define TH_INIT_FORCE_TCL   ((u32)0x00000002) /* Force Tcl to be enabled? */
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH commands re-added? */
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */





#define TH_INIT_DEFAULT     (TH_INIT_NONE)    /* Default flags. */


#endif



























/*
** Global variable counting the number of outstanding calls to malloc()
** made by the th1 implementation. This is used to catch memory leaks
** in the interpreter. Obviously, it also means th1 is not threadsafe.
*/
static int nOutstandingMalloc = 0;








|

>
>
>
>
>
|
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
** Flag parameters to the Th_FossilInit() routine used to control the
** interpreter creation and initialization process.
*/
#define TH_INIT_NONE        ((u32)0x00000000) /* No flags. */
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
#define TH_INIT_FORCE_TCL   ((u32)0x00000002) /* Force Tcl to be enabled? */
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
#define TH_INIT_MASK        ((u32)0x0000000F) /* All possible init flags. */

/*
** Useful and/or "well-known" combinations of flag values.
*/
#define TH_INIT_DEFAULT     (TH_INIT_NONE)      /* Default flags. */
#define TH_INIT_HOOK        (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
#define TH_INIT_FORBID_MASK (TH_INIT_FORCE_TCL) /* Illegal from a script. */
#endif

/*
** Flags set by functions in this file to keep track of integration state
** information.  These flags should not be used outside of this file.
*/
#define TH_STATE_CONFIG     ((u32)0x00000010) /* We opened the config. */
#define TH_STATE_REPOSITORY ((u32)0x00000020) /* We opened the repository. */
#define TH_STATE_MASK       ((u32)0x00000030) /* All possible state flags. */

#ifdef FOSSIL_ENABLE_TH1_HOOKS
/*
** These are the "well-known" TH1 error messages that occur when no hook is
** registered to be called prior to executing a command or processing a web
** page, respectively.  If one of these errors is seen, it will not be sent
** or displayed to the remote user or local interactive user, respectively.
*/
#define NO_COMMAND_HOOK_ERROR "no such command:  command_hook"
#define NO_WEBPAGE_HOOK_ERROR "no such command:  webpage_hook"
#endif

/*
** These macros are used within this file to detect if the repository and
** configuration ("user") database are currently open.
*/
#define Th_IsRepositoryOpen()     (g.repositoryOpen)
#define Th_IsConfigOpen()         (g.zConfigDbName!=0)

/*
** Global variable counting the number of outstanding calls to malloc()
** made by the th1 implementation. This is used to catch memory leaks
** in the interpreter. Obviously, it also means th1 is not threadsafe.
*/
static int nOutstandingMalloc = 0;

72
73
74
75
76
77
78












79
80
81
82
83
84
85
*/
void Th_Trace(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  blob_vappendf(&g.thLog, zFormat, ap);
  va_end(ap);
}













/*
** Checks if the TH1 trace log needs to be enabled.  If so, prepares
** it for use.
*/
void Th_InitTraceLog(){
  g.thTrace = find_option("th-trace", 0, 0)!=0;







>
>
>
>
>
>
>
>
>
>
>
>







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
*/
void Th_Trace(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  blob_vappendf(&g.thLog, zFormat, ap);
  va_end(ap);
}

/*
** Forces input and output to be done via the CGI subsystem.
*/
void Th_ForceCgi(int fullHttpReply){
  g.httpOut = stdout;
  g.httpIn = stdin;
  fossil_binary_mode(g.httpOut);
  fossil_binary_mode(g.httpIn);
  g.cgiOutput = 1;
  g.fullHttpReply = fullHttpReply;
}

/*
** Checks if the TH1 trace log needs to be enabled.  If so, prepares
** it for use.
*/
void Th_InitTraceLog(){
  g.thTrace = find_option("th-trace", 0, 0)!=0;
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    fossil_print("\n------------------ BEGIN TRACE LOG ------------------\n");
    fossil_print("%s", blob_str(&g.thLog));
    fossil_print("\n------------------- END TRACE LOG -------------------\n");
  }
}

/*
** TH command:      httpize STRING
**
** Escape all characters of STRING which have special meaning in URI
** components. Return a new string result.
*/
static int httpizeCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  char *zOut;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "httpize STRING");
  }
  zOut = httpize((char*)argv[1], argl[1]);
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** True if output is enabled.  False if disabled.
*/
static int enableOutput = 1;

/*
** TH command:     enable_output BOOLEAN
**
** Enable or disable the puts and hputs commands.
*/
static int enableOutputCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int rc;
  if( argc<2 || argc>3 ){
    return Th_WrongNumArgs(interp, "enable_output [LABEL] BOOLEAN");
  }
  rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &enableOutput);
  if( g.thTrace ){
    Th_Trace("enable_output {%.*s} -> %d<br>\n", argl[1],argv[1],enableOutput);
  }
  return rc;
}

/*
** Return a name for a TH1 return code.
*/
const char *Th_ReturnCodeName(int rc, int nullIfOk){
  static char zRc[32];

  switch( rc ){
    case TH_OK:       return nullIfOk ? 0 : "TH_OK";
    case TH_ERROR:    return "TH_ERROR";
    case TH_BREAK:    return "TH_BREAK";
    case TH_RETURN:   return "TH_RETURN";
    case TH_CONTINUE: return "TH_CONTINUE";
    default: {
      sqlite3_snprintf(sizeof(zRc),zRc,"return code %d",rc);
    }
  }
  return zRc;
}

/*
** Send text to the appropriate output:  Either to the console







|





|
|
|
|


















|




|
|
|
|














|



>







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    fossil_print("\n------------------ BEGIN TRACE LOG ------------------\n");
    fossil_print("%s", blob_str(&g.thLog));
    fossil_print("\n------------------- END TRACE LOG -------------------\n");
  }
}

/*
** TH1 command: httpize STRING
**
** Escape all characters of STRING which have special meaning in URI
** components. Return a new string result.
*/
static int httpizeCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  char *zOut;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "httpize STRING");
  }
  zOut = httpize((char*)argv[1], argl[1]);
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** True if output is enabled.  False if disabled.
*/
static int enableOutput = 1;

/*
** TH1 command: enable_output BOOLEAN
**
** Enable or disable the puts and hputs commands.
*/
static int enableOutputCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int rc;
  if( argc<2 || argc>3 ){
    return Th_WrongNumArgs(interp, "enable_output [LABEL] BOOLEAN");
  }
  rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &enableOutput);
  if( g.thTrace ){
    Th_Trace("enable_output {%.*s} -> %d<br>\n", argl[1],argv[1],enableOutput);
  }
  return rc;
}

/*
** Returns a name for a TH1 return code.
*/
const char *Th_ReturnCodeName(int rc, int nullIfOk){
  static char zRc[32];

  switch( rc ){
    case TH_OK:       return nullIfOk ? 0 : "TH_OK";
    case TH_ERROR:    return "TH_ERROR";
    case TH_BREAK:    return "TH_BREAK";
    case TH_RETURN:   return "TH_RETURN";
    case TH_CONTINUE: return "TH_CONTINUE";
    default: {
      sqlite3_snprintf(sizeof(zRc), zRc, "TH1 return code %d", rc);
    }
  }
  return zRc;
}

/*
** Send text to the appropriate output:  Either to the console
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331


332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359










360
361
362
363
364
365
366
  sendText("ERROR: ", -1, 0);
  sendText((char*)z, n, 1);
  sendText(forceCgi || g.cgiOutput ? "</p>" : "\n", -1, 0);
  enableOutput = savedEnable;
}

/*
** TH command:     puts STRING
** TH command:     html STRING
**
** Output STRING escaped for HTML (html) or unchanged (puts).  
*/
static int putsCmd(
  Th_Interp *interp, 
  void *pConvert, 
  int argc, 
  const char **argv, 
  int *argl
){
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "puts STRING");
  }
  sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
  return TH_OK;
}

/*
** TH command:      wiki STRING
**
** Render the input string as wiki.
*/
static int wikiCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int flags = WIKI_INLINE | WIKI_NOBADLINKS | *(unsigned int*)p;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "wiki STRING");
  }
  if( enableOutput ){
    Blob src;
    blob_init(&src, (char*)argv[1], argl[1]);
    wiki_convert(&src, 0, flags);
    blob_reset(&src);
  }
  return TH_OK;
}

/*
** TH command:      htmlize STRING
**
** Escape all characters of STRING which have special meaning in HTML.
** Return a new string result.
*/
static int htmlizeCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  char *zOut;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "htmlize STRING");
  }
  zOut = htmlize((char*)argv[1], argl[1]);
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** TH command:      date
**
** Return a string which is the current time and date.  If the
** -local option is used, the date appears using localtime instead
** of UTC.
*/
static int dateCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  char *zOut;
  if( argc>=2 && argl[1]==6 && memcmp(argv[1],"-local",6)==0 ){
    zOut = db_text("??", "SELECT datetime('now'%s)", timeline_utc());
  }else{
    zOut = db_text("??", "SELECT datetime('now')");
  }
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** TH command:     hascap STRING...
**
** Return true if the user has all of the capabilities listed in STRING.
*/
static int hascapCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int rc = 0, i;
  if( argc<2 ){
    return Th_WrongNumArgs(interp, "hascap STRING ...");
  }
  for(i=1; i<argc && rc==0; i++){
    rc = login_has_capability((char*)argv[i],argl[i]);
  }
  if( g.thTrace ){
    Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}

/*
** TH command:     hasfeature STRING
**
** Return true if the fossil binary has the given compile-time feature
** enabled. The set of features includes:
**
** "ssl"             = FOSSIL_ENABLE_SSL


** "tcl"             = FOSSIL_ENABLE_TCL
** "useTclStubs"     = USE_TCL_STUBS
** "tclStubs"        = FOSSIL_ENABLE_TCL_STUBS
** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
** "json"            = FOSSIL_ENABLE_JSON
** "markdown"        = FOSSIL_ENABLE_MARKDOWN
**
*/
static int hasfeatureCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int rc = 0;
  char const * zArg;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "hasfeature STRING");
  }
  zArg = (char const*)argv[1];
  if(NULL==zArg){
    /* placeholder for following ifdefs... */
  }
#if defined(FOSSIL_ENABLE_SSL)
  else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
    rc = 1;
  }










#endif
#if defined(FOSSIL_ENABLE_TCL)
  else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
    rc = 1;
  }
#endif
#if defined(USE_TCL_STUBS)







|
|

|


|
|
|
|










|




|
|
|
|
















|





|
|
|
|













|






|
|
|
|














|




|
|
|
|

















|





>
>









|
|
|
|















>
>
>
>
>
>
>
>
>
>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  sendText("ERROR: ", -1, 0);
  sendText((char*)z, n, 1);
  sendText(forceCgi || g.cgiOutput ? "</p>" : "\n", -1, 0);
  enableOutput = savedEnable;
}

/*
** TH1 command: puts STRING
** TH1 command: html STRING
**
** Output STRING escaped for HTML (html) or unchanged (puts).
*/
static int putsCmd(
  Th_Interp *interp,
  void *pConvert,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "puts STRING");
  }
  sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
  return TH_OK;
}

/*
** TH1 command: wiki STRING
**
** Render the input string as wiki.
*/
static int wikiCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int flags = WIKI_INLINE | WIKI_NOBADLINKS | *(unsigned int*)p;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "wiki STRING");
  }
  if( enableOutput ){
    Blob src;
    blob_init(&src, (char*)argv[1], argl[1]);
    wiki_convert(&src, 0, flags);
    blob_reset(&src);
  }
  return TH_OK;
}

/*
** TH1 command: htmlize STRING
**
** Escape all characters of STRING which have special meaning in HTML.
** Return a new string result.
*/
static int htmlizeCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  char *zOut;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "htmlize STRING");
  }
  zOut = htmlize((char*)argv[1], argl[1]);
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** TH1 command: date
**
** Return a string which is the current time and date.  If the
** -local option is used, the date appears using localtime instead
** of UTC.
*/
static int dateCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  char *zOut;
  if( argc>=2 && argl[1]==6 && memcmp(argv[1],"-local",6)==0 ){
    zOut = db_text("??", "SELECT datetime('now'%s)", timeline_utc());
  }else{
    zOut = db_text("??", "SELECT datetime('now')");
  }
  Th_SetResult(interp, zOut, -1);
  free(zOut);
  return TH_OK;
}

/*
** TH1 command: hascap STRING...
**
** Return true if the user has all of the capabilities listed in STRING.
*/
static int hascapCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int rc = 0, i;
  if( argc<2 ){
    return Th_WrongNumArgs(interp, "hascap STRING ...");
  }
  for(i=1; i<argc && rc==0; i++){
    rc = login_has_capability((char*)argv[i],argl[i]);
  }
  if( g.thTrace ){
    Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}

/*
** TH1 command: hasfeature STRING
**
** Return true if the fossil binary has the given compile-time feature
** enabled. The set of features includes:
**
** "ssl"             = FOSSIL_ENABLE_SSL
** "th1Docs"         = FOSSIL_ENABLE_TH1_DOCS
** "th1Hooks"        = FOSSIL_ENABLE_TH1_HOOKS
** "tcl"             = FOSSIL_ENABLE_TCL
** "useTclStubs"     = USE_TCL_STUBS
** "tclStubs"        = FOSSIL_ENABLE_TCL_STUBS
** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
** "json"            = FOSSIL_ENABLE_JSON
** "markdown"        = FOSSIL_ENABLE_MARKDOWN
**
*/
static int hasfeatureCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int rc = 0;
  char const * zArg;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "hasfeature STRING");
  }
  zArg = (char const*)argv[1];
  if(NULL==zArg){
    /* placeholder for following ifdefs... */
  }
#if defined(FOSSIL_ENABLE_SSL)
  else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
    rc = 1;
  }
#endif
#if defined(FOSSIL_ENABLE_TH1_DOCS)
  else if( 0 == fossil_strnicmp( zArg, "th1Docs\0", 8 ) ){
    rc = 1;
  }
#endif
#if defined(FOSSIL_ENABLE_TH1_HOOKS)
  else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){
    rc = 1;
  }
#endif
#if defined(FOSSIL_ENABLE_TCL)
  else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
    rc = 1;
  }
#endif
#if defined(USE_TCL_STUBS)
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}


/*
** TH command:     tclReady
**
** Return true if the fossil binary has the Tcl integration feature
** enabled and it is currently available for use by TH1 scripts.
**
*/
static int tclReadyCmd(
  Th_Interp *interp,







|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}


/*
** TH1 command: tclReady
**
** Return true if the fossil binary has the Tcl integration feature
** enabled and it is currently available for use by TH1 scripts.
**
*/
static int tclReadyCmd(
  Th_Interp *interp,
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}


/*
** TH command:     anycap STRING
**
** Return true if the user has any one of the capabilities listed in STRING.
*/
static int anycapCmd(
  Th_Interp *interp, 
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int rc = 0;
  int i;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "anycap STRING");
  }
  for(i=0; rc==0 && i<argl[1]; i++){
    rc = login_has_capability((char*)&argv[1][i],1);
  }
  if( g.thTrace ){
    Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}

/*
** TH1 command:  combobox NAME TEXT-LIST NUMLINES
**
** Generate an HTML combobox.  NAME is both the name of the
** CGI parameter and the name of a variable that contains the
** currently selected value.  TEXT-LIST is a list of possible
** values for the combobox.  NUMLINES is 1 for a true combobox.
** If NUMLINES is greater than one then the display is a listbox
** with the number of lines given.
*/
static int comboboxCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  if( argc!=4 ){
    return Th_WrongNumArgs(interp, "combobox NAME TEXT-LIST NUMLINES");
  }
  if( enableOutput ){
    int height;







|




|
|
|
|


















|










|
|
|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}


/*
** TH1 command: anycap STRING
**
** Return true if the user has any one of the capabilities listed in STRING.
*/
static int anycapCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int rc = 0;
  int i;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "anycap STRING");
  }
  for(i=0; rc==0 && i<argl[1]; i++){
    rc = login_has_capability((char*)&argv[1][i],1);
  }
  if( g.thTrace ){
    Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
  }
  Th_SetResultInt(interp, rc);
  return TH_OK;
}

/*
** TH1 command: combobox NAME TEXT-LIST NUMLINES
**
** Generate an HTML combobox.  NAME is both the name of the
** CGI parameter and the name of a variable that contains the
** currently selected value.  TEXT-LIST is a list of possible
** values for the combobox.  NUMLINES is 1 for a true combobox.
** If NUMLINES is greater than one then the display is a listbox
** with the number of lines given.
*/
static int comboboxCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=4 ){
    return Th_WrongNumArgs(interp, "combobox NAME TEXT-LIST NUMLINES");
  }
  if( enableOutput ){
    int height;
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    z = mprintf("<select id=\"%s\" name=\"%s\" size=\"%d\">", zH, zH, height);
    free(zH);
    sendText(z, -1, 0);
    free(z);
    blob_reset(&name);
    for(i=0; i<nElem; i++){
      zH = htmlize((char*)azElem[i], aszElem[i]);
      if( zValue && aszElem[i]==nValue 
             && memcmp(zValue, azElem[i], nValue)==0 ){
        z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>",
                     zH, zH);
      }else{
        z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
      }
      free(zH);
      sendText(z, -1, 0);
      free(z);
    }
    sendText("</select>", -1, 0);
    Th_Free(interp, azElem);
  }
  return TH_OK;
}

/*
** TH1 command:     linecount STRING MAX MIN
**
** Return one more than the number of \n characters in STRING.  But
** never return less than MIN or more than MAX.
*/
static int linecntCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  const char *z;
  int size, n, i;
  int iMin, iMax;
  if( argc!=4 ){
    return Th_WrongNumArgs(interp, "linecount STRING MAX MIN");







|

















|






|
|
|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
    z = mprintf("<select id=\"%s\" name=\"%s\" size=\"%d\">", zH, zH, height);
    free(zH);
    sendText(z, -1, 0);
    free(z);
    blob_reset(&name);
    for(i=0; i<nElem; i++){
      zH = htmlize((char*)azElem[i], aszElem[i]);
      if( zValue && aszElem[i]==nValue
             && memcmp(zValue, azElem[i], nValue)==0 ){
        z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>",
                     zH, zH);
      }else{
        z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
      }
      free(zH);
      sendText(z, -1, 0);
      free(z);
    }
    sendText("</select>", -1, 0);
    Th_Free(interp, azElem);
  }
  return TH_OK;
}

/*
** TH1 command: linecount STRING MAX MIN
**
** Return one more than the number of \n characters in STRING.  But
** never return less than MIN or more than MAX.
*/
static int linecntCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  const char *z;
  int size, n, i;
  int iMin, iMax;
  if( argc!=4 ){
    return Th_WrongNumArgs(interp, "linecount STRING MAX MIN");
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576


















































































































































































































































































































577
578
579
580
581
582
583
  if( n<iMin ) n = iMin;
  if( n>iMax ) n = iMax;
  Th_SetResultInt(interp, n);
  return TH_OK;
}

/*
** TH1 command:     repository ?BOOLEAN?
**
** Return the fully qualified file name of the open repository or an empty
** string if one is not currently open.  Optionally, it will attempt to open
** the repository if the boolean argument is non-zero.
*/
static int repositoryCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
  }
  if( argc==2 ){
    int openRepository = 0;
    if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){
      return TH_ERROR;
    }
    if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
  }
  Th_SetResult(interp, g.zRepositoryName, -1);
  return TH_OK;
}



















































































































































































































































































































#ifdef _WIN32
# include <windows.h>
#else
# include <sys/time.h>
# include <sys/resource.h>
#endif







|







|
|
|















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  if( n<iMin ) n = iMin;
  if( n>iMax ) n = iMax;
  Th_SetResultInt(interp, n);
  return TH_OK;
}

/*
** TH1 command: repository ?BOOLEAN?
**
** Return the fully qualified file name of the open repository or an empty
** string if one is not currently open.  Optionally, it will attempt to open
** the repository if the boolean argument is non-zero.
*/
static int repositoryCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
  }
  if( argc==2 ){
    int openRepository = 0;
    if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){
      return TH_ERROR;
    }
    if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
  }
  Th_SetResult(interp, g.zRepositoryName, -1);
  return TH_OK;
}

/*
** TH1 command: checkout ?BOOLEAN?
**
** Return the fully qualified directory name of the current checkout or an
** empty string if it is not available.  Optionally, it will attempt to find
** the current checkout, opening the configuration ("user") database and the
** repository as necessary, if the boolean argument is non-zero.
*/
static int checkoutCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "checkout ?BOOLEAN?");
  }
  if( argc==2 ){
    int openCheckout = 0;
    if( Th_ToInt(interp, argv[1], argl[1], &openCheckout) ){
      return TH_ERROR;
    }
    if( openCheckout ) db_open_local(0);
  }
  Th_SetResult(interp, g.zLocalRoot, -1);
  return TH_OK;
}

/*
** TH1 command: trace STRING
**
** Generate a TH1 trace message if debugging is enabled.
*/
static int traceCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "trace STRING");
  }
  if( g.thTrace ){
    Th_Trace("%s", argv[1]);
  }
  Th_SetResult(interp, 0, 0);
  return TH_OK;
}

/*
** TH1 command: globalState NAME ?DEFAULT?
**
** Returns a string containing the value of the specified global state
** variable -OR- the specified default value.  Currently, the supported
** items are:
**
** "checkout"        = The active local checkout directory, if any.
** "configuration"   = The active configuration database file name,
**                     if any.
** "executable"      = The fully qualified executable file name.
** "flags"           = The TH1 initialization flags.
** "log"             = The error log file name, if any.
** "repository"      = The active local repository file name, if
**                     any.
** "top"             = The base path for the active server instance,
**                     if applicable.
** "user"            = The active user name, if any.
** "vfs"             = The SQLite VFS in use, if overridden.
**
** Attempts to query for unsupported global state variables will result
** in a script error.  Additional global state variables may be exposed
** in the future.
**
** See also: checkout, repository, setting
*/
static int globalStateCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  const char *zDefault = 0;
  if( argc!=2 && argc!=3 ){
    return Th_WrongNumArgs(interp, "globalState NAME ?DEFAULT?");
  }
  if( argc==3 ){
    zDefault = argv[2];
  }
  if( fossil_strnicmp(argv[1], "checkout\0", 9)==0 ){
    Th_SetResult(interp, g.zLocalRoot ? g.zLocalRoot : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "configuration\0", 14)==0 ){
    Th_SetResult(interp, g.zConfigDbName ? g.zConfigDbName : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "executable\0", 11)==0 ){
    Th_SetResult(interp, g.nameOfExe ? g.nameOfExe : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "flags\0", 6)==0 ){
    Th_SetResultInt(interp, g.th1Flags);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "log\0", 4)==0 ){
    Th_SetResult(interp, g.zErrlog ? g.zErrlog : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "repository\0", 11)==0 ){
    Th_SetResult(interp, g.zRepositoryName ? g.zRepositoryName : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "top\0", 4)==0 ){
    Th_SetResult(interp, g.zTop ? g.zTop : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "user\0", 5)==0 ){
    Th_SetResult(interp, g.zLogin ? g.zLogin : zDefault, -1);
    return TH_OK;
  }else if( fossil_strnicmp(argv[1], "vfs\0", 4)==0 ){
    Th_SetResult(interp, g.zVfsName ? g.zVfsName : zDefault, -1);
    return TH_OK;
  }else{
    Th_ErrorMessage(interp, "unsupported global state:", argv[1], argl[1]);
    return TH_ERROR;
  }
}

/*
** TH1 command: getParameter NAME ?DEFAULT?
**
** Return the value of the specified query parameter or the specified default
** value when there is no matching query parameter.
*/
static int getParameterCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  const char *zDefault = 0;
  if( argc!=2 && argc!=3 ){
    return Th_WrongNumArgs(interp, "getParameter NAME ?DEFAULT?");
  }
  if( argc==3 ){
    zDefault = argv[2];
  }
  Th_SetResult(interp, cgi_parameter(argv[1], zDefault), -1);
  return TH_OK;
}

/*
** TH1 command: setParameter NAME VALUE
**
** Sets the value of the specified query parameter.
*/
static int setParameterCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=3 ){
    return Th_WrongNumArgs(interp, "setParameter NAME VALUE");
  }
  cgi_replace_parameter(mprintf("%s", argv[1]), mprintf("%s", argv[2]));
  return TH_OK;
}

/*
** TH1 command: reinitialize ?FLAGS?
**
** Reinitializes the TH1 interpreter using the specified flags.
*/
static int reinitializeCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  u32 flags = TH_INIT_DEFAULT;
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "reinitialize ?FLAGS?");
  }
  if( argc==2 ){
    int iFlags;
    if( Th_ToInt(interp, argv[1], argl[1], &iFlags) ){
      return TH_ERROR;
    }else{
      flags = (u32)iFlags;
    }
  }
  Th_FossilInit(flags & ~TH_INIT_FORBID_MASK);
  Th_SetResult(interp, 0, 0);
  return TH_OK;
}

/*
** TH1 command: render STRING
**
** Renders the template and writes the results.
*/
static int renderCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int rc;
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "render STRING");
  }
  rc = Th_Render(argv[1]);
  Th_SetResult(interp, 0, 0);
  return rc;
}

/*
** TH1 command: styleHeader TITLE
**
** Render the configured style header.
*/
static int styleHeaderCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=2 ){
    return Th_WrongNumArgs(interp, "styleHeader TITLE");
  }
  if( Th_IsRepositoryOpen() ){
    style_header("%s", argv[1]);
    Th_SetResult(interp, 0, 0);
    return TH_OK;
  }else{
    Th_SetResult(interp, "repository unavailable", -1);
    return TH_ERROR;
  }
}

/*
** TH1 command: styleFooter
**
** Render the configured style footer.
*/
static int styleFooterCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=1 ){
    return Th_WrongNumArgs(interp, "styleFooter");
  }
  if( Th_IsRepositoryOpen() ){
    style_footer();
    Th_SetResult(interp, 0, 0);
    return TH_OK;
  }else{
    Th_SetResult(interp, "repository unavailable", -1);
    return TH_ERROR;
  }
}

/*
** TH1 command: artifact ID ?FILENAME?
**
** Attempts to locate the specified artifact and return its contents.  An
** error is generated if the repository is not open or the artifact cannot
** be found.
*/
static int artifactCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  if( argc!=2 && argc!=3 ){
    return Th_WrongNumArgs(interp, "artifact ID ?FILENAME?");
  }
  if( Th_IsRepositoryOpen() ){
    int rid;
    Blob content;
    if( argc==3 ){
      rid = artifact_from_ci_and_filename(argv[1], argv[2]);
    }else{
      rid = name_to_rid(argv[1]);
    }
    if( rid!=0 && content_get(rid, &content) ){
      Th_SetResult(interp, blob_str(&content), blob_size(&content));
      blob_reset(&content);
      return TH_OK;
    }else{
      Th_SetResult(interp, "artifact not found", -1);
      return TH_ERROR;
    }
  }else{
    Th_SetResult(interp, "repository unavailable", -1);
    return TH_ERROR;
  }
}

#ifdef _WIN32
# include <windows.h>
#else
# include <sys/time.h>
# include <sys/resource.h>
#endif
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
#else
  struct rusage s;
  getrusage(RUSAGE_SELF, &s);
  if( piUser ){
    *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
  }
  if( piKernel ){
    *piKernel = 
              ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
  }
#endif
}

/*
** TH1 command:     utime
**
** Return the number of microseconds of CPU time consumed by the current
** process in user space.
*/
static int utimeCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  sqlite3_uint64 x;
  char zUTime[50];
  getCpuTimes(&x, 0);
  sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
  Th_SetResult(interp, zUTime, -1);
  return TH_OK;
}

/*
** TH1 command:     stime
**
** Return the number of microseconds of CPU time consumed by the current
** process in system space.
*/
static int stimeCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  sqlite3_uint64 x;
  char zUTime[50];
  getCpuTimes(0, &x);
  sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
  Th_SetResult(interp, zUTime, -1);
  return TH_OK;
}


/*
** TH1 command:     randhex  N
**
** Return N*2 random hexadecimal digits with N<50.  If N is omitted, 
** use a value of 10.
*/
static int randhexCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  int n;
  unsigned char aRand[50];
  unsigned char zOut[100];
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");







|






|






|
|
|











|






|
|
|












|

|




|
|
|







967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
#else
  struct rusage s;
  getrusage(RUSAGE_SELF, &s);
  if( piUser ){
    *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
  }
  if( piKernel ){
    *piKernel =
              ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
  }
#endif
}

/*
** TH1 command: utime
**
** Return the number of microseconds of CPU time consumed by the current
** process in user space.
*/
static int utimeCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  sqlite3_uint64 x;
  char zUTime[50];
  getCpuTimes(&x, 0);
  sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
  Th_SetResult(interp, zUTime, -1);
  return TH_OK;
}

/*
** TH1 command: stime
**
** Return the number of microseconds of CPU time consumed by the current
** process in system space.
*/
static int stimeCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  sqlite3_uint64 x;
  char zUTime[50];
  getCpuTimes(0, &x);
  sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
  Th_SetResult(interp, zUTime, -1);
  return TH_OK;
}


/*
** TH1 command: randhex  N
**
** Return N*2 random hexadecimal digits with N<50.  If N is omitted,
** use a value of 10.
*/
static int randhexCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  int n;
  unsigned char aRand[50];
  unsigned char zOut[100];
  if( argc!=1 && argc!=2 ){
    return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  sqlite3_randomness(n, aRand);
  encode16(aRand, zOut, n);
  Th_SetResult(interp, (const char *)zOut, -1);
  return TH_OK;
}

/*
** TH1 command:     query SQL CODE
**
** Run the SQL query given by the SQL argument.  For each row in the result
** set, run CODE.
**
** In SQL, parameters such as $var are filled in using the value of variable
** "var".  Result values are stored in variables with the column name prior
** to each invocation of CODE.
*/
static int queryCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  sqlite3_stmt *pStmt;
  int rc;
  const char *zSql;
  int nSql;
  const char *zTail;







|










|
|
|







1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  sqlite3_randomness(n, aRand);
  encode16(aRand, zOut, n);
  Th_SetResult(interp, (const char *)zOut, -1);
  return TH_OK;
}

/*
** TH1 command: query SQL CODE
**
** Run the SQL query given by the SQL argument.  For each row in the result
** set, run CODE.
**
** In SQL, parameters such as $var are filled in using the value of variable
** "var".  Result values are stored in variables with the column name prior
** to each invocation of CODE.
*/
static int queryCmd(
  Th_Interp *interp,
  void *p,
  int argc,
  const char **argv,
  int *argl
){
  sqlite3_stmt *pStmt;
  int rc;
  const char *zSql;
  int nSql;
  const char *zTail;
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
      if( res==TH_BREAK || res==TH_CONTINUE ) res = TH_OK;
    }
    rc = sqlite3_finalize(pStmt);
    if( rc!=SQLITE_OK ){
      Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
      return TH_ERROR;
    }
  } 
  return res;
}

/*
** TH1 command:     setting name
**
** Gets and returns the value of the specified Fossil setting.
*/
#define SETTING_WRONGNUMARGS "setting ?-strict? ?--? name"
static int settingCmd(
  Th_Interp *interp,
  void *p,







|




|







1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
      if( res==TH_BREAK || res==TH_CONTINUE ) res = TH_OK;
    }
    rc = sqlite3_finalize(pStmt);
    if( rc!=SQLITE_OK ){
      Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
      return TH_ERROR;
    }
  }
  return res;
}

/*
** TH1 command: setting name
**
** Gets and returns the value of the specified Fossil setting.
*/
#define SETTING_WRONGNUMARGS "setting ?-strict? ?--? name"
static int settingCmd(
  Th_Interp *interp,
  void *p,
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
    Th_Trace("[setting %s%#h] => %d<br />\n", strict ? "strict " : "",
             argl[nArg], argv[nArg], rc);
  }
  return rc;
}

/*
** TH1 command:     regexp ?-nocase? ?--? exp string
**
** Checks the string against the specified regular expression and returns
** non-zero if it matches.  If the regular expression is invalid or cannot
** be compiled, an error will be generated.
*/
#define REGEXP_WRONGNUMARGS "regexp ?-nocase? ?--? exp string"
static int regexpCmd(







|







1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
    Th_Trace("[setting %s%#h] => %d<br />\n", strict ? "strict " : "",
             argl[nArg], argv[nArg], rc);
  }
  return rc;
}

/*
** TH1 command: regexp ?-nocase? ?--? exp string
**
** Checks the string against the specified regular expression and returns
** non-zero if it matches.  If the regular expression is invalid or cannot
** be compiled, an error will be generated.
*/
#define REGEXP_WRONGNUMARGS "regexp ?-nocase? ?--? exp string"
static int regexpCmd(
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
    rc = TH_ERROR;
  }
  re_free(pRe);
  return rc;
}

/*
** TH command:      http ?-asynchronous? ?--? url ?payload?
**
** Perform an HTTP or HTTPS request for the specified URL.  If a
** payload is present, it will be interpreted as text/plain and
** the POST method will be used; otherwise, the GET method will
** be used.  Upon success, if the -asynchronous option is used, an
** empty string is returned as the result; otherwise, the response
** from the server is returned as the result.  Synchronous requests







|







1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
    rc = TH_ERROR;
  }
  re_free(pRe);
  return rc;
}

/*
** TH1 command: http ?-asynchronous? ?--? url ?payload?
**
** Perform an HTTP or HTTPS request for the specified URL.  If a
** payload is present, it will be interpreted as text/plain and
** the POST method will be used; otherwise, the GET method will
** be used.  Upon success, if the -asynchronous option is used, an
** empty string is returned as the result; otherwise, the response
** from the server is returned as the result.  Synchronous requests
969
970
971
972
973
974
975










































976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995


996
997
998
999


1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010


1011

1012


1013

1014
1015
1016
1017
1018



1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
  }else{
    Th_ErrorMessage(interp,
        "synchronous requests are not yet implemented", 0, 0);
    blob_reset(&payload);
    return TH_ERROR;
  }
}











































/*
** Make sure the interpreter has been initialized.  Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/
void Th_FossilInit(u32 flags){
  int wasInit = 0;
  int needConfig = flags & TH_INIT_NEED_CONFIG;
  int forceReset = flags & TH_INIT_FORCE_RESET;
  int forceTcl = flags & TH_INIT_FORCE_TCL;
  int forceSetup = flags & TH_INIT_FORCE_SETUP;
  static unsigned int aFlags[] = { 0, 1, WIKI_LINKSONLY };
  static struct _Command {
    const char *zName;
    Th_CommandProc xProc;
    void *pContext;
  } aCommand[] = {
    {"anycap",        anycapCmd,            0},


    {"combobox",      comboboxCmd,          0},
    {"date",          dateCmd,              0},
    {"decorate",      wikiCmd,              (void*)&aFlags[2]},
    {"enable_output", enableOutputCmd,      0},


    {"httpize",       httpizeCmd,           0},
    {"hascap",        hascapCmd,            0},
    {"hasfeature",    hasfeatureCmd,        0},
    {"html",          putsCmd,              (void*)&aFlags[0]},
    {"htmlize",       htmlizeCmd,           0},
    {"http",          httpCmd,              0},
    {"linecount",     linecntCmd,           0},
    {"puts",          putsCmd,              (void*)&aFlags[1]},
    {"query",         queryCmd,             0},
    {"randhex",       randhexCmd,           0},
    {"regexp",        regexpCmd,            0},


    {"repository",    repositoryCmd,        0},

    {"setting",       settingCmd,           0},


    {"tclReady",      tclReadyCmd,          0},

    {"stime",         stimeCmd,             0},
    {"utime",         utimeCmd,             0},
    {"wiki",          wikiCmd,              (void*)&aFlags[0]},
    {0, 0, 0}
  };



  if( needConfig ){
    /*
    ** This function uses several settings which may be defined in the
    ** repository and/or the global configuration.  Since the caller
    ** passed a non-zero value for the needConfig parameter, make sure
    ** the necessary database connections are open prior to continuing.
    */
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp(&vtab);
      created = 1;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















>
>




>
>











>
>

>

>
>

>





>
>
>







<
|







1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
  }else{
    Th_ErrorMessage(interp,
        "synchronous requests are not yet implemented", 0, 0);
    blob_reset(&payload);
    return TH_ERROR;
  }
}

/*
** Attempts to open the configuration ("user") database.  Optionally, also
** attempts to try to find the repository and open it.
*/
void Th_OpenConfig(
  int openRepository
){
  if( openRepository && !Th_IsRepositoryOpen() ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    if( Th_IsRepositoryOpen() ){
      g.th1Flags |= TH_STATE_REPOSITORY;
    }else{
      g.th1Flags &= ~TH_STATE_REPOSITORY;
    }
  }
  if( !Th_IsConfigOpen() ){
    db_open_config(0);
    if( Th_IsConfigOpen() ){
      g.th1Flags |= TH_STATE_CONFIG;
    }else{
      g.th1Flags &= ~TH_STATE_CONFIG;
    }
  }
}

/*
** Attempts to close the configuration ("user") database.  Optionally, also
** attempts to close the repository.
*/
void Th_CloseConfig(
  int closeRepository
){
  if( g.th1Flags & TH_STATE_CONFIG ){
    db_close_config();
    g.th1Flags &= ~TH_STATE_CONFIG;
  }
  if( closeRepository && (g.th1Flags & TH_STATE_REPOSITORY) ){
    db_close(1);
    g.th1Flags &= ~TH_STATE_REPOSITORY;
  }
}

/*
** Make sure the interpreter has been initialized.  Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/
void Th_FossilInit(u32 flags){
  int wasInit = 0;
  int needConfig = flags & TH_INIT_NEED_CONFIG;
  int forceReset = flags & TH_INIT_FORCE_RESET;
  int forceTcl = flags & TH_INIT_FORCE_TCL;
  int forceSetup = flags & TH_INIT_FORCE_SETUP;
  static unsigned int aFlags[] = { 0, 1, WIKI_LINKSONLY };
  static struct _Command {
    const char *zName;
    Th_CommandProc xProc;
    void *pContext;
  } aCommand[] = {
    {"anycap",        anycapCmd,            0},
    {"artifact",      artifactCmd,          0},
    {"checkout",      checkoutCmd,          0},
    {"combobox",      comboboxCmd,          0},
    {"date",          dateCmd,              0},
    {"decorate",      wikiCmd,              (void*)&aFlags[2]},
    {"enable_output", enableOutputCmd,      0},
    {"getParameter",  getParameterCmd,      0},
    {"globalState",   globalStateCmd,       0},
    {"httpize",       httpizeCmd,           0},
    {"hascap",        hascapCmd,            0},
    {"hasfeature",    hasfeatureCmd,        0},
    {"html",          putsCmd,              (void*)&aFlags[0]},
    {"htmlize",       htmlizeCmd,           0},
    {"http",          httpCmd,              0},
    {"linecount",     linecntCmd,           0},
    {"puts",          putsCmd,              (void*)&aFlags[1]},
    {"query",         queryCmd,             0},
    {"randhex",       randhexCmd,           0},
    {"regexp",        regexpCmd,            0},
    {"reinitialize",  reinitializeCmd,      0},
    {"render",        renderCmd,            0},
    {"repository",    repositoryCmd,        0},
    {"setParameter",  setParameterCmd,      0},
    {"setting",       settingCmd,           0},
    {"styleHeader",   styleHeaderCmd,       0},
    {"styleFooter",   styleFooterCmd,       0},
    {"tclReady",      tclReadyCmd,          0},
    {"trace",         traceCmd,             0},
    {"stime",         stimeCmd,             0},
    {"utime",         utimeCmd,             0},
    {"wiki",          wikiCmd,              (void*)&aFlags[0]},
    {0, 0, 0}
  };
  if( g.thTrace ){
    Th_Trace("th1-init 0x%x => 0x%x<br />\n", g.th1Flags, flags);
  }
  if( needConfig ){
    /*
    ** This function uses several settings which may be defined in the
    ** repository and/or the global configuration.  Since the caller
    ** passed a non-zero value for the needConfig parameter, make sure
    ** the necessary database connections are open prior to continuing.
    */

    Th_OpenConfig(1);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp(&vtab);
      created = 1;
1067
1068
1069
1070
1071
1072
1073


1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087












































1088
1089
1090
1091
1092
1093
1094
      }
    }
    if( g.thTrace ){
      Th_Trace("th1-setup {%h} => %h<br />\n", g.th1Setup,
               Th_ReturnCodeName(rc, 0));
    }
  }


}

/*
** Store a string value in a variable in the interpreter.
*/
void Th_Store(const char *zName, const char *zValue){
  Th_FossilInit(TH_INIT_DEFAULT);
  if( zValue ){
    if( g.thTrace ){
      Th_Trace("set %h {%h}<br />\n", zName, zValue);
    }
    Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
  }
}













































/*
** Store an integer value in a variable in the interpreter.
*/
void Th_StoreInt(const char *zName, int iValue){
  Blob value;
  char *zValue;







>
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
      }
    }
    if( g.thTrace ){
      Th_Trace("th1-setup {%h} => %h<br />\n", g.th1Setup,
               Th_ReturnCodeName(rc, 0));
    }
  }
  g.th1Flags &= ~TH_INIT_MASK;
  g.th1Flags |= (flags & TH_INIT_MASK);
}

/*
** Store a string value in a variable in the interpreter.
*/
void Th_Store(const char *zName, const char *zValue){
  Th_FossilInit(TH_INIT_DEFAULT);
  if( zValue ){
    if( g.thTrace ){
      Th_Trace("set %h {%h}<br />\n", zName, zValue);
    }
    Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
  }
}

/*
** Appends an element to a TH1 list value.  This function is called by the
** transfer subsystem; therefore, it must be very careful to avoid doing
** any unnecessary work.  To that end, the TH1 subsystem will not be called
** or initialized if the list pointer is zero (i.e. which will be the case
** when TH1 transfer hooks are disabled).
*/
void Th_AppendToList(
  char **pzList,
  int *pnList,
  const char *zElem,
  int nElem
){
  if( pzList && zElem ){
    Th_FossilInit(TH_INIT_DEFAULT);
    Th_ListAppend(g.interp, pzList, pnList, zElem, nElem);
  }
}

/*
** Stores a list value in the specified TH1 variable using the specified
** array of strings as the source of the element values.
*/
void Th_StoreList(
  const char *zName,
  char **pzList,
  int nList
){
  Th_FossilInit(TH_INIT_DEFAULT);
  if( pzList ){
    char *zValue = 0;
    int nValue = 0;
    int i;
    for(i=0; i<nList; i++){
      Th_ListAppend(g.interp, &zValue, &nValue, pzList[i], -1);
    }
    if( g.thTrace ){
      Th_Trace("set %h {%h}<br />\n", zName, zValue);
    }
    Th_SetVar(g.interp, zName, -1, zValue, nValue);
    Th_Free(g.interp, zValue);
  }
}

/*
** Store an integer value in a variable in the interpreter.
*/
void Th_StoreInt(const char *zName, int iValue){
  Blob value;
  char *zValue;
1179
1180
1181
1182
1183
1184
1185

1186






















































































































































































1187
1188
1189
1190
1191
1192
1193
1194
1195
  if( inBracket ){
    if( z[0]!='>' ) return 0;
    i += 2;
  }
  return i;
}


/*






















































































































































































** The z[] input contains text mixed with TH1 scripts.
** The TH1 scripts are contained within <th1>...</th1>. 
** TH1 variables are $aaa or $<aaa>.  The first form of
** variable is literal.  The second is run through htmlize
** before being inserted.
**
** This routine processes the template and writes the results
** on either stdout or into CGI.
*/







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
  if( inBracket ){
    if( z[0]!='>' ) return 0;
    i += 2;
  }
  return i;
}

#ifdef FOSSIL_ENABLE_TH1_HOOKS
/*
** This function determines if TH1 hooks are enabled for the repository.  It
** may be necessary to open the repository and/or the configuration ("user")
** database from within this function.  Before this function returns, any
** database opened will be closed again.  This is very important because some
** commands do not expect the repository and/or the configuration ("user")
** database to be open prior to their own code doing so.
*/
int Th_AreHooksEnabled(void){
  int rc;
  if( fossil_getenv("TH1_ENABLE_HOOKS")!=0 ){
    return 1;
  }
  Th_OpenConfig(1);
  rc = db_get_boolean("th1-hooks", 0);
  Th_CloseConfig(1);
  return rc;
}

/*
** This function is called by Fossil just prior to dispatching a command.
** Returning a value other than TH_OK from this function (i.e. via an
** evaluated script raising an error or calling [break]/[continue]) will
** cause the actual command execution to be skipped.
*/
int Th_CommandHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  if( !Th_AreHooksEnabled() ) return rc;
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);
    /*
    ** Make sure that the TH1 script error was not caused by a "missing"
    ** command hook handler as that is not actually an error condition.
    */
    if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
      sendError(zResult, nResult, 0);
    }
  }
  /*
  ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
  ** not exist because commands are not being hooked), return TH_OK because we
  ** do not want to skip executing essential commands unless the called command
  ** (i.e. "command_hook") explicitly forbids this by successfully returning
  ** TH_BREAK or TH_CONTINUE.
  */
  if( g.thTrace ){
    Th_Trace("[command_hook {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
  }
  /*
  ** Does our call to Th_FossilInit() result in opening a database?  If so,
  ** clean it up now.  This is very important because some commands do not
  ** expect the repository and/or the configuration ("user") database to be
  ** open prior to their own code doing so.
  */
  if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
  return (rc != TH_ERROR) ? rc : TH_OK;
}

/*
** This function is called by Fossil just after dispatching a command.
** Returning a value other than TH_OK from this function (i.e. via an
** evaluated script raising an error or calling [break]/[continue]) may
** cause an error message to be displayed to the local interactive user.
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_CommandNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  if( !Th_AreHooksEnabled() ) return rc;
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_notify", -1);
  if( g.thTrace ){
    Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
  }
  /*
  ** Does our call to Th_FossilInit() result in opening a database?  If so,
  ** clean it up now.  This is very important because some commands do not
  ** expect the repository and/or the configuration ("user") database to be
  ** open prior to their own code doing so.
  */
  if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
  return rc;
}

/*
** This function is called by Fossil just prior to processing a web page.
** Returning a value other than TH_OK from this function (i.e. via an
** evaluated script raising an error or calling [break]/[continue]) will
** cause the actual web page processing to be skipped.
*/
int Th_WebpageHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  if( !Th_AreHooksEnabled() ) return rc;
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);
    /*
    ** Make sure that the TH1 script error was not caused by a "missing"
    ** webpage hook handler as that is not actually an error condition.
    */
    if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
      sendError(zResult, nResult, 1);
    }
  }
  /*
  ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
  ** not exist because commands are not being hooked), return TH_OK because we
  ** do not want to skip processing essential web pages unless the called
  ** command (i.e. "webpage_hook") explicitly forbids this by successfully
  ** returning TH_BREAK or TH_CONTINUE.
  */
  if( g.thTrace ){
    Th_Trace("[webpage_hook {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
  }
  /*
  ** Does our call to Th_FossilInit() result in opening a database?  If so,
  ** clean it up now.  This is very important because some commands do not
  ** expect the repository and/or the configuration ("user") database to be
  ** open prior to their own code doing so.
  */
  if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
  return (rc != TH_ERROR) ? rc : TH_OK;
}

/*
** This function is called by Fossil just after processing a web page.
** Returning a value other than TH_OK from this function (i.e. via an
** evaluated script raising an error or calling [break]/[continue]) may
** cause an error message to be displayed to the remote user.
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_WebpageNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  if( !Th_AreHooksEnabled() ) return rc;
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
  if( g.thTrace ){
    Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
  }
  /*
  ** Does our call to Th_FossilInit() result in opening a database?  If so,
  ** clean it up now.  This is very important because some commands do not
  ** expect the repository and/or the configuration ("user") database to be
  ** open prior to their own code doing so.
  */
  if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
  return rc;
}
#endif

/*
** The z[] input contains text mixed with TH1 scripts.
** The TH1 scripts are contained within <th1>...</th1>.
** TH1 variables are $aaa or $<aaa>.  The first form of
** variable is literal.  The second is run through htmlize
** before being inserted.
**
** This routine processes the template and writes the results
** on either stdout or into CGI.
*/
1245
1246
1247
1248
1249
1250
1251

1252
1253



1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267
1268
1269
1270
1271
1272

1273



1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286






































  return rc;
}

/*
** COMMAND: test-th-render
*/
void test_th_render(void){

  Blob in;
  Th_InitTraceLog();



  if( find_option("th-open-config", 0, 0)!=0 ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( g.argc<3 ){
    usage("FILE");
  }
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
  Th_PrintTraceLog();

}

/*
** COMMAND: test-th-eval
*/
void test_th_eval(void){
  int rc;
  const char *zRc;

  Th_InitTraceLog();



  if( find_option("th-open-config", 0, 0)!=0 ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( g.argc!=3 ){
    usage("script");
  }
  Th_FossilInit(TH_INIT_DEFAULT);
  rc = Th_Eval(g.interp, 0, g.argv[2], -1);
  zRc = Th_ReturnCodeName(rc, 1);
  fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
  Th_PrintTraceLog();

}













































>


>
>
>

<
|








>








>

>
>
>

<
|









>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929

1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
  return rc;
}

/*
** COMMAND: test-th-render
*/
void test_th_render(void){
  int forceCgi, fullHttpReply;
  Blob in;
  Th_InitTraceLog();
  forceCgi = find_option("th-force-cgi", 0, 0)!=0;
  fullHttpReply = find_option("th-full-http", 0, 0)!=0;
  if( forceCgi ) Th_ForceCgi(fullHttpReply);
  if( find_option("th-open-config", 0, 0)!=0 ){

    Th_OpenConfig(1);
  }
  if( g.argc<3 ){
    usage("FILE");
  }
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
  Th_PrintTraceLog();
  if( forceCgi ) cgi_reply();
}

/*
** COMMAND: test-th-eval
*/
void test_th_eval(void){
  int rc;
  const char *zRc;
  int forceCgi, fullHttpReply;
  Th_InitTraceLog();
  forceCgi = find_option("th-force-cgi", 0, 0)!=0;
  fullHttpReply = find_option("th-full-http", 0, 0)!=0;
  if( forceCgi ) Th_ForceCgi(fullHttpReply);
  if( find_option("th-open-config", 0, 0)!=0 ){

    Th_OpenConfig(1);
  }
  if( g.argc!=3 ){
    usage("script");
  }
  Th_FossilInit(TH_INIT_DEFAULT);
  rc = Th_Eval(g.interp, 0, g.argv[2], -1);
  zRc = Th_ReturnCodeName(rc, 1);
  fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
  Th_PrintTraceLog();
  if( forceCgi ) cgi_reply();
}

#ifdef FOSSIL_ENABLE_TH1_HOOKS
/*
** COMMAND: test-th-hook
*/
void test_th_hook(void){
  int rc = TH_OK;
  int nResult = 0;
  char *zResult;
  int forceCgi, fullHttpReply;
  Th_InitTraceLog();
  forceCgi = find_option("th-force-cgi", 0, 0)!=0;
  fullHttpReply = find_option("th-full-http", 0, 0)!=0;
  if( forceCgi ) Th_ForceCgi(fullHttpReply);
  if( g.argc<5 ){
    usage("TYPE NAME FLAGS");
  }
  if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){
    rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4]));
  }else if( fossil_stricmp(g.argv[2], "cmdnotify")==0 ){
    rc = Th_CommandNotify(g.argv[3], (char)atoi(g.argv[4]));
  }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
    rc = Th_WebpageHook(g.argv[3], (char)atoi(g.argv[4]));
  }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
    rc = Th_WebpageNotify(g.argv[3], (char)atoi(g.argv[4]));
  }else{
    fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
  }
  zResult = (char*)Th_GetResult(g.interp, &nResult);
  sendText("RESULT (", -1, 0);
  sendText(Th_ReturnCodeName(rc, 0), -1, 0);
  sendText("): ", -1, 0);
  sendText(zResult, nResult, 0);
  sendText("\n", -1, 0);
  Th_PrintTraceLog();
  if( forceCgi ) cgi_reply();
}
#endif
Changes to src/th_tcl.c.
18
19
20
21
22
23
24

25
26
27
28
29
30
31
**
** This file contains code used to bridge the TH1 and Tcl scripting languages.
*/
#include "config.h"

#ifdef FOSSIL_ENABLE_TCL


#include "th.h"
#include "tcl.h"

/*
** These macros are designed to reduce the redundant code required to marshal
** arguments from TH1 to Tcl.
*/







>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
**
** This file contains code used to bridge the TH1 and Tcl scripting languages.
*/
#include "config.h"

#ifdef FOSSIL_ENABLE_TCL

#include "sqlite3.h"
#include "th.h"
#include "tcl.h"

/*
** These macros are designed to reduce the redundant code required to marshal
** arguments from TH1 to Tcl.
*/
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
*/
#if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)
/*
** HACK: Using some preprocessor magic and a private static variable, redirect
**       the Tcl API calls [found within this file] to the function pointers
**       that will be contained in our private Tcl stubs table.  This takes
**       advantage of the fact that the Tcl headers always define the Tcl API
**       functions in terms of the "tclStubsPtr" variable.

*/
#define tclStubsPtr privateTclStubsPtr
static const TclStubs *tclStubsPtr = NULL;

/*
** Create a Tcl interpreter structure that mirrors just enough fields to get
** it up and running successfully with our private implementation of the Tcl







|
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
*/
#if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)
/*
** HACK: Using some preprocessor magic and a private static variable, redirect
**       the Tcl API calls [found within this file] to the function pointers
**       that will be contained in our private Tcl stubs table.  This takes
**       advantage of the fact that the Tcl headers always define the Tcl API
**       functions in terms of the "tclStubsPtr" variable when the define
**       USE_TCL_STUBS is present during compilation.
*/
#define tclStubsPtr privateTclStubsPtr
static const TclStubs *tclStubsPtr = NULL;

/*
** Create a Tcl interpreter structure that mirrors just enough fields to get
** it up and running successfully with our private implementation of the Tcl
246
247
248
249
250
251
252






















253
254
255
256
257
258
259
/*
** Creates and initializes a Tcl interpreter for use with the specified TH1
** interpreter.  Stores the created Tcl interpreter in the Tcl context supplied
** by the caller.  This must be declared here because quite a few functions in
** this file need to use it before it can be defined.
*/
static int createTclInterp(Th_Interp *interp, void *pContext);























/*
** Returns the Tcl interpreter result as a string with the associated length.
** If the Tcl interpreter or the Tcl result are NULL, the length will be 0.
** If the length pointer is NULL, the length will not be stored.
*/
static char *getTclResult(







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
** Creates and initializes a Tcl interpreter for use with the specified TH1
** interpreter.  Stores the created Tcl interpreter in the Tcl context supplied
** by the caller.  This must be declared here because quite a few functions in
** this file need to use it before it can be defined.
*/
static int createTclInterp(Th_Interp *interp, void *pContext);

/*
** Returns a name for a Tcl return code.
*/
static const char *getTclReturnCodeName(
  int rc,
  int nullIfOk
){
  static char zRc[32];

  switch( rc ){
    case TCL_OK:       return nullIfOk ? 0 : "TCL_OK";
    case TCL_ERROR:    return "TCL_ERROR";
    case TCL_BREAK:    return "TCL_BREAK";
    case TCL_RETURN:   return "TCL_RETURN";
    case TCL_CONTINUE: return "TCL_CONTINUE";
    default: {
      sqlite3_snprintf(sizeof(zRc), zRc, "Tcl return code %d", rc);
    }
  }
  return zRc;
}

/*
** Returns the Tcl interpreter result as a string with the associated length.
** If the Tcl interpreter or the Tcl result are NULL, the length will be 0.
** If the length pointer is NULL, the length will not be stored.
*/
static char *getTclResult(
772
773
774
775
776
777
778


779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
794
795
796







797
798
799
800
801
802
803
/*
** Evaluate a Tcl script, creating the Tcl interpreter if necessary. If the
** Tcl script succeeds, start a Tcl event loop until there are no more events
** remaining to process -OR- the script calls [exit].  If the bWait argument
** is zero, only process events that are already in the queue; otherwise,
** process events until the script terminates the Tcl event loop.
*/


int evaluateTclWithEvents(
  Th_Interp *interp,
  void *pContext,
  const char *zScript,
  int nScript,
  int bWait

){
  struct TclContext *tclContext = (struct TclContext *)pContext;
  Tcl_Interp *tclInterp;
  int rc;
  int flags = TCL_ALL_EVENTS;

  if( createTclInterp(interp, pContext)!=TH_OK ){
    return TH_ERROR;
  }
  tclInterp = tclContext->interp;
  rc = Tcl_EvalEx(tclInterp, zScript, nScript, TCL_EVAL_GLOBAL);
  if( rc!=TCL_OK ) return rc;







  if( !bWait ) flags |= TCL_DONT_WAIT;
  while( Tcl_DoOneEvent(flags) ){
    /* do nothing */
  }
  return rc;
}








>
>





|
>











|
>
>
>
>
>
>
>







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
/*
** Evaluate a Tcl script, creating the Tcl interpreter if necessary. If the
** Tcl script succeeds, start a Tcl event loop until there are no more events
** remaining to process -OR- the script calls [exit].  If the bWait argument
** is zero, only process events that are already in the queue; otherwise,
** process events until the script terminates the Tcl event loop.
*/
void fossil_print(const char *zFormat, ...); /* printf.h */

int evaluateTclWithEvents(
  Th_Interp *interp,
  void *pContext,
  const char *zScript,
  int nScript,
  int bWait,
  int bVerbose
){
  struct TclContext *tclContext = (struct TclContext *)pContext;
  Tcl_Interp *tclInterp;
  int rc;
  int flags = TCL_ALL_EVENTS;

  if( createTclInterp(interp, pContext)!=TH_OK ){
    return TH_ERROR;
  }
  tclInterp = tclContext->interp;
  rc = Tcl_EvalEx(tclInterp, zScript, nScript, TCL_EVAL_GLOBAL);
  if( rc!=TCL_OK ){
    if( bVerbose ){
      const char *zResult = getTclResult(tclInterp, 0);
      fossil_print("%s: ", getTclReturnCodeName(rc, 0));
      fossil_print("%s\n", zResult);
    }
    return rc;
  }
  if( !bWait ) flags |= TCL_DONT_WAIT;
  while( Tcl_DoOneEvent(flags) ){
    /* do nothing */
  }
  return rc;
}

Changes to src/timeline.c.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
** This file contains code to implement the timeline web page
**
*/
#include "config.h"
#include <string.h>
#include <time.h>
#include "timeline.h"

/*
** Shorten a UUID so that is the minimum length needed to contain
** at least one digit in the range 'a'..'f'.  The minimum length is 10.
*/
static void shorten_uuid(char *zDest, const char *zSrc){
  int i;
  for(i=0; i<10 && zSrc[i]<='9'; i++){}
  memcpy(zDest, zSrc, 10);
  if( i==10 && zSrc[i] ){
    do{
      zDest[i] = zSrc[i];
      i++;
    }while( zSrc[i-1]<='9' );
  }else{
    i = 10;
  }
  zDest[i] = 0;
}


/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
  char z[UUID_SIZE+1];
  shorten_uuid(z, zUuid);
  if( g.perm.Hyperlink ){
    @ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%s(z)]</a>
  }else{
    @ <span class="timelineHistDsp">[%s(z)]</span>
  }
}

/*
** Generate a hyperlink to a date & time.
*/
void hyperlink_to_date(const char *zDate, const char *zSuffix){







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





<
<

|

|







18
19
20
21
22
23
24




















25
26
27
28
29


30
31
32
33
34
35
36
37
38
39
40
** This file contains code to implement the timeline web page
**
*/
#include "config.h"
#include <string.h>
#include <time.h>
#include "timeline.h"





















/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){


  if( g.perm.Hyperlink ){
    @ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%S(zUuid)]</a>
  }else{
    @ <span class="timelineHistDsp">[%S(zUuid)]</span>
  }
}

/*
** Generate a hyperlink to a date & time.
*/
void hyperlink_to_date(const char *zDate, const char *zSuffix){
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
**    n=COUNT        max number of events in output
**    p=UUID         artifact and up to COUNT parents and ancestors
**    d=UUID         artifact and up to COUNT descendants
**    dp=UUID        The same as d=UUID&p=UUID
**    t=TAGID        show only check-ins with the given tagid
**    r=TAGID        show check-ins related to tagid
**    u=USER         only if belonging to this user
**    y=TYPE         'ci', 'w', 't', 'e'
**    s=TEXT         string search (comment and brief)
**    ng             Suppress the graph if present
**    nd             Suppress "divider" lines
**    v              Show details of files changed
**    f=UUID         Show family (immediate parents and children) of UUID
**    from=UUID      Path from...
**    to=UUID          ... to this
**    nomerge          ... avoid merge links on the path

**    uf=FUUID       Show only checkins that use given file version
**    brbg           Background color from branch name
**    ubg            Background color from user
**    namechng       Show only checkins that filename changes
**    ym=YYYY-MM     Shown only events for the given year/month.
**
** p= and d= can appear individually or together.  If either p= or d=







|








>







994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
**    n=COUNT        max number of events in output
**    p=UUID         artifact and up to COUNT parents and ancestors
**    d=UUID         artifact and up to COUNT descendants
**    dp=UUID        The same as d=UUID&p=UUID
**    t=TAGID        show only check-ins with the given tagid
**    r=TAGID        show check-ins related to tagid
**    u=USER         only if belonging to this user
**    y=TYPE         'ci', 'w', 't', 'e', or (default) 'all'
**    s=TEXT         string search (comment and brief)
**    ng             Suppress the graph if present
**    nd             Suppress "divider" lines
**    v              Show details of files changed
**    f=UUID         Show family (immediate parents and children) of UUID
**    from=UUID      Path from...
**    to=UUID          ... to this
**    nomerge          ... avoid merge links on the path
**    shortest         ... show only the shortest path
**    uf=FUUID       Show only checkins that use given file version
**    brbg           Background color from branch name
**    ubg            Background color from user
**    namechng       Show only checkins that filename changes
**    ym=YYYY-MM     Shown only events for the given year/month.
**
** p= and d= can appear individually or together.  If either p= or d=
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237












1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258






1259
1260
1261
1262
1263
1264
1265
      if( np>0 ){
        if( nd>0 ) blob_appendf(&desc, " and ");
        blob_appendf(&desc, "%d ancestors", np);
        db_multi_exec("%s", blob_str(&sql));
      }
      if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
    }
    blob_appendf(&desc, " of %z[%.10s]</a>",
                   href("%R/info/%s", zUuid), zUuid);
    if( (tmFlags & TIMELINE_UNHIDE)==0 ){
      if( p_rid ){
        url_add_parameter(&url, "p", zUuid);
      }
      if( d_rid ){
        if( p_rid ){
          /* If both p= and d= are set, we don't have the uuid of d yet. */
          zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
        }
        url_add_parameter(&url, "d", zUuid);
      }












      timeline_submenu(&url, "Unhide", "unhide", "", 0);
    }
  }else if( f_rid && g.perm.Read ){
    /* If f= is present, ignore all other parameters other than n= */
    char *zUuid;
    db_multi_exec(
       "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
       "INSERT INTO ok VALUES(%d);"
       "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
       "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
       f_rid, f_rid, f_rid
    );
    blob_appendf(&sql, " AND event.objid IN ok");
    db_multi_exec("%s", blob_str(&sql));
    if( useDividers ) timeline_add_dividers(0, f_rid);
    blob_appendf(&desc, "Parents and children of check-in ");
    zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
    blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid);
    tmFlags |= TIMELINE_DISJOINT;
    if( (tmFlags & TIMELINE_UNHIDE)==0 ){
      url_add_parameter(&url, "f", zUuid);






      timeline_submenu(&url, "Unhide", "unhide", "", 0);
    }
  }else{
    /* Otherwise, a timeline based on a span of time */
    int n;
    const char *zEType = "timeline item";
    char *zDate;







|

<
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>

















|

<
|
>
>
>
>
>
>







1197
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
      if( np>0 ){
        if( nd>0 ) blob_appendf(&desc, " and ");
        blob_appendf(&desc, "%d ancestors", np);
        db_multi_exec("%s", blob_str(&sql));
      }
      if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
    }
    blob_appendf(&desc, " of %z[%S]</a>",
                   href("%R/info/%s", zUuid), zUuid);

    if( p_rid ){
      url_add_parameter(&url, "p", zUuid);
    }
    if( d_rid ){
      if( p_rid ){
        /* If both p= and d= are set, we don't have the uuid of d yet. */
        zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
      }
      url_add_parameter(&url, "d", zUuid);
    }
    if( nEntry>20 ){
      timeline_submenu(&url, "20 Entries", "n", "20", 0);
    }
    if( nEntry<200 ){
      timeline_submenu(&url, "200 Entries", "n", "200", 0);
    }
    if( tmFlags & TIMELINE_FCHANGES ){
      timeline_submenu(&url, "Hide Files", "v", 0, 0);
    }else{
      timeline_submenu(&url, "Show Files", "v", "", 0);
    }
    if( (tmFlags & TIMELINE_UNHIDE)==0 ){
      timeline_submenu(&url, "Unhide", "unhide", "", 0);
    }
  }else if( f_rid && g.perm.Read ){
    /* If f= is present, ignore all other parameters other than n= */
    char *zUuid;
    db_multi_exec(
       "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
       "INSERT INTO ok VALUES(%d);"
       "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
       "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
       f_rid, f_rid, f_rid
    );
    blob_appendf(&sql, " AND event.objid IN ok");
    db_multi_exec("%s", blob_str(&sql));
    if( useDividers ) timeline_add_dividers(0, f_rid);
    blob_appendf(&desc, "Parents and children of check-in ");
    zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
    blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%s", zUuid), zUuid);
    tmFlags |= TIMELINE_DISJOINT;

    url_add_parameter(&url, "f", zUuid);
    if( tmFlags & TIMELINE_FCHANGES ){
      timeline_submenu(&url, "Hide Files", "v", 0, 0);
    }else{
      timeline_submenu(&url, "Show Files", "v", "", 0);
    }
    if( (tmFlags & TIMELINE_UNHIDE)==0 ){
      timeline_submenu(&url, "Unhide", "unhide", "", 0);
    }
  }else{
    /* Otherwise, a timeline based on a span of time */
    int n;
    const char *zEType = "timeline item";
    char *zDate;
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
    }
    if( zUser ){
      blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
                   zUser, zUser);
      url_add_parameter(&url, "u", zUser);
      zThisUser = zUser;
    }
    if ( zSearch ){
      blob_appendf(&sql,
        " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
        zSearch, zSearch);
      url_add_parameter(&url, "s", zSearch);
    }
    rBefore = symbolic_name_to_mtime(zBefore);
    rAfter = symbolic_name_to_mtime(zAfter);







|







1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
    }
    if( zUser ){
      blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
                   zUser, zUser);
      url_add_parameter(&url, "u", zUser);
      zThisUser = zUser;
    }
    if( zSearch ){
      blob_appendf(&sql,
        " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
        zSearch, zSearch);
      url_add_parameter(&url, "s", zSearch);
    }
    rBefore = symbolic_name_to_mtime(zBefore);
    rAfter = symbolic_name_to_mtime(zAfter);
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
    const char *zDate = db_column_text(q, 2);
    const char *zCom = db_column_text(q, 3);
    int nChild = db_column_int(q, 4);
    int nParent = db_column_int(q, 5);
    char *zFree = 0;
    int n = 0;
    char zPrefix[80];
    char zUuid[UUID_SIZE+1];

    if( nAbsLimit!=0 ){
      if( nLimit<0 && nLine>=nAbsLimit ){
        fossil_print("--- line limit (%d) reached ---\n", nAbsLimit);
        break; /* line count limit hit, stop. */
      }else if( nEntry>=nAbsLimit ){
        fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
        break; /* entry count limit hit, stop. */
      }
    }
    sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
    if( fossil_strnicmp(zDate, zPrevDate, 10) ){
      fossil_print("=== %.10s ===\n", zDate);
      memcpy(zPrevDate, zDate, 10);
      nLine++; /* record another line */
    }
    if( zCom==0 ) zCom = "";
    fossil_print("%.8s ", &zDate[11]);







<










<







1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
    const char *zDate = db_column_text(q, 2);
    const char *zCom = db_column_text(q, 3);
    int nChild = db_column_int(q, 4);
    int nParent = db_column_int(q, 5);
    char *zFree = 0;
    int n = 0;
    char zPrefix[80];


    if( nAbsLimit!=0 ){
      if( nLimit<0 && nLine>=nAbsLimit ){
        fossil_print("--- line limit (%d) reached ---\n", nAbsLimit);
        break; /* line count limit hit, stop. */
      }else if( nEntry>=nAbsLimit ){
        fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
        break; /* entry count limit hit, stop. */
      }
    }

    if( fossil_strnicmp(zDate, zPrevDate, 10) ){
      fossil_print("=== %.10s ===\n", zDate);
      memcpy(zPrevDate, zDate, 10);
      nLine++; /* record another line */
    }
    if( zCom==0 ) zCom = "";
    fossil_print("%.8s ", &zDate[11]);
1607
1608
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType);
      n = strlen(zPrefix);
    }
    if( fossil_strcmp(zCurrentUuid,zId)==0 ){
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
      n += strlen(zPrefix);
    }
    zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
    nLine += comment_print(zFree, 9, width); /* record another X lines */

    sqlite3_free(zFree);

    if(verboseFlag){
      if( !fchngQueryInit ){
        db_prepare(&fchngQuery,
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
           "       (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"







|
|
>
|







1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType);
      n = strlen(zPrefix);
    }
    if( fossil_strcmp(zCurrentUuid,zId)==0 ){
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
      n += strlen(zPrefix);
    }
    zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
    /* record another X lines */
    nLine += comment_print(zFree, zCom, 9, width, g.comFmtFlags);
    fossil_free(zFree);

    if(verboseFlag){
      if( !fchngQueryInit ){
        db_prepare(&fchngQuery,
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
           "       (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
1735
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
1750
**                            ci = file commits only
**                            e  = events only
**                            t  = tickets only
**                            w  = wiki commits only
**   -v|--verbose         Output the list of files changed by each commit
**                        and the type of each change (edited, deleted,
**                        etc.) after the checkin comment.
**   -W|--width <num>     With of lines (default 79). Must be >20 or 0

**                        (= no limit, resulting in a single line per entry).
**   -R REPO_FILE         Specifies the repository db to use. Default is
**                        the current checkout's repository.
*/
void timeline_cmd(void){
  Stmt q;
  int n, k, width;
  const char *zLimit;







|
>
|







1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
**                            ci = file commits only
**                            e  = events only
**                            t  = tickets only
**                            w  = wiki commits only
**   -v|--verbose         Output the list of files changed by each commit
**                        and the type of each change (edited, deleted,
**                        etc.) after the checkin comment.
**   -W|--width <num>     Width of lines (default is to auto-detect). Must be
**                        >20 or 0 (= no limit, resulting in a single line per
**                        entry).
**   -R REPO_FILE         Specifies the repository db to use. Default is
**                        the current checkout's repository.
*/
void timeline_cmd(void){
  Stmt q;
  int n, k, width;
  const char *zLimit;
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788




1789
1790
1791
1792
1793
1794
1795
  if( !verboseFlag){
    verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
  }
  db_find_and_open_repository(0, 0);
  zLimit = find_option("limit","n",1);
  zWidth = find_option("width","W",1);
  zType = find_option("type","t",1);
  if ( !zLimit ){
    zLimit = find_option("count",0,1);
  }
  if( zLimit ){
    n = atoi(zLimit);
  }else{
    n = -20;
  }
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = 79;
  }
  zOffset = find_option("offset",0,1);
  iOffset = zOffset ? atoi(zOffset) : 0;




  if( g.argc>=4 ){
    k = strlen(g.argv[2]);
    if( strncmp(g.argv[2],"before",k)==0 ){
      mode = 1;
    }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
      mode = 2;
    }else if( strncmp(g.argv[2],"descendants",k)==0 ){







|













|



>
>
>
>







1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
  if( !verboseFlag){
    verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
  }
  db_find_and_open_repository(0, 0);
  zLimit = find_option("limit","n",1);
  zWidth = find_option("width","W",1);
  zType = find_option("type","t",1);
  if( !zLimit ){
    zLimit = find_option("count",0,1);
  }
  if( zLimit ){
    n = atoi(zLimit);
  }else{
    n = -20;
  }
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = -1;
  }
  zOffset = find_option("offset",0,1);
  iOffset = zOffset ? atoi(zOffset) : 0;

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc>=4 ){
    k = strlen(g.argv[2]);
    if( strncmp(g.argv[2],"before",k)==0 ){
      mode = 1;
    }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
      mode = 2;
    }else if( strncmp(g.argv[2],"descendants",k)==0 ){
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
*/
static int statsReportType = 0;

/*
** Set by stats_report_init_view() to one of the y=XXXX values
** accepted by /timeline?y=XXXX.
*/
static char const * statsReportTimelineYFlag = NULL;

/*
** Creates a TEMP VIEW named v_reports which is a wrapper around the
** EVENT table filtered on event.type. It looks for the request
** parameter 'type' (reminder: we "should" use 'y' for consistency
** with /timeline, but /reports uses 'y' for the year) and expects it
** to contain one of the conventional values from event.type or the
** value "all", which is treated as equivalent to "*".  By default (if
** no 'y' is specified), "*" is assumed (that is also the default for
** invalid/unknown filter values). That 'y' filter is the one used for
** the event list. Note that a filter of "*" or "all" is equivalent to
** querying against the full event table. The view, however, adds an
** abstraction level to simplify the implementation code for the
** various /reports pages.
**
** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
** filter it applies, or '*' if no filter is applied (i.e. if "all" is
** used).
*/
static int stats_report_init_view(){
  char const * zType = PD("type","*");  /* analog to /timeline?y=... */
  char const * zRealType = NULL;        /* normalized form of zType */
  int rc = 0;                          /* result code */
  assert( !statsReportType && "Must not be called more than once." );
  switch( (zType && *zType) ? *zType : 0 ){
    case 'c':
    case 'C':
      zRealType = "ci";
      rc = *zRealType;







|




















|
|







1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
*/
static int statsReportType = 0;

/*
** Set by stats_report_init_view() to one of the y=XXXX values
** accepted by /timeline?y=XXXX.
*/
static const char *statsReportTimelineYFlag = NULL;

/*
** Creates a TEMP VIEW named v_reports which is a wrapper around the
** EVENT table filtered on event.type. It looks for the request
** parameter 'type' (reminder: we "should" use 'y' for consistency
** with /timeline, but /reports uses 'y' for the year) and expects it
** to contain one of the conventional values from event.type or the
** value "all", which is treated as equivalent to "*".  By default (if
** no 'y' is specified), "*" is assumed (that is also the default for
** invalid/unknown filter values). That 'y' filter is the one used for
** the event list. Note that a filter of "*" or "all" is equivalent to
** querying against the full event table. The view, however, adds an
** abstraction level to simplify the implementation code for the
** various /reports pages.
**
** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
** filter it applies, or '*' if no filter is applied (i.e. if "all" is
** used).
*/
static int stats_report_init_view(){
  const char *zType = PD("type","*");  /* analog to /timeline?y=... */
  const char *zRealType = NULL;        /* normalized form of zType */
  int rc = 0;                          /* result code */
  assert( !statsReportType && "Must not be called more than once." );
  switch( (zType && *zType) ? *zType : 0 ){
    case 'c':
    case 'C':
      zRealType = "ci";
      rc = *zRealType;
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054


2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094





2095
2096
2097
2098
2099
2100
2101

/*
** Returns a string suitable (for a given value of suitable) for
** use in a label with the header of the /reports pages, dependent
** on the 'type' flag. See stats_report_init_view().
** The returned bytes are static.
*/
static char const * stats_report_label_for_type(){
  assert( statsReportType && "Must call stats_report_init_view() first." );
  switch( statsReportType ){
    case 'c':
      return "checkins";


    case 'w':
      return "wiki changes";
    case 't':
      return "ticket changes";
    case 'g':
      return "tag changes";
    default:
      return "all types";
  }
}

/*
** A helper for the /reports family of pages which prints out a menu
** of links for the various type=XXX flags. zCurrentViewName must be
** the name/value of the 'view' parameter which is in effect at the
** time this is called. e.g. if called from the 'byuser' view then
** zCurrentViewName must be "byuser". Any URL parameters which need to
** be added to the generated URLs should be passed in zParam. The
** caller is expected to have already encoded any zParam in the %T or
** %t encoding.  */
static void stats_report_event_types_menu(char const * zCurrentViewName,
                                          char const * zParam){
  char * zTop;
  if(zParam && !*zParam){
    zParam = NULL;
  }
  zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
                 zParam ? "&" : "", zParam);
  cgi_printf("<div>");
  cgi_printf("<span>Event types:</span> ");
  if('*' == statsReportType){
    cgi_printf(" <strong>all</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s'>all</a>", zTop);
  }
  if('c' == statsReportType){
    cgi_printf(" <strong>checkins</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
  }





  if( 't' == statsReportType ){
    cgi_printf(" <strong>tickets</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
  }
  if( 'g' == statsReportType ){
    cgi_printf(" <strong>tags</strong>", zTop);







|




>
>




















|
|
|






|










>
>
>
>
>







2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107

/*
** Returns a string suitable (for a given value of suitable) for
** use in a label with the header of the /reports pages, dependent
** on the 'type' flag. See stats_report_init_view().
** The returned bytes are static.
*/
static const char *stats_report_label_for_type(){
  assert( statsReportType && "Must call stats_report_init_view() first." );
  switch( statsReportType ){
    case 'c':
      return "checkins";
    case 'e':
      return "events";
    case 'w':
      return "wiki changes";
    case 't':
      return "ticket changes";
    case 'g':
      return "tag changes";
    default:
      return "all types";
  }
}

/*
** A helper for the /reports family of pages which prints out a menu
** of links for the various type=XXX flags. zCurrentViewName must be
** the name/value of the 'view' parameter which is in effect at the
** time this is called. e.g. if called from the 'byuser' view then
** zCurrentViewName must be "byuser". Any URL parameters which need to
** be added to the generated URLs should be passed in zParam. The
** caller is expected to have already encoded any zParam in the %T or
** %t encoding.  */
static void stats_report_event_types_menu(const char *zCurrentViewName,
                                          const char *zParam){
  char *zTop;
  if(zParam && !*zParam){
    zParam = NULL;
  }
  zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
                 zParam ? "&" : "", zParam);
  cgi_printf("<div>");
  cgi_printf("<span>Types:</span> ");
  if('*' == statsReportType){
    cgi_printf(" <strong>all</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s'>all</a>", zTop);
  }
  if('c' == statsReportType){
    cgi_printf(" <strong>checkins</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
  }
  if('e' == statsReportType){
    cgi_printf(" <strong>events</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s&type=e'>events</a>", zTop);
  }
  if( 't' == statsReportType ){
    cgi_printf(" <strong>tickets</strong>", zTop);
  }else{
    cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
  }
  if( 'g' == statsReportType ){
    cgi_printf(" <strong>tags</strong>", zTop);
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167


/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_output_week_links(const char * zTimeframe){
  Stmt stWeek = empty_Stmt;
  char yearPart[5] = {0,0,0,0,0};
  memcpy(yearPart, zTimeframe, 4);
  db_prepare(&stWeek,
             "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
             "count(*) AS n, "
             "substr(date(mtime),1,%d) AS ym "
             "FROM v_reports "
             "WHERE ym=%Q AND mtime < current_timestamp "
             "GROUP BY wk ORDER BY wk",
             strlen(zTimeframe),
             zTimeframe);
  while( SQLITE_ROW == db_step(&stWeek) ){
    const char * zWeek = db_column_text(&stWeek,0);
    const int nCount = db_column_int(&stWeek,1);
    cgi_printf("<a href='%s/timeline?"
               "yw=%t-%t&n=%d&y=%s'>%s</a>",
               g.zTop, yearPart, zWeek,
               nCount, statsReportTimelineYFlag, zWeek);
  }
  db_finalize(&stWeek);
}

/*
** Implements the "byyear" and "bymonth" reports for /reports.
** If includeMonth is true then it generates the "bymonth" report,
** else the "byyear" report. If zUserName is not NULL and not empty
** then the report is restricted to events created by the named user
** account.
*/
static void stats_report_by_month_year(char includeMonth,
                                       char includeWeeks,
                                       const char * zUserName){
  Stmt query = empty_Stmt;
  int nRowNumber = 0;                /* current TR number */
  int nEventTotal = 0;               /* Total event count */
  int rowClass = 0;                  /* counter for alternating
                                        row colors */
  Blob sql = empty_blob;             /* SQL */
  const char * zTimeLabel = includeMonth ? "Year/Month" : "Year";
  char zPrevYear[5] = {0};           /* For keeping track of when
                                        we change years while looping */
  int nEventsPerYear = 0;            /* Total event count for the
                                        current year */
  char showYearTotal = 0;            /* Flag telling us when to show
                                        the per-year event totals */
  Blob header = empty_blob;          /* Page header text */







|













|


















|






|







2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173


/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_output_week_links(const char *zTimeframe){
  Stmt stWeek = empty_Stmt;
  char yearPart[5] = {0,0,0,0,0};
  memcpy(yearPart, zTimeframe, 4);
  db_prepare(&stWeek,
             "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
             "count(*) AS n, "
             "substr(date(mtime),1,%d) AS ym "
             "FROM v_reports "
             "WHERE ym=%Q AND mtime < current_timestamp "
             "GROUP BY wk ORDER BY wk",
             strlen(zTimeframe),
             zTimeframe);
  while( SQLITE_ROW == db_step(&stWeek) ){
    const char *zWeek = db_column_text(&stWeek,0);
    const int nCount = db_column_int(&stWeek,1);
    cgi_printf("<a href='%s/timeline?"
               "yw=%t-%t&n=%d&y=%s'>%s</a>",
               g.zTop, yearPart, zWeek,
               nCount, statsReportTimelineYFlag, zWeek);
  }
  db_finalize(&stWeek);
}

/*
** Implements the "byyear" and "bymonth" reports for /reports.
** If includeMonth is true then it generates the "bymonth" report,
** else the "byyear" report. If zUserName is not NULL and not empty
** then the report is restricted to events created by the named user
** account.
*/
static void stats_report_by_month_year(char includeMonth,
                                       char includeWeeks,
                                       const char *zUserName){
  Stmt query = empty_Stmt;
  int nRowNumber = 0;                /* current TR number */
  int nEventTotal = 0;               /* Total event count */
  int rowClass = 0;                  /* counter for alternating
                                        row colors */
  Blob sql = empty_blob;             /* SQL */
  const char *zTimeLabel = includeMonth ? "Year/Month" : "Year";
  char zPrevYear[5] = {0};           /* For keeping track of when
                                        we change years while looping */
  int nEventsPerYear = 0;            /* Total event count for the
                                        current year */
  char showYearTotal = 0;            /* Flag telling us when to show
                                        the per-year event totals */
  Blob header = empty_blob;          /* Page header text */
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
    ++iterations;
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const char * zTimeframe = db_column_text(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 1;
    showYearTotal = 0;
    if(!nSize) nSize = 1;
    if(includeMonth){







|







2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
    ++iterations;
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const char *zTimeframe = db_column_text(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 1;
    showYearTotal = 0;
    if(!nSize) nSize = 1;
    if(includeMonth){
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
    @ <tr class='row%d(rowClass)'>
    @ <td></td>
    @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
    @</tr>
  }
  @ </tbody></table>
  if(nEventTotal){
    char const * zAvgLabel = includeMonth ? "month" : "year";
    int nAvg = iterations ? (nEventTotal/iterations) : 0;
    @ <br><div>Total events: %d(nEventTotal)
    @ <br>Average per active %s(zAvgLabel): %d(nAvg)
    @ </div>
  }
  if( !includeMonth ){
    output_table_sorting_javascript("statsTable","tnx");







|







2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
    @ <tr class='row%d(rowClass)'>
    @ <td></td>
    @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
    @</tr>
  }
  @ </tbody></table>
  if(nEventTotal){
    const char *zAvgLabel = includeMonth ? "month" : "year";
    int nAvg = iterations ? (nEventTotal/iterations) : 0;
    @ <br><div>Total events: %d(nEventTotal)
    @ <br>Average per active %s(zAvgLabel): %d(nAvg)
    @ </div>
  }
  if( !includeMonth ){
    output_table_sorting_javascript("statsTable","tnx");
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const char * zUser = db_column_text(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 0;
    if(!nCount) continue /* arguable! Possible? */;
    else if(!nSize) nSize = 1;
    rowClass = ++nRowNumber % 2;







|







2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const char *zUser = db_column_text(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 0;
    if(!nCount) continue /* arguable! Possible? */;
    else if(!nSize) nSize = 1;
    rowClass = ++nRowNumber % 2;
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
  int nRowNumber = 0;                /* current TR number */
  int nEventTotal = 0;               /* Total event count */
  int rowClass = 0;                  /* counter for alternating
                                        row colors */
  Blob sql = empty_blob;             /* SQL */
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  static char const * daysOfWeek[] = {
  "Monday", "Tuesday", "Wednesday", "Thursday",
  "Friday", "Saturday", "Sunday"
  };
      
  stats_report_init_view();
  stats_report_event_types_menu("byweekday", NULL);
  blob_append(&sql,
               "SELECT cast(mtime %% 7 AS INTEGER) dow, "
               "COUNT(*) AS eventCount "
               "FROM v_reports "
               "GROUP BY dow ORDER BY dow",







|



|







2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
  int nRowNumber = 0;                /* current TR number */
  int nEventTotal = 0;               /* Total event count */
  int rowClass = 0;                  /* counter for alternating
                                        row colors */
  Blob sql = empty_blob;             /* SQL */
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  static const char *const daysOfWeek[] = {
  "Monday", "Tuesday", "Wednesday", "Thursday",
  "Friday", "Saturday", "Sunday"
  };

  stats_report_init_view();
  stats_report_event_types_menu("byweekday", NULL);
  blob_append(&sql,
               "SELECT cast(mtime %% 7 AS INTEGER) dow, "
               "COUNT(*) AS eventCount "
               "FROM v_reports "
               "GROUP BY dow ORDER BY dow",
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    int const dayNum =db_column_int(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 0;
    if(!nCount) continue /* arguable! Possible? */;
    else if(!nSize) nSize = 1;
    rowClass = ++nRowNumber % 2;







|







2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const int dayNum =db_column_int(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 0;
    if(!nCount) continue /* arguable! Possible? */;
    else if(!nSize) nSize = 1;
    rowClass = ++nRowNumber % 2;
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465


/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_year_weeks(const char * zUserName){
  const char * zYear = P("y");
  int nYear = zYear ? strlen(zYear) : 0;
  int i = 0;
  Stmt qYears = empty_Stmt;
  char * zDefaultYear = NULL;
  Blob sql = empty_blob;
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  int iterations = 0;                /* # of active time periods. */
  stats_report_init_view();
  if(4==nYear){
    Blob urlParams = empty_blob;







|
|



|







2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471


/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_year_weeks(const char *zUserName){
  const char *zYear = P("y");
  int nYear = zYear ? strlen(zYear) : 0;
  int i = 0;
  Stmt qYears = empty_Stmt;
  char *zDefaultYear = NULL;
  Blob sql = empty_blob;
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  int iterations = 0;                /* # of active time periods. */
  stats_report_init_view();
  if(4==nYear){
    Blob urlParams = empty_blob;
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
    blob_appendf(&sql,"AND user=%Q ", zUserName);
  }
  blob_append(&sql,"GROUP BY y ORDER BY y", -1);
  db_prepare(&qYears, blob_str(&sql));
  blob_reset(&sql);
  cgi_printf("Select year: ");
  while( SQLITE_ROW == db_step(&qYears) ){
    const char * zT = db_column_text(&qYears, 0);
    if( i++ ){
      cgi_printf(" ");
    }
    cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
               (char)statsReportType);
    if(zUserName && *zUserName){
      cgi_printf("&user=%t",zUserName);







|







2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
    blob_appendf(&sql,"AND user=%Q ", zUserName);
  }
  blob_append(&sql,"GROUP BY y ORDER BY y", -1);
  db_prepare(&qYears, blob_str(&sql));
  blob_reset(&sql);
  cgi_printf("Select year: ");
  while( SQLITE_ROW == db_step(&qYears) ){
    const char *zT = db_column_text(&qYears, 0);
    if( i++ ){
      cgi_printf(" ");
    }
    cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
               (char)statsReportType);
    if(zUserName && *zUserName){
      cgi_printf("&user=%t",zUserName);
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
      if(nCount>nMaxEvents){
        nMaxEvents = nCount;
      }
      ++iterations;
    }
    db_reset(&stWeek);
    while( SQLITE_ROW == db_step(&stWeek) ){
      const char * zWeek = db_column_text(&stWeek,0);
      const int nCount = db_column_int(&stWeek,1);
      int nSize = nCount
        ? (int)(100 * nCount / nMaxEvents)
        : 0;
      if(!nSize) nSize = 1;
      total += nCount;
      cgi_printf("<tr class='row%d'>", ++rowCount % 2 );







|







2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
      if(nCount>nMaxEvents){
        nMaxEvents = nCount;
      }
      ++iterations;
    }
    db_reset(&stWeek);
    while( SQLITE_ROW == db_step(&stWeek) ){
      const char *zWeek = db_column_text(&stWeek,0);
      const int nCount = db_column_int(&stWeek,1);
      int nSize = nCount
        ? (int)(100 * nCount / nMaxEvents)
        : 0;
      if(!nSize) nSize = 1;
      total += nCount;
      cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
** view=byweek:
**
**   y=YYYY            The year to report (default is the server's
**                     current year).
*/
void stats_report_page(){
  HQuery url;                        /* URL for various branch links */
  const char * zView = P("view");    /* Which view/report to show. */
  const char *zUserName = P("user");

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if(!zUserName) zUserName = P("u");
  url_initialize(&url, "reports");
  if(zUserName && *zUserName){







|







2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
** view=byweek:
**
**   y=YYYY            The year to report (default is the server's
**                     current year).
*/
void stats_report_page(){
  HQuery url;                        /* URL for various branch links */
  const char *zView = P("view");    /* Which view/report to show. */
  const char *zUserName = P("user");

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if(!zUserName) zUserName = P("u");
  url_initialize(&url, "reports");
  if(zUserName && *zUserName){
Changes to src/tkt.c.
271
272
273
274
275
276
277























278
279
280
281
282
283
284
    db_finalize(&q);
  }
  blob_reset(&sql2);
  blob_reset(&sql3);
  fossil_free(aUsed);
  return tktid;
}
























/*
** Rebuild an entire entry in the TICKET table
*/
void ticket_rebuild_entry(const char *zTktUuid){
  char *zTag = mprintf("tkt-%s", zTktUuid);
  int tagid = tag_findid(zTag, 1);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
    db_finalize(&q);
  }
  blob_reset(&sql2);
  blob_reset(&sql3);
  fossil_free(aUsed);
  return tktid;
}

/*
** Returns non-zero if moderation is required for ticket changes and ticket
** attachments.
*/
int ticket_need_moderation(
  int localUser /* Are we being called for a local interactive user? */
){
  /*
  ** If the FOSSIL_FORCE_TICKET_MODERATION variable is set, *ALL* changes for
  ** tickets will be required to go through moderation (even those performed
  ** by the local interactive user via the command line).  This can be useful
  ** for local (or remote) testing of the moderation subsystem and its impact
  ** on the contents and status of tickets.
  */
  if( fossil_getenv("FOSSIL_FORCE_TICKET_MODERATION")!=0 ){
    return 1;
  }
  if( localUser ){
    return 0;
  }
  return g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1;
}

/*
** Rebuild an entire entry in the TICKET table
*/
void ticket_rebuild_entry(const char *zTktUuid){
  char *zTag = mprintf("tkt-%s", zTktUuid);
  int tagid = tag_findid(zTag, 1);
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
  zConfig = ticket_common_code();
  Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Create the TH1 interpreter and load the "change" code.
*/
int ticket_change(void){
  const char *zConfig;
  Th_FossilInit(TH_INIT_DEFAULT);

  zConfig = ticket_change_code();
  return Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Recreate the TICKET and TICKETCHNG tables.
*/







|


>







343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  zConfig = ticket_common_code();
  Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Create the TH1 interpreter and load the "change" code.
*/
int ticket_change(const char *zUuid){
  const char *zConfig;
  Th_FossilInit(TH_INIT_DEFAULT);
  Th_Store("uuid", zUuid);
  zConfig = ticket_change_code();
  return Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Recreate the TICKET and TICKETCHNG tables.
*/
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
    attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>");
  }

  style_footer();
}

/*
** TH command:   append_field FIELD STRING
**
** FIELD is the name of a database column to which we might want
** to append text.  STRING is the text to be appended to that
** column.  The append does not actually occur until the
** submit_ticket command is run.
*/
static int appendRemarkCmd(







|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
    attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>");
  }

  style_footer();
}

/*
** TH1 command: append_field FIELD STRING
**
** FIELD is the name of a database column to which we might want
** to append text.  STRING is the text to be appended to that
** column.  The append does not actually occur until the
** submit_ticket command is run.
*/
static int appendRemarkCmd(
564
565
566
567
568
569
570

571
572
573
574
575
576
577
  int *argl
){
  char *zDate;
  const char *zUuid;
  int i;
  int nJ = 0;
  Blob tktchng, cksum;


  login_verify_csrf_secret();
  if( !captcha_is_correct() ){
    @ <p class="generalError">Error: Incorrect security code.</p>
    return TH_OK;
  }
  zUuid = (const char *)pUuid;







>







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  int *argl
){
  char *zDate;
  const char *zUuid;
  int i;
  int nJ = 0;
  Blob tktchng, cksum;
  int needMod;

  login_verify_csrf_secret();
  if( !captcha_is_correct() ){
    @ <p class="generalError">Error: Incorrect security code.</p>
    return TH_OK;
  }
  zUuid = (const char *)pUuid;
619
620
621
622
623
624
625

626

627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  blob_appendf(&tktchng, "U %F\n", login_name());
  md5sum_blob(&tktchng, &cksum);
  blob_appendf(&tktchng, "Z %b\n", &cksum);
  if( nJ==0 ){
    blob_reset(&tktchng);
    return TH_OK;
  }

  if( g.zPath[0]=='d' ){

    /* If called from /debug_tktnew or /debug_tktedit... */
    @ <font color="blue">
    @ <p>Ticket artifact that would have been submitted:</p>
    @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>

    @ <hr /></font>
    return TH_OK;
  }else{
    if( g.thTrace ){
      Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
               "}<br />\n",
         blob_str(&tktchng));
    }
    ticket_put(&tktchng, zUuid,
               (g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1));
  }
  return ticket_change();
}


/*
** WEBPAGE: tktnew
** WEBPAGE: debug_tktnew
**







>

>




>








|
<

|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
  blob_appendf(&tktchng, "U %F\n", login_name());
  md5sum_blob(&tktchng, &cksum);
  blob_appendf(&tktchng, "Z %b\n", &cksum);
  if( nJ==0 ){
    blob_reset(&tktchng);
    return TH_OK;
  }
  needMod = ticket_need_moderation(0);
  if( g.zPath[0]=='d' ){
    const char *zNeedMod = needMod ? "required" : "skipped";
    /* If called from /debug_tktnew or /debug_tktedit... */
    @ <font color="blue">
    @ <p>Ticket artifact that would have been submitted:</p>
    @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
    @ <blockquote><pre>Moderation would be %h(zNeedMod).</pre></blockquote>
    @ <hr /></font>
    return TH_OK;
  }else{
    if( g.thTrace ){
      Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
               "}<br />\n",
         blob_str(&tktchng));
    }
    ticket_put(&tktchng, zUuid, needMod);

  }
  return ticket_change(zUuid);
}


/*
** WEBPAGE: tktnew
** WEBPAGE: debug_tktnew
**
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
        @
        @ <li><p>Delete attachment "%h(zFile)"
      }else{
        @
        @ <li><p>Add attachment
        @ "%z(href("%R/artifact/%s",zSrc))%s(zFile)</a>"
      }
      @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)</a>]
      @ (rid %d(rid)) by
      hyperlink_to_user(zUser,zDate," on");
      hyperlink_to_date(zDate, ".</p>");
    }else{
      pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
      if( pTicket ){
        @
        @ <li><p>Ticket change
        @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)</a>]
        @ (rid %d(rid)) by
        hyperlink_to_user(pTicket->zUser,zDate," on");
        hyperlink_to_date(zDate, ":");
        @ </p>
        ticket_output_change_artifact(pTicket, "a");
      }
      manifest_destroy(pTicket);







|








|







968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
        @
        @ <li><p>Delete attachment "%h(zFile)"
      }else{
        @
        @ <li><p>Add attachment
        @ "%z(href("%R/artifact/%s",zSrc))%s(zFile)</a>"
      }
      @ [%z(href("%R/artifact/%s",zChngUuid))%S(zChngUuid)</a>]
      @ (rid %d(rid)) by
      hyperlink_to_user(zUser,zDate," on");
      hyperlink_to_date(zDate, ".</p>");
    }else{
      pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
      if( pTicket ){
        @
        @ <li><p>Ticket change
        @ [%z(href("%R/artifact/%s",zChngUuid))%S(zChngUuid)</a>]
        @ (rid %d(rid)) by
        hyperlink_to_user(pTicket->zUser,zDate," on");
        hyperlink_to_date(zDate, ":");
        @ </p>
        ticket_output_change_artifact(pTicket, "a");
      }
      manifest_destroy(pTicket);
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
**     page in the gui is used. This has no effect in JSON mode.
**
**     Instead of the report title its possible to use the report
**     number. Using the special report number 0 list all columns,
**     defined in the ticket table.
**
**   %fossil ticket list fields

**
**     list all fields, defined for ticket in the fossil repository
**
**   %fossil ticket list reports

**
**     list all ticket reports, defined in the fossil repository
**
**   %fossil ticket set TICKETUUID (FIELD VALUE)+ ?-q|--quote?
**   %fossil ticket change TICKETUUID (FIELD VALUE)+ ?-q|--quote?
**
**     change ticket identified by TICKETUUID and set the value of







>




>







1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
**     page in the gui is used. This has no effect in JSON mode.
**
**     Instead of the report title its possible to use the report
**     number. Using the special report number 0 list all columns,
**     defined in the ticket table.
**
**   %fossil ticket list fields
**   %fossil ticket ls fields
**
**     list all fields, defined for ticket in the fossil repository
**
**   %fossil ticket list reports
**   %fossil ticket ls reports
**
**     list all ticket reports, defined in the fossil repository
**
**   %fossil ticket set TICKETUUID (FIELD VALUE)+ ?-q|--quote?
**   %fossil ticket change TICKETUUID (FIELD VALUE)+ ?-q|--quote?
**
**     change ticket identified by TICKETUUID and set the value of
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
    usage("add|change|list|set|show|history");
  }
  n = strlen(g.argv[2]);
  if( n==1 && g.argv[2][0]=='s' ){
    /* set/show cannot be distinguished, so show the usage */
    usage("add|change|list|set|show|history");
  }
  if( strncmp(g.argv[2],"list",n)==0 ){
    if( g.argc==3 ){
      usage("list fields|reports");
    }else{
      n = strlen(g.argv[3]);
      if( !strncmp(g.argv[3],"fields",n) ){
        /* simply show all field names */
        int i;







|







1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
    usage("add|change|list|set|show|history");
  }
  n = strlen(g.argv[2]);
  if( n==1 && g.argv[2][0]=='s' ){
    /* set/show cannot be distinguished, so show the usage */
    usage("add|change|list|set|show|history");
  }
  if(( strncmp(g.argv[2],"list",n)==0 ) || ( strncmp(g.argv[2],"ls",n)==0 )){
    if( g.argc==3 ){
      usage("list fields|reports");
    }else{
      n = strlen(g.argv[3]);
      if( !strncmp(g.argv[3],"fields",n) ){
        /* simply show all field names */
        int i;
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
      }

      /* we just handle history separately here, does not get out */
      if( eCmd==history ){
        Stmt q;
        int tagid;

        if ( i != g.argc ){
          fossil_fatal("no other parameters expected to %s!",g.argv[2]);
        }
        tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
                       zTktUuid);
        if( tagid==0 ){
          fossil_fatal("no such ticket %h", zTktUuid);
        }







|







1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
      }

      /* we just handle history separately here, does not get out */
      if( eCmd==history ){
        Stmt q;
        int tagid;

        if( i != g.argc ){
          fossil_fatal("no other parameters expected to %s!",g.argv[2]);
        }
        tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
                       zTktUuid);
        if( tagid==0 ){
          fossil_fatal("no such ticket %h", zTktUuid);
        }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
            z++;
          }else{
            fossil_print("  Change ");
          }
          fossil_print("%h: ",z);
          if( blob_size(&val)>50 || contains_newline(&val)) {
                  fossil_print("\n    ",blob_str(&val));
                  comment_print(blob_str(&val),4,79);
                }else{
                  fossil_print("%s\n",blob_str(&val));
                }
                blob_reset(&val);
              }
            }
            manifest_destroy(pTicket);







|







1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
            z++;
          }else{
            fossil_print("  Change ");
          }
          fossil_print("%h: ",z);
          if( blob_size(&val)>50 || contains_newline(&val)) {
                  fossil_print("\n    ",blob_str(&val));
                  comment_print(blob_str(&val),0,4,-1,g.comFmtFlags);
                }else{
                  fossil_print("%s\n",blob_str(&val));
                }
                blob_reset(&val);
              }
            }
            manifest_destroy(pTicket);
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
        }
        zFValue = g.argv[i++];
        if( tktEncoding == tktFossilize ){
          zFValue=mprintf("%s",zFValue);
          defossilize(zFValue);
        }
        append = (zFName[0] == '+');
        if (append){
          zFName++;
        }
        j = fieldId(zFName);
        if( j == -1 ){
          fossil_fatal("unknown field name '%s'!",zFName);
        }else{
          if (append) {
            aField[j].zAppend = zFValue;
          } else {
            aField[j].zValue = zFValue;
          }
        }
      }

      /* now add the needed artifacts to the repository */
      blob_zero(&tktchng);
      /* add the time to the ticket manifest */
      blob_appendf(&tktchng, "D %s\n", zDate);
      /* append defined elements */
      for(i=0; i<nField; i++){
        char *zValue = 0;
        char *zPfx;

        if (aField[i].zAppend && aField[i].zAppend[0] ){
          zPfx = " +";
          zValue = aField[i].zAppend;
        } else if( aField[i].zValue && aField[i].zValue[0] ){
          zPfx = " ";
          zValue = aField[i].zValue;
        } else {
          continue;
        }
        if( memcmp(aField[i].zName, "private_", 8)==0 ){
          zValue = db_conceal(zValue, strlen(zValue));
          blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
        }else{
          blob_appendf(&tktchng, "J%s%s %#F\n", zPfx,
                       aField[i].zName, strlen(zValue), zValue);
        }
      }
      blob_appendf(&tktchng, "K %s\n", zTktUuid);
      blob_appendf(&tktchng, "U %F\n", zUser);
      md5sum_blob(&tktchng, &cksum);
      blob_appendf(&tktchng, "Z %b\n", &cksum);
      if( ticket_put(&tktchng, zTktUuid, 0) ){
        fossil_fatal("%s\n", g.zErrMsg);
      }else{
        fossil_print("ticket %s succeeded for %s\n",
             (eCmd==set?"set":"add"),zTktUuid);
      }
    }
  }
}







|






|

|














|


|


|














|








1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
        }
        zFValue = g.argv[i++];
        if( tktEncoding == tktFossilize ){
          zFValue=mprintf("%s",zFValue);
          defossilize(zFValue);
        }
        append = (zFName[0] == '+');
        if( append ){
          zFName++;
        }
        j = fieldId(zFName);
        if( j == -1 ){
          fossil_fatal("unknown field name '%s'!",zFName);
        }else{
          if( append ){
            aField[j].zAppend = zFValue;
          }else{
            aField[j].zValue = zFValue;
          }
        }
      }

      /* now add the needed artifacts to the repository */
      blob_zero(&tktchng);
      /* add the time to the ticket manifest */
      blob_appendf(&tktchng, "D %s\n", zDate);
      /* append defined elements */
      for(i=0; i<nField; i++){
        char *zValue = 0;
        char *zPfx;

        if( aField[i].zAppend && aField[i].zAppend[0] ){
          zPfx = " +";
          zValue = aField[i].zAppend;
        }else if( aField[i].zValue && aField[i].zValue[0] ){
          zPfx = " ";
          zValue = aField[i].zValue;
        }else{
          continue;
        }
        if( memcmp(aField[i].zName, "private_", 8)==0 ){
          zValue = db_conceal(zValue, strlen(zValue));
          blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
        }else{
          blob_appendf(&tktchng, "J%s%s %#F\n", zPfx,
                       aField[i].zName, strlen(zValue), zValue);
        }
      }
      blob_appendf(&tktchng, "K %s\n", zTktUuid);
      blob_appendf(&tktchng, "U %F\n", zUser);
      md5sum_blob(&tktchng, &cksum);
      blob_appendf(&tktchng, "Z %b\n", &cksum);
      if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){
        fossil_fatal("%s\n", g.zErrMsg);
      }else{
        fossil_print("ticket %s succeeded for %s\n",
             (eCmd==set?"set":"add"),zTktUuid);
      }
    }
  }
}
Changes to src/tktsetup.c.
433
434
435
436
437
438
439

440
441
442



443

444




445
446
447
448
449
450
451
  );
}

static const char zDefaultView[] =
@ <table cellpadding="5">
@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
@ <th1>

@ if {[hascap s]} {
@   html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
@   html "($tkt_id)</td></tr>\n"



@ } else {

@   html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"




@ }
@ </th1>
@ <tr><td class="tktDspLabel">Title:</td>
@ <td class="tktDspValue" colspan="3">
@ $<title>
@ </td></tr>
@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">







>
|
|
|
>
>
>

>
|
>
>
>
>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  );
}

static const char zDefaultView[] =
@ <table cellpadding="5">
@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
@ <th1>
@ if {[info exists tkt_uuid]} {
@   if {[hascap s]} {
@     html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
@     html "($tkt_id)</td></tr>\n"
@   } else {
@     html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"
@   }
@ } else {
@   if {[hascap s]} {
@     html "<td class='tktDspValue' colspan='3'>Deleted "
@     html "(0)</td></tr>\n"
@   } else {
@     html "<td class='tktDspValue' colspan='3'>Deleted</td></tr>\n"
@   }
@ }
@ </th1>
@ <tr><td class="tktDspLabel">Title:</td>
@ <td class="tktDspValue" colspan="3">
@ $<title>
@ </td></tr>
@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">
463
464
465
466
467
468
469


470


471
472
473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500
@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
@ $<subsystem>
@ </td>
@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
@ $<resolution>
@ </td></tr>
@ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">


@ $<tkt_datetime>


@ </td>
@ <th1>enable_output [hascap e]</th1>
@   <td class="tktDspLabel">Contact:</td><td class="tktDspValue">
@   $<private_contact>
@   </td>
@ <th1>enable_output 1</th1>
@ </tr>
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
@ <td colspan="3" valign="top" class="tktDspValue">
@ $<foundin>
@ </td></tr>
@
@ <th1>
@ if {[info exists comment] && [string length $comment]>10} {

@   html {
@     <tr><td class="tktDspLabel">Description:</td></tr>
@     <tr><td colspan="5" class="tktDspValue">
@   }
@   if {[info exists plaintext]} {
@     set r [randhex]
@     wiki "<verbatim-$r links>\n$comment\n</verbatim-$r>"
@   } else {

@     wiki $comment
@   }
@ }
@ set seenRow 0
@ set alwaysPlaintext [info exists plaintext]
@ query {SELECT datetime(tkt_mtime) AS xdate, login AS xlogin,
@               mimetype as xmimetype, icomment AS xcomment,
@               username AS xusername







>
>
|
>
>













|
>
|
|
|
|
|
|
|
|
>
|







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
@ $<subsystem>
@ </td>
@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
@ $<resolution>
@ </td></tr>
@ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">
@ <th1>
@ if {[info exists tkt_datetime]} {
@   html $tkt_datetime
@ }
@ </th1>
@ </td>
@ <th1>enable_output [hascap e]</th1>
@   <td class="tktDspLabel">Contact:</td><td class="tktDspValue">
@   $<private_contact>
@   </td>
@ <th1>enable_output 1</th1>
@ </tr>
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
@ <td colspan="3" valign="top" class="tktDspValue">
@ $<foundin>
@ </td></tr>
@
@ <th1>
@ if {[info exists comment]} {
@   if {[string length $comment]>10} {
@     html {
@       <tr><td class="tktDspLabel">Description:</td></tr>
@       <tr><td colspan="5" class="tktDspValue">
@     }
@     if {[info exists plaintext]} {
@       set r [randhex]
@       wiki "<verbatim-$r links>\n$comment\n</verbatim-$r>"
@     } else {
@       wiki $comment
@     }
@   }
@ }
@ set seenRow 0
@ set alwaysPlaintext [info exists plaintext]
@ query {SELECT datetime(tkt_mtime) AS xdate, login AS xlogin,
@               mimetype as xmimetype, icomment AS xcomment,
@               username AS xusername
Changes to src/unicode.c.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110

111

112
113
114




115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
** is less than zero.
*/
int unicode_isalnum(int c){
  /* Each unsigned integer in the following array corresponds to a contiguous
  ** range of unicode codepoints that are not either letters or numbers (i.e.
  ** codepoints for which this function should return 0).
  **
  ** The most significant 22 bits in each 32-bit value contain the first 
  ** codepoint in the range. The least significant 10 bits are used to store
  ** the size of the range (always at least 1). In other words, the value 
  ** ((C<<22) + N) represents a range of N codepoints starting with codepoint 
  ** C. It is not possible to represent a range larger than 1023 codepoints 
  ** using this format.
  */
  static const unsigned int aEntry[] = {
    0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
    0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
    0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
    0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
    0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
    0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
    0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
    0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
    0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
    0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
    0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
    0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
    0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
    0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
    0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
    0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
    0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
    0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
    0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
    0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
    0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
    0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
    0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
    0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
    0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
    0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
    0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
    0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
    0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
    0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
    0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
    0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
    0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
    0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
    0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
    0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
    0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
    0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
    0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
    0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
    0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
    0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
    0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
    0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
    0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
    0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
    0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
    0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
    0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
    0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
    0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
    0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
    0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
    0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
    0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
    0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
    0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,

    0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
    0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
    0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
    0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
    0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
    0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
    0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
    0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
    0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
    0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,

    0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,

    0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
    0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
    0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,




    0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
    0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
    0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
    0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
    0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
    0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
    0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
    0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
    0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
    0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
    0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
    0x43FFF401,
  };
  static const unsigned int aAscii[4] = {
    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
  };

  if( c<128 ){
    return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );







|

|
|
|







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
>
|
>
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
<







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
** is less than zero.
*/
int unicode_isalnum(int c){
  /* Each unsigned integer in the following array corresponds to a contiguous
  ** range of unicode codepoints that are not either letters or numbers (i.e.
  ** codepoints for which this function should return 0).
  **
  ** The most significant 22 bits in each 32-bit value contain the first
  ** codepoint in the range. The least significant 10 bits are used to store
  ** the size of the range (always at least 1). In other words, the value
  ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
  ** C. It is not possible to represent a range larger than 1023 codepoints
  ** using this format.
  */
  static const unsigned int aEntry[] = {
    0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
    0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
    0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
    0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
    0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163403,
    0x00164437, 0x0017CC02, 0x0018001D, 0x00187802, 0x00192C15,
    0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, 0x001B9C07,
    0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, 0x001CC01B,
    0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, 0x00206C09,
    0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, 0x00217801,
    0x00239020, 0x0024E803, 0x0024F812, 0x00254407, 0x00258804,
    0x0025C001, 0x00260403, 0x0026F001, 0x0026F807, 0x00271C02,
    0x00272C03, 0x00275C01, 0x00278802, 0x0027C802, 0x0027E802,
    0x00280403, 0x0028F001, 0x0028F805, 0x00291C02, 0x00292C03,
    0x00294401, 0x0029C002, 0x0029D401, 0x002A0403, 0x002AF001,
    0x002AF808, 0x002B1C03, 0x002B2C03, 0x002B8802, 0x002BC002,
    0x002C0403, 0x002CF001, 0x002CF807, 0x002D1C02, 0x002D2C03,
    0x002D5802, 0x002D8802, 0x002DC001, 0x002E0801, 0x002EF805,
    0x002F1803, 0x002F2804, 0x002F5C01, 0x002FCC08, 0x00300004,
    0x0030F807, 0x00311803, 0x00312804, 0x00315402, 0x00318802,
    0x0031FC01, 0x00320403, 0x0032F001, 0x0032F807, 0x00331803,
    0x00332804, 0x00335402, 0x00338802, 0x00340403, 0x0034F807,
    0x00351803, 0x00352804, 0x00355C01, 0x00358802, 0x0035E401,
    0x00360802, 0x00372801, 0x00373C06, 0x00375801, 0x00376008,
    0x0037C803, 0x0038C401, 0x0038D007, 0x0038FC01, 0x00391C09,
    0x00396802, 0x003AC401, 0x003AD006, 0x003AEC02, 0x003B2006,
    0x003C041F, 0x003CD00C, 0x003DC417, 0x003E340B, 0x003E6424,
    0x003EF80F, 0x003F380D, 0x0040AC14, 0x00412806, 0x00415804,
    0x00417803, 0x00418803, 0x00419C07, 0x0041C404, 0x0042080C,
    0x00423C01, 0x00426806, 0x0043EC01, 0x004D740C, 0x004E400A,
    0x00500001, 0x0059B402, 0x005A0001, 0x005A6C02, 0x005BAC03,
    0x005C4803, 0x005CC805, 0x005D4802, 0x005DC802, 0x005ED023,
    0x005F6004, 0x005F7401, 0x0060000F, 0x0062A401, 0x0064800C,
    0x0064C00C, 0x00650001, 0x00651002, 0x0066C011, 0x00672002,
    0x00677822, 0x00685C05, 0x00687802, 0x0069540A, 0x0069801D,
    0x0069FC01, 0x006A8007, 0x006AA006, 0x006AC00F, 0x006C0005,
    0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, 0x006F980E,
    0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, 0x00730008,
    0x00734019, 0x0073B401, 0x0073C803, 0x0073E002, 0x00770036,
    0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
    0x007FB403, 0x007FF402, 0x00800065, 0x0081980A, 0x0081E805,
    0x00822805, 0x0082801E, 0x00834021, 0x00840002, 0x00840C04,
    0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
    0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
    0x00852804, 0x00853C01, 0x0086426B, 0x00900027, 0x0091000B,
    0x0092704E, 0x00940276, 0x009E53E0, 0x00ADD820, 0x00AE6022,
    0x00AEF40C, 0x00AF2808, 0x00B39406, 0x00B3BC03, 0x00B3E404,
    0x00B3F802, 0x00B5C001, 0x00B5FC01, 0x00B7804F, 0x00B8C013,
    0x00BA001A, 0x00BA6C59, 0x00BC00D6, 0x00BFC00C, 0x00C00005,
    0x00C02019, 0x00C0A807, 0x00C0D802, 0x00C0F403, 0x00C26404,
    0x00C28001, 0x00C3EC01, 0x00C64002, 0x00C6580A, 0x00C70024,
    0x00C8001F, 0x00C8A81E, 0x00C94001, 0x00C98020, 0x00CA2827,
    0x00CB003F, 0x00CC0100, 0x01370040, 0x02924037, 0x0293F802,
    0x02983403, 0x0299BC10, 0x029A7C01, 0x029BC008, 0x029C0017,
    0x029C8002, 0x029E2402, 0x02A00801, 0x02A01801, 0x02A02C01,
    0x02A08C09, 0x02A0D804, 0x02A1D004, 0x02A20002, 0x02A2D011,
    0x02A33802, 0x02A38012, 0x02A3E003, 0x02A4980A, 0x02A51C0D,
    0x02A57C01, 0x02A60004, 0x02A6CC1B, 0x02A77802, 0x02A79401,
    0x02A8A40E, 0x02A90C01, 0x02A93002, 0x02A97004, 0x02A9DC03,
    0x02A9EC03, 0x02AAC001, 0x02AAC803, 0x02AADC02, 0x02AAF802,
    0x02AB0401, 0x02AB7802, 0x02ABAC07, 0x02ABD402, 0x02AD6C01,
    0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, 0x037FFC01,
    0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, 0x03F7F002,
    0x03F8001A, 0x03F8800E, 0x03F8C023, 0x03F95013, 0x03F9A004,
    0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, 0x03FD6C0B,
    0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, 0x0404DC09,
    0x0405E411, 0x04063001, 0x0406400C, 0x04068001, 0x0407402E,
    0x040B8001, 0x040DD805, 0x040E7C01, 0x040F4001, 0x0415BC01,
    0x04215C01, 0x0421DC02, 0x04247C01, 0x0424FC01, 0x04280403,
    0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
    0x0429FC01, 0x042B2001, 0x042B9402, 0x042BC007, 0x042CE407,
    0x042E6404, 0x04400003, 0x0440E016, 0x0441FC04, 0x0442C012,
    0x04440003, 0x04449C0E, 0x04450004, 0x0445CC03, 0x04460003,
    0x0446CC0E, 0x04471404, 0x04473401, 0x0448B012, 0x044B7C0C,
    0x044C0403, 0x044CF001, 0x044CF807, 0x044D1C02, 0x044D2C03,
    0x044D5C01, 0x044D8802, 0x044D9807, 0x044DC005, 0x0452C014,
    0x04531801, 0x0456BC07, 0x0456E012, 0x0458C014, 0x045AAC0D,
    0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, 0x05AD1002,
    0x05BD442E, 0x05BE3C04, 0x06F27008, 0x074000F6, 0x07440027,
    0x0744A4B5, 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01,
    0x075BEC01, 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01,
    0x075E2401, 0x075EA401, 0x075F0C01, 0x07A34007, 0x07BBC002,
    0x07C0002C, 0x07C0C064, 0x07C2800F, 0x07C2C40F, 0x07C3040F,
    0x07C34425, 0x07C4401F, 0x07C4C03C, 0x07C5C02B, 0x07C7981D,
    0x07C8402B, 0x07C90009, 0x07C94002, 0x07CC002D, 0x07CCC04E,
    0x07CE004F, 0x07CF5024, 0x07D000FF, 0x07D4004B, 0x07D5402A,
    0x07D5EC29, 0x07D6949E, 0x07D9148B, 0x07DB800D, 0x07DBC004,
    0x07DC0074, 0x07DE0055, 0x07E0000C, 0x07E04038, 0x07E1400A,
    0x07E18028, 0x07E2401E, 0x38000401, 0x38008060, 0x380400F0,

  };
  static const unsigned int aAscii[4] = {
    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
  };

  if( c<128 ){
    return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
** in the ASCII range with a diacritic added, return the codepoint
** of the ASCII letter only. For example, if passed 235 - "LATIN
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int unicode_remove_diacritic(int c){
  unsigned short aDia[] = {
        0,  1797,  1848,  1859,  1891,  1928,  1940,  1995, 
     2024,  2040,  2060,  2110,  2168,  2206,  2264,  2286, 
     2344,  2383,  2472,  2488,  2516,  2596,  2668,  2732, 
     2782,  2842,  2894,  2954,  2984,  3000,  3028,  3336, 
     3456,  3696,  3712,  3728,  3744,  3896,  3912,  3928, 
     3968,  4008,  4040,  4106,  4138,  4170,  4202,  4234, 
     4266,  4296,  4312,  4344,  4408,  4424,  4472,  4504, 
     6148,  6198,  6264,  6280,  6360,  6429,  6505,  6529, 
    61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, 
    61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, 
    62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, 
    62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, 
    62924, 63050, 63082, 63274, 63390, 
  };
  char aChar[] = {
    '\0', 'a',  'c',  'e',  'i',  'n',  'o',  'u',  'y',  'y',  'a',  'c',  
    'd',  'e',  'e',  'g',  'h',  'i',  'j',  'k',  'l',  'n',  'o',  'r',  
    's',  't',  'u',  'u',  'w',  'y',  'z',  'o',  'u',  'a',  'i',  'o',  
    'u',  'g',  'k',  'o',  'j',  'g',  'n',  'a',  'e',  'i',  'o',  'r',  
    'u',  's',  't',  'h',  'a',  'e',  'o',  'y',  '\0', '\0', '\0', '\0', 
    '\0', '\0', '\0', '\0', 'a',  'b',  'd',  'd',  'e',  'f',  'g',  'h',  
    'h',  'i',  'k',  'l',  'l',  'm',  'n',  'p',  'r',  'r',  's',  't',  
    'u',  'v',  'w',  'w',  'x',  'y',  'z',  'h',  't',  'w',  'y',  'a',  
    'e',  'i',  'o',  'u',  'y',  
  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
    int iTest = (iHi + iLo) / 2;
    if( key >= aDia[iTest] ){
      iRes = iTest;
      iLo = iTest+1;
    }else{
      iHi = iTest-1;
    }
  }
  assert( key>=aDia[iRes] );
  return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
};



/*
** Return true if the argument interpreted as a unicode codepoint
** is a diacritical modifier character.
*/
int unicode_is_diacritic(int c){







|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

















<
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
** in the ASCII range with a diacritic added, return the codepoint
** of the ASCII letter only. For example, if passed 235 - "LATIN
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int unicode_remove_diacritic(int c){
  static const unsigned short aDia[] = {
        0,  1797,  1848,  1859,  1891,  1928,  1940,  1995,
     2024,  2040,  2060,  2110,  2168,  2206,  2264,  2286,
     2344,  2383,  2472,  2488,  2516,  2596,  2668,  2732,
     2782,  2842,  2894,  2954,  2984,  3000,  3028,  3336,
     3456,  3696,  3712,  3728,  3744,  3896,  3912,  3928,
     3968,  4008,  4040,  4106,  4138,  4170,  4202,  4234,
     4266,  4296,  4312,  4344,  4408,  4424,  4472,  4504,
     6148,  6198,  6264,  6280,  6360,  6429,  6505,  6529,
    61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
    61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
    62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
    62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
    62924, 63050, 63082, 63274, 63390,
  };
  static const char aChar[] = {
    '\0', 'a',  'c',  'e',  'i',  'n',  'o',  'u',  'y',  'y',  'a',  'c',
    'd',  'e',  'e',  'g',  'h',  'i',  'j',  'k',  'l',  'n',  'o',  'r',
    's',  't',  'u',  'u',  'w',  'y',  'z',  'o',  'u',  'a',  'i',  'o',
    'u',  'g',  'k',  'o',  'j',  'g',  'n',  'a',  'e',  'i',  'o',  'r',
    'u',  's',  't',  'h',  'a',  'e',  'o',  'y',  '\0', '\0', '\0', '\0',
    '\0', '\0', '\0', '\0', 'a',  'b',  'd',  'd',  'e',  'f',  'g',  'h',
    'h',  'i',  'k',  'l',  'l',  'm',  'n',  'p',  'r',  'r',  's',  't',
    'u',  'v',  'w',  'w',  'x',  'y',  'z',  'h',  't',  'w',  'y',  'a',
    'e',  'i',  'o',  'u',  'y',
  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
    int iTest = (iHi + iLo) / 2;
    if( key >= aDia[iTest] ){
      iRes = iTest;
      iLo = iTest+1;
    }else{
      iHi = iTest-1;
    }
  }
  assert( key>=aDia[iRes] );
  return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);

}


/*
** Return true if the argument interpreted as a unicode codepoint
** is a diacritical modifier character.
*/
int unicode_is_diacritic(int c){
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309


310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327
328
329
  static const struct TableEntry {
    unsigned short iCode;
    unsigned char flags;
    unsigned char nRange;
  } aEntry[] = {
    {65, 14, 26},          {181, 64, 1},          {192, 14, 23},
    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
    {313, 1, 16},          {330, 1, 46},          {376, 116, 1},
    {377, 1, 6},           {383, 104, 1},         {385, 50, 1},
    {386, 1, 4},           {390, 44, 1},          {391, 0, 1},
    {393, 42, 2},          {395, 0, 1},           {398, 32, 1},
    {399, 38, 1},          {400, 40, 1},          {401, 0, 1},
    {403, 42, 1},          {404, 46, 1},          {406, 52, 1},
    {407, 48, 1},          {408, 0, 1},           {412, 52, 1},
    {413, 54, 1},          {415, 56, 1},          {416, 1, 6},
    {422, 60, 1},          {423, 0, 1},           {425, 60, 1},
    {428, 0, 1},           {430, 60, 1},          {431, 0, 1},
    {433, 58, 2},          {435, 1, 4},           {439, 62, 1},
    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
    {497, 2, 1},           {498, 1, 4},           {502, 122, 1},
    {503, 134, 1},         {504, 1, 40},          {544, 110, 1},
    {546, 1, 18},          {570, 70, 1},          {571, 0, 1},
    {573, 108, 1},         {574, 68, 1},          {577, 0, 1},
    {579, 106, 1},         {580, 28, 1},          {581, 30, 1},
    {582, 1, 10},          {837, 36, 1},          {880, 1, 4},
    {886, 0, 1},           {902, 18, 1},          {904, 16, 3},
    {908, 26, 1},          {910, 24, 2},          {913, 14, 17},
    {931, 14, 9},          {962, 0, 1},           {975, 4, 1},
    {976, 140, 1},         {977, 142, 1},         {981, 146, 1},
    {982, 144, 1},         {984, 1, 24},          {1008, 136, 1},
    {1009, 138, 1},        {1012, 130, 1},        {1013, 128, 1},
    {1015, 0, 1},          {1017, 152, 1},        {1018, 0, 1},
    {1021, 110, 3},        {1024, 34, 16},        {1040, 14, 32},
    {1120, 1, 34},         {1162, 1, 54},         {1216, 6, 1},
    {1217, 1, 14},         {1232, 1, 88},         {1329, 22, 38},
    {4256, 66, 38},        {4295, 66, 1},         {4301, 66, 1},
    {7680, 1, 150},        {7835, 132, 1},        {7838, 96, 1},
    {7840, 1, 96},         {7944, 150, 8},        {7960, 150, 6},
    {7976, 150, 8},        {7992, 150, 8},        {8008, 150, 6},
    {8025, 151, 8},        {8040, 150, 8},        {8072, 150, 8},
    {8088, 150, 8},        {8104, 150, 8},        {8120, 150, 2},
    {8122, 126, 2},        {8124, 148, 1},        {8126, 100, 1},
    {8136, 124, 4},        {8140, 148, 1},        {8152, 150, 2},
    {8154, 120, 2},        {8168, 150, 2},        {8170, 118, 2},
    {8172, 152, 1},        {8184, 112, 2},        {8186, 114, 2},
    {8188, 148, 1},        {8486, 98, 1},         {8490, 92, 1},
    {8491, 94, 1},         {8498, 12, 1},         {8544, 8, 16},
    {8579, 0, 1},          {9398, 10, 26},        {11264, 22, 47},
    {11360, 0, 1},         {11362, 88, 1},        {11363, 102, 1},
    {11364, 90, 1},        {11367, 1, 6},         {11373, 84, 1},
    {11374, 86, 1},        {11375, 80, 1},        {11376, 82, 1},
    {11378, 0, 1},         {11381, 0, 1},         {11390, 78, 2},
    {11392, 1, 100},       {11499, 1, 4},         {11506, 0, 1},
    {42560, 1, 46},        {42624, 1, 24},        {42786, 1, 14},
    {42802, 1, 62},        {42873, 1, 4},         {42877, 76, 1},
    {42878, 1, 10},        {42891, 0, 1},         {42893, 74, 1},
    {42896, 1, 4},         {42912, 1, 10},        {42922, 72, 1},


    {65313, 14, 26},       
  };
  static const unsigned short aiOff[] = {
   1,     2,     8,     15,    16,    26,    28,    32,    
   37,    38,    40,    48,    63,    64,    69,    71,    
   79,    80,    116,   202,   203,   205,   206,   207,   
   209,   210,   211,   213,   214,   217,   218,   219,   
   775,   7264,  10792, 10795, 23228, 23256, 30204, 54721, 

   54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, 
   57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, 
   65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, 
   65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, 
   65514, 65521, 65527, 65528, 65529, 
  };

  int ret = c;

  assert( c>=0 );
  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );








|
|












|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|


|
|
|
|
|
>
|
|
|
|
|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  static const struct TableEntry {
    unsigned short iCode;
    unsigned char flags;
    unsigned char nRange;
  } aEntry[] = {
    {65, 14, 26},          {181, 64, 1},          {192, 14, 23},
    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
    {313, 1, 16},          {330, 1, 46},          {376, 126, 1},
    {377, 1, 6},           {383, 114, 1},         {385, 50, 1},
    {386, 1, 4},           {390, 44, 1},          {391, 0, 1},
    {393, 42, 2},          {395, 0, 1},           {398, 32, 1},
    {399, 38, 1},          {400, 40, 1},          {401, 0, 1},
    {403, 42, 1},          {404, 46, 1},          {406, 52, 1},
    {407, 48, 1},          {408, 0, 1},           {412, 52, 1},
    {413, 54, 1},          {415, 56, 1},          {416, 1, 6},
    {422, 60, 1},          {423, 0, 1},           {425, 60, 1},
    {428, 0, 1},           {430, 60, 1},          {431, 0, 1},
    {433, 58, 2},          {435, 1, 4},           {439, 62, 1},
    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
    {497, 2, 1},           {498, 1, 4},           {502, 132, 1},
    {503, 144, 1},         {504, 1, 40},          {544, 120, 1},
    {546, 1, 18},          {570, 70, 1},          {571, 0, 1},
    {573, 118, 1},         {574, 68, 1},          {577, 0, 1},
    {579, 116, 1},         {580, 28, 1},          {581, 30, 1},
    {582, 1, 10},          {837, 36, 1},          {880, 1, 4},
    {886, 0, 1},           {895, 36, 1},          {902, 18, 1},
    {904, 16, 3},          {908, 26, 1},          {910, 24, 2},
    {913, 14, 17},         {931, 14, 9},          {962, 0, 1},
    {975, 4, 1},           {976, 150, 1},         {977, 152, 1},
    {981, 156, 1},         {982, 154, 1},         {984, 1, 24},
    {1008, 146, 1},        {1009, 148, 1},        {1012, 140, 1},
    {1013, 138, 1},        {1015, 0, 1},          {1017, 162, 1},
    {1018, 0, 1},          {1021, 120, 3},        {1024, 34, 16},
    {1040, 14, 32},        {1120, 1, 34},         {1162, 1, 54},
    {1216, 6, 1},          {1217, 1, 14},         {1232, 1, 96},
    {1329, 22, 38},        {4256, 66, 38},        {4295, 66, 1},
    {4301, 66, 1},         {7680, 1, 150},        {7835, 142, 1},
    {7838, 106, 1},        {7840, 1, 96},         {7944, 160, 8},
    {7960, 160, 6},        {7976, 160, 8},        {7992, 160, 8},
    {8008, 160, 6},        {8025, 161, 8},        {8040, 160, 8},
    {8072, 160, 8},        {8088, 160, 8},        {8104, 160, 8},
    {8120, 160, 2},        {8122, 136, 2},        {8124, 158, 1},
    {8126, 110, 1},        {8136, 134, 4},        {8140, 158, 1},
    {8152, 160, 2},        {8154, 130, 2},        {8168, 160, 2},
    {8170, 128, 2},        {8172, 162, 1},        {8184, 122, 2},
    {8186, 124, 2},        {8188, 158, 1},        {8486, 108, 1},
    {8490, 102, 1},        {8491, 104, 1},        {8498, 12, 1},
    {8544, 8, 16},         {8579, 0, 1},          {9398, 10, 26},
    {11264, 22, 47},       {11360, 0, 1},         {11362, 98, 1},
    {11363, 112, 1},       {11364, 100, 1},       {11367, 1, 6},
    {11373, 94, 1},        {11374, 96, 1},        {11375, 90, 1},
    {11376, 92, 1},        {11378, 0, 1},         {11381, 0, 1},
    {11390, 88, 2},        {11392, 1, 100},       {11499, 1, 4},
    {11506, 0, 1},         {42560, 1, 46},        {42624, 1, 28},
    {42786, 1, 14},        {42802, 1, 62},        {42873, 1, 4},
    {42877, 86, 1},        {42878, 1, 10},        {42891, 0, 1},
    {42893, 82, 1},        {42896, 1, 4},         {42902, 1, 20},
    {42922, 76, 1},        {42923, 72, 1},        {42924, 74, 1},
    {42925, 78, 1},        {42928, 84, 1},        {42929, 80, 1},
    {65313, 14, 26},
  };
  static const unsigned short aiOff[] = {
   1,     2,     8,     15,    16,    26,    28,    32,
   37,    38,    40,    48,    63,    64,    69,    71,
   79,    80,    116,   202,   203,   205,   206,   207,
   209,   210,   211,   213,   214,   217,   218,   219,
   775,   7264,  10792, 10795, 23217, 23221, 23228, 23231,
   23254, 23256, 23278, 30204, 54721, 54753, 54754, 54756,
   54787, 54793, 54809, 57153, 57274, 57921, 58019, 58363,
   61722, 65268, 65341, 65373, 65406, 65408, 65410, 65415,
   65424, 65436, 65439, 65450, 65462, 65472, 65476, 65478,
   65480, 65482, 65488, 65506, 65511, 65514, 65521, 65527,
   65528, 65529,
  };

  int ret = c;

  assert( c>=0 );
  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );

352
353
354
355
356
357
358
359
360
361



362
363
364
365
        ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
        assert( ret>0 );
      }
    }

    if( bRemoveDiacritic ) ret = unicode_remove_diacritic(ret);
  }
  
  else if( c>=66560 && c<66600 ){
    ret = c + 40;



  }

  return ret;
}







|


>
>
>




361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
        ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
        assert( ret>0 );
      }
    }

    if( bRemoveDiacritic ) ret = unicode_remove_diacritic(ret);
  }

  else if( c>=66560 && c<66600 ){
    ret = c + 40;
  }
  else if( c>=71840 && c<71872 ){
    ret = c + 32;
  }

  return ret;
}
Changes to src/update.c.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81





82
83
84
85
86
87
88
89
90
91
92
93
94
95


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115

116
117
118
119









120
121
122
123
124
125
126
127
128
129
130



131
132
133
134
135

136
137
138
139
140
141
142
}

/*
** COMMAND: update
**
** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
**
** Change the version of the current checkout to VERSION.  Any uncommitted
** changes are retained and applied to the new checkout.
**
** The VERSION argument can be a specific version or tag or branch name.
** If the VERSION argument is omitted, then the leaf of the subtree
** that begins at the current version is used, if there is only a single
** leaf.  VERSION can also be "current" to select the leaf of the current
** version or "latest" to select the most recent check-in.

**
** If one or more FILES are listed after the VERSION then only the
** named files are candidates to be updated.  If FILES is omitted, all
** files in the current checkout are subject to be updated.  Using
** a directory name for one of the FILES arguments is the same as
** using every subdirectory and file beneath that directory.
**





** The -n or --dry-run option causes this command to do a "dry run".  It
** prints out what would have happened but does not actually make any
** changes to the current checkout or the repository.
**
** The -v or --verbose option prints status information about unchanged
** files in addition to those file that actually do change.
**
** Options:
**   --case-sensitive <BOOL> override case-sensitive setting
**   --debug          print debug information on stdout
**   --latest         acceptable in place of VERSION, update to latest version
**   --force-missing  force update if missing content after sync
**   -n|--dry-run     If given, display instead of run actions
**   -v|--verbose     print status information about all files


**
** See also: revert
*/
void update_cmd(void){
  int vid;              /* Current version */
  int tid=0;            /* Target version - version we are changing to */
  Stmt q;
  int latestFlag;       /* --latest.  Pick the latest version if true */
  int dryRunFlag;       /* -n or --dry-run.  Do a dry run */
  int verboseFlag;      /* -v or --verbose.  Output extra information */
  int forceMissingFlag; /* --force-missing.  Continue if missing content */
  int debugFlag;        /* --debug option */
  int setmtimeFlag;     /* --setmtime.  Set mtimes on files */
  int nChng;            /* Number of file renames */
  int *aChng;           /* Array of file renames */
  int i;                /* Loop counter */
  int nConflict = 0;    /* Number of merge conflicts */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  int nUpdate = 0;      /* Number of changes of any kind */

  Stmt mtimeXfer;       /* Statement to transfer mtimes */


  if( !internalUpdate ){
    undo_capture_command_line();
    url_proxy_options();









  }
  latestFlag = find_option("latest",0, 0)!=0;
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  verboseFlag = find_option("verbose","v",0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  debugFlag = find_option("debug",0,0)!=0;
  setmtimeFlag = find_option("setmtime",0,0)!=0;
  capture_case_sensitive_option();



  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  user_select();
  if( !dryRunFlag && !internalUpdate ){
    if( autosync(SYNC_PULL + SYNC_VERBOSE*verboseFlag) ){

      fossil_fatal("Cannot proceed with update");
    }
  }
  
  /* Create any empty directories now, as well as after the update,
  ** so changes in settings are reflected now */
  if( !dryRunFlag ) ensure_empty_dirs_created();







|
|

|
|
|
|
|
>


|
|
|
|

>
>
>
>
>
|
|
|

|
|








>
>



















>

>




>
>
>
>
>
>
>
>
>










|
>
>
>




|
>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
}

/*
** COMMAND: update
**
** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
**
** Change the version of the current checkout to VERSION.  Any
** uncommitted changes are retained and applied to the new checkout.
**
** The VERSION argument can be a specific version or tag or branch
** name.  If the VERSION argument is omitted, then the leaf of the
** subtree that begins at the current version is used, if there is
** only a single leaf.  VERSION can also be "current" to select the
** leaf of the current version or "latest" to select the most recent
** check-in.
**
** If one or more FILES are listed after the VERSION then only the
** named files are candidates to be updated, and any updates to them
** will be treated as edits to the current version. Using a directory
** name for one of the FILES arguments is the same as using every
** subdirectory and file beneath that directory.
**
** If FILES is omitted, all files in the current checkout are subject
** to being updated and the version of the current checkout is changed
** to VERSION. Any uncommitted changes are retained and applied to the
** new checkout.
**
** The -n or --dry-run option causes this command to do a "dry run".
** It prints out what would have happened but does not actually make
** any changes to the current checkout or the repository.
**
** The -v or --verbose option prints status information about
** unchanged files in addition to those file that actually do change.
**
** Options:
**   --case-sensitive <BOOL> override case-sensitive setting
**   --debug          print debug information on stdout
**   --latest         acceptable in place of VERSION, update to latest version
**   --force-missing  force update if missing content after sync
**   -n|--dry-run     If given, display instead of run actions
**   -v|--verbose     print status information about all files
**   -W|--width <num> Width of lines (default is to auto-detect). Must be >20
**                    or 0 (= no limit, resulting in a single line per entry).
**
** See also: revert
*/
void update_cmd(void){
  int vid;              /* Current version */
  int tid=0;            /* Target version - version we are changing to */
  Stmt q;
  int latestFlag;       /* --latest.  Pick the latest version if true */
  int dryRunFlag;       /* -n or --dry-run.  Do a dry run */
  int verboseFlag;      /* -v or --verbose.  Output extra information */
  int forceMissingFlag; /* --force-missing.  Continue if missing content */
  int debugFlag;        /* --debug option */
  int setmtimeFlag;     /* --setmtime.  Set mtimes on files */
  int nChng;            /* Number of file renames */
  int *aChng;           /* Array of file renames */
  int i;                /* Loop counter */
  int nConflict = 0;    /* Number of merge conflicts */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  int nUpdate = 0;      /* Number of changes of any kind */
  int width;            /* Width of printed comment lines */
  Stmt mtimeXfer;       /* Statement to transfer mtimes */
  const char *zWidth;   /* Width option string value */

  if( !internalUpdate ){
    undo_capture_command_line();
    url_proxy_options();
  }
  zWidth = find_option("width","W",1);
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = -1;
  }
  latestFlag = find_option("latest",0, 0)!=0;
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  verboseFlag = find_option("verbose","v",0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  debugFlag = find_option("debug",0,0)!=0;
  setmtimeFlag = find_option("setmtime",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  user_select();
  if( !dryRunFlag && !internalUpdate ){
    if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
                      db_get_int("autosync-tries", 1)) ){
      fossil_fatal("Cannot proceed with update");
    }
  }
  
  /* Create any empty directories now, as well as after the update,
  ** so changes in settings are reflected now */
  if( !dryRunFlag ) ensure_empty_dirs_created();
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
        compute_leaves(vid, closeCode);
        db_prepare(&q, 
          "%s "
          "   AND event.objid IN leaves"
          " ORDER BY event.mtime DESC",
          timeline_query_for_tty()
        );
        print_timeline(&q, -100, 79, 0);
        db_finalize(&q);
        fossil_fatal("Multiple descendants");
      }
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 







|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
        compute_leaves(vid, closeCode);
        db_prepare(&q, 
          "%s "
          "   AND event.objid IN leaves"
          " ORDER BY event.mtime DESC",
          timeline_query_for_tty()
        );
        print_timeline(&q, -100, width, 0);
        db_finalize(&q);
        fossil_fatal("Multiple descendants");
      }
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
    "   FROM vfile WHERE vid=%d",
    vid
  );

  /* Compute file name changes on V->T.  Record name changes in files that
  ** have changed locally.
  */

  find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
  if( nChng ){
    for(i=0; i<nChng; i++){
      db_multi_exec(
        "UPDATE fv"
        "   SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
        " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
        aChng[i*2+1], aChng[i*2]
      );
    }
    fossil_free(aChng);

  }

  /* Add files found in the target version T but missing from the current
  ** version V.
  */
  db_multi_exec(
    "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)"







>
|
|
|
|
|
|
|
|
|
|
|
>







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    "   FROM vfile WHERE vid=%d",
    vid
  );

  /* Compute file name changes on V->T.  Record name changes in files that
  ** have changed locally.
  */
  if( vid ){
    find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
    if( nChng ){
      for(i=0; i<nChng; i++){
        db_multi_exec(
          "UPDATE fv"
          "   SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
          " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
          aChng[i*2+1], aChng[i*2]
        );
      }
      fossil_free(aChng);
    }
  }

  /* Add files found in the target version T but missing from the current
  ** version V.
  */
  db_multi_exec(
    "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)"
Changes to src/url.c.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define URL_REMEMBER_PW      0x008  /* Should remember pw */
#define URL_PROMPTED         0x010  /* Prompted for PW already */

/*
** The URL related data used with this subsystem.
*/
struct UrlData {
  /*
  ** NOTE: These members MUST be kept in sync with the related ones in the
  **       "Global" structure defined in "main.c".
  */
  int isFile;      /* True if a "file:" url */
  int isHttps;     /* True if a "https:" url */
  int isSsh;       /* True if an "ssh:" url */
  char *name;      /* Hostname for http: or filename for file: */
  char *hostname;  /* The HOST: parameter on http headers */
  char *protocol;  /* "http" or "https" */
  int port;        /* TCP port number for http: or https: */







<
<
<
<







41
42
43
44
45
46
47




48
49
50
51
52
53
54
#define URL_REMEMBER_PW      0x008  /* Should remember pw */
#define URL_PROMPTED         0x010  /* Prompted for PW already */

/*
** The URL related data used with this subsystem.
*/
struct UrlData {




  int isFile;      /* True if a "file:" url */
  int isHttps;     /* True if a "https:" url */
  int isSsh;       /* True if an "ssh:" url */
  char *name;      /* Hostname for http: or filename for file: */
  char *hostname;  /* The HOST: parameter on http headers */
  char *protocol;  /* "http" or "https" */
  int port;        /* TCP port number for http: or https: */
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
        cQuerySep = '&';
      }
    }

    dehttpize(pUrlData->path);
    if( pUrlData->dfltPort==pUrlData->port ){
      pUrlData->canonical = mprintf(
        "%s://%s%T%T%s", 
        pUrlData->protocol, zLogin, pUrlData->name, pUrlData->path, zExe
      );
    }else{
      pUrlData->canonical = mprintf(
        "%s://%s%T:%d%T%s",
        pUrlData->protocol, zLogin, pUrlData->name, pUrlData->port,
        pUrlData->path, zExe







|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
        cQuerySep = '&';
      }
    }

    dehttpize(pUrlData->path);
    if( pUrlData->dfltPort==pUrlData->port ){
      pUrlData->canonical = mprintf(
        "%s://%s%T%T%s",
        pUrlData->protocol, zLogin, pUrlData->name, pUrlData->path, zExe
      );
    }else{
      pUrlData->canonical = mprintf(
        "%s://%s%T:%d%T%s",
        pUrlData->protocol, zLogin, pUrlData->name, pUrlData->port,
        pUrlData->path, zExe
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    zFile = mprintf("%s", zUrl);
  }else if( file_isdir(zUrl)==1 ){
    zFile = mprintf("%s/FOSSIL", zUrl);
    if( file_isfile(zFile) ){
      pUrlData->isFile = 1;
    }else{
      free(zFile);

      fossil_fatal("unknown repository: %s", zUrl);
    }
  }else{
    fossil_fatal("unknown repository: %s", zUrl);
  }
  if( urlFlags ) pUrlData->flags = urlFlags;
  if( pUrlData->isFile ){
    Blob cfile;
    dehttpize(zFile);  
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);

    pUrlData->protocol = "file";
    pUrlData->path = "";
    pUrlData->name = mprintf("%b", &cfile);
    pUrlData->canonical = mprintf("file://%T", pUrlData->name);
    blob_reset(&cfile);
  }else if( pUrlData->user!=0 && pUrlData->passwd==0 && (urlFlags & URL_PROMPT_PW) ){
    url_prompt_for_password_local(pUrlData);
  }else if( pUrlData->user!=0 && ( urlFlags & URL_ASK_REMEMBER_PW ) ){
    if( isatty(fileno(stdin)) ){
      if( save_password_prompt(pUrlData->passwd) ){
        pUrlData->flags = urlFlags |= URL_REMEMBER_PW;
      }else{
        pUrlData->flags = urlFlags &= ~URL_REMEMBER_PW;
      }
    }
  }
}

/*
** Parse the given URL, which describes a sync server.  Populate variables 
** in the global "g" structure as follows:
**
**      g.url.isFile      True if FILE:
**      g.url.isHttps     True if HTTPS: 
**      g.url.isSsh       True if SSH:
**      g.url.protocol    "http" or "https" or "file"
**      g.url.name        Hostname for HTTP:, HTTPS:, SSH:.  Filename for FILE:
**      g.url.port        TCP port number for HTTP or HTTPS.
**      g.url.dfltPort    Default TCP port number (80 or 443).
**      g.url.path        Path name for HTTP or HTTPS.
**      g.url.user        Userid.







>








|


>



















|



|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    zFile = mprintf("%s", zUrl);
  }else if( file_isdir(zUrl)==1 ){
    zFile = mprintf("%s/FOSSIL", zUrl);
    if( file_isfile(zFile) ){
      pUrlData->isFile = 1;
    }else{
      free(zFile);
      zFile = 0;
      fossil_fatal("unknown repository: %s", zUrl);
    }
  }else{
    fossil_fatal("unknown repository: %s", zUrl);
  }
  if( urlFlags ) pUrlData->flags = urlFlags;
  if( pUrlData->isFile ){
    Blob cfile;
    dehttpize(zFile);
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);
    zFile = 0;
    pUrlData->protocol = "file";
    pUrlData->path = "";
    pUrlData->name = mprintf("%b", &cfile);
    pUrlData->canonical = mprintf("file://%T", pUrlData->name);
    blob_reset(&cfile);
  }else if( pUrlData->user!=0 && pUrlData->passwd==0 && (urlFlags & URL_PROMPT_PW) ){
    url_prompt_for_password_local(pUrlData);
  }else if( pUrlData->user!=0 && ( urlFlags & URL_ASK_REMEMBER_PW ) ){
    if( isatty(fileno(stdin)) ){
      if( save_password_prompt(pUrlData->passwd) ){
        pUrlData->flags = urlFlags |= URL_REMEMBER_PW;
      }else{
        pUrlData->flags = urlFlags &= ~URL_REMEMBER_PW;
      }
    }
  }
}

/*
** Parse the given URL, which describes a sync server.  Populate variables
** in the global "g" structure as follows:
**
**      g.url.isFile      True if FILE:
**      g.url.isHttps     True if HTTPS:
**      g.url.isSsh       True if SSH:
**      g.url.protocol    "http" or "https" or "file"
**      g.url.name        Hostname for HTTP:, HTTPS:, SSH:.  Filename for FILE:
**      g.url.port        TCP port number for HTTP or HTTPS.
**      g.url.dfltPort    Default TCP port number (80 or 443).
**      g.url.path        Path name for HTTP or HTTPS.
**      g.url.user        Userid.
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  const char *zName1,     /* First override */
  const char *zValue1,    /* First override value */
  const char *zName2,     /* Second override */
  const char *zValue2     /* Second override value */
){
  const char *zSep = "?";
  int i;
  
  blob_reset(&p->url);
  blob_appendf(&p->url, "%s/%s", g.zTop, p->zBase);
  for(i=0; i<p->nParam; i++){
    const char *z = p->azValue[i];
    if( zName1 && fossil_strcmp(zName1,p->azName[i])==0 ){
      zName1 = 0;
      z = zValue1;







|







466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
  const char *zName1,     /* First override */
  const char *zValue1,    /* First override value */
  const char *zName2,     /* Second override */
  const char *zValue2     /* Second override value */
){
  const char *zSep = "?";
  int i;

  blob_reset(&p->url);
  blob_appendf(&p->url, "%s/%s", g.zTop, p->zBase);
  for(i=0; i<p->nParam; i++){
    const char *z = p->azValue[i];
    if( zName1 && fossil_strcmp(zName1,p->azName[i])==0 ){
      zName1 = 0;
      z = zValue1;
Changes to src/user.c.
195
196
197
198
199
200
201

202
203
204
205
206
207
208
**
**    %fossil user default ?USERNAME?
**
**        Query or set the default user.  The default user is the
**        user for command-line interaction.
**
**    %fossil user list

**
**        List all users known to the repository
**
**    %fossil user new ?USERNAME? ?CONTACT-INFO? ?PASSWORD?
**
**        Create a new user in the repository.  Users can never be
**        deleted.  They can be denied all access but they must continue







>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
**
**    %fossil user default ?USERNAME?
**
**        Query or set the default user.  The default user is the
**        user for command-line interaction.
**
**    %fossil user list
**    %fossil user ls
**
**        List all users known to the repository
**
**    %fossil user new ?USERNAME? ?CONTACT-INFO? ?PASSWORD?
**
**        Create a new user in the repository.  Users can never be
**        deleted.  They can be denied all access but they must continue
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    db_multi_exec(
      "INSERT INTO user(login,pw,cap,info,mtime)"
      "VALUES(%B,%Q,%B,%B,now())",
      &login, zPw, &caps, &contact
    );
    free(zPw);
  }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
    user_select();
    if( g.argc==3 ){

      fossil_print("%s\n", g.zLogin);
    }else{
      if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.argv[3]) ){
        fossil_fatal("no such user: %s", g.argv[3]);
      }
      if( g.localOpen ){
        db_lset("default-user", g.argv[3]);
      }else{
        db_set("default-user", g.argv[3], 0);
      }
    }
  }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;
    db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
    }
    db_finalize(&q);
  }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){







<

>











|







247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    db_multi_exec(
      "INSERT INTO user(login,pw,cap,info,mtime)"
      "VALUES(%B,%Q,%B,%B,now())",
      &login, zPw, &caps, &contact
    );
    free(zPw);
  }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){

    if( g.argc==3 ){
      user_select();
      fossil_print("%s\n", g.zLogin);
    }else{
      if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.argv[3]) ){
        fossil_fatal("no such user: %s", g.argv[3]);
      }
      if( g.localOpen ){
        db_lset("default-user", g.argv[3]);
      }else{
        db_set("default-user", g.argv[3], 0);
      }
    }
  }else if(( n>=2 && strncmp(g.argv[2],"list",n)==0 ) || ( n>=2 && strncmp(g.argv[2],"ls",n)==0 )){
    Stmt q;
    db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
    }
    db_finalize(&q);
  }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
Changes to src/utf8.c.
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  }
  WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0);
  pUtf = qUtf = zUtf;
  while( *pUtf ) {
    if( *pUtf == (char)0xef ){
      wchar_t c = ((pUtf[1]&0x3f)<<6)|(pUtf[2]&0x3f);
      /* Only really convert it when the resulting char is in range. */
      if ( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
        *qUtf++ = c; pUtf+=3; continue;
      }
    }
    *qUtf++ = *pUtf++;
  }
  *qUtf = 0;
  return zUtf;







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  }
  WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0);
  pUtf = qUtf = zUtf;
  while( *pUtf ) {
    if( *pUtf == (char)0xef ){
      wchar_t c = ((pUtf[1]&0x3f)<<6)|(pUtf[2]&0x3f);
      /* Only really convert it when the resulting char is in range. */
      if( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
        *qUtf++ = c; pUtf+=3; continue;
      }
    }
    *qUtf++ = *pUtf++;
  }
  *qUtf = 0;
  return zUtf;
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  /*
  ** In the remainder of the path, translate invalid characters to
  ** characters in the Unicode private use area. This is what makes
  ** Win32 fossil.exe work well in a Cygwin environment even when a
  ** filename contains characters which are invalid for Win32.
  */
  while( *wUnicode != '\0' ){
    if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
      *wUnicode |= 0xF000;
    }else if( *wUnicode == '/' ){
      *wUnicode = '\\';
    }
    ++wUnicode;
  }
  return zUnicode;







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  /*
  ** In the remainder of the path, translate invalid characters to
  ** characters in the Unicode private use area. This is what makes
  ** Win32 fossil.exe work well in a Cygwin environment even when a
  ** filename contains characters which are invalid for Win32.
  */
  while( *wUnicode != '\0' ){
    if( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
      *wUnicode |= 0xF000;
    }else if( *wUnicode == '/' ){
      *wUnicode = '\\';
    }
    ++wUnicode;
  }
  return zUnicode;
Changes to src/util.c.
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
** Returns true (non-0) if the given timer ID (as returned from
** fossil_timer_start() is currently active.
*/
int fossil_timer_is_active( int timerId ){
  if(timerId<1 || timerId>FOSSIL_TIMER_COUNT){
    return 0;
  }else{
    int const rc = fossilTimerList[timerId-1].id;
    assert(!rc || (rc == timerId));
    return fossilTimerList[timerId-1].id;
  }
}

/*
** Return TRUE if fd is a valid open file descriptor.  This only







|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
** Returns true (non-0) if the given timer ID (as returned from
** fossil_timer_start() is currently active.
*/
int fossil_timer_is_active( int timerId ){
  if(timerId<1 || timerId>FOSSIL_TIMER_COUNT){
    return 0;
  }else{
    const int rc = fossilTimerList[timerId-1].id;
    assert(!rc || (rc == timerId));
    return fossilTimerList[timerId-1].id;
  }
}

/*
** Return TRUE if fd is a valid open file descriptor.  This only
315
316
317
318
319
320
321
322
323
324
325
326
#endif
}

/*
** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
** only lower-case ASCII hexadecimal values.
*/
int fossil_is_uuid(char const * zSym){
  return zSym
    && (UUID_SIZE==strlen(zSym))
    && validate16(zSym, UUID_SIZE);
}







|




315
316
317
318
319
320
321
322
323
324
325
326
#endif
}

/*
** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
** only lower-case ASCII hexadecimal values.
*/
int fossil_is_uuid(const char *zSym){
  return zSym
    && (UUID_SIZE==strlen(zSym))
    && validate16(zSym, UUID_SIZE);
}
Changes to src/wiki.c.
154
155
156
157
158
159
160






















161
162
163
164
165
166
167
  }else{
    @ <pre>
    @ %h(blob_str(pWiki))
    @ </pre>
  }
}
























/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
  char *zTag;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  }else{
    @ <pre>
    @ %h(blob_str(pWiki))
    @ </pre>
  }
}

/*
** Returns non-zero if moderation is required for wiki changes and wiki
** attachments.
*/
int wiki_need_moderation(
  int localUser /* Are we being called for a local interactive user? */
){
  /*
  ** If the FOSSIL_FORCE_WIKI_MODERATION variable is set, *ALL* changes for
  ** wiki pages will be required to go through moderation (even those performed
  ** by the local interactive user via the command line).  This can be useful
  ** for local (or remote) testing of the moderation subsystem and its impact
  ** on the contents and status of wiki pages.
  */
  if( fossil_getenv("FOSSIL_FORCE_WIKI_MODERATION")!=0 ){
    return 1;
  }
  if( localUser ){
    return 0;
  }
  return g.perm.ModWiki==0 && db_get_boolean("modreq-wiki",0)==1;
}

/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
  char *zTag;
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  manifest_destroy(pWiki);
  style_footer();
}

/*
** Write a wiki artifact into the repository
*/
static void wiki_put(Blob *pWiki, int parent){
  int nrid;
  if( g.perm.ModWiki || db_get_boolean("modreq-wiki",0)==0 ){
    nrid = content_put_ex(pWiki, 0, 0, 0, 0);
    if( parent) content_deltify(parent, nrid, 0);
  }else{
    nrid = content_put_ex(pWiki, 0, 0, 0, 1);
    moderation_table_create();
    db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
  }







|

|







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  manifest_destroy(pWiki);
  style_footer();
}

/*
** Write a wiki artifact into the repository
*/
static void wiki_put(Blob *pWiki, int parent, int needMod){
  int nrid;
  if( !needMod ){
    nrid = content_put_ex(pWiki, 0, 0, 0, 0);
    if( parent) content_deltify(parent, nrid, 0);
  }else{
    nrid = content_put_ex(pWiki, 0, 0, 0, 1);
    moderation_table_create();
    db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
  }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
      if( !login_is_nobody() ){
        blob_appendf(&wiki, "U %F\n", login_name());
      }
      blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, 0);
    }
    db_end_transaction(0);
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;







|







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
      if( !login_is_nobody() ){
        blob_appendf(&wiki, "U %F\n", login_name());
      }
      blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, 0, wiki_need_moderation(0));
    }
    db_end_transaction(0);
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
        blob_appendf(&wiki, "U %F\n", login_name());
      }
      appendRemark(&body, zMimetype);
      blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body));
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, rid);
      db_end_transaction(0);
    }
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;







|







678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
        blob_appendf(&wiki, "U %F\n", login_name());
      }
      appendRemark(&body, zMimetype);
      blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body));
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, rid, wiki_need_moderation(0));
      db_end_transaction(0);
    }
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
** WEBPAGE: wfind
**
** URL: /wfind?title=TITLE
** List all wiki pages whose titles contain the search text
*/
void wfind_page(void){
  Stmt q;
  const char * zTitle;
  login_check_credentials();
  if( !g.perm.RdWiki ){ login_needed(); return; }
  zTitle = PD("title","*");
  style_header("Wiki Pages Found");
  @ <ul>
  db_prepare(&q,
    "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"







|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
** WEBPAGE: wfind
**
** URL: /wfind?title=TITLE
** List all wiki pages whose titles contain the search text
*/
void wfind_page(void){
  Stmt q;
  const char *zTitle;
  login_check_credentials();
  if( !g.perm.RdWiki ){ login_needed(); return; }
  zTitle = PD("title","*");
  style_header("Wiki Pages Found");
  @ <ul>
  db_prepare(&q,
    "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
**
** The content of the new page is given by the blob pContent.
**
** zMimeType specifies the N-card for the wiki page. If it is 0,
** empty, or "text/x-fossil-wiki" (the default format) then it is
** ignored.
*/
int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent,
                    char const * zMimeType){
  Blob wiki;              /* Wiki page content */
  Blob cksum;             /* wiki checksum */
  int rid;                /* artifact ID of parent page */
  char *zDate;            /* timestamp */
  char *zUuid;            /* uuid for rid */
  
  rid = db_int(0,
     "SELECT x.rid FROM tag t, tagxref x"
     " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
     " ORDER BY x.mtime DESC LIMIT 1",
     zPageName
  );
  if( rid==0 && !isNew ){







|
|





|







980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
**
** The content of the new page is given by the blob pContent.
**
** zMimeType specifies the N-card for the wiki page. If it is 0,
** empty, or "text/x-fossil-wiki" (the default format) then it is
** ignored.
*/
int wiki_cmd_commit(const char *zPageName, int isNew, Blob *pContent,
                    const char *zMimeType, int localUser){
  Blob wiki;              /* Wiki page content */
  Blob cksum;             /* wiki checksum */
  int rid;                /* artifact ID of parent page */
  char *zDate;            /* timestamp */
  char *zUuid;            /* uuid for rid */

  rid = db_int(0,
     "SELECT x.rid FROM tag t, tagxref x"
     " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
     " ORDER BY x.mtime DESC LIMIT 1",
     zPageName
  );
  if( rid==0 && !isNew ){
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  }
  blob_appendf( &wiki, "W %d\n%s\n", blob_size(pContent),
                blob_str(pContent) );
  md5sum_blob(&wiki, &cksum);
  blob_appendf(&wiki, "Z %b\n", &cksum);
  blob_reset(&cksum);
  db_begin_transaction();
  wiki_put(&wiki, 0);
  db_end_transaction(0);
  return 1;
}

/*
** COMMAND: wiki*
**







|







1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  }
  blob_appendf( &wiki, "W %d\n%s\n", blob_size(pContent),
                blob_str(pContent) );
  md5sum_blob(&wiki, &cksum);
  blob_appendf(&wiki, "Z %b\n", &cksum);
  blob_reset(&cksum);
  db_begin_transaction();
  wiki_put(&wiki, 0, wiki_need_moderation(localUser));
  db_end_transaction(0);
  return 1;
}

/*
** COMMAND: wiki*
**
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
**
**     %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
**
**        Create a new wiki page with initial content taken from
**        FILE or from standard input.
**
**     %fossil wiki list

**
**        Lists all wiki entries, one per line, ordered
**        case-insensitively by name.
**
*/
void wiki_cmd(void){
  int n;
  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto wiki_cmd_usage;
  }
  n = strlen(g.argv[2]);
  if( n==0 ){
    goto wiki_cmd_usage;
  }

  if( strncmp(g.argv[2],"export",n)==0 ){
    char const *zPageName;        /* Name of the wiki page to export */
    char const *zFile;            /* Name of the output file (0=stdout) */
    int rid;                      /* Artifact ID of the wiki page */
    int i;                        /* Loop counter */
    char *zBody = 0;              /* Wiki page content */
    Blob body;                    /* Wiki page content */
    Manifest *pWiki = 0;          /* Parsed wiki page content */
    if( (g.argc!=4) && (g.argc!=5) ){
      usage("export PAGENAME ?FILE?");







>

















|
|







1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
**
**     %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
**
**        Create a new wiki page with initial content taken from
**        FILE or from standard input.
**
**     %fossil wiki list
**     %fossil wiki ls
**
**        Lists all wiki entries, one per line, ordered
**        case-insensitively by name.
**
*/
void wiki_cmd(void){
  int n;
  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto wiki_cmd_usage;
  }
  n = strlen(g.argv[2]);
  if( n==0 ){
    goto wiki_cmd_usage;
  }

  if( strncmp(g.argv[2],"export",n)==0 ){
    const char *zPageName;        /* Name of the wiki page to export */
    const char *zFile;            /* Name of the output file (0=stdout) */
    int rid;                      /* Artifact ID of the wiki page */
    int i;                        /* Loop counter */
    char *zBody = 0;              /* Wiki page content */
    Blob body;                    /* Wiki page content */
    Manifest *pWiki = 0;          /* Parsed wiki page content */
    if( (g.argc!=4) && (g.argc!=5) ){
      usage("export PAGENAME ?FILE?");
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
    blob_append(&body, "\n", 1);
    blob_write_to_file(&body, zFile);
    blob_reset(&body);
    manifest_destroy(pWiki);
    return;
  }else if( strncmp(g.argv[2],"commit",n)==0
            || strncmp(g.argv[2],"create",n)==0 ){
    char const *zPageName;        /* page name */
    Blob content;                 /* Input content */
    int rid;
    Manifest *pWiki = 0;          /* Parsed wiki page content */
    char const * zMimeType = find_option("mimetype", "M", 1);
    if( g.argc!=4 && g.argc!=5 ){
      usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
    }
    zPageName = g.argv[3];
    if( g.argc==4 ){
      blob_read_from_channel(&content, stdin, -1);
    }else{







|



|







1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
    blob_append(&body, "\n", 1);
    blob_write_to_file(&body, zFile);
    blob_reset(&body);
    manifest_destroy(pWiki);
    return;
  }else if( strncmp(g.argv[2],"commit",n)==0
            || strncmp(g.argv[2],"create",n)==0 ){
    const char *zPageName;        /* page name */
    Blob content;                 /* Input content */
    int rid;
    Manifest *pWiki = 0;          /* Parsed wiki page content */
    const char *zMimeType = find_option("mimetype", "M", 1);
    if( g.argc!=4 && g.argc!=5 ){
      usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
    }
    zPageName = g.argv[3];
    if( g.argc==4 ){
      blob_read_from_channel(&content, stdin, -1);
    }else{
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
                   );
      if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
         && (pWiki->zMimetype && *pWiki->zMimetype)){
        zMimeType = pWiki->zMimetype;
      }
    }
    if( g.argv[2][1]=='r' ){
      wiki_cmd_commit(zPageName, 1, &content, zMimeType);
      fossil_print("Created new wiki page %s.\n", zPageName);
    }else{
      wiki_cmd_commit(zPageName, 0, &content, zMimeType);
      fossil_print("Updated wiki page %s.\n", zPageName);
    }
    manifest_destroy(pWiki);
    blob_reset(&content);
  }else if( strncmp(g.argv[2],"delete",n)==0 ){
    if( g.argc!=5 ){
      usage("delete PAGENAME");
    }
    fossil_fatal("delete not yet implemented.");
  }else if( strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;
    db_prepare(&q,
      "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
      " ORDER BY lower(tagname) /*sort*/"
    );
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);







|


|









|







1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
                   );
      if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
         && (pWiki->zMimetype && *pWiki->zMimetype)){
        zMimeType = pWiki->zMimetype;
      }
    }
    if( g.argv[2][1]=='r' ){
      wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
      fossil_print("Created new wiki page %s.\n", zPageName);
    }else{
      wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
      fossil_print("Updated wiki page %s.\n", zPageName);
    }
    manifest_destroy(pWiki);
    blob_reset(&content);
  }else if( strncmp(g.argv[2],"delete",n)==0 ){
    if( g.argc!=5 ){
      usage("delete PAGENAME");
    }
    fossil_fatal("delete not yet implemented.");
  }else if(( strncmp(g.argv[2],"list",n)==0 ) || ( strncmp(g.argv[2],"ls",n)==0 )){
    Stmt q;
    db_prepare(&q,
      "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
      " ORDER BY lower(tagname) /*sort*/"
    );
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
Changes to src/winhttp.c.
30
31
32
33
34
35
36

37
38
39
40
41
42
43
** HTTP request.
*/
typedef struct HttpRequest HttpRequest;
struct HttpRequest {
  int id;                /* ID counter */
  SOCKET s;              /* Socket on which to receive data */
  SOCKADDR_IN addr;      /* Address from which data is coming */

  const char *zOptions;  /* --notfound and/or --localauth options */
};

/*
** Prefix for a temporary file.
*/
static char *zTempPrefix;







>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
** HTTP request.
*/
typedef struct HttpRequest HttpRequest;
struct HttpRequest {
  int id;                /* ID counter */
  SOCKET s;              /* Socket on which to receive data */
  SOCKADDR_IN addr;      /* Address from which data is coming */
  int flags;             /* Flags passed to win32_http_server() */
  const char *zOptions;  /* --notfound and/or --localauth options */
};

/*
** Prefix for a temporary file.
*/
static char *zTempPrefix;
109
110
111
112
113
114
115







116
117




118
119

120
121
122
123
124
125
126
    }else{
      break;
    }
    wanted -= got;
  }
  fclose(out);
  out = 0;







  sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s",
    get_utf8_bom(0), g.zRepositoryName, zRequestFName, zReplyFName,




    inet_ntoa(p->addr.sin_addr)
  );

  out = fossil_fopen(zCmdFName, "wb");
  if( out==0 ) goto end_request;
  fwrite(zCmd, 1, strlen(zCmd), out);
  fclose(out);

  sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http -args \"%s\" --nossl%s",
    g.nameOfExe, zCmdFName, p->zOptions







>
>
>
>
>
>
>
|
|
>
>
>
>
|
|
>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    }else{
      break;
    }
    wanted -= got;
  }
  fclose(out);
  out = 0;
  /*
  ** The repository name is only needed if there was no open checkout.  This
  ** is designed to allow the open checkout for the interactive user to work
  ** with the local Fossil server started via the "ui" command.
  */
  if( (p->flags & HTTP_SERVER_HAD_CHECKOUT)==0 ){
    assert( g.zRepositoryName && g.zRepositoryName[0] );
    sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s",
      get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr),
      g.zRepositoryName
    );
  }else{
    sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s",
      get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr)
    );
  }
  out = fossil_fopen(zCmdFName, "wb");
  if( out==0 ) goto end_request;
  fwrite(zCmd, 1, strlen(zCmd), out);
  fclose(out);

  sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http -args \"%s\" --nossl%s",
    g.nameOfExe, zCmdFName, p->zOptions
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
    got = recv(p->s, zHdr, wanted<sizeof(zHdr) ? wanted : sizeof(zHdr), 0);
    if( got<=0 ) break;
    fwrite(zHdr, 1, got, out);
    wanted += got;
  }
  fclose(out);
  out = 0;

  sqlite3_snprintf(sizeof(zCmd), zCmd,
    "\"%s\" http \"%s\" %s %s %s --scgi --nossl%s",
    g.nameOfExe, g.zRepositoryName, zRequestFName, zReplyFName,
    inet_ntoa(p->addr.sin_addr), p->zOptions
  );
  fossil_system(zCmd);
  in = fossil_fopen(zReplyFName, "rb");
  if( in ){
    while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
      send(p->s, zHdr, got, 0);
    }







>

|
|
|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    got = recv(p->s, zHdr, wanted<sizeof(zHdr) ? wanted : sizeof(zHdr), 0);
    if( got<=0 ) break;
    fwrite(zHdr, 1, got, out);
    wanted += got;
  }
  fclose(out);
  out = 0;
  assert( g.zRepositoryName && g.zRepositoryName[0] );
  sqlite3_snprintf(sizeof(zCmd), zCmd,
    "\"%s\" http \"%s\" \"%s\" %s \"%s\" --scgi --nossl%s",
    g.nameOfExe, zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr),
    g.zRepositoryName, p->zOptions
  );
  fossil_system(zCmd);
  in = fossil_fopen(zReplyFName, "rb");
  if( in ){
    while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
      send(p->s, zHdr, got, 0);
    }
316
317
318
319
320
321
322

323
324
325
326
327
328
329
    }else if( zStopper && file_size(zStopper)>=0 ){
      break;
    }
    p = fossil_malloc( sizeof(*p) );
    p->id = ++idCnt;
    p->s = client;
    p->addr = client_addr;

    p->zOptions = blob_str(&options);
    if( flags & HTTP_SERVER_SCGI ){
      _beginthread(win32_scgi_request, 0, (void*)p);
    }else{
      _beginthread(win32_http_request, 0, (void*)p);
    }
  }







>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    }else if( zStopper && file_size(zStopper)>=0 ){
      break;
    }
    p = fossil_malloc( sizeof(*p) );
    p->id = ++idCnt;
    p->s = client;
    p->addr = client_addr;
    p->flags = flags;
    p->zOptions = blob_str(&options);
    if( flags & HTTP_SERVER_SCGI ){
      _beginthread(win32_scgi_request, 0, (void*)p);
    }else{
      _beginthread(win32_http_request, 0, (void*)p);
    }
  }
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691





692
693
694
695
696
697
698
    const char *zStart      = find_option("start", "S", 1);
    const char *zUsername   = find_option("username", "U", 1);
    const char *zPassword   = find_option("password", "W", 1);
    const char *zPort       = find_option("port", "P", 1);
    const char *zNotFound   = find_option("notfound", 0, 1);
    const char *zFileGlob   = find_option("files", 0, 1);
    const char *zLocalAuth  = find_option("localauth", 0, 0);
    const char *zRepository = find_option("repository", "R", 1);
    int useSCGI             = find_option("scgi", 0, 0)!=0;
    Blob binPath;

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for create method.");
    }
    /* Process service creation specific options. */
    if( !zDisplay ){
      zDisplay = zSvcName;





    }
    if( zStart ){
      if( strncmp(zStart, "auto", strlen(zStart))==0 ){
        dwStartType = SERVICE_AUTO_START;
      }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
        dwStartType = SERVICE_DEMAND_START;
      }else{







|







|




>
>
>
>
>







687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
    const char *zStart      = find_option("start", "S", 1);
    const char *zUsername   = find_option("username", "U", 1);
    const char *zPassword   = find_option("password", "W", 1);
    const char *zPort       = find_option("port", "P", 1);
    const char *zNotFound   = find_option("notfound", 0, 1);
    const char *zFileGlob   = find_option("files", 0, 1);
    const char *zLocalAuth  = find_option("localauth", 0, 0);
    const char *zRepository = find_repository_option();
    int useSCGI             = find_option("scgi", 0, 0)!=0;
    Blob binPath;

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("too many arguments for create method.");
    }
    /* Process service creation specific options. */
    if( !zDisplay ){
      zDisplay = zSvcName;
    }
    /* Per MSDN, the password parameter cannot be NULL.  Must use empty
    ** string instead (i.e. in the call to CreateServiceW). */
    if( !zPassword ){
      zPassword = "";
    }
    if( zStart ){
      if( strncmp(zStart, "auto", strlen(zStart))==0 ){
        dwStartType = SERVICE_AUTO_START;
      }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
        dwStartType = SERVICE_DEMAND_START;
      }else{
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
             SERVICE_WIN32_OWN_PROCESS,               /* Service type */
             dwStartType,                             /* Start type */
             SERVICE_ERROR_NORMAL,                    /* Error control */
             fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
             NULL,                                    /* Load ordering group */
             NULL,                                    /* Tag value */
             NULL,                                    /* Service dependencies */
             fossil_utf8_to_unicode(zUsername),       /* Service account */
             fossil_utf8_to_unicode(zPassword)        /* Account password */
           );
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    /* Set the service description. */
    ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
    fossil_print("Service '%s' successfully created.\n", zSvcName);
    CloseServiceHandle(hSvc);
    CloseServiceHandle(hScm);
  }else
  if( strncmp(zMethod, "delete", n)==0 ){
    SC_HANDLE hScm;
    SC_HANDLE hSvc;
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to delete service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for delete method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);







|



















|







754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
             SERVICE_WIN32_OWN_PROCESS,               /* Service type */
             dwStartType,                             /* Start type */
             SERVICE_ERROR_NORMAL,                    /* Error control */
             fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
             NULL,                                    /* Load ordering group */
             NULL,                                    /* Tag value */
             NULL,                                    /* Service dependencies */
             zUsername ? fossil_utf8_to_unicode(zUsername) : 0, /* Account */
             fossil_utf8_to_unicode(zPassword)        /* Account password */
           );
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    /* Set the service description. */
    ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
    fossil_print("Service '%s' successfully created.\n", zSvcName);
    CloseServiceHandle(hSvc);
    CloseServiceHandle(hScm);
  }else
  if( strncmp(zMethod, "delete", n)==0 ){
    SC_HANDLE hScm;
    SC_HANDLE hSvc;
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to delete service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("too many arguments for delete method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
    };
    const char *zSvcState = "";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for show method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    /* Get the service configuration */
    bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired);







|







843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
    };
    const char *zSvcState = "";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("too many arguments for show method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    /* Get the service configuration */
    bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired);
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to start service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for start method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);







|







925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to start service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("too many arguments for start method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to stop service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for stop method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);







|







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
    SERVICE_STATUS sstat;
    char *zErrFmt = "unable to stop service '%s': %s";

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("too many arguments for stop method.");
    }
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
                        SERVICE_ALL_ACCESS);
    if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
    QueryServiceStatus(hSvc, &sstat);
Changes to src/wysiwyg.c.
249
250
251
252
253
254
255




256








257
258
259
260
261
262
263
  @   if(oDoc.style.whiteSpace=="pre-wrap"){setDocMode(0);}
  @   document.getElementById("wysiwygValue").value=oDoc.innerHTML;
  @ }
  @
  @ /* Run the editing command if in WYSIWYG mode */
  @ function formatDoc(sCmd, sValue) {
  @   if (isWysiwyg()){




  @     document.execCommand("styleWithCSS", false, false);








  @     document.execCommand(sCmd, false, sValue);
  @     oDoc.focus();
  @   }
  @ }
  @
  @ /* Change the editing mode.  Convert to markup if the argument
  @ ** is true and wysiwyg if the argument is false. */







>
>
>
>
|
>
>
>
>
>
>
>
>







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  @   if(oDoc.style.whiteSpace=="pre-wrap"){setDocMode(0);}
  @   document.getElementById("wysiwygValue").value=oDoc.innerHTML;
  @ }
  @
  @ /* Run the editing command if in WYSIWYG mode */
  @ function formatDoc(sCmd, sValue) {
  @   if (isWysiwyg()){
  @     try {
  @       // First, try the W3C draft standard way, which has
  @       // been working on all non-IE browsers for a while.
  @       // It is also supported by IE11 and higher.
  @       document.execCommand("styleWithCSS", false, false);
  @     } catch (e) {
  @       try {
  @         // For IE9 or IE10, this should work.
  @         document.execCommand("useCSS", 0, true);
  @       } catch (e) {
  @         // Ok, that apparently did not work, do nothing.
  @       }
  @     }
  @     document.execCommand(sCmd, false, sValue);
  @     oDoc.focus();
  @   }
  @ }
  @
  @ /* Change the editing mode.  Convert to markup if the argument
  @ ** is true and wysiwyg if the argument is false. */
Changes to src/xfer.c.
111
112
113
114
115
116
117
118





119
120
121
122
123
124
125
**
** If any error occurs, write a message into pErr which has already
** be initialized to an empty string.
**
** Any artifact successfully received by this routine is considered to
** be public and is therefore removed from the "private" table.
*/
static void xfer_accept_file(Xfer *pXfer, int cloneFlag){





  int n;
  int rid;
  int srcid = 0;
  Blob content, hash;
  int isPriv;

  isPriv = pXfer->nextIsPrivate;







|
>
>
>
>
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
**
** If any error occurs, write a message into pErr which has already
** be initialized to an empty string.
**
** Any artifact successfully received by this routine is considered to
** be public and is therefore removed from the "private" table.
*/
static void xfer_accept_file(
  Xfer *pXfer,
  int cloneFlag,
  char **pzUuidList,
  int *pnUuidList
){
  int n;
  int rid;
  int srcid = 0;
  Blob content, hash;
  int isPriv;

  isPriv = pXfer->nextIsPrivate;
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
      pXfer->nDeltaRcvd++;
    }else{
      srcid = 0;
      pXfer->nFileRcvd++;
    }
    rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                         0, isPriv);


    remote_has(rid);
    blob_reset(&content);
    return;
  }
  if( pXfer->nToken==4 ){
    Blob src, next;
    srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
    if( content_get(srcid, &src)==0 ){
      rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                           0, isPriv);


      pXfer->nDanglingFile++;
      db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
      if( !isPriv ) content_make_public(rid);
      blob_reset(&src);
      blob_reset(&content);
      return;
    }
    pXfer->nDeltaRcvd++;
    blob_delta_apply(&src, &content, &next);
    blob_reset(&src);
    blob_reset(&content);
    content = next;
  }else{
    pXfer->nFileRcvd++;
  }
  sha1sum_blob(&content, &hash);
  if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
    blob_appendf(&pXfer->err, "content does not match sha1 hash");
  }
  rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv);

  blob_reset(&hash);
  if( rid==0 ){
    blob_appendf(&pXfer->err, "%s", g.zErrMsg);
    blob_reset(&content);
  }else{
    if( !isPriv ) content_make_public(rid);
    manifest_crosslink(rid, &content, MC_NONE);







>
>










>
>




















>







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
      pXfer->nDeltaRcvd++;
    }else{
      srcid = 0;
      pXfer->nFileRcvd++;
    }
    rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                         0, isPriv);
    Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
                    blob_size(&pXfer->aToken[1]));
    remote_has(rid);
    blob_reset(&content);
    return;
  }
  if( pXfer->nToken==4 ){
    Blob src, next;
    srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
    if( content_get(srcid, &src)==0 ){
      rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                           0, isPriv);
      Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
                      blob_size(&pXfer->aToken[1]));
      pXfer->nDanglingFile++;
      db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
      if( !isPriv ) content_make_public(rid);
      blob_reset(&src);
      blob_reset(&content);
      return;
    }
    pXfer->nDeltaRcvd++;
    blob_delta_apply(&src, &content, &next);
    blob_reset(&src);
    blob_reset(&content);
    content = next;
  }else{
    pXfer->nFileRcvd++;
  }
  sha1sum_blob(&content, &hash);
  if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
    blob_appendf(&pXfer->err, "content does not match sha1 hash");
  }
  rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv);
  Th_AppendToList(pzUuidList, pnUuidList, blob_str(&hash), blob_size(&hash));
  blob_reset(&hash);
  if( rid==0 ){
    blob_appendf(&pXfer->err, "%s", g.zErrMsg);
    blob_reset(&content);
  }else{
    if( !isPriv ) content_make_public(rid);
    manifest_crosslink(rid, &content, MC_NONE);
218
219
220
221
222
223
224
225




226
227
228
229
230
231
232
**
** If any error occurs, write a message into pErr which has already
** be initialized to an empty string.
**
** Any artifact successfully received by this routine is considered to
** be public and is therefore removed from the "private" table.
*/
static void xfer_accept_compressed_file(Xfer *pXfer){




  int szC;   /* CSIZE */
  int szU;   /* USIZE */
  int rid;
  int srcid = 0;
  Blob content;
  int isPriv;








|
>
>
>
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
**
** If any error occurs, write a message into pErr which has already
** be initialized to an empty string.
**
** Any artifact successfully received by this routine is considered to
** be public and is therefore removed from the "private" table.
*/
static void xfer_accept_compressed_file(
  Xfer *pXfer,
  char **pzUuidList,
  int *pnUuidList
){
  int szC;   /* CSIZE */
  int szU;   /* USIZE */
  int rid;
  int srcid = 0;
  Blob content;
  int isPriv;

259
260
261
262
263
264
265


266
267
268
269
270
271
272
    pXfer->nDeltaRcvd++;
  }else{
    srcid = 0;
    pXfer->nFileRcvd++;
  }
  rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                       szC, isPriv);


  remote_has(rid);
  blob_reset(&content);
}

/*
** Try to send a file as a delta against its parent.
** If successful, return the number of bytes in the delta.







>
>







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    pXfer->nDeltaRcvd++;
  }else{
    srcid = 0;
    pXfer->nFileRcvd++;
  }
  rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
                       szC, isPriv);
  Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
                  blob_size(&pXfer->aToken[1]));
  remote_has(rid);
  blob_reset(&content);
}

/*
** Try to send a file as a delta against its parent.
** If successful, return the number of bytes in the delta.
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
        nUncl -= nRow;
        nRow = 0;
        blob_appendf(&deleteWhere, ",%d", rid);
      }
    }
    db_finalize(&q);
    db_multi_exec(
      "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",

      blob_str(&deleteWhere)
    );
    blob_reset(&deleteWhere);
    if( nRow>0 ){
      md5sum_blob(&cluster, &cksum);
      blob_appendf(&cluster, "Z %b\n", &cksum);
      blob_reset(&cksum);







|
>







714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
        nUncl -= nRow;
        nRow = 0;
        blob_appendf(&deleteWhere, ",%d", rid);
      }
    }
    db_finalize(&q);
    db_multi_exec(
      "DELETE FROM unclustered WHERE rid NOT IN (0 %s)"
      "   AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=unclustered.rid)",
      blob_str(&deleteWhere)
    );
    blob_reset(&deleteWhere);
    if( nRow>0 ){
      md5sum_blob(&cluster, &cksum);
      blob_appendf(&cluster, "Z %b\n", &cksum);
      blob_reset(&cksum);
850
851
852
853
854
855
856
857




858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
const char *xfer_ticket_code(void){
  return db_get("xfer-ticket-script", 0);
}

/*
** Run the specified TH1 script, if any, and returns 1 on error.
*/
int xfer_run_script(const char *zScript, const char *zUuid){




  int rc;
  if( !zScript ) return TH_OK;
  Th_FossilInit(TH_INIT_DEFAULT);
  if( zUuid ){
    rc = Th_SetVar(g.interp, "uuid", -1, zUuid, -1);
    if( rc!=TH_OK ){
      fossil_error(1, "%s", Th_GetResult(g.interp, 0));
      return rc;
    }
  }
  rc = Th_Eval(g.interp, 0, zScript, -1);
  if( rc!=TH_OK ){
    fossil_error(1, "%s", Th_GetResult(g.interp, 0));
  }
  return rc;
}

/*
** Runs the pre-transfer TH1 script, if any, and returns its return code.
** This script may be run multiple times.  If the script performs actions
** that cannot be redone, it should use an internal [if] guard similar to
** the following:
**
** if {![info exists common_done]} {
**   # ... code here
**   set common_done 1
** }
*/
int xfer_run_common_script(void){
  return xfer_run_script(xfer_common_code(), 0);
}

/*
** If this variable is set, disable login checks.  Used for debugging
** only.
*/
static int disableLogin = 0;







|
>
>
>
>
|
|

|
<
<
<
<
<
<



















|







867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882






883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
const char *xfer_ticket_code(void){
  return db_get("xfer-ticket-script", 0);
}

/*
** Run the specified TH1 script, if any, and returns 1 on error.
*/
int xfer_run_script(
  const char *zScript,
  const char *zUuidOrList,
  int bIsList
){
  int rc = TH_OK;
  if( !zScript ) return rc;
  Th_FossilInit(TH_INIT_DEFAULT);
  Th_Store(bIsList ? "uuids" : "uuid", zUuidOrList ? zUuidOrList : "");






  rc = Th_Eval(g.interp, 0, zScript, -1);
  if( rc!=TH_OK ){
    fossil_error(1, "%s", Th_GetResult(g.interp, 0));
  }
  return rc;
}

/*
** Runs the pre-transfer TH1 script, if any, and returns its return code.
** This script may be run multiple times.  If the script performs actions
** that cannot be redone, it should use an internal [if] guard similar to
** the following:
**
** if {![info exists common_done]} {
**   # ... code here
**   set common_done 1
** }
*/
int xfer_run_common_script(void){
  return xfer_run_script(xfer_common_code(), 0, 0);
}

/*
** If this variable is set, disable login checks.  Used for debugging
** only.
*/
static int disableLogin = 0;
914
915
916
917
918
919
920





921
922
923
924
925
926
927
  int deltaFlag = 0;
  int isClone = 0;
  int nGimme = 0;
  int size;
  int recvConfig = 0;
  char *zNow;
  int rc;






  if( fossil_strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
     fossil_redirect_home();
  }
  g.zLogin = "anonymous";
  login_set_anon_nobody_capabilities();
  login_check_credentials();







>
>
>
>
>







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  int deltaFlag = 0;
  int isClone = 0;
  int nGimme = 0;
  int size;
  int recvConfig = 0;
  char *zNow;
  int rc;
  const char *zScript = 0;
  char *zUuidList = 0;
  int nUuidList = 0;
  char **pzUuidList = 0;
  int *pnUuidList = 0;

  if( fossil_strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
     fossil_redirect_home();
  }
  g.zLogin = "anonymous";
  login_set_anon_nobody_capabilities();
  login_check_credentials();
948
949
950
951
952
953
954





955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  );
  manifest_crosslink_begin();
  rc = xfer_run_common_script();
  if( rc==TH_ERROR ){
    cgi_reset_content();
    @ error common\sscript\sfailed:\s%F(g.zErrMsg)
    nErr++;





  }
  while( blob_line(xfer.pIn, &xfer.line) ){
    if( blob_buffer(&xfer.line)[0]=='#' ) continue;
    if( blob_size(&xfer.line)==0 ) continue;
    xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));

    /*   file UUID SIZE \n CONTENT
    **   file UUID DELTASRC SIZE \n CONTENT
    **
    ** Accept a file from the client.
    */
    if( blob_eq(&xfer.aToken[0], "file") ){
      if( !isPush ){
        cgi_reset_content();
        @ error not\sauthorized\sto\swrite
        nErr++;
        break;
      }
      xfer_accept_file(&xfer, 0);
      if( blob_size(&xfer.err) ){
        cgi_reset_content();
        @ error %T(blob_str(&xfer.err))
        nErr++;
        break;
      }
    }else

    /*   cfile UUID USIZE CSIZE \n CONTENT
    **   cfile UUID DELTASRC USIZE CSIZE \n CONTENT
    **
    ** Accept a file from the client.
    */
    if( blob_eq(&xfer.aToken[0], "cfile") ){
      if( !isPush ){
        cgi_reset_content();
        @ error not\sauthorized\sto\swrite
        nErr++;
        break;
      }
      xfer_accept_compressed_file(&xfer);
      if( blob_size(&xfer.err) ){
        cgi_reset_content();
        @ error %T(blob_str(&xfer.err))
        nErr++;
        break;
      }
    }else







>
>
>
>
>


















|




















|







968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  );
  manifest_crosslink_begin();
  rc = xfer_run_common_script();
  if( rc==TH_ERROR ){
    cgi_reset_content();
    @ error common\sscript\sfailed:\s%F(g.zErrMsg)
    nErr++;
  }
  zScript = xfer_push_code();
  if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
    pzUuidList = &zUuidList;
    pnUuidList = &nUuidList;
  }
  while( blob_line(xfer.pIn, &xfer.line) ){
    if( blob_buffer(&xfer.line)[0]=='#' ) continue;
    if( blob_size(&xfer.line)==0 ) continue;
    xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));

    /*   file UUID SIZE \n CONTENT
    **   file UUID DELTASRC SIZE \n CONTENT
    **
    ** Accept a file from the client.
    */
    if( blob_eq(&xfer.aToken[0], "file") ){
      if( !isPush ){
        cgi_reset_content();
        @ error not\sauthorized\sto\swrite
        nErr++;
        break;
      }
      xfer_accept_file(&xfer, 0, pzUuidList, pnUuidList);
      if( blob_size(&xfer.err) ){
        cgi_reset_content();
        @ error %T(blob_str(&xfer.err))
        nErr++;
        break;
      }
    }else

    /*   cfile UUID USIZE CSIZE \n CONTENT
    **   cfile UUID DELTASRC USIZE CSIZE \n CONTENT
    **
    ** Accept a file from the client.
    */
    if( blob_eq(&xfer.aToken[0], "cfile") ){
      if( !isPush ){
        cgi_reset_content();
        @ error not\sauthorized\sto\swrite
        nErr++;
        break;
      }
      xfer_accept_compressed_file(&xfer, pzUuidList, pnUuidList);
      if( blob_size(&xfer.err) ){
        cgi_reset_content();
        @ error %T(blob_str(&xfer.err))
        nErr++;
        break;
      }
    }else
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287



1288
1289
1290
1291
1292
1293
1294
      @ error bad\scommand:\s%F(blob_str(&xfer.line))
    }
    blobarray_reset(xfer.aToken, xfer.nToken);
    blob_reset(&xfer.line);
  }
  if( isPush ){
    if( rc==TH_OK ){
      rc = xfer_run_script(xfer_push_code(), 0);
      if( rc==TH_ERROR ){
        cgi_reset_content();
        @ error push\sscript\sfailed:\s%F(g.zErrMsg)
        nErr++;
      }
    }
    request_phantoms(&xfer, 500);
  }



  if( isClone && nGimme==0 ){
    /* The initial "clone" message from client to server contains no
    ** "gimme" cards. On that initial message, send the client an "igot"
    ** card for every artifact currently in the repository.  This will
    ** cause the client to create phantoms for all artifacts, which will
    ** in turn make sure that the entire repository is sent efficiently
    ** and expeditiously.







|








>
>
>







1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
      @ error bad\scommand:\s%F(blob_str(&xfer.line))
    }
    blobarray_reset(xfer.aToken, xfer.nToken);
    blob_reset(&xfer.line);
  }
  if( isPush ){
    if( rc==TH_OK ){
      rc = xfer_run_script(zScript, zUuidList, 1);
      if( rc==TH_ERROR ){
        cgi_reset_content();
        @ error push\sscript\sfailed:\s%F(g.zErrMsg)
        nErr++;
      }
    }
    request_phantoms(&xfer, 500);
  }
  if( zUuidList ){
    Th_Free(g.interp, zUuidList);
  }
  if( isClone && nGimme==0 ){
    /* The initial "clone" message from client to server contains no
    ** "gimme" cards. On that initial message, send the client an "igot"
    ** card for every artifact currently in the repository.  This will
    ** cause the client to create phantoms for all artifacts, which will
    ** in turn make sure that the entire repository is sent efficiently
    ** and expeditiously.
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658

      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **
      ** Receive a file transmitted from the server.
      */
      if( blob_eq(&xfer.aToken[0],"file") ){
        xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0);
        nArtifactRcvd++;
      }else

      /*   cfile UUID USIZE CSIZE \n CONTENT
      **   cfile UUID DELTASRC USIZE CSIZE \n CONTENT
      **
      ** Receive a compressed file transmitted from the server.
      */
      if( blob_eq(&xfer.aToken[0],"cfile") ){
        xfer_accept_compressed_file(&xfer);
        nArtifactRcvd++;
      }else

      /*   gimme UUID
      **
      ** Server is requesting a file.  If the file is a manifest, assume
      ** that the server will also want to know all of the content files







|









|







1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686

      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **
      ** Receive a file transmitted from the server.
      */
      if( blob_eq(&xfer.aToken[0],"file") ){
        xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
        nArtifactRcvd++;
      }else

      /*   cfile UUID USIZE CSIZE \n CONTENT
      **   cfile UUID DELTASRC USIZE CSIZE \n CONTENT
      **
      ** Receive a compressed file transmitted from the server.
      */
      if( blob_eq(&xfer.aToken[0],"cfile") ){
        xfer_accept_compressed_file(&xfer, 0, 0);
        nArtifactRcvd++;
      }else

      /*   gimme UUID
      **
      ** Server is requesting a file.  If the file is a manifest, assume
      ** that the server will also want to know all of the content files
1830
1831
1832
1833
1834
1835
1836


1837
1838
1839
1840
1841
1842
1843
              go = 1;
              if( g.cgiOutput==0 ){
                g.url.flags |= URL_PROMPT_PW;
                g.url.flags &= ~URL_PROMPTED;
                url_prompt_for_password();
                url_remember();
              }


            }
          }else{
            blob_appendf(&xfer.err, "server says: %s\n", zMsg);
            nErr++;
          }
          break;
        }







>
>







1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
              go = 1;
              if( g.cgiOutput==0 ){
                g.url.flags |= URL_PROMPT_PW;
                g.url.flags &= ~URL_PROMPTED;
                url_prompt_for_password();
                url_remember();
              }
            }else{
              nErr++;
            }
          }else{
            blob_appendf(&xfer.err, "server says: %s\n", zMsg);
            nErr++;
          }
          break;
        }
Changes to src/zip.c.
15
16
17
18
19
20
21




22

23
24
25
26
27
28
29
**
*******************************************************************************
**
** This file contains code used to generate ZIP archives.
*/
#include "config.h"
#include <assert.h>




#include <zlib.h>

#include "zip.h"

/*
** Write a 16- or 32-bit integer as little-endian into the given buffer.
*/
static void put16(char *z, int v){
  z[0] = v & 0xff;







>
>
>
>
|
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
**
*******************************************************************************
**
** This file contains code used to generate ZIP archives.
*/
#include "config.h"
#include <assert.h>
#if defined(FOSSIL_ENABLE_MINIZ)
#  define MINIZ_HEADER_FILE_ONLY
#  include "miniz.c"
#else
#  include <zlib.h>
#endif
#include "zip.h"

/*
** Write a 16- or 32-bit integer as little-endian into the given buffer.
*/
static void put16(char *z, int v){
  z[0] = v & 0xff;
343
344
345
346
347
348
349
350
351


352
353
354
355
356
357
358
  if( pManifest ){
    char *zName;
    zip_set_timedate(pManifest->rDate);
    if( db_get_boolean("manifest", 0) ){
      blob_append(&filename, "manifest", -1);
      zName = blob_str(&filename);
      zip_add_folders(zName);
      zip_add_file(zName, &mfile, 0);
      sha1sum_blob(&mfile, &hash);


      blob_reset(&mfile);
      blob_append(&hash, "\n", 1);
      blob_resize(&filename, nPrefix);
      blob_append(&filename, "manifest.uuid", -1);
      zName = blob_str(&filename);
      zip_add_file(zName, &hash, 0);
      blob_reset(&hash);







<

>
>







348
349
350
351
352
353
354

355
356
357
358
359
360
361
362
363
364
  if( pManifest ){
    char *zName;
    zip_set_timedate(pManifest->rDate);
    if( db_get_boolean("manifest", 0) ){
      blob_append(&filename, "manifest", -1);
      zName = blob_str(&filename);
      zip_add_folders(zName);

      sha1sum_blob(&mfile, &hash);
      sterilize_manifest(&mfile);
      zip_add_file(zName, &mfile, 0);
      blob_reset(&mfile);
      blob_append(&hash, "\n", 1);
      blob_resize(&filename, nPrefix);
      blob_append(&filename, "manifest.uuid", -1);
      zName = blob_str(&filename);
      zip_add_file(zName, &hash, 0);
      blob_reset(&hash);
391
392
393
394
395
396
397




398
399
400
401
402
403
404
*/
void baseline_zip_cmd(void){
  int rid;
  Blob zip;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);




  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2],"ci");
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "







>
>
>
>







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
*/
void baseline_zip_cmd(void){
  int rid;
  Blob zip;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);
  
  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2],"ci");
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "
419
420
421
422
423
424
425
426
427


428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446







447
448
449
450

451
452
453
454
455
456
457
** URL: /zip/RID.zip
**
** Generate a ZIP archive for the baseline.
** Return that ZIP archive as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=base name of the output file. Defaults to
** something project/version-specific.


**
** - uuid=the version to zip (may be a tag/branch name).
** Defaults to trunk.
**
*/
void baseline_zip_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob zip;
  char *zKey;

  login_check_credentials();
  if( !g.perm.Zip ){ login_needed(); return; }
  load_control();
  zName = mprintf("%s", PD("name",""));
  nName = strlen(zName);
  zRid = mprintf("%s", PD("uuid","trunk"));
  nRid = strlen(zRid);







  for(nName=strlen(zName)-1; nName>5; nName--){
    if( zName[nName]=='.' ){
      zName[nName] = 0;
      break;

    }
  }
  rid = name_to_typed_rid(nRid?zRid:zName,"ci");
  if( rid==0 ){
    @ Not found
    return;
  }







|
|
>
>


|
















>
>
>
>
>
>
>
|
|
|
|
>







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
** URL: /zip/RID.zip
**
** Generate a ZIP archive for the baseline.
** Return that ZIP archive as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=NAME[.zip] is the name of the output file. Defaults to
** something project/version-specific. The base part of the
** name, up to the last dot, is used as the top-most directory
** name in the output file.
**
** - uuid=the version to zip (may be a tag/branch name).
** Defaults to "trunk".
**
*/
void baseline_zip_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob zip;
  char *zKey;

  login_check_credentials();
  if( !g.perm.Zip ){ login_needed(); return; }
  load_control();
  zName = mprintf("%s", PD("name",""));
  nName = strlen(zName);
  zRid = mprintf("%s", PD("uuid","trunk"));
  nRid = strlen(zRid);
  if( nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){
    /* Special case:  Remove the ".zip" suffix.  */
    nName -= 4;
    zName[nName] = 0;
  }else{
    /* If the file suffix is not ".zip" then just remove the
    ** suffix up to and including the last "." */
    for(nName=strlen(zName)-1; nName>5; nName--){
      if( zName[nName]=='.' ){
        zName[nName] = 0;
        break;
      }
    }
  }
  rid = name_to_typed_rid(nRid?zRid:zName,"ci");
  if( rid==0 ){
    @ Not found
    return;
  }
Added test/comment.test.




























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
#
# Copyright (c) 2014 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
############################################################################
#
# Test comment formatting and printing.
#

fossil test-comment-format "" ""
test comment-1 {$RESULT eq "\n(1 lines output)"}

###############################################################################

fossil test-comment-format --decode "" ""
test comment-2 {$RESULT eq "\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 26 " " "this is a short comment."
test comment-3 {$RESULT eq " this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --decode " " "this is a short comment."
test comment-4 {$RESULT eq " this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 26 "*PREFIX* " "this is a short comment."
test comment-5 {$RESULT eq "*PREFIX* this is a short c\n         omment.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --decode "*PREFIX* " "this is a short comment."
test comment-6 {$RESULT eq "*PREFIX* this is a short c\n         omment.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 "" "this\\sis\\sa\\sshort\\scomment."
test comment-7 {$RESULT eq "this\\sis\\sa\\sshort\\scommen\nt.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --decode "" "this\\sis\\sa\\sshort\\scomment."
test comment-8 {$RESULT eq "this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --decode --trimspace "HH:MM:SS " "this is a long comment that should span multiple lines if the test is working correctly."
test comment-9 {$RESULT eq "HH:MM:SS this is a long comment that should span multiple lines if the test is\n         working correctly.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --decode --trimspace "HH:MM:SS " "this is a long comment that should span multiple lines if the test is working correctly.  more text here describing the issue.\\nanother line here..................................................................................*"
test comment-10 {$RESULT eq "HH:MM:SS this is a long comment that should span multiple lines if the test is\n         working correctly.  more text here describing the issue.\n         another line here....................................................\n         ..............................*\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 78 "HH:MM:SS " "....................................................................................*"
test comment-11 {$RESULT eq "HH:MM:SS .....................................................................\n         ...............*\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 78 "HH:MM:SS " ".....................................................................*" 78
test comment-12 {$RESULT eq "HH:MM:SS .....................................................................\n         *\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 "*TEST* " "this\tis a test."
test comment-13 {$RESULT eq "*TEST* this\tis a te\n       st.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 "*TEST* " "this is a test......................................................................................................................."
test comment-14 {$RESULT eq "*TEST* this is a test.......................................\n       .....................................................\n       ...........................\n(3 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --wordbreak "*TEST* " "this is a test......................................................................................................................."
test comment-15 {$RESULT eq "*TEST* this is a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 "*TEST* " "this	is	a	test......................................................................................................................."
test comment-16 {$RESULT eq "*TEST* this	is	a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --wordbreak "*TEST* " "this	is	a	test......................................................................................................................."
test comment-17 {$RESULT eq "*TEST* this	is	a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 "*TEST* " "one two three four five six seven eight nine ten eleven twelve"
test comment-18 {$RESULT eq "*TEST* one two three four five six seven eight nine ten elev\n       en twelve\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --wordbreak "*TEST* " "one two three four five six seven eight nine ten eleven twelve"
test comment-19 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n       eleven twelve\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 "*TEST* " "one	two	three	four	five	six	seven	eight	nine	ten	eleven	twelve"
test comment-20 {$RESULT eq "*TEST* one	two	three	four	five\n       six	seven	eight	nine	ten\n       eleven	twelve\n(3 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --wordbreak "*TEST* " "one	two	three	four	five	six	seven	eight	nine	ten	eleven	twelve"
test comment-21 {$RESULT eq "*TEST* one	two	three	four	five\n       six	seven	eight	nine	ten\n       eleven	twelve\n(3 lines output)"}

###############################################################################

fossil test-comment-format --legacy "" ""
test comment-22 {$RESULT eq "\n(1 lines output)"}

###############################################################################

fossil test-comment-format --legacy --decode "" ""
test comment-23 {$RESULT eq "\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --legacy " " "this is a short comment."
test comment-24 {$RESULT eq " this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --legacy --decode " " "this is a short comment."
test comment-25 {$RESULT eq " this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 25 --legacy "*PREFIX* " "this is a short comment."
test comment-26 {$RESULT eq "*PREFIX* this is a short\n         comment.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 25 --legacy --decode "*PREFIX* " "this is a short comment."
test comment-27 {$RESULT eq "*PREFIX* this is a short\n         comment.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --legacy "" "this\\sis\\sa\\sshort\\scomment."
test comment-28 {$RESULT eq "this\\sis\\sa\\sshort\\scommen\nt.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --legacy --decode "" "this\\sis\\sa\\sshort\\scomment."
test comment-29 {$RESULT eq "this is a short comment.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --legacy --decode "HH:MM:SS " "this is a long comment that should span multiple lines if the test is working correctly."
test comment-30 {$RESULT eq "HH:MM:SS this is a long comment that should span multiple lines if the test\n         is working correctly.\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --legacy --decode "HH:MM:SS " "this is a long comment that should span multiple lines if the test is working correctly.  more text here describing the issue.\\nanother line here..................................................................................*"
test comment-31 {$RESULT eq "HH:MM:SS this is a long comment that should span multiple lines if the test\n         is working correctly. more text here describing the issue. another\n         line\n         here.................................................................\n         .................*\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --legacy "HH:MM:SS " "....................................................................................*"
test comment-32 {$RESULT eq "HH:MM:SS .....................................................................\n         ...............*\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 78 --legacy "HH:MM:SS " ".....................................................................*"
test comment-33 {$RESULT eq "HH:MM:SS .....................................................................\n         *\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 26 --legacy "*TEST* " "this\tis a test."
test comment-34 {$RESULT eq "*TEST* this is a test.\n(1 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy "*TEST* " "this is a test......................................................................................................................."
test comment-35 {$RESULT eq "*TEST* this is a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy --wordbreak "*TEST* " "this is a test......................................................................................................................."
test comment-36 {$RESULT eq "*TEST* this is a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy "*TEST* " "this	is	a	test......................................................................................................................."
test comment-37 {$RESULT eq "*TEST* this is a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy --wordbreak "*TEST* " "this	is	a	test......................................................................................................................."
test comment-38 {$RESULT eq "*TEST* this is a\n       test.................................................\n       .....................................................\n       .................\n(4 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy "*TEST* " "one two three four five six seven eight nine ten eleven twelve"
test comment-39 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n       eleven twelve\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy --wordbreak "*TEST* " "one two three four five six seven eight nine ten eleven twelve"
test comment-40 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n       eleven twelve\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy "*TEST* " "one	two	three	four	five	six	seven	eight	nine	ten	eleven	twelve"
test comment-41 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n       eleven twelve\n(2 lines output)"}

###############################################################################

fossil test-comment-format --width 60 --legacy --wordbreak "*TEST* " "one	two	three	four	five	six	seven	eight	nine	ten	eleven	twelve"
test comment-42 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n       eleven twelve\n(2 lines output)"}

###############################################################################

set orig "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\\nxxxxxxx."
fossil test-comment-format --width 73 --decode --origbreak "" $orig
test comment-43 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 73 --decode --origbreak "" $orig $orig
test comment-44 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 73 --decode --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
test comment-45 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(6 lines output)"}

###############################################################################

fossil test-comment-format --width 82 --indent 9 --decode --origbreak "         " $orig
test comment-46 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 82 --indent 9 --decode --origbreak "         " $orig $orig
test comment-47 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 82 --indent 9 --decode --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
test comment-48 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(6 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig
test comment-49 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig $orig
test comment-50 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimspace --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
test comment-51 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(6 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak "         " $orig
test comment-52 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak "         " $orig $orig
test comment-53 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
test comment-54 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(6 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig
test comment-55 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig $orig
test comment-56 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
test comment-57 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\nxxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\nxxxxxxx.\n(6 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak "         " $orig
test comment-58 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak "         " $orig $orig
test comment-59 {$RESULT eq "         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(5 lines output)"}

###############################################################################

fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
test comment-60 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n         xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n         xxxxxxx xxxxx xxxx  xxxx xx xxxxxxx xxxxxxx (xxxxxx  xxxxxxxxx x xxxxx).\n         xxx'x xxx xxx xx  xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx  xx xx xxxx. x\n         xxxxx  x xxxxxx  xxxx xxxx  xxxx xxxx  xxxx x  xxxxx xx  xxx x  xxxxxxxx\n         xxxxxxx.\n(6 lines output)"}
Changes to test/graph-test-1.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<title>Graph Test One</title>

This page contains examples a list of URLs of timelines with
interesting graphs.  Click on all URLs, one by one, to verify 
the correct operation of the graph drawing logic.

  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08" target="testwindow">
     20-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08&ng" target="testwindow">
     20-element timeline, check-ins only, no graph, before 2010-11-08</a>
  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08&fc" target="testwindow">
     20-element timeline, check-ins only, file changes, before 2010-11-08</a>
  *  <a href="../../../timeline?n=40&y=ci&b=2010-11-08" target="testwindow">
     40-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=1000&y=ci&b=2010-11-08" target="testwindow">
     1000-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=10&c=2010-11-07+10:23:00" target="testwindow">
     10-elements circa 2010-11-07 10:23:00, with dividers</a>
  *  <a href="../../../timeline?n=10&c=2010-11-07+10:23:00&nd" 
     target="testwindow">
     10-elements circa 2010-11-07 10:23:00, without dividers</a>
  *  <a href="../../../timeline?f=3ea66260b5555" target="testwindow">
     Parents and children of check-in 3ea66260b5555</a>
  *  <a href="../../../timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3"
     target="testwindow">multiple merge descenders from the penultimate node.
     </a>



|












|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<title>Graph Test One</title>

This page contains examples a list of URLs of timelines with
interesting graphs.  Click on all URLs, one by one, to verify
the correct operation of the graph drawing logic.

  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08" target="testwindow">
     20-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08&ng" target="testwindow">
     20-element timeline, check-ins only, no graph, before 2010-11-08</a>
  *  <a href="../../../timeline?n=20&y=ci&b=2010-11-08&fc" target="testwindow">
     20-element timeline, check-ins only, file changes, before 2010-11-08</a>
  *  <a href="../../../timeline?n=40&y=ci&b=2010-11-08" target="testwindow">
     40-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=1000&y=ci&b=2010-11-08" target="testwindow">
     1000-element timeline, check-ins only, before 2010-11-08</a>
  *  <a href="../../../timeline?n=10&c=2010-11-07T10:23:00" target="testwindow">
     10-elements circa 2010-11-07 10:23:00, with dividers</a>
  *  <a href="../../../timeline?n=10&c=2010-11-07T10:23:00&nd"
     target="testwindow">
     10-elements circa 2010-11-07 10:23:00, without dividers</a>
  *  <a href="../../../timeline?f=3ea66260b5555" target="testwindow">
     Parents and children of check-in 3ea66260b5555</a>
  *  <a href="../../../timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3"
     target="testwindow">multiple merge descenders from the penultimate node.
     </a>
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  *  <a href="../../../finfo?name=Makefile" target="testwindow">
     History of source file "Makefile".</a>
  *  <a href="../../../timeline?a=1970-01-01" target="testwindow">
     20 elements after 1970-01-01.</a>
  *  <a href="../../../timeline?n=100000000&y=ci" target="testwindow">
     All check-ins - a huge graph.</a>
  *  <a href="../../../timeline?f=8dfed953f7530442" target="testwindow">
     This malformed commit has a 
     merge parent which is not a valid checkin.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 by shortest path.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 without merge links.</a>







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  *  <a href="../../../finfo?name=Makefile" target="testwindow">
     History of source file "Makefile".</a>
  *  <a href="../../../timeline?a=1970-01-01" target="testwindow">
     20 elements after 1970-01-01.</a>
  *  <a href="../../../timeline?n=100000000&y=ci" target="testwindow">
     All check-ins - a huge graph.</a>
  *  <a href="../../../timeline?f=8dfed953f7530442" target="testwindow">
     This malformed commit has a
     merge parent which is not a valid checkin.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 by shortest path.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 without merge links.</a>
Added test/merge6.test.






































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#
# Copyright (c) 2014 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
############################################################################
#
# Tests of the "merge" command
#

####################################################################
# TEST 1: Handle multiple merges each with one or more ADDED files #
####################################################################

repo_init
fossil ls

test merge_multi-0 {[string map [list \r\n \n] [string trim $RESULT]] eq {}}

write_file f1 "f1 line"
fossil add f1
fossil commit -m "base file"
fossil ls

test merge_multi-1 {[string map [list \r\n \n] [string trim $RESULT]] eq {f1}}

fossil update trunk
write_file f2 "f2 line"
fossil add f2
fossil commit -m "branch for file f2" -b branch_for_f2
fossil ls

test merge_multi-2 {[string map [list \r\n \n] [string trim $RESULT]] eq {f1
f2}}

fossil update trunk
write_file f3 "f3 line"
write_file f4 "f4 line"
fossil add f3
fossil add f4
fossil commit -m "branch for files f3 and f4" -b branch_for_f3_f4
fossil ls

test merge_multi-3 {[string map [list \r\n \n] [string trim $RESULT]] eq {f1
f3
f4}}

fossil update trunk
fossil merge branch_for_f2
fossil merge branch_for_f3_f4
fossil commit -m "new trunk files f2, f3, and f4 via merge"
fossil ls

test merge_multi-4 {[string map [list \r\n \n] [string trim $RESULT]] eq {f1
f2
f3
f4}}
Changes to test/merge_renames.test.
1
2
3
4
5
6
7
8
9
10
#
# Tests for merging with renames
# 
#

catch {exec $::fossilexe info} res
puts res=$res
if {![regexp {use --repository} $res]} {
  puts stderr "Cannot run this test within an open checkout"
  return


|







1
2
3
4
5
6
7
8
9
10
#
# Tests for merging with renames
#
#

catch {exec $::fossilexe info} res
puts res=$res
if {![regexp {use --repository} $res]} {
  puts stderr "Cannot run this test within an open checkout"
  return
167
168
169
170
171
172
173




174





























175
176
177
178
179
######################################
#  Test 4                            #
#  Reported: Ticket [67176c3aa4]     #
######################################

# TO BE WRITTEN.



































# Tests for troubles not specifically linked with renames but that I'd like to
# write:
#  [c26c63eb1b] - 'merge --backout' does not handle conflicts properly
#  [953031915f] - Lack of warning when overwriting extra files 
#  [4df5f38f1e] - Troubles merging a file delete with a file change 







>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
######################################
#  Test 4                            #
#  Reported: Ticket [67176c3aa4]     #
######################################

# TO BE WRITTEN.

######################################
#  Test 5                            #
#  Handle Rename/Add via Merge       #
######################################

repo_init

write_file f1 "old f1 line"
fossil add f1
fossil commit -m "base file"

write_file f3 "f3 line"
fossil add f3
fossil commit -m "branch file" -b branch_for_f3

fossil update trunk
fossil mv f1 f2
file rename -force f1 f2
write_file f1 "new f1 line"
fossil add f1
fossil commit -m "rename and add file with old name"

fossil update branch_for_f3
fossil merge trunk
fossil commit -m "trunk merged, should have 3 files"

fossil ls

test merge_renames-5 {[string map [list \r\n \n] [string trim $RESULT]] eq {f1
f2
f3}}

######################################
#
# Tests for troubles not specifically linked with renames but that I'd like to
# write:
#  [c26c63eb1b] - 'merge --backout' does not handle conflicts properly
#  [953031915f] - Lack of warning when overwriting extra files
#  [4df5f38f1e] - Troubles merging a file delete with a file change
Changes to test/release-checklist.wiki.
15
16
17
18
19
20
21
22
23
24





25
26
27
28
29
30
31
[./graph-test-1.wiki] document and verify that all graphs are
rendered correctly.

<li><p>
Click on each of the links in in the
[./diff-test-1.wiki] document and verify that all diffs are
rendered correctly.

<li><p>
Click on the following link to verify that it works: [./test-page%2b%2b.wiki | ./test-page++.wiki]






<li><p>
Verify correct name-change tracking behavior (no net changes) for:
<blockquote><b>
fossil test-name-changes --debug  b120bc8b262ac 374920b20944b
</b></blockquote>








<


>
>
>
>
>







15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
[./graph-test-1.wiki] document and verify that all graphs are
rendered correctly.

<li><p>
Click on each of the links in in the
[./diff-test-1.wiki] document and verify that all diffs are
rendered correctly.

<li><p>
Click on the following link to verify that it works: [./test-page%2b%2b.wiki | ./test-page++.wiki]
(NB:  Many web servers automatically block
or rewrite URLs that contain "+" characters, even when those "+"
characters are encoded as "%2B".  On such web servers, the URL
above will not work.  This test is only guaranteed to work
when running "fossil ui".)

<li><p>
Verify correct name-change tracking behavior (no net changes) for:
<blockquote><b>
fossil test-name-changes --debug  b120bc8b262ac 374920b20944b
</b></blockquote>

Added test/subdir-b/readme.txt.






>
>
>
1
2
3
This file exists in order to create the "subdir-b" subdirectory.  There is
exists sibling directory "subdir" that is a prefix of this subdirectory.
This file exists for self-testing.
Added test/subdir/one/two/three/four/five/six/readme.txt.




>
>
1
2
This file exists in order to provide Fossil with a test case of a file
that is deeply nested below many subdirectories.
Changes to test/tester.tcl.
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44








45
46
47
48
49
50
51







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90




91
92
93
94
95
96
97
98
99
100
101
#
#     tclsh ../test/tester.tcl ../bld/fossil
#
# Where ../test/tester.tcl is the name of this file and ../bld/fossil
# is the name of the executable to be tested.
#


set testdir [file normalize [file dir $argv0]]
set fossilexe [file normalize [lindex $argv 0]]
set argv [lrange $argv 1 end]

set i [lsearch $argv -halt]
if {$i>=0} {
  set HALT 1
  set argv [lreplace $argv $i $i]
} else {
  set HALT 0
}

set i [lsearch $argv -prot]
if {$i>=0} {
  set PROT 1
  set argv [lreplace $argv $i $i]
} else {
  set PROT 0
}









if {[llength $argv]==0} {
  foreach f [lsort [glob $testdir/*.test]] {
    set base [file root [file tail $f]]
    lappend argv $base
  }
}








# start protocol
#
proc protInit {cmd} {
  if {$::PROT} {
    set out [open "prot" w]
    fconfigure $out -translation platform
    puts $out "starting tests with:$cmd"
    close $out
  }
}

# write protocol
#
proc protOut {msg} {
  puts "$msg"
  if {$::PROT} {
    set out [open "prot" a]
    fconfigure $out -translation platform
    puts $out "$msg"
    close $out
  }
}

# Run the fossil program
#
proc fossil {args} {
  global fossilexe
  set cmd $fossilexe
  foreach a $args {
    lappend cmd $a
  }
  protOut $cmd

  flush stdout
  set rc [catch {eval exec $cmd} result]
  global RESULT CODE
  set CODE $rc
  if {$rc} {puts "ERROR: $result"}




  set RESULT $result
}

# Read a file into memory. 
#
proc read_file {filename} {
  set in [open $filename r]
  fconfigure $in -translation binary
  set txt [read $in [file size $filename]]
  close $in
  return $txt







>



















>
>
>
>
>
>
>
>







>
>
>
>
>
>
>





|

|







|

|

|


















|
>
>
>
>



|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#
#     tclsh ../test/tester.tcl ../bld/fossil
#
# Where ../test/tester.tcl is the name of this file and ../bld/fossil
# is the name of the executable to be tested.
#

set testrundir [pwd]
set testdir [file normalize [file dir $argv0]]
set fossilexe [file normalize [lindex $argv 0]]
set argv [lrange $argv 1 end]

set i [lsearch $argv -halt]
if {$i>=0} {
  set HALT 1
  set argv [lreplace $argv $i $i]
} else {
  set HALT 0
}

set i [lsearch $argv -prot]
if {$i>=0} {
  set PROT 1
  set argv [lreplace $argv $i $i]
} else {
  set PROT 0
}

set i [lsearch $argv -verbose]
if {$i>=0} {
  set VERBOSE 1
  set argv [lreplace $argv $i $i]
} else {
  set VERBOSE 0
}

if {[llength $argv]==0} {
  foreach f [lsort [glob $testdir/*.test]] {
    set base [file root [file tail $f]]
    lappend argv $base
  }
}

set tempPath [expr {[info exists env(TEMP)] ? \
    $env(TEMP) : [file dirname [info script]]}]

if {$tcl_platform(platform) eq "windows"} then {
  set tempPath [string map [list \\ /] $tempPath]
}

# start protocol
#
proc protInit {cmd} {
  if {$::PROT} {
    set out [open [file join $::testrundir prot] w]
    fconfigure $out -translation platform
    puts $out "starting tests with: $cmd"
    close $out
  }
}

# write protocol
#
proc protOut {msg} {
  puts stdout $msg
  if {$::PROT} {
    set out [open [file join $::testrundir prot] a]
    fconfigure $out -translation platform
    puts $out $msg
    close $out
  }
}

# Run the fossil program
#
proc fossil {args} {
  global fossilexe
  set cmd $fossilexe
  foreach a $args {
    lappend cmd $a
  }
  protOut $cmd

  flush stdout
  set rc [catch {eval exec $cmd} result]
  global RESULT CODE
  set CODE $rc
  if {$rc} {
    protOut "ERROR: $result"
  } elseif {$::VERBOSE} {
    protOut "RESULT: $result"
  }
  set RESULT $result
}

# Read a file into memory.
#
proc read_file {filename} {
  set in [open $filename r]
  fconfigure $in -translation binary
  set txt [read $in [file size $filename]]
  close $in
  return $txt
164
165
166
167
168
169
170
171

































































172
173
174
175
176
177
178
  set result [normalize_status_list $result]
  if {$result eq $expected} {
    test $name 1
  } else {
    protOut "  Expected:\n    [join $expected "\n    "]"
    protOut "  Got:\n    [join $result "\n    "]"
    test $name 0
  } 

































































}

# Perform a test
#
set test_count 0
proc test {name expr} {
  global bad_test test_count







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  set result [normalize_status_list $result]
  if {$result eq $expected} {
    test $name 1
  } else {
    protOut "  Expected:\n    [join $expected "\n    "]"
    protOut "  Got:\n    [join $result "\n    "]"
    test $name 0
  }
}

# Append all arguments into a single value and then returns it.
#
proc appendArgs {args} {
  eval append result $args
}

# Return the name of the versioned settings file containing the TH1
# setup script.
#
proc getTh1SetupFileName {} {
  #
  # NOTE: This uses the "testdir" global variable provided by the
  #       test suite; alternatively, the root of the source tree
  #       could be obtained directly from Fossil.
  #
  return [file normalize [file join [file dirname $::testdir] \
      .fossil-settings th1-setup]]
}

# Return the saved name of the versioned settings file containing
# the TH1 setup script.
#
proc getSavedTh1SetupFileName {} {
  return [appendArgs [getTh1SetupFileName] . [pid]]
}

# Sets the TH1 setup script to the one provided.  Prior to calling
# this, the [saveTh1SetupFile] procedure should be called in order to
# preserve the existing TH1 setup script.  Prior to completing the test,
# the [restoreTh1SetupFile] procedure should be called to restore the
# original TH1 setup script.
#
proc writeTh1SetupFile { data } {
  return [write_file [getTh1SetupFileName] $data]
}

# Saves the TH1 setup script file by renaming it, based on the current
# process ID.
#
proc saveTh1SetupFile {} {
  set oldFileName [getTh1SetupFileName]
  if {[file exists $oldFileName]} then {
    set newFileName [getSavedTh1SetupFileName]
    catch {file delete $newFileName}
    file rename $oldFileName $newFileName
  }
}

# Restores the original TH1 setup script file by renaming it back, based
# on the current process ID.
#
proc restoreTh1SetupFile {} {
  set oldFileName [getSavedTh1SetupFileName]
  set newFileName [getTh1SetupFileName]
  if {[file exists $oldFileName]} then {
    catch {file delete $newFileName}
    file rename $oldFileName $newFileName
  } else {
    #
    # NOTE: There was no TH1 setup script file, delete the test one.
    #
    file delete $newFileName
  }
}

# Perform a test
#
set test_count 0
proc test {name expr} {
  global bad_test test_count
Added test/th1-hooks-input.txt.








>
>
>
>
1
2
3
4
GET ${url} HTTP/1.1
Host: localhost
User-Agent: Fossil

Added test/th1-hooks.test.


















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#
# Copyright (c) 2011 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
############################################################################
#
# TH1 Hooks
#

fossil test-th-eval "hasfeature th1Hooks"

if {$::RESULT ne "1"} then {
  puts "Fossil was not compiled with TH1 hooks support."; return
}

###############################################################################

set env(TH1_ENABLE_HOOKS) 1; # TH1 hooks must be enabled for this test.

###############################################################################

proc fossil_th1_hook_http { repository url } {
  set suffix [appendArgs [pid] - [clock seconds] .txt]
  set inFileName [file join $::tempPath [appendArgs test-http-in- $suffix]]
  set outFileName [file join $::tempPath [appendArgs test-http-out- $suffix]]
  set data [subst [read_file [file join $::testdir th1-hooks-input.txt]]]

  write_file $inFileName $data
  fossil http $repository $inFileName $outFileName 127.0.0.1
  set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]

  if {1} then {
    catch {file delete $inFileName}
    catch {file delete $outFileName}
  }

  return $result
}

proc first_data_line {} {
  return [lindex [split [string trim $::RESULT] \r\n] 0]
}

proc second_data_line {} {
  return [lindex [split [string trim $::RESULT] \r\n] 1]
}

proc third_data_line {} {
  return [lindex [split [string trim $::RESULT] \r\n] 2]
}

proc last_data_line {} {
  return [lindex [split [string trim $::RESULT] \r\n] end]
}

proc next_to_last_data_line {} {
  return [lindex [split [string trim $::RESULT] \r\n] end-1]
}

###############################################################################

set testTh1Setup {
  proc initialize_hook_log {} {
    if {![info exists ::hook_log]} {
      set ::hook_log ""
    }
  }

  proc append_hook_log { args } {
    initialize_hook_log
    if {[string length $::hook_log] > 0} {
      set ::hook_log "$::hook_log "
    }
    for {set i 0} {$i < [llength $args]} {set i [expr {$i + 1}]} {
      set ::hook_log $::hook_log[lindex $args $i]
    }
  }

  proc emit_hook_log {} {
    initialize_hook_log
    html "\n<h1><b>$::hook_log</b></h1>\n"
  }

  proc command_hook {} {
    append_hook_log command_hook " " $::cmd_name
    if {$::cmd_name eq "test1"} {
      puts [repository]; continue
    } elseif {$::cmd_name eq "test2"} {
      error "unsupported command"
    } elseif {$::cmd_name eq "test3"} {
      emit_hook_log
      break "TH_BREAK return code"
    } elseif {$::cmd_name eq "test4"} {
      emit_hook_log
      return -code 2 "TH_RETURN return code"
    } elseif {$::cmd_name eq "timeline"} {
      if {$::cmd_args eq "custom"} {
        emit_hook_log
        return "custom timeline"
      } else {
        emit_hook_log
        error "unsupported timeline"
      }
    }
  }

  proc command_notify {} {
    append_hook_log command_notify " " $::cmd_name
    emit_hook_log
  }

  proc webpage_hook {} {
    append_hook_log webpage_hook " " $::web_name
    if {$::web_name eq "test1"} {
      puts [repository]; continue
    }
  }

  proc webpage_notify {} {
    append_hook_log webpage_notify " " $::web_name
    emit_hook_log
  }
}

###############################################################################

set data [fossil info]
regexp -line -- {^repository:   (.*)$} $data dummy repository

if {[string length $repository] == 0 || ![file exists $repository]} then {
  error "unable to locate repository"
}

###############################################################################

saveTh1SetupFile; writeTh1SetupFile $testTh1Setup

###############################################################################

fossil timeline custom; # NOTE: Bad "WHEN" argument.
test th1-cmd-hooks-1a {[string map [list \r\n \n] [string trim $RESULT]] eq {<h1><b>command_hook timeline</b></h1>
ERROR: unsupported timeline
+++ no more data (0) +++

<h1><b>command_hook timeline command_notify timeline</b></h1>}}

###############################################################################

fossil timeline
test th1-cmd-hooks-2a {[first_data_line] eq {<h1><b>command_hook timeline</b></h1>}}
test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
test th1-cmd-hooks-2c {[regexp -- {=== \d{4}-\d{2}-\d{2} ===} [third_data_line]]}
test th1-cmd-hooks-2d {[last_data_line] eq {<h1><b>command_hook timeline command_notify timeline</b></h1>}}

###############################################################################

fossil test1
test th1-custom-cmd-1a {[next_to_last_data_line] eq $repository}
test th1-custom-cmd-1b {[last_data_line] eq {<h1><b>command_hook test1 command_notify test1</b></h1>}}

###############################################################################

fossil test2
test th1-custom-cmd-2a {[first_data_line] eq {ERROR: unsupported command}}

###############################################################################

fossil test3
test th1-custom-cmd-3a {[string trim $RESULT] eq {<h1><b>command_hook test3</b></h1>}}

###############################################################################

fossil test4
test th1-custom-cmd-4a {[string trim $RESULT] eq {<h1><b>command_hook test4</b></h1>}}

###############################################################################

set RESULT [fossil_th1_hook_http $repository /timeline]
test th1-web-hooks-1a {[regexp {<title>Fossil: Timeline</title>} $RESULT]}
test th1-web-hooks-1b {[regexp {<h1><b>command_hook http webpage_hook timeline webpage_notify timeline</b></h1>} $RESULT]}

###############################################################################

set RESULT [fossil_th1_hook_http $repository /test1]
test th1-custom-web-1a {[next_to_last_data_line] eq $repository}
test th1-custom-web-1b {[last_data_line] eq {<h1><b>command_hook http webpage_hook test1 webpage_notify test1</b></h1>}}

###############################################################################

restoreTh1SetupFile
Changes to test/th1.test.
14
15
16
17
18
19
20





21
22
23
24
25
26
27
#   http://www.hwaci.com/drh/
#
############################################################################
#
# TH1 Commands
#






fossil test-th-eval --th-open-config "setting abc"
test th1-setting-1 {$RESULT eq ""}

###############################################################################

fossil test-th-eval --th-open-config "setting -- abc"
test th1-setting-2 {$RESULT eq ""}







>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#   http://www.hwaci.com/drh/
#
############################################################################
#
# TH1 Commands
#

fossil test-th-eval --th-open-config "setting th1-hooks"
set th1Hooks [expr {$RESULT eq "1"}]

###############################################################################

fossil test-th-eval --th-open-config "setting abc"
test th1-setting-1 {$RESULT eq ""}

###############################################################################

fossil test-th-eval --th-open-config "setting -- abc"
test th1-setting-2 {$RESULT eq ""}
466
467
468
469
470
471
472
473
474
475
476
477
478

479








































































































































































































































































































































test th1-expr-33 {$RESULT eq {1}}

###############################################################################

fossil test-th-eval "expr 0b1+5"
test th1-expr-34 {$RESULT eq {6}}


###############################################################################

fossil test-th-eval "expr 0+0b"
test th1-expr-35 {$RESULT eq {TH_ERROR: expected number, got: "0b"}}


















































































































































































































































































































































<





>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
test th1-expr-33 {$RESULT eq {1}}

###############################################################################

fossil test-th-eval "expr 0b1+5"
test th1-expr-34 {$RESULT eq {6}}


###############################################################################

fossil test-th-eval "expr 0+0b"
test th1-expr-35 {$RESULT eq {TH_ERROR: expected number, got: "0b"}}

###############################################################################

fossil test-th-eval "expr (-1)+1"
test th1-expr-36 {$RESULT eq {0}}

###############################################################################

fossil test-th-eval "expr (((-1)))"
test th1-expr-37 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr (((1)))"
test th1-expr-38 {$RESULT eq {1}}

###############################################################################

fossil test-th-eval "expr (((1))"
test th1-expr-39 {$RESULT eq {TH_ERROR: syntax error in expression: "(((1))"}}

###############################################################################

fossil test-th-eval "expr ((1)))"
test th1-expr-40 {$RESULT eq {TH_ERROR: syntax error in expression: "((1)))"}}

###############################################################################

fossil test-th-eval "expr (((1)*2)*2)"
test th1-expr-41 {$RESULT eq {4}}

###############################################################################

fossil test-th-eval "checkout 1"; # NOTE: Assumes running "in tree".
test th1-checkout-1 {[string length $RESULT] > 0}

###############################################################################

fossil test-th-eval "checkout"; # NOTE: Assumes running "in tree".
test th1-checkout-2 {[string length $RESULT] > 0}

###############################################################################

set savedPwd [pwd]; cd /
fossil test-th-eval "checkout 1"
cd $savedPwd; unset savedPwd
test th1-checkout-3 {[string length $RESULT] == 0}

###############################################################################

set savedPwd [pwd]; cd /
fossil test-th-eval "checkout"
cd $savedPwd; unset savedPwd
test th1-checkout-4 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval "render {}"
test th1-render-1 {$RESULT eq {}}

###############################################################################

fossil test-th-eval "render {$<x> before <th1>set x 123</th1> after $<x> }"
test th1-render-2 {$RESULT eq {no such variable: x before  after 123 }}

###############################################################################

fossil test-th-eval "trace {}"
test th1-trace-1 {$RESULT eq {}}

###############################################################################

fossil test-th-eval --th-trace "trace {}"
if {$th1Hooks} {
  test th1-trace-2 {[string map [list \r\n \n] [string trim $RESULT]] eq \
{------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />

------------------- END TRACE LOG -------------------}}
} else {
  test th1-trace-2 {[string map [list \r\n \n] [string trim $RESULT]] eq \
      {------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
th1-setup {} => TH_OK<br />

------------------- END TRACE LOG -------------------}}
}

###############################################################################

fossil test-th-eval "trace {this is a trace message.}"
test th1-trace-3 {$RESULT eq {}}

###############################################################################

fossil test-th-eval --th-trace "trace {this is a trace message.}"
if {$th1Hooks} {
  test th1-trace-4 {[string map [list \r\n \n] [string trim $RESULT]] eq \
      {------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
this is a trace message.
------------------- END TRACE LOG -------------------}}
} else {
  test th1-trace-4 {[string map [list \r\n \n] [string trim $RESULT]] eq \
      {------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
th1-setup {} => TH_OK<br />
this is a trace message.
------------------- END TRACE LOG -------------------}}
}

###############################################################################

fossil test-th-eval "styleHeader {Page Title Here}"
test th1-header-1 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "styleHeader {Page Title Here}"
test th1-header-2 {[regexp -- {<title>Fossil: Page Title Here</title>} $RESULT]}

###############################################################################

fossil test-th-eval "styleFooter"
test th1-footer-1 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "styleFooter"
test th1-footer-2 {$RESULT eq {}}

###############################################################################

fossil test-th-eval --th-open-config --th-force-cgi "styleHeader {}; styleFooter"
test th1-footer-3 {[regexp -- {</body></html>} $RESULT]}

###############################################################################

fossil test-th-eval "getParameter"
test th1-get-parameter-1 {$RESULT eq \
    {TH_ERROR: wrong # args: should be "getParameter NAME ?DEFAULT?"}}

###############################################################################

fossil test-th-eval "getParameter test1"
test th1-get-parameter-2 {$RESULT eq {}}

###############################################################################

fossil test-th-eval "getParameter test1 defValue1"
test th1-get-parameter-3 {$RESULT eq {defValue1}}

###############################################################################

fossil test-th-eval "setParameter"
test th1-set-parameter-1 {$RESULT eq \
    {TH_ERROR: wrong # args: should be "setParameter NAME VALUE"}}

###############################################################################

fossil test-th-eval "setParameter test1 value1; getParameter test1"
test th1-set-parameter-2 {$RESULT eq {value1}}

###############################################################################

fossil test-th-eval "setParameter test2 value2; getParameter test1"
test th1-set-parameter-3 {$RESULT eq {}}

###############################################################################

fossil test-th-eval "setParameter test3 value3; getParameter test3"
test th1-set-parameter-4 {$RESULT eq {value3}}

###############################################################################

fossil test-th-eval "setParameter test3 value3; getParameter test3 defValue3"
test th1-set-parameter-5 {$RESULT eq {value3}}

###############################################################################

fossil test-th-eval "setParameter test4 value4; setParameter test4 value5; getParameter test4"
test th1-set-parameter-6 {$RESULT eq {value5}}

###############################################################################

fossil test-th-eval "setParameter test4 value4; setParameter test4 value5; getParameter test4 defValue4"
test th1-set-parameter-7 {$RESULT eq {value5}}

###############################################################################

fossil test-th-eval "artifact"
test th1-artifact-1 {$RESULT eq \
    {TH_ERROR: wrong # args: should be "artifact ID ?FILENAME?"}}

###############################################################################

fossil test-th-eval "artifact tip"
test th1-artifact-2 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "artifact tip"
test th1-artifact-3 {[regexp -- {F test/th1\.test [0-9a-f]{40}} $RESULT]}

###############################################################################

fossil test-th-eval "artifact 0000000000"
test th1-artifact-4 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "artifact 0000000000"
test th1-artifact-5 {$RESULT eq {TH_ERROR: artifact not found}}

###############################################################################

fossil test-th-eval "artifact tip test/th1.test"
test th1-artifact-6 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "artifact tip test/th1.test"
test th1-artifact-7 {[regexp -- {th1-artifact-7} $RESULT]}

###############################################################################

fossil test-th-eval "artifact 0000000000 test/th1.test"
test th1-artifact-8 {$RESULT eq {TH_ERROR: repository unavailable}}

###############################################################################

fossil test-th-eval --th-open-config "artifact 0000000000 test/th1.test"
test th1-artifact-9 {$RESULT eq {TH_ERROR: artifact not found}}

###############################################################################

fossil test-th-eval "globalState checkout"
test th1-globalState-1 {[string length $RESULT] > 0}

###############################################################################

fossil test-th-eval "globalState checkout"
test th1-globalState-2 {$RESULT eq [fossil test-th-eval checkout]}

###############################################################################

fossil test-th-eval "globalState configuration"
test th1-globalState-3 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval --th-open-config "globalState configuration"
test th1-globalState-4 {[string length $RESULT] > 0}

###############################################################################

fossil test-th-eval "globalState executable"
test th1-globalState-5 {[file rootname [file tail $RESULT]] eq "fossil"}

###############################################################################

fossil test-th-eval "globalState log"
test th1-globalState-6 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval --errorlog foserrors.log "globalState log"
test th1-globalState-7 {$RESULT eq "foserrors.log"}

###############################################################################

fossil test-th-eval "globalState repository"
test th1-globalState-8 {[string length $RESULT] > 0}

###############################################################################

fossil test-th-eval "globalState repository"
test th1-globalState-9 {$RESULT eq [fossil test-th-eval repository]}

###############################################################################

fossil test-th-eval "globalState top"
test th1-globalState-10 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval "globalState user"
test th1-globalState-11 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval --user fossil-th1-test "globalState user"
test th1-globalState-12 {$RESULT eq "fossil-th1-test"}

###############################################################################

fossil test-th-eval "globalState vfs"
test th1-globalState-13 {[string length $RESULT] == 0}

###############################################################################

fossil test-th-eval "globalState vfs"
test th1-globalState-14 {[string length $RESULT] == 0}

###############################################################################

if {$tcl_platform(platform) eq "windows"} then {
  set altVfs win32-longpath
} else {
  set altVfs unix-dotfile
}

###############################################################################

fossil test-th-eval --vfs $altVfs "globalState vfs"
test th1-globalState-15 {$RESULT eq $altVfs}

###############################################################################

fossil test-th-eval "globalState flags"
test th1-globalState-16 {$RESULT eq "0"}

###############################################################################

fossil test-th-eval "reinitialize; globalState configuration"
test th1-reinitialize-1 {$RESULT eq ""}

###############################################################################

fossil test-th-eval "reinitialize 1; globalState configuration"
test th1-reinitialize-2 {$RESULT ne ""}
Changes to test/utf.test.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#   http://www.hwaci.com/drh/
#
############################################################################
#
# Test UTF-8/UTF-16 detection
#

proc appendArgs {args} {
  eval append result $args
}

proc swap_byte_order {str} {
  set result ""
  for {set i 0} {$i < [string length $str]} {incr i} {
    set c [scan [string index $str $i] %c]
    set c [expr {(($c << 8) & 0xFF00) | (($c >> 8) & 0xFF)}]
    append result [format %c $c]
  }







<
<
<
<







14
15
16
17
18
19
20




21
22
23
24
25
26
27
#   http://www.hwaci.com/drh/
#
############################################################################
#
# Test UTF-8/UTF-16 detection
#





proc swap_byte_order {str} {
  set result ""
  for {set i 0} {$i < [string length $str]} {incr i} {
    set c [scan [string index $str $i] %c]
    set c [expr {(($c << 8) & 0xFF00) | (($c >> 8) & 0xFF)}]
    append result [format %c $c]
  }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
        incr fn
      }
    }
  }
  flush $f; close $f
}

set tempPath [expr {[info exists env(TEMP)] ? \
    $env(TEMP) : [file dirname [info script]]}]

if {$tcl_platform(platform) eq "windows"} then {
  set tempPath [string map [list \\ /] $tempPath]
}

createTestFiles $tempPath 100
# createTestResults $tempPath 100
########################### BEGIN GENERATED SECTION ###########################

utf-check 100 utf-check-100-0-0-0.jnk \
{File "%TEMP%/utf-check-100-0-0-0.jnk" has 0 bytes.
Starts with UTF-8 BOM: no







<
<
<
<
<
<
<







309
310
311
312
313
314
315







316
317
318
319
320
321
322
        incr fn
      }
    }
  }
  flush $f; close $f
}








createTestFiles $tempPath 100
# createTestResults $tempPath 100
########################### BEGIN GENERATED SECTION ###########################

utf-check 100 utf-check-100-0-0-0.jnk \
{File "%TEMP%/utf-check-100-0-0-0.jnk" has 0 bytes.
Starts with UTF-8 BOM: no
Changes to win/Makefile.PellesCGMake.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   zlib sources    1.2.5
#   Windows XP SP 2
# and
#   PellesC         6.00.4
#   gmake           3.80
#   zlib sources    1.2.5
#   Windows 7 Home Premium
#  

#  
PellesCDir=c:\Programme\PellesC

# Select between 32/64 bit code, default is 32 bit
#TARGETVERSION=64

ifeq ($(TARGETVERSION),64)
# 64 bit version







|

|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   zlib sources    1.2.5
#   Windows XP SP 2
# and
#   PellesC         6.00.4
#   gmake           3.80
#   zlib sources    1.2.5
#   Windows 7 Home Premium
#

#
PellesCDir=c:\Programme\PellesC

# Select between 32/64 bit code, default is 32 bit
#TARGETVERSION=64

ifeq ($(TARGETVERSION),64)
# 64 bit version
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

# define the special utilities files, needed to generate
# the automatically generated source files
UTILS=translate.exe mkindex.exe makeheaders.exe
UTILS_OBJ=$(UTILS:.exe=.obj)
UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))

# define the sqlite files, which need special flags on compile
SQLITESRC=sqlite3.c
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
SQLITEDEFINES=-DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS

# define the sqlite shell files, which need special flags on compile
SQLITESHELLSRC=shell.c
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

# define the th scripting files, which need special flags on compile
THSRC=th.c th_lang.c
ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))

# define the zlib files, needed by this compile







|



|

|



|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

# define the special utilities files, needed to generate
# the automatically generated source files
UTILS=translate.exe mkindex.exe makeheaders.exe
UTILS_OBJ=$(UTILS:.exe=.obj)
UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c))

# define the SQLite files, which need special flags on compile
SQLITESRC=sqlite3.c
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_WIN32_NO_ANSI

# define the SQLite shell files, which need special flags on compile
SQLITESHELLSRC=shell.c
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

# define the th scripting files, which need special flags on compile
THSRC=th.c th_lang.c
ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))

# define the zlib files, needed by this compile
Changes to win/Makefile.dmc.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
SSL    =

CFLAGS = -o
BCC    = $(DMDIR)\bin\dmc $(CFLAGS)
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32

SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS

SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c 

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR) 
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add allrepo attach bag bisect blob branch browse cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c







|

|

|

|










|






|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
SSL    =

CFLAGS = -o
BCC    = $(DMDIR)\bin\dmc $(CFLAGS)
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS

SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c 

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add allrepo attach bag bisect blob branch browse cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
	cp $@ $@

VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
	+$** > $@

page_index.h: mkindex$E $(SRC) 
	+$** > $@

clean:
	-del $(OBJDIR)\*.obj
	-del *.obj *_.c *.h *.map

realclean:







|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
	cp $@ $@

VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
	+$** > $@

page_index.h: mkindex$E $(SRC)
	+$** > $@

clean:
	-del $(OBJDIR)\*.obj
	-del *.obj *_.c *.h *.map

realclean:
290
291
292
293
294
295
296






297
298
299
300
301
302
303
	+translate$E $** > $@

$(OBJDIR)\finfo$O : finfo_.c finfo.h
	$(TCC) -o$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	+translate$E $** > $@







$(OBJDIR)\glob$O : glob_.c glob.h
	$(TCC) -o$@ -c glob_.c

glob_.c : $(SRCDIR)\glob.c
	+translate$E $** > $@








>
>
>
>
>
>







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
	+translate$E $** > $@

$(OBJDIR)\finfo$O : finfo_.c finfo.h
	$(TCC) -o$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	+translate$E $** > $@

$(OBJDIR)\fusefs$O : fusefs_.c fusefs.h
	$(TCC) -o$@ -c fusefs_.c

fusefs_.c : $(SRCDIR)\fusefs.c
	+translate$E $** > $@

$(OBJDIR)\glob$O : glob_.c glob.h
	$(TCC) -o$@ -c glob_.c

glob_.c : $(SRCDIR)\glob.c
	+translate$E $** > $@

772
773
774
775
776
777
778
779
780
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h VERSION.h
	 +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 cache_.c:cache.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_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.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 loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.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 regexp_.c:regexp.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 unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.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
	@copy /Y nul: headers







|

778
779
780
781
782
783
784
785
786
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h VERSION.h
	 +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 cache_.c:cache.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 fusefs_.c:fusefs.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_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.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 loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.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 regexp_.c:regexp.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 unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.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
	@copy /Y nul: headers
Changes to win/Makefile.mingw.
45
46
47
48
49
50
51













52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67




68
69
70
71
72
73
74
75
76
77
78
79
80
81








82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#### Enable JSON (http://www.json.org) support using "cson"
#
# FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL = 1














#### Enable scripting support via Tcl/Tk
#
# FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
# FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
# FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' sqlite
#
# USE_SYSTEM_SQLITE = 1





#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif









#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







>
>
>
>
>
>
>
>
>
>
>
>
>













|


>
>
>
>














>
>
>
>
>
>
>
>











|
|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#### Enable JSON (http://www.json.org) support using "cson"
#
# FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL = 1

#### Automatically build OpenSSL when building Fossil (causes rebuild
#    issues when building incrementally).
#
# FOSSIL_BUILD_SSL = 1

#### Enable TH1 scripts in embedded documentation files
#
# FOSSIL_ENABLE_TH1_DOCS = 1

#### Enable hooks for commands and web pages via TH1
#
# FOSSIL_ENABLE_TH1_HOOKS = 1

#### Enable scripting support via Tcl/Tk
#
# FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
# FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
# FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' SQLite
#
# USE_SYSTEM_SQLITE = 1

#### Use the miniz compression library
#
# FOSSIL_ENABLE_MINIZ = 1

#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif
ifeq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
SSLCONFIG = mingw
else
SSLCONFIG = mingw64
endif
ifndef FOSSIL_ENABLE_MINIZ
SSLCONFIG +=  --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
endif

#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
132
133
134
135
136
137
138
139






140
141
142
143
144
145
146
147
148
149
150
151




152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168






169
170
171
172
173
174
175
176
177
178
179
180












181
182
183
184
185
186
187

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)







#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR)





# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif







# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif













# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS







|
>
>
>
>
>
>











|
>
>
>
>

















>
>
>
>
>
>












>
>
>
>
>
>
>
>
>
>
>
>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
TCC += -L$(ZLIBDIR) -I$(ZINCDIR)
endif

#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR)

ifndef FOSSIL_ENABLE_MINIZ
RCC += -I$(ZINCDIR)
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif

# With miniz (i.e. instead of zlib)
ifdef FOSSIL_ENABLE_MINIZ
TCC += -DFOSSIL_ENABLE_MINIZ=1
RCC += -DFOSSIL_ENABLE_MINIZ=1
endif

# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif

# With TH1 embedded docs support
ifdef FOSSIL_ENABLE_TH1_DOCS
TCC += -DFOSSIL_ENABLE_TH1_DOCS=1
RCC += -DFOSSIL_ENABLE_TH1_DOCS=1
endif

# With TH1 hook support
ifdef FOSSIL_ENABLE_TH1_HOOKS
TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS
204
205
206
207
208
209
210
211

212
213
214
215


216
217
218
219
220

221
222
223
224
225

226
227
228
229
230
231
232
233
234






235
236
237
238
239
240
241
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# MinGW: If available, use the Unicode capable runtime startup code.

ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif



ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

# OpenSSL: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex -lz







#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32







|
>




>
>




|
>




|
>








|
>
>
>
>
>
>







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

#### MinGW: If available, use the Unicode capable runtime startup code.
#
ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif

#### SQLite: If enabled, use the system SQLite library.
#
ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

#### OpenSSL: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

#### Tcl: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
LIB += -lz
endif

#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32
249
250
251
252
253
254
255
256




257
258
259
260
261
262
263
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(ProgramFiles)\NSIS\MakeNSIS.exe"





#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line







|
>
>
>
>







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(PROGRAMFILES)\NSIS\MakeNSIS.exe"

#### Inno Setup executable location
#
INNOSETUP = "$(PROGRAMFILES)\Inno Setup 5\ISCC.exe"

#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line
291
292
293
294
295
296
297

298
299
300
301
302
303
304
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \

  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \







>







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
403
404
405
406
407
408
409

410
411
412
413
414
415
416
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \

  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \







>







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
515
516
517
518
519
520
521

522
523
524
525
526
527
528
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \

 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \







>







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \
596
597
598
599
600
601
602
603


604
605
606
607
608
609
610
611
612
613
614
615
616

617

618
619
620
621
622
623
624
625
626

627

628
629
630
631
632
633
634
635
636
637

638
639
640
641

642
643
644
645
646
647
648
 $(OBJDIR)/winfile.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/wysiwyg.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME = fossil.exe



#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex)
VERSION     = $(subst /,\,$(OBJDIR)/version)

CP          = copy

MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate
MAKEHEADERS = $(OBJDIR)/makeheaders
MKINDEX     = $(OBJDIR)/mkindex
VERSION     = $(OBJDIR)/version

CP          = cp

MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif

all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS

	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else

	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)







|
>
>









|
|
|
|
>

>





|
|
|
|
>

>










>




>







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
 $(OBJDIR)/winfile.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/wysiwyg.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME    = fossil.exe
APPTARGETS =
LIBTARGETS =

#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\,$(OBJDIR)/version.exe)
CAT         = type
CP          = copy
GREP        = find
MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate.exe
MAKEHEADERS = $(OBJDIR)/makeheaders.exe
MKINDEX     = $(OBJDIR)/mkindex.exe
VERSION     = $(OBJDIR)/version.exe
CAT         = cat
CP          = cp
GREP        = grep
MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif

all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS
	$(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else
	$(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692









693







694
695
696
697
698
699
700




701
702
703
704
705
706
707
708
709
710
711
712
713
714






715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735



736
737
738
739
740
741
742
743
744
745
746
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c

$(OBJDIR)/makeheaders:	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)










EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o








zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean





openssl:	zlib
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib mingw
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean







$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o zlib
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./fossil.nsi




$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
	$(MKINDEX) $(TRANS_SRC) >$@

$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
	$(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 \







|
|

|
|

|
|


|












|





>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>







>
>
>
>
|
|












>
>
>
>
>
>
|


















|

>
>
>
|


|







736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(TRANSLATE):	$(SRCDIR)/translate.c
	$(BCC) -o $(TRANSLATE) $(SRCDIR)/translate.c

$(MAKEHEADERS):	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(MAKEHEADERS) $(SRCDIR)/makeheaders.c

$(MKINDEX):	$(SRCDIR)/mkindex.c
	$(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1.  If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ.  = $(MINIZ_OBJ.0)


EXTRAOBJ = \
 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
 $(OBJDIR)/shell.o \
 $(OBJDIR)/th.o \
 $(OBJDIR)/th_lang.o \
 $(OBJDIR)/th_tcl.o \
 $(OBJDIR)/cson_amalgamation.o


zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

ifndef FOSSIL_ENABLE_MINIZ
LIBTARGETS += zlib
endif

openssl:	$(LIBTARGETS)
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG)
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean

APPTARGETS += $(LIBTARGETS)

ifdef FOSSIL_BUILD_SSL
APPTARGETS += openssl
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./setup/fossil.nsi

innosetup: $(OBJDIR) $(APPNAME)
	$(INNOSETUP) ./setup/fossil.iss -DAppVersion=$(shell $(CAT) ./VERSION)

$(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
	$(MKINDEX) $(TRANS_SRC) >$@

$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
	$(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 \
763
764
765
766
767
768
769

770
771
772
773
774
775
776
		$(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 \







>







871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
		$(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)/fusefs_.c:$(OBJDIR)/fusefs.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 \
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098








1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752
1753

1754
1755
1756




1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776



		$(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile

Makefile:

$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers

$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers

$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers

$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers

$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers

$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers

$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers

$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers

$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers

$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers

$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers

$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers

$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers

$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers

$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers

$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers

$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers

$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers

$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers

$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers

$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers

$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers

$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers

$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers

$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers









$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers

$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers

$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers

$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers

$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers

$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers

$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers

$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers

$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers

$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers

$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers

$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers

$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers

$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers

$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers

$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers

$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers

$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers

$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers

$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers

$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers

$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers

$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers

$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers

$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers

$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers

$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers

$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers

$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers

$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers

$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers

$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers

$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers

$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers

$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers

$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers

$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers

$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers

$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers

$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers

$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers

$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers

$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers

$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers

$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers

$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers

$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers

$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers

$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers

$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers

$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers

$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers

$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers

$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers

$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers

$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers

$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers

$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers

$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers

$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers

$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers

$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers

$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers

$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers

$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers

$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers

$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers

$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers

$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers

$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers

$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers

$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers


SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \

                 -D_HAVE__MINGW_H \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                -Daccess=file_access \

                -Dgetenv=fossil_getenv \
                -Dfopen=fossil_fopen





$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/cson_amalgamation.o:	$(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o











|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




>
>
>
>
>
>
>
>
|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|







|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




>
|





>









>



>
>
>
>




















>
>
>
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
		$(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile

Makefile:

$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers

$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers

$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers

$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers

$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers

$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers

$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers

$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers

$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers

$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers

$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers

$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers

$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers

$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers

$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers

$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers

$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers

$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers

$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers

$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers

$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers

$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers

$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers

$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers

$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/fusefs_.c:	$(SRCDIR)/fusefs.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/fusefs.c >$(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.o:	$(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.h:	$(OBJDIR)/headers

$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers

$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers

$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers

$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers

$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers

$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers

$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers

$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers

$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers

$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers

$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers

$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers

$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers

$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers

$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers

$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers

$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers

$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers

$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers

$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers

$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers

$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers

$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers

$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers

$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers

$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers

$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers

$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers

$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers

$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers

$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers

$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers

$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers

$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers

$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers

$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers

$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers

$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers

$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers

$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers

$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers

$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers

$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers

$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers

$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers

$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers

$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers

$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers

$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers

$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers

$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers

$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers

$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers

$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers

$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers

$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers

$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers

$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers

$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers

$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers

$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers

$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers

$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers

$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers

$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers

$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers

$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers

$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers

$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers

$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers

$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers

$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers

SQLITE_OPTIONS = -DNDEBUG=1 \
                 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                 -DSQLITE_WIN32_NO_ANSI \
                 -D_HAVE__MINGW_H \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                -Daccess=file_access \
                -Dsystem=fossil_system \
                -Dgetenv=fossil_getenv \
                -Dfopen=fossil_fopen

MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
                -DMINIZ_NO_TIME \
                -DMINIZ_NO_ARCHIVE_APIS

$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/cson_amalgamation.o:	$(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o

$(OBJDIR)/miniz.o:	$(SRCDIR)/miniz.c
	$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $(OBJDIR)/miniz.o

Changes to win/Makefile.mingw.mistachkin.
45
46
47
48
49
50
51













52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67




68
69
70
71
72
73
74
75
76
77
78
79
80
81








82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#### Enable JSON (http://www.json.org) support using "cson"
#
FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
FOSSIL_ENABLE_SSL = 1














#### Enable scripting support via Tcl/Tk
#
FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' sqlite
#
# USE_SYSTEM_SQLITE = 1





#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif









#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







>
>
>
>
>
>
>
>
>
>
>
>
>













|


>
>
>
>














>
>
>
>
>
>
>
>











|
|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#### Enable JSON (http://www.json.org) support using "cson"
#
FOSSIL_ENABLE_JSON = 1

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
FOSSIL_ENABLE_SSL = 1

#### Automatically build OpenSSL when building Fossil (causes rebuild
#    issues when building incrementally).
#
# FOSSIL_BUILD_SSL = 1

#### Enable TH1 scripts in embedded documentation files
#
# FOSSIL_ENABLE_TH1_DOCS = 1

#### Enable hooks for commands and web pages via TH1
#
FOSSIL_ENABLE_TH1_HOOKS = 1

#### Enable scripting support via Tcl/Tk
#
FOSSIL_ENABLE_TCL = 1

#### Load Tcl using the stubs library mechanism
#
FOSSIL_ENABLE_TCL_STUBS = 1

#### Load Tcl using the private stubs mechanism
#
FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1

#### Use 'system' SQLite
#
# USE_SYSTEM_SQLITE = 1

#### Use the miniz compression library
#
# FOSSIL_ENABLE_MINIZ = 1

#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### Check if the workaround for the MinGW command line handling needs to
#    be enabled by default.
#
ifndef MINGW_IS_32BIT_ONLY
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
MINGW_IS_32BIT_ONLY = 1
endif
endif
ifeq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
SSLCONFIG = mingw
else
SSLCONFIG = mingw64
endif
ifndef FOSSIL_ENABLE_MINIZ
SSLCONFIG +=  --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
endif

#### The directories where the zlib include and library files are located.
#
ZINCDIR = $(SRCDIR)/../compat/zlib
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
132
133
134
135
136
137
138
139






140
141
142
143
144
145
146
147
148
149
150
151




152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168






169
170
171
172
173
174
175
176
177
178
179
180












181
182
183
184
185
186
187

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)







#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR)





# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif







# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif













# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS







|
>
>
>
>
>
>











|
>
>
>
>

















>
>
>
>
>
>












>
>
>
>
>
>
>
>
>
>
>
>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

#### C Compile and options for use in building executables that
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.  This C compiler builds
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = $(PREFIX)gcc -Os -Wall

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
TCC += -L$(ZLIBDIR) -I$(ZINCDIR)
endif

#### Add the necessary command line options to build with debugging
#    symbols, if enabled.
#
ifdef FOSSIL_ENABLE_SYMBOLS
TCC += -g
endif

#### Compile resources for use in building executables that will run
#    on the target platform.
#
RCC = $(PREFIX)windres -I$(SRCDIR)

ifndef FOSSIL_ENABLE_MINIZ
RCC += -I$(ZINCDIR)
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
RCC += -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
RCC += -I$(TCLINCDIR)
endif
endif

# With miniz (i.e. instead of zlib)
ifdef FOSSIL_ENABLE_MINIZ
TCC += -DFOSSIL_ENABLE_MINIZ=1
RCC += -DFOSSIL_ENABLE_MINIZ=1
endif

# With MinGW command line handling workaround
ifdef MINGW_IS_32BIT_ONLY
TCC += -DBROKEN_MINGW_CMDLINE=1
RCC += -DBROKEN_MINGW_CMDLINE=1
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
RCC += -DFOSSIL_ENABLE_SSL=1
endif

# With TH1 embedded docs support
ifdef FOSSIL_ENABLE_TH1_DOCS
TCC += -DFOSSIL_ENABLE_TH1_DOCS=1
RCC += -DFOSSIL_ENABLE_TH1_DOCS=1
endif

# With TH1 hook support
ifdef FOSSIL_ENABLE_TH1_HOOKS
TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1
RCC += -DFOSSIL_ENABLE_TCL=1
# Either statically linked or via stubs
ifdef FOSSIL_ENABLE_TCL_STUBS
204
205
206
207
208
209
210
211

212
213
214
215


216
217
218
219
220

221
222
223
224
225

226
227
228
229
230
231
232
233
234






235
236
237
238
239
240
241
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# MinGW: If available, use the Unicode capable runtime startup code.

ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif



ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

# OpenSSL: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libraries required, if enabled.

ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex -lz







#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32







|
>




>
>




|
>




|
>








|
>
>
>
>
>
>







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

#### MinGW: If available, use the Unicode capable runtime startup code.
#
ifndef MINGW_IS_32BIT_ONLY
LIB += -municode
endif

#### SQLite: If enabled, use the system SQLite library.
#
ifdef USE_SYSTEM_SQLITE
LIB += -lsqlite3
endif

#### OpenSSL: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

#### Tcl: Add the necessary libraries required, if enabled.
#
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.
#
LIB += -lmingwex

#### When not using the miniz compression library, zlib is required.
#
ifndef FOSSIL_ENABLE_MINIZ
LIB += -lz
endif

#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_ENABLE_TCL_STUBS
LIB += -lkernel32 -lws2_32
249
250
251
252
253
254
255
256




257
258
259
260
261
262
263
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(ProgramFiles)\NSIS\MakeNSIS.exe"





#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line







|
>
>
>
>







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#### Tcl shell for use in running the fossil test suite.  This is only
#    used for testing.
#
TCLSH = tclsh

#### Nullsoft installer MakeNSIS location
#
MAKENSIS = "$(PROGRAMFILES)\NSIS\MakeNSIS.exe"

#### Inno Setup executable location
#
INNOSETUP = "$(PROGRAMFILES)\Inno Setup 5\ISCC.exe"

#### Include a configuration file that can override any one of these settings.
#
-include config.w32

# STOP HERE
# You should not need to change anything below this line
291
292
293
294
295
296
297

298
299
300
301
302
303
304
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \

  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \







>







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/glob.c \
  $(SRCDIR)/graph.c \
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
403
404
405
406
407
408
409

410
411
412
413
414
415
416
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \

  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \







>







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/glob_.c \
  $(OBJDIR)/graph_.c \
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
515
516
517
518
519
520
521

522
523
524
525
526
527
528
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \

 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \







>







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/glob.o \
 $(OBJDIR)/graph.o \
 $(OBJDIR)/gzip.o \
 $(OBJDIR)/http.o \
 $(OBJDIR)/http_socket.o \
 $(OBJDIR)/http_ssl.o \
 $(OBJDIR)/http_transport.o \
596
597
598
599
600
601
602
603


604
605
606
607
608
609
610
611
612
613
614
615
616

617

618
619
620
621
622
623
624
625
626

627

628
629
630
631
632
633
634
635
636
637

638
639
640
641

642
643
644
645
646
647
648
 $(OBJDIR)/winfile.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/wysiwyg.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME = fossil.exe



#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex)
VERSION     = $(subst /,\,$(OBJDIR)/version)

CP          = copy

MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate
MAKEHEADERS = $(OBJDIR)/makeheaders
MKINDEX     = $(OBJDIR)/mkindex
VERSION     = $(OBJDIR)/version

CP          = cp

MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif

all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS

	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else

	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)







|
>
>









|
|
|
|
>

>





|
|
|
|
>

>










>




>







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
 $(OBJDIR)/winfile.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/wysiwyg.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME    = fossil.exe
APPTARGETS =
LIBTARGETS =

#### If the USE_WINDOWS variable exists, it is assumed that we are building
#    inside of a Windows-style shell; otherwise, it is assumed that we are
#    building inside of a Unix-style shell.  Note that the "move" command is
#    broken when attempting to use it from the Windows shell via MinGW make
#    because the SHELL variable is only used for certain commands that are
#    recognized internally by make.
#
ifdef USE_WINDOWS
TRANSLATE   = $(subst /,\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\,$(OBJDIR)/version.exe)
CAT         = type
CP          = copy
GREP        = find
MV          = copy
RM          = del /Q
MKDIR       = -mkdir
RMDIR       = rmdir /S /Q
else
TRANSLATE   = $(OBJDIR)/translate.exe
MAKEHEADERS = $(OBJDIR)/makeheaders.exe
MKINDEX     = $(OBJDIR)/mkindex.exe
VERSION     = $(OBJDIR)/version.exe
CAT         = cat
CP          = cp
GREP        = grep
MV          = mv
RM          = rm -f
MKDIR       = -mkdir -p
RMDIR       = rm -rf
endif

all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/fossil.o:	$(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS
	$(CAT) $(subst /,\,$(SRCDIR)\miniz.c) | $(GREP) "define MZ_VERSION" > $(subst /,\,$(OBJDIR)\minizver.h)
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
	$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else
	$(CAT) $(SRCDIR)/miniz.c | $(GREP) "define MZ_VERSION" > $(OBJDIR)/minizver.h
	$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
	$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
	$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o

install:	$(OBJDIR) $(APPNAME)
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692









693







694
695
696
697
698
699
700




701
702
703
704
705
706
707
708
709
710
711
712
713
714






715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735



736
737
738
739
740
741
742
743
744
745
746
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c

$(OBJDIR)/makeheaders:	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)










EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o








zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean





openssl:	zlib
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib mingw
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean







$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o zlib
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./fossil.nsi




$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
	$(MKINDEX) $(TRANS_SRC) >$@

$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
	$(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 \







|
|

|
|

|
|


|












|





>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>







>
>
>
>
|
|












>
>
>
>
>
>
|


















|

>
>
>
|


|







736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
$(OBJDIR):
ifdef USE_WINDOWS
	$(MKDIR) $(subst /,\,$(OBJDIR))
else
	$(MKDIR) $(OBJDIR)
endif

$(TRANSLATE):	$(SRCDIR)/translate.c
	$(BCC) -o $(TRANSLATE) $(SRCDIR)/translate.c

$(MAKEHEADERS):	$(SRCDIR)/makeheaders.c
	$(BCC) -o $(MAKEHEADERS) $(SRCDIR)/makeheaders.c

$(MKINDEX):	$(SRCDIR)/mkindex.c
	$(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c

$(VERSION): $(SRCDIR)/mkversion.c
	$(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 =
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1.  If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ.  = $(MINIZ_OBJ.0)


EXTRAOBJ = \
 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
 $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
 $(OBJDIR)/shell.o \
 $(OBJDIR)/th.o \
 $(OBJDIR)/th_lang.o \
 $(OBJDIR)/th_tcl.o \
 $(OBJDIR)/cson_amalgamation.o


zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

ifndef FOSSIL_ENABLE_MINIZ
LIBTARGETS += zlib
endif

openssl:	$(LIBTARGETS)
	cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG)
	$(MAKE) -C $(OPENSSLLIBDIR) build_libs

clean-openssl:
	$(MAKE) -C $(OPENSSLLIBDIR) clean

tcl:
	cd $(TCLSRCDIR)/win;./configure
	$(MAKE) -C $(TCLSRCDIR)/win $(TCLTARGET)

clean-tcl:
	$(MAKE) -C $(TCLSRCDIR)/win distclean

APPTARGETS += $(LIBTARGETS)

ifdef FOSSIL_BUILD_SSL
APPTARGETS += openssl
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
	# noop

clean:
ifdef USE_WINDOWS
	$(RM) $(subst /,\,$(APPNAME))
	$(RMDIR) $(subst /,\,$(OBJDIR))
else
	$(RM) $(APPNAME)
	$(RMDIR) $(OBJDIR)
endif

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./setup/fossil.nsi

innosetup: $(OBJDIR) $(APPNAME)
	$(INNOSETUP) ./setup/fossil.iss -DAppVersion=$(shell $(CAT) ./VERSION)

$(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
	$(MKINDEX) $(TRANS_SRC) >$@

$(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
	$(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 \
763
764
765
766
767
768
769

770
771
772
773
774
775
776
		$(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 \







>







871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
		$(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)/fusefs_.c:$(OBJDIR)/fusefs.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 \
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098








1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752
1753

1754
1755
1756




1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775




		$(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile

Makefile:

$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers

$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers

$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers

$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers

$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers

$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers

$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers

$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers

$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers

$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers

$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers

$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers

$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers

$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers

$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers

$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers

$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers

$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers

$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers

$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers

$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers

$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers

$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers

$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers

$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers









$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers

$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers

$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers

$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers

$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers

$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers

$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers

$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers

$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers

$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers

$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers

$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers

$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers

$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers

$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers

$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers

$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers

$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers

$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers

$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers

$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers

$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers

$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers

$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers

$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers

$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers

$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers

$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers

$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers

$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers

$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers

$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers

$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers

$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers

$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers

$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers

$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers

$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers

$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers

$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers

$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers

$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers

$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers

$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers

$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers

$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers

$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers

$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers

$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers

$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers

$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers

$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers

$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers

$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers

$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers

$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers

$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers

$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers

$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers

$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers

$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers

$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers

$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers

$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers

$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers

$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers

$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers

$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers

$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers

$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers

$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers

$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h  $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers


SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \

                 -D_HAVE__MINGW_H \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                -Daccess=file_access \

                -Dgetenv=fossil_getenv \
                -Dfopen=fossil_fopen





$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw.mistachkin
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/cson_amalgamation.o:	$(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw.mistachkin
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o











|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




>
>
>
>
>
>
>
>
|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|







|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




|


|




>
|





>









>



>
>
>
>



















>
>
>
>
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
		$(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile

Makefile:

$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

$(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/add.o -c $(OBJDIR)/add_.c

$(OBJDIR)/add.h:	$(OBJDIR)/headers

$(OBJDIR)/allrepo_.c:	$(SRCDIR)/allrepo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/allrepo.c >$(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.o:	$(OBJDIR)/allrepo_.c $(OBJDIR)/allrepo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/allrepo.o -c $(OBJDIR)/allrepo_.c

$(OBJDIR)/allrepo.h:	$(OBJDIR)/headers

$(OBJDIR)/attach_.c:	$(SRCDIR)/attach.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/attach.c >$(OBJDIR)/attach_.c

$(OBJDIR)/attach.o:	$(OBJDIR)/attach_.c $(OBJDIR)/attach.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/attach.o -c $(OBJDIR)/attach_.c

$(OBJDIR)/attach.h:	$(OBJDIR)/headers

$(OBJDIR)/bag_.c:	$(SRCDIR)/bag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/bag.c >$(OBJDIR)/bag_.c

$(OBJDIR)/bag.o:	$(OBJDIR)/bag_.c $(OBJDIR)/bag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bag.o -c $(OBJDIR)/bag_.c

$(OBJDIR)/bag.h:	$(OBJDIR)/headers

$(OBJDIR)/bisect_.c:	$(SRCDIR)/bisect.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/bisect.c >$(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.o:	$(OBJDIR)/bisect_.c $(OBJDIR)/bisect.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/bisect.o -c $(OBJDIR)/bisect_.c

$(OBJDIR)/bisect.h:	$(OBJDIR)/headers

$(OBJDIR)/blob_.c:	$(SRCDIR)/blob.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/blob.c >$(OBJDIR)/blob_.c

$(OBJDIR)/blob.o:	$(OBJDIR)/blob_.c $(OBJDIR)/blob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/blob.o -c $(OBJDIR)/blob_.c

$(OBJDIR)/blob.h:	$(OBJDIR)/headers

$(OBJDIR)/branch_.c:	$(SRCDIR)/branch.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/branch.c >$(OBJDIR)/branch_.c

$(OBJDIR)/branch.o:	$(OBJDIR)/branch_.c $(OBJDIR)/branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/branch.o -c $(OBJDIR)/branch_.c

$(OBJDIR)/branch.h:	$(OBJDIR)/headers

$(OBJDIR)/browse_.c:	$(SRCDIR)/browse.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/browse.c >$(OBJDIR)/browse_.c

$(OBJDIR)/browse.o:	$(OBJDIR)/browse_.c $(OBJDIR)/browse.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/browse.o -c $(OBJDIR)/browse_.c

$(OBJDIR)/browse.h:	$(OBJDIR)/headers

$(OBJDIR)/cache_.c:	$(SRCDIR)/cache.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/cache.c >$(OBJDIR)/cache_.c

$(OBJDIR)/cache.o:	$(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c

$(OBJDIR)/cache.h:	$(OBJDIR)/headers

$(OBJDIR)/captcha_.c:	$(SRCDIR)/captcha.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/captcha.c >$(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.o:	$(OBJDIR)/captcha_.c $(OBJDIR)/captcha.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/captcha.o -c $(OBJDIR)/captcha_.c

$(OBJDIR)/captcha.h:	$(OBJDIR)/headers

$(OBJDIR)/cgi_.c:	$(SRCDIR)/cgi.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/cgi.c >$(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.o:	$(OBJDIR)/cgi_.c $(OBJDIR)/cgi.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/cgi.o -c $(OBJDIR)/cgi_.c

$(OBJDIR)/cgi.h:	$(OBJDIR)/headers

$(OBJDIR)/checkin_.c:	$(SRCDIR)/checkin.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/checkin.c >$(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.o:	$(OBJDIR)/checkin_.c $(OBJDIR)/checkin.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkin.o -c $(OBJDIR)/checkin_.c

$(OBJDIR)/checkin.h:	$(OBJDIR)/headers

$(OBJDIR)/checkout_.c:	$(SRCDIR)/checkout.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/checkout.c >$(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.o:	$(OBJDIR)/checkout_.c $(OBJDIR)/checkout.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/checkout.o -c $(OBJDIR)/checkout_.c

$(OBJDIR)/checkout.h:	$(OBJDIR)/headers

$(OBJDIR)/clearsign_.c:	$(SRCDIR)/clearsign.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/clearsign.c >$(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.o:	$(OBJDIR)/clearsign_.c $(OBJDIR)/clearsign.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clearsign.o -c $(OBJDIR)/clearsign_.c

$(OBJDIR)/clearsign.h:	$(OBJDIR)/headers

$(OBJDIR)/clone_.c:	$(SRCDIR)/clone.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/clone.c >$(OBJDIR)/clone_.c

$(OBJDIR)/clone.o:	$(OBJDIR)/clone_.c $(OBJDIR)/clone.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/clone.o -c $(OBJDIR)/clone_.c

$(OBJDIR)/clone.h:	$(OBJDIR)/headers

$(OBJDIR)/comformat_.c:	$(SRCDIR)/comformat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/comformat.c >$(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.o:	$(OBJDIR)/comformat_.c $(OBJDIR)/comformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/comformat.o -c $(OBJDIR)/comformat_.c

$(OBJDIR)/comformat.h:	$(OBJDIR)/headers

$(OBJDIR)/configure_.c:	$(SRCDIR)/configure.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/configure.c >$(OBJDIR)/configure_.c

$(OBJDIR)/configure.o:	$(OBJDIR)/configure_.c $(OBJDIR)/configure.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/configure.o -c $(OBJDIR)/configure_.c

$(OBJDIR)/configure.h:	$(OBJDIR)/headers

$(OBJDIR)/content_.c:	$(SRCDIR)/content.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/content.c >$(OBJDIR)/content_.c

$(OBJDIR)/content.o:	$(OBJDIR)/content_.c $(OBJDIR)/content.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/content.o -c $(OBJDIR)/content_.c

$(OBJDIR)/content.h:	$(OBJDIR)/headers

$(OBJDIR)/db_.c:	$(SRCDIR)/db.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/db.c >$(OBJDIR)/db_.c

$(OBJDIR)/db.o:	$(OBJDIR)/db_.c $(OBJDIR)/db.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/db.o -c $(OBJDIR)/db_.c

$(OBJDIR)/db.h:	$(OBJDIR)/headers

$(OBJDIR)/delta_.c:	$(SRCDIR)/delta.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/delta.c >$(OBJDIR)/delta_.c

$(OBJDIR)/delta.o:	$(OBJDIR)/delta_.c $(OBJDIR)/delta.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/delta.o -c $(OBJDIR)/delta_.c

$(OBJDIR)/delta.h:	$(OBJDIR)/headers

$(OBJDIR)/deltacmd_.c:	$(SRCDIR)/deltacmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

$(OBJDIR)/diff_.c:	$(SRCDIR)/diff.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/diff.c >$(OBJDIR)/diff_.c

$(OBJDIR)/diff.o:	$(OBJDIR)/diff_.c $(OBJDIR)/diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diff.o -c $(OBJDIR)/diff_.c

$(OBJDIR)/diff.h:	$(OBJDIR)/headers

$(OBJDIR)/diffcmd_.c:	$(SRCDIR)/diffcmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/diffcmd.c >$(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.o:	$(OBJDIR)/diffcmd_.c $(OBJDIR)/diffcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/diffcmd.o -c $(OBJDIR)/diffcmd_.c

$(OBJDIR)/diffcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/doc_.c:	$(SRCDIR)/doc.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/doc.c >$(OBJDIR)/doc_.c

$(OBJDIR)/doc.o:	$(OBJDIR)/doc_.c $(OBJDIR)/doc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/doc.o -c $(OBJDIR)/doc_.c

$(OBJDIR)/doc.h:	$(OBJDIR)/headers

$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$(OBJDIR)/encode_.c

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$(OBJDIR)/event_.c

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

$(OBJDIR)/event.h:	$(OBJDIR)/headers

$(OBJDIR)/export_.c:	$(SRCDIR)/export.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/export.c >$(OBJDIR)/export_.c

$(OBJDIR)/export.o:	$(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c

$(OBJDIR)/export.h:	$(OBJDIR)/headers

$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/file.c >$(OBJDIR)/file_.c

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/finfo.c >$(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

$(OBJDIR)/finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/fusefs_.c:	$(SRCDIR)/fusefs.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/fusefs.c >$(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.o:	$(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c

$(OBJDIR)/fusefs.h:	$(OBJDIR)/headers

$(OBJDIR)/glob_.c:	$(SRCDIR)/glob.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c

$(OBJDIR)/glob.o:	$(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c

$(OBJDIR)/glob.h:	$(OBJDIR)/headers

$(OBJDIR)/graph_.c:	$(SRCDIR)/graph.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c

$(OBJDIR)/graph.o:	$(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c

$(OBJDIR)/graph.h:	$(OBJDIR)/headers

$(OBJDIR)/gzip_.c:	$(SRCDIR)/gzip.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/gzip.c >$(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.o:	$(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c

$(OBJDIR)/gzip.h:	$(OBJDIR)/headers

$(OBJDIR)/http_.c:	$(SRCDIR)/http.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http.c >$(OBJDIR)/http_.c

$(OBJDIR)/http.o:	$(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http.o -c $(OBJDIR)/http_.c

$(OBJDIR)/http.h:	$(OBJDIR)/headers

$(OBJDIR)/http_socket_.c:	$(SRCDIR)/http_socket.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_socket.c >$(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.o:	$(OBJDIR)/http_socket_.c $(OBJDIR)/http_socket.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_socket.o -c $(OBJDIR)/http_socket_.c

$(OBJDIR)/http_socket.h:	$(OBJDIR)/headers

$(OBJDIR)/http_ssl_.c:	$(SRCDIR)/http_ssl.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_ssl.c >$(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.o:	$(OBJDIR)/http_ssl_.c $(OBJDIR)/http_ssl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_ssl.o -c $(OBJDIR)/http_ssl_.c

$(OBJDIR)/http_ssl.h:	$(OBJDIR)/headers

$(OBJDIR)/http_transport_.c:	$(SRCDIR)/http_transport.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/http_transport.c >$(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.o:	$(OBJDIR)/http_transport_.c $(OBJDIR)/http_transport.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/http_transport.o -c $(OBJDIR)/http_transport_.c

$(OBJDIR)/http_transport.h:	$(OBJDIR)/headers

$(OBJDIR)/import_.c:	$(SRCDIR)/import.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/import.c >$(OBJDIR)/import_.c

$(OBJDIR)/import.o:	$(OBJDIR)/import_.c $(OBJDIR)/import.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/import.o -c $(OBJDIR)/import_.c

$(OBJDIR)/import.h:	$(OBJDIR)/headers

$(OBJDIR)/info_.c:	$(SRCDIR)/info.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/info.c >$(OBJDIR)/info_.c

$(OBJDIR)/info.o:	$(OBJDIR)/info_.c $(OBJDIR)/info.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/info.o -c $(OBJDIR)/info_.c

$(OBJDIR)/info.h:	$(OBJDIR)/headers

$(OBJDIR)/json_.c:	$(SRCDIR)/json.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json.c >$(OBJDIR)/json_.c

$(OBJDIR)/json.o:	$(OBJDIR)/json_.c $(OBJDIR)/json.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json.o -c $(OBJDIR)/json_.c

$(OBJDIR)/json.h:	$(OBJDIR)/headers

$(OBJDIR)/json_artifact_.c:	$(SRCDIR)/json_artifact.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_artifact.c >$(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.o:	$(OBJDIR)/json_artifact_.c $(OBJDIR)/json_artifact.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_artifact.o -c $(OBJDIR)/json_artifact_.c

$(OBJDIR)/json_artifact.h:	$(OBJDIR)/headers

$(OBJDIR)/json_branch_.c:	$(SRCDIR)/json_branch.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_branch.c >$(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.o:	$(OBJDIR)/json_branch_.c $(OBJDIR)/json_branch.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_branch.o -c $(OBJDIR)/json_branch_.c

$(OBJDIR)/json_branch.h:	$(OBJDIR)/headers

$(OBJDIR)/json_config_.c:	$(SRCDIR)/json_config.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_config.c >$(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.o:	$(OBJDIR)/json_config_.c $(OBJDIR)/json_config.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_config.o -c $(OBJDIR)/json_config_.c

$(OBJDIR)/json_config.h:	$(OBJDIR)/headers

$(OBJDIR)/json_diff_.c:	$(SRCDIR)/json_diff.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_diff.c >$(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.o:	$(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c

$(OBJDIR)/json_diff.h:	$(OBJDIR)/headers

$(OBJDIR)/json_dir_.c:	$(SRCDIR)/json_dir.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.o:	$(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c

$(OBJDIR)/json_dir.h:	$(OBJDIR)/headers

$(OBJDIR)/json_finfo_.c:	$(SRCDIR)/json_finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.o:	$(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c

$(OBJDIR)/json_finfo.h:	$(OBJDIR)/headers

$(OBJDIR)/json_login_.c:	$(SRCDIR)/json_login.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.o:	$(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c

$(OBJDIR)/json_login.h:	$(OBJDIR)/headers

$(OBJDIR)/json_query_.c:	$(SRCDIR)/json_query.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_query.c >$(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.o:	$(OBJDIR)/json_query_.c $(OBJDIR)/json_query.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_query.o -c $(OBJDIR)/json_query_.c

$(OBJDIR)/json_query.h:	$(OBJDIR)/headers

$(OBJDIR)/json_report_.c:	$(SRCDIR)/json_report.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_report.c >$(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.o:	$(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c

$(OBJDIR)/json_report.h:	$(OBJDIR)/headers

$(OBJDIR)/json_status_.c:	$(SRCDIR)/json_status.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.o:	$(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c

$(OBJDIR)/json_status.h:	$(OBJDIR)/headers

$(OBJDIR)/json_tag_.c:	$(SRCDIR)/json_tag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.o:	$(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c

$(OBJDIR)/json_tag.h:	$(OBJDIR)/headers

$(OBJDIR)/json_timeline_.c:	$(SRCDIR)/json_timeline.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_timeline.c >$(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.o:	$(OBJDIR)/json_timeline_.c $(OBJDIR)/json_timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_timeline.o -c $(OBJDIR)/json_timeline_.c

$(OBJDIR)/json_timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/json_user_.c:	$(SRCDIR)/json_user.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_user.c >$(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.o:	$(OBJDIR)/json_user_.c $(OBJDIR)/json_user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_user.o -c $(OBJDIR)/json_user_.c

$(OBJDIR)/json_user.h:	$(OBJDIR)/headers

$(OBJDIR)/json_wiki_.c:	$(SRCDIR)/json_wiki.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/json_wiki.c >$(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.o:	$(OBJDIR)/json_wiki_.c $(OBJDIR)/json_wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/json_wiki.o -c $(OBJDIR)/json_wiki_.c

$(OBJDIR)/json_wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/leaf_.c:	$(SRCDIR)/leaf.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/leaf.c >$(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.o:	$(OBJDIR)/leaf_.c $(OBJDIR)/leaf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/leaf.o -c $(OBJDIR)/leaf_.c

$(OBJDIR)/leaf.h:	$(OBJDIR)/headers

$(OBJDIR)/loadctrl_.c:	$(SRCDIR)/loadctrl.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/loadctrl.c >$(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.o:	$(OBJDIR)/loadctrl_.c $(OBJDIR)/loadctrl.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/loadctrl.o -c $(OBJDIR)/loadctrl_.c

$(OBJDIR)/loadctrl.h:	$(OBJDIR)/headers

$(OBJDIR)/login_.c:	$(SRCDIR)/login.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c

$(OBJDIR)/login.o:	$(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c

$(OBJDIR)/login.h:	$(OBJDIR)/headers

$(OBJDIR)/lookslike_.c:	$(SRCDIR)/lookslike.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.o:	$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c

$(OBJDIR)/lookslike.h:	$(OBJDIR)/headers

$(OBJDIR)/main_.c:	$(SRCDIR)/main.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c

$(OBJDIR)/main.o:	$(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c

$(OBJDIR)/main.h:	$(OBJDIR)/headers

$(OBJDIR)/manifest_.c:	$(SRCDIR)/manifest.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.o:	$(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c

$(OBJDIR)/manifest.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_.c:	$(SRCDIR)/markdown.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.o:	$(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c

$(OBJDIR)/markdown.h:	$(OBJDIR)/headers

$(OBJDIR)/markdown_html_.c:	$(SRCDIR)/markdown_html.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.o:	$(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c

$(OBJDIR)/markdown_html.h:	$(OBJDIR)/headers

$(OBJDIR)/md5_.c:	$(SRCDIR)/md5.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c

$(OBJDIR)/md5.o:	$(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c

$(OBJDIR)/md5.h:	$(OBJDIR)/headers

$(OBJDIR)/merge_.c:	$(SRCDIR)/merge.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/merge.c >$(OBJDIR)/merge_.c

$(OBJDIR)/merge.o:	$(OBJDIR)/merge_.c $(OBJDIR)/merge.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge.o -c $(OBJDIR)/merge_.c

$(OBJDIR)/merge.h:	$(OBJDIR)/headers

$(OBJDIR)/merge3_.c:	$(SRCDIR)/merge3.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/merge3.c >$(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.o:	$(OBJDIR)/merge3_.c $(OBJDIR)/merge3.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/merge3.o -c $(OBJDIR)/merge3_.c

$(OBJDIR)/merge3.h:	$(OBJDIR)/headers

$(OBJDIR)/moderate_.c:	$(SRCDIR)/moderate.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/moderate.c >$(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.o:	$(OBJDIR)/moderate_.c $(OBJDIR)/moderate.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/moderate.o -c $(OBJDIR)/moderate_.c

$(OBJDIR)/moderate.h:	$(OBJDIR)/headers

$(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/name.c >$(OBJDIR)/name_.c

$(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c

$(OBJDIR)/name.h:	$(OBJDIR)/headers

$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/path.c >$(OBJDIR)/path_.c

$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c

$(OBJDIR)/path.h:	$(OBJDIR)/headers

$(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c

$(OBJDIR)/pivot.h:	$(OBJDIR)/headers

$(OBJDIR)/popen_.c:	$(SRCDIR)/popen.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/popen.c >$(OBJDIR)/popen_.c

$(OBJDIR)/popen.o:	$(OBJDIR)/popen_.c $(OBJDIR)/popen.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/popen.o -c $(OBJDIR)/popen_.c

$(OBJDIR)/popen.h:	$(OBJDIR)/headers

$(OBJDIR)/pqueue_.c:	$(SRCDIR)/pqueue.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/pqueue.c >$(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.o:	$(OBJDIR)/pqueue_.c $(OBJDIR)/pqueue.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/pqueue.o -c $(OBJDIR)/pqueue_.c

$(OBJDIR)/pqueue.h:	$(OBJDIR)/headers

$(OBJDIR)/printf_.c:	$(SRCDIR)/printf.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/printf.c >$(OBJDIR)/printf_.c

$(OBJDIR)/printf.o:	$(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c

$(OBJDIR)/printf.h:	$(OBJDIR)/headers

$(OBJDIR)/rebuild_.c:	$(SRCDIR)/rebuild.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/rebuild.c >$(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.o:	$(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c

$(OBJDIR)/rebuild.h:	$(OBJDIR)/headers

$(OBJDIR)/regexp_.c:	$(SRCDIR)/regexp.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.o:	$(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c

$(OBJDIR)/regexp.h:	$(OBJDIR)/headers

$(OBJDIR)/report_.c:	$(SRCDIR)/report.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c

$(OBJDIR)/report.o:	$(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c

$(OBJDIR)/report.h:	$(OBJDIR)/headers

$(OBJDIR)/rss_.c:	$(SRCDIR)/rss.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/rss.c >$(OBJDIR)/rss_.c

$(OBJDIR)/rss.o:	$(OBJDIR)/rss_.c $(OBJDIR)/rss.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/rss.o -c $(OBJDIR)/rss_.c

$(OBJDIR)/rss.h:	$(OBJDIR)/headers

$(OBJDIR)/schema_.c:	$(SRCDIR)/schema.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/schema.c >$(OBJDIR)/schema_.c

$(OBJDIR)/schema.o:	$(OBJDIR)/schema_.c $(OBJDIR)/schema.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/schema.o -c $(OBJDIR)/schema_.c

$(OBJDIR)/schema.h:	$(OBJDIR)/headers

$(OBJDIR)/search_.c:	$(SRCDIR)/search.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/search.c >$(OBJDIR)/search_.c

$(OBJDIR)/search.o:	$(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c

$(OBJDIR)/search.h:	$(OBJDIR)/headers

$(OBJDIR)/setup_.c:	$(SRCDIR)/setup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c

$(OBJDIR)/setup.o:	$(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c

$(OBJDIR)/setup.h:	$(OBJDIR)/headers

$(OBJDIR)/sha1_.c:	$(SRCDIR)/sha1.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sha1.c >$(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.o:	$(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c

$(OBJDIR)/sha1.h:	$(OBJDIR)/headers

$(OBJDIR)/shun_.c:	$(SRCDIR)/shun.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/shun.c >$(OBJDIR)/shun_.c

$(OBJDIR)/shun.o:	$(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c

$(OBJDIR)/shun.h:	$(OBJDIR)/headers

$(OBJDIR)/skins_.c:	$(SRCDIR)/skins.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/skins.c >$(OBJDIR)/skins_.c

$(OBJDIR)/skins.o:	$(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/skins.o -c $(OBJDIR)/skins_.c

$(OBJDIR)/skins.h:	$(OBJDIR)/headers

$(OBJDIR)/sqlcmd_.c:	$(SRCDIR)/sqlcmd.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sqlcmd.c >$(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.o:	$(OBJDIR)/sqlcmd_.c $(OBJDIR)/sqlcmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sqlcmd.o -c $(OBJDIR)/sqlcmd_.c

$(OBJDIR)/sqlcmd.h:	$(OBJDIR)/headers

$(OBJDIR)/stash_.c:	$(SRCDIR)/stash.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/stash.c >$(OBJDIR)/stash_.c

$(OBJDIR)/stash.o:	$(OBJDIR)/stash_.c $(OBJDIR)/stash.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stash.o -c $(OBJDIR)/stash_.c

$(OBJDIR)/stash.h:	$(OBJDIR)/headers

$(OBJDIR)/stat_.c:	$(SRCDIR)/stat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/stat.c >$(OBJDIR)/stat_.c

$(OBJDIR)/stat.o:	$(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c

$(OBJDIR)/stat.h:	$(OBJDIR)/headers

$(OBJDIR)/style_.c:	$(SRCDIR)/style.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/style.c >$(OBJDIR)/style_.c

$(OBJDIR)/style.o:	$(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/style.o -c $(OBJDIR)/style_.c

$(OBJDIR)/style.h:	$(OBJDIR)/headers

$(OBJDIR)/sync_.c:	$(SRCDIR)/sync.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/sync.c >$(OBJDIR)/sync_.c

$(OBJDIR)/sync.o:	$(OBJDIR)/sync_.c $(OBJDIR)/sync.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/sync.o -c $(OBJDIR)/sync_.c

$(OBJDIR)/sync.h:	$(OBJDIR)/headers

$(OBJDIR)/tag_.c:	$(SRCDIR)/tag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tag.c >$(OBJDIR)/tag_.c

$(OBJDIR)/tag.o:	$(OBJDIR)/tag_.c $(OBJDIR)/tag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tag.o -c $(OBJDIR)/tag_.c

$(OBJDIR)/tag.h:	$(OBJDIR)/headers

$(OBJDIR)/tar_.c:	$(SRCDIR)/tar.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tar.c >$(OBJDIR)/tar_.c

$(OBJDIR)/tar.o:	$(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c

$(OBJDIR)/tar.h:	$(OBJDIR)/headers

$(OBJDIR)/th_main_.c:	$(SRCDIR)/th_main.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/th_main.c >$(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.o:	$(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/th_main.o -c $(OBJDIR)/th_main_.c

$(OBJDIR)/th_main.h:	$(OBJDIR)/headers

$(OBJDIR)/timeline_.c:	$(SRCDIR)/timeline.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/timeline.c >$(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.o:	$(OBJDIR)/timeline_.c $(OBJDIR)/timeline.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/timeline.o -c $(OBJDIR)/timeline_.c

$(OBJDIR)/timeline.h:	$(OBJDIR)/headers

$(OBJDIR)/tkt_.c:	$(SRCDIR)/tkt.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tkt.c >$(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.o:	$(OBJDIR)/tkt_.c $(OBJDIR)/tkt.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tkt.o -c $(OBJDIR)/tkt_.c

$(OBJDIR)/tkt.h:	$(OBJDIR)/headers

$(OBJDIR)/tktsetup_.c:	$(SRCDIR)/tktsetup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/tktsetup.c >$(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.o:	$(OBJDIR)/tktsetup_.c $(OBJDIR)/tktsetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/tktsetup.o -c $(OBJDIR)/tktsetup_.c

$(OBJDIR)/tktsetup.h:	$(OBJDIR)/headers

$(OBJDIR)/undo_.c:	$(SRCDIR)/undo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/undo.c >$(OBJDIR)/undo_.c

$(OBJDIR)/undo.o:	$(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c

$(OBJDIR)/undo.h:	$(OBJDIR)/headers

$(OBJDIR)/unicode_.c:	$(SRCDIR)/unicode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.o:	$(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c

$(OBJDIR)/unicode.h:	$(OBJDIR)/headers

$(OBJDIR)/update_.c:	$(SRCDIR)/update.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c

$(OBJDIR)/update.o:	$(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c

$(OBJDIR)/update.h:	$(OBJDIR)/headers

$(OBJDIR)/url_.c:	$(SRCDIR)/url.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/url.c >$(OBJDIR)/url_.c

$(OBJDIR)/url.o:	$(OBJDIR)/url_.c $(OBJDIR)/url.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/url.o -c $(OBJDIR)/url_.c

$(OBJDIR)/url.h:	$(OBJDIR)/headers

$(OBJDIR)/user_.c:	$(SRCDIR)/user.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/user.c >$(OBJDIR)/user_.c

$(OBJDIR)/user.o:	$(OBJDIR)/user_.c $(OBJDIR)/user.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/user.o -c $(OBJDIR)/user_.c

$(OBJDIR)/user.h:	$(OBJDIR)/headers

$(OBJDIR)/utf8_.c:	$(SRCDIR)/utf8.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/utf8.c >$(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.o:	$(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c

$(OBJDIR)/utf8.h:	$(OBJDIR)/headers

$(OBJDIR)/util_.c:	$(SRCDIR)/util.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c

$(OBJDIR)/util.o:	$(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c

$(OBJDIR)/util.h:	$(OBJDIR)/headers

$(OBJDIR)/verify_.c:	$(SRCDIR)/verify.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c

$(OBJDIR)/verify.o:	$(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c

$(OBJDIR)/verify.h:	$(OBJDIR)/headers

$(OBJDIR)/vfile_.c:	$(SRCDIR)/vfile.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/vfile.c >$(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.o:	$(OBJDIR)/vfile_.c $(OBJDIR)/vfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/vfile.o -c $(OBJDIR)/vfile_.c

$(OBJDIR)/vfile.h:	$(OBJDIR)/headers

$(OBJDIR)/wiki_.c:	$(SRCDIR)/wiki.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wiki.c >$(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.o:	$(OBJDIR)/wiki_.c $(OBJDIR)/wiki.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wiki.o -c $(OBJDIR)/wiki_.c

$(OBJDIR)/wiki.h:	$(OBJDIR)/headers

$(OBJDIR)/wikiformat_.c:	$(SRCDIR)/wikiformat.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wikiformat.c >$(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.o:	$(OBJDIR)/wikiformat_.c $(OBJDIR)/wikiformat.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wikiformat.o -c $(OBJDIR)/wikiformat_.c

$(OBJDIR)/wikiformat.h:	$(OBJDIR)/headers

$(OBJDIR)/winfile_.c:	$(SRCDIR)/winfile.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/winfile.c >$(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.o:	$(OBJDIR)/winfile_.c $(OBJDIR)/winfile.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winfile.o -c $(OBJDIR)/winfile_.c

$(OBJDIR)/winfile.h:	$(OBJDIR)/headers

$(OBJDIR)/winhttp_.c:	$(SRCDIR)/winhttp.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/winhttp.c >$(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.o:	$(OBJDIR)/winhttp_.c $(OBJDIR)/winhttp.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/winhttp.o -c $(OBJDIR)/winhttp_.c

$(OBJDIR)/winhttp.h:	$(OBJDIR)/headers

$(OBJDIR)/wysiwyg_.c:	$(SRCDIR)/wysiwyg.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/wysiwyg.c >$(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.o:	$(OBJDIR)/wysiwyg_.c $(OBJDIR)/wysiwyg.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/wysiwyg.o -c $(OBJDIR)/wysiwyg_.c

$(OBJDIR)/wysiwyg.h:	$(OBJDIR)/headers

$(OBJDIR)/xfer_.c:	$(SRCDIR)/xfer.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/xfer.c >$(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.o:	$(OBJDIR)/xfer_.c $(OBJDIR)/xfer.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfer.o -c $(OBJDIR)/xfer_.c

$(OBJDIR)/xfer.h:	$(OBJDIR)/headers

$(OBJDIR)/xfersetup_.c:	$(SRCDIR)/xfersetup.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/xfersetup.c >$(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.o:	$(OBJDIR)/xfersetup_.c $(OBJDIR)/xfersetup.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/xfersetup.o -c $(OBJDIR)/xfersetup_.c

$(OBJDIR)/xfersetup.h:	$(OBJDIR)/headers

$(OBJDIR)/zip_.c:	$(SRCDIR)/zip.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c

$(OBJDIR)/zip.o:	$(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c

$(OBJDIR)/zip.h:	$(OBJDIR)/headers

SQLITE_OPTIONS = -DNDEBUG=1 \
                 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 -DSQLITE_THREADSAFE=0 \
                 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 -DSQLITE_OMIT_DEPRECATED \
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                 -DSQLITE_WIN32_NO_ANSI \
                 -D_HAVE__MINGW_H \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_OMIT_LOAD_EXTENSION=1 \
                -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                -Daccess=file_access \
                -Dsystem=fossil_system \
                -Dgetenv=fossil_getenv \
                -Dfopen=fossil_fopen

MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
                -DMINIZ_NO_TIME \
                -DMINIZ_NO_ARCHIVE_APIS

$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw.mistachkin
	$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/cson_amalgamation.o:	$(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw.mistachkin
	$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o

$(OBJDIR)/miniz.o:	$(SRCDIR)/miniz.c
	$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $(OBJDIR)/miniz.o

Changes to win/Makefile.msc.
1
2
3
4








5
6
7
8
9
10
11
12
13
14
15
16






17
18
19
20
21
22



23
24
25









26
27
28
29
30
31

32
33
















34
35
36
37
38
39
40
41
42
43
44
45
46
47




48
49
50
51
52
53
54
#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################








#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B      = ..
SRCDIR = $B\src
OBJDIR = .
OX     = .
O      = .obj
E      = .exe
P      = .pdb







# Uncomment to enable debug symbols
# DEBUG = 1

# Uncomment to enable JSON API
# FOSSIL_ENABLE_JSON = 1




# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1










# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1g\include

SSLLIBDIR = $(B)\compat\openssl-1.0.1g\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
















!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
!endif

# zlib options
ZINCDIR   = $(B)\compat\zlib
ZLIBDIR   = $(B)\compat\zlib
ZLIB      = zlib.lib

INCL      = /I. /I$(SRCDIR) /I$B\win\include /I$(ZINCDIR)





!ifdef FOSSIL_ENABLE_SSL
INCL      = $(INCL) /I$(SSLINCDIR)
!endif

!ifdef FOSSIL_ENABLE_TCL
INCL      = $(INCL) /I$(TCLINCDIR)




>
>
>
>
>
>
>
>





|
|
|
|
|
|
|
>
>
>
>
>
>






>
>
>



>
>
>
>
>
>
>
>
>





|
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This Makefile will only function correctly if used from a sub-directory
# that is a direct child of the top-level directory for this project.
#
!if !exist("..\.fossil-settings")
!error "Please change the current directory to the one containing this file."
!endif

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B       = ..
SRCDIR  = $B\src
OBJDIR  = .
OX      = .
O       = .obj
E       = .exe
P       = .pdb

# Perl is only necessary if OpenSSL support is enabled and it must
# be built from source code.  The PERLDIR variable should point to
# the directory containing the main Perl binary (i.e. "perl.exe").
PERLDIR = C:\Perl\bin
PERL    = perl.exe

# Uncomment to enable debug symbols
# DEBUG = 1

# Uncomment to enable JSON API
# FOSSIL_ENABLE_JSON = 1

# Uncomment to enable miniz usage
# FOSSIL_ENABLE_MINIZ = 1

# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to build SSL libraries
# FOSSIL_BUILD_SSL = 1

# Uncomment to enable TH1 scripts in embedded documentation files
# FOSSIL_ENABLE_TH1_DOCS = 1

# Uncomment to enable TH1 hooks
# FOSSIL_ENABLE_TH1_HOOKS = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLDIR    = $(B)\compat\openssl-1.0.1i
SSLINCDIR = $(SSLDIR)\inc32
SSLLIBDIR = $(SSLDIR)\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
!message Using 'x64' platform for OpenSSL...
SSLCONFIG = VC-WIN64A no-asm
SSLSETUP  = ms\do_win64a.bat
SSLNMAKE  = ms\nt.mak all
!elseif "$(PLATFORM)"=="ia64"
!message Using 'ia64' platform for OpenSSL...
SSLCONFIG = VC-WIN64I no-asm
SSLSETUP  = ms\do_win64i.bat
SSLNMAKE  = ms\nt.mak all
!else
!message Assuming 'x86' platform for OpenSSL...
SSLCONFIG = VC-WIN32 no-asm
SSLSETUP  = ms\do_ms.bat
SSLNMAKE  = ms\nt.mak all
!endif
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
!endif

# zlib options
ZINCDIR   = $(B)\compat\zlib
ZLIBDIR   = $(B)\compat\zlib
ZLIB      = zlib.lib

INCL      = /I. /I$(SRCDIR) /I$B\win\include

!ifndef FOSSIL_ENABLE_MINIZ
INCL      = $(INCL) /I$(ZINCDIR)
!endif

!ifdef FOSSIL_ENABLE_SSL
INCL      = $(INCL) /I$(SSLINCDIR)
!endif

!ifdef FOSSIL_ENABLE_TCL
INCL      = $(INCL) /I$(TCLINCDIR)
63
64
65
66
67
68
69
70
71










72
73
74
75
76
77
78
79
80
81
82
83










84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101

102
103
104
105
106
107

108
109
110




111
112
113
114
115
116
117
!else
CFLAGS    = $(CFLAGS) /MT /O2
!endif

BCC       = $(CC) $(CFLAGS)
TCC       = $(CC) /c $(CFLAGS) $(MSCDEF) $(INCL)
RCC       = rc /D_WIN32 /D_MSC_VER $(MSCDEF) $(INCL)
LIBS      = $(ZLIB) ws2_32.lib advapi32.lib
LIBDIR    = /LIBPATH:$(ZLIBDIR)











!ifdef FOSSIL_ENABLE_JSON
TCC       = $(TCC) /DFOSSIL_ENABLE_JSON=1
RCC       = $(RCC) /DFOSSIL_ENABLE_JSON=1
!endif

!ifdef FOSSIL_ENABLE_SSL
TCC       = $(TCC) /DFOSSIL_ENABLE_SSL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_SSL=1
LIBS      = $(LIBS) $(SSLLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
!endif











!ifdef FOSSIL_ENABLE_TCL
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC       = $(TCC) /DUSE_TCL_STUBS=1
RCC       = $(RCC) /DUSE_TCL_STUBS=1
!endif


SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 /DSQLITE_THREADSAFE=0 \
                 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 /DSQLITE_OMIT_DEPRECATED \
                 /DSQLITE_ENABLE_EXPLAIN_COMMENTS


SHELL_OPTIONS = /Dmain=sqlite3_shell \
                /DSQLITE_OMIT_LOAD_EXTENSION=1 \
                /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                /Daccess=file_access \

                /Dgetenv=fossil_getenv \
                /Dfopen=fossil_fopen





SRC   = add_.c \
        allrepo_.c \
        attach_.c \
        bag_.c \
        bisect_.c \
        blob_.c \
        branch_.c \







|
|
>
>
>
>
>
>
>
>
>
>












>
>
>
>
>
>
>
>
>
>












>
|




|
>






>



>
>
>
>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
!else
CFLAGS    = $(CFLAGS) /MT /O2
!endif

BCC       = $(CC) $(CFLAGS)
TCC       = $(CC) /c $(CFLAGS) $(MSCDEF) $(INCL)
RCC       = rc /D_WIN32 /D_MSC_VER $(MSCDEF) $(INCL)
LIBS      = ws2_32.lib advapi32.lib
LIBDIR    =

!ifndef FOSSIL_ENABLE_MINIZ
LIBS      = $(LIBS) $(ZLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(ZLIBDIR)
!endif

!ifdef FOSSIL_ENABLE_MINIZ
TCC       = $(TCC) /DFOSSIL_ENABLE_MINIZ=1
RCC       = $(RCC) /DFOSSIL_ENABLE_MINIZ=1
!endif

!ifdef FOSSIL_ENABLE_JSON
TCC       = $(TCC) /DFOSSIL_ENABLE_JSON=1
RCC       = $(RCC) /DFOSSIL_ENABLE_JSON=1
!endif

!ifdef FOSSIL_ENABLE_SSL
TCC       = $(TCC) /DFOSSIL_ENABLE_SSL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_SSL=1
LIBS      = $(LIBS) $(SSLLIB)
LIBDIR    = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
!endif

!ifdef FOSSIL_ENABLE_TH1_DOCS
TCC       = $(TCC) /DFOSSIL_ENABLE_TH1_DOCS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TH1_DOCS=1
!endif

!ifdef FOSSIL_ENABLE_TH1_HOOKS
TCC       = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
!endif

!ifdef FOSSIL_ENABLE_TCL
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC       = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC       = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC       = $(TCC) /DUSE_TCL_STUBS=1
RCC       = $(RCC) /DUSE_TCL_STUBS=1
!endif

SQLITE_OPTIONS = /DNDEBUG=1 \
                 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
                 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
                 /DSQLITE_THREADSAFE=0 \
                 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
                 /DSQLITE_OMIT_DEPRECATED \
                 /DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                 /DSQLITE_WIN32_NO_ANSI

SHELL_OPTIONS = /Dmain=sqlite3_shell \
                /DSQLITE_OMIT_LOAD_EXTENSION=1 \
                /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
                /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
                /Daccess=file_access \
                /Dsystem=fossil_system \
                /Dgetenv=fossil_getenv \
                /Dfopen=fossil_fopen

MINIZ_OPTIONS = /DMINIZ_NO_STDIO \
                /DMINIZ_NO_TIME \
                /DMINIZ_NO_ARCHIVE_APIS

SRC   = add_.c \
        allrepo_.c \
        attach_.c \
        bag_.c \
        bisect_.c \
        blob_.c \
        branch_.c \
134
135
136
137
138
139
140

141
142
143
144
145
146
147
        diffcmd_.c \
        doc_.c \
        encode_.c \
        event_.c \
        export_.c \
        file_.c \
        finfo_.c \

        glob_.c \
        graph_.c \
        gzip_.c \
        http_.c \
        http_socket_.c \
        http_ssl_.c \
        http_transport_.c \







>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
        diffcmd_.c \
        doc_.c \
        encode_.c \
        event_.c \
        export_.c \
        file_.c \
        finfo_.c \
        fusefs_.c \
        glob_.c \
        graph_.c \
        gzip_.c \
        http_.c \
        http_socket_.c \
        http_ssl_.c \
        http_transport_.c \
246
247
248
249
250
251
252

253
254
255
256
257
258
259
        $(OX)\diffcmd$O \
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\file$O \
        $(OX)\finfo$O \

        $(OX)\glob$O \
        $(OX)\graph$O \
        $(OX)\gzip$O \
        $(OX)\http$O \
        $(OX)\http_socket$O \
        $(OX)\http_ssl$O \
        $(OX)\http_transport$O \







>







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
        $(OX)\diffcmd$O \
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\file$O \
        $(OX)\finfo$O \
        $(OX)\fusefs$O \
        $(OX)\glob$O \
        $(OX)\graph$O \
        $(OX)\gzip$O \
        $(OX)\http$O \
        $(OX)\http_socket$O \
        $(OX)\http_ssl$O \
        $(OX)\http_transport$O \
331
332
333
334
335
336
337



338
339
340
341
342

343
344
345
346
347
348
349





















350
351
352
353
354
355
356
357
358
        $(OX)\wikiformat$O \
        $(OX)\winfile$O \
        $(OX)\winhttp$O \
        $(OX)\wysiwyg$O \
        $(OX)\xfer$O \
        $(OX)\xfersetup$O \
        $(OX)\zip$O \



        $(OX)\fossil.res


APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)


all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd






















$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
	cd $(OX) 
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc
	echo $(OX)\add.obj > $@
	echo $(OX)\allrepo.obj >> $@
	echo $(OX)\attach.obj >> $@
	echo $(OX)\bag.obj >> $@







>
>
>



|
|
>





|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
        $(OX)\wikiformat$O \
        $(OX)\winfile$O \
        $(OX)\winhttp$O \
        $(OX)\wysiwyg$O \
        $(OX)\xfer$O \
        $(OX)\xfersetup$O \
        $(OX)\zip$O \
!ifdef FOSSIL_ENABLE_MINIZ
        $(OX)\miniz$O \
!endif
        $(OX)\fossil.res


APPNAME    = $(OX)\fossil$(E)
PDBNAME    = $(OX)\fossil$(P)
APPTARGETS =

all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd

!ifdef FOSSIL_ENABLE_SSL
openssl:
	@echo Building OpenSSL from "$(SSLDIR)"...
!if "$(PERLDIR)" != ""
	@set PATH=$(PERLDIR);$(PATH)
!endif
	@pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
	@pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
	@pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
!endif

!ifndef FOSSIL_ENABLE_MINIZ
APPTARGETS = $(APPTARGETS) zlib
!endif

!ifdef FOSSIL_ENABLE_SSL
!ifdef FOSSIL_BUILD_SSL
APPTARGETS = $(APPTARGETS) openssl
!endif
!endif

$(APPNAME) : $(APPTARGETS) translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
	cd $(OX)
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc
	echo $(OX)\add.obj > $@
	echo $(OX)\allrepo.obj >> $@
	echo $(OX)\attach.obj >> $@
	echo $(OX)\bag.obj >> $@
379
380
381
382
383
384
385

386
387
388
389
390
391
392
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\file.obj >> $@
	echo $(OX)\finfo.obj >> $@

	echo $(OX)\glob.obj >> $@
	echo $(OX)\graph.obj >> $@
	echo $(OX)\gzip.obj >> $@
	echo $(OX)\http.obj >> $@
	echo $(OX)\http_socket.obj >> $@
	echo $(OX)\http_ssl.obj >> $@
	echo $(OX)\http_transport.obj >> $@







>







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\file.obj >> $@
	echo $(OX)\finfo.obj >> $@
	echo $(OX)\fusefs.obj >> $@
	echo $(OX)\glob.obj >> $@
	echo $(OX)\graph.obj >> $@
	echo $(OX)\gzip.obj >> $@
	echo $(OX)\http.obj >> $@
	echo $(OX)\http_socket.obj >> $@
	echo $(OX)\http_ssl.obj >> $@
	echo $(OX)\http_transport.obj >> $@
464
465
466
467
468
469
470



471
472
473
474
475
476
477
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winfile.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\wysiwyg.obj >> $@
	echo $(OX)\xfer.obj >> $@
	echo $(OX)\xfersetup.obj >> $@
	echo $(OX)\zip.obj >> $@



	echo $(LIBS) >> $@

$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**







>
>
>







566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winfile.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\wysiwyg.obj >> $@
	echo $(OX)\xfer.obj >> $@
	echo $(OX)\xfersetup.obj >> $@
	echo $(OX)\zip.obj >> $@
!ifdef FOSSIL_ENABLE_MINIZ
	echo $(OX)\miniz.obj >> $@
!endif
	echo $(LIBS) >> $@

$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**
496
497
498
499
500
501
502



503
504
505
506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
524
525

526

527

528

529
530
531
532
533
534
535

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**




VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 
	$** > $@

clean:
	-del $(OX)\*.obj
	-del *.obj
	-del *_.c
	-del *.h

	-del *.map
	-del *.res
	-del headers
	-del linkopts
	-del vc*.pdb

realclean: clean
	-del $(APPNAME)
	-del $(PDBNAME)
	-del translate$E

	-del mkindex$E

	-del makeheaders$E

	-del mkversion$E


$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h







>
>
>





|







>










>

>

>

>







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**

$(OX)\miniz$O : $(SRCDIR)\miniz.c
	$(TCC) /Fo$@ -c $(MINIZ_OPTIONS) $(SRCDIR)\miniz.c

VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC)
	$** > $@

clean:
	-del $(OX)\*.obj
	-del *.obj
	-del *_.c
	-del *.h
	-del *.ilk
	-del *.map
	-del *.res
	-del headers
	-del linkopts
	-del vc*.pdb

realclean: clean
	-del $(APPNAME)
	-del $(PDBNAME)
	-del translate$E
	-del translate$P
	-del mkindex$E
	-del mkindex$P
	-del makeheaders$E
	-del makeheaders$P
	-del mkversion$E
	-del mkversion$P

$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
718
719
720
721
722
723
724






725
726
727
728
729
730
731
	translate$E $** > $@

$(OX)\finfo$O : finfo_.c finfo.h
	$(TCC) /Fo$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	translate$E $** > $@







$(OX)\glob$O : glob_.c glob.h
	$(TCC) /Fo$@ -c glob_.c

glob_.c : $(SRCDIR)\glob.c
	translate$E $** > $@








>
>
>
>
>
>







831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
	translate$E $** > $@

$(OX)\finfo$O : finfo_.c finfo.h
	$(TCC) /Fo$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	translate$E $** > $@

$(OX)\fusefs$O : fusefs_.c fusefs.h
	$(TCC) /Fo$@ -c fusefs_.c

fusefs_.c : $(SRCDIR)\fusefs.c
	translate$E $** > $@

$(OX)\glob$O : glob_.c glob.h
	$(TCC) /Fo$@ -c glob_.c

glob_.c : $(SRCDIR)\glob.c
	translate$E $** > $@

1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
			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 \







>







1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
			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 \
			fusefs_.c:fusefs.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 \
Changes to win/buildmsvc.bat.
11
12
13
14
15
16
17























18
19
20
21
22
23
24
SETLOCAL

REM SET __ECHO=ECHO
REM SET __ECHO2=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)
























REM
REM Visual Studio ????
REM
IF DEFINED VSVARS32 IF EXIST "%VSVARS32%" (
  %_AECHO% Build environment batch file manually overridden to "%VSVARS32%"...
  GOTO skip_detectVisualStudio







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
SETLOCAL

REM SET __ECHO=ECHO
REM SET __ECHO2=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

REM
REM NOTE: Setup local environment variables that point to the root directory
REM       of the Fossil source checkout and to the directory containing this
REM       build tool.
REM
SET ROOT=%~dp0\..
SET ROOT=%ROOT:\\=\%

%_VECHO% Root = '%ROOT%'

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

REM
REM Visual C++ ????
REM
IF DEFINED VCINSTALLDIR IF EXIST "%VCINSTALLDIR%" (
  %_AECHO% Build environment appears to be setup.
  GOTO skip_setupVisualStudio
)

REM
REM Visual Studio ????
REM
IF DEFINED VSVARS32 IF EXIST "%VSVARS32%" (
  %_AECHO% Build environment batch file manually overridden to "%VSVARS32%"...
  GOTO skip_detectVisualStudio
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156








157
158
159
160
161
162
163
REM       selected Visual Studio common tools path.  This is not strictly
REM       necessary; however, it makes reading the output easier.
REM
SET VSVARS32=%VSVARS32:\\=\%

%_VECHO% VsVars32 = '%VSVARS32%'

REM
REM NOTE: Setup local environment variables that point to the root directory
REM       of the Fossil source checkout and to the directory containing this
REM       build tool.
REM
SET ROOT=%~dp0\..
SET ROOT=%ROOT:\\=\%

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Root = '%ROOT%'
%_VECHO% Tools = '%TOOLS%'

REM
REM NOTE: After this point, a clean ERRORLEVEL is required; therefore, make
REM       sure it is reset now.
REM
CALL :fn_ResetErrorLevel

REM
REM NOTE: Attempt to call the selected batch file to setup the environment
REM       variables for building with MSVC.
REM
%__ECHO3% CALL "%VSVARS32%"

IF ERRORLEVEL 1 (
  ECHO Visual Studio build environment batch file "%VSVARS32%" failed.
  GOTO errors
)









REM
REM NOTE: Attempt to create the build output directory, if necessary.
REM
IF NOT EXIST "%ROOT%\msvcbld" (
  %__ECHO% MKDIR "%ROOT%\msvcbld"

  IF ERRORLEVEL 1 (







<
<
<
<
<
<
<
<
<
<
<
<
<
<

















>
>
>
>
>
>
>
>







142
143
144
145
146
147
148














149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
REM       selected Visual Studio common tools path.  This is not strictly
REM       necessary; however, it makes reading the output easier.
REM
SET VSVARS32=%VSVARS32:\\=\%

%_VECHO% VsVars32 = '%VSVARS32%'















REM
REM NOTE: After this point, a clean ERRORLEVEL is required; therefore, make
REM       sure it is reset now.
REM
CALL :fn_ResetErrorLevel

REM
REM NOTE: Attempt to call the selected batch file to setup the environment
REM       variables for building with MSVC.
REM
%__ECHO3% CALL "%VSVARS32%"

IF ERRORLEVEL 1 (
  ECHO Visual Studio build environment batch file "%VSVARS32%" failed.
  GOTO errors
)

REM
REM NOTE: After this point, the environment should already be setup for
REM       building with MSVC.
REM
:skip_setupVisualStudio

%_VECHO% VcInstallDir = '%VCINSTALLDIR%'

REM
REM NOTE: Attempt to create the build output directory, if necessary.
REM
IF NOT EXIST "%ROOT%\msvcbld" (
  %__ECHO% MKDIR "%ROOT%\msvcbld"

  IF ERRORLEVEL 1 (
Changes to win/fossil.rc.
28
29
30
31
32
33
34









35

36
37
38
39
40
41
42
#  define VS_FF_NONE            0x00000000L
#endif /* !defined(VS_FF_NONE) */

#include "VERSION.h"
#define _RC_COMPILE_
#include "config.h"
#include "sqlite3.h"









#include "zlib.h"


#if defined(FOSSIL_ENABLE_SSL)
#include "openssl/opensslv.h"
#endif /* defined(FOSSIL_ENABLE_SSL) */

#if defined(FOSSIL_ENABLE_TCL)
#include "tcl.h"







>
>
>
>
>
>
>
>
>

>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#  define VS_FF_NONE            0x00000000L
#endif /* !defined(VS_FF_NONE) */

#include "VERSION.h"
#define _RC_COMPILE_
#include "config.h"
#include "sqlite3.h"

#if defined(FOSSIL_ENABLE_MINIZ)
#if defined(__MINGW32__)
#include "minizver.h"
#else
#define MINIZ_HEADER_FILE_ONLY
#include "miniz.c"
#endif /* defined(__MINGW32__) */
#else
#include "zlib.h"
#endif /* defined(FOSSIL_ENABLE_MINIZ) */

#if defined(FOSSIL_ENABLE_SSL)
#include "openssl/opensslv.h"
#endif /* defined(FOSSIL_ENABLE_SSL) */

#if defined(FOSSIL_ENABLE_TCL)
#include "tcl.h"
90
91
92
93
94
95
96



97

98
99
100
101
102
103
104
105










106
107
108
109
110
111
112
      VALUE "ProductVersion", "Fossil " RELEASE_VERSION " " MANIFEST_VERSION " " MANIFEST_DATE " UTC\0"
      VALUE "FileVersion", "Fossil " RELEASE_VERSION " " MANIFEST_VERSION " " MANIFEST_DATE " UTC\0"
      VALUE "InternalName", "fossil\0"
      VALUE "LegalCopyright", "Copyright © " MANIFEST_YEAR " by D. Richard Hipp.  All rights reserved.\0"
      VALUE "OriginalFilename", "fossil.exe\0"
      VALUE "CompilerName", COMPILER_NAME "\0"
      VALUE "SQLiteVersion", "SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\0"



      VALUE "ZlibVersion", "zlib " ZLIB_VERSION "\0"

#if defined(BROKEN_MINGW_CMDLINE)
      VALUE "CommandLineIsUnicode", "No\0"
#else
      VALUE "CommandLineIsUnicode", "Yes\0"
#endif /* defined(BROKEN_MINGW_CMDLINE) */
#if defined(FOSSIL_ENABLE_SSL)
      VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
#endif /* defined(FOSSIL_ENABLE_SSL) */










#if defined(FOSSIL_ENABLE_TCL)
      VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
#if defined(USE_TCL_STUBS)
      VALUE "UseTclStubsEnabled", "Yes\0"
#else
      VALUE "UseTclStubsEnabled", "No\0"
#endif /* defined(USE_TCL_STUBS) */







>
>
>

>








>
>
>
>
>
>
>
>
>
>







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
      VALUE "ProductVersion", "Fossil " RELEASE_VERSION " " MANIFEST_VERSION " " MANIFEST_DATE " UTC\0"
      VALUE "FileVersion", "Fossil " RELEASE_VERSION " " MANIFEST_VERSION " " MANIFEST_DATE " UTC\0"
      VALUE "InternalName", "fossil\0"
      VALUE "LegalCopyright", "Copyright © " MANIFEST_YEAR " by D. Richard Hipp.  All rights reserved.\0"
      VALUE "OriginalFilename", "fossil.exe\0"
      VALUE "CompilerName", COMPILER_NAME "\0"
      VALUE "SQLiteVersion", "SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\0"
#if defined(FOSSIL_ENABLE_MINIZ)
      VALUE "MinizVersion", "miniz " MZ_VERSION "\0"
#else
      VALUE "ZlibVersion", "zlib " ZLIB_VERSION "\0"
#endif /* defined(FOSSIL_ENABLE_MINIZ) */
#if defined(BROKEN_MINGW_CMDLINE)
      VALUE "CommandLineIsUnicode", "No\0"
#else
      VALUE "CommandLineIsUnicode", "Yes\0"
#endif /* defined(BROKEN_MINGW_CMDLINE) */
#if defined(FOSSIL_ENABLE_SSL)
      VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
#endif /* defined(FOSSIL_ENABLE_SSL) */
#if defined(FOSSIL_ENABLE_TH1_DOCS)
      VALUE "Th1Docs", "Yes\0"
#else
      VALUE "Th1Docs", "No\0"
#endif /* defined(FOSSIL_ENABLE_TH1_DOCS) */
#if defined(FOSSIL_ENABLE_TH1_HOOKS)
      VALUE "Th1Hooks", "Yes\0"
#else
      VALUE "Th1Hooks", "No\0"
#endif /* defined(FOSSIL_ENABLE_TH1_HOOKS) */
#if defined(FOSSIL_ENABLE_TCL)
      VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
#if defined(USE_TCL_STUBS)
      VALUE "UseTclStubsEnabled", "Yes\0"
#else
      VALUE "UseTclStubsEnabled", "No\0"
#endif /* defined(USE_TCL_STUBS) */
135
136
137
138
139
140
141
142
143
144
145
146
147
148

/*
 * This embedded manifest is needed for Windows 8.1.
 */

#ifndef RT_MANIFEST
#define RT_MANIFEST     24
#endif

#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#endif

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "fossil.exe.manifest"







|



|


159
160
161
162
163
164
165
166
167
168
169
170
171
172

/*
 * This embedded manifest is needed for Windows 8.1.
 */

#ifndef RT_MANIFEST
#define RT_MANIFEST     24
#endif /* RT_MANIFEST */

#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#endif /* CREATEPROCESS_MANIFEST_RESOURCE_ID */

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "fossil.exe.manifest"
Changes to win/include/dirent.h.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94





95
96
97
98
99
100
101
102
103
104
105
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 *
 * Version 1.13, Dec 12 2012, Toni Ronkko
 * Use traditional 8+3 file name if the name cannot be represented in the
 * default ANSI code page.  Now compiles again with MSVC 6.0.  Thanks to
 * Konstantin Khomoutov for testing.
 *
 * Version 1.12.1, Oct 1 2012, Toni Ronkko
 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
 * capital W) in order to maintain compatibility with MingW.
 *
 * Version 1.12, Sep 30 2012, Toni Ronkko
 * Define PATH_MAX and NAME_MAX.  Added wide-character variants _wDIR, 
 * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
 * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
 *
 * Do not include windows.h.  This allows dirent.h to be integrated more
 * easily into programs using winsock.  Thanks to Fernando Azaldegui.
 *
 * Version 1.11, Mar 15, 2011, Toni Ronkko
 * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
 *
 * Version 1.10, Aug 11, 2010, Toni Ronkko
 * Added d_type and d_namlen fields to dirent structure.  The former is
 * especially useful for determining whether directory entry represents a
 * file or a directory.  For more information, see
 * http://www.delorie.com/gnu/docs/glibc/libc_270.html
 *
 * Improved conformance to the standards.  For example, errno is now set
 * properly on failure and assert() is never used.  Thanks to Peter Brockam
 * for suggestions.
 *
 * Fixed a bug in rewinddir(): when using relative directory names, change
 * of working directory no longer causes rewinddir() to fail.
 *
 * Version 1.9, Dec 15, 2009, John Cunningham
 * Added rewinddir member function
 *
 * Version 1.8, Jan 18, 2008, Toni Ronkko
 * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
 * between multi-byte and unicode representations.  This makes the
 * code simpler and also allows the code to be compiled under MingW.  Thanks
 * to Azriel Fasten for the suggestion.
 *
 * Mar 4, 2007, Toni Ronkko
 * Bug fix: due to the strncpy_s() function this file only compiled in
 * Visual Studio 2005.  Using the new string functions only when the
 * compiler version allows.
 *
 * Nov  2, 2006, Toni Ronkko
 * Major update: removed support for Watcom C, MS-DOS and Turbo C to
 * simplify the file, updated the code to compile cleanly on Visual
 * Studio 2005 with both unicode and multi-byte character strings,
 * removed rewinddir() as it had a bug.
 *
 * Aug 20, 2006, Toni Ronkko
 * Removed all remarks about MSVC 1.0, which is antiqued now.  Simplified
 * comments by removing SGML tags.
 *
 * May 14 2002, Toni Ronkko
 * Embedded the function definitions directly to the header so that no
 * source modules need to be included in the Visual Studio project.  Removed
 * all the dependencies to other projects so that this header file can be
 * used independently.
 *
 * May 28 1998, Toni Ronkko
 * First version.
 *****************************************************************************/
#ifndef DIRENT_H
#define DIRENT_H






#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IX86)
#   define _X86_
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_AMD64)
#define _AMD64_
#endif

#include <stdio.h>
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



>
>
>
>
>
|


|







18
19
20
21
22
23
24











































25



26



















27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *











































 * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $



 */



















#ifndef DIRENT_H
#define DIRENT_H

/*
 * Define architecture flags so we don't need to include windows.h.
 * Avoiding windows.h makes it simpler to use windows sockets in conjunction
 * with dirent.h.
 */
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
#   define _X86_
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
#define _AMD64_
#endif

#include <stdio.h>
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#define	S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
#define	S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)

/* Return the exact length of d_namlen without zero terminator */
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)

/* Return number of bytes needed to store d_namlen */
#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)


#ifdef __cplusplus
extern "C" {
#endif


/* Wide-character version */
struct _wdirent {
    long d_ino;                                 /* Always zero */
    unsigned short d_reclen;                    /* Structure size */
    size_t d_namlen;                            /* Length of name without \0 */
    int d_type;                                 /* File type */
    wchar_t d_name[PATH_MAX + 1];               /* File name */
};
typedef struct _wdirent _wdirent;

struct _WDIR {
    struct _wdirent ent;                        /* Current directory entry */
    WIN32_FIND_DATAW data;                      /* Private file data */
    int cached;                                 /* True if data is valid */







|













|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#define	S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
#define	S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)

/* Return the exact length of d_namlen without zero terminator */
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)

/* Return number of bytes needed to store d_namlen */
#define _D_ALLOC_NAMLEN(p) (PATH_MAX)


#ifdef __cplusplus
extern "C" {
#endif


/* Wide-character version */
struct _wdirent {
    long d_ino;                                 /* Always zero */
    unsigned short d_reclen;                    /* Structure size */
    size_t d_namlen;                            /* Length of name without \0 */
    int d_type;                                 /* File type */
    wchar_t d_name[PATH_MAX];                   /* File name */
};
typedef struct _wdirent _wdirent;

struct _WDIR {
    struct _wdirent ent;                        /* Current directory entry */
    WIN32_FIND_DATAW data;                      /* Private file data */
    int cached;                                 /* True if data is valid */
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

/* Multi-byte character versions */
struct dirent {
    long d_ino;                                 /* Always zero */
    unsigned short d_reclen;                    /* Structure size */
    size_t d_namlen;                            /* Length of name without \0 */
    int d_type;                                 /* File type */
    char d_name[PATH_MAX + 1];                  /* File name */
};
typedef struct dirent dirent;

struct DIR {
    struct dirent ent;
    struct _WDIR *wdirp;
};







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

/* Multi-byte character versions */
struct dirent {
    long d_ino;                                 /* Always zero */
    unsigned short d_reclen;                    /* Structure size */
    size_t d_namlen;                            /* Length of name without \0 */
    int d_type;                                 /* File type */
    char d_name[PATH_MAX];                      /* File name */
};
typedef struct dirent dirent;

struct DIR {
    struct dirent ent;
    struct _WDIR *wdirp;
};
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

        /* 
         * Copy file name as wide-character string.  If the file name is too
         * long to fit in to the destination buffer, then truncate file name
         * to PATH_MAX characters and zero-terminate the buffer.
         */
        n = 0;
        while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {
            entp->d_name[n] = datap->cFileName[n];
            n++;
        }
        dirp->ent.d_name[n] = 0;

        /* Length of file name excluding zero terminator */
        entp->d_namlen = n;







|







361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

        /* 
         * Copy file name as wide-character string.  If the file name is too
         * long to fit in to the destination buffer, then truncate file name
         * to PATH_MAX characters and zero-terminate the buffer.
         */
        n = 0;
        while (n + 1 < PATH_MAX  &&  datap->cFileName[n] != 0) {
            entp->d_name[n] = datap->cFileName[n];
            n++;
        }
        dirp->ent.d_name[n] = 0;

        /* Length of file name excluding zero terminator */
        entp->d_namlen = n;
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
        dirent_set_errno (ENOENT);
        return NULL;
    }

    /* Allocate memory for DIR structure */
    dirp = (DIR*) malloc (sizeof (struct DIR));
    if (dirp) {
        wchar_t wname[PATH_MAX + 1];
        size_t n;

        /* Convert directory name to wide-character string */
        error = dirent_mbstowcs_s(
            &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
        if (!error) {

            /* Open directory stream using wide-character name */
            dirp->wdirp = _wopendir (wname);
            if (dirp->wdirp) {
                /* Directory stream opened */
                error = 0;







|



|
<







530
531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
        dirent_set_errno (ENOENT);
        return NULL;
    }

    /* Allocate memory for DIR structure */
    dirp = (DIR*) malloc (sizeof (struct DIR));
    if (dirp) {
        wchar_t wname[PATH_MAX];
        size_t n;

        /* Convert directory name to wide-character string */
        error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);

        if (!error) {

            /* Open directory stream using wide-character name */
            dirp->wdirp = _wopendir (wname);
            if (dirp->wdirp) {
                /* Directory stream opened */
                error = 0;
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
    datap = dirent_next (dirp->wdirp);
    if (datap) {
        size_t n;
        int error;

        /* Attempt to convert file name to multi-byte string */
        error = dirent_wcstombs_s(
            &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);

        /* 
         * If the file name cannot be represented by a multi-byte string,
         * then attempt to use old 8+3 file name.  This allows traditional
         * Unix-code to access some file names despite of unicode
         * characters, although file names may seem unfamiliar to the user.
         *
         * Be ware that the code below cannot come up with a short file
         * name unless the file system provides one.  At least
         * VirtualBox shared folders fail to do this.
         */
        if (error  &&  datap->cAlternateFileName[0] != '\0') {
            error = dirent_wcstombs_s(
                &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
                sizeof (datap->cAlternateFileName) / 
                    sizeof (datap->cAlternateFileName[0]));
        }

        if (!error) {
            DWORD attr;

            /* Initialize directory entry for return */
            entp = &dirp->ent;







|













|
|
<







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
    datap = dirent_next (dirp->wdirp);
    if (datap) {
        size_t n;
        int error;

        /* Attempt to convert file name to multi-byte string */
        error = dirent_wcstombs_s(
            &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);

        /* 
         * If the file name cannot be represented by a multi-byte string,
         * then attempt to use old 8+3 file name.  This allows traditional
         * Unix-code to access some file names despite of unicode
         * characters, although file names may seem unfamiliar to the user.
         *
         * Be ware that the code below cannot come up with a short file
         * name unless the file system provides one.  At least
         * VirtualBox shared folders fail to do this.
         */
        if (error  &&  datap->cAlternateFileName[0] != '\0') {
            error = dirent_wcstombs_s(
                &n, dirp->ent.d_name, PATH_MAX, 
                datap->cAlternateFileName, PATH_MAX);

        }

        if (!error) {
            DWORD attr;

            /* Initialize directory entry for return */
            entp = &dirp->ent;
785
786
787
788
789
790
791
792
793
794
795
796
797



798
799
800
801
802
803
804
    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);

#else

    /* Older Visual Studio or non-Microsoft compiler */
    size_t n;

    /* Convert to wide-character string */
    n = mbstowcs (wcstr, mbstr, count);
    if (n < sizeInWords) {

        /* Zero-terminate output buffer */
        if (wcstr) {



            wcstr[n] = 0;
        }

        /* Length of resuting multi-byte string WITH zero terminator */
        if (pReturnValue) {
            *pReturnValue = n + 1;
        }







|
|
|


|
>
>
>







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);

#else

    /* Older Visual Studio or non-Microsoft compiler */
    size_t n;

    /* Convert to wide-character string (or count characters) */
    n = mbstowcs (wcstr, mbstr, sizeInWords);
    if (!wcstr  ||  n < count) {

        /* Zero-terminate output buffer */
        if (wcstr  &&  sizeInWords) {
            if (n >= sizeInWords) {
                n = sizeInWords - 1;
            }
            wcstr[n] = 0;
        }

        /* Length of resuting multi-byte string WITH zero terminator */
        if (pReturnValue) {
            *pReturnValue = n + 1;
        }
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847



848
849
850
851
852
853
854
}

/* Convert wide-character string to multi-byte string */
static int
dirent_wcstombs_s(
    size_t *pReturnValue,
    char *mbstr,
    size_t sizeInBytes,
    const wchar_t *wcstr,
    size_t count)
{
    int error;

#if defined(_MSC_VER)  &&  _MSC_VER >= 1400

    /* Microsoft Visual Studio 2005 or later */
    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);

#else

    /* Older Visual Studio or non-Microsoft compiler */
    size_t n;

    /* Convert to multi-byte string */
    n = wcstombs (mbstr, wcstr, count);
    if (n < sizeInBytes) {

        /* Zero-terminate output buffer */
        if (mbstr) {



            mbstr[n] = '\0';
        }

        /* Lenght of resulting multi-bytes string WITH zero-terminator */
        if (pReturnValue) {
            *pReturnValue = n + 1;
        }







|















|
|
|


|
>
>
>







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
}

/* Convert wide-character string to multi-byte string */
static int
dirent_wcstombs_s(
    size_t *pReturnValue,
    char *mbstr,
    size_t sizeInBytes, /* max size of mbstr */
    const wchar_t *wcstr,
    size_t count)
{
    int error;

#if defined(_MSC_VER)  &&  _MSC_VER >= 1400

    /* Microsoft Visual Studio 2005 or later */
    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);

#else

    /* Older Visual Studio or non-Microsoft compiler */
    size_t n;

    /* Convert to multi-byte string (or count the number of bytes needed) */
    n = wcstombs (mbstr, wcstr, sizeInBytes);
    if (!mbstr  ||  n < count) {

        /* Zero-terminate output buffer */
        if (mbstr  &&  sizeInBytes) {
            if (n >= sizeInBytes) {
                n = sizeInBytes - 1;
            }
            mbstr[n] = '\0';
        }

        /* Lenght of resulting multi-bytes string WITH zero-terminator */
        if (pReturnValue) {
            *pReturnValue = n + 1;
        }
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
}

/* Set errno variable */
static void
dirent_set_errno(
    int error)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400

    /* Microsoft Visual Studio 2005 and later */
    _set_errno (error);

#else

    /* Non-Microsoft compiler or older Microsoft compiler */







|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
}

/* Set errno variable */
static void
dirent_set_errno(
    int error)
{
#if defined(_MSC_VER)  &&  _MSC_VER >= 1400

    /* Microsoft Visual Studio 2005 and later */
    _set_errno (error);

#else

    /* Non-Microsoft compiler or older Microsoft compiler */
Changes to www/branching.wiki.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
But as sequential numbers are easier to read, we will substitute them for
the 40-character SHA1 hashes in this document.

The arrows in figure 1 show the evolution of a project.  The initial
check-in is 1.  Check-in 2 is derived from 1.  In other words, check-in 2
was created by making edits to check-in 1 and then committing those edits.
We say that 2 is a <i>child</i> of 1
and that 1 is a <i>parent</i> of 2.  
Check-in 3 is derived from check-in 2, making
3 a child of 2.  We say that 3 is a <i>descendant</i> of both 1 and 2 and that 1
and 2 are both <i>ancestors</i> of 3.  

<a name="dag"></a>
<h2>DAGs</h2>

The graph of check-ins is a 
[http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph]
commonly shortened to <i>DAG</i>.  Check-in 1 is the <i>root</i> of the DAG
since it has no ancestors.  Check-in 4 is a <i>leaf</i> of the DAG since
it has no descendants.  (We will give a more precise definition later of
"leaf.")

Alas, reality often interferes with the simple linear development of a
project.  Suppose two programmers make independent modifications to check-in 2.
After both changes are committed, the check-in graph looks like figure 2:

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch02.gif" width=210 height=140><br>
Figure 2
</td></tr></table></center>

The graph in figure 2 has two leaves: check-ins 3 and 4.  Check-in 2 has
two children, check-ins 3 and 4.  We call this state a <i>fork</i>.

Fossil tries to prevent forks. Suppose two programmers named Alice and 
Bob are each editing check-in 2 separately. Alice finishes her edits 
first and commits her changes, resulting in check-in 3. Later, when Bob 
attempts to commit his changes, fossil verifies that check-in 2 is still 
a leaf. Fossil sees that check-in 3 has occurred and aborts Bob's commit 
attempt with a message "would fork." This allows Bob to do a "fossil 
update" which pulls in Alice's changes, merging them into his own 
changes. After merging, Bob commits check-in 4 as a child of check-in 3. 
The result is a linear graph as shown in figure 1. This is how CVS 
works. This is also how fossil works in [./concepts.wiki#workflow | 
"autosync"] mode. 

But perhaps Bob is off-network when he does his commit, so he
has no way of knowing that Alice has already committed her changes.
Or, it could be that Bob has turned off "autosync" mode in Fossil.  Or,
maybe Bob just doesn't want to merge in Alice's changes before he has
saved his own, so he forces the commit to occur using the "--force" option
to the fossil <b>commit</b> command.  For any of these reasons, two commits against
check-in 2 have occurred and now the DAG has two leaves.

So which version of the project is the "latest" in the sense of having
the most features and the most bug fixes?  When there is more than
one leaf in the graph, you don't really know.  So we like to have
graphs with a single leaf.

To resolve this situation, Alice can use the fossil <b>merge</b> command
to merge in Bob's changes in her local copy of check-in 3.  Then she
can commit the results as check-in 5.  This results in a DAG as shown
in figure 3.

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch03.gif" width=282 height=152><br>
Figure 3
</td></tr></table></center>

Check-in 5 is a child of check-in 3 because it was created by editing
check-in 3.  But check-in 5 also inherits the changes from check-in 4 by
virtue of the merge.  So we say that check-in 5 is a <i>merge child</i>
of check-in 4 and that it is a <i>direct child</i> of check-in 3.  
The graph is now back to a single leaf (check-in 5).

We have already seen that if fossil is in autosync mode then Bob would
have been warned about the potential fork the first time he tried to
commit check-in 4.  If Bob had updated his local check-out to merge in
Alice's check-in 3 changes, then committed, then the fork would have
never occurred.  The resulting graph would have been linear, as shown







|


|




|



















|
|
|
|
|
|
|
|
|
|
|





|
|
|




















|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
But as sequential numbers are easier to read, we will substitute them for
the 40-character SHA1 hashes in this document.

The arrows in figure 1 show the evolution of a project.  The initial
check-in is 1.  Check-in 2 is derived from 1.  In other words, check-in 2
was created by making edits to check-in 1 and then committing those edits.
We say that 2 is a <i>child</i> of 1
and that 1 is a <i>parent</i> of 2.
Check-in 3 is derived from check-in 2, making
3 a child of 2.  We say that 3 is a <i>descendant</i> of both 1 and 2 and that 1
and 2 are both <i>ancestors</i> of 3.

<a name="dag"></a>
<h2>DAGs</h2>

The graph of check-ins is a
[http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph]
commonly shortened to <i>DAG</i>.  Check-in 1 is the <i>root</i> of the DAG
since it has no ancestors.  Check-in 4 is a <i>leaf</i> of the DAG since
it has no descendants.  (We will give a more precise definition later of
"leaf.")

Alas, reality often interferes with the simple linear development of a
project.  Suppose two programmers make independent modifications to check-in 2.
After both changes are committed, the check-in graph looks like figure 2:

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch02.gif" width=210 height=140><br>
Figure 2
</td></tr></table></center>

The graph in figure 2 has two leaves: check-ins 3 and 4.  Check-in 2 has
two children, check-ins 3 and 4.  We call this state a <i>fork</i>.

Fossil tries to prevent forks. Suppose two programmers named Alice and
Bob are each editing check-in 2 separately. Alice finishes her edits
first and commits her changes, resulting in check-in 3. Later, when Bob
attempts to commit his changes, fossil verifies that check-in 2 is still
a leaf. Fossil sees that check-in 3 has occurred and aborts Bob's commit
attempt with a message "would fork." This allows Bob to do a "fossil
update" which pulls in Alice's changes, merging them into his own
changes. After merging, Bob commits check-in 4 as a child of check-in 3.
The result is a linear graph as shown in figure 1. This is how CVS
works. This is also how fossil works in [./concepts.wiki#workflow |
"autosync"] mode.

But perhaps Bob is off-network when he does his commit, so he
has no way of knowing that Alice has already committed her changes.
Or, it could be that Bob has turned off "autosync" mode in Fossil.  Or,
maybe Bob just doesn't want to merge in Alice's changes before he has
saved his own, so he forces the commit to occur using the "--allow-fork"
option to the fossil <b>commit</b> command.  For any of these reasons,
two commits against check-in 2 have occurred and now the DAG has two leaves.

So which version of the project is the "latest" in the sense of having
the most features and the most bug fixes?  When there is more than
one leaf in the graph, you don't really know.  So we like to have
graphs with a single leaf.

To resolve this situation, Alice can use the fossil <b>merge</b> command
to merge in Bob's changes in her local copy of check-in 3.  Then she
can commit the results as check-in 5.  This results in a DAG as shown
in figure 3.

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch03.gif" width=282 height=152><br>
Figure 3
</td></tr></table></center>

Check-in 5 is a child of check-in 3 because it was created by editing
check-in 3.  But check-in 5 also inherits the changes from check-in 4 by
virtue of the merge.  So we say that check-in 5 is a <i>merge child</i>
of check-in 4 and that it is a <i>direct child</i> of check-in 3.
The graph is now back to a single leaf (check-in 5).

We have already seen that if fossil is in autosync mode then Bob would
have been warned about the potential fork the first time he tried to
commit check-in 4.  If Bob had updated his local check-out to merge in
Alice's check-in 3 changes, then committed, then the fork would have
never occurred.  The resulting graph would have been linear, as shown
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
taken in figure 1 is better because it is much easier to visualize a
linear line of development and because the merging happens automatically
instead of as a separate manual step.  We will not take sides in that
debate.  We will simply point out that fossil enables you to do it either way.

<h2>Forking Versus Branching</h2>

Having more than one leaf in the check-in DAG is called a "fork." This 
is usually undesirable and either avoided entirely,
as in figure 1, or else quickly resolved as shown in figure 3.
But sometimes, one does want to have multiple leaves.  For example, a project
might have one leaf that is the latest version of the project under
development and another leaf that is the latest version that has been
tested.
When multiple leaves are desirable, we call this <i>branching</i>
instead of <i>forking</i>.
Figure 4 shows an example of a project where there are two branches, one
for development work and another for testing.

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch04.gif" width=426 height=123><br>
Figure 4
</td></tr></table></center>

The hypothetical scenario of figure 4 is this:  The project starts and
progresses to a point where (at check-in 2) 
it is ready to enter testing for its first release.
In a real project, of course, there might be hundreds or thousands of
check-ins before a project reaches this point, but for simplicity of
presentation we will say that the project is ready after check-in 2.
The project then splits into two branches that are used by separate
teams.  The testing team, using the blue branch, finds and fixes a few
bugs.  This is shown by check-ins 6 and 9.  Meanwhile the development
team, working on the top uncolored branch, 
is busy adding features for the second
release.  Of course, the development team would like to take advantage of
the bug fixes implemented by the testing team.  So periodically, the
changes in the test branch are merged into the dev branch.  This is
shown by the dashed merge arrows between check-ins 6 and 7 and between
check-ins 9 and 10.








|


















|







|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
taken in figure 1 is better because it is much easier to visualize a
linear line of development and because the merging happens automatically
instead of as a separate manual step.  We will not take sides in that
debate.  We will simply point out that fossil enables you to do it either way.

<h2>Forking Versus Branching</h2>

Having more than one leaf in the check-in DAG is called a "fork." This
is usually undesirable and either avoided entirely,
as in figure 1, or else quickly resolved as shown in figure 3.
But sometimes, one does want to have multiple leaves.  For example, a project
might have one leaf that is the latest version of the project under
development and another leaf that is the latest version that has been
tested.
When multiple leaves are desirable, we call this <i>branching</i>
instead of <i>forking</i>.
Figure 4 shows an example of a project where there are two branches, one
for development work and another for testing.

<center><table border=1 cellpadding=10 hspace=10 vspace=10>
<tr><td align="center">
<img src="branch04.gif" width=426 height=123><br>
Figure 4
</td></tr></table></center>

The hypothetical scenario of figure 4 is this:  The project starts and
progresses to a point where (at check-in 2)
it is ready to enter testing for its first release.
In a real project, of course, there might be hundreds or thousands of
check-ins before a project reaches this point, but for simplicity of
presentation we will say that the project is ready after check-in 2.
The project then splits into two branches that are used by separate
teams.  The testing team, using the blue branch, finds and fixes a few
bugs.  This is shown by check-ins 6 and 9.  Meanwhile the development
team, working on the top uncolored branch,
is busy adding features for the second
release.  Of course, the development team would like to take advantage of
the bug fixes implemented by the testing team.  So periodically, the
changes in the test branch are merged into the dev branch.  This is
shown by the dashed merge arrows between check-ins 6 and 7 and between
check-ins 9 and 10.

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
Figure 5
</td></tr></table></center>

A <i>tag</i> is a name that is attached to a check-in.  A
<i>property</i> is a name/value pair.  Internally, fossil implements
tags as properties with a NULL value.  So, tags and properties really
are much the same thing, and henceforth we will use the word "tag"
to mean either a tag or a property. 

A tag can be a one-time tag, a propagating tag or a cancellation tag. 
A one-time tag only applies to the check-in to which it is attached.  A
propagating tag applies to the check-in to which it is attached and also
to all direct descendants of that check-in.  A <i>direct descendant</i>
is a descendant through direct children.  Tags propagation does not
cross merges.  Tag propagation also stops as soon
as it encounters another check-in with the same tag.  A cancellation tag
is attached to a single check-in in order to either override a one-time
tag that was previously placed on that same check-in, or to block
tag propagation from an ancestor.

Every repository is created with a single empty check-in that has two
propagating tags.  In figure 5, that initial empty check-in is check-in 1.
The <b>branch</b> tag tells (by its value) 
what branch the check-in is a member of.
The default branch is called "trunk."  All tags that begin with "<b>sym-</b>"
are symbolic name tags.  When a symbolic name tag is attached to a
check-in, that allows you to refer to that check-in by its symbolic
name rather than by its 40-character SHA1 hash name.  When a symbolic name
tag propagates (as does the <b>sym-trunk</b> tag) then referring to that
name is the same as referring to the most recent check-in with that name.
Thus the two tags on check-in 1 cause all descendants to be in the







|

|










<
|
|
|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
200
201
Figure 5
</td></tr></table></center>

A <i>tag</i> is a name that is attached to a check-in.  A
<i>property</i> is a name/value pair.  Internally, fossil implements
tags as properties with a NULL value.  So, tags and properties really
are much the same thing, and henceforth we will use the word "tag"
to mean either a tag or a property.

A tag can be a one-time tag, a propagating tag or a cancellation tag.
A one-time tag only applies to the check-in to which it is attached.  A
propagating tag applies to the check-in to which it is attached and also
to all direct descendants of that check-in.  A <i>direct descendant</i>
is a descendant through direct children.  Tags propagation does not
cross merges.  Tag propagation also stops as soon
as it encounters another check-in with the same tag.  A cancellation tag
is attached to a single check-in in order to either override a one-time
tag that was previously placed on that same check-in, or to block
tag propagation from an ancestor.


The initial checkin of every repository has two propagating tags.  In
figure 5, that initial check-in is check-in 1.  The <b>branch</b> tag
tells (by its value)  what branch the check-in is a member of.
The default branch is called "trunk."  All tags that begin with "<b>sym-</b>"
are symbolic name tags.  When a symbolic name tag is attached to a
check-in, that allows you to refer to that check-in by its symbolic
name rather than by its 40-character SHA1 hash name.  When a symbolic name
tag propagates (as does the <b>sym-trunk</b> tag) then referring to that
name is the same as referring to the most recent check-in with that name.
Thus the two tags on check-in 1 cause all descendants to be in the
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
so that it cannot reach check-ins 6 or 9.  This causes check-ins 4, 6, and
9 to be in the "test" branch and all others to be in the "trunk" branch.

Check-in 4 also has a <b>sym-test</b> tag, which gives the symbolic name
"test" to check-ins 4, 6, and 9.  Because tags do not propagate across
merges, check-ins 7, 8, and 10 do not inherit the <b>sym-test</b> tag and
are hence not known by the name "test."
To prevent the <b>sym-trunk</b> tag from propagating from check-in 1 
into check-ins 4, 6, and 9, there is a cancellation tag for 
<b>sym-trunk</b> on check-in 4.  The net effect is that
check-ins on the trunk go by the symbolic name of "trunk" and check-ins
on the test branch go by the symbolic name "test."

The <b>bgcolor=blue</b> tag on check-in 4 causes the background color
of timelines to be blue for check-in 4 and its direct descendants.

Figure 5 also shows two one-time tags on check-in 9.  (The diagram does
not make a graphical distinction between one-time and propagating tags.)
The <b>sym-release-1.0</b> tag means that check-in 9 can be referred to
using the more meaningful name "release-1.0."  The <b>closed</b> tag means
that check-in 9 is a "closed leaf."  A closed leaf is a leaf that should 
never have direct children.

<h2>Review Of Terminology</h2>

<blockquote><dl>
<dt><b>Branch</b></dt>
<dd><p>A branch is a set of check-ins with the same value for their







|
|











|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
so that it cannot reach check-ins 6 or 9.  This causes check-ins 4, 6, and
9 to be in the "test" branch and all others to be in the "trunk" branch.

Check-in 4 also has a <b>sym-test</b> tag, which gives the symbolic name
"test" to check-ins 4, 6, and 9.  Because tags do not propagate across
merges, check-ins 7, 8, and 10 do not inherit the <b>sym-test</b> tag and
are hence not known by the name "test."
To prevent the <b>sym-trunk</b> tag from propagating from check-in 1
into check-ins 4, 6, and 9, there is a cancellation tag for
<b>sym-trunk</b> on check-in 4.  The net effect is that
check-ins on the trunk go by the symbolic name of "trunk" and check-ins
on the test branch go by the symbolic name "test."

The <b>bgcolor=blue</b> tag on check-in 4 causes the background color
of timelines to be blue for check-in 4 and its direct descendants.

Figure 5 also shows two one-time tags on check-in 9.  (The diagram does
not make a graphical distinction between one-time and propagating tags.)
The <b>sym-release-1.0</b> tag means that check-in 9 can be referred to
using the more meaningful name "release-1.0."  The <b>closed</b> tag means
that check-in 9 is a "closed leaf."  A closed leaf is a leaf that should
never have direct children.

<h2>Review Of Terminology</h2>

<blockquote><dl>
<dt><b>Branch</b></dt>
<dd><p>A branch is a set of check-ins with the same value for their
Changes to www/build.wiki.
110
111
112
113
114
115
116
117
118
119
120
121














122
123
124
125
126
127
128

<li><p><i>MinGW/MinGW-w64</i> → Use the mingw makefile:
"<b>make -f win/Makefile.mingw</b>". On a Windows box you will
need either Cygwin or Msys as build environment. On Cygwin, Linux
or Darwin you may want to make minor edits to win/Makefile.mingw
to configure the cross-compile environment.

<li><p><i>MSVC</i> → Use the msc makefile.  First
change to the "win/" subdirectory ("<b>cd win</b>") then run
"<b>nmake /f Makefile.msc</b>".  Alternatively, the batch file
"<b>win\buildmsvc.bat</b>" may be used and it will attempt to
detect and use the latest installed version of MSVC.















<li><p><i>Cygwin</i> → The same as other unix-like systems. It is
recommended to configure using: "<b>configure --disable-internal-sqlite</b>",
making sure you have the "libsqlite3-devel" , "zlib-devel" and
"openssl-devel" packages installed first.
</ol>
</ol>







|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

<li><p><i>MinGW/MinGW-w64</i> → Use the mingw makefile:
"<b>make -f win/Makefile.mingw</b>". On a Windows box you will
need either Cygwin or Msys as build environment. On Cygwin, Linux
or Darwin you may want to make minor edits to win/Makefile.mingw
to configure the cross-compile environment.

<li><p><i>MSVC</i> → Use the MSVC makefile.  First
change to the "win/" subdirectory ("<b>cd win</b>") then run
"<b>nmake /f Makefile.msc</b>".<br><br>Alternatively, the batch
file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to
detect and use the latest installed version of MSVC.<br><br>To enable
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
first <a href="https://www.openssl.org/source/">download the official
source code for OpenSSL</a> and extract it to an appropriately named
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
[/tree?ci=trunk&name=compat | compat] directory (e.g.
"<b>compat/openssl-1.0.1i</b>"), then make sure that some recent
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
and finally run one of the following commands:
<blockquote><pre>
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
</pre></blockquote>
<blockquote><pre>
buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
</pre></blockquote>

<li><p><i>Cygwin</i> → The same as other unix-like systems. It is
recommended to configure using: "<b>configure --disable-internal-sqlite</b>",
making sure you have the "libsqlite3-devel" , "zlib-devel" and
"openssl-devel" packages installed first.
</ol>
</ol>
Changes to www/changes.wiki.
1
2




























3
4
5
6
7
8
9
10
<title>Change Log</title>





























<h2>Changes For Version 1.29 (as yet unreleased)</h2>
  *  Add the ability to display content, diffs and annotations for UTF16
     text files in the web interface.
  *  Add the "SaveAs..." and "Invert" buttons
     to the graphical diff display that results
     from using the --tk option with the [/help/diff | fossil diff] command.
  *  The [/reports] page now requires Read ("o") permissions. The "byweek"
     report now properly propagates the selected year through the event type


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<title>Change Log</title>

<h2>Changes For Version 1.30 (as yet unreleased)</h2>
  *  Add setting to control the number of times autosync will be tried before
     returning an error.
  *  Add the [/help/fusefs|fossil fusefs DIRECTORY] command that mounts a
     Fuse Filesystem at the given DIRECTORY and populates it with read-only
     copies of all historical check-ins. This only works on systems that
     support FuseFS.
  *  Added a compile-time option (--with-miniz) to build using miniz instead
     of zlib.  Disabled by default.
  *  Several fixes to the TH1 expression parser.
  *  Support customization of commands and webpages, including the ability to
     add new ones, via the "TH1 hooks" feature.  Disabled by default. Enabled
     via a compile-time option.
  *  Add the <nowiki>[checkout], [render], [styleHeader], [styleFooter],
     [trace], [getParameter], [setParameter], [artifact], and
     [globalState]</nowiki> commands to TH1, primarily for use by TH1 hooks.
  *  Bring in the latest version of autosetup from upstream.
  *  When committing a (non-binary) file which contains bytes forming an
     invalid UTF-8 stream, fossil now adds the possibility to convert it
     to a valid UTF-8 stream ('c') if you like.
  *  Let [/help?cmd=new|fossil new] no longer create an initial empty commit
     by default. The first commit after checking out an empty repository will
     become the initial commit. (NOT PLANNED FOR 1.30, BUT DONE TO EXPOSE
     [/help?cmd=new|fossil new --empty] TO MORE FIELD TESTING BEFORE
     MAKING ANY DECISION ON IT!)
  *  Added a line-number toggle option to the [/help?cmd=/info|/info]
     and [/help?cmd=/artifact|/artifact] pages.

<h2>Changes For Version 1.29 (2014-06-12)</h2>
  *  Add the ability to display content, diffs and annotations for UTF16
     text files in the web interface.
  *  Add the "SaveAs..." and "Invert" buttons
     to the graphical diff display that results
     from using the --tk option with the [/help/diff | fossil diff] command.
  *  The [/reports] page now requires Read ("o") permissions. The "byweek"
     report now properly propagates the selected year through the event type
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  *  Add an Admin/Access setting to change the number of octets of the
     IP address that are saved in login cookies - allowing this setting
     to be changed to zero
  *  Promote the "test-md5sum" command to "md5sum".
  *  Added the "whatis" command.
  *  Stop showing the server-code in status outputs - it is no longer used
     for anything.
  *  Added a compile-time option (--with-tcl) to build in the full
     TCL interpreter to augment TH1.
  *  Merged the JSON branch into trunk.  Disabled by default.  Enabled
     by a compile-time option.  Probably it will be enabled by default
     in some future release.
  *  Update to use SQLite version 3.7.9 plus the alignment fix for Sparc.
     align

<h2>Changes For Version 1.20 (2011-10-21)</h2>







|
|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  *  Add an Admin/Access setting to change the number of octets of the
     IP address that are saved in login cookies - allowing this setting
     to be changed to zero
  *  Promote the "test-md5sum" command to "md5sum".
  *  Added the "whatis" command.
  *  Stop showing the server-code in status outputs - it is no longer used
     for anything.
  *  Added a compile-time option (--with-tcl) to build in full Tcl scripting
     support via integration with TH1.
  *  Merged the JSON branch into trunk.  Disabled by default.  Enabled
     by a compile-time option.  Probably it will be enabled by default
     in some future release.
  *  Update to use SQLite version 3.7.9 plus the alignment fix for Sparc.
     align

<h2>Changes For Version 1.20 (2011-10-21)</h2>
Changes to www/fileformat.wiki.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
The local state is not versioned and is not synchronized
with the global state.
The local state is not composed of artifacts and is not intended to be enduring.
This document is concerned with global state only.  Local state is only
mentioned here in order to distinguish it from global state.

Each artifact in the repository is named by its SHA1 hash.
No prefixes or meta information is added to a artifact before
its hash is computed.  The name of a artifact in the repository
is exactly the same SHA1 hash that is computed by sha1sum 
on the file as it exists in your source tree.</p>

Some artifacts have a particular format which gives them special
meaning to fossil.  Fossil recognizes:

<ul>







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
The local state is not versioned and is not synchronized
with the global state.
The local state is not composed of artifacts and is not intended to be enduring.
This document is concerned with global state only.  Local state is only
mentioned here in order to distinguish it from global state.

Each artifact in the repository is named by its SHA1 hash.
No prefixes or meta information is added to an artifact before
its hash is computed.  The name of an artifact in the repository
is exactly the same SHA1 hash that is computed by sha1sum 
on the file as it exists in your source tree.</p>

Some artifacts have a particular format which gives them special
meaning to fossil.  Fossil recognizes:

<ul>
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

A sample manifest from Fossil itself can be seen
[/artifact/28987096ac | here].

<a name="cluster"></a>
<h2>2.0 Clusters</h2>

A cluster is a artifact that declares the existence of other artifacts.
Clusters are used during repository synchronization to help 
reduce network traffic.  As such, clusters are an optimization and
may be removed from a repository without loss or damage to the
underlying project code.

Clusters follow a syntax that is very similar to manifests.
A Cluster is a line-oriented text file.  Newline characters







|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

A sample manifest from Fossil itself can be seen
[/artifact/28987096ac | here].

<a name="cluster"></a>
<h2>2.0 Clusters</h2>

A cluster is an artifact that declares the existence of other artifacts.
Clusters are used during repository synchronization to help 
reduce network traffic.  As such, clusters are an optimization and
may be removed from a repository without loss or damage to the
underlying project code.

Clusters follow a syntax that is very similar to manifests.
A Cluster is a line-oriented text file.  Newline characters
Changes to www/fossil-v-git.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<title>Fossil Versus Git</title>

<h2>1.0 Don't Stress!</h2>

If you start out using one DVCS and later decide you like the other better,
it is [./inout.wiki | easy to change].

But it also helps to be informed about the differences between 
[http://git-scm.com | Git] and Fossil.  See the table below for
a high-level summary and the text that follows for more details.

Keep in mind that you are reading this on a Fossil website, 
so the information here
might be biased in favor of Fossil.  Ask around with people who have
used both Fossil and Git for other opinions.

<h2>2.0 Executive Summary:</h2>

<blockquote><center><table border=1 cellpadding=5>







|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<title>Fossil Versus Git</title>

<h2>1.0 Don't Stress!</h2>

If you start out using one DVCS and later decide you like the other better,
it is [./inout.wiki | easy to change].

But it also helps to be informed about the differences between
[http://git-scm.com | Git] and Fossil.  See the table below for
a high-level summary and the text that follows for more details.

Keep in mind that you are reading this on a Fossil website,
so the information here
might be biased in favor of Fossil.  Ask around with people who have
used both Fossil and Git for other opinions.

<h2>2.0 Executive Summary:</h2>

<blockquote><center><table border=1 cellpadding=5>
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"[https://github.com/ | github]-in-a-box".

<h3>3.2 Sharding versus Replicating</h3>

Git makes it easy for each repository in a project to hold a subset of
the branches for that project.  In fact, it is entirely possible and not
uncommon for no repository in the project to hold all the different code
versions for a project.  Instead the information is distributed.  
Individual developers have one or more private branches.  A hierarchy
of integrators merge changes from individual developers into collaborative
branches, until all the changes are merged together at the top-level master
branch.  And all of this can be accomplished without having to have all the
code in any one repository.  Developers or groups of developers can share
only those branches that they want to share and keep other branchs of the
project private.  This is analogous to sharding an a distributed database.

Fossil allows private branches, but its default mode is to share everything.
And so in a Fossil project, all respositories tend to contain all of the
content at all times.  This is analogous to replication in a
distributed database.

The Git model works best for large projects, like the
Linux kernel for which Git was designed.
Linus Torvalds does not need or want to see a thousand
different branches, one for each contributor.  Git allows intermediary
"gate-keepers" to merge changes from multiple lower-level developers
into a single branch and only present Linus with a handful of branches
at a time.  Git encourages a programming model where each developer
works in his or her own branch and then merges changes up the hierarchy
until they reach the master branch.

Fossil is designed for smaller and non-hierarchical teams where all
developers are operating directly on the master branch, or at most
a small number of well defined branches.  
The [./concepts.wiki#workflow | autosync] mode of Fossil makes it easy
for multiple developers to work on a single branch and maintain
linear development on that branch and avoid needless forking
and merging.

<h3>3.3 Branches</h3>

Git (and especially GitHub) encourages a workflow where each developer 
has his or her own branch or branches.  Developers then send "pull requests"
to have their changes be merged into "official" branches by integrators.
For example, the Linux kernel team has a hierarchy of integrators with
Linus Torvalds at the root.  Individual developers each have their own
private branches of the source tree into which they make their own changes.
They then encourage first-tier integrators to pull those changes.  The
first-tier integrators merge together changes from multiple contributors
then try to get second-tier integrators to pull their branches.  The
changes merge up the hierarchy until (hopefully) they are pulled into 
"Linus's branch", at which time they become part of the "official" Linux.

In Git, each branch is "owned" by the person who creates it and works
on it.  The owner might pull changes from others, but the owner is always
in control of the branch.  Branches are developer-centric.

Fossil, on the other hand, encourages a workflow where branches are 
associated with features or releases, not individual developers.
All developers share all branches in common, and two
or more developers can and often do intersperse commits onto the same branch.
Branches do not belong to individuals.  All branches are read/write
accessible to all developers at all times.  There is no need
for integrators to merge together changes from various independent
developers.  Instead, all of the developers work together cooperatively
and the changes stay integrated naturally.

So to a first approximation, branches in Git are developer-centric whereas
branches in Fossil are feature-centric.

The Git approach scales much better for large projects like the Linux
kernel with thousands of contributors who in many cases don't even know
each others names.  The integrators serve a gatekeeper role to help keep
undesirable code out of the official Linux source tree.  On the other hand, 
not many projects are as big or as loosely organized as the Linux kernel.
Most projects have a small team of developers who all know each other
well and trust each other, and who enjoy working together collaboratively
without the overhead and hierarchy of integrators.

One consequence of the "everybody-sees-everything" focus of Fossil is that
branch names are global and are part of the distributed and synchronized







|









|















|







|








|






|















|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"[https://github.com/ | github]-in-a-box".

<h3>3.2 Sharding versus Replicating</h3>

Git makes it easy for each repository in a project to hold a subset of
the branches for that project.  In fact, it is entirely possible and not
uncommon for no repository in the project to hold all the different code
versions for a project.  Instead the information is distributed.
Individual developers have one or more private branches.  A hierarchy
of integrators merge changes from individual developers into collaborative
branches, until all the changes are merged together at the top-level master
branch.  And all of this can be accomplished without having to have all the
code in any one repository.  Developers or groups of developers can share
only those branches that they want to share and keep other branchs of the
project private.  This is analogous to sharding an a distributed database.

Fossil allows private branches, but its default mode is to share everything.
And so in a Fossil project, all repositories tend to contain all of the
content at all times.  This is analogous to replication in a
distributed database.

The Git model works best for large projects, like the
Linux kernel for which Git was designed.
Linus Torvalds does not need or want to see a thousand
different branches, one for each contributor.  Git allows intermediary
"gate-keepers" to merge changes from multiple lower-level developers
into a single branch and only present Linus with a handful of branches
at a time.  Git encourages a programming model where each developer
works in his or her own branch and then merges changes up the hierarchy
until they reach the master branch.

Fossil is designed for smaller and non-hierarchical teams where all
developers are operating directly on the master branch, or at most
a small number of well defined branches.
The [./concepts.wiki#workflow | autosync] mode of Fossil makes it easy
for multiple developers to work on a single branch and maintain
linear development on that branch and avoid needless forking
and merging.

<h3>3.3 Branches</h3>

Git (and especially GitHub) encourages a workflow where each developer
has his or her own branch or branches.  Developers then send "pull requests"
to have their changes be merged into "official" branches by integrators.
For example, the Linux kernel team has a hierarchy of integrators with
Linus Torvalds at the root.  Individual developers each have their own
private branches of the source tree into which they make their own changes.
They then encourage first-tier integrators to pull those changes.  The
first-tier integrators merge together changes from multiple contributors
then try to get second-tier integrators to pull their branches.  The
changes merge up the hierarchy until (hopefully) they are pulled into
"Linus's branch", at which time they become part of the "official" Linux.

In Git, each branch is "owned" by the person who creates it and works
on it.  The owner might pull changes from others, but the owner is always
in control of the branch.  Branches are developer-centric.

Fossil, on the other hand, encourages a workflow where branches are
associated with features or releases, not individual developers.
All developers share all branches in common, and two
or more developers can and often do intersperse commits onto the same branch.
Branches do not belong to individuals.  All branches are read/write
accessible to all developers at all times.  There is no need
for integrators to merge together changes from various independent
developers.  Instead, all of the developers work together cooperatively
and the changes stay integrated naturally.

So to a first approximation, branches in Git are developer-centric whereas
branches in Fossil are feature-centric.

The Git approach scales much better for large projects like the Linux
kernel with thousands of contributors who in many cases don't even know
each others names.  The integrators serve a gatekeeper role to help keep
undesirable code out of the official Linux source tree.  On the other hand,
not many projects are as big or as loosely organized as the Linux kernel.
Most projects have a small team of developers who all know each other
well and trust each other, and who enjoy working together collaboratively
without the overhead and hierarchy of integrators.

One consequence of the "everybody-sees-everything" focus of Fossil is that
branch names are global and are part of the distributed and synchronized
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
development.  One should not have to stop and think about how to operate
the VCS.  Of course, no VCS is ideal.  Every VCS requires the developer
to think about version control to some extent.  But one wants to minimize
the thinking about version control.

Git requires the developer to maintain a more complex mental model than
most other DVCSes.  Git takes longer to learn.  And you have to spend
more time thinking about what you are doing with Git.  

Fossil strives for simplicity.  Fossil wants to be easy to learn and to
require little thinking about how to operating it.  
[./quotes.wiki | Reports from the field]
indicate that Fossil is mostly successful at this effort.

<h3>3.5 Web Interface</h3>

Git has a web interface, but it requires a fair amount of setup and an
external web server.  Fossil comes with a fully functional







|


|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
development.  One should not have to stop and think about how to operate
the VCS.  Of course, no VCS is ideal.  Every VCS requires the developer
to think about version control to some extent.  But one wants to minimize
the thinking about version control.

Git requires the developer to maintain a more complex mental model than
most other DVCSes.  Git takes longer to learn.  And you have to spend
more time thinking about what you are doing with Git.

Fossil strives for simplicity.  Fossil wants to be easy to learn and to
require little thinking about how to operating it.
[./quotes.wiki | Reports from the field]
indicate that Fossil is mostly successful at this effort.

<h3>3.5 Web Interface</h3>

Git has a web interface, but it requires a fair amount of setup and an
external web server.  Fossil comes with a fully functional
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

<h3>3.8 Audit Trail</h3>

Git features the "rebase" command which can be used to change the
sequence of check-ins in the repository.  Rebase can be used to "clean up"
a complex sequence of check-ins to make their intent easier for others
to understand.  This is important if you view the history of a project
as part of the documentation for the project.  

Fossil takes an opposing view.  Fossil views history as sacrosanct and
stubornly refuses to change it.
Fossil allows mistakes to be corrected (for example, check-in comments
can be revised, and check-ins can be moved onto new branches even after
the check-in has occurred) but the correction is an addition to the respository
and the original actions are preserved and displayed alongside
the corrections, thus preserving an historically accurate audit trail.
This is analogous to an accountant marking through an incorrect
entry in a ledger and writing in a correction beside it, rather than
erasing and incorrect entry.

To put it another way, Git remembers what you should have done whereas
Fossil remembers what you actually did.

The lack of a "rebase" command and the inability to rewrite history
is considered a feature of Fossil, not an omission or bug.

<h3>3.9 License</h3>

Both Git and Fossil are open-source.  Git is under 
[http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is
under the 
[http://en.wikipedia.org/wiki/BSD_licenses | two-clause BSD license].
The difference should not be of a concern to most users.  However,
some corporate lawyers have objections to using GPL products and
are more comfortable with a BSD-style license.







|





|














|

|




193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

<h3>3.8 Audit Trail</h3>

Git features the "rebase" command which can be used to change the
sequence of check-ins in the repository.  Rebase can be used to "clean up"
a complex sequence of check-ins to make their intent easier for others
to understand.  This is important if you view the history of a project
as part of the documentation for the project.

Fossil takes an opposing view.  Fossil views history as sacrosanct and
stubornly refuses to change it.
Fossil allows mistakes to be corrected (for example, check-in comments
can be revised, and check-ins can be moved onto new branches even after
the check-in has occurred) but the correction is an addition to the repository
and the original actions are preserved and displayed alongside
the corrections, thus preserving an historically accurate audit trail.
This is analogous to an accountant marking through an incorrect
entry in a ledger and writing in a correction beside it, rather than
erasing and incorrect entry.

To put it another way, Git remembers what you should have done whereas
Fossil remembers what you actually did.

The lack of a "rebase" command and the inability to rewrite history
is considered a feature of Fossil, not an omission or bug.

<h3>3.9 License</h3>

Both Git and Fossil are open-source.  Git is under
[http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is
under the
[http://en.wikipedia.org/wiki/BSD_licenses | two-clause BSD license].
The difference should not be of a concern to most users.  However,
some corporate lawyers have objections to using GPL products and
are more comfortable with a BSD-style license.
Changes to www/makefile.wiki.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  6.  shell.c

The sqlite3.c and sqlite3.h source files are byte-for-byte copies of a
standard [http://www.sqlite.org/amalgamation.html | amalgamation].
The shell.c source file is code for the SQLite
[http://www.sqlite.org/sqlite.html | command-line shell] that is used
to help implement the [/help/sqlite3 | fossil sql] command.  The
shell.c source file has been modified slightly from the standard
shell.c file in the SQLite release.  Search for "Fossil Patch" in
the shell.c source file of Fossil to see the changes.

The TH1 script engine is implemented using files:

  7.  th.c
  8.  th.h

These two files are imports like the SQLite source files, 







|
|
<







40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
  6.  shell.c

The sqlite3.c and sqlite3.h source files are byte-for-byte copies of a
standard [http://www.sqlite.org/amalgamation.html | amalgamation].
The shell.c source file is code for the SQLite
[http://www.sqlite.org/sqlite.html | command-line shell] that is used
to help implement the [/help/sqlite3 | fossil sql] command.  The
shell.c source file is also a byte-for-byte copy of the
shell.c file from the SQLite release.


The TH1 script engine is implemented using files:

  7.  th.c
  8.  th.h

These two files are imports like the SQLite source files, 
Changes to www/password.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<title>Fossil Password Management</title>
<h1 align="center">Password Management</h1>

Fossil handles user authentication using passwords.
Passwords are unique to each repository.  Passwords are not part of the
persistent state of a project.  Passwords are not versioned and
are not transmitted from one repository to another during a sync.
Passwords are local configuration information that can (and usually does)
vary from one repository to the next within the same project.

Passwords are stored in the PW field of the USER table.
In older versions of Fossil (prior to 
[/timeline?c=2010-01-10+20:56:30 | 2010-01-11]) the password 
is stored as cleartext.  In newer versions of Fossil, the password
can be either cleartext or an SHA1 hash (written as a 40-character
lower-case hexadecimal number).  If the USER.PW field contains
a 40-character string, that string is assumed to be a SHA1 hash.
If the size of USER.PW is anything other than 40 characters, then
it is understood as a plain-text password.












|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<title>Fossil Password Management</title>
<h1 align="center">Password Management</h1>

Fossil handles user authentication using passwords.
Passwords are unique to each repository.  Passwords are not part of the
persistent state of a project.  Passwords are not versioned and
are not transmitted from one repository to another during a sync.
Passwords are local configuration information that can (and usually does)
vary from one repository to the next within the same project.

Passwords are stored in the PW field of the USER table.
In older versions of Fossil (prior to
[/timeline?c=2010-01-10T20:56:30 | 2010-01-11]) the password
is stored as cleartext.  In newer versions of Fossil, the password
can be either cleartext or an SHA1 hash (written as a 40-character
lower-case hexadecimal number).  If the USER.PW field contains
a 40-character string, that string is assumed to be a SHA1 hash.
If the size of USER.PW is anything other than 40 characters, then
it is understood as a plain-text password.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
When a user logs into Fossil using the web interface, the login name
and password are sent in the clear to the server.  The server then
hashes the password and compares it against the value stored in USER.PW.
If they match, the server sets a cookie on the client to record the
login.  This cookie contains a large amount of high-quality randomness
and is thus intractable to guess.  The value of the cookie and the IP
address of the client is stored in the USER.COOKIE and USER.IPADDR fields
of the USER table on the server.  
The USER.CEXPIRE field holds an expiration date
for the cookie, encoded as a julian day number.  On all subsequent
HTTP requests, the cookie value is matched against the USER table to 
enable access to the repository.

A login cookie will only work if the IP address matches.  This feature
is designed to make it more difficult for an attacker to sniff the cookie
and take over the connection.  A cookie-sniffing attack will only work
if the attacker is able to send and receive from the same IP address as
the original login.  However, we found that doing an exact IP match







|


|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
When a user logs into Fossil using the web interface, the login name
and password are sent in the clear to the server.  The server then
hashes the password and compares it against the value stored in USER.PW.
If they match, the server sets a cookie on the client to record the
login.  This cookie contains a large amount of high-quality randomness
and is thus intractable to guess.  The value of the cookie and the IP
address of the client is stored in the USER.COOKIE and USER.IPADDR fields
of the USER table on the server.
The USER.CEXPIRE field holds an expiration date
for the cookie, encoded as a julian day number.  On all subsequent
HTTP requests, the cookie value is matched against the USER table to
enable access to the repository.

A login cookie will only work if the IP address matches.  This feature
is designed to make it more difficult for an attacker to sniff the cookie
and take over the connection.  A cookie-sniffing attack will only work
if the attacker is able to send and receive from the same IP address as
the original login.  However, we found that doing an exact IP match
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
login attempt.  The plan moving forward is to compute the SHA1 hash of
the password on the client using javascript and then send only the hash
over the wire, but that plan has not yet been set in code.

<h2>Sync Protocol Authentication</h2>

A different authentication mechanism is used when one repository wants
to sync (or push or pull or clone) another respository.  When two
respositories are syncing, the one that initiates the transaction is
the client and the repository that responds is the server.  The client
works by sending HTTP requests to the server with a method of "xfer"
and a content-type of "application/x-fossil".  The content is Zlib-compressed
text consisting of "cards" of instructions.  The first card of this content
is a "login" card responsible for authentication.  The login card contains
the login name of the user and a "signature" where the signature is the
SHA1 hash of a nonce and the value of USER.PW.  The nonce is the







|
|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
login attempt.  The plan moving forward is to compute the SHA1 hash of
the password on the client using javascript and then send only the hash
over the wire, but that plan has not yet been set in code.

<h2>Sync Protocol Authentication</h2>

A different authentication mechanism is used when one repository wants
to sync (or push or pull or clone) another repository.  When two
repositories are syncing, the one that initiates the transaction is
the client and the repository that responds is the server.  The client
works by sending HTTP requests to the server with a method of "xfer"
and a content-type of "application/x-fossil".  The content is Zlib-compressed
text consisting of "cards" of instructions.  The first card of this content
is a "login" card responsible for authentication.  The login card contains
the login name of the user and a "signature" where the signature is the
SHA1 hash of a nonce and the value of USER.PW.  The nonce is the
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
The client normally gets the login and password from the "remote URL".

<blockquote><pre>
http://<font color="blue">login:password</font>@servername.org/path
</pre></blockquote>

For older clients, the password is used for the shared secret as stated
in the URL and with no encoding.  
For newer clients, the shared secret is derived from the password 
by transformed the password using the SHA1 hash encoding
described above.  However, if the first character of the password is
"*" (ASCII 0x2a) then the "*" is skipped and the rest of the password
is used directly as the share secret without the SHA1 encoding.

<blockquote><pre>
http://<font color="blue">login:*password</font>@servername.org/path
</pre></blockquote>

This *-before-the-password trick can be used by newer clients to
sync against a legacy server that does not understand the new SHA1
password encoding.







|
|












135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
The client normally gets the login and password from the "remote URL".

<blockquote><pre>
http://<font color="blue">login:password</font>@servername.org/path
</pre></blockquote>

For older clients, the password is used for the shared secret as stated
in the URL and with no encoding.
For newer clients, the shared secret is derived from the password
by transformed the password using the SHA1 hash encoding
described above.  However, if the first character of the password is
"*" (ASCII 0x2a) then the "*" is skipped and the rest of the password
is used directly as the share secret without the SHA1 encoding.

<blockquote><pre>
http://<font color="blue">login:*password</font>@servername.org/path
</pre></blockquote>

This *-before-the-password trick can be used by newer clients to
sync against a legacy server that does not understand the new SHA1
password encoding.
Changes to www/pop.wiki.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
collection of artifacts.  Each artifact is named by 
its SHA1 hash encoded in lowercase hexadecimal.
In many contexts, the name can be
abbreviated to a unique prefix.  A five- or six-character
prefix usually suffices to uniquely identify a file.</p></li>

<li><p>Because artifacts are named by their SHA1 hash, all artifacts
are immutable.  Any change to the content of a artifact also 
changes the hash that forms the artifacts name, thus
creating a new artifact.  Both the old original version of the
artifact and the new change are preserved under different names.</p></li>

<li><p>It is theoretically possible for two artifacts with different
content to share the same hash.  But finding two such
artifacts is so incredibly difficult and unlikely that we







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
collection of artifacts.  Each artifact is named by 
its SHA1 hash encoded in lowercase hexadecimal.
In many contexts, the name can be
abbreviated to a unique prefix.  A five- or six-character
prefix usually suffices to uniquely identify a file.</p></li>

<li><p>Because artifacts are named by their SHA1 hash, all artifacts
are immutable.  Any change to the content of an artifact also 
changes the hash that forms the artifacts name, thus
creating a new artifact.  Both the old original version of the
artifact and the new change are preserved under different names.</p></li>

<li><p>It is theoretically possible for two artifacts with different
content to share the same hash.  But finding two such
artifacts is so incredibly difficult and unlikely that we
Changes to www/quotes.wiki.
55
56
57
58
59
60
61













62
63
64
65
66
67
68
69
70
71
72
73
74










75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

<li>Klingon Code Warriors embrace Git; we enjoy arbitrary conflicts. Git is not for the weak and feeble. TODAY IS A GOOD DAY TO CODE.

<blockquote>
<i>teastain at [http://www.reddit.com/r/programming/comments/xpitj/10_things_i_hate_about_git/c5oj4fk]
</blockquote>















</ol>

<h2>On The Usability Of Fossil:</h2>

<ol>
<li value=7>
Fossil mesmerizes me with simplicity especially after I struggled to
get a bug-tracking system to work with mercurial.

<blockquote>
<i>rawjeev at [http://stackoverflow.com/questions/156322/what-do-people-think-of-the-fossil-dvcs]</i>
</blockquote>











<li>Fossil is awesome!!! I have never seen an app like that before, 
such simplicity and flexibility!!!

<blockquote>
<i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
</blockquote>


</ol>


<h2>On Git Versus Fossil</h2>

<ol>
<li value=9>
Just want to say thanks for fossil making my life easier.... 
Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.

<blockquote>
<i>Joshua Paine at [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg02736.html]</i>
</blockquote>








>
>
>
>
>
>
>
>
>
>
>
>
>






|






>
>
>
>
>
>
>
>
>
>















|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

<li>Klingon Code Warriors embrace Git; we enjoy arbitrary conflicts. Git is not for the weak and feeble. TODAY IS A GOOD DAY TO CODE.

<blockquote>
<i>teastain at [http://www.reddit.com/r/programming/comments/xpitj/10_things_i_hate_about_git/c5oj4fk]
</blockquote>

<li>&#91;G&#93;it is <i>designed</i> to forget things.

<blockquote>
<i>[http://www.cs.cmu.edu/~davide/howto/git_lose.html]
</blockquote>

<li>&#91;I&#93;n nearly 31 years of using a computer i have, in total, lost more data to git
(while following the instructions!!!) than any other single piece of software.

<blockquote>
<i>Stephen Beal on the [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg17181.html|Fossil mailing list]
   2014-09-01.</i>
</blockquote>

</ol>

<h2>On The Usability Of Fossil:</h2>

<ol>
<li value=9>
Fossil mesmerizes me with simplicity especially after I struggled to
get a bug-tracking system to work with mercurial.

<blockquote>
<i>rawjeev at [http://stackoverflow.com/questions/156322/what-do-people-think-of-the-fossil-dvcs]</i>
</blockquote>

<li>Fossil is the best thing to happen
to my development workflow this year, as I am pretty sure that using
Git has resulted in the premature death of too many of my brain cells.
I'm glad to be able to replace Git in every place that I possibly can
with Fossil.

<blockquote>
<i>Joe Prostko at [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg16716.html]
</blockquote>

<li>Fossil is awesome!!! I have never seen an app like that before, 
such simplicity and flexibility!!!

<blockquote>
<i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
</blockquote>


</ol>


<h2>On Git Versus Fossil</h2>

<ol>
<li value=12>
Just want to say thanks for fossil making my life easier.... 
Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.

<blockquote>
<i>Joshua Paine at [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg02736.html]</i>
</blockquote>

Changes to www/shunning.wiki.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using the normal "sync" mechanism.  An artifact can be
shunned from one repository but be allowed to exist in another.  The fact that
the shunning list does not propagate is a security feature.  If the
shunning list propagated then a malicious user (or
a bug in the fossil code) might introduce a shun record that would
propagate through all repositories in a network and permanently 
destroy vital information.  By refusing to propagate the shunning list,
Fossil insures that no remote user will ever be able to remove 
information from your personal repositories without your permission.

The shunning list does not propagate to a remote repository 
by the normal "sync" mechanism,
but it is still possible to copy shuns from one repository to another
using the "configuration" command:








|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using the normal "sync" mechanism.  An artifact can be
shunned from one repository but be allowed to exist in another.  The fact that
the shunning list does not propagate is a security feature.  If the
shunning list propagated then a malicious user (or
a bug in the fossil code) might introduce a shun record that would
propagate through all repositories in a network and permanently 
destroy vital information.  By refusing to propagate the shunning list,
Fossil ensures that no remote user will ever be able to remove 
information from your personal repositories without your permission.

The shunning list does not propagate to a remote repository 
by the normal "sync" mechanism,
but it is still possible to copy shuns from one repository to another
using the "configuration" command:

Changes to www/sync.wiki.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<p>A synchronization request between a client and server consists of
one or more HTTP requests as described in the previous section.  This
section details the "x-fossil" content type.</p>

<h3>3.1 Line-oriented Format</h3>

<p>The x-fossil content type consists of zero or more "cards".  Cards
are separate by the newline character ("\n").  Leading and trailing
whitespace on a card is ignored.  Blank cards are ignored.</p>

<p>Each card is divided into zero or more space separated tokens.
The first token on each card is the operator.  Subsequent tokens
are arguments.  The set of operators understood by servers is slightly
different from the operators understood by clients, though the two
are very similar.</p>







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<p>A synchronization request between a client and server consists of
one or more HTTP requests as described in the previous section.  This
section details the "x-fossil" content type.</p>

<h3>3.1 Line-oriented Format</h3>

<p>The x-fossil content type consists of zero or more "cards".  Cards
are separated by the newline character ("\n").  Leading and trailing
whitespace on a card is ignored.  Blank cards are ignored.</p>

<p>Each card is divided into zero or more space separated tokens.
The first token on each card is the operator.  Subsequent tokens
are arguments.  The set of operators understood by servers is slightly
different from the operators understood by clients, though the two
are very similar.</p>
157
158
159
160
161
162
163
164
165
166
167






168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

































199
200
201
202
203
204
205
206
207
208
209
210
checks out, then the client is granted all privileges of the
specified user.</p>

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>

<h3>3.3 File Cards</h3>

<p>Artifacts are transferred using "file" cards.  (The name "file"
card comes from the fact that most artifacts correspond to files.)






File cards come in two different formats depending
on whether the artifact is sent directly or as a delta from some
other artifact.</p>

<blockquote>
<b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
<b>file</b> <i>artifact-id delta-artifact-id size</i> <b>\n</b> <i>content</i>
</blockquote>

<p>File cards are different from all other cards in that they
followed by in-line "payload" data.  The content of the artifact
or the artifact delta consists of the first <i>size</i> bytes of the
x-fossil content that immediately follow the newline that
terminates the file card.  No other cards have this characteristic.
</p>

<p>The first argument of a file card is the ID of the artifact that
is being transferred.  The artifact ID is the lower-case hexadecimal
representation of the SHA1 hash of the artifact.
The last argument of the file card is the number of bytes of
payload that immediately follow the file card.  If the file
card has only two arguments, that means the payload is the
complete content of the artifact.  If the file card has three
arguments, then the payload is a delta and second argument is
the ID of another artifact that is the source of the delta.</p>

<p>File cards are sent in both directions: client to server and
server to client.  A delta might be sent before the source of
the delta, so both client and server should remember deltas
and be able to apply them when their source arrives.</p>


































<h3>3.4 Push and Pull Cards</h3>

<p>Among of the first cards in a client-to-server message are
the push and pull cards.  The push card tell the server that
the client is pushing content.  The pull card tell the server
that the client wants to pull content.  In the event of a sync,
both cards are sent.  The format is as follows:</p>

<blockquote>
<b>push</b> <i>servercode projectcode</i><br>
<b>pull</b> <i>servercode projectcode</i>
</blockquote>







|

|
|
>
>
>
>
>
>
|












|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|
|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
checks out, then the client is granted all privileges of the
specified user.</p>

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>

<h3>3.3 File and Compressed File Cards</h3>

<p>Artifacts are transferred using either "file" cards, or "cfile" cards.
(The name "file" card comes from the fact that most artifacts correspond to 
files, and "cfile" is just a compressed file.)
</p>

<h4>3.3.1 File Cards</h4>

<p>For sync protocols, artifacts are transferred using "file"
cards.  File cards come in two different formats depending
on whether the artifact is sent directly or as a delta from some
other artifact.</p>

<blockquote>
<b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
<b>file</b> <i>artifact-id delta-artifact-id size</i> <b>\n</b> <i>content</i>
</blockquote>

<p>File cards are different from all other cards in that they
followed by in-line "payload" data.  The content of the artifact
or the artifact delta consists of the first <i>size</i> bytes of the
x-fossil content that immediately follow the newline that
terminates the file card.  Only file and cfile cards have this characteristic.
</p>

<p>The first argument of a file card is the ID of the artifact that
is being transferred.  The artifact ID is the lower-case hexadecimal
representation of the SHA1 hash of the artifact.
The last argument of the file card is the number of bytes of
payload that immediately follow the file card.  If the file
card has only two arguments, that means the payload is the
complete content of the artifact.  If the file card has three
arguments, then the payload is a delta and second argument is
the ID of another artifact that is the source of the delta.</p>

<p>File cards are sent in both directions: client to server and
server to client.  A delta might be sent before the source of
the delta, so both client and server should remember deltas
and be able to apply them when their source arrives.</p>

<h4>3.3.2 Compressed File Cards</h4>

<p>A client that sends a clone protocol version "3" or greater will
receive artifacts as "cfile" cards while cloning.  This card was
introduced to improve the speed of the transfer of content by sending the
compressed artifact directly from the server database to the client.</p>

<p>Compressed File cards are similar to File cards, sharing the same
in-line "payload" data characteristics and also the same treatment of
direct content or delta content.  It comes in two different formats
depending on whether the artifact is sent directly or as a delta from
some other artifact.</p>

<blockquote>
<b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
<b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
</blockquote>

<p>The first argument of the cfile card is the ID of the artifact that
is being transferred.  The artifact ID is the lower-case hexadecimal
representation of the SHA1 hash of the artifact.  The second argument of
the cfile card is the original size in bytes of the artifact.  The last
argument of the cfile card is the number of compressed bytes of payload
that immediately follow the cfile card.  If the cfile card has only
three arguments, that means the payload is the complete content of the
artifact.  If the cfile card has four arguments, then the payload is a
delta and the second argument is the ID of another artifact that is the
source of the delta and the third argument is the original size of the
delta artifact.</p>

<p>Unlike file cards, cfile cards are only sent in one direction during a 
clone from server to client for clone protocol version "3" or greater.</p>

<h3>3.4 Push and Pull Cards</h3>

<p>Among the first cards in a client-to-server message are
the push and pull cards.  The push card tells the server that
the client is pushing content.  The pull card tells the server
that the client wants to pull content.  In the event of a sync,
both cards are sent.  The format is as follows:</p>

<blockquote>
<b>push</b> <i>servercode projectcode</i><br>
<b>pull</b> <i>servercode projectcode</i>
</blockquote>
230
231
232
233
234
235
236
237
238
239
240







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
two-argument format.</p>

<blockquote>
<b>clone</b><br>
<b>clone</b> <i>protocol-version sequence-number</i>
</blockquote>

<h4>3.5.1 Protocol 2</h4>

<p>The latest clients send a two-argument clone message with a
protocol version of "2".  (Future versions of Fossil might use larger







protocol version numbers.)  The sequence-number sent is the number
of artifacts received so far.  For the first clone message, the
sequence number if 0.  The server will respond by sending file
cards for some number of artifacts up to the maximum message size.

<p>The server will also send a single "clone_seqno" card to the client
so that the client can know where the server left off.

<blockquote>
<b>clone_seqno</b>  <i>sequence-number</i>
</blockquote>

<p>The clone message in subquence HTTP requests for the same clone
operation will use the sequence-number from the
clone_seqno of the previous reply.</p>

<p>In response to an initial clone message, the server also sends the client
a push message so that the client can discover the projectcode for
this project.</p>

<h4>3.5.2 Legacy Protocol</h4>

<p>Older clients send a clone card with no argument.  The server responds
to a blank clone card by sending an "igot" card for every artifact in the
repository.  The client will then issue "gimme" cards to pull down all the
content it needs.

<p>The legacy protocol works well for smaller repositories (50MB with 50,000







|


|
>
>
>
>
>
>
>
|

|









|







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
two-argument format.</p>

<blockquote>
<b>clone</b><br>
<b>clone</b> <i>protocol-version sequence-number</i>
</blockquote>

<h4>3.5.1 Protocol 3</h4>

<p>The latest clients send a two-argument clone message with a
protocol version of "3".   (Future versions of Fossil might use larger
protocol version numbers.)  Version "3" of the protocol enhanced version
"2" by introducing the "cfile" card which is intended to speed up clone
operations.  Instead of sending "file" cards, the server will send "cfile"
cards</p>

<h4>3.5.2 Protocol 2</h4>

<p>The sequence-number sent is the number
of artifacts received so far.  For the first clone message, the
sequence number is 0.  The server will respond by sending file
cards for some number of artifacts up to the maximum message size.

<p>The server will also send a single "clone_seqno" card to the client
so that the client can know where the server left off.

<blockquote>
<b>clone_seqno</b>  <i>sequence-number</i>
</blockquote>

<p>The clone message in subsequent HTTP requests for the same clone
operation will use the sequence-number from the
clone_seqno of the previous reply.</p>

<p>In response to an initial clone message, the server also sends the client
a push message so that the client can discover the projectcode for
this project.</p>

<h4>3.5.3 Legacy Protocol</h4>

<p>Older clients send a clone card with no argument.  The server responds
to a blank clone card by sending an "igot" card for every artifact in the
repository.  The client will then issue "gimme" cards to pull down all the
content it needs.

<p>The legacy protocol works well for smaller repositories (50MB with 50,000
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
<h3>3.13 Unknown Cards</h3>

<p>If either the client or the server sees a card that is not
described above, then it generates an error and aborts.</p>

<h2>4.0 Phantoms And Clusters</h2>

<p>When a repository knows that a artifact exists and knows the ID of
that artifact, but it does not know the artifact content, then it stores that
artifact as a "phantom".  A repository will typically create a phantom when
it receives an igot card for a artifact that it does not hold or when it
receives a file card that references a delta source that it does not
hold.  When a server is generating its reply or when a client is
generating a new request, it will usually send gimme cards for every
phantom that it holds.</p>

<p>A cluster is a special artifact that tells of the existence of other
artifacts.  Any artifact in the repository that follows the syntactic rules
of a cluster is considered a cluster.</p>

<p>A cluster is line oriented.  Each line of a cluster
is a card.  The cards are separated by the newline ("\n") character.
Each card consists of a single character card type, a space, and a
single argument.  No extra whitespace and no trailing or leading
whitespace is allowed.  All cards in the cluster must occur in
strict lexicographical order.</p>

<p>A cluster consists of one or more "M" cards followed by a single
"Z" card.  Each M card holds an argument which is a artifact ID for an
artifact in the repository.  The Z card has a single argument which is the
lower-case hexadecimal representation of the MD5 checksum of all
preceding M cards up to and included the newline character that
occurred just before the Z that starts the Z card.</p>

<p>Any artifact that does not match the specifications of a cluster
exactly is not a cluster.  There must be no extra whitespace in







|


|

















|







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
<h3>3.13 Unknown Cards</h3>

<p>If either the client or the server sees a card that is not
described above, then it generates an error and aborts.</p>

<h2>4.0 Phantoms And Clusters</h2>

<p>When a repository knows that an artifact exists and knows the ID of
that artifact, but it does not know the artifact content, then it stores that
artifact as a "phantom".  A repository will typically create a phantom when
it receives an igot card for an artifact that it does not hold or when it
receives a file card that references a delta source that it does not
hold.  When a server is generating its reply or when a client is
generating a new request, it will usually send gimme cards for every
phantom that it holds.</p>

<p>A cluster is a special artifact that tells of the existence of other
artifacts.  Any artifact in the repository that follows the syntactic rules
of a cluster is considered a cluster.</p>

<p>A cluster is line oriented.  Each line of a cluster
is a card.  The cards are separated by the newline ("\n") character.
Each card consists of a single character card type, a space, and a
single argument.  No extra whitespace and no trailing or leading
whitespace is allowed.  All cards in the cluster must occur in
strict lexicographical order.</p>

<p>A cluster consists of one or more "M" cards followed by a single
"Z" card.  Each M card holds an argument which is an artifact ID for an
artifact in the repository.  The Z card has a single argument which is the
lower-case hexadecimal representation of the MD5 checksum of all
preceding M cards up to and included the newline character that
occurred just before the Z that starts the Z card.</p>

<p>Any artifact that does not match the specifications of a cluster
exactly is not a cluster.  There must be no extra whitespace in
Changes to www/tickets.wiki.
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

The <b>tkt_id</b> fields of TICKET and TICKETCHNG are an integer key
used to uniquely identify the ticket to which the row belongs.  These
keys are for internal use only and may change when doing a "fossil rebuild".

The <b>tkt_uuid</b> field is the unique hexadecimal identifier for the ticket.
Ticket identifiers appear to be SHA1 hash strings, but they
are not really the hash of any identifible artifact.  They are
just random hexadecimal numbers.  When creating a new ticket, Fossil uses
a (high-quality) pseudo-random number generator to create the ticket 
number.  The ticket numbers are large so that the chance of collision
between any two tickets is vanishingly small.

The <b>tkt_mtime</b> field of TICKET shows the time (as a Julian day number)
of the most recent ticket change artifact for that ticket.  The
<b>tkt_mtime</b> field of TICKETCHNG shows the timestamp on the ticket
change artifact that the TICKETCHNG row refers to.  The 
<b>tkt_ctime</b> field of TICKET is the time of the oldest ticket change
artifact for that ticket, thus holding the time that the ticket was
created.

The <b>tkt_rid</b> field of TICKETCHNG is the integer primary key in the
BLOB table of the ticket change artifact that gave rise to the row in the
TICKETCHNG table.







|

|






|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

The <b>tkt_id</b> fields of TICKET and TICKETCHNG are an integer key
used to uniquely identify the ticket to which the row belongs.  These
keys are for internal use only and may change when doing a "fossil rebuild".

The <b>tkt_uuid</b> field is the unique hexadecimal identifier for the ticket.
Ticket identifiers appear to be SHA1 hash strings, but they
are not really the hash of any identifiable artifact.  They are
just random hexadecimal numbers.  When creating a new ticket, Fossil uses
a (high-quality) pseudo-random number generator to create the ticket
number.  The ticket numbers are large so that the chance of collision
between any two tickets is vanishingly small.

The <b>tkt_mtime</b> field of TICKET shows the time (as a Julian day number)
of the most recent ticket change artifact for that ticket.  The
<b>tkt_mtime</b> field of TICKETCHNG shows the timestamp on the ticket
change artifact that the TICKETCHNG row refers to.  The
<b>tkt_ctime</b> field of TICKET is the time of the oldest ticket change
artifact for that ticket, thus holding the time that the ticket was
created.

The <b>tkt_rid</b> field of TICKETCHNG is the integer primary key in the
BLOB table of the ticket change artifact that gave rise to the row in the
TICKETCHNG table.
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
To reconstruct the TICKET table, the ticket change
artifacts are visited in timestamp order.  As each ticket change artifact is
visited, its key/value pairs are examined.  For any key/value pair in
which the key is the same as a field in the TICKET table, the value
of that pair either replaces or is appended to the previous value
of the corresponding field in the TICKET table.  Whether a value is
replaced or appended is determined by markings in the ticket change
artifact itself.  Most fields are usually replaced. (For example, to change 
the status from "Open" to "Fixed" would involve a key value pair
"status/Fixed" with the replace attribute set).  The main exception
is the "comment" field, which is usually appended with new comment
text.

Note that the replace-or-append mark on ticket change artifacts is
only used by the TICKET table.  Since the initial value of all fields
in the TICKETCHNG table is NULL, the replace-or-append mark makes no
difference there.

<h3>2.3 Old-Style versus New-Style Tickets</h3>

Older versions of Fossil
(before [/timeline?c=2012-11-27+16:26:29 | 2012-11-27]) 
only supported the TICKET table.
In this older style, new comments were added to tickets by using
the append-value feature on the comment field.  Thus the TICKET.COMMENT
field contains the complete text of all user comments already appended
together and ready for display.

A problem with the old approach is that all comment text had to
be in the same format.  In other words, the all comment text had to be
either plaintext or wiki or HTML.  It was not possible for some comments
to be in HTML and others to be plaintext.  Some site adminstrators wanted the
ability to mix plaintext, wiki, and HTML comments and display each 
comment according to its chosen format.  Hence, Fossil was enhanced to
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its on mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in timestamp order.







|













|









|
|









158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
To reconstruct the TICKET table, the ticket change
artifacts are visited in timestamp order.  As each ticket change artifact is
visited, its key/value pairs are examined.  For any key/value pair in
which the key is the same as a field in the TICKET table, the value
of that pair either replaces or is appended to the previous value
of the corresponding field in the TICKET table.  Whether a value is
replaced or appended is determined by markings in the ticket change
artifact itself.  Most fields are usually replaced. (For example, to change
the status from "Open" to "Fixed" would involve a key value pair
"status/Fixed" with the replace attribute set).  The main exception
is the "comment" field, which is usually appended with new comment
text.

Note that the replace-or-append mark on ticket change artifacts is
only used by the TICKET table.  Since the initial value of all fields
in the TICKETCHNG table is NULL, the replace-or-append mark makes no
difference there.

<h3>2.3 Old-Style versus New-Style Tickets</h3>

Older versions of Fossil
(before [/timeline?c=2012-11-27T16:26:29 | 2012-11-27])
only supported the TICKET table.
In this older style, new comments were added to tickets by using
the append-value feature on the comment field.  Thus the TICKET.COMMENT
field contains the complete text of all user comments already appended
together and ready for display.

A problem with the old approach is that all comment text had to
be in the same format.  In other words, the all comment text had to be
either plaintext or wiki or HTML.  It was not possible for some comments
to be in HTML and others to be plaintext.  Some site administrators wanted the
ability to mix plaintext, wiki, and HTML comments and display each
comment according to its chosen format.  Hence, Fossil was enhanced to
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its on mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in timestamp order.