Check-in [7124f09f07]
Not logged in

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

Overview
Comment:Merge latest changes from trunk.
Timelines: family | ancestors | descendants | both | ashish-ipv6
Files: files | file ages | folders
SHA1: 7124f09f0770f64948f18d1866b37aa52e8048dd
User & Date: ashish 2012-03-10 13:17:50.720
Context
2013-04-21
08:08
Merge with trunk - Remove reverse-proxying support which is already provided by --baseurl option. check-in: 940b0b33c9 user: ashish tags: ashish-ipv6
2012-03-10
13:17
Merge latest changes from trunk. check-in: 7124f09f07 user: ashish tags: ashish-ipv6
03:59
Removed some dead code in /json/timeline/wiki. check-in: fe5cf37e66 user: stephan tags: trunk
2012-01-15
18:06
Merge latest changes from trunk check-in: b3130baa06 user: ashish tags: ashish-ipv6
Changes
Unified Diff Ignore Whitespace Patch
Changes to Makefile.in.
38
39
40
41
42
43
44

45
46
47
48
49
#
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







>





38
39
40
41
42
43
44
45
46
47
48
49
50
#
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@
FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@

include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile
Changes to VERSION.
1
1.21
|
1
1.22
Changes to ajax/i-test/rhino-test.js.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var TestApp = {
    serverUrl:
        'http://localhost:8080'
        //'http://fjson/cgi-bin/fossil-json.cgi'
        //'http://192.168.1.62:8080'
        //'http://fossil.wanderinghorse.net/repos/fossil-json-java/index.cgi'
        ,
    verbose:false,
    fossilBinary:'fossil',
    wiki:{}
};
(function bootstrap() {
    var srcdir = '../js/';
    var includes = [srcdir+'json2.js',
                    srcdir+'whajaj.js',







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var TestApp = {
    serverUrl:
        'http://localhost:8080'
        //'http://fjson/cgi-bin/fossil-json.cgi'
        //'http://192.168.1.62:8080'
        //'http://fossil.wanderinghorse.net/repos/fossil-json-java/index.cgi'
        ,
    verbose:true,
    fossilBinary:'fossil',
    wiki:{}
};
(function bootstrap() {
    var srcdir = '../js/';
    var includes = [srcdir+'json2.js',
                    srcdir+'whajaj.js',
169
170
171
172
173
174
175
















176
177
178
179
180
181
182
    assertResponseOK(rs);
    assert(rs.payload.name == TestApp.wiki.list[0], "Fetched page name matches expectations.");
    print("Got first wiki page: "+WhAjaj.stringify(rs.payload));

}
testAnonWiki.description = 'Fetch wiki list as anonymous user.';

















function testAnonLogout(){
    var rs;
    TestApp.fossil.logout({
        onResponse:function(resp,req){
            rs = resp;
        }
    });







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







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
    assertResponseOK(rs);
    assert(rs.payload.name == TestApp.wiki.list[0], "Fetched page name matches expectations.");
    print("Got first wiki page: "+WhAjaj.stringify(rs.payload));

}
testAnonWiki.description = 'Fetch wiki list as anonymous user.';

function testFetchCheckinArtifact(){
    var art = '18dd383e5e7684ece';
    var rs;
    TestApp.fossil.sendCommand('/json/artifact',{
        'name': art
        },
        {
            onResponse:function(resp,req){
                rs = resp;
            }
        });
    assertResponseOK(rs);
    assert(3 == rs.payload.artifact.parents.length, 'Got 3 parent artifacts.');
}
testFetchCheckinArtifact.description = '/json/artifact/CHECKIN';

function testAnonLogout(){
    var rs;
    TestApp.fossil.logout({
        onResponse:function(resp,req){
            rs = resp;
        }
    });
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
    var args = [TestApp.fossilBinary, 'json', '--json-input', '-'];
    var p = java.lang.Runtime.getRuntime().exec(args);
    var outs = p.getOutputStream();
    var osr = new java.io.OutputStreamWriter(outs);
    var osb = new java.io.BufferedWriter(osr);
    var json = JSON.stringify(req);
    osb.write(json,0, json.length);
    //osb.flush();
    osb.close();

    var ins = p.getInputStream();
    var isr = new java.io.InputStreamReader(ins);
    var br = new java.io.BufferedReader(isr);
    var line;
    
    while( null !== (line=br.readLine())){
        print(line);
    }
    //outs.close();

    ins.close();

}
testExternalProcess.description = 'Run fossil as external process.';

function testExternalProcessHandler(){
    var aj = TestApp.fossil.ajaj;
    var oldImpl = aj.sendImpl;
    aj.sendImpl = FossilAjaj.rhinoLocalBinarySendImpl;







<

>








|
>

>







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
    var args = [TestApp.fossilBinary, 'json', '--json-input', '-'];
    var p = java.lang.Runtime.getRuntime().exec(args);
    var outs = p.getOutputStream();
    var osr = new java.io.OutputStreamWriter(outs);
    var osb = new java.io.BufferedWriter(osr);
    var json = JSON.stringify(req);
    osb.write(json,0, json.length);

    osb.close();
    req = json = outs = osr = osb = undefined;
    var ins = p.getInputStream();
    var isr = new java.io.InputStreamReader(ins);
    var br = new java.io.BufferedReader(isr);
    var line;
    
    while( null !== (line=br.readLine())){
        print(line);
    }
    br.close();
    isr.close();
    ins.close();
    p.waitFor();
}
testExternalProcess.description = 'Run fossil as external process.';

function testExternalProcessHandler(){
    var aj = TestApp.fossil.ajaj;
    var oldImpl = aj.sendImpl;
    aj.sendImpl = FossilAjaj.rhinoLocalBinarySendImpl;
235
236
237
238
239
240
241

242
243
244
245
246
247
248
249
250

(function runAllTests(){
    var testList = [
        testHAI,
        testIAmNobody,
        testAnonymousLogin,
        testAnonWiki,

        testAnonLogout,
        //testExternalProcess,
        testExternalProcessHandler
    ];
    var i, f;
    for( i = 0; i < testList.length; ++i ){
        f = testList[i];
        try{
            print("Running test #"+(i+1)+": "+(f.description || "no description."));







>

|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

(function runAllTests(){
    var testList = [
        testHAI,
        testIAmNobody,
        testAnonymousLogin,
        testAnonWiki,
        testFetchCheckinArtifact,
        testAnonLogout,
        testExternalProcess,
        testExternalProcessHandler
    ];
    var i, f;
    for( i = 0; i < testList.length; ++i ){
        f = testList[i];
        try{
            print("Running test #"+(i+1)+": "+(f.description || "no description."));
Changes to ajax/index.html.
231
232
233
234
235
236
237



238

239
240

241
242
243
244
245
246
247
<br/>

<input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
<input type='button' value='timeline/branch' onclick='TheApp.cgi.sendCommand("/json/timeline/branch")' />



<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />

<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{name:"Fossil"})' />
<input type='button' value='wiki/get/Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get/Fossil")' />


<br/>

<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
<input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' />
<input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' />







>
>
>

>


>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<br/>

<input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
<input type='button' value='timeline/branch' onclick='TheApp.cgi.sendCommand("/json/timeline/branch")' />

<br/>

<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
<input type='button' value='wiki/list verbose' onclick='TheApp.cgi.sendCommand("/json/wiki/list",{verbose:1})' />
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{name:"Fossil"})' />
<input type='button' value='wiki/get/Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get/Fossil")' />
<input type='button' value='wiki/diff' onclick='TheApp.cgi.sendCommand("/json/wiki/diff/e32ccdcda59e930c77c/e15992f475760cdf3a9")' />

<br/>

<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
<input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' />
<input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' />
265
266
267
268
269
270
271


272
273
274
275
276
277
278
<input type='button' value='report list'
    onclick='TheApp.cgi.sendCommand("/json/report/list")' />
<input type='button' value='report get'
    onclick='TheApp.cgi.sendCommand("/json/report/get",2)' />

<input type='button' value='report run'
    onclick='TheApp.cgi.sendCommand("/json/report/run",{"report":2,"format":"o"})' />



<!-- not yet ready...
<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
-->

<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />







>
>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<input type='button' value='report list'
    onclick='TheApp.cgi.sendCommand("/json/report/list")' />
<input type='button' value='report get'
    onclick='TheApp.cgi.sendCommand("/json/report/get",2)' />

<input type='button' value='report run'
    onclick='TheApp.cgi.sendCommand("/json/report/run",{"report":2,"format":"o"})' />

<input type='button' value='config/get' onclick='TheApp.cgi.sendCommand("/json/config/get")' />

<!-- not yet ready...
<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
-->

<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
Changes to ajax/js/whajaj.js.
107
108
109
110
111
112
113

114
115
116
117
118
119
120
    if( 0 === arguments.length ) {
        if( ('undefined' === typeof window) ||
            !window.location ||
            !window.location.search )  return false;
        else str = (''+window.location.search).substring(1);
    }
    if( ! str ) return false;

    var args = {};
    var sp = str.split(/&+/);
    var rx = /^([^=]+)(=(.+))?/;
    var i, m;
    for( i in sp ) {
        m = rx.exec( sp[i] );
        if( ! m ) continue;







>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
    if( 0 === arguments.length ) {
        if( ('undefined' === typeof window) ||
            !window.location ||
            !window.location.search )  return false;
        else str = (''+window.location.search).substring(1);
    }
    if( ! str ) return false;
    str = (''+str).split(/#/,2)[0]; // remove #... to avoid it being added as part of the last value.
    var args = {};
    var sp = str.split(/&+/);
    var rx = /^([^=]+)(=(.+))?/;
    var i, m;
    for( i in sp ) {
        m = rx.exec( sp[i] );
        if( ! m ) continue;
Changes to auto.def.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
            if {$dir eq ""} {
                set msg "system ssl"
                set cflags ""
                set ldflags ""
            } else {
                set msg "ssl in $dir"
                set cflags "-I$dir/include"
                set ldflags "-L$dir/include"
            }
            if {[check-for-openssl $msg "$cflags $ldflags"]} {
                incr found
                break
            }
        }
    }







|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
            if {$dir eq ""} {
                set msg "system ssl"
                set cflags ""
                set ldflags ""
            } else {
                set msg "ssl in $dir"
                set cflags "-I$dir/include"
                set ldflags "-L$dir/lib"
            }
            if {[check-for-openssl $msg "$cflags $ldflags"]} {
                incr found
                break
            }
        }
    }
Changes to autosetup/README.autosetup.
1
This is autosetup v0.6.2. See http://msteveb.github.com/autosetup/
|
1
This is autosetup v0.6.4. See http://msteveb.github.com/autosetup/
Changes to autosetup/autosetup.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh
# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
# All rights reserved
# vim:se syntax=tcl:
# \
dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"

set autosetup(version) 0.6.2

# Can be set to 1 to debug early-init problems
set autosetup(debug) 0

##################################################################
#
# Main flow of control, option handling







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh
# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
# All rights reserved
# vim:se syntax=tcl:
# \
dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"

set autosetup(version) 0.6.4

# Can be set to 1 to debug early-init problems
set autosetup(debug) 0

##################################################################
#
# Main flow of control, option handling
514
515
516
517
518
519
520

521
522
523
524
525
526



527
528
529
530
531
532
533
	}
	getenv $name $default
}

# @env-is-set name
#
# Returns 1 if the $name was specified on the command line or in the environment.

#
proc env-is-set {name} {
	if {[dict exists $::autosetup(cmdline) $name]} {
		return 1
	}
	info exists ::env($name)



}

# @readfile filename ?default=""?
#
# Return the contents of the file, without the trailing newline.
# If the doesn't exist or can't be read, returns $default.
#







>





|
>
>
>







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
	}
	getenv $name $default
}

# @env-is-set name
#
# Returns 1 if the $name was specified on the command line or in the environment.
# Note that an empty environment variable is not considered to be set.
#
proc env-is-set {name} {
	if {[dict exists $::autosetup(cmdline) $name]} {
		return 1
	}
	if {[getenv $name ""] ne ""} {
		return 1
	}
	return 0
}

# @readfile filename ?default=""?
#
# Return the contents of the file, without the trailing newline.
# If the doesn't exist or can't be read, returns $default.
#
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
	} else {
		puts "I don't see configure, so I will create it."
	}
	if {$create_configure} {
		if {!$::autosetup(installed)} {
			user-notice "Warning: Initialising from the development version of autosetup"

			writefile configure "#!/bin/sh\nWRAPPER=\"\$0\" exec $::autosetup(dir)/autosetup \"\$@\"\n"
		} else {
			writefile configure \
{#!/bin/sh
dir="`dirname "$0"`/autosetup"
WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
}
		}
		catch {exec chmod 755 configure}
	}
	if {![file exists auto.def]} {
		puts "I don't see auto.def, so I will create a default one."
		writefile auto.def {# Initial auto.def created by 'autosetup --init'







|




|







1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
	} else {
		puts "I don't see configure, so I will create it."
	}
	if {$create_configure} {
		if {!$::autosetup(installed)} {
			user-notice "Warning: Initialising from the development version of autosetup"

			writefile configure "#!/bin/sh\nWRAPPER=\"\$0\"; export WRAPPER; exec $::autosetup(dir)/autosetup \"\$@\"\n"
		} else {
			writefile configure \
{#!/bin/sh
dir="`dirname "$0"`/autosetup"
WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
}
		}
		catch {exec chmod 755 configure}
	}
	if {![file exists auto.def]} {
		puts "I don't see auto.def, so I will create a default one."
		writefile auto.def {# Initial auto.def created by 'autosetup --init'
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
	}
} elseif {$autosetup(iswin)} {
	# On Windows, backslash convert all environment variables
	# (Assume that Tcl does this for us)
	proc getenv {name args} {
		string map {\\ /} [env $name {*}$args]
	}
	# Jim uses system() for exec under mingw, so
	# we need to fetch the output ourselves
	proc exec-with-stderr {args} {
			set tmpfile auto[format %04x [rand 10000]].tmp
			set rc [catch [list exec {*}$args >$tmpfile 2>&1] result]
			set result [readfile $tmpfile]
			file delete $tmpfile
			return -code $rc $result
	}
} else {
	# Jim on unix is simple
	alias getenv env
}

# In case 'file normalize' doesn't exist
#







<
<
<
<
<
<
<
<
<







1543
1544
1545
1546
1547
1548
1549









1550
1551
1552
1553
1554
1555
1556
	}
} elseif {$autosetup(iswin)} {
	# On Windows, backslash convert all environment variables
	# (Assume that Tcl does this for us)
	proc getenv {name args} {
		string map {\\ /} [env $name {*}$args]
	}









} else {
	# Jim on unix is simple
	alias getenv env
}

# In case 'file normalize' doesn't exist
#
Added autosetup/cc-db.tcl.






























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
# All rights reserved

# @synopsis:
#
# The 'cc-db' module provides a knowledge based of system idiosyncracies
# In general, this module can always be included

use cc

module-options {}

# openbsd needs sys/types.h to detect some system headers
cc-include-needs sys/socket.h sys/types.h
cc-include-needs netinet/in.h sys/types.h
Changes to autosetup/cc-shared.tcl.
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




# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved

# @synopsis:
#
# The 'cc-shared' module provides support for shared libraries and shared objects.
# It defines the following variables:
#
## SH_CFLAGS         Flags to use compiling sources destined for a shared library
## SH_LDFLAGS        Flags to use linking a shared library
## SHOBJ_CFLAGS      Flags to use compiling sources destined for a shared object
## SHOBJ_LDFLAGS     Flags to use linking a shared object

## SH_LINKFLAGS      Flags to use linking an executable which will load shared objects
## LD_LIBRARY_PATH   Environment variable which specifies path to shared libraries

module-options {}

foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LDFLAGS} {
	define $i ""
}

define LD_LIBRARY_PATH LD_LIBRARY_PATH

switch -glob -- [get-define host] {
	*-*-darwin* {
		define SH_CFLAGS -dynamic
		define SH_LDFLAGS "-dynamiclib"
		define SHOBJ_CFLAGS "-dynamic -fno-common"
		define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup"

		define LD_LIBRARY_PATH DYLD_LIBRARY_PATH
	}
	*-*-ming* {
		define SH_LDFLAGS -shared
		define SHOBJ_LDFLAGS -shared

	}
	*-*-cygwin {
		define SH_LDFLAGS -shared
		define SHOBJ_LDFLAGS -shared
	}
	*-*-solaris* {
		# XXX: These haven't been fully tested. 
		#define SH_LINKFLAGS -Wl,-export-dynamic
		define SH_CFLAGS -Kpic
		define SHOBJ_CFLAGS -Kpic
		define SHOBJ_LDFLAGS "-G"
	}
	*-*-hpux {
		# XXX: These haven't been tested
		define SH_LINKFLAGS -Wl,+s
		define SH_CFLAGS +z
		define SHOBJ_CFLAGS "+O3 +z"
		define SHOBJ_LDFLAGS -b
		define LD_LIBRARY_PATH SHLIB_PATH
	}








	* {
		# Generic Unix settings
		define SH_LINKFLAGS -rdynamic
		define SH_CFLAGS -fpic
		define SH_LDFLAGS -shared
		define SHOBJ_CFLAGS -fpic
		define SHOBJ_LDFLAGS "-shared -nostartfiles"
	}
}















|
>

















>





>




















>
>
>
>
>
>
>
>






|


>
>
>
>
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
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved

# @synopsis:
#
# The 'cc-shared' module provides support for shared libraries and shared objects.
# It defines the following variables:
#
## SH_CFLAGS         Flags to use compiling sources destined for a shared library
## SH_LDFLAGS        Flags to use linking a shared library
## SHOBJ_CFLAGS      Flags to use compiling sources destined for a shared object
## SHOBJ_LDFLAGS     Flags to use linking a shared object, undefined symbols allowed
## SHOBJ_LDFLAGS_R   - as above, but all symbols must be resolved
## SH_LINKFLAGS      Flags to use linking an executable which will load shared objects
## LD_LIBRARY_PATH   Environment variable which specifies path to shared libraries

module-options {}

foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LDFLAGS} {
	define $i ""
}

define LD_LIBRARY_PATH LD_LIBRARY_PATH

switch -glob -- [get-define host] {
	*-*-darwin* {
		define SH_CFLAGS -dynamic
		define SH_LDFLAGS "-dynamiclib"
		define SHOBJ_CFLAGS "-dynamic -fno-common"
		define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup"
		define SHOBJ_LDFLAGS_R "-bundle"
		define LD_LIBRARY_PATH DYLD_LIBRARY_PATH
	}
	*-*-ming* {
		define SH_LDFLAGS -shared
		define SHOBJ_LDFLAGS -shared
		define SHOBJ_LDFLAGS_R -shared
	}
	*-*-cygwin {
		define SH_LDFLAGS -shared
		define SHOBJ_LDFLAGS -shared
	}
	*-*-solaris* {
		# XXX: These haven't been fully tested. 
		#define SH_LINKFLAGS -Wl,-export-dynamic
		define SH_CFLAGS -Kpic
		define SHOBJ_CFLAGS -Kpic
		define SHOBJ_LDFLAGS "-G"
	}
	*-*-hpux {
		# XXX: These haven't been tested
		define SH_LINKFLAGS -Wl,+s
		define SH_CFLAGS +z
		define SHOBJ_CFLAGS "+O3 +z"
		define SHOBJ_LDFLAGS -b
		define LD_LIBRARY_PATH SHLIB_PATH
	}
	sparc* {
		# sparc has a very small GOT table limit, so use -fPIC
		define SH_LINKFLAGS -rdynamic
		define SH_CFLAGS -fPIC
		define SH_LDFLAGS -shared
		define SHOBJ_CFLAGS -fPIC
		define SHOBJ_LDFLAGS -shared
	}
	* {
		# Generic Unix settings
		define SH_LINKFLAGS -rdynamic
		define SH_CFLAGS -fpic
		define SH_LDFLAGS -shared
		define SHOBJ_CFLAGS -fpic
		define SHOBJ_LDFLAGS -shared
	}
}

if {![is-defined SHOBJ_LDFLAGS_R]} {
	define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
}
Changes to autosetup/cc.tcl.
109
110
111
112
113
114
115












116
117


118










119
120
121
122
123
124
125
}

# @cc-check-includes includes ...
#
# Checks that the given include files can be used
proc cc-check-includes {args} {
	cc-check-some-feature $args {












		cctest -includes $each
	}


}











# @cc-check-types type ...
#
# Checks that the types exist.
proc cc-check-types {args} {
	cc-check-some-feature $args {
		cctest_type $each







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







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
}

# @cc-check-includes includes ...
#
# Checks that the given include files can be used
proc cc-check-includes {args} {
	cc-check-some-feature $args {
		set with {}
		if {[dict exists $::autosetup(cc-include-deps) $each]} {
			set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
			msg-quiet cc-check-includes $deps
			foreach i $deps {
				if {[have-feature $i]} {
					lappend with $i
				}
			}
		}
		if {[llength $with]} {
			cc-with [list -includes $with] {
				cctest -includes $each
			}
		} else {
			cctest -includes $each
		}
	}
}

# @cc-include-needs include required
#
# Ensures that when checking for 'include', a check is first
# made for 'required', and if found, it is #included
proc cc-include-needs {file depfile} {
	dict set ::autosetup(cc-include-deps) $file $depfile 1
}

# @cc-check-types type ...
#
# Checks that the types exist.
proc cc-check-types {args} {
	cc-check-some-feature $args {
		cctest_type $each
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
	} elseif {[llength $args] > 1} {
		autosetup-error "usage: cc-with settings ?script?"
	} else {
		set save [cc-add-settings $settings]
		set rc [catch {uplevel 1 [lindex $args 0]} result info]
		cc-store-settings $save
		if {$rc != 0} {
			return $result -code [dict get $info -code]
		}
		return $result
	}
}

# @cctest ?settings?
# 







|







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
	} elseif {[llength $args] > 1} {
		autosetup-error "usage: cc-with settings ?script?"
	} else {
		set save [cc-add-settings $settings]
		set rc [catch {uplevel 1 [lindex $args 0]} result info]
		cc-store-settings $save
		if {$rc != 0} {
			return -code [dict get $info -code] $result
		}
		return $result
	}
}

# @cctest ?settings?
# 
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
	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 {}}


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]"

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







>










668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
	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]"

if {![cc-check-includes stdlib.h]} {
	user-error "Compiler does not work. See config.log"
}
Changes to autosetup/find-tclsh.
1
2
3
4

5
6
7
8
9
10
11
12
13
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
d=`dirname "$0"`

PATH="$PATH:$d"
for tclsh in jimsh tclsh tclsh8.5 tclsh8.6 jimsh0; do
	{ $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
	"$d/jimsh0" "$d/test-tclsh" && exit 0
done




>
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
d=`dirname "$0"`
{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
PATH="$PATH:$d"; export PATH
for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do
	{ $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
	"$d/jimsh0" "$d/test-tclsh" && exit 0
done
Changes to autosetup/jimsh0.c.

more than 10,000 changes

Changes to autosetup/system.tcl.
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
define prefix $prefix
define builddir $autosetup(builddir)
define srcdir $autosetup(srcdir)
# Allow this to come from the environment
define top_srcdir [get-env top_srcdir [get-define srcdir]]

# autoconf supports all of these
define exec_prefix [opt-val exec-prefix [get-env exec-prefix \${prefix}]]

foreach {name defpath} {
	bindir \${exec_prefix}/bin
	sbindir \${exec_prefix}/sbin
	libexecdir \${exec_prefix}/libexec
	libdir \${exec_prefix}/lib




	datadir \${prefix}/share
	sysconfdir \${prefix}/etc
	sharedstatedir \${prefix}/com
	localstatedir \${prefix}/var
	infodir \${prefix}/share/info
	mandir \${prefix}/share/man
	includedir \${prefix}/include
} {
	define $name [opt-val $name [get-env $name $defpath]]
}

define SHELL [get-env SHELL [find-an-executable sh bash ksh]]

# Windows vs. non-Windows
switch -glob -- [get-define host] {
	*-*-ming* - *-*-cygwin {







|
>

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

|







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 prefix $prefix
define builddir $autosetup(builddir)
define srcdir $autosetup(srcdir)
# Allow this to come from the environment
define top_srcdir [get-env top_srcdir [get-define srcdir]]

# autoconf supports all of these
set exec_prefix [opt-val exec-prefix $prefix]
define exec_prefix $exec_prefix
foreach {name defpath} {
	bindir /bin
	sbindir /sbin
	libexecdir /libexec
	libdir /lib
} {
	define $name [opt-val $name $exec_prefix$defpath]
}
foreach {name defpath} {
	datadir /share
	sysconfdir /etc
	sharedstatedir /com
	localstatedir /var
	infodir /share/info
	mandir /share/man
	includedir /include
} {
	define $name [opt-val $name $prefix$defpath]
}

define SHELL [get-env SHELL [find-an-executable sh bash ksh]]

# Windows vs. non-Windows
switch -glob -- [get-define host] {
	*-*-ming* - *-*-cygwin {
Changes to autosetup/test-tclsh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# A small Tcl script to verify that the chosen
# interpreter works. Sometimes we might e.g. pick up
# an interpreter for a different arch.
# Outputs the full path to the interpreter

if {[catch {info version} version] == 0} {
	# This is Jim Tcl
	if {$version >= 0.70} {
		# Ensure that regexp works
		regexp (a.*?) a

		# Older versions of jimsh may return a relative path for [info nameofexecutable]
		puts [file join [pwd] [info nameofexecutable]]
		exit 0
	}
} elseif {[catch {info tclversion} version] == 0} {
	if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
		puts [info nameofexecutable]
		exit 0
	}







|


<
<
|







1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
# A small Tcl script to verify that the chosen
# interpreter works. Sometimes we might e.g. pick up
# an interpreter for a different arch.
# Outputs the full path to the interpreter

if {[catch {info version} version] == 0} {
	# This is Jim Tcl
	if {$version >= 0.72} {
		# Ensure that regexp works
		regexp (a.*?) a


		puts [info nameofexecutable]
		exit 0
	}
} elseif {[catch {info tclversion} version] == 0} {
	if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
		puts [info nameofexecutable]
		exit 0
	}
Changes to configure.
1
2
3
#!/bin/sh
dir="`dirname "$0"`/autosetup"
WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"


|
1
2
3
#!/bin/sh
dir="`dirname "$0"`/autosetup"
WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
Changes to debian/makedeb.sh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# A quick hack to generate a Debian package of fossil. i took most of this
# from Martin Krafft's "The Debian System" book.

DEB_REV=${1-1} # .deb package build/revision number.
PACKAGE_DEBNAME=fossil-scm
THISDIR=${PWD}

if uname -a | grep -i nexenta &>/dev/null; then
# Assume NexentaOS/GnuSolaris:
    DEB_PLATFORM=nexenta
    DEB_ARCH_NAME=solaris-i386
    DEB_ARCH_PKGDEPENDS="sunwcsl" # for -lsocket
else
    DEB_PLATFORM=${DEB_PLATFORM-ubuntu-gutsy}
    DEB_ARCH_NAME=i386
fi

SRCDIR=$(cd ..; pwd)
test -e ${SRCDIR}/fossil || {
    echo "This script must be run from a BUILT copy of the source tree."
    exit 1
}





|




<



<
|







1
2
3
4
5
6
7
8
9
10

11
12
13

14
15
16
17
18
19
20
21
#!/bin/bash
# A quick hack to generate a Debian package of fossil. i took most of this
# from Martin Krafft's "The Debian System" book.

DEB_REV=${1-1} # .deb package build/revision number.
PACKAGE_DEBNAME=fossil
THISDIR=${PWD}

if uname -a | grep -i nexenta &>/dev/null; then
# Assume NexentaOS/GnuSolaris:

    DEB_ARCH_NAME=solaris-i386
    DEB_ARCH_PKGDEPENDS="sunwcsl" # for -lsocket
else

    DEB_ARCH_NAME=$(dpkg --print-architecture)
fi

SRCDIR=$(cd ..; pwd)
test -e ${SRCDIR}/fossil || {
    echo "This script must be run from a BUILT copy of the source tree."
    exit 1
}
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


rm -fr DEBIAN
mkdir DEBIAN

PACKAGE_VERSION=$(date +%Y.%m.%d)
PACKAGE_DEB_VERSION=${PACKAGE_VERSION}-${DEB_REV}
DEBFILE=${THISDIR}/${PACKAGE_DEBNAME}-${PACKAGE_DEB_VERSION}-dev-${DEB_ARCH_NAME}-${DEB_PLATFORM}.deb
PACKAGE_TIME=$(/bin/date)

rm -f ${DEBFILE}
echo "Creating .deb package [${DEBFILE}]..."

echo "Generating md5 sums..."
find ${DEBLOCALPREFIX} -type f -exec md5sum {} \; > DEBIAN/md5sums

true && {
    echo "Generating Debian-specific files..."
    COPYRIGHT=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/copyright
    cat <<EOF > ${COPYRIGHT}
This package was created by stephan beal <stephan@s11n.net>
on ${PACKAGE_TIME}.

The original sources for fossil can be downloaded for free from:

http://www.fossil-scm.org/

fossil is released under the terms of the GNU General Public License.

EOF
}

true && {
    CHANGELOG=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/changelog.gz
    cat <<EOF | gzip -c > ${CHANGELOG}
${PACKAGE_DEBNAME} ${PACKAGE_DEB_VERSION}; urgency=low

This release has no changes over the core source distribution. It has
simply been Debianized.

Packaged by stephan beal <stephan@s11n.net> on
${PACKAGE_TIME}.

EOF

}


true && {
    CONTROL=DEBIAN/control
    echo "Generating ${CONTROL}..."
    cat <<EOF > ${CONTROL}
Package: ${PACKAGE_DEBNAME}
Section: devel
Priority: optional
Maintainer: stephan beal <stephan@s11n.net>
Architecture: ${DEB_ARCH_NAME}
Depends: libc6-dev ${DEB_ARCH_PKGDEPENDS+, }${DEB_ARCH_PKGDEPENDS}
Version: ${PACKAGE_DEB_VERSION}
Description: Fossil is a unique SCM (Software Configuration Management) system.
 This package contains the Fossil binary for *buntu/Debian systems.
 Fossil is a unique SCM program which supports distributed source control
 management using local repositories, access over HTTP CGI, or using the
 built-in HTTP server. It has a built-in wiki, file browsing, etc.
 Fossil home page: http://fossil-scm.org







|












|



















|












|

|

|







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


rm -fr DEBIAN
mkdir DEBIAN

PACKAGE_VERSION=$(date +%Y.%m.%d)
PACKAGE_DEB_VERSION=${PACKAGE_VERSION}-${DEB_REV}
DEBFILE=${THISDIR}/${PACKAGE_DEBNAME}-${PACKAGE_DEB_VERSION}-dev-${DEB_ARCH_NAME}.deb
PACKAGE_TIME=$(/bin/date)

rm -f ${DEBFILE}
echo "Creating .deb package [${DEBFILE}]..."

echo "Generating md5 sums..."
find ${DEBLOCALPREFIX} -type f -exec md5sum {} \; > DEBIAN/md5sums

true && {
    echo "Generating Debian-specific files..."
    COPYRIGHT=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/copyright
    cat <<EOF > ${COPYRIGHT}
This package was created by fossil-scm <fossil-dev@lists.fossil-scm.org>
on ${PACKAGE_TIME}.

The original sources for fossil can be downloaded for free from:

http://www.fossil-scm.org/

fossil is released under the terms of the GNU General Public License.

EOF
}

true && {
    CHANGELOG=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/changelog.gz
    cat <<EOF | gzip -c > ${CHANGELOG}
${PACKAGE_DEBNAME} ${PACKAGE_DEB_VERSION}; urgency=low

This release has no changes over the core source distribution. It has
simply been Debianized.

Packaged by fossil-dev <fossil-dev@lists.fossil-scm.org> on
${PACKAGE_TIME}.

EOF

}


true && {
    CONTROL=DEBIAN/control
    echo "Generating ${CONTROL}..."
    cat <<EOF > ${CONTROL}
Package: ${PACKAGE_DEBNAME}
Section: vcs
Priority: optional
Maintainer: fossil-dev <fossil-dev@lists.fossil-scm.org>
Architecture: ${DEB_ARCH_NAME}
Depends: libc6 ${DEB_ARCH_PKGDEPENDS+, }${DEB_ARCH_PKGDEPENDS}
Version: ${PACKAGE_DEB_VERSION}
Description: Fossil is a unique SCM (Software Configuration Management) system.
 This package contains the Fossil binary for *buntu/Debian systems.
 Fossil is a unique SCM program which supports distributed source control
 management using local repositories, access over HTTP CGI, or using the
 built-in HTTP server. It has a built-in wiki, file browsing, etc.
 Fossil home page: http://fossil-scm.org
Changes to src/add.c.
42
43
44
45
46
47
48








49
50
51
52
53
54
55
  ** its associated journals
  */
  static const char *azName[] = {
     "_FOSSIL_",
     "_FOSSIL_-journal",
     "_FOSSIL_-wal",
     "_FOSSIL_-shm",








     ".fos",
     ".fos-journal",
     ".fos-wal",
     ".fos-shm",
  };

  /* Names of auxiliary files generated by SQLite when the "manifest"







>
>
>
>
>
>
>
>







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  ** its associated journals
  */
  static const char *azName[] = {
     "_FOSSIL_",
     "_FOSSIL_-journal",
     "_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",
  };

  /* Names of auxiliary files generated by SQLite when the "manifest"
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
** Move or rename one or more files or directories within the repository tree.
** You can either rename a file or directory or move it to another subdirectory.
**
** This command does NOT rename or move the files on disk.  This command merely
** records the fact that filenames have changed so that appropriate notations
** can be made at the next commit/checkin.
**
**
** SUMMARY: fossil mv|rename OLDNAME NEWNAME
**      or: fossil mv|rename OLDNAME... DIR
*/
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;
  Stmt q;







|
<
<







505
506
507
508
509
510
511
512


513
514
515
516
517
518
519
** Move or rename one or more files or directories within the repository tree.
** You can either rename a file or directory or move it to another subdirectory.
**
** This command does NOT rename or move the files on disk.  This command merely
** records the fact that filenames have changed so that appropriate notations
** can be made at the next commit/checkin.
**
** See also: changes, status


*/
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;
  Stmt q;
Changes to src/branch.c.
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    prompt_user("unable to sign manifest.  continue (y/N)? ", &ans);
    if( blob_str(&ans)[0]!='y' ){
      db_end_transaction(1);
      fossil_exit(1);
    }
  }

  brid = content_put(&branch);
  if( brid==0 ){
    fossil_panic("trouble committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch)==0 ){
    fossil_panic("unable to install new manifest");
  }







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    prompt_user("unable to sign manifest.  continue (y/N)? ", &ans);
    if( blob_str(&ans)[0]!='y' ){
      db_end_transaction(1);
      fossil_exit(1);
    }
  }

  brid = content_put_ex(&branch, 0, 0, 0, isPrivate);
  if( brid==0 ){
    fossil_panic("trouble committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch)==0 ){
    fossil_panic("unable to install new manifest");
  }
Changes to src/cgi.c.
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  }

  /* If no match is found and the name begins with an upper-case
  ** letter, then check to see if there is an environment variable
  ** with the given name.
  */
  if( fossil_isupper(zName[0]) ){
    const char *zValue = getenv(zName);
    if( zValue ){
      cgi_set_parameter_nocopy(zName, zValue);
      CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
      return zValue;
    }
  }
  CGIDEBUG(("no-match [%s]\n", zName));







|







913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  }

  /* If no match is found and the name begins with an upper-case
  ** letter, then check to see if there is an environment variable
  ** with the given name.
  */
  if( fossil_isupper(zName[0]) ){
    const char *zValue = fossil_getenv(zName);
    if( zValue ){
      cgi_set_parameter_nocopy(zName, zValue);
      CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
      return zValue;
    }
  }
  CGIDEBUG(("no-match [%s]\n", zName));
Changes to src/checkin.c.
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
**
** See also: changes, extra, ls
*/
void status_cmd(void){
  int vid;
  db_must_be_within_tree();
       /* 012345678901234 */
  fossil_print("repository:   %s\n", db_lget("repository",""));
  fossil_print("local-root:   %s\n", g.zLocalRoot);
  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }
  db_record_repository_filename(0);
  changes_cmd();







|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
**
** See also: changes, extra, 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);
  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }
  db_record_repository_filename(0);
  changes_cmd();
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
      "# repositories.\n"
      "#\n", -1
    );
  }
  status_report(&text, "# ", 1, 0);
  zEditor = db_get("editor", 0);
  if( zEditor==0 ){
    zEditor = getenv("VISUAL");
  }
  if( zEditor==0 ){
    zEditor = getenv("EDITOR");
  }
  if( zEditor==0 ){
    blob_append(&text,
       "#\n"
       "# Since no default text editor is set using EDITOR or VISUAL\n"
       "# environment variables or the \"fossil set editor\" command,\n"
       "# and because no check-in comment was specified using the \"-m\"\n"







|


|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
      "# repositories.\n"
      "#\n", -1
    );
  }
  status_report(&text, "# ", 1, 0);
  zEditor = db_get("editor", 0);
  if( zEditor==0 ){
    zEditor = fossil_getenv("VISUAL");
  }
  if( zEditor==0 ){
    zEditor = fossil_getenv("EDITOR");
  }
  if( zEditor==0 ){
    blob_append(&text,
       "#\n"
       "# Since no default text editor is set using EDITOR or VISUAL\n"
       "# environment variables or the \"fossil set editor\" command,\n"
       "# and because no check-in comment was specified using the \"-m\"\n"
Changes to src/clone.c.
17
18
19
20
21
22
23























































24
25
26
27
28
29
30
**
** This file contains code used to clone a repository
*/
#include "config.h"
#include "clone.h"
#include <assert.h>


























































/*
** COMMAND: clone
**
** Usage: %fossil clone ?OPTIONS? URL FILENAME
**







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







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
**
** This file contains code used to clone a repository
*/
#include "config.h"
#include "clone.h"
#include <assert.h>

/*
** If there are public BLOBs that deltas from private BLOBs, then
** undeltify the public BLOBs so that the private BLOBs may be safely
** deleted.
*/
void fix_private_blob_dependencies(int showWarning){
  Bag toUndelta;
  Stmt q;
  int rid;

  /* Careful:  We are about to delete all BLOB entries that are private.
  ** So make sure that any no public BLOBs are deltas from a private BLOB.
  ** Otherwise after the deletion, we won't be able to recreate the public
  ** BLOBs.
  */
  db_prepare(&q,
    "SELECT "
    "   rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
    "   srcid, (SELECT uuid FROM blob WHERE rid=delta.srcid)"
    "  FROM delta"
    " WHERE srcid in private AND rid NOT IN private"
  );
  bag_init(&toUndelta);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char *zId = db_column_text(&q, 1);
    int srcid = db_column_int(&q, 2);
    const char *zSrc = db_column_text(&q, 3);
    if( showWarning ){
      fossil_warning(
        "public artifact %S (%d) is a delta from private artifact %S (%d)",
        zId, rid, zSrc, srcid
      );
    }
    bag_insert(&toUndelta, rid);
  }
  db_finalize(&q);
  while( (rid = bag_first(&toUndelta))>0 ){
    content_undelta(rid);
    bag_remove(&toUndelta, rid);
  }
  bag_clear(&toUndelta);
}

/*
** Delete all private content from a repository.
*/
void delete_private_content(void){
  fix_private_blob_dependencies(1);
  db_multi_exec(
    "DELETE FROM blob WHERE rid IN private;"
    "DELETE FROM delta wHERE rid IN private;"
    "DELETE FROM private;"
  );
}


/*
** COMMAND: clone
**
** Usage: %fossil clone ?OPTIONS? URL FILENAME
**
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))),now());"
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('last-sync-url', '%q',now());",
      g.urlCanonical
    );
    db_multi_exec(
       "DELETE FROM blob WHERE rid IN private;"
       "DELETE FROM delta wHERE rid IN private;"
       "DELETE FROM private;"
    );
    shun_artifacts();
    db_create_default_users(1, zDefaultUser);
    if( zDefaultUser ){
      g.zLogin = zDefaultUser;
    }else{
      g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
    }







<
<
<
|
<







125
126
127
128
129
130
131



132

133
134
135
136
137
138
139
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))),now());"
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('last-sync-url', '%q',now());",
      g.urlCanonical
    );



    if( !bPrivate ) delete_private_content();

    shun_artifacts();
    db_create_default_users(1, zDefaultUser);
    if( zDefaultUser ){
      g.zLogin = zDefaultUser;
    }else{
      g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
    }
Changes to src/configure.c.
31
32
33
34
35
36
37

38
39
40
41
42
43
44
*/
#define CONFIGSET_SKIN      0x000001     /* WWW interface appearance */
#define CONFIGSET_TKT       0x000002     /* Ticket configuration */
#define CONFIGSET_PROJ      0x000004     /* Project name */
#define CONFIGSET_SHUN      0x000008     /* Shun settings */
#define CONFIGSET_USER      0x000010     /* The USER table */
#define CONFIGSET_ADDR      0x000020     /* The CONCEALED table */


#define CONFIGSET_ALL       0x0000ff     /* Everything */

#define CONFIGSET_OVERWRITE 0x100000     /* Causes overwrite instead of merge */
#define CONFIGSET_OLDFORMAT 0x200000     /* Use the legacy format */

#endif /* INTERFACE */







>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
*/
#define CONFIGSET_SKIN      0x000001     /* WWW interface appearance */
#define CONFIGSET_TKT       0x000002     /* Ticket configuration */
#define CONFIGSET_PROJ      0x000004     /* Project name */
#define CONFIGSET_SHUN      0x000008     /* Shun settings */
#define CONFIGSET_USER      0x000010     /* The USER table */
#define CONFIGSET_ADDR      0x000020     /* The CONCEALED table */
#define CONFIGSET_XFER      0x000040     /* Transfer configuration */

#define CONFIGSET_ALL       0x0000ff     /* Everything */

#define CONFIGSET_OVERWRITE 0x100000     /* Causes overwrite instead of merge */
#define CONFIGSET_OLDFORMAT 0x200000     /* Use the legacy format */

#endif /* INTERFACE */
53
54
55
56
57
58
59

60
61
62
63
64
65
66
} aGroupName[] = {
  { "/email",        CONFIGSET_ADDR,  "Concealed email addresses in tickets" },
  { "/project",      CONFIGSET_PROJ,  "Project name and description"         },
  { "/skin",         CONFIGSET_SKIN,  "Web interface apparance settings"     },
  { "/shun",         CONFIGSET_SHUN,  "List of shunned artifacts"            },
  { "/ticket",       CONFIGSET_TKT,   "Ticket setup",                        },
  { "/user",         CONFIGSET_USER,  "Users and privilege settings"         },

  { "/all",          CONFIGSET_ALL,   "All of the above"                     },
};


/*
** The following is a list of settings that we are willing to
** transfer.  







>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
} aGroupName[] = {
  { "/email",        CONFIGSET_ADDR,  "Concealed email addresses in tickets" },
  { "/project",      CONFIGSET_PROJ,  "Project name and description"         },
  { "/skin",         CONFIGSET_SKIN,  "Web interface apparance settings"     },
  { "/shun",         CONFIGSET_SHUN,  "List of shunned artifacts"            },
  { "/ticket",       CONFIGSET_TKT,   "Ticket setup",                        },
  { "/user",         CONFIGSET_USER,  "Users and privilege settings"         },
  { "/xfer",         CONFIGSET_XFER,  "Transfer setup",                      },
  { "/all",          CONFIGSET_ALL,   "All of the above"                     },
};


/*
** The following is a list of settings that we are willing to
** transfer.  
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
  { "manifest",               CONFIGSET_PROJ },
  { "ignore-glob",            CONFIGSET_PROJ },
  { "crnl-glob",              CONFIGSET_PROJ },
  { "empty-dirs",             CONFIGSET_PROJ },
  { "allow-symlinks",         CONFIGSET_PROJ },
  { "index-page",             CONFIGSET_SKIN },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT },
#endif
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },

  { "ticket-newpage",         CONFIGSET_TKT  },
  { "ticket-viewpage",        CONFIGSET_TKT  },
  { "ticket-editpage",        CONFIGSET_TKT  },
  { "ticket-reportlist",      CONFIGSET_TKT  },
  { "ticket-report-template", CONFIGSET_TKT  },
  { "ticket-key-template",    CONFIGSET_TKT  },
  { "ticket-title-expr",      CONFIGSET_TKT  },
  { "ticket-closed-expr",     CONFIGSET_TKT  },
  { "@reportfmt",             CONFIGSET_TKT  },
  { "@user",                  CONFIGSET_USER },
  { "@concealed",             CONFIGSET_ADDR },
  { "@shun",                  CONFIGSET_SHUN },


};
static int iConfig = 0;

/*
** Return name of first configuration property matching the given mask.
*/
const char *configure_first_name(int iMask){







|





>












>
>







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
  { "manifest",               CONFIGSET_PROJ },
  { "ignore-glob",            CONFIGSET_PROJ },
  { "crnl-glob",              CONFIGSET_PROJ },
  { "empty-dirs",             CONFIGSET_PROJ },
  { "allow-symlinks",         CONFIGSET_PROJ },
  { "index-page",             CONFIGSET_SKIN },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
#endif
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },
  { "ticket-change",          CONFIGSET_TKT  },
  { "ticket-newpage",         CONFIGSET_TKT  },
  { "ticket-viewpage",        CONFIGSET_TKT  },
  { "ticket-editpage",        CONFIGSET_TKT  },
  { "ticket-reportlist",      CONFIGSET_TKT  },
  { "ticket-report-template", CONFIGSET_TKT  },
  { "ticket-key-template",    CONFIGSET_TKT  },
  { "ticket-title-expr",      CONFIGSET_TKT  },
  { "ticket-closed-expr",     CONFIGSET_TKT  },
  { "@reportfmt",             CONFIGSET_TKT  },
  { "@user",                  CONFIGSET_USER },
  { "@concealed",             CONFIGSET_ADDR },
  { "@shun",                  CONFIGSET_SHUN },
  { "xfer-common-script",     CONFIGSET_XFER },
  { "xfer-push-script",       CONFIGSET_XFER },
};
static int iConfig = 0;

/*
** Return name of first configuration property matching the given mask.
*/
const char *configure_first_name(int iMask){
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
**
**         Synchronize configuration changes in the local repository with
**         the remote repository at URL.  
**
** Options:
**    -R|--repository FILE       Extract info from repository FILE
**
** See also: set
*/
void configuration_cmd(void){
  int n;
  const char *zMethod;
  if( g.argc<3 ){
    usage("export|import|merge|pull|reset ...");
  }







|







783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
**
**         Synchronize configuration changes in the local repository with
**         the remote repository at URL.  
**
** Options:
**    -R|--repository FILE       Extract info from repository FILE
**
** See also: settings, unset
*/
void configuration_cmd(void){
  int n;
  const char *zMethod;
  if( g.argc<3 ){
    usage("export|import|merge|pull|reset ...");
  }
Changes to src/content.c.
311
312
313
314
315
316
317


318
319
320
321
322
323
324
325
326



327
328
329
330
331
332
333
**
** Extract an artifact by its SHA1 hash and write the results on
** standard output, or if the optional 4th argument is given, in
** the named output file.
**
** Options:
**    -R|--repository FILE       Extract artifacts from repository FILE


*/
void artifact_cmd(void){
  int rid;
  Blob content;
  const char *zFile;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
  if( g.argc!=4 && g.argc!=3 ) usage("ARTIFACT-ID ?FILENAME? ?OPTIONS?");
  zFile = g.argc==4 ? g.argv[3] : "-";
  rid = name_to_rid(g.argv[2]);



  content_get(rid, &content);
  blob_write_to_file(&content, zFile);
}

/*
** COMMAND:  test-content-rawget
**







>
>









>
>
>







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
**
** Extract an artifact by its SHA1 hash and write the results on
** standard output, or if the optional 4th argument is given, in
** the named output file.
**
** Options:
**    -R|--repository FILE       Extract artifacts from repository FILE
**
** See also: finfo
*/
void artifact_cmd(void){
  int rid;
  Blob content;
  const char *zFile;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
  if( g.argc!=4 && g.argc!=3 ) usage("ARTIFACT-ID ?FILENAME? ?OPTIONS?");
  zFile = g.argc==4 ? g.argv[3] : "-";
  rid = name_to_rid(g.argv[2]);
  if( rid==0 ){
    fossil_fatal("%s",g.zErrMsg);
  }
  content_get(rid, &content);
  blob_write_to_file(&content, zFile);
}

/*
** COMMAND:  test-content-rawget
**
Changes to src/cson_amalgamation.c.
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

    
/**
   Type IDs corresponding to JavaScript/JSON types.
*/
enum cson_type_id {
  /**
    The special "null" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */







|







1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

    
/**
   Type IDs corresponding to JavaScript/JSON types.
*/
enum cson_type_id {
  /**
    The special "undefined" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */
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
static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 };
static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 };
static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };









struct cson_string
{
    unsigned int length;
};
#define cson_string_empty_m {0/*length*/}
static const cson_string cson_string_empty = cson_string_empty_m;



#define CSON_CAST(T,V) ((T*)((V)->value))
#define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))




#define CSON_INT(V) ((cson_int_t*)(V)->value)


#define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
#define CSON_STR(V) CSON_CAST(cson_string,(V))
#define CSON_OBJ(V) CSON_CAST(cson_object,(V))
#define CSON_ARRAY(V) CSON_CAST(cson_array,(V))

/**
 







>
>
>
>
>
>
>
>











>
>
>
>
|
>
>







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
static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 };
static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 };
static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };

/**
   Strings are allocated as an instances of this class with N+1
   trailing bytes, where N is the length of the string being
   allocated. To convert a cson_string to c-string we simply increment
   the cson_string pointer. To do the opposite we use (cstr -
   sizeof(cson_string)). Zero-length strings are a special case
   handled by a couple of the cson_string functions.
*/
struct cson_string
{
    unsigned int length;
};
#define cson_string_empty_m {0/*length*/}
static const cson_string cson_string_empty = cson_string_empty_m;



#define CSON_CAST(T,V) ((T*)((V)->value))
#define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))

#if CSON_VOID_PTR_IS_BIG
#  define CSON_INT(V) ((cson_int_t*)(&((V)->value)))
#else
#  define CSON_INT(V) ((cson_int_t*)(V)->value)
#endif

#define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
#define CSON_STR(V) CSON_CAST(cson_string,(V))
#define CSON_OBJ(V) CSON_CAST(cson_object,(V))
#define CSON_ARRAY(V) CSON_CAST(cson_array,(V))

/**
 
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
{ &cson_value_api_undef, NULL, 0 }, /* UNDEF */
{ &cson_value_api_null, NULL, 0 }, /* NULL */
{ &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
{ &cson_value_api_bool, NULL, 0 }, /* FALSE */
{ &cson_value_api_integer, NULL, 0 }, /* INT_0 */
{ &cson_value_api_double, NULL, 0 }, /* DBL_0 */
{ &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
{ 0, NULL, 0 }
};


/**
    Returns non-0 (true) if m is one of our special
    "built-in" values, e.g. from CSON_SPECIAL_VALUES and some
    "empty" values.







|







1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
{ &cson_value_api_undef, NULL, 0 }, /* UNDEF */
{ &cson_value_api_null, NULL, 0 }, /* NULL */
{ &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
{ &cson_value_api_bool, NULL, 0 }, /* FALSE */
{ &cson_value_api_integer, NULL, 0 }, /* INT_0 */
{ &cson_value_api_double, NULL, 0 }, /* DBL_0 */
{ &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
{ NULL, NULL, 0 }
};


/**
    Returns non-0 (true) if m is one of our special
    "built-in" values, e.g. from CSON_SPECIAL_VALUES and some
    "empty" values.
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
/**
   Fetches v's string value as a non-const string.

   cson_strings are supposed to be immutable, but this form provides
   access to the immutable bits, which are v->length bytes long. A
   length-0 string is returned as NULL from here, as opposed to
   "". (This is a side-effect of the string allocation mechanism.)
   Returns NULL if !v.
*/
static char * cson_string_str(cson_string *v)
{
    /*
      See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
    */
#if 1







|







1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
/**
   Fetches v's string value as a non-const string.

   cson_strings are supposed to be immutable, but this form provides
   access to the immutable bits, which are v->length bytes long. A
   length-0 string is returned as NULL from here, as opposed to
   "". (This is a side-effect of the string allocation mechanism.)
   Returns NULL if !v or if v is the internal empty-string singleton.
*/
static char * cson_string_str(cson_string *v)
{
    /*
      See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
    */
#if 1
1946
1947
1948
1949
1950
1951
1952


1953

1954
1955
1956
1957
1958
1959
1960
{
    /*
      See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
    */
#if 1
    if( ! v ) return NULL;
    else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";


    else return (char *)((unsigned char *)(v+1));

#else
    return (NULL == v)
        ? NULL
        : (v->length
           ? (char const *) ((unsigned char const *)(v+1))
           : "");
#endif







>
>
|
>







1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
{
    /*
      See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
    */
#if 1
    if( ! v ) return NULL;
    else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";
    else {
        assert((0 < v->length) && "How do we have a non-singleton empty string?");
        return (char const *)((unsigned char const *)(v+1));
    }
#else
    return (NULL == v)
        ? NULL
        : (v->length
           ? (char const *) ((unsigned char const *)(v+1))
           : "");
#endif
2026
2027
2028
2029
2030
2031
2032



2033
2034
2035
2036
2037
2038
2039
    cson_value * key;
    cson_value * value;
};
#define cson_kvp_empty_m {NULL,NULL}
static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;

/** @def CSON_OBJECT_PROPS_SORT




   If CSON_OBJECT_PROPS_SORT is set to a true value then
   qsort() and bsearch() are used to sort (upon insertion)
   and search cson_object::kvp property lists. This costs us
   a re-sort on each insertion but searching is O(log n)
   average/worst case (and O(1) best-case).








>
>
>







2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
    cson_value * key;
    cson_value * value;
};
#define cson_kvp_empty_m {NULL,NULL}
static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;

/** @def CSON_OBJECT_PROPS_SORT

    Don't use this - it has not been updated to account for internal
    changes in cson_object.

   If CSON_OBJECT_PROPS_SORT is set to a true value then
   qsort() and bsearch() are used to sort (upon insertion)
   and search cson_object::kvp property lists. This costs us
   a re-sort on each insertion but searching is O(log n)
   average/worst case (and O(1) best-case).

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
#  define LIST_T cson_kvp_list
#  define VALUE_T cson_kvp *
#  define VALUE_T_IS_PTR 1
#else
#endif

/**
   Allocates a new value of the specified type ownership of it to the
   caller. It must eventually be destroyed, by the caller or its
   owning container, by passing it to cson_value_free() or transfering
   ownership to a container.

   extra is only valid for type CSON_TYPE_STRING, and must be the length
   of the string to allocate + 1 byte (for the NUL).

   The returned value->api member will be set appropriately and
   val->value will be set to point to the memory allocated to hold the
   native value type. Use the internal CSON_CAST() family of macros to
   convert them.


   Returns NULL on allocation error.

   @see cson_value_new_array()
   @see cson_value_new_object()
   @see cson_value_new_string()
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_free()
*/
static cson_value * cson_value_new(cson_type_id t, size_t extra);

cson_value * cson_value_new(cson_type_id t, size_t extra)
{
    static const size_t vsz = sizeof(cson_value);
    const size_t sz = vsz + extra;
    size_t tx = 0;
    cson_value def = cson_value_undef;
    cson_value * v = NULL;
    char const * reason = "cson_value_new";







|
|
<
|







|
>











|
<
<







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
#  define LIST_T cson_kvp_list
#  define VALUE_T cson_kvp *
#  define VALUE_T_IS_PTR 1
#else
#endif

/**
   Allocates a new value of the specified type. Ownership is
   transfered to the caller, who must eventually free it by passing it

   to cson_value_free() or transfering ownership to a container.

   extra is only valid for type CSON_TYPE_STRING, and must be the length
   of the string to allocate + 1 byte (for the NUL).

   The returned value->api member will be set appropriately and
   val->value will be set to point to the memory allocated to hold the
   native value type. Use the internal CSON_CAST() family of macros to
   convert the cson_values to their corresponding native
   representation.

   Returns NULL on allocation error.

   @see cson_value_new_array()
   @see cson_value_new_object()
   @see cson_value_new_string()
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_free()
*/
static cson_value * cson_value_new(cson_type_id t, size_t extra)


{
    static const size_t vsz = sizeof(cson_value);
    const size_t sz = vsz + extra;
    size_t tx = 0;
    cson_value def = cson_value_undef;
    cson_value * v = NULL;
    char const * reason = "cson_value_new";
2248
2249
2250
2251
2252
2253
2254

2255

2256
2257
2258
2259
2260
2261
2262
          def = cson_value_double_empty;
          tx = sizeof(cson_double_t);
          reason = "cson_value:double";
          break;
      case CSON_TYPE_INTEGER:
          assert( 0 == extra );
          def = cson_value_integer_empty;

          tx = sizeof(cson_int_t);

          reason = "cson_value:int";
          break;
      case CSON_TYPE_STRING:
          assert( 0 != extra );
          def = cson_value_string_empty;
          tx = sizeof(cson_string);
          reason = "cson_value:string";







>

>







2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
          def = cson_value_double_empty;
          tx = sizeof(cson_double_t);
          reason = "cson_value:double";
          break;
      case CSON_TYPE_INTEGER:
          assert( 0 == extra );
          def = cson_value_integer_empty;
#if !CSON_VOID_PTR_IS_BIG
          tx = sizeof(cson_int_t);
#endif
          reason = "cson_value:int";
          break;
      case CSON_TYPE_STRING:
          assert( 0 != extra );
          def = cson_value_string_empty;
          tx = sizeof(cson_string);
          reason = "cson_value:string";
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
            memset(v+1, 0, tx + extra);
            v->value = (void *)(v+1);
        }
    }
    return v;
}


void cson_value_free(cson_value *v)
{
    cson_refcount_decr( v );
}

#if 0 /* we might actually want this later on. */
/** Returns true if v is not NULL and has the given type ID. */







<







2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309
2310
2311
2312
            memset(v+1, 0, tx + extra);
            v->value = (void *)(v+1);
        }
    }
    return v;
}


void cson_value_free(cson_value *v)
{
    cson_refcount_decr( v );
}

#if 0 /* we might actually want this later on. */
/** Returns true if v is not NULL and has the given type ID. */
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}
#endif

char cson_value_is_undef( cson_value const * v )
{
    /**
       This special-case impl is needed because the underlying
       (generic) list operations do not know how to populate
       new entries
     */
    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
        /*return (v && v->api) ? cson_value_is_a(v,CSON_TYPE_##TID) : 0;*/ \
        return (v && (v->api == &cson_value_api_##T)) ? 1 : 0; \
    } static const char bogusPlaceHolderForEmacsIndention##TID = CSON_TYPE_##TID







<
<
<
<
<







2321
2322
2323
2324
2325
2326
2327





2328
2329
2330
2331
2332
2333
2334
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}
#endif

char cson_value_is_undef( cson_value const * v )
{





    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
        /*return (v && v->api) ? cson_value_is_a(v,CSON_TYPE_##TID) : 0;*/ \
        return (v && (v->api == &cson_value_api_##T)) ? 1 : 0; \
    } static const char bogusPlaceHolderForEmacsIndention##TID = CSON_TYPE_##TID
2648
2649
2650
2651
2652
2653
2654

2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
              i = (cson_int_t)d;
              break;
            }
            case CSON_TYPE_STRING:
            case CSON_TYPE_ARRAY:
            case CSON_TYPE_OBJECT:
            default:

              break;
        }
        if(v) *v = i;
        return rc;
    }
}

cson_int_t cson_value_get_integer( cson_value const * val )
{
    cson_int_t i = 0;







>
|

|







2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
              i = (cson_int_t)d;
              break;
            }
            case CSON_TYPE_STRING:
            case CSON_TYPE_ARRAY:
            case CSON_TYPE_OBJECT:
            default:
                rc = cson_rc.TypeError;
                break;
        }
        if(!rc && v) *v = i;
        return rc;
    }
}

cson_int_t cson_value_get_integer( cson_value const * val )
{
    cson_int_t i = 0;
2863
2864
2865
2866
2867
2868
2869
2870


2871
2872
2873
2874
2875
2876
2877

cson_value * cson_value_new_integer( cson_int_t v )
{
    if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
    else
    {
        cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);



        if( c )
        {
            *CSON_INT(c) = v;
        }
        return c;
    }
}







|
>
>







2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894

cson_value * cson_value_new_integer( cson_int_t v )
{
    if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
    else
    {
        cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
        assert( sizeof(cson_int_t) <= sizeof(void *) );
#endif
        if( c )
        {
            *CSON_INT(c) = v;
        }
        return c;
    }
}
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
                cson_value_free( kvp->value );
                cson_refcount_incr( v );
                kvp->value = v;
            }
            return 0;
        }
        if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
        {
            unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
            if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
            {
                return cson_rc.AllocError;
            }
        }
        { /* insert new item... */







|







3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
                cson_value_free( kvp->value );
                cson_refcount_incr( v );
                kvp->value = v;
            }
            return 0;
        }
        if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
        { /* reserve space */
            unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
            if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
            {
                return cson_rc.AllocError;
            }
        }
        { /* insert new item... */
3281
3282
3283
3284
3285
3286
3287


3288
3289
3290
3291
3292
3293
3294
        kvp = cson_kvp_alloc();
        if( ! kvp )
        {
            cson_value_free(val);
            return cson_rc.AllocError;
        }
        kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;


        p->ckey = NULL;
        kvp->value = val;
        cson_refcount_incr( val );
        rc = cson_kvp_list_append( &obj->kvp, kvp );
        if( 0 != rc )
        {
            cson_kvp_free( kvp );







>
>







3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
        kvp = cson_kvp_alloc();
        if( ! kvp )
        {
            cson_value_free(val);
            return cson_rc.AllocError;
        }
        kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
        assert(0 == kvp->key->refcount);
        cson_refcount_incr(kvp->key);
        p->ckey = NULL;
        kvp->value = val;
        cson_refcount_incr( val );
        rc = cson_kvp_list_append( &obj->kvp, kvp );
        if( 0 != rc )
        {
            cson_kvp_free( kvp );
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
      case JSON_T_OBJECT_BEGIN: {
          cson_value * obja = (JSON_T_ARRAY_BEGIN == type)
              ? cson_value_new_array()
              : cson_value_new_object();
          if( ! obja )
          {
              p->errNo = cson_rc.AllocError;
              return 0;
          }
          if( 0 != rc ) break;
          if( ! p->root )
          {
              p->root = p->node = obja;
              rc = cson_array_append( &p->stack, obja );
              if( 0 != rc )







|







3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
      case JSON_T_OBJECT_BEGIN: {
          cson_value * obja = (JSON_T_ARRAY_BEGIN == type)
              ? cson_value_new_array()
              : cson_value_new_object();
          if( ! obja )
          {
              p->errNo = cson_rc.AllocError;
              break;
          }
          if( 0 != rc ) break;
          if( ! p->root )
          {
              p->root = p->node = obja;
              rc = cson_array_append( &p->stack, obja );
              if( 0 != rc )
3384
3385
3386
3387
3388
3389
3390



3391
3392

3393
3394
3395
3396
3397
3398
3399
                      ;
                  ++p->totalValueCount;
              }
          }
          else
          {
              rc = cson_array_append( &p->stack, obja );



              if( 0 == rc ) rc = cson_parser_push_value( p, obja );
              if( 0 == rc ) p->node = obja;

          }
          break;
      }
      case JSON_T_ARRAY_END:
      case JSON_T_OBJECT_END: {
          if( 0 == p->stack.list.count )
          {







>
>
>
|
|
>







3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
                      ;
                  ++p->totalValueCount;
              }
          }
          else
          {
              rc = cson_array_append( &p->stack, obja );
              if(rc) cson_value_free( obja );
              else
              {
                  rc = cson_parser_push_value( p, obja );
                  if( 0 == rc ) p->node = obja;
              }
          }
          break;
      }
      case JSON_T_ARRAY_END:
      case JSON_T_OBJECT_END: {
          if( 0 == p->stack.list.count )
          {
3731
3732
3733
3734
3735
3736
3737
3738

3739

3740
3741
3742
3743
3744
3745
3746
  int c;
  READ_UTF8(z, zTerm, c);
  *pzNext = z;
  return c;
}
#undef READ_UTF8

#if defined(_WIN32)

#  pragma warning( pop )

#endif

unsigned int cson_string_length_utf8( cson_string const * str )
{
    if( ! str ) return 0;
    else
    {







|
>
|
>







3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
  int c;
  READ_UTF8(z, zTerm, c);
  *pzNext = z;
  return c;
}
#undef READ_UTF8

#ifdef _MSC_VER
#  if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
#    pragma warning( pop )
#  endif
#endif

unsigned int cson_string_length_utf8( cson_string const * str )
{
    if( ! str ) return 0;
    else
    {
4576
4577
4578
4579
4580
4581
4582





























4583
4584
4585
4586
4587
4588
4589
cson_value * cson_object_get_sub2( cson_object const * obj, char const * path )
{
    cson_value * v = NULL;
    cson_object_fetch_sub2( obj, &v, path );
    return v;
}






























static cson_value * cson_value_clone_array( cson_value const * orig )
{
    unsigned int i = 0;
    cson_array const * asrc = cson_value_get_array( orig );
    unsigned int alen = cson_array_length_get( asrc );
    cson_value * destV = NULL;
    cson_array * destA = NULL;







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







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
cson_value * cson_object_get_sub2( cson_object const * obj, char const * path )
{
    cson_value * v = NULL;
    cson_object_fetch_sub2( obj, &v, path );
    return v;
}


/**
   If v is-a Object or Array then this function returns a deep
   clone, otherwise it returns v. In either case, the refcount
   of the returned value is increased by 1 by this call.
*/
static cson_value * cson_value_clone_ref( cson_value * v )
{
    cson_value * rc = NULL;
#define TRY_SHARING 1
#if TRY_SHARING
    if(!v ) return rc;
    else if( cson_value_is_object(v)
             || cson_value_is_array(v))
    {
        rc = cson_value_clone( v );
    }
    else
    {
        rc = v;
    }
#else
    rc = cson_value_clone(v);
#endif
#undef TRY_SHARING
    cson_value_add_reference(rc);
    return rc;
}
    
static cson_value * cson_value_clone_array( cson_value const * orig )
{
    unsigned int i = 0;
    cson_array const * asrc = cson_value_get_array( orig );
    unsigned int alen = cson_array_length_get( asrc );
    cson_value * destV = NULL;
    cson_array * destA = NULL;
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
        return NULL;
    }
    for( ; i < alen; ++i )
    {
        cson_value * ch = cson_array_get( asrc, i );
        if( NULL != ch )
        {
            cson_value * cl = cson_value_clone( ch );
            if( NULL == cl )
            {
                cson_value_free( destV );
                return NULL;
            }
            if( 0 != cson_array_set( destA, i, cl ) )
            {
                cson_value_free( cl );
                cson_value_free( destV );
                return NULL;
            }

        }
    }
    return destV;
}

static cson_value * cson_value_clone_object( cson_value const * orig )
{
    cson_object const * src = cson_value_get_object( orig );
    cson_value * destV = NULL;
    cson_object * dest = NULL;
    cson_kvp const * kvp = NULL;
    cson_object_iterator iter = cson_object_iterator_empty;







|











>




|







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
        return NULL;
    }
    for( ; i < alen; ++i )
    {
        cson_value * ch = cson_array_get( asrc, i );
        if( NULL != ch )
        {
            cson_value * cl = cson_value_clone_ref( ch );
            if( NULL == cl )
            {
                cson_value_free( destV );
                return NULL;
            }
            if( 0 != cson_array_set( destA, i, cl ) )
            {
                cson_value_free( cl );
                cson_value_free( destV );
                return NULL;
            }
            cson_value_free(cl)/*remove our artificial reference */;
        }
    }
    return destV;
}
    
static cson_value * cson_value_clone_object( cson_value const * orig )
{
    cson_object const * src = cson_value_get_object( orig );
    cson_value * destV = NULL;
    cson_object * dest = NULL;
    cson_kvp const * kvp = NULL;
    cson_object_iterator iter = cson_object_iterator_empty;
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
    assert( dest );
    if( src->kvp.count > cson_kvp_list_reserve( &dest->kvp, src->kvp.count ) ){
        cson_value_free( destV );
        return NULL;
    }
    while( (kvp = cson_object_iter_next( &iter )) )
    {
        /*
          FIXME: refcount the keys! We first need a setter which takes
          a cson_string or cson_value key type.
         */
        cson_value * key = NULL;
        cson_value * val = NULL;

        key = cson_value_clone(kvp->key);
        val = key ? cson_value_clone( kvp->value ) : NULL;
        if( ! key || !val ){
            cson_value_free(key);
            cson_value_free(val);
            cson_value_free(destV);
            return NULL;

        }
        assert( CSON_STR(key) );
        if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
        {



            cson_value_free(key);
            cson_value_free(val);




            cson_value_free(destV);
            return NULL;
        }

    }
    return destV;
}

cson_value * cson_value_clone( cson_value const * orig )
{
    if( NULL == orig ) return NULL;







<
<
<
<


>
|
|

<
<
<
<
>




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







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
    assert( dest );
    if( src->kvp.count > cson_kvp_list_reserve( &dest->kvp, src->kvp.count ) ){
        cson_value_free( destV );
        return NULL;
    }
    while( (kvp = cson_object_iter_next( &iter )) )
    {




        cson_value * key = NULL;
        cson_value * val = NULL;
        assert( kvp->key && (kvp->key->refcount>0) );
        key = cson_value_clone_ref(kvp->key);
        val = key ? cson_value_clone_ref(kvp->value) : NULL;
        if( ! key || !val ){




            goto error;
        }
        assert( CSON_STR(key) );
        if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
        {
            goto error;
        }
        /* remove our references */
        cson_value_free(key);
        cson_value_free(val);
        continue;
        error:
        cson_value_free(key);
        cson_value_free(val);
        cson_value_free(destV);
        destV = NULL;

        break;
    }
    return destV;
}

cson_value * cson_value_clone( cson_value const * orig )
{
    if( NULL == orig ) return NULL;
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
    if(x) cson_value_free(cson_object_value(x));
}
void cson_free_array(cson_array *x)
{
    if(x) cson_value_free(cson_array_value(x));
}

void cson_free_string(cson_string const *x)
{
    if(x) cson_value_free(cson_string_value(x));
}
void cson_free_value(cson_value *x)
{
    cson_value_free(x);
}


#if 0
/* i'm not happy with this... */
char * cson_pod_to_string( cson_value const * orig )
{







|





|







4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
    if(x) cson_value_free(cson_object_value(x));
}
void cson_free_array(cson_array *x)
{
    if(x) cson_value_free(cson_array_value(x));
}

void cson_free_string(cson_string *x)
{
    if(x) cson_value_free(cson_string_value(x));
}
void cson_free_value(cson_value *x)
{
    if(x) cson_value_free(x);
}


#if 0
/* i'm not happy with this... */
char * cson_pod_to_string( cson_value const * orig )
{
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
          case CSON_TYPE_NULL:
          case CSON_TYPE_BOOL:
              assert( 0 && "Should have been caught by is-builtin check!" );
              break;
          default:
              assert(0 && "Invalid typeID!");
              return 0;

        }
        return rc;
    }
}

int cson_object_merge( cson_object * dest, cson_object const * src, int flags ){
    cson_object_iterator iter = cson_object_iterator_empty;







|







4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
          case CSON_TYPE_NULL:
          case CSON_TYPE_BOOL:
              assert( 0 && "Should have been caught by is-builtin check!" );
              break;
          default:
              assert(0 && "Invalid typeID!");
              return 0;
#undef RCCHECK
        }
        return rc;
    }
}

int cson_object_merge( cson_object * dest, cson_object const * src, int flags ){
    cson_object_iterator iter = cson_object_iterator_empty;
4952
4953
4954
4955
4956
4957
4958

4959
4960
4961
4962

4963
4964
4965
4966


4967
4968

4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
        else continue;
    }
    return 0;
}

static cson_value * cson_guess_arg_type(char const *arg){
    char * end = NULL;

    if(('0'<=*arg) && ('9'>=*arg)){
        goto do_string;
    }
    {

        long const val = strtol(arg, &end, 10);
        if(!*end){
            return cson_value_new_integer( (cson_int_t)val);
        }


    }
    {

        double const val = strtod(arg, &end);
        if(!*end){
            return cson_value_new_double(val);
        }
    }

    
    do_string:
    return cson_value_new_string(arg, strlen(arg));
}


int cson_parse_argv_flags( int argc, char const * const * argv,
                           cson_object ** tgt, unsigned int * count ){







>
|


<
>




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







5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018

5019
5020
5021
5022
5023
5024
5025
5026

5027
5028
5029
5030
5031
5032
5033

5034
5035
5036
5037
5038
5039
5040
        else continue;
    }
    return 0;
}

static cson_value * cson_guess_arg_type(char const *arg){
    char * end = NULL;
    if(!arg || !*arg) return cson_value_null();
    else if(('0'>*arg) || ('9'<*arg)){
        goto do_string;
    }

    else{ /* try numbers... */
        long const val = strtol(arg, &end, 10);
        if(!*end){
            return cson_value_new_integer( (cson_int_t)val);
        }
        else if( '.' != *end ) {
            goto do_string;
        }

        else {
            double const val = strtod(arg, &end);
            if(!*end){
                return cson_value_new_double(val);
            }
        }
    }

    do_string:
    return cson_value_new_string(arg, strlen(arg));
}


int cson_parse_argv_flags( int argc, char const * const * argv,
                           cson_object ** tgt, unsigned int * count ){
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
            break;
        }
        if(!*pos){ /** --key */
            v = cson_value_true();
        }else{ /** --key=...*/
            assert('=' == *pos);
            ++pos /*skip '='*/;
            v = *pos
                ? cson_guess_arg_type(pos)
                : cson_value_null();
        }
        if(0 != (rc=cson_object_set_s(o, k, v))){
            cson_free_string(k);
            cson_value_free(v);
            break;
        }
        else if(count) ++*count;







<
|
<







5061
5062
5063
5064
5065
5066
5067

5068

5069
5070
5071
5072
5073
5074
5075
            break;
        }
        if(!*pos){ /** --key */
            v = cson_value_true();
        }else{ /** --key=...*/
            assert('=' == *pos);
            ++pos /*skip '='*/;

            v = cson_guess_arg_type(pos);

        }
        if(0 != (rc=cson_object_set_s(o, k, v))){
            cson_free_string(k);
            cson_value_free(v);
            break;
        }
        else if(count) ++*count;
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
#define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; }
    if( ! tgt || !st ) return cson_rc.ArgError;
    else
    {
        cson_value * rootV = NULL;
        cson_object * root = NULL;
        cson_value * aryV = NULL;
        cson_array * ary = NULL;
        cson_value * rowsV = NULL;
        cson_array * rows = NULL;
        int rc = 0;
        int const colCount = sqlite3_column_count(st);
        if( colCount <= 0 ) return cson_rc.ArgError;
        rootV = cson_value_new_object();
        if( ! rootV ) return cson_rc.AllocError;







<







5558
5559
5560
5561
5562
5563
5564

5565
5566
5567
5568
5569
5570
5571
#define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; }
    if( ! tgt || !st ) return cson_rc.ArgError;
    else
    {
        cson_value * rootV = NULL;
        cson_object * root = NULL;
        cson_value * aryV = NULL;

        cson_value * rowsV = NULL;
        cson_array * rows = NULL;
        int rc = 0;
        int const colCount = sqlite3_column_count(st);
        if( colCount <= 0 ) return cson_rc.ArgError;
        rootV = cson_value_new_object();
        if( ! rootV ) return cson_rc.AllocError;
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
        rc = cson_object_set( root, "columns", aryV );
        if( rc )
        {
            cson_value_free( aryV );
            RETURN(rc);
        }
        aryV = NULL;
        ary = NULL;
        rowsV = cson_value_new_array();
        if( ! rowsV ) RETURN(cson_rc.AllocError);
        rc = cson_object_set( root, "rows", rowsV );
        if( 0 != rc )
        {
            cson_value_free( rowsV );
            RETURN(rc);







<







5579
5580
5581
5582
5583
5584
5585

5586
5587
5588
5589
5590
5591
5592
        rc = cson_object_set( root, "columns", aryV );
        if( rc )
        {
            cson_value_free( aryV );
            RETURN(rc);
        }
        aryV = NULL;

        rowsV = cson_value_new_array();
        if( ! rowsV ) RETURN(cson_rc.AllocError);
        rc = cson_object_set( root, "rows", rowsV );
        if( 0 != rc )
        {
            cson_value_free( rowsV );
            RETURN(rc);
Changes to src/cson_amalgamation.h.
72
73
74
75
76
77
78




































79
80
81
82
83
84
85
#define CSON_DOUBLE_T_SFMT "Lf"
#define CSON_DOUBLE_T_PFMT "Lf"
#else
typedef double cson_double_t;
#define CSON_DOUBLE_T_SFMT "f"
#define CSON_DOUBLE_T_PFMT "f"
#endif





































/** @def CSON_INT_T_SFMT

scanf()-compatible format token for cson_int_t.
*/

/** @def CSON_INT_T_PFMT







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







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
#define CSON_DOUBLE_T_SFMT "Lf"
#define CSON_DOUBLE_T_PFMT "Lf"
#else
typedef double cson_double_t;
#define CSON_DOUBLE_T_SFMT "f"
#define CSON_DOUBLE_T_PFMT "f"
#endif

/** @def CSON_VOID_PTR_IS_BIG

ONLY define this to a true value if you know that

(sizeof(cson_int_t) <= sizeof(void*))

If that is the case, cson does not need to dynamically
allocate integers. However, enabling this may cause
compilation warnings in 32-bit builds even though the code
being warned about cannot ever be called. To get around such
warnings, when building on a 64-bit environment you can define
this to 1 to get "big" integer support. HOWEVER, all clients must
also use the same value for this macro. If i knew a halfway reliable
way to determine this automatically at preprocessor-time, i would
automate this. We might be able to do halfway reliably by looking
for a large INT_MAX value?
*/
#if !defined(CSON_VOID_PTR_IS_BIG)

/* Largely taken from http://predef.sourceforge.net/prearch.html

See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
*/
#  if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
    || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
    ||  defined(__x86_64__) || defined(__x86_64) \
    || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
    || defined(_M_IA64) \
    || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
    || defined(__64BIT__)
#    define CSON_VOID_PTR_IS_BIG 1
#  else
#    define CSON_VOID_PTR_IS_BIG 0
#  endif
#endif

/** @def CSON_INT_T_SFMT

scanf()-compatible format token for cson_int_t.
*/

/** @def CSON_INT_T_PFMT
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
cson_string * cson_value_get_string( cson_value const * val );

/**
   Returns a pointer to the NULL-terminated string bytes of str.
   The bytes are owned by string and will be invalided when it
   is cleaned up.

   If str is NULL then NULL is returned.


   @see cson_string_length_bytes()
   @see cson_value_get_string()
*/
char const * cson_string_cstr( cson_string const * str );

/**







|
>







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
cson_string * cson_value_get_string( cson_value const * val );

/**
   Returns a pointer to the NULL-terminated string bytes of str.
   The bytes are owned by string and will be invalided when it
   is cleaned up.

   If str is NULL then NULL is returned. If the string has a length
   of 0 then "" is returned.

   @see cson_string_length_bytes()
   @see cson_value_get_string()
*/
char const * cson_string_cstr( cson_string const * str );

/**
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
   Equivalent to cson_value_free(cson_array_value(x)).
*/
void cson_free_array(cson_array *x);

/**
   Equivalent to cson_value_free(cson_string_value(x)).
*/
void cson_free_string(cson_string const *x);


/**
   Allocates a new "array" value and transfers ownership of it to the
   caller. It must eventually be destroyed, by the caller or its
   owning container, by passing it to cson_value_free().








|







1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
   Equivalent to cson_value_free(cson_array_value(x)).
*/
void cson_free_array(cson_array *x);

/**
   Equivalent to cson_value_free(cson_string_value(x)).
*/
void cson_free_string(cson_string *x);


/**
   Allocates a new "array" value and transfers ownership of it to the
   caller. It must eventually be destroyed, by the caller or its
   owning container, by passing it to cson_value_free().

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
int cson_value_refcount_set( cson_value * v, unsigned short rc );
#endif

/**
   Deeply copies a JSON value, be it an object/array or a "plain"
   value (e.g. number/string/boolean). If cv is not NULL then this
   function makes a deep clone of it and returns that clone. Ownership
   of the clone is transfered to the caller, who must eventually free
   the value using cson_value_free() or add it to a container
   object/array to transfer ownership to the container. The returned
   object will be of the same logical type as orig.

   ACHTUNG: if orig contains any cyclic references at any depth level
   this function will endlessly recurse. (Having _any_ cyclic
   references violates this library's requirements.)
   
   Returns NULL if orig is NULL or if cloning fails. Assuming that
   orig is in a valid state, the only "likely" error case is that an
   allocation fails while constructing the clone. In other words, if
   cloning fails due to something other than an allocation error then
   either orig is in an invalid state or there is a bug.


























*/
cson_value * cson_value_clone( cson_value const * orig );

/**
   Returns the value handle associated with s. The handle itself owns
   s, and ownership of the handle is not changed by calling this
   function. If the returned handle is part of a container, calling
   cson_value_free() on the returned handle invoked undefined
   behaviour (quite possibly downstream when the container tries to
   use it).

   This function only returns NULL if s. is NULL.

*/
cson_value * cson_string_value(cson_string const * s);
/**
   The Object form of cson_string_value(). See that function
   for full details.
*/
cson_value * cson_object_value(cson_object const * s);

/**
   The Array form of cson_string_value(). See that function
   for full details.
*/
cson_value * cson_array_value(cson_array const * s);


/**
   Calculates the in-memory-allocated size of v, recursively if it is
   a container type, with the following caveats and limitations:


   If a given value is reference counted and multiple times within a
   traversed container, each reference is counted at full cost. We
   have no what of knowing if a given reference has been visited
   already and whether it should or should not be counted, so we
   pessimistically count them even though the _might_ not really count
   for the given object tree (it depends on where the other open
   references live).

   This function returns 0 if any of the following are true:

   - v is NULL

   - v is one of the special singleton values (null, bools, empty







|
|
|
|










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











|
>
















|
|
>

|
|
|
|
|
|







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
int cson_value_refcount_set( cson_value * v, unsigned short rc );
#endif

/**
   Deeply copies a JSON value, be it an object/array or a "plain"
   value (e.g. number/string/boolean). If cv is not NULL then this
   function makes a deep clone of it and returns that clone. Ownership
   of the clone is identical t transfered to the caller, who must
   eventually free the value using cson_value_free() or add it to a
   container object/array to transfer ownership to the container. The
   returned object will be of the same logical type as orig.

   ACHTUNG: if orig contains any cyclic references at any depth level
   this function will endlessly recurse. (Having _any_ cyclic
   references violates this library's requirements.)
   
   Returns NULL if orig is NULL or if cloning fails. Assuming that
   orig is in a valid state, the only "likely" error case is that an
   allocation fails while constructing the clone. In other words, if
   cloning fails due to something other than an allocation error then
   either orig is in an invalid state or there is a bug.

   When this function clones Objects or Arrays it shares any immutable
   values (including object keys) between the parent and the
   clone. Mutable values (Objects and Arrays) are copied, however.
   For example, if we clone:

   @code
   { a: 1, b: 2, c:["hi"] }
   @endcode

   The cloned object and the array "c" would be a new Object/Array
   instances but the object keys (a,b,b) and the values of (a,b), as
   well as the string value within the "c" array, would be shared
   between the original and the clone. The "c" array itself would be
   deeply cloned, such that future changes to the clone are not
   visible to the parent, and vice versa, but immutable values within
   the array are shared (in this case the string "hi"). The
   justification for this heuristic is that immutable values can never
   be changed, so there is no harm in sharing them across
   clones. Additionally, such types can never contribute to cycles in
   a JSON tree, so they are safe to share this way. Objects and
   Arrays, on the other hand, can be modified later and can contribute
   to cycles, and thus the clone needs to be an independent instance.
   Note, however, that if this function directly passed a
   non-Object/Array, that value is deeply cloned. The sharing
   behaviour only applies when traversing Objects/Arrays.
*/
cson_value * cson_value_clone( cson_value const * orig );

/**
   Returns the value handle associated with s. The handle itself owns
   s, and ownership of the handle is not changed by calling this
   function. If the returned handle is part of a container, calling
   cson_value_free() on the returned handle invoked undefined
   behaviour (quite possibly downstream when the container tries to
   use it).

   This function only returns NULL if s is NULL. The length of the
   returned string is cson_string_length_bytes().
*/
cson_value * cson_string_value(cson_string const * s);
/**
   The Object form of cson_string_value(). See that function
   for full details.
*/
cson_value * cson_object_value(cson_object const * s);

/**
   The Array form of cson_string_value(). See that function
   for full details.
*/
cson_value * cson_array_value(cson_array const * s);


/**
   Calculates the approximate in-memory-allocated size of v,
   recursively if it is a container type, with the following caveats
   and limitations:

   If a given value is reference counted then it is only and multiple
   times within a traversed container, each reference is counted at
   full cost. We have no way of knowing if a given reference has been
   visited already and whether it should or should not be counted, so
   we pessimistically count them even though the _might_ not really
   count for the given object tree (it depends on where the other open
   references live).

   This function returns 0 if any of the following are true:

   - v is NULL

   - v is one of the special singleton values (null, bools, empty
Changes to src/db.c.
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
    fprintf(stderr, "%s: %s\n\n%s", fossil_nameofexe(), z, zRebuildMsg);
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
}






static int nBegin = 0;      /* Nesting depth of BEGIN */
static int doRollback = 0;  /* True to force a rollback */
static int nCommitHook = 0; /* Number of commit hooks */



static struct sCommitHook {
  int (*xHook)(void);  /* Functions to call at db_end_transaction() */
  int sequence;        /* Call functions in sequence order */
} aHook[5];
static Stmt *pAllStmt = 0;  /* List of all unfinalized statements */
static int nPrepare = 0;    /* Number of calls to sqlite3_prepare() */
static int nDeleteOnFail = 0;  /* Number of entries in azDeleteOnFail[] */
static char *azDeleteOnFail[3]; /* Files to delete on a failure */


/*
** Arrange for the given file to be deleted on a failure.
*/
void db_delete_on_failure(const char *zFilename){
  assert( nDeleteOnFail<count(azDeleteOnFail) );
  azDeleteOnFail[nDeleteOnFail++] = fossil_strdup(zFilename);
}

/*
** This routine is called by the SQLite commit-hook mechanism
** just prior to each commit.  All this routine does is verify
** that nBegin really is zero.  That insures that transactions
** cannot commit by any means other than by calling db_end_transaction()
** below.
**
** This is just a safety and sanity check.
*/
static int db_verify_at_commit(void *notUsed){
  if( nBegin ){
    fossil_panic("illegal commit attempt");
    return 1;
  }
  return 0;
}

/*
** Begin and end a nested transaction
*/
void db_begin_transaction(void){
  if( nBegin==0 ){
    db_multi_exec("BEGIN");
    sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
  }
  nBegin++;
}
void db_end_transaction(int rollbackFlag){
  if( g.db==0 ) return;
  if( nBegin<=0 ) return;
  if( rollbackFlag ) doRollback = 1;
  nBegin--;
  if( nBegin==0 ){
    int i;
    if( doRollback==0 ) leaf_do_pending_checks();
    for(i=0; doRollback==0 && i<nCommitHook; i++){
      doRollback |= aHook[i].xHook();
    }
    while( pAllStmt ){
      db_finalize(pAllStmt);
    }
    db_multi_exec(doRollback ? "ROLLBACK" : "COMMIT");
    doRollback = 0;
  }
}

/*
** Force a rollback and shutdown the database
*/
void db_force_rollback(void){
  int i;
  static int busy = 0;
  sqlite3_stmt *pStmt = 0;
  if( busy || g.db==0 ) return;
  busy = 1;
  undo_rollback();
  while( (pStmt = sqlite3_next_stmt(g.db,pStmt))!=0 ){
    sqlite3_reset(pStmt);
  }
  while( pAllStmt ){
    db_finalize(pAllStmt);
  }
  if( nBegin ){
    sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
    nBegin = 0;
  }
  busy = 0;
  db_close(0);
  for(i=0; i<nDeleteOnFail; i++){
    file_delete(azDeleteOnFail[i]);
  }
}

/*
** Install a commit hook.  Hooks are installed in sequence order.
** It is an error to install the same commit hook more than once.
**
** Each commit hook is called (in order of accending sequence) at
** each commit operation.  If any commit hook returns non-zero,
** the subsequence commit hooks are omitted and the transaction
** rolls back rather than commit.  It is the responsibility of the
** hooks themselves to issue any error messages.
*/
void db_commit_hook(int (*x)(void), int sequence){
  int i;
  assert( nCommitHook < sizeof(aHook)/sizeof(aHook[1]) );
  for(i=0; i<nCommitHook; i++){
    assert( x!=aHook[i].xHook );
    if( aHook[i].sequence>sequence ){
      int s = sequence;
      int (*xS)(void) = x;
      sequence = aHook[i].sequence;
      x = aHook[i].xHook;
      aHook[i].sequence = s;
      aHook[i].xHook = xS;
    }
  }
  aHook[nCommitHook].sequence = sequence;
  aHook[nCommitHook].xHook = x;
  nCommitHook++;
}

/*
** Prepare a Stmt.  Assume that the Stmt is previously uninitialized.
** If the input string contains multiple SQL statements, only the first
** one is processed.  All statements beyond the first are silently ignored.
*/
int db_vprepare(Stmt *pStmt, int errOk, const char *zFormat, va_list ap){
  int rc;
  char *zSql;
  blob_zero(&pStmt->sql);
  blob_vappendf(&pStmt->sql, zFormat, ap);
  va_end(ap);
  zSql = blob_str(&pStmt->sql);
  nPrepare++;
  rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0);
  if( rc!=0 && !errOk ){
    db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
  }
  pStmt->pNext = pStmt->pPrev = 0;
  pStmt->nStep = 0;
  return rc;







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





|
|












|










|



|



|
|
|
|

|
|
|

|
|

|
|
















|
|

|

|



|
|















|
|
|
|


|
|
|
|


|
|
|














|







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
    fprintf(stderr, "%s: %s\n\n%s", fossil_nameofexe(), z, zRebuildMsg);
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
}

/*
** All static variable that a used by only this file are gathered into
** the following structure.
*/
static struct DbLocalData {
  int nBegin;               /* Nesting depth of BEGIN */
  int doRollback;           /* True to force a rollback */
  int nCommitHook;          /* Number of commit hooks */
  Stmt *pAllStmt;           /* List of all unfinalized statements */
  int nPrepare;             /* Number of calls to sqlite3_prepare() */
  int nDeleteOnFail;        /* Number of entries in azDeleteOnFail[] */
  struct sCommitHook {
    int (*xHook)(void);         /* Functions to call at db_end_transaction() */
    int sequence;               /* Call functions in sequence order */
  } aHook[5];



  char *azDeleteOnFail[3];  /* Files to delete on a failure */
} db = {0, 0, 0, 0, 0, 0, };

/*
** Arrange for the given file to be deleted on a failure.
*/
void db_delete_on_failure(const char *zFilename){
  assert( db.nDeleteOnFail<count(db.azDeleteOnFail) );
  db.azDeleteOnFail[db.nDeleteOnFail++] = fossil_strdup(zFilename);
}

/*
** This routine is called by the SQLite commit-hook mechanism
** just prior to each commit.  All this routine does is verify
** that nBegin really is zero.  That insures that transactions
** cannot commit by any means other than by calling db_end_transaction()
** below.
**
** This is just a safety and sanity check.
*/
static int db_verify_at_commit(void *notUsed){
  if( db.nBegin ){
    fossil_panic("illegal commit attempt");
    return 1;
  }
  return 0;
}

/*
** Begin and end a nested transaction
*/
void db_begin_transaction(void){
  if( db.nBegin==0 ){
    db_multi_exec("BEGIN");
    sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
  }
  db.nBegin++;
}
void db_end_transaction(int rollbackFlag){
  if( g.db==0 ) return;
  if( db.nBegin<=0 ) return;
  if( rollbackFlag ) db.doRollback = 1;
  db.nBegin--;
  if( db.nBegin==0 ){
    int i;
    if( db.doRollback==0 ) leaf_do_pending_checks();
    for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
      db.doRollback |= db.aHook[i].xHook();
    }
    while( db.pAllStmt ){
      db_finalize(db.pAllStmt);
    }
    db_multi_exec(db.doRollback ? "ROLLBACK" : "COMMIT");
    db.doRollback = 0;
  }
}

/*
** Force a rollback and shutdown the database
*/
void db_force_rollback(void){
  int i;
  static int busy = 0;
  sqlite3_stmt *pStmt = 0;
  if( busy || g.db==0 ) return;
  busy = 1;
  undo_rollback();
  while( (pStmt = sqlite3_next_stmt(g.db,pStmt))!=0 ){
    sqlite3_reset(pStmt);
  }
  while( db.pAllStmt ){
    db_finalize(db.pAllStmt);
  }
  if( db.nBegin ){
    sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
    db.nBegin = 0;
  }
  busy = 0;
  db_close(0);
  for(i=0; i<db.nDeleteOnFail; i++){
    file_delete(db.azDeleteOnFail[i]);
  }
}

/*
** Install a commit hook.  Hooks are installed in sequence order.
** It is an error to install the same commit hook more than once.
**
** Each commit hook is called (in order of accending sequence) at
** each commit operation.  If any commit hook returns non-zero,
** the subsequence commit hooks are omitted and the transaction
** rolls back rather than commit.  It is the responsibility of the
** hooks themselves to issue any error messages.
*/
void db_commit_hook(int (*x)(void), int sequence){
  int i;
  assert( db.nCommitHook < sizeof(db.aHook)/sizeof(db.aHook[1]) );
  for(i=0; i<db.nCommitHook; i++){
    assert( x!=db.aHook[i].xHook );
    if( db.aHook[i].sequence>sequence ){
      int s = sequence;
      int (*xS)(void) = x;
      sequence = db.aHook[i].sequence;
      x = db.aHook[i].xHook;
      db.aHook[i].sequence = s;
      db.aHook[i].xHook = xS;
    }
  }
  db.aHook[db.nCommitHook].sequence = sequence;
  db.aHook[db.nCommitHook].xHook = x;
  db.nCommitHook++;
}

/*
** Prepare a Stmt.  Assume that the Stmt is previously uninitialized.
** If the input string contains multiple SQL statements, only the first
** one is processed.  All statements beyond the first are silently ignored.
*/
int db_vprepare(Stmt *pStmt, int errOk, const char *zFormat, va_list ap){
  int rc;
  char *zSql;
  blob_zero(&pStmt->sql);
  blob_vappendf(&pStmt->sql, zFormat, ap);
  va_end(ap);
  zSql = blob_str(&pStmt->sql);
  db.nPrepare++;
  rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0);
  if( rc!=0 && !errOk ){
    db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
  }
  pStmt->pNext = pStmt->pPrev = 0;
  pStmt->nStep = 0;
  return rc;
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
}
int db_static_prepare(Stmt *pStmt, const char *zFormat, ...){
  int rc = SQLITE_OK;
  if( blob_size(&pStmt->sql)==0 ){
    va_list ap;
    va_start(ap, zFormat);
    rc = db_vprepare(pStmt, 0, zFormat, ap);
    pStmt->pNext = pAllStmt;
    pStmt->pPrev = 0;
    if( pAllStmt ) pAllStmt->pPrev = pStmt;
    pAllStmt = pStmt;
    va_end(ap);
  }
  return rc;
}

/*
** Return the index of a bind parameter







|

|
|







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
}
int db_static_prepare(Stmt *pStmt, const char *zFormat, ...){
  int rc = SQLITE_OK;
  if( blob_size(&pStmt->sql)==0 ){
    va_list ap;
    va_start(ap, zFormat);
    rc = db_vprepare(pStmt, 0, zFormat, ap);
    pStmt->pNext = db.pAllStmt;
    pStmt->pPrev = 0;
    if( db.pAllStmt ) db.pAllStmt->pPrev = pStmt;
    db.pAllStmt = pStmt;
    va_end(ap);
  }
  return rc;
}

/*
** Return the index of a bind parameter
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  db_check_result(rc);
  pStmt->pStmt = 0;
  if( pStmt->pNext ){
    pStmt->pNext->pPrev = pStmt->pPrev;
  }
  if( pStmt->pPrev ){
    pStmt->pPrev->pNext = pStmt->pNext;
  }else if( pAllStmt==pStmt ){
    pAllStmt = pStmt->pNext;
  }
  pStmt->pNext = 0;
  pStmt->pPrev = 0;
  return rc;
}

/*







|
|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  db_check_result(rc);
  pStmt->pStmt = 0;
  if( pStmt->pNext ){
    pStmt->pNext->pPrev = pStmt->pPrev;
  }
  if( pStmt->pPrev ){
    pStmt->pPrev->pNext = pStmt->pNext;
  }else if( db.pAllStmt==pStmt ){
    db.pAllStmt = pStmt->pNext;
  }
  pStmt->pNext = 0;
  pStmt->pPrev = 0;
  return rc;
}

/*
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
** connection.  An error results in process abort.
*/
static sqlite3 *openDatabase(const char *zDbName){
  int rc;
  const char *zVfs;
  sqlite3 *db;

  zVfs = getenv("FOSSIL_VFS");
  rc = sqlite3_open_v2(
       zDbName, &db,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       zVfs
  );
  if( rc!=SQLITE_OK ){
    db_err(sqlite3_errmsg(db));







|







659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
** connection.  An error results in process abort.
*/
static sqlite3 *openDatabase(const char *zDbName){
  int rc;
  const char *zVfs;
  sqlite3 *db;

  zVfs = fossil_getenv("FOSSIL_VFS");
  rc = sqlite3_open_v2(
       zDbName, &db,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       zVfs
  );
  if( rc!=SQLITE_OK ){
    db_err(sqlite3_errmsg(db));
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
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  const char *zHome;
  if( g.configOpen ) return;
#if defined(_WIN32)
  zHome = getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = getenv("HOMEDRIVE");
      zHome = getenv("HOMEPATH");
      if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome);
    }
  }
  if( zHome==0 ){
    fossil_fatal("cannot locate home directory - "
                "please set the LOCALAPPDATA or APPDATA or HOMEPATH "
                "environment variables");
  }
  zHome = fossil_mbcs_to_utf8(zHome);
#else
  zHome = getenv("HOME");
  if( zHome==0 ){
    fossil_fatal("cannot locate home directory - "
                 "please set the HOME environment variable");
  }
#endif
  if( file_isdir(zHome)!=1 ){
    fossil_fatal("invalid home directory: %s", zHome);







|

|

|
|








<

|







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
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  const char *zHome;
  if( g.configOpen ) return;
#if defined(_WIN32)
  zHome = fossil_getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = fossil_getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = fossil_getenv("HOMEDRIVE");
      zHome = fossil_getenv("HOMEPATH");
      if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome);
    }
  }
  if( zHome==0 ){
    fossil_fatal("cannot locate home directory - "
                "please set the LOCALAPPDATA or APPDATA or HOMEPATH "
                "environment variables");
  }

#else
  zHome = fossil_getenv("HOME");
  if( zHome==0 ){
    fossil_fatal("cannot locate home directory - "
                 "please set the HOME environment variable");
  }
#endif
  if( file_isdir(zHome)!=1 ){
    fossil_fatal("invalid home directory: %s", zHome);
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
static int isValidLocalDb(const char *zDbName){
  i64 lsize;

  if( file_access(zDbName, F_OK) ) return 0;
  lsize = file_size(zDbName);
  if( lsize%1024!=0 || lsize<4096 ) return 0;
  db_open_or_attach(zDbName, "localdb");
  g.localOpen = 1;
  db_open_config(0);
  db_open_repository(0);

  /* If the "isexe" column is missing from the vfile table, then
  ** add it now.   This code added on 2010-03-06.  After all users have
  ** upgraded, this code can be safely deleted. 
  */
  if( !db_local_column_exists("vfile", "isexe") )
    db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");


  /* If "islink"/"isLink" columns are missing from tables, then
  ** add them now.   This code added on 2011-01-17 and 2011-08-27.
  ** After all users have upgraded, this code can be safely deleted. 
  */
  if( !db_local_column_exists("vfile", "islink") )
    db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
  

  if( !db_local_column_exists("stashfile", "isLink") &&
       db_local_table_exists("stashfile") )
    db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOLEAN DEFAULT 0");


  if( !db_local_column_exists("undo", "isLink") &&
       db_local_table_exists("undo") )
    db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
  

  if( !db_local_column_exists("undo_vfile", "islink") &&
       db_local_table_exists("undo_vfile") )
    db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOLEAN DEFAULT 0");

  return 1;
}

/*
** Locate the root directory of the local repository tree.  The root
** directory is found by searching for a file named "_FOSSIL_" or ".fos"
** that contains a valid repository database.



**
** If no valid _FOSSIL_ or .fos file is found, we move up one level and 
** try again. Once the file is found, the g.zLocalRoot variable is set
** to the root of the repository tree and this routine returns 1.  If
** no database is found, then this routine return 0.
**
** This routine always opens the user database regardless of whether or
** not the repository database is found.  If the _FOSSIL_ or .fos file
** is found, it is attached to the open database connection too.
*/
int db_open_local(void){
  int i, n;
  char zPwd[2000];
  static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
  
  if( g.localOpen) return 1;
  file_getcwd(zPwd, sizeof(zPwd)-20);
  n = strlen(zPwd);
  if( n==1 && zPwd[0]=='/' ) zPwd[0] = '.';
  while( n>0 ){
    if( file_access(zPwd, W_OK) ) break;
    for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
      sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
      if( isValidLocalDb(zPwd) ){
        /* Found a valid checkout database file */
        zPwd[n] = 0;
        while( n>1 && zPwd[n-1]=='/' ){
          n--;
          zPwd[n] = 0;
        }
        g.zLocalRoot = mprintf("%s/", zPwd);



        return 1;
      }
    }
    n--;
    while( n>0 && zPwd[n]!='/' ){ n--; }
    while( n>0 && zPwd[n-1]=='/' ){ n--; }
    zPwd[n] = 0;
  }

  /* A checkout database file could not be found */
  return 0;
}



















/*
** Open the repository database given by zDbName.  If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
  if( g.repositoryOpen ) return;
  if( zDbName==0 ){
    if( g.localOpen ){
      zDbName = db_lget("repository", 0);
    }
    if( zDbName==0 ){
      db_err("unable to find the name of a repository database");
    }
  }
  if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
    if( file_access(zDbName, 0) ){







<
<
<





|

>





|

|
>

|

|
>

|

|
>

|

|





|

>
>
>













|

















>
>
>












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









|







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
static int isValidLocalDb(const char *zDbName){
  i64 lsize;

  if( file_access(zDbName, F_OK) ) return 0;
  lsize = file_size(zDbName);
  if( lsize%1024!=0 || lsize<4096 ) return 0;
  db_open_or_attach(zDbName, "localdb");




  /* If the "isexe" column is missing from the vfile table, then
  ** add it now.   This code added on 2010-03-06.  After all users have
  ** upgraded, this code can be safely deleted. 
  */
  if( !db_local_column_exists("vfile", "isexe") ){
    db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
  }

  /* If "islink"/"isLink" columns are missing from tables, then
  ** add them now.   This code added on 2011-01-17 and 2011-08-27.
  ** After all users have upgraded, this code can be safely deleted. 
  */
  if( !db_local_column_exists("vfile", "islink") ){
    db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
  }
  
  if( !db_local_column_exists("stashfile", "isLink") &&
       db_local_table_exists("stashfile") ){
    db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOLEAN DEFAULT 0");
  }

  if( !db_local_column_exists("undo", "isLink") &&
       db_local_table_exists("undo") ){
    db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
  }
  
  if( !db_local_column_exists("undo_vfile", "islink") &&
       db_local_table_exists("undo_vfile") ){
    db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
  }
  return 1;
}

/*
** Locate the root directory of the local repository tree.  The root
** directory is found by searching for a file named "_FOSSIL_" or ".fslckout"
** that contains a valid repository database.
**
** For legacy, also look for ".fos".  The use of ".fos" is deprecated
** since "fos" has negative connotations in Hungarian, we are told.
**
** If no valid _FOSSIL_ or .fos file is found, we move up one level and 
** try again. Once the file is found, the g.zLocalRoot variable is set
** to the root of the repository tree and this routine returns 1.  If
** no database is found, then this routine return 0.
**
** This routine always opens the user database regardless of whether or
** not the repository database is found.  If the _FOSSIL_ or .fos file
** is found, it is attached to the open database connection too.
*/
int db_open_local(void){
  int i, n;
  char zPwd[2000];
  static const char *aDbName[] = { "/_FOSSIL_", "/.fslckout", "/.fos" };
  
  if( g.localOpen) return 1;
  file_getcwd(zPwd, sizeof(zPwd)-20);
  n = strlen(zPwd);
  if( n==1 && zPwd[0]=='/' ) zPwd[0] = '.';
  while( n>0 ){
    if( file_access(zPwd, W_OK) ) break;
    for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
      sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
      if( isValidLocalDb(zPwd) ){
        /* Found a valid checkout database file */
        zPwd[n] = 0;
        while( n>1 && zPwd[n-1]=='/' ){
          n--;
          zPwd[n] = 0;
        }
        g.zLocalRoot = mprintf("%s/", zPwd);
        g.localOpen = 1;
        db_open_config(0);
        db_open_repository(0);
        return 1;
      }
    }
    n--;
    while( n>0 && zPwd[n]!='/' ){ n--; }
    while( n>0 && zPwd[n-1]=='/' ){ n--; }
    zPwd[n] = 0;
  }

  /* A checkout database file could not be found */
  return 0;
}

/*
** Get the full pathname to the repository database file.  The
** local database (the _FOSSIL_ or .fslckout database) must have already
** been opened before this routine is called.
*/
const char *db_repository_filename(void){
  static char *zRepo = 0;
  assert( g.localOpen );
  assert( g.zLocalRoot );
  if( zRepo==0 ){
    zRepo = db_lget("repository", 0);
    if( zRepo && !file_is_absolute_path(zRepo) ){
      zRepo = mprintf("%s%s", g.zLocalRoot, zRepo);
    }
  }
  return zRepo;
}

/*
** Open the repository database given by zDbName.  If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
  if( g.repositoryOpen ) return;
  if( zDbName==0 ){
    if( g.localOpen ){
      zDbName = db_repository_filename();
    }
    if( zDbName==0 ){
      db_err("unable to find the name of a repository database");
    }
  }
  if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
    if( file_access(zDbName, 0) ){
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
    zRep = g.argv[nArgUsed];
  }
  if( zRep==0 ){
    if( db_open_local()==0 ){
      goto rep_not_found;
    }
    zRep = db_lget("repository", 0)/*leak here*/;
    if( zRep==0 ){
      goto rep_not_found;
    }
  }
  db_open_repository(zRep);
  if( g.repositoryOpen ){
    if( (bFlags & OPEN_ANY_SCHEMA)==0 ) db_verify_schema();







|







957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
    zRep = g.argv[nArgUsed];
  }
  if( zRep==0 ){
    if( db_open_local()==0 ){
      goto rep_not_found;
    }
    zRep = db_repository_filename();
    if( zRep==0 ){
      goto rep_not_found;
    }
  }
  db_open_repository(zRep);
  if( g.repositoryOpen ){
    if( (bFlags & OPEN_ANY_SCHEMA)==0 ) db_verify_schema();
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
    fprintf(stderr, "-- MEMORY_USED            %10d %10d\n", cur, hiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &cur, &hiwtr, 0);
    fprintf(stderr, "-- MALLOC_SIZE                       %10d\n", hiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &cur, &hiwtr, 0);
    fprintf(stderr, "-- MALLOC_COUNT           %10d %10d\n", cur, hiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0);
    fprintf(stderr, "-- PCACHE_OVFLOW          %10d %10d\n", cur, hiwtr);
    fprintf(stderr, "-- prepared statements    %10d\n", nPrepare);
  }
  while( pAllStmt ){
    db_finalize(pAllStmt);
  }
  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));
    }







|

|
|







1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
    fprintf(stderr, "-- MEMORY_USED            %10d %10d\n", cur, hiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &cur, &hiwtr, 0);
    fprintf(stderr, "-- MALLOC_SIZE                       %10d\n", hiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &cur, &hiwtr, 0);
    fprintf(stderr, "-- MALLOC_COUNT           %10d %10d\n", cur, hiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0);
    fprintf(stderr, "-- PCACHE_OVFLOW          %10d %10d\n", cur, hiwtr);
    fprintf(stderr, "-- prepared statements    %10d\n", db.nPrepare);
  }
  while( db.pAllStmt ){
    db_finalize(db.pAllStmt);
  }
  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));
    }
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
  const char *zUser = zDefaultUser;
  if( zUser==0 ){
    zUser = db_get("default-user", 0);
  }
  if( zUser==0 ){
#if defined(_WIN32)
    zUser = getenv("USERNAME");
#else
    zUser = getenv("USER");
#endif
  }
  if( zUser==0 ){
    zUser = "root";
  }
  db_multi_exec(
     "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser







|

|







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
  const char *zUser = zDefaultUser;
  if( zUser==0 ){
    zUser = db_get("default-user", 0);
  }
  if( zUser==0 ){
#if defined(_WIN32)
    zUser = fossil_getenv("USERNAME");
#else
    zUser = fossil_getenv("USER");
#endif
  }
  if( zUser==0 ){
    zUser = "root";
  }
  db_multi_exec(
     "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
**
** 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_lget("repository", 0);
  }
  file_canonical_name(zName, &full);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)







|







1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
**
** 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);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path);
  db_open_repository(blob_str(&path));
  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_open_local();
  db_lset("repository", blob_str(&path));
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
                  " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
  if( vid==0 ){
    db_lset_int("checkout", 1);
  }else{
    char **oldArgv = g.argv;







|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path);
  db_open_repository(blob_str(&path));
  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
                  " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
  if( vid==0 ){
    db_lset_int("checkout", 1);
  }else{
    char **oldArgv = g.argv;
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
  { 0,0,0,0,0 }
};

/*
** COMMAND: settings
** COMMAND: unset*
**
** %fossil settings ?PROPERTY? ?VALUE? ?-global?
** %fossil unset PROPERTY ?-global?
**
** The "settings" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.
**
** Settings marked as versionable are overridden by the contents of the
** file named .fossil-settings/PROPERTY in the checked out files, if that







|
|







1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
  { 0,0,0,0,0 }
};

/*
** COMMAND: settings
** COMMAND: unset*
**
** %fossil settings ?PROPERTY? ?VALUE? ?OPTIONS?
** %fossil unset PROPERTY ?OPTIONS?
**
** The "settings" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.
**
** Settings marked as versionable are overridden by the contents of the
** file named .fossil-settings/PROPERTY in the checked out files, if that
2005
2006
2007
2008
2009
2010
2011






2012
2013
2014
2015
2016
2017
2018
**                     Tcl interpreter will be able to evaluate TH1 expressions
**                     and scripts.  Default: off.
**
**    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.






*/
void setting_cmd(void){
  int i;
  int globalFlag = find_option("global","g",0)!=0;
  int unsetFlag = g.argv[1][0]=='u';
  db_open_config(1);
  if( !globalFlag ){







>
>
>
>
>
>







2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
**                     Tcl interpreter will be able to evaluate TH1 expressions
**                     and scripts.  Default: off.
**
**    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.
**
** Options:
**   --global   set or unset the given property globally instead of
**              setting or unsetting it for the open repository only.
** 
** See also: configuration
*/
void setting_cmd(void){
  int i;
  int globalFlag = find_option("global","g",0)!=0;
  int unsetFlag = g.argv[1][0]=='u';
  db_open_config(1);
  if( !globalFlag ){
Changes to src/diff.c.
23
24
25
26
27
28
29
30
31
32
33
34






35
36
37
38
39
40
41
#include <assert.h>


#if INTERFACE
/*
** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions:
*/
#define DIFF_CONTEXT_MASK  0x0000fff  /* Lines of context.  Default if 0 */
#define DIFF_WIDTH_MASK    0x00ff000  /* side-by-side column width */
#define DIFF_IGNORE_EOLWS  0x0100000  /* Ignore end-of-line whitespace */
#define DIFF_SIDEBYSIDE    0x0200000  /* Generate a side-by-side diff */
#define DIFF_NEWFILE       0x0400000  /* Missing files are as empty files */







#endif /* INTERFACE */

/*
** Maximum length of a line in a text file.  (8192)
*/
#define LENGTH_MASK_SZ  13







|
|
|
|
|
>
>
>
>
>
>







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
#include <assert.h>


#if INTERFACE
/*
** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions:
*/
#define DIFF_CONTEXT_MASK  0x0000ffff  /* Lines of context.  Default if 0 */
#define DIFF_WIDTH_MASK    0x00ff0000  /* side-by-side column width */
#define DIFF_IGNORE_EOLWS  0x01000000  /* Ignore end-of-line whitespace */
#define DIFF_SIDEBYSIDE    0x02000000  /* Generate a side-by-side diff */
#define DIFF_NEWFILE       0x04000000  /* Missing files are as empty files */
#define DIFF_BRIEF         0x08000000  /* Show filenames only */
#define DIFF_INLINE        0x00000000  /* Inline (not side-by-side) diff */
#define DIFF_HTML          0x10000000  /* Render for HTML */
#define DIFF_LINENO        0x20000000  /* Show line numbers in context diff */
#define DIFF_NOOPT         0x40000000  /* Suppress optimizations for debug */
#define DIFF_INVERT        0x80000000  /* Invert the diff for debug */

#endif /* INTERFACE */

/*
** Maximum length of a line in a text file.  (8192)
*/
#define LENGTH_MASK_SZ  13
57
58
59
60
61
62
63





64










65
66
67
68
69
70
71
  /* an array of DLine elements services two purposes.  The fields
  ** above are one per line of input text.  But each entry is also
  ** a bucket in a hash table, as follows: */
  unsigned int iHash;   /* 1+(first entry in the hash chain) */
};

/*





** A context for running a diff.










*/
typedef struct DContext DContext;
struct DContext {
  int *aEdit;        /* Array of copy/delete/insert triples */
  int nEdit;         /* Number of integers (3x num of triples) in aEdit[] */
  int nEditAlloc;    /* Space allocated for aEdit[] */
  DLine *aFrom;      /* File on left side of the diff */







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







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
  /* an array of DLine elements services two purposes.  The fields
  ** above are one per line of input text.  But each entry is also
  ** a bucket in a hash table, as follows: */
  unsigned int iHash;   /* 1+(first entry in the hash chain) */
};

/*
** Length of a dline
*/
#define LENGTH(X)   ((X)->h & LENGTH_MASK)

/*
** A context for running a raw diff.
**
** The aEdit[] array describes the raw diff.  Each triple of integers in
** aEdit[] means:
**
**   (1) COPY:   Number of lines aFrom and aTo have in common
**   (2) DELETE: Number of lines found only in aFrom
**   (3) INSERT: Number of lines found only in aTo
**
** The triples repeat until all lines of both aFrom and aTo are accounted
** for.
*/
typedef struct DContext DContext;
struct DContext {
  int *aEdit;        /* Array of copy/delete/insert triples */
  int nEdit;         /* Number of integers (3x num of triples) in aEdit[] */
  int nEditAlloc;    /* Space allocated for aEdit[] */
  DLine *aFrom;      /* File on left side of the diff */
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
** Return true if two DLine elements are identical.
*/
static int same_dline(DLine *pA, DLine *pB){
  return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
}

/*
** Append a single line of "diff" output to pOut.
*/
static void appendDiffLine(Blob *pOut, char *zPrefix, DLine *pLine){














  blob_append(pOut, zPrefix, 1);





  blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);

  blob_append(pOut, "\n", 1);
}

/*
** Expand the size of aEdit[] array to hold nEdit elements.
*/
static void expandEdit(DContext *p, int nEdit){
  p->aEdit = fossil_realloc(p->aEdit, nEdit*sizeof(int));
  p->nEditAlloc = nEdit;
}

/*
** Append a new COPY/DELETE/INSERT triple.
*/
static void appendTriple(DContext *p, int nCopy, int nDel, int nIns){
  /* printf("APPEND %d/%d/%d\n", nCopy, nDel, nIns); */
  if( p->nEdit>=3 ){
    if( p->aEdit[p->nEdit-1]==0 ){
      if( p->aEdit[p->nEdit-2]==0 ){
        p->aEdit[p->nEdit-3] += nCopy;
        p->aEdit[p->nEdit-2] += nDel;
        p->aEdit[p->nEdit-1] += nIns;
        return;
      }
      if( nCopy==0 ){
        p->aEdit[p->nEdit-2] += nDel;
        p->aEdit[p->nEdit-1] += nIns;
        return;

      }

    }
    if( nCopy==0 && nDel==0 ){
      p->aEdit[p->nEdit-1] += nIns;
      return;

    }

  }  
  if( p->nEdit+3>p->nEditAlloc ){
    expandEdit(p, p->nEdit*2 + 15);
    if( p->aEdit==0 ) return;
  }
  p->aEdit[p->nEdit++] = nCopy;
  p->aEdit[p->nEdit++] = nDel;
  p->aEdit[p->nEdit++] = nIns;
}


/*
** Given a diff context in which the aEdit[] array has been filled
** in, compute a context diff into pOut.
*/
static void contextDiff(DContext *p, Blob *pOut, int nContext){






  DLine *A;     /* Left side of the diff */
  DLine *B;     /* Right side of the diff */  
  int a = 0;    /* Index of next line in A[] */
  int b = 0;    /* Index of next line in B[] */
  int *R;       /* Array of COPY/DELETE/INSERT triples */
  int r;        /* Index into R[] */
  int nr;       /* Number of COPY/DELETE/INSERT triples to process */
  int mxr;      /* Maximum value for r */
  int na, nb;   /* Number of lines shown from A and B */
  int i, j;     /* Loop counters */
  int m;        /* Number of lines to output */
  int skip;     /* Number of lines to skip */


  A = p->aFrom;
  B = p->aTo;
  R = p->aEdit;
  mxr = p->nEdit;
  while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
  for(r=0; r<mxr; r += 3*nr){







|

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




|
|
|
<
<
<
|
<
<

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







|
>
>
>
>
>
>












>







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
** Return true if two DLine elements are identical.
*/
static int same_dline(DLine *pA, DLine *pB){
  return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
}

/*
** Append a single line of context-diff output to pOut.
*/
static void appendDiffLine(
  Blob *pOut,         /* Where to write the line of output */
  char cPrefix,       /* One of " ", "+",  or "-" */
  DLine *pLine,       /* The line to be output */
  int html            /* True if generating HTML.  False for plain text */
){
  blob_append(pOut, &cPrefix, 1);
  if( html ){
    char *zHtml;
    if( cPrefix=='+' ){
      blob_append(pOut, "<span class=\"diffadd\">", -1);
    }else if( cPrefix=='-' ){
      blob_append(pOut, "<span class=\"diffrm\">", -1);
    }
    zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK));
    blob_append(pOut, zHtml, -1);
    fossil_free(zHtml);
    if( cPrefix!=' ' ){
      blob_append(pOut, "</span>", -1);
    }
  }else{
    blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);
  }
  blob_append(pOut, "\n", 1);
}

/*
** Add two line numbers to the beginning of an output line for a context
** diff.  One or of the other of the two numbers might be zero, which means
** to leave that number field blank.  The "html" parameter means to format



** the output for HTML.  


*/
static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){

  if( html ) blob_append(pOut, "<span class=\"diffln\">", -1);







  if( lnA>0 ){



    blob_appendf(pOut, "%6d ", lnA);
  }else{
    blob_append(pOut, "       ", 7);
  }
  if( lnB>0 ){


    blob_appendf(pOut, "%6d  ", lnB);
  }else{
    blob_append(pOut, "        ", 8);
  }


  if( html ) blob_append(pOut, "</span>", -1);




}


/*
** Given a diff context in which the aEdit[] array has been filled
** in, compute a context diff into pOut.
*/
static void contextDiff(
  DContext *p,      /* The difference */
  Blob *pOut,       /* Output a context diff to here */
  int nContext,     /* Number of lines of context */
  int showLn,       /* Show line numbers */
  int html          /* Render as HTML */
){
  DLine *A;     /* Left side of the diff */
  DLine *B;     /* Right side of the diff */  
  int a = 0;    /* Index of next line in A[] */
  int b = 0;    /* Index of next line in B[] */
  int *R;       /* Array of COPY/DELETE/INSERT triples */
  int r;        /* Index into R[] */
  int nr;       /* Number of COPY/DELETE/INSERT triples to process */
  int mxr;      /* Maximum value for r */
  int na, nb;   /* Number of lines shown from A and B */
  int i, j;     /* Loop counters */
  int m;        /* Number of lines to output */
  int skip;     /* Number of lines to skip */
  int nChunk = 0;  /* Number of diff chunks seen so far */

  A = p->aFrom;
  B = p->aTo;
  R = p->aEdit;
  mxr = p->nEdit;
  while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
  for(r=0; r<mxr; r += 3*nr){
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
      na += R[r+nr*3];
      nb += R[r+nr*3];
    }
    for(i=1; i<nr; i++){
      na += R[r+i*3];
      nb += R[r+i*3];
    }

















    /*
     * If the patch changes an empty file or results in an empty file,
     * the block header must use 0,0 as position indicator and not 1,0.
     * Otherwise, patch would be confused and may reject the diff.
     */
    blob_appendf(pOut,"@@ -%d,%d +%d,%d @@\n",
      na ? a+skip+1 : 0, na,
      nb ? b+skip+1 : 0, nb);




    /* Show the initial common area */
    a += skip;
    b += skip;
    m = R[r] - skip;
    for(j=0; j<m; j++){

      appendDiffLine(pOut, " ", &A[a+j]);
    }
    a += m;
    b += m;

    /* Show the differences */
    for(i=0; i<nr; i++){
      m = R[r+i*3+1];
      for(j=0; j<m; j++){

        appendDiffLine(pOut, "-", &A[a+j]);
      }
      a += m;
      m = R[r+i*3+2];
      for(j=0; j<m; j++){

        appendDiffLine(pOut, "+", &B[b+j]);
      }
      b += m;
      if( i<nr-1 ){
        m = R[r+i*3+3];
        for(j=0; j<m; j++){

          appendDiffLine(pOut, " ", &B[b+j]);
        }
        b += m;
        a += m;
      }
    }

    /* Show the final common area */
    assert( nr==i );
    m = R[r+nr*3];
    if( m>nContext ) m = nContext;
    for(j=0; j<m; j++){

      appendDiffLine(pOut, " ", &B[b+j]);
    }
  }
}

/*
** Write a 6-digit line number into the buffer z[].  z[] is guaranteed to
** have space for at least 7 characters.
*/

static void sbsWriteLineno(char *z, int ln){
  sqlite3_snprintf(7, z, "%6d", ln+1);
  z[6] = ' ';









}






/*
** Write up to width characters of pLine into z[].  Translate tabs into
** spaces.  If trunc is true, then append \n\000 after the last character
** written.
*/
static int sbsWriteText(char *z, DLine *pLine, int width, int trunc){
  int n = pLine->h & LENGTH_MASK;



  int i, j;
  const char *zIn = pLine->z;

  for(i=j=0; i<n && j<width; i++){

    char c = zIn[i];





















    if( c=='\t' ){
      z[j++] = ' ';
      while( (j&7)!=0 && j<width ) z[j++] = ' ';
    }else if( c=='\r' || c=='\f' ){
      z[j++] = ' ';









    }else{
      z[j++] = c;
    }
  }
  if( trunc ){







    z[j++] = '\n';






































































    z[j] = 0;




































































































































































































































  }








  return j;
}











































































































/*
** Given a diff context in which the aEdit[] array has been filled
** in, compute a side-by-side diff into pOut.
*/
static void sbsDiff(DContext *p, Blob *pOut, int nContext, int width){






  DLine *A;     /* Left side of the diff */
  DLine *B;     /* Right side of the diff */  
  int a = 0;    /* Index of next line in A[] */
  int b = 0;    /* Index of next line in B[] */
  int *R;       /* Array of COPY/DELETE/INSERT triples */
  int r;        /* Index into R[] */
  int nr;       /* Number of COPY/DELETE/INSERT triples to process */
  int mxr;      /* Maximum value for r */
  int na, nb;   /* Number of lines shown from A and B */
  int i, j;     /* Loop counters */
  int m, ma, mb;/* Number of lines to output */
  int skip;     /* Number of lines to skip */
  int mxLine;   /* Length of a line of text */
  char *zLine;  /* A line of text being formatted */
  int len;      /* Length of an output line */

  mxLine = width*2 + 2*7 + 3 + 1;
  zLine = fossil_malloc( mxLine + 1 );
  if( zLine==0 ) return;



  zLine[mxLine] = 0;
  A = p->aFrom;
  B = p->aTo;
  R = p->aEdit;
  mxr = p->nEdit;
  while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
  for(r=0; r<mxr; r += 3*nr){
    /* Figure out how many triples to show in a single block */







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






>
|








>
|




>
|





>
|











>
|





|
<

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



|
|

|

>
>
>
|

>
|
>

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


|


>
>
>
>
>
>
>
>
>




|
>
>
>
>
>
>
>

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

>
>
>
>
>
>
>
>
|


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

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




|
>
>
>
>
>
>












|
<
|

<
|
|
>
>
>
|







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
      na += R[r+nr*3];
      nb += R[r+nr*3];
    }
    for(i=1; i<nr; i++){
      na += R[r+i*3];
      nb += R[r+i*3];
    }

    /* Show the header for this block, or if we are doing a modified
    ** context diff that contains line numbers, show the separate from
    ** the previous block.
    */
    nChunk++;
    if( showLn ){
      if( r==0 ){
        /* Do not show a top divider */
      }else if( html ){
        blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
        blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
      }else{
        blob_appendf(pOut, "%.80c\n", '.');
      }
    }else{
      if( html ) blob_appendf(pOut, "<span class=\"diffln\">");
      /*
       * If the patch changes an empty file or results in an empty file,
       * the block header must use 0,0 as position indicator and not 1,0.
       * Otherwise, patch would be confused and may reject the diff.
       */
      blob_appendf(pOut,"@@ -%d,%d +%d,%d @@",
        na ? a+skip+1 : 0, na,
        nb ? b+skip+1 : 0, nb);
      if( html ) blob_appendf(pOut, "</span>");
      blob_append(pOut, "\n", 1);
    }

    /* Show the initial common area */
    a += skip;
    b += skip;
    m = R[r] - skip;
    for(j=0; j<m; j++){
      if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
      appendDiffLine(pOut, ' ', &A[a+j], html);
    }
    a += m;
    b += m;

    /* Show the differences */
    for(i=0; i<nr; i++){
      m = R[r+i*3+1];
      for(j=0; j<m; j++){
        if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html);
        appendDiffLine(pOut, '-', &A[a+j], html);
      }
      a += m;
      m = R[r+i*3+2];
      for(j=0; j<m; j++){
        if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html);
        appendDiffLine(pOut, '+', &B[b+j], html);
      }
      b += m;
      if( i<nr-1 ){
        m = R[r+i*3+3];
        for(j=0; j<m; j++){
          if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
          appendDiffLine(pOut, ' ', &B[b+j], html);
        }
        b += m;
        a += m;
      }
    }

    /* Show the final common area */
    assert( nr==i );
    m = R[r+nr*3];
    if( m>nContext ) m = nContext;
    for(j=0; j<m; j++){
      if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
      appendDiffLine(pOut, ' ', &B[b+j], html);
    }
  }
}

/*
** Status of a single output line

*/
typedef struct SbsLine SbsLine;
struct SbsLine {
  char *zLine;             /* The output line under construction */
  int n;                   /* Index of next unused slot in the zLine[] */
  int width;               /* Maximum width of a column in the output */
  unsigned char escHtml;   /* True to escape html characters */
  int iStart;              /* Write zStart prior to character iStart */
  const char *zStart;      /* A <span> tag */
  int iEnd;                /* Write </span> prior to character iEnd */
  int iStart2;             /* Write zStart2 prior to character iStart2 */
  const char *zStart2;     /* A <span> tag */
  int iEnd2;               /* Write </span> prior to character iEnd2 */
};

/*
** Flags for sbsWriteText()
*/
#define SBS_NEWLINE      0x0001   /* End with \n\000 */
#define SBS_PAD          0x0002   /* Pad output to width spaces */

/*
** Write up to width characters of pLine into z[].  Translate tabs into
** spaces.  Add a newline if SBS_NEWLINE is set.  Translate HTML characters
** if SBS_HTML is set.  Pad the rendering out width bytes if SBS_PAD is set.
*/
static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){
  int n = pLine->h & LENGTH_MASK;
  int i;   /* Number of input characters consumed */
  int j;   /* Number of output characters generated */
  int k;   /* Cursor position */
  int needEndSpan = 0;
  const char *zIn = pLine->z;
  char *z = &p->zLine[p->n];
  int w = p->width;
  for(i=j=k=0; k<w && i<n; i++, k++){
    char c = zIn[i];
    if( p->escHtml ){
      if( i==p->iStart ){
        int x = strlen(p->zStart);
        memcpy(z+j, p->zStart, x);
        j += x;
        needEndSpan = 1;
        if( p->iStart2 ){
          p->iStart = p->iStart2;
          p->zStart = p->zStart2;
          p->iStart2 = 0;
        }
      }else if( i==p->iEnd ){
        memcpy(z+j, "</span>", 7);
        j += 7;
        needEndSpan = 0;
        if( p->iEnd2 ){
          p->iEnd = p->iEnd2;
          p->iEnd2 = 0;
        }
      }
    }
    if( c=='\t' ){
      z[j++] = ' ';
      while( (k&7)!=7 && k<w ){ z[j++] = ' '; k++; }
    }else if( c=='\r' || c=='\f' ){
      z[j++] = ' ';
    }else if( c=='<' && p->escHtml ){
      memcpy(&z[j], "&lt;", 4);
      j += 4;
    }else if( c=='&' && p->escHtml ){
      memcpy(&z[j], "&amp;", 5);
      j += 5;
    }else if( c=='>' && p->escHtml ){
      memcpy(&z[j], "&gt;", 4);
      j += 4;
    }else{
      z[j++] = c;
    }
  }
  if( needEndSpan ){
    memcpy(&z[j], "</span>", 7);
    j += 7;
  }
  if( (flags & SBS_PAD)!=0 ){
    while( k<w ){ k++;  z[j++] = ' '; }
  }
  if( flags & SBS_NEWLINE ){
    z[j++] = '\n';
  }
  p->n += j;
}

/*
** Append a string to an SbSLine with coding, interpretation, or padding.
*/
static void sbsWrite(SbsLine *p, const char *zIn, int nIn){
  memcpy(p->zLine+p->n, zIn, nIn);
  p->n += nIn;
}

/*
** Append n spaces to the string.
*/
static void sbsWriteSpace(SbsLine *p, int n){
  while( n-- ) p->zLine[p->n++] = ' ';
}

/*
** Append a string to the output only if we are rendering HTML.
*/
static void sbsWriteHtml(SbsLine *p, const char *zIn){
  if( p->escHtml ) sbsWrite(p, zIn, strlen(zIn));
}

/*
** Write a 6-digit line number followed by a single space onto the line.
*/
static void sbsWriteLineno(SbsLine *p, int ln){
  sbsWriteHtml(p, "<span class=\"diffln\">");
  sqlite3_snprintf(7, &p->zLine[p->n], "%5d ", ln+1);
  p->n += 6;
  sbsWriteHtml(p, "</span>");
  p->zLine[p->n++] = ' ';
}

/*
** The two text segments zLeft and zRight are known to be different on 
** both ends, but they might have  a common segment in the middle.  If
** they do not have a common segment, return 0.  If they do have a large
** common segment, return 1 and before doing so set:
**
**   aLCS[0] = start of the common segment in zLeft
**   aLCS[1] = end of the common segment in zLeft
**   aLCS[2] = start of the common segment in zLeft
**   aLCS[3] = end of the common segment in zLeft
**
** This computation is for display purposes only and does not have to be
** optimal or exact.
*/
static int textLCS(
  const char *zLeft,  int nA,       /* String on the left */
  const char *zRight,  int nB,      /* String on the right */
  int *aLCS                         /* Identify bounds of LCS here */
){
  const unsigned char *zA = (const unsigned char*)zLeft;    /* left string */
  const unsigned char *zB = (const unsigned char*)zRight;   /* right string */
  int nt;                    /* Number of target points */
  int ti[3];                 /* Index for start of each 4-byte target */
  unsigned int target[3];    /* 4-byte alignment targets */
  unsigned int probe;        /* probe to compare against target */
  int iAS, iAE, iBS, iBE;    /* Range of common segment */
  int i, j;                  /* Loop counters */
  int rc = 0;                /* Result code.  1 for success */

  if( nA<6 || nB<6 ) return 0;
  memset(aLCS, 0, sizeof(int)*4);
  ti[0] = i = nB/2-2;
  target[0] = (zB[i]<<24) | (zB[i+1]<<16) | (zB[i+2]<<8) | zB[i+3];
  probe = 0;
  if( nB<16 ){
    nt = 1;
  }else{
    ti[1] = i = nB/4-2;
    target[1] = (zB[i]<<24) | (zB[i+1]<<16) | (zB[i+2]<<8) | zB[i+3];
    ti[2] = i = (nB*3)/4-2;
    target[2] = (zB[i]<<24) | (zB[i+1]<<16) | (zB[i+2]<<8) | zB[i+3];
    nt = 3;
  }
  probe = (zA[0]<<16) | (zA[1]<<8) | zA[2];
  for(i=3; i<nA; i++){
    probe = (probe<<8) | zA[i];
    for(j=0; j<nt; j++){
      if( probe==target[j] ){
        iAS = i-3;
        iAE = i+1;
        iBS = ti[j];
        iBE = ti[j]+4;
        while( iAE<nA && iBE<nB && zA[iAE]==zB[iBE] ){ iAE++; iBE++; }
        while( iAS>0 && iBS>0 && zA[iAS-1]==zB[iBS-1] ){ iAS--; iBS--; }
        if( iAE-iAS > aLCS[1] - aLCS[0] ){
          aLCS[0] = iAS;
          aLCS[1] = iAE;
          aLCS[2] = iBS;
          aLCS[3] = iBE;
          rc = 1;
        }
      }
    }
  }
  return rc;
}

/*
** Write out lines that have been edited.  Adjust the highlight to cover
** only those parts of the line that actually changed.
*/
static void sbsWriteLineChange(
  SbsLine *p,          /* The SBS output line */
  DLine *pLeft,        /* Left line of the change */
  int lnLeft,          /* Line number for the left line */
  DLine *pRight,       /* Right line of the change */
  int lnRight          /* Line number of the right line */
){
  int nLeft;           /* Length of left line in bytes */
  int nRight;          /* Length of right line in bytes */
  int nPrefix;         /* Length of common prefix */
  int nSuffix;         /* Length of common suffix */
  const char *zLeft;   /* Text of the left line */
  const char *zRight;  /* Text of the right line */
  int nLeftDiff;       /* nLeft - nPrefix - nSuffix */
  int nRightDiff;      /* nRight - nPrefix - nSuffix */
  int aLCS[4];         /* Bounds of common middle segment */
  static const char zClassRm[]   = "<span class=\"diffrm\">";
  static const char zClassAdd[]  = "<span class=\"diffadd\">";
  static const char zClassChng[] = "<span class=\"diffchng\">";

  nLeft = pLeft->h & LENGTH_MASK;
  zLeft = pLeft->z;
  nRight = pRight->h & LENGTH_MASK;
  zRight = pRight->z;

  nPrefix = 0;
  while( nPrefix<nLeft && nPrefix<nRight && zLeft[nPrefix]==zRight[nPrefix] ){
    nPrefix++;
  }
  nSuffix = 0;
  if( nPrefix<nLeft && nPrefix<nRight ){
    while( nSuffix<nLeft && nSuffix<nRight
           && zLeft[nLeft-nSuffix-1]==zRight[nRight-nSuffix-1] ){
      nSuffix++;
    }
    if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0;
  }
  if( nPrefix+nSuffix > nLeft ) nSuffix = nLeft - nPrefix;
  if( nPrefix+nSuffix > nRight ) nSuffix = nRight - nPrefix;

  /* A single chunk of text inserted on the right */
  if( nPrefix+nSuffix==nLeft ){
    sbsWriteLineno(p, lnLeft);
    p->iStart2 = p->iEnd2 = 0;
    p->iStart = p->iEnd = -1;
    sbsWriteText(p, pLeft, SBS_PAD);
    sbsWrite(p, " | ", 3);
    sbsWriteLineno(p, lnRight);
    p->iStart = nPrefix;
    p->iEnd = nRight - nSuffix;
    p->zStart = zClassAdd;
    sbsWriteText(p, pRight, SBS_NEWLINE);
    return;
  }

  /* A single chunk of text deleted from the left */
  if( nPrefix+nSuffix==nRight ){
    /* Text deleted from the left */
    sbsWriteLineno(p, lnLeft);
    p->iStart2 = p->iEnd2 = 0;
    p->iStart = nPrefix;
    p->iEnd = nLeft - nSuffix;
    p->zStart = zClassRm;
    sbsWriteText(p, pLeft, SBS_PAD);
    sbsWrite(p, " | ", 3);
    sbsWriteLineno(p, lnRight);
    p->iStart = p->iEnd = -1;
    sbsWriteText(p, pRight, SBS_NEWLINE);
    return;
  }

  /* At this point we know that there is a chunk of text that has
  ** changed between the left and the right.  Check to see if there
  ** is a large unchanged section in the middle of that changed block.
  */
  nLeftDiff = nLeft - nSuffix - nPrefix;
  nRightDiff = nRight - nSuffix - nPrefix;
  if( p->escHtml
   && nLeftDiff >= 6
   && nRightDiff >= 6
   && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS)
  ){
    sbsWriteLineno(p, lnLeft);
    p->iStart = nPrefix;
    p->iEnd = nPrefix + aLCS[0];
    p->zStart = aLCS[2]==0 ? zClassRm : zClassChng;
    p->iStart2 = nPrefix + aLCS[1];
    p->iEnd2 = nLeft - nSuffix;
    p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng;
    if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
    if( p->iStart==p->iEnd ){
      p->iStart = p->iStart2;
      p->iEnd = p->iEnd2;
      p->zStart = p->zStart2;
      p->iStart2 = 0;
      p->iEnd2 = 0;
    }
    if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
    sbsWriteText(p, pLeft, SBS_PAD);
    sbsWrite(p, " | ", 3);
    sbsWriteLineno(p, lnRight);
    p->iStart = nPrefix;
    p->iEnd = nPrefix + aLCS[2];
    p->zStart = aLCS[0]==0 ? zClassAdd : zClassChng;
    p->iStart2 = nPrefix + aLCS[3];
    p->iEnd2 = nRight - nSuffix;
    p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng;
    if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
    if( p->iStart==p->iEnd ){
      p->iStart = p->iStart2;
      p->iEnd = p->iEnd2;
      p->zStart = p->zStart2;
      p->iStart2 = 0;
      p->iEnd2 = 0;
    }
    if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; 
    sbsWriteText(p, pRight, SBS_NEWLINE);
    return;
  }

  /* If all else fails, show a single big change between left and right */
  sbsWriteLineno(p, lnLeft);
  p->iStart2 = p->iEnd2 = 0;
  p->iStart = nPrefix;
  p->iEnd = nLeft - nSuffix;
  p->zStart = zClassChng;
  sbsWriteText(p, pLeft, SBS_PAD);
  sbsWrite(p, " | ", 3);
  sbsWriteLineno(p, lnRight);
  p->iEnd = nRight - nSuffix;
  sbsWriteText(p, pRight, SBS_NEWLINE);
}

/*
** Minimum of two values
*/
static int minInt(int a, int b){ return a<b ? a : b; }

/*
** Return the number between 0 and 100 that is smaller the closer pA and
** pB match.  Return 0 for a perfect match.  Return 100 if pA and pB are
** completely different.
**
** The current algorithm is as follows:
**
** (1) Remove leading and trailing whitespace.
** (2) Truncate both strings to at most 250 characters
** (3) Find the length of the longest common subsequence
** (4) Longer common subsequences yield lower scores.
*/
static int match_dline(DLine *pA, DLine *pB){
  const char *zA;            /* Left string */
  const char *zB;            /* right string */
  int nA;                    /* Bytes in zA[] */
  int nB;                    /* Bytes in zB[] */
  int avg;                   /* Average length of A and B */
  int i, j, k;               /* Loop counters */
  int best = 0;              /* Longest match found so far */
  int score;                 /* Final score.  0..100 */
  unsigned char c;           /* Character being examined */
  unsigned char aFirst[256]; /* aFirst[X] = index in zB[] of first char X */
  unsigned char aNext[252];  /* aNext[i] = index in zB[] of next zB[i] char */

  zA = pA->z;
  zB = pB->z;
  nA = pA->h & LENGTH_MASK;
  nB = pB->h & LENGTH_MASK;
  while( nA>0 && fossil_isspace(zA[0]) ){ nA--; zA++; }
  while( nA>0 && fossil_isspace(zA[nA-1]) ){ nA--; }
  while( nB>0 && fossil_isspace(zB[0]) ){ nB--; zB++; }
  while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
  if( nA>250 ) nA = 250;
  if( nB>250 ) nB = 250;
  avg = (nA+nB)/2;
  if( avg==0 ) return 0;
  if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
  memset(aFirst, 0, sizeof(aFirst));
  zA--; zB--;   /* Make both zA[] and zB[] 1-indexed */
  for(i=nB; i>0; i--){
    c = (unsigned char)zB[i];
    aNext[i] = aFirst[c];
    aFirst[c] = i;
  }
  best = 0;
  for(i=1; i<=nA-best; i++){
    c = (unsigned char)zA[i];
    for(j=aFirst[c]; j>0 && j<nB-best; j = aNext[j]){
      int limit = minInt(nA-i, nB-j);
      for(k=1; k<=limit && zA[k+i]==zB[k+j]; k++){}
      if( k>best ) best = k;
    }
  }
  score = (best>avg) ? 0 : (avg - best)*100/avg;

#if 0
  fprintf(stderr, "A: [%.*s]\nB: [%.*s]\nbest=%d avg=%d score=%d\n",
  nA, zA+1, nB, zB+1, best, avg, score);
#endif

  /* Return the result */
  return score;
}

/*
** There is a change block in which nLeft lines of text on the left are
** converted into nRight lines of text on the right.  This routine computes
** how the lines on the left line up with the lines on the right.
**
** The return value is a buffer of unsigned characters, obtained from
** fossil_malloc().  (The caller needs to free the return value using
** fossil_free().)  Entries in the returned array have values as follows:
**
**    1.   Delete the next line of pLeft.
**    2.   The next line of pLeft changes into the next line of pRight.
**    3.   Insert the next line of pRight.
**
** The length of the returned array will be just large enough to cause
** all elements of pLeft and pRight to be consumed.
**
** Algorithm:  Wagner's minimum edit-distance algorithm, modified by
** adding a cost to each match based on how well the two rows match
** each other.  Insertion and deletion costs are 50.  Match costs
** are between 0 and 100 where 0 is a perfect match 100 is a complete
** mismatch.
*/
static unsigned char *sbsAlignment(
   DLine *aLeft, int nLeft,       /* Text on the left */
   DLine *aRight, int nRight      /* Text on the right */
){
  int i, j, k;                 /* Loop counters */
  int *a;                      /* One row of the Wagner matrix */
  int *pToFree;                /* Space that needs to be freed */
  unsigned char *aM;           /* Wagner result matrix */
  int aBuf[100];               /* Stack space for a[] if nRight not to big */

  aM = fossil_malloc( (nLeft+1)*(nRight+1) );
  if( nLeft==0 ){
    memset(aM, 3, nRight);
    return aM;
  }
  if( nRight==0 ){
    memset(aM, 1, nLeft);
    return aM;
  }
  if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
    pToFree = 0;
    a = aBuf;
  }else{
    a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
  }

  /* Compute the best alignment */
  for(i=0; i<=nRight; i++){
    aM[i] = 3;
    a[i] = i*50;
  }
  aM[0] = 0;
  for(j=1; j<=nLeft; j++){
    int p = a[0];
    a[0] = p+50;
    aM[j*(nRight+1)] = 1;
    for(i=1; i<=nRight; i++){
      int m = a[i-1]+50;
      int d = 3;
      if( m>a[i]+50 ){
        m = a[i]+50;
        d = 1;
      }
      if( m>p ){
        int score = match_dline(&aLeft[j-1], &aRight[i-1]);
        if( (score<66 || (i<j+1 && i>j-1)) && m>p+score ){
          m = p+score;
          d = 2;
        }
      }
      p = a[i];
      a[i] = m;
      aM[j*(nRight+1)+i] = d;
    }
  }

  /* Compute the lowest-cost path back through the matrix */
  i = nRight;
  j = nLeft;
  k = (nRight+1)*(nLeft+1)-1;
  while( i+j>0 ){
    unsigned char c = aM[k--];
    if( c==2 ){
      assert( i>0 && j>0 );
      i--;
      j--;
    }else if( c==3 ){
      assert( i>0 );
      i--;
    }else{
      assert( j>0 );
      j--;
    }
    aM[k] = aM[j*(nRight+1)+i];
  }
  k++;
  i = (nRight+1)*(nLeft+1) - k;
  memmove(aM, &aM[k], i);

  /* Return the result */
  fossil_free(pToFree);
  return aM;
}

/*
** Given a diff context in which the aEdit[] array has been filled
** in, compute a side-by-side diff into pOut.
*/
static void sbsDiff(
  DContext *p,       /* The computed diff */
  Blob *pOut,        /* Write the results here */
  int nContext,      /* Number of lines of context around each change */
  int width,         /* Width of each column of output */
  int escHtml        /* True to generate HTML output */
){
  DLine *A;     /* Left side of the diff */
  DLine *B;     /* Right side of the diff */  
  int a = 0;    /* Index of next line in A[] */
  int b = 0;    /* Index of next line in B[] */
  int *R;       /* Array of COPY/DELETE/INSERT triples */
  int r;        /* Index into R[] */
  int nr;       /* Number of COPY/DELETE/INSERT triples to process */
  int mxr;      /* Maximum value for r */
  int na, nb;   /* Number of lines shown from A and B */
  int i, j;     /* Loop counters */
  int m, ma, mb;/* Number of lines to output */
  int skip;     /* Number of lines to skip */
  int nChunk = 0; /* Number of chunks of diff output seen so far */

  SbsLine s;    /* Output line buffer */


  s.zLine = fossil_malloc( 10*width + 200 );
  if( s.zLine==0 ) return;
  s.width = width;
  s.escHtml = escHtml;
  s.iStart = -1;
  s.iEnd = -1;
  A = p->aFrom;
  B = p->aTo;
  R = p->aEdit;
  mxr = p->nEdit;
  while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
  for(r=0; r<mxr; r += 3*nr){
    /* Figure out how many triples to show in a single block */
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
      na += R[r+nr*3];
      nb += R[r+nr*3];
    }
    for(i=1; i<nr; i++){
      na += R[r+i*3];
      nb += R[r+i*3];
    }
    /*
     * If the patch changes an empty file or results in an empty file,
     * the block header must use 0,0 as position indicator and not 1,0.
     * Otherwise, patch would be confused and may reject the diff.

     */

    if( r>0 ) blob_appendf(pOut,"%.*c\n", width*2+16, '.');







    /* Show the initial common area */
    a += skip;
    b += skip;
    m = R[r] - skip;
    for(j=0; j<m; j++){
      memset(zLine, ' ', mxLine);
      sbsWriteLineno(zLine, a+j);

      sbsWriteText(&zLine[7], &A[a+j], width, 0);

      sbsWriteLineno(&zLine[width+10], b+j);
      len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1);
      blob_append(pOut, zLine, len+width+17);
    }
    a += m;
    b += m;

    /* Show the differences */
    for(i=0; i<nr; i++){

      ma = R[r+i*3+1];
      mb = R[r+i*3+2];
      m = ma<mb ? ma : mb;

      for(j=0; j<m; j++){
        memset(zLine, ' ', mxLine);


        sbsWriteLineno(zLine, a+j);
        sbsWriteText(&zLine[7], &A[a+j], width, 0);
        zLine[width+8] = '|';

        sbsWriteLineno(&zLine[width+10], b+j);
        len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1);

        blob_append(pOut, zLine, len+width+17);
      }
      a += m;

      b += m;

      ma -= m;




      mb -= m;
      for(j=0; j<ma; j++){



        memset(zLine, ' ', width+7);

        sbsWriteLineno(zLine, a+j);
        sbsWriteText(&zLine[7], &A[a+j], width, 0);
        zLine[width+8] = '<';
        zLine[width+9] = '\n';
        zLine[width+10] = 0;

        blob_append(pOut, zLine, width+10);



      }
      a += ma;
      for(j=0; j<mb; j++){
        memset(zLine, ' ', mxLine);
        zLine[width+8] = '>';
        sbsWriteLineno(&zLine[width+10], b+j);
        len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1);
        blob_append(pOut, zLine, len+width+17);
      }
      b += mb;

      if( i<nr-1 ){
        m = R[r+i*3+3];
        for(j=0; j<m; j++){
          memset(zLine, ' ', mxLine);
          sbsWriteLineno(zLine, a+j);

          sbsWriteText(&zLine[7], &A[a+j], width, 0);

          sbsWriteLineno(&zLine[width+10], b+j);
          len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1);
          blob_append(pOut, zLine, len+width+17);
        }
        b += m;
        a += m;
      }
    }

    /* Show the final common area */
    assert( nr==i );
    m = R[r+nr*3];
    if( m>nContext ) m = nContext;
    for(j=0; j<m; j++){
      memset(zLine, ' ', mxLine);
      sbsWriteLineno(zLine, a+j);

      sbsWriteText(&zLine[7], &A[a+j], width, 0);

      sbsWriteLineno(&zLine[width+10], b+j);
      len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1);
      blob_append(pOut, zLine, len+width+17);
    }
  }
  free(zLine);
}

/*
** Compute the optimal longest common subsequence (LCS) using an
** exhaustive search.  This version of the LCS is only used for
** shorter input strings since runtime is O(N*N) where N is the
** input string length.







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






|
|
>
|
>
|
|
|






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

<
>



|
|
>
|
>
|
|
|











|
|
>
|
>
|
|
|


|







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
      na += R[r+nr*3];
      nb += R[r+nr*3];
    }
    for(i=1; i<nr; i++){
      na += R[r+i*3];
      nb += R[r+i*3];
    }

    /* Draw the separator between blocks */
    if( r>0 ){
      if( escHtml ){
        blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n",
                           width*2+16, '.');
      }else{
        blob_appendf(pOut, "%.*c\n", width*2+16, '.');
      }
    }
    nChunk++;
    if( escHtml ){
      blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
    }

    /* Show the initial common area */
    a += skip;
    b += skip;
    m = R[r] - skip;
    for(j=0; j<m; j++){
      s.n = 0;
      sbsWriteLineno(&s, a+j);
      s.iStart = s.iEnd = -1;
      sbsWriteText(&s, &A[a+j], SBS_PAD);
      sbsWrite(&s, "   ", 3);
      sbsWriteLineno(&s, b+j);
      sbsWriteText(&s, &B[b+j], SBS_NEWLINE);
      blob_append(pOut, s.zLine, s.n);
    }
    a += m;
    b += m;

    /* Show the differences */
    for(i=0; i<nr; i++){
      unsigned char *alignment;
      ma = R[r+i*3+1];   /* Lines on left but not on right */
      mb = R[r+i*3+2];   /* Lines on right but not on left */

      alignment = sbsAlignment(&A[a], ma, &B[b], mb);
      for(j=0; ma+mb>0; j++){

        if( alignment[j]==1 ){
          s.n = 0;
          sbsWriteLineno(&s, a);

          s.iStart = 0;
          s.zStart = "<span class=\"diffrm\">";
          s.iEnd = s.width;
          sbsWriteText(&s, &A[a], SBS_PAD);
          sbsWrite(&s, " <\n", 3);
          blob_append(pOut, s.zLine, s.n);

          assert( ma>0 );
          ma--;
          a++;
        }else if( alignment[j]==2 ){
          s.n = 0;
          sbsWriteLineChange(&s, &A[a], a, &B[b], b);
          blob_append(pOut, s.zLine, s.n);
          assert( ma>0 && mb>0 );
          ma--;
          mb--;
          a++;
          b++;
        }else{
          s.n = 0;
          sbsWriteSpace(&s, width + 7);
          sbsWrite(&s, " > ", 3);
          sbsWriteLineno(&s, b);

          s.iStart = 0;
          s.zStart = "<span class=\"diffadd\">";
          s.iEnd = s.width;
          sbsWriteText(&s, &B[b], SBS_NEWLINE);
          blob_append(pOut, s.zLine, s.n);
          assert( mb>0 );
          mb--;
          b++;
        }







      }

      fossil_free(alignment);
      if( i<nr-1 ){
        m = R[r+i*3+3];
        for(j=0; j<m; j++){
          s.n = 0;
          sbsWriteLineno(&s, a+j);
          s.iStart = s.iEnd = -1;
          sbsWriteText(&s, &A[a+j], SBS_PAD);
          sbsWrite(&s, "   ", 3);
          sbsWriteLineno(&s, b+j);
          sbsWriteText(&s, &B[b+j], SBS_NEWLINE);
          blob_append(pOut, s.zLine, s.n);
        }
        b += m;
        a += m;
      }
    }

    /* Show the final common area */
    assert( nr==i );
    m = R[r+nr*3];
    if( m>nContext ) m = nContext;
    for(j=0; j<m; j++){
      s.n = 0;
      sbsWriteLineno(&s, a+j);
      s.iStart = s.iEnd = -1;
      sbsWriteText(&s, &A[a+j], SBS_PAD);
      sbsWrite(&s, "   ", 3);
      sbsWriteLineno(&s, b+j);
      sbsWriteText(&s, &B[b+j], SBS_NEWLINE);
      blob_append(pOut, s.zLine, s.n);
    }
  }
  free(s.zLine);
}

/*
** Compute the optimal longest common subsequence (LCS) using an
** exhaustive search.  This version of the LCS is only used for
** shorter input strings since runtime is O(N*N) where N is the
** input string length.
550
551
552
553
554
555
556

557

558
559
560
561
562
563
564
  DContext *p,               /* Two files being compared */
  int iS1, int iE1,          /* Range of lines in p->aFrom[] */
  int iS2, int iE2,          /* Range of lines in p->aTo[] */
  int *piSX, int *piEX,      /* Write p->aFrom[] common segment here */
  int *piSY, int *piEY       /* Write p->aTo[] common segment here */
){
  double bestScore = -1e30;  /* Best score seen so far */

  int i, j;                  /* Loop counters */

  int iSX, iSY, iEX, iEY;    /* Current match */
  double score;              /* Current score */
  int skew;                  /* How lopsided is the match */
  int dist;                  /* Distance of match from center */
  int mid;                   /* Center of the span */
  int iSXb, iSYb, iEXb, iEYb;   /* Best match so far */
  int iSXp, iSYp, iEXp, iEYp;   /* Previous match */







>
|
>







1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  DContext *p,               /* Two files being compared */
  int iS1, int iE1,          /* Range of lines in p->aFrom[] */
  int iS2, int iE2,          /* Range of lines in p->aTo[] */
  int *piSX, int *piEX,      /* Write p->aFrom[] common segment here */
  int *piSY, int *piEY       /* Write p->aTo[] common segment here */
){
  double bestScore = -1e30;  /* Best score seen so far */
  int i, j, k;               /* Loop counters */
  int n;                     /* Loop limit */
  DLine *pA, *pB;            /* Pointers to lines */
  int iSX, iSY, iEX, iEY;    /* Current match */
  double score;              /* Current score */
  int skew;                  /* How lopsided is the match */
  int dist;                  /* Distance of match from center */
  int mid;                   /* Center of the span */
  int iSXb, iSYb, iEXb, iEYb;   /* Best match so far */
  int iSXp, iSYp, iEXp, iEYp;   /* Previous match */
583
584
585
586
587
588
589
590



591
592
593
594
595
596



597
598
599
600
601
602
603
604
605
606
    }
    if( j==0 ) continue;
    assert( i>=iSXb && i>=iSXp );
    if( i<iEXb && j>=iSYb && j<iEYb ) continue;
    if( i<iEXp && j>=iSYp && j<iEYp ) continue;
    iSX = i;
    iSY = j-1;
    while( iSX>iS1 && iSY>iS2 && same_dline(&p->aFrom[iSX-1],&p->aTo[iSY-1]) ){



      iSX--;
      iSY--;
    }
    iEX = i+1;
    iEY = j;
    while( iEX<iE1 && iEY<iE2 && same_dline(&p->aFrom[iEX],&p->aTo[iEY]) ){



      iEX++;
      iEY++;
    }
    skew = (iSX-iS1) - (iSY-iS2);
    if( skew<0 ) skew = -skew;
    dist = (iSX+iEX)/2 - mid;
    if( dist<0 ) dist = -dist;
    score = (iEX - iSX) - 0.05*skew - 0.05*dist;
    if( score>bestScore ){
      bestScore = score;







|
>
>
>
|
|
<


|
>
>
>
|
|
<







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
    }
    if( j==0 ) continue;
    assert( i>=iSXb && i>=iSXp );
    if( i<iEXb && j>=iSYb && j<iEYb ) continue;
    if( i<iEXp && j>=iSYp && j<iEYp ) continue;
    iSX = i;
    iSY = j-1;
    pA = &p->aFrom[iSX-1];
    pB = &p->aTo[iSY-1];
    n = minInt(iSX-iS1, iSY-iS2);
    for(k=0; k<n && same_dline(pA,pB); k++, pA--, pB--){}
    iSX -= k;
    iSY -= k;

    iEX = i+1;
    iEY = j;
    pA = &p->aFrom[iEX];
    pB = &p->aTo[iEY];
    n = minInt(iE1-iEX, iE2-iEY);
    for(k=0; k<n && same_dline(pA,pB); k++, pA++, pB++){}
    iEX += k;
    iEY += k;

    skew = (iSX-iS1) - (iSY-iS2);
    if( skew<0 ) skew = -skew;
    dist = (iSX+iEX)/2 - mid;
    if( dist<0 ) dist = -dist;
    score = (iEX - iSX) - 0.05*skew - 0.05*dist;
    if( score>bestScore ){
      bestScore = score;
624
625
626
627
628
629
630









































631
632
633
634
635
636
637
    *piSY = iSYb;
    *piEX = iEXb;
    *piEY = iEYb;
  }
  /* printf("LCS(%d..%d/%d..%d) = %d..%d/%d..%d\n", 
     iS1, iE1, iS2, iE2, *piSX, *piEX, *piSY, *piEY);  */
}










































/*
** Do a single step in the difference.  Compute a sequence of
** copy/delete/insert steps that will convert lines iS1 through iE1-1 of
** the input into lines iS2 through iE2-1 of the output and write
** that sequence into the difference context.
**







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







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
    *piSY = iSYb;
    *piEX = iEXb;
    *piEY = iEYb;
  }
  /* printf("LCS(%d..%d/%d..%d) = %d..%d/%d..%d\n", 
     iS1, iE1, iS2, iE2, *piSX, *piEX, *piSY, *piEY);  */
}

/*
** Expand the size of aEdit[] array to hold at least nEdit elements.
*/
static void expandEdit(DContext *p, int nEdit){
  p->aEdit = fossil_realloc(p->aEdit, nEdit*sizeof(int));
  p->nEditAlloc = nEdit;
}

/*
** Append a new COPY/DELETE/INSERT triple.
*/
static void appendTriple(DContext *p, int nCopy, int nDel, int nIns){
  /* printf("APPEND %d/%d/%d\n", nCopy, nDel, nIns); */
  if( p->nEdit>=3 ){
    if( p->aEdit[p->nEdit-1]==0 ){
      if( p->aEdit[p->nEdit-2]==0 ){
        p->aEdit[p->nEdit-3] += nCopy;
        p->aEdit[p->nEdit-2] += nDel;
        p->aEdit[p->nEdit-1] += nIns;
        return;
      }
      if( nCopy==0 ){
        p->aEdit[p->nEdit-2] += nDel;
        p->aEdit[p->nEdit-1] += nIns;
        return;
      }
    }
    if( nCopy==0 && nDel==0 ){
      p->aEdit[p->nEdit-1] += nIns;
      return;
    }
  }  
  if( p->nEdit+3>p->nEditAlloc ){
    expandEdit(p, p->nEdit*2 + 15);
    if( p->aEdit==0 ) return;
  }
  p->aEdit[p->nEdit++] = nCopy;
  p->aEdit[p->nEdit++] = nDel;
  p->aEdit[p->nEdit++] = nIns;
}

/*
** Do a single step in the difference.  Compute a sequence of
** copy/delete/insert steps that will convert lines iS1 through iE1-1 of
** the input into lines iS2 through iE2-1 of the output and write
** that sequence into the difference context.
**
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
    return;
  }

  /* Find the longest matching segment between the two sequences */
  longestCommonSequence(p, iS1, iE1, iS2, iE2, &iSX, &iEX, &iSY, &iEY);

  if( iEX>iSX ){
    /* A common segement has been found.
    ** Recursively diff either side of the matching segment */
    diff_step(p, iS1, iSX, iS2, iSY);
    if( iEX>iSX ){
      appendTriple(p, iEX - iSX, 0, 0);
    }
    diff_step(p, iEX, iE1, iEY, iE2);
  }else{







|







1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
    return;
  }

  /* Find the longest matching segment between the two sequences */
  longestCommonSequence(p, iS1, iE1, iS2, iE2, &iSX, &iEX, &iSY, &iEY);

  if( iEX>iSX ){
    /* A common segment has been found.
    ** Recursively diff either side of the matching segment */
    diff_step(p, iS1, iSX, iS2, iSY);
    if( iEX>iSX ){
      appendTriple(p, iEX - iSX, 0, 0);
    }
    diff_step(p, iEX, iE1, iEY, iE2);
  }else{
716
717
718
719
720
721
722






































































































723
724
725
726
727
728
729
  expandEdit(p, p->nEdit+3);
  if( p->aEdit ){
    p->aEdit[p->nEdit++] = 0;
    p->aEdit[p->nEdit++] = 0;
    p->aEdit[p->nEdit++] = 0;
  }
}







































































































/*
** Extract the number of lines of context from diffFlags.  Supply an
** appropriate default if no context width is specified.
*/
int diff_context_lines(int diffFlags){
  int n = diffFlags & DIFF_CONTEXT_MASK;







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







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
  expandEdit(p, p->nEdit+3);
  if( p->aEdit ){
    p->aEdit[p->nEdit++] = 0;
    p->aEdit[p->nEdit++] = 0;
    p->aEdit[p->nEdit++] = 0;
  }
}

/*
** Attempt to shift insertion or deletion blocks so that they begin and
** end on lines that are pure whitespace.  In other words, try to transform
** this:
**
**      int func1(int x){
**         return x*10;
**     +}
**     +
**     +int func2(int x){
**     +   return x*20;
**      }
**
**      int func3(int x){
**         return x/5;
**      }
**
** Into one of these:
**
**      int func1(int x){              int func1(int x){
**         return x*10;                   return x*10;
**      }                              }
**     +
**     +int func2(int x){             +int func2(int x){
**     +   return x*20;               +   return x*20;
**     +}                             +}
**                                    +
**      int func3(int x){              int func3(int x){
**         return x/5;                    return x/5;
**      }                              }
*/
static void diff_optimize(DContext *p){
  int r;       /* Index of current triple */
  int lnFrom;  /* Line number in p->aFrom */
  int lnTo;    /* Line number in p->aTo */
  int cpy, del, ins;

  lnFrom = lnTo = 0;
  for(r=0; r<p->nEdit; r += 3){
    cpy = p->aEdit[r];
    del = p->aEdit[r+1];
    ins = p->aEdit[r+2];
    lnFrom += cpy;
    lnTo += cpy;

    /* Shift insertions toward the beginning of the file */
    while( cpy>0 && del==0 && ins>0 ){
      DLine *pTop = &p->aFrom[lnFrom-1];  /* Line before start of insert */
      DLine *pBtm = &p->aTo[lnTo+ins-1];  /* Last line inserted */
      if( same_dline(pTop, pBtm)==0 ) break;
      if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
      lnFrom--;
      lnTo--;
      p->aEdit[r]--;
      p->aEdit[r+3]++;
      cpy--;
    }

    /* Shift insertions toward the end of the file */
    while( r+3<p->nEdit && p->aEdit[r+3]>0 && del==0 && ins>0 ){
      DLine *pTop = &p->aTo[lnTo];       /* First line inserted */
      DLine *pBtm = &p->aTo[lnTo+ins];   /* First line past end of insert */
      if( same_dline(pTop, pBtm)==0 ) break;
      if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop+1)+LENGTH(pBtm) ) break;
      lnFrom++;
      lnTo++;
      p->aEdit[r]++;
      p->aEdit[r+3]--;
      cpy++;
    }

    /* Shift deletions toward the beginning of the file */
    while( cpy>0 && del>0 && ins==0 ){
      DLine *pTop = &p->aFrom[lnFrom-1];     /* Line before start of delete */
      DLine *pBtm = &p->aFrom[lnFrom+del-1]; /* Last line deleted */
      if( same_dline(pTop, pBtm)==0 ) break;
      if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
      lnFrom--;
      lnTo--;
      p->aEdit[r]--;
      p->aEdit[r+3]++;
      cpy--;
    }

    /* Shift deletions toward the end of the file */
    while( r+3<p->nEdit && p->aEdit[r+3]>0 && del>0 && ins==0 ){
      DLine *pTop = &p->aFrom[lnFrom];     /* First line deleted */
      DLine *pBtm = &p->aFrom[lnFrom+del]; /* First line past end of delete */
      if( same_dline(pTop, pBtm)==0 ) break;
      if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop)+LENGTH(pBtm) ) break;
      lnFrom++;
      lnTo++;
      p->aEdit[r]++;
      p->aEdit[r+3]--;
      cpy++;
    }

    lnFrom += del;
    lnTo += ins;
  }
}

/*
** Extract the number of lines of context from diffFlags.  Supply an
** appropriate default if no context width is specified.
*/
int diff_context_lines(int diffFlags){
  int n = diffFlags & DIFF_CONTEXT_MASK;
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
  Blob *pOut,      /* Write diff here if not NULL */
  int diffFlags    /* DIFF_* flags defined above */
){
  int ignoreEolWs; /* Ignore whitespace at the end of lines */
  int nContext;    /* Amount of context to display */	
  DContext c;






  nContext = diff_context_lines(diffFlags);
  ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;

  /* Prepare the input files */
  memset(&c, 0, sizeof(c));
  c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
                             &c.nFrom, ignoreEolWs);
  c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
                           &c.nTo, ignoreEolWs);
  if( c.aFrom==0 || c.aTo==0 ){
    free(c.aFrom);
    free(c.aTo);
    if( pOut ){
      blob_appendf(pOut, "cannot compute difference between binary files\n");
    }
    return 0;
  }

  /* Compute the difference */
  diff_all(&c);


  if( pOut ){
    /* Compute a context or side-by-side diff into pOut */

    if( diffFlags & DIFF_SIDEBYSIDE ){
      int width = diff_width(diffFlags);
      sbsDiff(&c, pOut, nContext, width);
    }else{

      contextDiff(&c, pOut, nContext);
    }
    free(c.aFrom);
    free(c.aTo);
    free(c.aEdit);
    return 0;
  }else{
    /* If a context diff is not requested, then return the
    ** array of COPY/DELETE/INSERT triples.
    */
    free(c.aFrom);
    free(c.aTo);
    return c.aEdit;
  }
}

/*
** Copy a line with a limit. Used for side-by-side diffs to enforce a maximum
** line length limit.
*/
static char *copylimline(char *out, DLine *dl, int lim){
  int len;
  len = dl->h & LENGTH_MASK;
  if( lim && len > lim ){
    memcpy(out, dl->z, lim-3);
    memcpy(&out[lim-3], "...", 4);
  }else{
    memcpy(out, dl->z, len);
    out[len] = '\0';
  }
  return out;
}

/*
** Output table body of a side-by-side diff. Prior to the call, the caller
** should have output:
**   <table class="sbsdiff">
**   <tr><th colspan="2" class="diffhdr">Old title</th><th/>
**   <th colspan="2" class="diffhdr">New title</th></tr>
**
** And after the call, it should output:
**   </table>
**
** Some good reference diffs in the fossil repository for testing:
** /vdiff?from=080d27a&to=4b0f813&detail=1
** /vdiff?from=636804745b&to=c1d78e0556&detail=1
** /vdiff?from=c0b6c28d29&to=25169506b7&detail=1
** /vdiff?from=e3d022dffa&to=48bcfbd47b&detail=1
*/
int html_sbsdiff(
  Blob *pA_Blob,   /* FROM file */
  Blob *pB_Blob,   /* TO file */
  int nContext,    /* Amount of context to unified diff */
  int ignoreEolWs  /* Ignore whitespace at the end of lines */
){
  DContext c;
  int i;
  int iFrom, iTo;
  char *linebuf;
  int collim=0; /* Currently not settable; allows a column limit for diffs */
  int allowExp=0; /* Currently not settable; (dis)allow expansion of rows */

  /* Prepare the input files */
  memset(&c, 0, sizeof(c));
  c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
                             &c.nFrom, ignoreEolWs);
  c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
                           &c.nTo, ignoreEolWs);
  if( c.aFrom==0 || c.aTo==0 ){
    free(c.aFrom);
    free(c.aTo);
    /* Note: This would be generated within a table. */
    @ <p class="generalError" style="white-space: nowrap">cannot compute
    @ difference between binary files</p>
    return 0;
  }

  collim = collim < 4 ? 0 : collim;

  /* Compute the difference */
  diff_all(&c);

  linebuf = fossil_malloc(LENGTH_MASK+1);
  if( !linebuf ){
    free(c.aFrom);
    free(c.aTo);
    free(c.aEdit);
    return 0;
  }

  iFrom=iTo=0;
  i=0;
  while( i<c.nEdit ){
    int j;
    /* Copied lines */
    for( j=0; j<c.aEdit[i]; j++){
      /* Hide lines which are copied and are further away from block boundaries
      ** than nContext lines. For each block with hidden lines, show a row
      ** notifying the user about the hidden rows.
      */
      if( j<nContext || j>c.aEdit[i]-nContext-1 ){
        @ <tr>
      }else if( j==nContext && j<c.aEdit[i]-nContext-1 ){
        @ <tr>
        @ <td class="meta" colspan="5" style="white-space: nowrap;">
        @ %d(c.aEdit[i]-2*nContext) hidden lines</td>
        @ </tr>
        if( !allowExp )
           continue;
        @ <tr style="display:none;">
      }else{
        if( !allowExp )
           continue;
        @ <tr style="display:none;">
      }

      copylimline(linebuf, &c.aFrom[iFrom+j], collim);
      @ <td class="lineno">%d(iFrom+j+1)</td>
      @ <td class="srcline">%h(linebuf)</td>

      @ <td> </td>

      copylimline(linebuf, &c.aTo[iTo+j], collim);
      @ <td class="lineno">%d(iTo+j+1)</td>
      @ <td class="srcline">%h(linebuf)</td>

      @ </tr>
    }
    iFrom+=c.aEdit[i];
    iTo+=c.aEdit[i];

    if( c.aEdit[i+1]!=0 && c.aEdit[i+2]!=0 ){
      int lim;
      lim = c.aEdit[i+1] > c.aEdit[i+2] ? c.aEdit[i+1] : c.aEdit[i+2];

      /* Assume changed lines */
      for( j=0; j<lim; j++ ){
        @ <tr>

        if( j<c.aEdit[i+1] ){
          copylimline(linebuf, &c.aFrom[iFrom+j], collim);
          @ <td class="changed lineno">%d(iFrom+j+1)</td>
          @ <td class="changed srcline">%h(linebuf)</td>
        }else{
          @ <td colspan="2" class="changedvoid"/>
        }

        @ <td class="changed">|</td>

        if( j<c.aEdit[i+2] ){
          copylimline(linebuf, &c.aTo[iTo+j], collim);
          @ <td class="changed lineno">%d(iTo+j+1)</td>
          @ <td class="changed srcline">%h(linebuf)</td>
        }else{
          @ <td colspan="2" class="changedvoid"/>
        }

        @ </tr>
      }
      iFrom+=c.aEdit[i+1];
      iTo+=c.aEdit[i+2];
    }else{

      /* Process deleted lines */
      for( j=0; j<c.aEdit[i+1]; j++ ){
        @ <tr>

        copylimline(linebuf, &c.aFrom[iFrom+j], collim);
        @ <td class="removed lineno">%d(iFrom+j+1)</td>
        @ <td class="removed srcline">%h(linebuf)</td>
        @ <td>&lt;</td>
        @ <td colspan="2" class="removedvoid"/>
        @ </tr>
      }
      iFrom+=c.aEdit[i+1];

      /* Process inserted lines */
      for( j=0; j<c.aEdit[i+2]; j++ ){
        @ <tr>
        @ <td colspan="2" class="addedvoid"/>
        @ <td>&gt;</td>
        copylimline(linebuf, &c.aTo[iTo+j], collim);
        @ <td class="added lineno">%d(iTo+j+1)</td>
        @ <td class="added srcline">%h(linebuf)</td>
        @ </tr>
      }
      iTo+=c.aEdit[i+2];
    }

    i+=3;
  }

  free(linebuf);
  free(c.aFrom);
  free(c.aTo);
  free(c.aEdit);
  return 1;
}


/*
** COMMAND: test-rawdiff
*/
void test_rawdiff_cmd(void){
  Blob a, b;
  int r;
  int i;
  int *R;
  if( g.argc<4 ) usage("FILE1 FILE2 ...");
  blob_read_from_file(&a, g.argv[2]);
  for(i=3; i<g.argc; i++){
    if( i>3 ) fossil_print("-------------------------------\n");
    blob_read_from_file(&b, g.argv[i]);
    R = text_diff(&a, &b, 0, 0);
    for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
      fossil_print(" copy %4d  delete %4d  insert %4d\n", R[r], R[r+1], R[r+2]);
    }
    /* free(R); */
    blob_reset(&b);
  }
}

/*
** Process diff-related command-line options and return an appropriate
** "diffFlags" integer.  
**
**   --side-by-side|-y      Side-by-side diff.     DIFF_SIDEBYSIDE
**   --context|-c N         N lines of context.    DIFF_CONTEXT_MASK





**   --width|-W N           N character lines.     DIFF_WIDTH_MASK
*/
int diff_options(void){
  int diffFlags = 0;
  const char *z;
  int f;
  if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
  if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){
    if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
    diffFlags |= f;
  }
  if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
    f *= DIFF_CONTEXT_MASK+1;
    if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
    diffFlags |= f;
  }





  return diffFlags;
}
























/*
** COMMAND: test-udiff
**
** Print the difference between two files.  The usual diff options apply.
*/
void test_udiff_cmd(void){







>
>
>
>
>




















>



>


|

>
|
















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



|

>
>
>
>
>
















>
>
>
>
>


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







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
  Blob *pOut,      /* Write diff here if not NULL */
  int diffFlags    /* DIFF_* flags defined above */
){
  int ignoreEolWs; /* Ignore whitespace at the end of lines */
  int nContext;    /* Amount of context to display */	
  DContext c;

  if( diffFlags & DIFF_INVERT ){
    Blob *pTemp = pA_Blob;
    pA_Blob = pB_Blob;
    pB_Blob = pTemp;
  }
  nContext = diff_context_lines(diffFlags);
  ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;

  /* Prepare the input files */
  memset(&c, 0, sizeof(c));
  c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
                             &c.nFrom, ignoreEolWs);
  c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
                           &c.nTo, ignoreEolWs);
  if( c.aFrom==0 || c.aTo==0 ){
    free(c.aFrom);
    free(c.aTo);
    if( pOut ){
      blob_appendf(pOut, "cannot compute difference between binary files\n");
    }
    return 0;
  }

  /* Compute the difference */
  diff_all(&c);
  if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);

  if( pOut ){
    /* Compute a context or side-by-side diff into pOut */
    int escHtml = (diffFlags & DIFF_HTML)!=0;
    if( diffFlags & DIFF_SIDEBYSIDE ){
      int width = diff_width(diffFlags);
      sbsDiff(&c, pOut, nContext, width, escHtml);
    }else{
      int showLn = (diffFlags & DIFF_LINENO)!=0;
      contextDiff(&c, pOut, nContext, showLn, escHtml);
    }
    free(c.aFrom);
    free(c.aTo);
    free(c.aEdit);
    return 0;
  }else{
    /* If a context diff is not requested, then return the
    ** array of COPY/DELETE/INSERT triples.
    */
    free(c.aFrom);
    free(c.aTo);
    return c.aEdit;
  }
}

/*














































































































































































































** Process diff-related command-line options and return an appropriate
** "diffFlags" integer.  
**
**   --brief                Show filenames only    DIFF_BRIEF
**   --context|-c N         N lines of context.    DIFF_CONTEXT_MASK
**   --html                 Format for HTML        DIFF_HTML
**   --invert               Invert the diff        DIFF_INVERT
**   --linenum|-n           Show line numbers      DIFF_LINENO
**   --noopt                Disable optimization   DIFF_NOOPT
**   --side-by-side|-y      Side-by-side diff.     DIFF_SIDEBYSIDE
**   --width|-W N           N character lines.     DIFF_WIDTH_MASK
*/
int diff_options(void){
  int diffFlags = 0;
  const char *z;
  int f;
  if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
  if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){
    if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
    diffFlags |= f;
  }
  if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
    f *= DIFF_CONTEXT_MASK+1;
    if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
    diffFlags |= f;
  }
  if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
  if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
  if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
  if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
  if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF;
  return diffFlags;
}

/*
** COMMAND: test-rawdiff
*/
void test_rawdiff_cmd(void){
  Blob a, b;
  int r;
  int i;
  int *R;
  int diffFlags = diff_options();
  if( g.argc<4 ) usage("FILE1 FILE2 ...");
  blob_read_from_file(&a, g.argv[2]);
  for(i=3; i<g.argc; i++){
    if( i>3 ) fossil_print("-------------------------------\n");
    blob_read_from_file(&b, g.argv[i]);
    R = text_diff(&a, &b, 0, diffFlags);
    for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
      fossil_print(" copy %4d  delete %4d  insert %4d\n", R[r], R[r+1], R[r+2]);
    }
    /* free(R); */
    blob_reset(&b);
  }
}

/*
** COMMAND: test-udiff
**
** Print the difference between two files.  The usual diff options apply.
*/
void test_udiff_cmd(void){
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
  while( db_step(&q)==SQLITE_ROW ){
    int pid = db_column_int(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    if( webLabel ){
      zLabel = mprintf(
          "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 
          g.zTop, zUuid, zUuid, zDate, zUser
      );
    }else{
      zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
    }
    p->nVers++;
    p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
    p->azVers[p->nVers-1] = zLabel;
    content_get(pid, &step);
    annotation_step(p, &step, zLabel);
    blob_reset(&step);







|



|







1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
  while( db_step(&q)==SQLITE_ROW ){
    int pid = db_column_int(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    if( webLabel ){
      zLabel = mprintf(
          "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s", 
          g.zTop, zUuid, zUuid, zDate, zUser
      );
    }else{
      zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
    }
    p->nVers++;
    p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
    p->azVers[p->nVers-1] = zLabel;
    content_get(pid, &step);
    annotation_step(p, &step, zLabel);
    blob_reset(&step);
1317
1318
1319
1320
1321
1322
1323


1324
1325
1326
1327
1328
1329
1330
** Output the text of a file with markings to show when each line of
** the file was last modified.
**
** Options:
**   --limit N       Only look backwards in time by N versions
**   --log           List all versions analyzed
**   --filevers      Show file version numbers rather than check-in versions


*/
void annotate_cmd(void){
  int fnid;         /* Filename ID */
  int fid;          /* File instance ID */
  int mid;          /* Manifest where file was checked in */
  int cid;          /* Checkout ID */
  Blob treename;    /* FILENAME translated to canonical form */







>
>







1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
** Output the text of a file with markings to show when each line of
** the file was last modified.
**
** Options:
**   --limit N       Only look backwards in time by N versions
**   --log           List all versions analyzed
**   --filevers      Show file version numbers rather than check-in versions
**
** See also: info, finfo, timeline
*/
void annotate_cmd(void){
  int fnid;         /* Filename ID */
  int fid;          /* File instance ID */
  int mid;          /* Manifest where file was checked in */
  int cid;          /* Checkout ID */
  Blob treename;    /* FILENAME translated to canonical form */
Changes to src/diffcmd.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
68
69
70
71
72
73
**
** This file contains code used to implement the "diff" command
*/
#include "config.h"
#include "diffcmd.h"
#include <assert.h>

/*
** Output the results of a diff.  Output goes to stdout for command-line
** or to the CGI/HTTP result buffer for web pages.
*/
static void diff_printf(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  if( g.cgiOutput ){
    cgi_vprintf(zFormat, ap);
  }else{
    vprintf(zFormat, ap);
  }
  va_end(ap);
}

/*
** Print the "Index:" message that patches wants to see at the top of a diff.
*/
void diff_print_index(const char *zFile, int diffFlags){
  if( (diffFlags & DIFF_SIDEBYSIDE)==0 ){
    char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
    diff_printf("%s", z);
    fossil_free(z);
  }
}

/*
** Print the +++/--- filename lines for a diff operation.
*/
void diff_print_filenames(const char *zLeft, const char *zRight, int diffFlags){
  char *z = 0;
  if( diffFlags & DIFF_SIDEBYSIDE ){


    int w = diff_width(diffFlags);
    int n1 = strlen(zLeft);
    int x;
    if( n1>w*2 ) n1 = w*2;
    x = w*2+17 - (n1+2);
    z = mprintf("%.*c %.*s %.*c\n",
                x/2, '=', n1, zLeft, (x+1)/2, '=');
  }else{
    z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
  }
  diff_printf("%s", z);
  fossil_free(z);
}

/*
** Show the difference between two files, one in memory and one on disk.
**
** The difference is the set of edits needed to transform pFile1 into







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




|

|









|
>
>










|







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
**
** This file contains code used to implement the "diff" command
*/
#include "config.h"
#include "diffcmd.h"
#include <assert.h>
















/*
** Print the "Index:" message that patches wants to see at the top of a diff.
*/
void diff_print_index(const char *zFile, int diffFlags){
  if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
    char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
    fossil_print("%s", z);
    fossil_free(z);
  }
}

/*
** Print the +++/--- filename lines for a diff operation.
*/
void diff_print_filenames(const char *zLeft, const char *zRight, int diffFlags){
  char *z = 0;
  if( diffFlags & DIFF_BRIEF ){
    /* no-op */
  }else if( diffFlags & DIFF_SIDEBYSIDE ){
    int w = diff_width(diffFlags);
    int n1 = strlen(zLeft);
    int x;
    if( n1>w*2 ) n1 = w*2;
    x = w*2+17 - (n1+2);
    z = mprintf("%.*c %.*s %.*c\n",
                x/2, '=', n1, zLeft, (x+1)/2, '=');
  }else{
    z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
  }
  fossil_print("%s", z);
  fossil_free(z);
}

/*
** Show the difference between two files, one in memory and one on disk.
**
** The difference is the set of edits needed to transform pFile1 into
98
99
100
101
102
103
104





105
106
107
108
109


110
111
112
113
114
115
116
117
118
119
120
121
      }else{
        blob_read_from_file(&file2, zFile2);
      }
      zName2 = zName;
    }

    /* Compute and output the differences */





    blob_zero(&out);
    text_diff(pFile1, &file2, &out, diffFlags);
    if( blob_size(&out) ){
      diff_print_filenames(zName, zName2, diffFlags);
      diff_printf("%s\n", blob_str(&out));


    }

    /* Release memory resources */
    blob_reset(&file2);
    blob_reset(&out);
  }else{
    int cnt = 0;
    Blob nameFile1;    /* Name of temporary file to old pFile1 content */
    Blob cmd;          /* Text of command to run */

    /* Construct a temporary file to hold pFile1 based on the name of
    ** zFile2 */







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




<







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
      }else{
        blob_read_from_file(&file2, zFile2);
      }
      zName2 = zName;
    }

    /* Compute and output the differences */
    if( diffFlags & DIFF_BRIEF ){
      if( blob_compare(pFile1, &file2) ){
        fossil_print("CHANGED  %s\n", zName);
      }
    }else{
      blob_zero(&out);
      text_diff(pFile1, &file2, &out, diffFlags);
      if( blob_size(&out) ){
        diff_print_filenames(zName, zName2, diffFlags);
        fossil_print("%s\n", blob_str(&out));
      }
      blob_reset(&out);
    }

    /* Release memory resources */
    blob_reset(&file2);

  }else{
    int cnt = 0;
    Blob nameFile1;    /* Name of temporary file to old pFile1 content */
    Blob cmd;          /* Text of command to run */

    /* Construct a temporary file to hold pFile1 based on the name of
    ** zFile2 */
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
void diff_file_mem(
  Blob *pFile1,             /* In memory content to compare from */
  Blob *pFile2,             /* In memory content to compare to */
  const char *zName,        /* Display name of the file */
  const char *zDiffCmd,     /* Command for comparison */
  int diffFlags             /* Diff flags */
){

  if( zDiffCmd==0 ){
    Blob out;      /* Diff output text */

    blob_zero(&out);
    text_diff(pFile1, pFile2, &out, diffFlags);
    diff_print_filenames(zName, zName, diffFlags);
    diff_printf("%s\n", blob_str(&out));

    /* Release memory resources */
    blob_reset(&out);
  }else{
    Blob cmd;
    char zTemp1[300];
    char zTemp2[300];







>






|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
void diff_file_mem(
  Blob *pFile1,             /* In memory content to compare from */
  Blob *pFile2,             /* In memory content to compare to */
  const char *zName,        /* Display name of the file */
  const char *zDiffCmd,     /* Command for comparison */
  int diffFlags             /* Diff flags */
){
  if( diffFlags & DIFF_BRIEF ) return;
  if( zDiffCmd==0 ){
    Blob out;      /* Diff output text */

    blob_zero(&out);
    text_diff(pFile1, pFile2, &out, diffFlags);
    diff_print_filenames(zName, zName, diffFlags);
    fossil_print("%s\n", blob_str(&out));

    /* Release memory resources */
    blob_reset(&out);
  }else{
    Blob cmd;
    char zTemp1[300];
    char zTemp2[300];
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
){
  Blob fname;
  Blob content;
  int isLink;
  file_tree_name(zFileTreeName, &fname, 1);
  historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
  if( !isLink != !file_wd_islink(zFrom) ){
    diff_printf("cannot compute difference between symlink and regular file\n");

  }else{
    diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, diffFlags);
  }
  blob_reset(&content);
  blob_reset(&fname);
}








|
>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
){
  Blob fname;
  Blob content;
  int isLink;
  file_tree_name(zFileTreeName, &fname, 1);
  historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
  if( !isLink != !file_wd_islink(zFrom) ){
    fossil_print("cannot compute difference between "
                 "symlink and regular file\n");
  }else{
    diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, diffFlags);
  }
  blob_reset(&content);
  blob_reset(&fname);
}

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
    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 ){
      diff_printf("DELETED  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
    }else if( file_access(zFullName, 0) ){
      diff_printf("MISSING  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; }
    }else if( isNew ){
      diff_printf("ADDED    %s\n", zPathname);
      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }else if( isChnged==3 ){
      diff_printf("ADDED_BY_MERGE %s\n", zPathname);
      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }
    if( showDiff ){
      Blob content;
      if( !isLink != !file_wd_islink(zFullName) ){
        diff_print_index(zPathname, diffFlags);
        diff_print_filenames(zPathname, zPathname, diffFlags);
        diff_printf("cannot compute difference between symlink and regular file\n");

        continue;
      }
      if( srcid>0 ){
        content_get(srcid, &content);
      }else{
        blob_zero(&content);
      }







|


|


|



|








|
>







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
    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 = "/dev/null"; }
    }else if( file_access(zFullName, 0) ){
      fossil_print("MISSING  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; }
    }else if( isNew ){
      fossil_print("ADDED    %s\n", zPathname);
      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }else if( isChnged==3 ){
      fossil_print("ADDED_BY_MERGE %s\n", zPathname);
      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }
    if( showDiff ){
      Blob content;
      if( !isLink != !file_wd_islink(zFullName) ){
        diff_print_index(zPathname, diffFlags);
        diff_print_filenames(zPathname, zPathname, diffFlags);
        fossil_print("cannot compute difference between "
                     "symlink and regular file\n");
        continue;
      }
      if( srcid>0 ){
        content_get(srcid, &content);
      }else{
        blob_zero(&content);
      }
337
338
339
340
341
342
343

344
345
346
347
348
349

350
351
352
353
354
355
356
357
  int diffFlags,
  const char *zFileTreeName
){
  char *zName;
  Blob fname;
  Blob v1, v2;
  int isLink1, isLink2;

  file_tree_name(zFileTreeName, &fname, 1);
  zName = blob_str(&fname);
  historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, 0);
  historical_version_of_file(zTo, zName, &v2, &isLink2, 0, 0);
  if( isLink1 != isLink2 ){
    diff_print_filenames(zName, zName, diffFlags);

    diff_printf("cannot compute difference between symlink and regular file\n");
  }else{
    diff_file_mem(&v1, &v2, zName, zDiffCmd, diffFlags);
  }
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&fname);
}







>






>
|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
  int diffFlags,
  const char *zFileTreeName
){
  char *zName;
  Blob fname;
  Blob v1, v2;
  int isLink1, isLink2;
  if( diffFlags & DIFF_BRIEF ) return;
  file_tree_name(zFileTreeName, &fname, 1);
  zName = blob_str(&fname);
  historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, 0);
  historical_version_of_file(zTo, zName, &v2, &isLink2, 0, 0);
  if( isLink1 != isLink2 ){
    diff_print_filenames(zName, zName, diffFlags);
    fossil_print("cannot compute difference "
                 " between symlink and regular file\n");
  }else{
    diff_file_mem(&v1, &v2, zName, zDiffCmd, diffFlags);
  }
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&fname);
}
365
366
367
368
369
370
371

372
373
374
375
376
377
378
  struct ManifestFile *pTo,
  const char *zDiffCmd,
  int diffFlags
){
  Blob f1, f2;
  int rid;
  const char *zName =  pFrom ? pFrom->zName : pTo->zName;

  diff_print_index(zName, diffFlags);
  if( pFrom ){
    rid = uuid_to_rid(pFrom->zUuid, 0);
    content_get(rid, &f1);
  }else{
    blob_zero(&f1);
  }







>







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  struct ManifestFile *pTo,
  const char *zDiffCmd,
  int diffFlags
){
  Blob f1, f2;
  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);
  }
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
      cmp = +1;
    }else if( pToFile==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFromFile->zName, pToFile->zName);
    }
    if( cmp<0 ){
      diff_printf("DELETED %s\n", pFromFile->zName);
      if( asNewFlag ){
        diff_manifest_entry(pFromFile, 0, zDiffCmd, diffFlags);
      }
      pFromFile = manifest_file_next(pFrom,0);
    }else if( cmp>0 ){
      diff_printf("ADDED   %s\n", pToFile->zName);
      if( asNewFlag ){
        diff_manifest_entry(0, pToFile, zDiffCmd, diffFlags);
      }
      pToFile = manifest_file_next(pTo,0);
    }else if( fossil_strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){
      /* No changes */
      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }else{

      /* diff_printf("CHANGED %s\n", pFromFile->zName); */

      diff_manifest_entry(pFromFile, pToFile, zDiffCmd, diffFlags);

      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);
}







|





|









>
|
>
|
>







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
      cmp = +1;
    }else if( pToFile==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFromFile->zName, pToFile->zName);
    }
    if( cmp<0 ){
      fossil_print("DELETED %s\n", pFromFile->zName);
      if( asNewFlag ){
        diff_manifest_entry(pFromFile, 0, zDiffCmd, diffFlags);
      }
      pFromFile = manifest_file_next(pFrom,0);
    }else if( cmp>0 ){
      fossil_print("ADDED   %s\n", pToFile->zName);
      if( asNewFlag ){
        diff_manifest_entry(0, pToFile, zDiffCmd, diffFlags);
      }
      pToFile = manifest_file_next(pTo,0);
    }else if( fossil_strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){
      /* No changes */
      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }else{
      if( diffFlags & DIFF_BRIEF ){
        fossil_print("CHANGED %s\n", pFromFile->zName);
      }else{
        diff_manifest_entry(pFromFile, pToFile, zDiffCmd, diffFlags);
      }
      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);
}
468
469
470
471
472
473
474

475
476
477
478

479
480
481
482
483
484
485
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
**
** The "-N" or "--new-file" option causes the complete text of added or
** deleted files to be displayed.
**
** Options:

**   --context|-c N      Use N lines of context 
**   --from|-r VERSION   select VERSION as source for the diff
**   --new-file|-N       output complete text of added or deleted files
**   -i                  use internal diff logic

**   --to VERSION        select VERSION as target for the diff
**   --side-by-side|-y   side-by-side diff
**   --width|-W N        Width of lines in side-by-side diff 
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */







>


<

>







470
471
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
**
** The "-N" or "--new-file" option causes the complete text of added or
** deleted files to be displayed.
**
** Options:
**   --brief             Show filenames only
**   --context|-c N      Use N lines of context 
**   --from|-r VERSION   select VERSION as source for the diff

**   -i                  use internal diff logic
**   --new-file|-N       output complete text of added or deleted files
**   --to VERSION        select VERSION as target for the diff
**   --side-by-side|-y   side-by-side diff
**   --width|-W N        Width of lines in side-by-side diff 
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */
Changes to src/file.c.
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
    }else{
      fossil_fatal("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif
}



















/*
** Compute a canonical pathname for a file or directory.
** Make the name absolute if it is relative.
** Remove redundant / characters
** Remove all /./ path elements.
** Convert /A/../ to just /
*/
void file_canonical_name(const char *zOrigName, Blob *pOut){
  if( zOrigName[0]=='/' 
#if defined(_WIN32)
      || zOrigName[0]=='\\'
      || (strlen(zOrigName)>3 && zOrigName[1]==':'
           && (zOrigName[2]=='\\' || zOrigName[2]=='/'))
#endif
  ){
    blob_set(pOut, zOrigName);
    blob_materialize(pOut);
  }else{
    char zPwd[2000];
    file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
    blob_zero(pOut);
    blob_appendf(pOut, "%//%/", zPwd, zOrigName);







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









|
<
<
<
<
<
<







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
    }else{
      fossil_fatal("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif
}

/*
** Return true if zPath is an absolute pathname.  Return false
** if it is relative.
*/
int file_is_absolute_path(const char *zPath){
  if( zPath[0]=='/'
#if defined(_WIN32)
      || zPath[0]=='\\'
      || (strlen(zPath)>3 && zPath[1]==':'
           && (zPath[2]=='\\' || zPath[2]=='/'))
#endif
  ){
    return 1;
  }else{
    return 0;
  }
}

/*
** Compute a canonical pathname for a file or directory.
** Make the name absolute if it is relative.
** Remove redundant / characters
** Remove all /./ path elements.
** Convert /A/../ to just /
*/
void file_canonical_name(const char *zOrigName, Blob *pOut){
  if( file_is_absolute_path(zOrigName) ){






    blob_set(pOut, zOrigName);
    blob_materialize(pOut);
  }else{
    char zPwd[2000];
    file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
    blob_zero(pOut);
    blob_appendf(pOut, "%//%/", zPwd, zOrigName);
947
948
949
950
951
952
953











954
955
956
957
958
959
960
#ifdef _WIN32
  extern char *sqlite3_win32_utf8_to_mbcs(const char*);
  return sqlite3_win32_utf8_to_mbcs(zUtf8);
#else
  return (char*)zUtf8;  /* No-op on unix */
#endif  
}












/*
** Translate UTF8 to MBCS for display on the console.  Return a pointer to the
** translated text..  Call fossil_mbcs_free() to deallocate any memory
** used to store the returned pointer when done.
*/
char *fossil_utf8_to_console(const char *zUtf8){







>
>
>
>
>
>
>
>
>
>
>







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
#ifdef _WIN32
  extern char *sqlite3_win32_utf8_to_mbcs(const char*);
  return sqlite3_win32_utf8_to_mbcs(zUtf8);
#else
  return (char*)zUtf8;  /* No-op on unix */
#endif  
}

/*
** Return the value of an environment variable as UTF8.
*/
char *fossil_getenv(const char *zName){
  char *zValue = getenv(zName);
#ifdef _WIN32
  if( zValue ) zValue = fossil_mbcs_to_utf8(zValue);
#endif
  return zValue;
}

/*
** Translate UTF8 to MBCS for display on the console.  Return a pointer to the
** translated text..  Call fossil_mbcs_free() to deallocate any memory
** used to store the returned pointer when done.
*/
char *fossil_utf8_to_console(const char *zUtf8){
Changes to src/finfo.c.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
**   -p                   select print mode
**   --revision|-r R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s                   select status mode (print a status indicator for FILE)
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
**                        boolean: "yes", "no", "true", "false", etc.
**
** See also: 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;







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
**   -p                   select print mode
**   --revision|-r R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s                   select status mode (print a status indicator for FILE)
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
**                        boolean: "yes", "no", "true", "false", etc.
**
** See also: artifact, 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;
Changes to src/http.c.
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  */
  if( g.fHttpTrace ){
    static int traceCnt = 0;
    char *zOutFile;
    FILE *out;
    traceCnt++;
    zOutFile = mprintf("http-request-%d.txt", traceCnt);
    out = fopen(zOutFile, "w");
    if( out ){
      fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out);
      fwrite(blob_buffer(&payload), 1, blob_size(&payload), out);
      fclose(out);
    }
    free(zOutFile);
    zOutFile = mprintf("http-reply-%d.txt", traceCnt);
    out = fopen(zOutFile, "w");
    transport_log(out);
    free(zOutFile);
  }

  /*
  ** Send the request to the server.
  */







|







|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  */
  if( g.fHttpTrace ){
    static int traceCnt = 0;
    char *zOutFile;
    FILE *out;
    traceCnt++;
    zOutFile = mprintf("http-request-%d.txt", traceCnt);
    out = fopen(zOutFile, "wb");
    if( out ){
      fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out);
      fwrite(blob_buffer(&payload), 1, blob_size(&payload), out);
      fclose(out);
    }
    free(zOutFile);
    zOutFile = mprintf("http-reply-%d.txt", traceCnt);
    out = fopen(zOutFile, "wb");
    transport_log(out);
    free(zOutFile);
  }

  /*
  ** Send the request to the server.
  */
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
                          "application/x-fossil-uncompressed", -1)==0 ){
        isCompressed = 0;
      }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
        isError = 1;
      }
    }
  }




  if( rc!=200 ){
    fossil_warning("\"location:\" missing from 302 redirect reply");
    goto write_err;
  }

  /*
  ** Extract the reply payload that follows the header
  */
  if( iLength<0 ){
    fossil_fatal("server did not reply");
    goto write_err;
  }
  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);
  if( isError ){
    char *z;
    int i, j;







>
>
>
>








<
<
<
<







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
                          "application/x-fossil-uncompressed", -1)==0 ){
        isCompressed = 0;
      }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
        isError = 1;
      }
    }
  }
  if( iLength<0 ){
    fossil_fatal("server did not reply");
    goto write_err;
  }
  if( rc!=200 ){
    fossil_warning("\"location:\" missing from 302 redirect reply");
    goto write_err;
  }

  /*
  ** Extract the reply payload that follows the header
  */




  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);
  if( isError ){
    char *z;
    int i, j;
Changes to src/info.c.
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
**
** Use the "finfo" command to get information about a specific
** file in a checkout.
**
** Options:
**
**    -R|--repository FILE       Extract info from repository FILE


*/
void info_cmd(void){
  i64 fsize;
  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>"));
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_lget("repository", ""));
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }
#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif







>
>


















|







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
**
** Use the "finfo" command to get information about a specific
** file in a checkout.
**
** Options:
**
**    -R|--repository FILE       Extract info from repository FILE
**
** See also: annotate, artifact, finfo, timeline
*/
void info_cmd(void){
  i64 fsize;
  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>"));
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_repository_filename());
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }
#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif
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
  }
}


/*
** Append the difference between two RIDs to the output
*/
static void append_diff(const char *zFrom, const char *zTo){
  int fromid;
  int toid;
  Blob from, to, out;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
    blob_zero(&from);
  }
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);
  }
  blob_zero(&out);

  text_diff(&from, &to, &out, DIFF_IGNORE_EOLWS | 5);

  @ %h(blob_str(&out))
  blob_reset(&from);
  blob_reset(&to);
  blob_reset(&out);  
}


/*
** Write the difference between two RIDs to the output
*/
static void generate_sbsdiff(const char *zFrom, const char *zTo){
  int fromid;
  int toid;
  Blob from, to;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
    blob_zero(&from);
  }
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);

  }
  @ <table class="sbsdiff">
  @ <tr><th colspan="2" class="diffhdr">Old (%S(zFrom))</th><th/>
  @ <th colspan="2" class="diffhdr">New (%S(zTo))</th></tr>
  html_sbsdiff(&from, &to, 5, 1);
  @ </table>
  blob_reset(&from);
  blob_reset(&to);

}


/*
** Write a line of web-page output that shows changes that have occurred 
** to a file between two check-ins.
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int showDiff,         /* Show edit diffs if true */
  int sideBySide,       /* Show diffs side-by-side */
  int mperm             /* executable or symlink permission for zNew */
){
  if( !g.perm.History ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
      @  for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( showDiff ){
      if( sideBySide ){
        generate_sbsdiff(zOld, zNew);
      }else{
        @ <blockquote><pre>
        append_diff(zOld, zNew);
        @ </pre></blockquote>
      }
    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>







|
















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

|
<
|
<
<
<
|
>

<
<
<
<
<


>












|
<















|
<
<
<
|
|
|
<







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
  }
}


/*
** Append the difference between two RIDs to the output
*/
static void append_diff(const char *zFrom, const char *zTo, int diffFlags){
  int fromid;
  int toid;
  Blob from, to, out;
  if( zFrom ){
    fromid = uuid_to_rid(zFrom, 0);
    content_get(fromid, &from);
  }else{
    blob_zero(&from);
  }
  if( zTo ){
    toid = uuid_to_rid(zTo, 0);
    content_get(toid, &to);
  }else{
    blob_zero(&to);
  }
  blob_zero(&out);
  if( diffFlags & DIFF_SIDEBYSIDE ){
    text_diff(&from, &to, &out, diffFlags | DIFF_HTML);
    @ <div class="sbsdiff">
    @ %s(blob_str(&out))




    @ </div>











  }else{
    text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML);

    @ <div class="udiff">



    @ %s(blob_str(&out))
    @ </div>
  }





  blob_reset(&from);
  blob_reset(&to);
  blob_reset(&out);  
}


/*
** Write a line of web-page output that shows changes that have occurred 
** to a file between two check-ins.
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int diffFlags,        /* Flags for text_diff().  Zero to omit diffs */

  int mperm             /* executable or symlink permission for zNew */
){
  if( !g.perm.History ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
      @  for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( diffFlags ){



      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>

    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
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
    }else if( zOld ){
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
    }
    if( showDiff ){
      if( sideBySide ){
        generate_sbsdiff(zOld, zNew);
      }else{
        @ <blockquote><pre>
        append_diff(zOld, zNew);
        @ </pre></blockquote>
      }
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
    }
    @ </p>
  }
}


































/*
** WEBPAGE: vinfo
** WEBPAGE: ci
** URL:  /ci?name=RID|ARTIFACTID
**







|
<
<
<
|
|
|
<







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







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
    }else if( zOld ){
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
    }
    if( diffFlags ){



      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>

    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
    }
    @ </p>
  }
}

/*
** Construct an appropriate diffFlag for text_diff() based on query
** parameters and the to boolean arguments.
*/
int construct_diff_flags(int showDiff, int sideBySide){
  int diffFlags;
  if( showDiff==0 ){
    diffFlags = 0;  /* Zero means do not show any diff */
  }else{
    int x;
    if( sideBySide ){
      diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS;

      /* "dw" query parameter determines width of each column */
      x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1);
      if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK;
      diffFlags += x;
    }else{
      diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS;
    }

    /* "dc" query parameter determines lines of context */
    x = atoi(PD("dc","7"));
    if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
    diffFlags += x;

    /* The "noopt" parameter disables diff optimization */
    if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
  }
  return diffFlags;
}


/*
** WEBPAGE: vinfo
** WEBPAGE: ci
** URL:  /ci?name=RID|ARTIFACTID
**
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
** shown, without diffs.  This behavior is inverted if the
** "show-version-diffs" setting is turned on.
*/
void ci_page(void){
  Stmt q;
  int rid;
  int isLeaf;
  int showDiff;
  int sideBySide;

  const char *zName;   /* Name of the checkin to be displayed */
  const char *zUuid;   /* UUID of zName */
  const char *zParent; /* UUID of the parent checkin (if any) */

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = P("name");







|
|
>







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
** shown, without diffs.  This behavior is inverted if the
** "show-version-diffs" setting is turned on.
*/
void ci_page(void){
  Stmt q;
  int rid;
  int isLeaf;
  int showDiff;        /* True to show diffs */
  int sideBySide;      /* True for side-by-side diffs */
  int diffFlags;       /* Flag parameter for text_diff() */
  const char *zName;   /* Name of the checkin to be displayed */
  const char *zUuid;   /* UUID of zName */
  const char *zParent; /* UUID of the parent checkin (if any) */

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = P("name");
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
       "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"
       "       (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
       "  FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
       " WHERE mlink.mid=%d"
       " ORDER BY name /*sort*/",
       rid
    );

    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q,0);
      int mperm = db_column_int(&q, 1);
      const char *zOld = db_column_text(&q,2);
      const char *zNew = db_column_text(&q,3);
      const char *zOldName = db_column_text(&q, 4);
      append_file_change_line(zName, zOld, zNew, zOldName, showDiff,
            sideBySide, mperm);
    }
    db_finalize(&q);
  }
  style_footer();
}

/*







>






|
<







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
       "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"
       "       (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
       "  FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
       " WHERE mlink.mid=%d"
       " ORDER BY name /*sort*/",
       rid
    );
    diffFlags = construct_diff_flags(showDiff, sideBySide);
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q,0);
      int mperm = db_column_int(&q, 1);
      const char *zOld = db_column_text(&q,2);
      const char *zNew = db_column_text(&q,3);
      const char *zOldName = db_column_text(&q, 4);
      append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm);

    }
    db_finalize(&q);
  }
  style_footer();
}

/*
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
**
** Show all differences between two checkins.  
*/
void vdiff_page(void){
  int ridFrom, ridTo;
  int showDetail = 0;
  int sideBySide = 0;

  Manifest *pFrom, *pTo;
  ManifestFile *pFileFrom, *pFileTo;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  login_anonymous_available();

  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;

  showDetail = atoi(PD("detail","0"));
  sideBySide = atoi(PD("sbs","1"));
  if( !sideBySide ){
    style_submenu_element("Side-by-side Diff", "sbsdiff",
                          "%s/vdiff?from=%T&to=%T&detail=%d&sbs=1",
                          g.zTop, P("from"), P("to"), showDetail);
  }else{
    style_submenu_element("Unified Diff", "udiff",
                          "%s/vdiff?from=%T&to=%T&detail=%d&sbs=0",
                          g.zTop, P("from"), P("to"), showDetail);
  }
  style_header("Check-in Differences");
  @ <h2>Difference From:</h2><blockquote>
  checkin_description(ridFrom);
  @ </blockquote><h2>To:</h2><blockquote>
  checkin_description(ridTo);
  @ </blockquote><hr /><p>

  manifest_file_rewind(pFrom);
  pFileFrom = manifest_file_next(pFrom, 0);
  manifest_file_rewind(pTo);
  pFileTo = manifest_file_next(pTo, 0);

  while( pFileFrom || pFileTo ){
    int cmp;
    if( pFileFrom==0 ){
      cmp = +1;
    }else if( pFileTo==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
    }
    if( cmp<0 ){
      append_file_change_line(pFileFrom->zName, 
                              pFileFrom->zUuid, 0, 0, 0, 0, 0);
      pFileFrom = manifest_file_next(pFrom, 0);
    }else if( cmp>0 ){
      append_file_change_line(pFileTo->zName, 
                              0, pFileTo->zUuid, 0, 0, 0,
                              manifest_file_mperm(pFileTo));
      pFileTo = manifest_file_next(pTo, 0);
    }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
      /* No changes */
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }else{
      append_file_change_line(pFileFrom->zName, 
                              pFileFrom->zUuid,
                              pFileTo->zUuid, 0, showDetail, sideBySide,
                              manifest_file_mperm(pFileTo));
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);







>











>

|




















>











|



|









|







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
**
** Show all differences between two checkins.  
*/
void vdiff_page(void){
  int ridFrom, ridTo;
  int showDetail = 0;
  int sideBySide = 0;
  int diffFlags = 0;
  Manifest *pFrom, *pTo;
  ManifestFile *pFileFrom, *pFileTo;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  login_anonymous_available();

  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;
  sideBySide = atoi(PD("sbs","1"));
  showDetail = atoi(PD("detail","0"));
  if( !showDetail && sideBySide ) showDetail = 1;
  if( !sideBySide ){
    style_submenu_element("Side-by-side Diff", "sbsdiff",
                          "%s/vdiff?from=%T&to=%T&detail=%d&sbs=1",
                          g.zTop, P("from"), P("to"), showDetail);
  }else{
    style_submenu_element("Unified Diff", "udiff",
                          "%s/vdiff?from=%T&to=%T&detail=%d&sbs=0",
                          g.zTop, P("from"), P("to"), showDetail);
  }
  style_header("Check-in Differences");
  @ <h2>Difference From:</h2><blockquote>
  checkin_description(ridFrom);
  @ </blockquote><h2>To:</h2><blockquote>
  checkin_description(ridTo);
  @ </blockquote><hr /><p>

  manifest_file_rewind(pFrom);
  pFileFrom = manifest_file_next(pFrom, 0);
  manifest_file_rewind(pTo);
  pFileTo = manifest_file_next(pTo, 0);
  diffFlags = construct_diff_flags(showDetail, sideBySide);
  while( pFileFrom || pFileTo ){
    int cmp;
    if( pFileFrom==0 ){
      cmp = +1;
    }else if( pFileTo==0 ){
      cmp = -1;
    }else{
      cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
    }
    if( cmp<0 ){
      append_file_change_line(pFileFrom->zName, 
                              pFileFrom->zUuid, 0, 0, 0, 0);
      pFileFrom = manifest_file_next(pFrom, 0);
    }else if( cmp>0 ){
      append_file_change_line(pFileTo->zName, 
                              0, pFileTo->zUuid, 0, 0,
                              manifest_file_mperm(pFileTo));
      pFileTo = manifest_file_next(pTo, 0);
    }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
      /* No changes */
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }else{
      append_file_change_line(pFileFrom->zName, 
                              pFileFrom->zUuid,
                              pFileTo->zUuid, 0, diffFlags,
                              manifest_file_mperm(pFileTo));
      pFileFrom = manifest_file_next(pFrom, 0);
      pFileTo = manifest_file_next(pTo, 0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);
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
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  Blob c1, c2, diff, *pOut;
  char *zV1;
  char *zV2;



  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();
  sideBySide = atoi(PD("sbs","1"));
  zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
  zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
  isPatch = P("patch")!=0;
  if( isPatch ){
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");

  }else{
    blob_zero(&diff);
    pOut = &diff;






  }
  if( !sideBySide || isPatch ){

    content_get(v1, &c1);
    content_get(v2, &c2);
    text_diff(&c1, &c2, pOut, 4 | 0);
    blob_reset(&c1);
    blob_reset(&c2);
  }
  if( !isPatch ){
    style_header("Diff");
    style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
                          g.zTop, P("v1"), P("v2"));
    if( !sideBySide ){
      style_submenu_element("Side-by-side Diff", "sbsdiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=1",
                            g.zTop, P("v1"), P("v2"));
    }else{
      style_submenu_element("Unified Diff", "udiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=0",
                            g.zTop, P("v1"), P("v2"));
    }






    @ <h2>Differences From
    @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);

    @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);

    @ <hr />
    if( sideBySide ){
      generate_sbsdiff(zV1, zV2);
    }else{
      @ <blockquote><pre>
      @ %h(blob_str(&diff))
      @ </pre></blockquote>
    }
    blob_reset(&diff);
    style_footer();
  }
}

/*
** WEBPAGE: raw







>
>













>



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














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

<
<
<
|
|
|
<







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
void diff_page(void){
  int v1, v2;
  int isPatch;
  int sideBySide;
  Blob c1, c2, diff, *pOut;
  char *zV1;
  char *zV2;
  int diffFlags;
  const char *zStyle = "sbsdiff";

  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();
  sideBySide = atoi(PD("sbs","1"));
  zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
  zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
  isPatch = P("patch")!=0;
  if( isPatch ){
    pOut = cgi_output_blob();
    cgi_set_content_type("text/plain");
    diffFlags = 4;
  }else{
    blob_zero(&diff);
    pOut = &diff;
    diffFlags = construct_diff_flags(1, sideBySide);
    if( sideBySide ){
      zStyle = "sbsdiff";
    }else{
      diffFlags |= DIFF_LINENO;
      zStyle = "udiff";
    }

  }
  content_get(v1, &c1);
  content_get(v2, &c2);
  text_diff(&c1, &c2, pOut, diffFlags | DIFF_HTML );
  blob_reset(&c1);
  blob_reset(&c2);

  if( !isPatch ){
    style_header("Diff");
    style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
                          g.zTop, P("v1"), P("v2"));
    if( !sideBySide ){
      style_submenu_element("Side-by-side Diff", "sbsdiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=1",
                            g.zTop, P("v1"), P("v2"));
    }else{
      style_submenu_element("Unified Diff", "udiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=0",
                            g.zTop, P("v1"), P("v2"));
    }

    if( P("smhdr")!=0 ){
      @ <h2>Differences From Artifact
      @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To
      @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2>
    }else{
      @ <h2>Differences From
      @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
      object_description(v1, 0, 0);
      @ <h2>To Artifact
      @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
      object_description(v2, 0, 0);
    }
    @ <hr />



    @ <div class="%s(zStyle)">
    @ %s(blob_str(&diff))
    @ </div>

    blob_reset(&diff);
    style_footer();
  }
}

/*
** WEBPAGE: raw
Changes to src/json.c.
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
  "payload" /* payload */,
  "requestId" /*requestId*/,
  "resultCode" /*resultCode*/,
  "resultText" /*resultText*/,
  "timestamp" /*timestamp*/
};

/*
** Internal helpers to manipulate a byte array as a bitset. The B
** argument must be-a array at least (BIT/8+1) bytes long.
** The BIT argument is the bit number to query/set/clear/toggle.
*/
#define BITSET_BYTEFOR(B,BIT) ((B)[ BIT / 8 ])
#define BITSET_SET(B,BIT) ((BITSET_BYTEFOR(B,BIT) |= (0x01 << (BIT%8))),0x01)
#define BITSET_UNSET(B,BIT) ((BITSET_BYTEFOR(B,BIT) &= ~(0x01 << (BIT%8))),0x00)
#define BITSET_GET(B,BIT) ((BITSET_BYTEFOR(B,BIT) & (0x01 << (BIT%8))) ? 0x01 : 0x00)
#define BITSET_TOGGLE(B,BIT) (BITSET_GET(B,BIT) ? (BITSET_UNSET(B,BIT)) : (BITSET_SET(B,BIT)))


/* Timer code taken from sqlite3's shell.c, modified slightly.
   FIXME: move the timer into the fossil core API so that we can
   start the timer early on in the app init phase. Right now we're
   just timing the json ops themselves.
*/
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)







<
<
<
<
<
<
<
<
<
<
<







50
51
52
53
54
55
56











57
58
59
60
61
62
63
  "payload" /* payload */,
  "requestId" /*requestId*/,
  "resultCode" /*resultCode*/,
  "resultText" /*resultText*/,
  "timestamp" /*timestamp*/
};













/* Timer code taken from sqlite3's shell.c, modified slightly.
   FIXME: move the timer into the fossil core API so that we can
   start the timer early on in the app init phase. Right now we're
   just timing the json ops themselves.
*/
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
93
94
95
96
97
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113

/*
** Print the timing results.
*/
static double endTimer(void){
  struct rusage sEnd;
  getrusage(RUSAGE_SELF, &sEnd);
  return timeDiff(&sBegin.ru_utime, &sEnd.ru_utime)
    + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime);
#if 0
  printf("CPU Time: user %f sys %f\n",
         timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
         timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
#endif


}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER 1

#elif (defined(_WIN32) || defined(WIN32))







<
<





>
>







82
83
84
85
86
87
88


89
90
91
92
93
94
95
96
97
98
99
100
101
102

/*
** Print the timing results.
*/
static double endTimer(void){
  struct rusage sEnd;
  getrusage(RUSAGE_SELF, &sEnd);


#if 0
  printf("CPU Time: user %f sys %f\n",
         timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
         timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
#endif
  return timeDiff(&sBegin.ru_utime, &sEnd.ru_utime)
    + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime);
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER 1

#elif (defined(_WIN32) || defined(WIN32))
171
172
173
174
175
176
177

178
179
180
181
182
183
184
static double endTimer(void){
  if(getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
    return timeDiff(&ftUserBegin, &ftUserEnd) +
      timeDiff(&ftKernelBegin, &ftKernelEnd);
  }

}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER hasTimer()

#else







>







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
static double endTimer(void){
  if(getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
    return timeDiff(&ftUserBegin, &ftUserEnd) +
      timeDiff(&ftKernelBegin, &ftKernelEnd);
  }
  return 0.0;
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER hasTimer()

#else
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
static char const * json_err_cstr( int errCode ){
  switch( errCode ){
    case 0: return "Success";
#define C(X,V) case FSL_JSON_E_ ## X: return V

    C(GENERIC,"Generic error");
    C(INVALID_REQUEST,"Invalid request");
    C(UNKNOWN_COMMAND,"Unknown Command");
    C(UNKNOWN,"Unknown error");
    C(TIMEOUT,"Timeout reached");
    C(ASSERT,"Assertion failed");
    C(ALLOC,"Resource allocation failed");
    C(NYI,"Not yet implemented");
    C(PANIC,"x");
    C(MANIFEST_READ_FAILED,"Reading artifact manifest failed");







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
static char const * json_err_cstr( int errCode ){
  switch( errCode ){
    case 0: return "Success";
#define C(X,V) case FSL_JSON_E_ ## X: return V

    C(GENERIC,"Generic error");
    C(INVALID_REQUEST,"Invalid request");
    C(UNKNOWN_COMMAND,"Unknown command or subcommand");
    C(UNKNOWN,"Unknown error");
    C(TIMEOUT,"Timeout reached");
    C(ASSERT,"Assertion failed");
    C(ALLOC,"Resource allocation failed");
    C(NYI,"Not yet implemented");
    C(PANIC,"x");
    C(MANIFEST_READ_FAILED,"Reading artifact manifest failed");
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  }else{
    char const * cv = PD(zKey,NULL);
    if(!cv && !g.isHTTP){
      /* reminder to self: in CLI mode i'd like to try
         find_option(zKey,NULL,XYZ) here, but we don't have a sane
         default for the XYZ param here.
      */
      cv = getenv(zKey);
    }
    if(cv){/*transform it to JSON for later use.*/
      /* use sscanf() to figure out if it's an int,
         and transform it to JSON int if it is.

         FIXME: use strtol(), since it has more accurate
         error handling.







|







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  }else{
    char const * cv = PD(zKey,NULL);
    if(!cv && !g.isHTTP){
      /* reminder to self: in CLI mode i'd like to try
         find_option(zKey,NULL,XYZ) here, but we don't have a sane
         default for the XYZ param here.
      */
      cv = fossil_getenv(zKey);
    }
    if(cv){/*transform it to JSON for later use.*/
      /* use sscanf() to figure out if it's an int,
         and transform it to JSON int if it is.

         FIXME: use strtol(), since it has more accurate
         error handling.
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
** json_getenv_int(), with the addition that string values which
** either start with a digit 1..9 or the letters [tT] are considered
** to be true. If this function cannot find a matching key/value then
** dflt is returned. e.g. if it finds the key but the value is-a
** Object then dftl is returned.
**
** 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







|







488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
** json_getenv_int(), with the addition that string values which
** either start with a digit 1..9 or the letters [tTyY] are considered
** to be true. If this function cannot find a matching key/value then
** dflt is returned. e.g. if it finds the key but the value is-a
** Object then dftl is returned.
**
** 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
520
521
522
523
524
525
526

527
528

529
530
531
532
533
534
535
  }else if( cson_value_is_number(v) ){
    return cson_value_get_integer(v) ? 1 : 0;
  }else if( cson_value_is_string(v) ){
    char const * sv = cson_string_cstr(cson_value_get_string(v));
    if(!*sv || ('0'==*sv)){
      return 0;
    }else{

      return (('t'==*sv) || ('T'==*sv)
              || (('1'<=*sv) && ('9'>=*sv)))

        ? 1 : 0;
    }
  }else if( cson_value_is_bool(v) ){
    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){
    return 0;
  }else{







>
|
|
>







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  }else if( cson_value_is_number(v) ){
    return cson_value_get_integer(v) ? 1 : 0;
  }else if( cson_value_is_string(v) ){
    char const * sv = cson_string_cstr(cson_value_get_string(v));
    if(!*sv || ('0'==*sv)){
      return 0;
    }else{
      return ((('1'<=*sv) && ('9'>=*sv))
              || ('t'==*sv) || ('T'==*sv)
              || ('y'==*sv) || ('Y'==*sv)
              )
        ? 1 : 0;
    }
  }else if( cson_value_is_bool(v) ){
    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){
    return 0;
  }else{
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
}

/*
** An extended form of find_option() which tries to look up a combo
** GET/POST/CLI argument.
**
** zKey must be the GET/POST parameter key. zCLILong must be the "long
** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
** the "short form" CLI flag (if NULL, no short form is used).
**
** If argPos is >=0 and no other match is found,
** json_command_arg(argPos) is also checked.
**
** On error (no match found) NULL is returned.
**







|







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
}

/*
** An extended form of find_option() which tries to look up a combo
** GET/POST/CLI argument.
**
** zKey must be the GET/POST parameter key. zCLILong must be the "long
s** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
** the "short form" CLI flag (if NULL, no short form is used).
**
** If argPos is >=0 and no other match is found,
** json_command_arg(argPos) is also checked.
**
** On error (no match found) NULL is returned.
**
579
580
581
582
583
584
585



586
587
588
589
590
591
592
593
594
595
596
  }
  if(!rc && (argPos>=0)){
    rc = json_command_arg((unsigned char)argPos);
  }
  return rc;
}




char const * json_find_option_cstr(char const * zKey,
                                   char const * zCLILong,
                                   char const * zCLIShort){
  return json_find_option_cstr2(zKey, zCLIShort, 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,







>
>
>



|







571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  }
  if(!rc && (argPos>=0)){
    rc = json_command_arg((unsigned char)argPos);
  }
  return rc;
}

/*
** Short-hand form of json_find_option_cstr2(zKey,zCLILong,zCLIShort,-1).
*/
char const * json_find_option_cstr(char const * zKey,
                                   char const * zCLILong,
                                   char const * zCLIShort){
  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,
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
  if((-1==rc) && fossil_has_json()){
    rc = json_getenv_bool(zKey,-1);
  }
  return (-1==rc) ? dflt : rc;
}

/*
** The integer equivalent of json_find_option_cstr().
** If the option is not found, dftl is returned.
*/
int json_find_option_int(char const * zKey,
                         char const * zCLILong,
                         char const * zCLIShort,
                         int dflt ){
  enum { Magic = -947 };
  int rc = Magic;
  if(!g.isHTTP){
    /* FIXME: use strtol() for better error/dflt handling. */
    char const * opt = find_option(zCLILong ? zCLILong : zKey,
                                   zCLIShort, 1);
    if(NULL!=opt){
      rc = atoi(opt);







|






|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  if((-1==rc) && fossil_has_json()){
    rc = json_getenv_bool(zKey,-1);
  }
  return (-1==rc) ? dflt : rc;
}

/*
** The integer equivalent of json_find_option_cstr2().
** If the option is not found, dftl is returned.
*/
int json_find_option_int(char const * zKey,
                         char const * zCLILong,
                         char const * zCLIShort,
                         int dflt ){
  enum { Magic = -1947854832 };
  int rc = Magic;
  if(!g.isHTTP){
    /* FIXME: use strtol() for better error/dflt handling. */
    char const * opt = find_option(zCLILong ? zCLILong : zKey,
                                   zCLIShort, 1);
    if(NULL!=opt){
      rc = atoi(opt);
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
                       char separator,
                       char doDeHttp,
                       cson_array * target ){
  char const * p = zStr /* current byte */;
  char const * head  /* current start-of-token */;
  unsigned int len = 0   /* current token's length */;
  int rc = 0   /* return code (number of added elements)*/;
  char skipWs = fossil_isspace(separator) ? 0 : 1;
  assert( zStr && target );
  while( fossil_isspace(*p) ){
    ++p;
  }
  head = p;
  for( ; ; ++p){
    if( !*p || (separator == *p) ){







<







913
914
915
916
917
918
919

920
921
922
923
924
925
926
                       char separator,
                       char doDeHttp,
                       cson_array * target ){
  char const * p = zStr /* current byte */;
  char const * head  /* current start-of-token */;
  unsigned int len = 0   /* current token's length */;
  int rc = 0   /* return code (number of added elements)*/;

  assert( zStr && target );
  while( fossil_isspace(*p) ){
    ++p;
  }
  head = p;
  for( ; ; ++p){
    if( !*p || (separator == *p) ){
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
/*
** Wrapper around json_string_split(), taking the same first 3
** parameters as this function, but returns the results as a JSON
** Array (if splitting produced tokens) or NULL (if splitting failed
** in any way or produced no tokens).
**
** The returned value is owned by the caller. If not NULL then it
** _will_ have a JSON type of Array or Null.
*/
cson_value * json_string_split2( char const * zStr,
                                 char separator,
                                 char doDeHttp ){
  cson_value * v = cson_value_new_array();
  cson_array * a = cson_value_get_array(v);
  int rc = json_string_split( zStr, separator, doDeHttp, a );







|







979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
/*
** Wrapper around json_string_split(), taking the same first 3
** parameters as this function, but returns the results as a JSON
** Array (if splitting produced tokens) or NULL (if splitting failed
** in any way or produced no tokens).
**
** The returned value is owned by the caller. If not NULL then it
** _will_ have a JSON type of Array.
*/
cson_value * json_string_split2( char const * zStr,
                                 char separator,
                                 char doDeHttp ){
  cson_value * v = cson_value_new_array();
  cson_array * a = cson_value_get_array(v);
  int rc = json_string_split( zStr, separator, doDeHttp, a );
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
** before they do any work.
**
** This must only be called once, or an assertion may be triggered.
*/
static void json_mode_bootstrap(){
  static char once = 0  /* guard against multiple runs */;
  char const * zPath = P("PATH_INFO");
  cson_value * pathSplit = NULL;
  assert( (0==once) && "json_mode_bootstrap() called too many times!");
  if( once ){
    return;
  }else{
    once = 1;
  }
  g.json.isJsonMode = 1;







<







1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
** before they do any work.
**
** This must only be called once, or an assertion may be triggered.
*/
static void json_mode_bootstrap(){
  static char once = 0  /* guard against multiple runs */;
  char const * zPath = P("PATH_INFO");

  assert( (0==once) && "json_mode_bootstrap() called too many times!");
  if( once ){
    return;
  }else{
    once = 1;
  }
  g.json.isJsonMode = 1;
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
  }
  if(!g.isHTTP){
    g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
  }

  {/* set up JSON output formatting options. */
    int indent = -1;
    char const * indentStr = NULL;
    indent = json_find_option_int("indent",NULL,"I",-1);
    g.json.outOpt.indentation = (0>indent)
      ? (g.isHTTP ? 0 : 1)
      : (unsigned char)indent;
    g.json.outOpt.addNewline = g.isHTTP
      ? 0
      : (g.json.jsonp ? 0 : 1);
  }

  if( g.isHTTP ){
    json_auth_token()/* will copy our auth token, if any, to fossil's
                        core, which we need before we call
                        login_check_credentials(). */;
    login_check_credentials()/* populates g.perm */;
  }
  else{







    db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
  }
}

/*
** Returns the ndx'th item in the "command path", where index 0 is the
** position of the "json" part of the path. Returns NULL if ndx is out







<
















>
>
>
>
>
>
>







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
  }
  if(!g.isHTTP){
    g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
  }

  {/* set up JSON output formatting options. */
    int indent = -1;

    indent = json_find_option_int("indent",NULL,"I",-1);
    g.json.outOpt.indentation = (0>indent)
      ? (g.isHTTP ? 0 : 1)
      : (unsigned char)indent;
    g.json.outOpt.addNewline = g.isHTTP
      ? 0
      : (g.json.jsonp ? 0 : 1);
  }

  if( g.isHTTP ){
    json_auth_token()/* will copy our auth token, if any, to fossil's
                        core, which we need before we call
                        login_check_credentials(). */;
    login_check_credentials()/* populates g.perm */;
  }
  else{
    /* FIXME: we need an option which allows us to skip this. At least
       one known command (/json/version) does not need an opened
       repo. The problem here is we cannot know which functions need
       it from here (because command dispatching hasn't yet happened)
       and all other commands rely on the repo being opened before
       they are called. A textbook example of lack of foresight :/.
     */
    db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
  }
}

/*
** Returns the ndx'th item in the "command path", where index 0 is the
** position of the "json" part of the path. Returns NULL if ndx is out
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
    return code;
  }
}

/*
** Convenience routine which converts a Julian time value into a Unix
** Epoch timestamp. Requires the db, so this cannot be used before the
** repo is opened (will trigger a fatal error in db_xxx()).

*/
cson_value * json_julian_to_timestamp(double j){
  return cson_value_new_integer((cson_int_t)
           db_int64(0,"SELECT cast(strftime('%%s',%lf) as int)",j)
                                );
}

/*
** Returns a timestamp value.
*/
cson_int_t json_timestamp(){
  return (cson_int_t)time(0);
}

/*
** Returns a new JSON value (owned by the caller) representing
** a timestamp. If timeVal is < 0 then time(0) is used to fetch
** the time, else timeVal is used as-is

*/
cson_value * json_new_timestamp(cson_int_t timeVal){
  return cson_value_new_integer((timeVal<0) ? (cson_int_t)time(0) : timeVal);
}

/*
** Internal helper for json_create_response(). Appends the first
** g.json.dispatchDepth elements of g.json.cmd.a, skipping the first
** one (the "json" part), to a string and returns that string value
** (which is owned by the caller).
*/
static cson_value * json_response_command_path(){
  if(!g.json.cmd.a){
    return NULL;
  }else{
    cson_value * rc = NULL;
    Blob path = empty_blob;
    char const * part;
    unsigned int aLen = g.json.dispatchDepth+1; /*cson_array_length_get(g.json.cmd.a);*/
    unsigned int i = 1;
    for( ; i < aLen; ++i ){
      char const * part = cson_string_cstr(cson_value_get_string(cson_array_get(g.json.cmd.a, i)));
      if(!part){
        fossil_warning("Iterating further than expected in %s.",
                       __FILE__);







|
>













>



|
>

















<







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
    return code;
  }
}

/*
** Convenience routine which converts a Julian time value into a Unix
** Epoch timestamp. Requires the db, so this cannot be used before the
** repo is opened (will trigger a fatal error in db_xxx()). The returned
** value is owned by the caller.
*/
cson_value * json_julian_to_timestamp(double j){
  return cson_value_new_integer((cson_int_t)
           db_int64(0,"SELECT cast(strftime('%%s',%lf) as int)",j)
                                );
}

/*
** Returns a timestamp value.
*/
cson_int_t json_timestamp(){
  return (cson_int_t)time(0);
}

/*
** Returns a new JSON value (owned by the caller) representing
** a timestamp. If timeVal is < 0 then time(0) is used to fetch
** the time, else timeVal is used as-is. The returned value is
** owned by the caller.
*/
cson_value * json_new_timestamp(cson_int_t timeVal){
  return cson_value_new_integer((timeVal<0) ? (cson_int_t)time(0) : timeVal);
}

/*
** Internal helper for json_create_response(). Appends the first
** g.json.dispatchDepth elements of g.json.cmd.a, skipping the first
** one (the "json" part), to a string and returns that string value
** (which is owned by the caller).
*/
static cson_value * json_response_command_path(){
  if(!g.json.cmd.a){
    return NULL;
  }else{
    cson_value * rc = NULL;
    Blob path = empty_blob;

    unsigned int aLen = g.json.dispatchDepth+1; /*cson_array_length_get(g.json.cmd.a);*/
    unsigned int i = 1;
    for( ; i < aLen; ++i ){
      char const * part = cson_string_cstr(cson_value_get_string(cson_array_get(g.json.cmd.a, i)));
      if(!part){
        fossil_warning("Iterating further than expected in %s.",
                       __FILE__);
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
/*
** Creates a new Fossil/JSON response envelope skeleton.  It is owned
** by the caller, who must eventually free it using cson_value_free(),
** or add it to a cson container to transfer ownership. Returns NULL
** on error.
**
** If payload is not NULL and resultCode is 0 then it is set as the
** "payload" property of the returned object.  If resultCode is

** non-zero and payload is not NULL then this function calls
** cson_value_free(payload) and does not insert the payload into the
** response. In either case, onwership of payload is transfered to (or
** shared with, if the caller holds a reference) this function.
**
** pMsg is an optional message string property (resultText) of the
** response. If resultCode is non-0 and pMsg is NULL then
** json_err_cstr() is used to get the error string. The caller may
** provide his own or may use an empty string to suppress the
** resultText property.
**
*/
cson_value * json_create_response( int resultCode,
                                   char const * pMsg,
                                   cson_value * payload){
  cson_value * v = NULL;
  cson_value * tmp = NULL;
  cson_object * o = NULL;
  int rc;
  resultCode = json_dumbdown_rc(resultCode);
  o = cson_new_object();
  v = cson_object_value(o);
  if( ! o ) return NULL;
#define SET(K) if(!tmp) goto cleanup; \
  rc = cson_object_set( o, K, tmp ); \
  if(rc) do{\
    cson_value_free(tmp); \
    tmp = NULL; \
    goto cleanup; \
  }while(0)


  tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID));
  SET("fossil");

  tmp = json_new_timestamp(-1);
  SET(FossilJsonKeys.timestamp);

  if( 0 != resultCode ){
    if( ! pMsg ){







|
>












|
|
|




|











>
|







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
/*
** Creates a new Fossil/JSON response envelope skeleton.  It is owned
** by the caller, who must eventually free it using cson_value_free(),
** or add it to a cson container to transfer ownership. Returns NULL
** on error.
**
** If payload is not NULL and resultCode is 0 then it is set as the
** "payload" property of the returned object.  If resultCode is 0 then
** it defaults to g.json.resultCode. If resultCode is (or defaults to)
** non-zero and payload is not NULL then this function calls
** cson_value_free(payload) and does not insert the payload into the
** response. In either case, onwership of payload is transfered to (or
** shared with, if the caller holds a reference) this function.
**
** pMsg is an optional message string property (resultText) of the
** response. If resultCode is non-0 and pMsg is NULL then
** json_err_cstr() is used to get the error string. The caller may
** provide his own or may use an empty string to suppress the
** resultText property.
**
*/
static cson_value * json_create_response( int resultCode,
                                          char const * pMsg,
                                          cson_value * payload){
  cson_value * v = NULL;
  cson_value * tmp = NULL;
  cson_object * o = NULL;
  int rc;
  resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode);
  o = cson_new_object();
  v = cson_object_value(o);
  if( ! o ) return NULL;
#define SET(K) if(!tmp) goto cleanup; \
  rc = cson_object_set( o, K, tmp ); \
  if(rc) do{\
    cson_value_free(tmp); \
    tmp = NULL; \
    goto cleanup; \
  }while(0)

  
  tmp = json_new_string(MANIFEST_UUID);
  SET("fossil");

  tmp = json_new_timestamp(-1);
  SET(FossilJsonKeys.timestamp);

  if( 0 != resultCode ){
    if( ! pMsg ){
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
** the cgi_xxx() family of functions, this function inherits any
** compression which fossil does for its output.
**
** If alsoOutput is true AND g.isHTTP then cgi_reply() is called to
** flush the output (and headers). Generally only do this if you are
** about to call exit().
**
** !g.isHTTP then alsoOutput is ignored and all output is sent to
** stdout immediately.
**
** For generating the resultText property: if msg is not NULL then it
** is used as-is. If it is NULL then g.zErrMsg is checked, and if that
** is NULL then json_err_cstr(code) is used.
*/
void json_err( int code, char const * msg, char alsoOutput ){







|







1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
** the cgi_xxx() family of functions, this function inherits any
** compression which fossil does for its output.
**
** If alsoOutput is true AND g.isHTTP then cgi_reply() is called to
** flush the output (and headers). Generally only do this if you are
** about to call exit().
**
** If !g.isHTTP then alsoOutput is ignored and all output is sent to
** stdout immediately.
**
** For generating the resultText property: if msg is not NULL then it
** is used as-is. If it is NULL then g.zErrMsg is checked, and if that
** is NULL then json_err_cstr(code) is used.
*/
void json_err( int code, char const * msg, char alsoOutput ){
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
    if(!a){
      a = cson_new_array();
      assert(NULL!=a);
    }
    if(!colNames){
      colNamesV = cson_sqlite3_column_names(pStmt->pStmt);
      assert(NULL != colNamesV);
      cson_value_add_reference(colNamesV);
      colNames = cson_value_get_array(colNamesV);
      assert(NULL != colNames);
    }      
    row = cson_sqlite3_row_to_object2(pStmt->pStmt, colNames);
    if(!row && !warnMsg){
      warnMsg = "Could not convert at least one result row to JSON.";
      continue;







|







1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
    if(!a){
      a = cson_new_array();
      assert(NULL!=a);
    }
    if(!colNames){
      colNamesV = cson_sqlite3_column_names(pStmt->pStmt);
      assert(NULL != colNamesV);
      cson_value_add_reference(colNamesV)/*avoids an ownership problem*/;
      colNames = cson_value_get_array(colNamesV);
      assert(NULL != colNames);
    }      
    row = cson_sqlite3_row_to_object2(pStmt->pStmt, colNames);
    if(!row && !warnMsg){
      warnMsg = "Could not convert at least one result row to JSON.";
      continue;
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
** Executes the given SQL and runs it through
** json_stmt_to_array_of_obj(), returning the result of that
** function. If resetBlob is true then blob_reset(pSql) is called
** after preparing the query.
**
** pTgt has the same semantics as described for
** json_stmt_to_array_of_obj().



*/
cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
                                      char resetBlob){
  Stmt q = empty_Stmt;
  cson_value * pay = NULL;
  assert( blob_size(pSql) > 0 );
  db_prepare(&q, "%s", blob_str(pSql));
  if(resetBlob){
    blob_reset(pSql);
  }
  pay = json_stmt_to_array_of_obj(&q, pTgt);
  db_finalize(&q);
  return pay;

}

/*
** If the given COMMIT rid has any tags associated with it, this
** function returns a JSON Array containing the tag names, else it
** returns NULL.
**
** See info_tags_of_checkin() for more details (this is simply a JSON
** wrapper for that function).



*/
cson_value * json_tags_for_checkin_rid(int rid, char propagatingOnly){
  cson_value * v = NULL;
  char * tags = info_tags_of_checkin(rid, propagatingOnly);
  if(tags){
    if(*tags){
      v = json_string_split2(tags,',',0);







>
>
>


















|
|



>
>
>







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
** Executes the given SQL and runs it through
** json_stmt_to_array_of_obj(), returning the result of that
** function. If resetBlob is true then blob_reset(pSql) is called
** after preparing the query.
**
** pTgt has the same semantics as described for
** json_stmt_to_array_of_obj().
**
** FIXME: change this to take a (char const *) instead of a blob,
** to simplify the trivial use-cases (which don't need a Blob).
*/
cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
                                      char resetBlob){
  Stmt q = empty_Stmt;
  cson_value * pay = NULL;
  assert( blob_size(pSql) > 0 );
  db_prepare(&q, "%s", blob_str(pSql));
  if(resetBlob){
    blob_reset(pSql);
  }
  pay = json_stmt_to_array_of_obj(&q, pTgt);
  db_finalize(&q);
  return pay;

}

/*
** If the given COMMIT rid has any tags associated with it, this
** function returns a JSON Array containing the tag names (owned by
** the caller), else it returns NULL.
**
** See info_tags_of_checkin() for more details (this is simply a JSON
** wrapper for that function).
**
** If there are no tags then this function returns NULL, not an empty
** Array.
*/
cson_value * json_tags_for_checkin_rid(int rid, char propagatingOnly){
  cson_value * v = NULL;
  char * tags = info_tags_of_checkin(rid, propagatingOnly);
  if(tags){
    if(*tags){
      v = json_string_split2(tags,',',0);
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
    cson_array * list = cson_value_get_array(listV);
    cson_value * objV = NULL;
    cson_object * obj = NULL;
    cson_string * kRC;
    cson_string * kSymbol;
    cson_string * kNumber;
    cson_string * kDesc;
    int rc = cson_array_reserve( list, 35 );
    if(rc){
        assert( 0 && "Allocation error.");
        exit(1);
    }
    kRC = cson_new_string("resultCode",10);
    kSymbol = cson_new_string("cSymbol",7);
    kNumber = cson_new_string("number",6);
    kDesc = cson_new_string("description",11);
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
    cson_object_set_s(obj, kRC, json_new_string(json_rc_cstr(FSL_JSON_E_##K)) ); \
    cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) );             \







|
<
<
<
<







1826
1827
1828
1829
1830
1831
1832
1833




1834
1835
1836
1837
1838
1839
1840
    cson_array * list = cson_value_get_array(listV);
    cson_value * objV = NULL;
    cson_object * obj = NULL;
    cson_string * kRC;
    cson_string * kSymbol;
    cson_string * kNumber;
    cson_string * kDesc;
    cson_array_reserve( list, 35 );




    kRC = cson_new_string("resultCode",10);
    kSymbol = cson_new_string("cSymbol",7);
    kNumber = cson_new_string("number",6);
    kDesc = cson_new_string("description",11);
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
    cson_object_set_s(obj, kRC, json_new_string(json_rc_cstr(FSL_JSON_E_##K)) ); \
    cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) );             \
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903


1904
1905
1906
1907
1908
1909
1910
  jobj = cson_value_get_object(jval);
#define FSET(X,K) cson_object_set( jobj, K, cson_value_new_string(X,strlen(X)))
  FSET(MANIFEST_UUID,"manifestUuid");
  FSET(MANIFEST_VERSION,"manifestVersion");
  FSET(MANIFEST_DATE,"manifestDate");
  FSET(MANIFEST_YEAR,"manifestYear");
  FSET(RELEASE_VERSION,"releaseVersion");
#undef FSET
  cson_object_set( jobj, "releaseVersionNumber",
                   cson_value_new_integer(RELEASE_VERSION_NUMBER) );
  cson_object_set( jobj, "resultCodeParanoiaLevel",
                   cson_value_new_integer(g.json.errorDetailParanoia) );


  return jval;
}


/*
** Returns the current user's capabilities string as a String value.
** Returned value is owned by the caller, and will only be NULL if







<




>
>







1897
1898
1899
1900
1901
1902
1903

1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
  jobj = cson_value_get_object(jval);
#define FSET(X,K) cson_object_set( jobj, K, cson_value_new_string(X,strlen(X)))
  FSET(MANIFEST_UUID,"manifestUuid");
  FSET(MANIFEST_VERSION,"manifestVersion");
  FSET(MANIFEST_DATE,"manifestDate");
  FSET(MANIFEST_YEAR,"manifestYear");
  FSET(RELEASE_VERSION,"releaseVersion");

  cson_object_set( jobj, "releaseVersionNumber",
                   cson_value_new_integer(RELEASE_VERSION_NUMBER) );
  cson_object_set( jobj, "resultCodeParanoiaLevel",
                   cson_value_new_integer(g.json.errorDetailParanoia) );
  FSET(FOSSIL_JSON_API_VERSION, "jsonApiVersion" );
#undef FSET
  return jval;
}


/*
** Returns the current user's capabilities string as a String value.
** Returned value is owned by the caller, and will only be NULL if
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
  const char *zDb;
  enum { BufLen = 1000 };
  char zBuf[BufLen];
  cson_value * jv = NULL;
  cson_object * jo = NULL;
  cson_value * jv2 = NULL;
  cson_object * jo2 = NULL;

  if( !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  full = json_find_option_bool("full",NULL,"f",0);
#define SETBUF(O,K) cson_object_set(O, K, cson_value_new_string(zBuf, strlen(zBuf)));

  jv = cson_value_new_object();
  jo = cson_value_get_object(jv);

  sqlite3_snprintf(BufLen, zBuf, db_get("project-name",""));
  SETBUF(jo, "projectName");

  /* FIXME: don't include project-description until we ensure that
     zBuf will always be big enough. We "should" replace zBuf
     with a blob for this purpose.
  */


  fsize = file_size(g.zRepositoryName);
  cson_object_set(jo, "repositorySize", cson_value_new_integer((cson_int_t)fsize));

  if(full){
    n = db_int(0, "SELECT count(*) FROM blob");
    m = db_int(0, "SELECT count(*) FROM delta");
    cson_object_set(jo, "blobCount", cson_value_new_integer((cson_int_t)n));







>











|
|
>
|
<
|
<
>
>







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
  const char *zDb;
  enum { BufLen = 1000 };
  char zBuf[BufLen];
  cson_value * jv = NULL;
  cson_object * jo = NULL;
  cson_value * jv2 = NULL;
  cson_object * jo2 = NULL;
  char * zTmp = NULL;
  if( !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  full = json_find_option_bool("full",NULL,"f",0);
#define SETBUF(O,K) cson_object_set(O, K, cson_value_new_string(zBuf, strlen(zBuf)));

  jv = cson_value_new_object();
  jo = cson_value_get_object(jv);

  zTmp = db_get("project-name",NULL);
  cson_object_set(jo, "projectName", json_new_string(zTmp));
  free(zTmp);
  zTmp = db_get("project-description",NULL);

  cson_object_set(jo, "projectDescription", json_new_string(zTmp));

  free(zTmp);
  zTmp = NULL;
  fsize = file_size(g.zRepositoryName);
  cson_object_set(jo, "repositorySize", cson_value_new_integer((cson_int_t)fsize));

  if(full){
    n = db_int(0, "SELECT count(*) FROM blob");
    m = db_int(0, "SELECT count(*) FROM delta");
    cson_object_set(jo, "blobCount", cson_value_new_integer((cson_int_t)n));
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
    if((zPages+1)->name){
      blob_append(pOut, ", ",2);
    }
  }
  return i;
}


























cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
  JsonPageDef const * def;
  char const * cmd = json_command_arg(1+g.json.dispatchDepth);
  assert( NULL != pages );
  if( ! cmd ){
    Blob cmdNames = empty_blob;
    json_pagedefs_to_string(pages, &cmdNames);
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "No subcommand specified. Try one of (%s).",
                 blob_str(&cmdNames));
    blob_reset(&cmdNames);

    return NULL;
  }
  def = json_handler_for_name( cmd, pages );
  if(!def){
    g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND;

    return NULL;
  }
  else{
    ++g.json.dispatchDepth;
    return (*def->func)();
  }
}







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






<
|
<
|
<
<
>




|
>







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
    if((zPages+1)->name){
      blob_append(pOut, ", ",2);
    }
  }
  return i;
}

/*
** Creates an error message using zErrPrefix and the given array of
** JSON command definitions, and sets the g.json error state to
** reflect FSL_JSON_E_MISSING_ARGS. If zErrPrefix is NULL then
** some default is used (e.g. "Try one of: "). If it is "" then
** no prefix is used.
**
** The intention is to provide the user (via the response.resultText)
** a list of available commands/subcommands.
**
*/
void json_dispatch_missing_args_err( JsonPageDef const * pCommands,
                                     char const * zErrPrefix ){
  Blob cmdNames = empty_blob;
  blob_init(&cmdNames,NULL,0);
  if( !zErrPrefix ) {
    zErrPrefix = "Try one of: ";
  }
  blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
  json_pagedefs_to_string(pCommands, &cmdNames);
  json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
               blob_str(&cmdNames));
  blob_reset(&cmdNames);
}

cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
  JsonPageDef const * def;
  char const * cmd = json_command_arg(1+g.json.dispatchDepth);
  assert( NULL != pages );
  if( ! cmd ){

    json_dispatch_missing_args_err(pages,

                                   "No subcommand specified. "


                                   "Try one of: ");
    return NULL;
  }
  def = json_handler_for_name( cmd, pages );
  if(!def){
    json_set_err(FSL_JSON_E_UNKNOWN_COMMAND,
                 "Unknown subcommand: %s", cmd);
    return NULL;
  }
  else{
    ++g.json.dispatchDepth;
    return (*def->func)();
  }
}
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
cson_value * json_page_query();
/* Impl in json_report.c. */
cson_value * json_page_report();
/* Impl in json_tag.c. */
cson_value * json_page_tag();
/* Impl in json_user.c. */
cson_value * json_page_user();





/*
** Mapping of names to JSON pages/commands.  Each name is a subpath of
** /json (in CGI mode) or a subcommand of the json command in CLI mode
*/
static const JsonPageDef JsonPageDefs[] = {
/* please keep alphabetically sorted (case-insensitive) for maintenance reasons. */
{"anonymousPassword", json_page_anon_password, 0},
{"artifact", json_page_artifact, 0},
{"branch", json_page_branch,0},
{"cap", json_page_cap, 0},

{"diff", json_page_diff, 0},
{"dir", json_page_nyi, 0},

{"g", json_page_g, 0},
{"HAI",json_page_version,0},
{"login",json_page_login,0},
{"logout",json_page_logout,0},
{"query",json_page_query,0},
{"rebuild",json_page_rebuild,0},
{"report", json_page_report, 0},
{"resultCodes", json_page_resultCodes,0},
{"stat",json_page_stat,0},
{"tag", json_page_tag,0},
{"ticket", json_page_nyi,0},
{"timeline", json_page_timeline,0},
{"user",json_page_user,0},
{"version",json_page_version,0},
{"whoami",json_page_whoami,0},
{"wiki",json_page_wiki,0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*

** Mapping of /json/ticket/XXX commands/paths to callbacks.




*/



static const JsonPageDef JsonPageDefs_Ticket[] = {
{"get", json_page_nyi, 0},
{"list", json_page_nyi, 0},

{"save", json_page_nyi, 1},
{"create", json_page_nyi, 1},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};







/*
** Mapping of /json/artifact/XXX commands/paths to callbacks.
*/

static const JsonPageDef JsonPageDefs_Artifact[] = {
{"vinfo", json_page_nyi, 0},
{"finfo", json_page_nyi, 0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};

/*

** Mapping of /json/tag/XXX commands/paths to callbacks.
*/
static const JsonPageDef JsonPageDefs_Tag[] = {
{"list", json_page_nyi, 0},
{"create", json_page_nyi, 1},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** WEBPAGE: json
**
** Pages under /json/... must be entered into JsonPageDefs.
** This function dispatches them, and is the HTTP equivalent of
** json_cmd_top().
*/
void json_page_top(void){
  int rc = FSL_JSON_E_UNKNOWN_COMMAND;
  char const * cmd;
  cson_value * payload = NULL;
  JsonPageDef const * pageDef = NULL;
  BEGIN_TIMER;
  json_mode_bootstrap();
  cmd = json_command_arg(1);
  if(!cmd || !*cmd){
    goto usage;
  }
  /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/
  pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);
  if( ! pageDef ){
    json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 0 );
    return;
  }else if( pageDef->runMode < 0 /*CLI only*/){
    rc = FSL_JSON_E_WRONG_MODE;
  }else{
    rc = 0;
    g.json.dispatchDepth = 1;
    payload = (*pageDef->func)();
  }
  if( g.json.resultCode ){
    cson_value_free(payload);
    json_err(g.json.resultCode, NULL, 0);
  }else{
    cson_value * root = json_create_response(rc, NULL, payload);
    json_send_response(root);
    cson_value_free(root);
  }

  return;
  usage:
  {
    Blob cmdNames = empty_blob;
    blob_init(&cmdNames,
              "No command (sub-path) specified. Try one of: ",
              -1);
    json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
    json_err(FSL_JSON_E_MISSING_ARGS,
             blob_str(&cmdNames), 0);
    blob_reset(&cmdNames);
  }

}
#endif /* FOSSIL_ENABLE_JSON */

#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** This function dispatches json commands and is the CLI equivalent of
** json_page_top().
**
** COMMAND: json
**
** Usage: %fossil json SUBCOMMAND




**
** The commands include:
**


**   branch
**   cap








**   stat

**   timeline

**   version (alias: HAI)
**   wiki
**
**
** TODOs:


**
**   tag
**   ticket
**   ...

**
*/
void json_cmd_top(void){
  char const * cmd = NULL;
  int rc = FSL_JSON_E_UNKNOWN_COMMAND;
  cson_value * payload = NULL;
  JsonPageDef const * pageDef;
  BEGIN_TIMER;
  memset( &g.perm, 0xff, sizeof(g.perm) )
    /* In CLI mode fossil does not use permissions
       and they all default to false. We enable them
       here because (A) fossil doesn't use them in local
       mode but (B) having them set gives us one less
       difference in the CLI/CGI/Server-mode JSON
       handling.
    */
    ;
  json_main_bootstrap();
  json_mode_bootstrap();
  if( 2 > cson_array_length_get(g.json.cmd.a) ){
    goto usage;
  }
  db_find_and_open_repository(0, 0);
#if 0
  json_warn(FSL_JSON_W_ROW_TO_JSON_FAILED, "Just testing.");
  json_warn(FSL_JSON_W_ROW_TO_JSON_FAILED, "Just testing again.");
#endif
  cmd = json_command_arg(1);
  if( !cmd || !*cmd ){
    goto usage;
  }
  pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);
  if( ! pageDef ){
    json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 1 );
    return;
  }else if( pageDef->runMode > 0 /*HTTP only*/){
    rc = FSL_JSON_E_WRONG_MODE;
  }else{
    rc = 0;
    g.json.dispatchDepth = 1;
    payload = (*pageDef->func)();
  }
  if( g.json.resultCode ){
    cson_value_free(payload);
    json_err(g.json.resultCode, NULL, 1);
  }else{
    payload = json_create_response(rc, NULL, payload);
    json_send_response(payload);
    cson_value_free( payload );
    if((0 != rc) && !g.isHTTP){
      /* FIXME: we need a way of passing this error back
         up to the routine which called this callback.
         e.g. add g.errCode.
      */
      fossil_exit(1);
    }
  }
  return;
  usage:
  {
    Blob cmdNames = empty_blob;
    blob_init(&cmdNames,

              "No subcommand specified. Try one of: ", -1);

    json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
    json_err(FSL_JSON_E_MISSING_ARGS,
             blob_str(&cmdNames), 1);
    blob_reset(&cmdNames);

    fossil_exit(1);
  }
}
#endif /* FOSSIL_ENABLE_JSON */

#undef BITSET_BYTEFOR
#undef BITSET_SET
#undef BITSET_UNSET
#undef BITSET_GET
#undef BITSET_TOGGLE
#endif /* FOSSIL_ENABLE_JSON */







>
>
>
>











>

|
>










|









<

>
|
>
>
>
>

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










<
|
<
<


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

|

|








|
>
>
>
>



>
>


>
>
>
>
>
>
>
>

>

>

|
|

<
>
>

<
<
<
>




|
<
<















<








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



<
|
>
|
>
|
|
<
<
>



|

<
<
<
<
<

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
cson_value * json_page_query();
/* Impl in json_report.c. */
cson_value * json_page_report();
/* Impl in json_tag.c. */
cson_value * json_page_tag();
/* Impl in json_user.c. */
cson_value * json_page_user();
/* Impl in json_config.c. */
cson_value * json_page_config();
/* Impl in json_finfo.c. */
cson_value * json_page_finfo();

/*
** Mapping of names to JSON pages/commands.  Each name is a subpath of
** /json (in CGI mode) or a subcommand of the json command in CLI mode
*/
static const JsonPageDef JsonPageDefs[] = {
/* please keep alphabetically sorted (case-insensitive) for maintenance reasons. */
{"anonymousPassword", json_page_anon_password, 0},
{"artifact", json_page_artifact, 0},
{"branch", json_page_branch,0},
{"cap", json_page_cap, 0},
{"config", json_page_config, 0 },
{"diff", json_page_diff, 0},
/*{"dir", json_page_nyi, 0},*/
{"finfo", json_page_finfo, 0},
{"g", json_page_g, 0},
{"HAI",json_page_version,0},
{"login",json_page_login,0},
{"logout",json_page_logout,0},
{"query",json_page_query,0},
{"rebuild",json_page_rebuild,0},
{"report", json_page_report, 0},
{"resultCodes", json_page_resultCodes,0},
{"stat",json_page_stat,0},
{"tag", json_page_tag,0},
/*{"ticket", json_page_nyi,0},*/
{"timeline", json_page_timeline,0},
{"user",json_page_user,0},
{"version",json_page_version,0},
{"whoami",json_page_whoami,0},
{"wiki",json_page_wiki,0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*
** Internal helper for json_cmd_top() and json_page_top().
**
** Searches JsonPageDefs for a command with the given name. If found,
** it is used to generate and output a JSON response. If not found, it
** generates a JSON-style error response. Returns 0 on success, non-0
** on error. On error it will set g.json's error state.
*/
static int json_dispatch_root_command( char const * zCommand ){
  int rc = 0;
  cson_value * payload = NULL;
  JsonPageDef const * pageDef = NULL;
  pageDef = json_handler_for_name(zCommand,&JsonPageDefs[0]);
  if( ! pageDef ){
    rc = FSL_JSON_E_UNKNOWN_COMMAND;
    json_set_err( rc, "Unknown command: %s", zCommand );
  }else if( pageDef->runMode < 0 /*CLI only*/){



    rc = FSL_JSON_E_WRONG_MODE;
  }else if( (g.isHTTP && (pageDef->runMode < 0 /*CLI only*/))
            ||
            (!g.isHTTP && (pageDef->runMode > 0 /*HTTP only*/))
            ){
    rc = FSL_JSON_E_WRONG_MODE;
  }



  else{
    rc = 0;
    g.json.dispatchDepth = 1;
    payload = (*pageDef->func)();



  }

  payload = json_create_response(rc, NULL, payload);
  json_send_response(payload);


  cson_value_free(payload);
  return rc;



}

#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** WEBPAGE: json
**
** Pages under /json/... must be entered into JsonPageDefs.
** This function dispatches them, and is the HTTP equivalent of
** json_cmd_top().
*/
void json_page_top(void){

  char const * zCommand;


  BEGIN_TIMER;
  json_mode_bootstrap();
  zCommand = json_command_arg(1);
  if(!zCommand || !*zCommand){



    json_dispatch_missing_args_err( JsonPageDefs,







                                    "No command (sub-path) specified."










                                    " Try one of: ");
    return;










  }
  json_dispatch_root_command( zCommand );
}
#endif /* FOSSIL_ENABLE_JSON for mkindex */

#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** This function dispatches json commands and is the CLI equivalent of
** json_page_top().
**
** COMMAND: json
**
** Usage: %fossil json SUBCOMMAND ?OPTIONS?
**
** In CLI mode, the -R REPO common option is supported. Due to limitations
** in the argument dispatching code, any -FLAGS must come after the final
** sub- (or subsub-) command.
**
** The commands include:
**
**   anonymousPassord
**   artifact
**   branch
**   cap
**   diff
**   g
**   login
**   logout
**   query
**   rebuild
**   report
**   resultCodes
**   stat
**   tag
**   timeline
**   user
**   version (alias: HAI)
**   whoami
**   wiki
**

** Run '%fossil json' without any subcommand to see the full list (but be
** aware that some listed might not yet be implemented).
**



** PS: the notable TODO-commands include: config, dir, finfo, ticket
**
*/
void json_cmd_top(void){
  char const * cmd = NULL;
  int rc = 0;


  BEGIN_TIMER;
  memset( &g.perm, 0xff, sizeof(g.perm) )
    /* In CLI mode fossil does not use permissions
       and they all default to false. We enable them
       here because (A) fossil doesn't use them in local
       mode but (B) having them set gives us one less
       difference in the CLI/CGI/Server-mode JSON
       handling.
    */
    ;
  json_main_bootstrap();
  json_mode_bootstrap();
  if( 2 > cson_array_length_get(g.json.cmd.a) ){
    goto usage;
  }

#if 0
  json_warn(FSL_JSON_W_ROW_TO_JSON_FAILED, "Just testing.");
  json_warn(FSL_JSON_W_ROW_TO_JSON_FAILED, "Just testing again.");
#endif
  cmd = json_command_arg(1);
  if( !cmd || !*cmd ){
    goto usage;
  }








  rc = json_dispatch_root_command( cmd );









  if(0 != rc){
    /* FIXME: we need a way of passing this error back
       up to the routine which called this callback.
       e.g. add g.errCode.
    */
    fossil_exit(1);
  }

  return;
  usage:
  {

    cson_value * payload;
    json_dispatch_missing_args_err( JsonPageDefs,
                                    "No subcommand specified."
                                    " Try one of: ");
    payload = json_create_response(0, NULL, NULL);
    json_send_response(payload);


    cson_value_free(payload);
    fossil_exit(1);
  }
}
#endif /* FOSSIL_ENABLE_JSON for mkindex */






#endif /* FOSSIL_ENABLE_JSON */
Changes to src/json_artifact.c.
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
  /**
     JSON construction callback. Creates the contents for the
     payload.artifact property of /json/artifact responses.
  */
  artifact_f func;
} ArtifactDispatchEntry;


























/*
** Generates an artifact Object for the given rid,
** which must refer to a Checkin.
**
** Returned value is NULL or an Object owned by the caller.
*/
cson_value * json_artifact_for_ci( int rid, char showFiles ){
  char * zParent = NULL;
  cson_value * v = NULL;
  Stmt q;
  static cson_value * eventTypeLabel = NULL;
  if(!eventTypeLabel){
    eventTypeLabel = json_new_string("checkin");
    json_gc_add("$EVENT_TYPE_LABEL(commit)", eventTypeLabel);
  }
  zParent = db_text(0,
    "SELECT uuid FROM plink, blob"
    " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
    rid
  );

  db_prepare(&q, 
             "SELECT uuid, "
             " cast(strftime('%%s',mtime) as int), "

             " user, "
             " comment,"
             " strftime('%%s',omtime)"
             " FROM blob, event"
             " WHERE blob.rid=%d"
             "   AND event.objid=%d",
             rid, rid
             );
  if( db_step(&q)==SQLITE_ROW ){
    cson_object * o;
    cson_value * tmpV = NULL;
    const char *zUuid = db_column_text(&q, 0);
    char * zTmp;
    const char *zUser;
    const char *zComment;
    char * zEUser, * zEComment;
    int mtime, omtime;
    v = cson_value_new_object();
    o = cson_value_get_object(v);
#define SET(K,V) cson_object_set(o,(K), (V))
    SET("type", eventTypeLabel );
    SET("uuid",json_new_string(zUuid));
    SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));








    zUser = db_column_text(&q,2);
    zEUser = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_USER, rid);
    if(zEUser){
      SET("user", json_new_string(zEUser));
      if(0!=strcmp(zEUser,zUser)){
        SET("originUser",json_new_string(zUser));
      }
      free(zEUser);
    }else{
      SET("user",json_new_string(zUser));
    }

    zComment = db_column_text(&q,3);
    zEComment = db_text(0, 
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_COMMENT, rid);
    if(zEComment){
      SET("comment",json_new_string(zEComment));
      if(0 != strcmp(zEComment,zComment)){
        SET("originComment", json_new_string(zComment));
      }
      free(zEComment);
    }else{
      SET("comment",json_new_string(zComment));
    }

    mtime = db_column_int(&q,1);
    SET("mtime",json_new_int(mtime));
    omtime = db_column_int(&q,4);
    if(omtime && (omtime!=mtime)){
      SET("originTime",json_new_int(omtime));
    }

    if(zParent){
      SET("parentUuid", json_new_string(zParent));
    }

    tmpV = json_tags_for_checkin_rid(rid,0);
    if(tmpV){
      SET("tags",tmpV);
    }

    if( showFiles ){
      cson_value * fileList = json_get_changed_files(rid);
      if(fileList){
        SET("files",fileList);
      }
    }


#undef SET
  }
  free(zParent);
  db_finalize(&q);
  return v;
}

/*
** Very incomplete/incorrect impl of /json/artifact/TICKET_ID.
*/







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








<

|





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






<










>
>
>
>
>
>
>
>
|













|













<
<
<
<
<
<
|
|
|








|
|
|



<


<







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
  /**
     JSON construction callback. Creates the contents for the
     payload.artifact property of /json/artifact responses.
  */
  artifact_f func;
} ArtifactDispatchEntry;


/*
** Generates a JSON Array reference holding the parent UUIDs (as strings).
** If it finds no matches then it returns NULL (OOM is a fatal error).
**
** Returned value is NULL or an Array owned by the caller.
*/
cson_value * json_parent_uuids_for_ci( int rid ){
  Stmt q = empty_Stmt;
  cson_array * pParents = NULL;
  db_prepare( &q,
              "SELECT uuid FROM plink, blob"
              " WHERE plink.cid=%d AND blob.rid=plink.pid"
              " ORDER BY plink.isprim DESC",
              rid );
  while( SQLITE_ROW==db_step(&q) ){
    if(!pParents) {
      pParents = cson_new_array();
    }
    cson_array_append( pParents, cson_sqlite3_column_to_value( q.pStmt, 0 ) );
  }
  db_finalize(&q);
  return cson_array_value(pParents);
}

/*
** Generates an artifact Object for the given rid,
** which must refer to a Checkin.
**
** Returned value is NULL or an Object owned by the caller.
*/
cson_value * json_artifact_for_ci( int rid, char showFiles ){

  cson_value * v = NULL;
  Stmt q = empty_Stmt;
  static cson_value * eventTypeLabel = NULL;
  if(!eventTypeLabel){
    eventTypeLabel = json_new_string("checkin");
    json_gc_add("$EVENT_TYPE_LABEL(commit)", eventTypeLabel);
  }





  
  db_prepare(&q,
             "SELECT b.uuid, "
             " cast(strftime('%%s',e.mtime) as int), "
             " strftime('%%s',e.omtime),"
             " e.user, "
             " e.comment"

             " FROM blob b, event e"
             " WHERE b.rid=%d"
             "   AND e.objid=%d",
             rid, rid
             );
  if( db_step(&q)==SQLITE_ROW ){
    cson_object * o;
    cson_value * tmpV = NULL;
    const char *zUuid = db_column_text(&q, 0);

    const char *zUser;
    const char *zComment;
    char * zEUser, * zEComment;
    int mtime, omtime;
    v = cson_value_new_object();
    o = cson_value_get_object(v);
#define SET(K,V) cson_object_set(o,(K), (V))
    SET("type", eventTypeLabel );
    SET("uuid",json_new_string(zUuid));
    SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));

    mtime = db_column_int(&q,1);
    SET("mtime",json_new_int(mtime));
    omtime = db_column_int(&q,2);
    if(omtime && (omtime!=mtime)){
      SET("originTime",json_new_int(omtime));
    }

    zUser = db_column_text(&q,3);
    zEUser = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_USER, rid);
    if(zEUser){
      SET("user", json_new_string(zEUser));
      if(0!=strcmp(zEUser,zUser)){
        SET("originUser",json_new_string(zUser));
      }
      free(zEUser);
    }else{
      SET("user",json_new_string(zUser));
    }

    zComment = db_column_text(&q,4);
    zEComment = db_text(0, 
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_COMMENT, rid);
    if(zEComment){
      SET("comment",json_new_string(zEComment));
      if(0 != strcmp(zEComment,zComment)){
        SET("originComment", json_new_string(zComment));
      }
      free(zEComment);
    }else{
      SET("comment",json_new_string(zComment));
    }







    tmpV = json_parent_uuids_for_ci(rid);
    if(tmpV){
      SET("parents", tmpV);
    }

    tmpV = json_tags_for_checkin_rid(rid,0);
    if(tmpV){
      SET("tags",tmpV);
    }

    if( showFiles ){
      tmpV = json_get_changed_files(rid);
      if(tmpV){
        SET("files",tmpV);
      }
    }


#undef SET
  }

  db_finalize(&q);
  return v;
}

/*
** Very incomplete/incorrect impl of /json/artifact/TICKET_ID.
*/
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  return cson_object_value(pay);
}

/*
** Sub-impl of /json/artifact for checkins.
*/
static cson_value * json_artifact_ci( int rid ){
  if(! g.perm.Read ){
    g.json.resultCode = FSL_JSON_E_DENIED;
    return NULL;
  }else{
    return json_artifact_for_ci(rid, 1);
  }
}

/*







|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  return cson_object_value(pay);
}

/*
** Sub-impl of /json/artifact for checkins.
*/
static cson_value * json_artifact_ci( int rid ){
  if(!g.perm.Read){
    json_set_err( FSL_JSON_E_DENIED, "Viewing checkins requires 'o' privileges." );
    return NULL;
  }else{
    return json_artifact_for_ci(rid, 1);
  }
}

/*
222
223
224
225
226
227
228




229
230
231
232
233
234
235
236

cson_value * json_artifact_wiki(int rid){
  if( ! g.perm.RdWiki ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' privileges.");
    return NULL;
  }else{




    return json_get_wiki_page_by_rid(rid, 0);
  }
}

cson_value * json_artifact_file(int rid){
  cson_object * pay = NULL;
  const char *zMime;
  Blob content = empty_blob;







>
>
>
>
|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

cson_value * json_artifact_wiki(int rid){
  if( ! g.perm.RdWiki ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' privileges.");
    return NULL;
  }else{
    char contentFormat = json_wiki_get_content_format_flag(-9);
    if(-9 == contentFormat){
      contentFormat = json_artifact_include_content_flag() ? -1 : 0;
    }
    return json_get_wiki_page_by_rid(rid, contentFormat);
  }
}

cson_value * json_artifact_file(int rid){
  cson_object * pay = NULL;
  const char *zMime;
  Blob content = empty_blob;
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  char const * zType = NULL;
  char const * zUuid = NULL;
  cson_value * entry = NULL;
  Blob uuid = empty_blob;
  int rc;
  int rid = 0;
  ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
  zName = json_find_option_cstr2("uuid", NULL, NULL, 2);
  if(!zName || !*zName) {
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Missing 'uuid' argument.");
    return NULL;
  }

  if( validate16(zName, strlen(zName)) ){
    if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
      zType = "ticket";
      goto handle_entry;







|


|







316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  char const * zType = NULL;
  char const * zUuid = NULL;
  cson_value * entry = NULL;
  Blob uuid = empty_blob;
  int rc;
  int rid = 0;
  ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
  zName = json_find_option_cstr2("name", NULL, NULL, 2);
  if(!zName || !*zName) {
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Missing 'name' argument.");
    return NULL;
  }

  if( validate16(zName, strlen(zName)) ){
    if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
      zType = "ticket";
      goto handle_entry;
Added src/json_config.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
#ifdef FOSSIL_ENABLE_JSON
/*
** 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/
**
*/
#include "VERSION.h"
#include "config.h"
#include "json_config.h"

#if INTERFACE
#include "json_detail.h"
#endif

static cson_value * json_config_get();
static cson_value * json_config_save();

/*
** Mapping of /json/config/XXX commands/paths to callbacks.
*/
static const JsonPageDef JsonPageDefs_Config[] = {
{"get", json_config_get, 0},
{"save", json_config_save, 0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*
** Implements the /json/config family of pages/commands.
**
*/
cson_value * json_page_config(){
  return json_page_dispatch_helper(&JsonPageDefs_Config[0]);
}


/*
** JSON-internal mapping of config options to config groups.  This is
** mostly a copy of the config options in configure.c, but that data
** is private and cannot be re-used directly here.
*/
static const struct JsonConfigProperty {
  char const * name;
  int groupMask;
} JsonConfigProperties[] = {
{ "css",                    CONFIGSET_SKIN },
{ "header",                 CONFIGSET_SKIN },
{ "footer",                 CONFIGSET_SKIN },
{ "index-page",             CONFIGSET_SKIN },
{ "timeline-block-markup",  CONFIGSET_SKIN },
{ "timeline-max-comment",   CONFIGSET_SKIN },

{ "project-name",           CONFIGSET_PROJ },
{ "project-description",    CONFIGSET_PROJ },
{ "manifest",               CONFIGSET_PROJ },
{ "ignore-glob",            CONFIGSET_PROJ },
{ "crnl-glob",              CONFIGSET_PROJ },
{ "empty-dirs",             CONFIGSET_PROJ },
{ "allow-symlinks",         CONFIGSET_PROJ },

{ "ticket-table",           CONFIGSET_TKT  },
{ "ticket-common",          CONFIGSET_TKT  },
{ "ticket-change",          CONFIGSET_TKT  },
{ "ticket-newpage",         CONFIGSET_TKT  },
{ "ticket-viewpage",        CONFIGSET_TKT  },
{ "ticket-editpage",        CONFIGSET_TKT  },
{ "ticket-reportlist",      CONFIGSET_TKT  },
{ "ticket-report-template", CONFIGSET_TKT  },
{ "ticket-key-template",    CONFIGSET_TKT  },
{ "ticket-title-expr",      CONFIGSET_TKT  },
{ "ticket-closed-expr",     CONFIGSET_TKT  },

{NULL, 0}
};


/*
** Impl of /json/config/get. Requires setup rights.
**
*/
static cson_value * json_config_get(){
  cson_object * pay = NULL;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  char const * zName = NULL;
  int confMask = 0;
  char optSkinBackups = 0;
  unsigned int i;
  if(!g.perm.Setup){
    json_set_err(FSL_JSON_E_DENIED, "Requires 's' permissions.");
    return NULL;
  }

  i = g.json.dispatchDepth + 1;
  zName = json_command_arg(i);
  for( ; zName; zName = json_command_arg(++i) ){
    if(0==(strcmp("all", zName))){
      confMask = CONFIGSET_ALL;
    }else if(0==(strcmp("project", zName))){
      confMask |= CONFIGSET_PROJ;
    }else if(0==(strcmp("skin", zName))){
      confMask |= CONFIGSET_SKIN;
    }else if(0==(strcmp("ticket", zName))){
      confMask |= CONFIGSET_TKT;
    }else if(0==(strcmp("skin-backup", zName))){
      optSkinBackups = 1;
    }else{
      json_set_err( FSL_JSON_E_INVALID_ARGS,
                    "Unknown config area: %s", zName);
      return NULL;
    }
  }

  if(!confMask && !optSkinBackups){
    json_set_err(FSL_JSON_E_MISSING_ARGS, "No configuration area(s) selected.");
  }
  blob_append(&sql,
              "SELECT name, value"
              " FROM config "
              " WHERE 0 ", -1);
  {
    const struct JsonConfigProperty * prop = &JsonConfigProperties[0];
    blob_append(&sql," OR name IN (",-1);
    for( i = 0; prop->name; ++prop ){
      if(prop->groupMask & confMask){
        if( i++ ){
          blob_append(&sql,",",1);
        }
        blob_appendf(&sql, "%Q", prop->name);
      }
    }
    blob_append(&sql,") ", -1);
  }


  if( optSkinBackups ){
    blob_append(&sql, " OR name GLOB 'skin:*'", -1);
  }
  blob_append(&sql," ORDER BY name", -1);
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  pay = cson_new_object();
  while( (SQLITE_ROW==db_step(&q)) ){
    cson_object_set(pay,
                    db_column_text(&q,0),
                    json_new_string(db_column_text(&q,1)));
  }
  db_finalize(&q);
  return cson_object_value(pay);
}

/*
** Impl of /json/config/save.
**
** TODOs:
*/
static cson_value * json_config_save(){
  json_set_err(FSL_JSON_E_NYI, NULL);
  return NULL;
}
#endif /* FOSSIL_ENABLE_JSON */
Changes to src/json_detail.h.
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
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*/

#include "cson_amalgamation.h"









/*
** Impl details for the JSON API which need to be shared
** across multiple C files.
*/

/*
** The "official" list of Fossil/JSON error codes.  Their values might
** very well change during initial development but after their first
** public release they must stay stable.
**
** Values must be in the range 1000..9999 for error codes and 1..999
** for warning codes.
**
** Numbers evenly dividable by 100 are "categories", and error codes
** for a given category have their high bits set to the category
** value.




**
*/
enum FossilJsonCodes {
FSL_JSON_W_START = 0,
FSL_JSON_W_UNKNOWN /*+1*/,
FSL_JSON_W_ROW_TO_JSON_FAILED /*+2*/,
FSL_JSON_W_COL_TO_JSON_FAILED /*+3*/,







>
>
>
>
>
>
>
>
>
















>
>
>
>







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
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*/

#include "cson_amalgamation.h"

/**
   FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest
   "significant" change to the JSON API (a change in an interface
   or new functionality). It is sent as part of the /json/version
   request. We could arguably add it to each response.
*/
#define FOSSIL_JSON_API_VERSION "20120409"

/*
** Impl details for the JSON API which need to be shared
** across multiple C files.
*/

/*
** The "official" list of Fossil/JSON error codes.  Their values might
** very well change during initial development but after their first
** public release they must stay stable.
**
** Values must be in the range 1000..9999 for error codes and 1..999
** for warning codes.
**
** Numbers evenly dividable by 100 are "categories", and error codes
** for a given category have their high bits set to the category
** value.
**
** Maintenance reminder: when entries are added to this list, update
** the code in json_page_resultCodes() and json_err_cstr() (both in
** json.c)!
**
*/
enum FossilJsonCodes {
FSL_JSON_W_START = 0,
FSL_JSON_W_UNKNOWN /*+1*/,
FSL_JSON_W_ROW_TO_JSON_FAILED /*+2*/,
FSL_JSON_W_COL_TO_JSON_FAILED /*+3*/,
Changes to src/json_diff.c.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
cson_value * json_generate_diff(const char *zFrom, const char *zTo,
                                int nContext, char fSbs){
  int fromid;
  int toid;
  int outLen;
  Blob from = empty_blob, to = empty_blob, out = empty_blob;
  cson_value * rc = NULL;
  char const * zType = "ci";
  int flags = (DIFF_CONTEXT_MASK & nContext)
      | (fSbs ? DIFF_SIDEBYSIDE : 0);
  fromid = name_to_typed_rid(zFrom, "*");
  if(fromid<=0){
      json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
                   "Could not resolve 'from' ID.");
      return NULL;







<







35
36
37
38
39
40
41

42
43
44
45
46
47
48
cson_value * json_generate_diff(const char *zFrom, const char *zTo,
                                int nContext, char fSbs){
  int fromid;
  int toid;
  int outLen;
  Blob from = empty_blob, to = empty_blob, out = empty_blob;
  cson_value * rc = NULL;

  int flags = (DIFF_CONTEXT_MASK & nContext)
      | (fSbs ? DIFF_SIDEBYSIDE : 0);
  fromid = name_to_typed_rid(zFrom, "*");
  if(fromid<=0){
      json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
                   "Could not resolve 'from' ID.");
      return NULL;
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
  content_get(fromid, &from);
  content_get(toid, &to);
  blob_zero(&out);
  text_diff(&from, &to, &out, flags);
  blob_reset(&from);
  blob_reset(&to);
  outLen = blob_size(&out);
  if(outLen>0){
    rc = cson_value_new_string(blob_buffer(&out), blob_size(&out));

  }
  blob_reset(&out);
  return rc;
}

/*
** Implementation of the /json/diff page.







|
|
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  content_get(fromid, &from);
  content_get(toid, &to);
  blob_zero(&out);
  text_diff(&from, &to, &out, flags);
  blob_reset(&from);
  blob_reset(&to);
  outLen = blob_size(&out);
  if(outLen>=0){
    rc = cson_value_new_string(blob_buffer(&out),
                               (unsigned int)blob_size(&out));
  }
  blob_reset(&out);
  return rc;
}

/*
** Implementation of the /json/diff page.
Added src/json_finfo.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
#ifdef FOSSIL_ENABLE_JSON
/*
** 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/
**
*/
#include "VERSION.h"
#include "config.h"
#include "json_finfo.h"

#if INTERFACE
#include "json_detail.h"
#endif

/*
** Implements the /json/finfo page/command.
**
*/
cson_value * json_page_finfo(){
  cson_object * pay = NULL;
  cson_array * checkins = NULL;
  char const * zFilename = NULL;
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;
  char const * zAfter = NULL;
  char const * zBefore = NULL;
  int limit = -1;
  int currentRow = 0;
  if(!g.perm.Read){
    json_set_err(FSL_JSON_E_DENIED,"Requires 'o' privileges.");
    return NULL;
  }
  json_warn( FSL_JSON_W_UNKNOWN, "Achtung: the output of the finfo command is up for change.");
  zFilename = json_find_option_cstr2("name",NULL,NULL,
                                 g.json.dispatchDepth+1);

  if(!zFilename){
    json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter.");
    return NULL;
  }
  zBefore = json_find_option_cstr("before",NULL,"b");
  zAfter = json_find_option_cstr("after",NULL,"a");
  limit = json_find_option_int("limit",NULL,"n", -1);

  blob_appendf(&sql, 
        "SELECT b.uuid,"
        "   ci.uuid,"
        "   (SELECT uuid FROM blob WHERE rid=mlink.fid),"  /* Current file uuid */
        "   cast(strftime('%%s',event.mtime) AS INTEGER),"
        "   coalesce(event.euser, event.user),"
        "   coalesce(event.ecomment, event.comment),"
#if 1
        " (SELECT uuid FROM blob WHERE rid=mlink.pid),"  /* Parent file uuid */
#endif
        "   event.bgcolor,"
        " 1"
        "  FROM mlink, blob b, event, blob ci, filename"
        " WHERE filename.name=%Q %s"
        "   AND mlink.fnid=filename.fnid"
        "   AND b.rid=mlink.fid"
        "   AND event.objid=mlink.mid"
        "   AND event.objid=ci.rid",
        zFilename, filename_collation()
               );
  if( zAfter ){
    blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zAfter);
  }else if( zBefore ){
    blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zBefore);
  }
  blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/");
  db_prepare(&q, "%s", blob_str(&sql)/*extra %s to avoid double-expanding
                                       SQL escapes*/);
  blob_reset(&sql);

  pay = cson_new_object();
  cson_object_set(pay, "name", json_new_string(zFilename));
  if( limit > 0 ){
    cson_object_set(pay, "limit", json_new_int(limit));
  }
  checkins = cson_new_array();
  cson_object_set(pay, "checkins", cson_array_value(checkins));
  while( db_step(&q)==SQLITE_ROW ){
    cson_object * row = cson_new_object();
    cson_array_append( checkins, cson_object_value(row) );
    cson_object_set(row, "checkin", json_new_string( db_column_text(&q,1) ));
    cson_object_set(row, "artifact", json_new_string( db_column_text(&q,2) ));
    /*cson_object_set(row, "parentArtifact", json_new_string( db_column_text(&q,6) ));*/
    cson_object_set(row, "mtime", json_new_int( db_column_int(&q,3) ));
    cson_object_set(row, "user", json_new_string( db_column_text(&q,4) ));
    cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) ));
    /*cson_object_set(row, "bgColor", json_new_string( db_column_text(&q,7) ));*/
    if( (0 < limit) && (++currentRow >= limit) ){
      break;
    }
  }
  db_finalize(&q);

  return cson_object_value(pay);
}



#endif /* FOSSIL_ENABLE_JSON */
Changes to src/json_report.c.
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 't' privileges.");
    return NULL;
  }
  nReport = json_report_get_number(3);
  if(nReport <=0){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Missing or invalid 'number' (-n) parameter.");
    return NULL;
  }

  db_prepare(&q,"SELECT rn AS report,"
             " owner AS owner,"
             " title AS title,"
             " cast(strftime('%%s',mtime) as int) as mtime,"







|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 't' privileges.");
    return NULL;
  }
  nReport = json_report_get_number(3);
  if(nReport <=0){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Missing or invalid 'report' (-r) parameter.");
    return NULL;
  }

  db_prepare(&q,"SELECT rn AS report,"
             " owner AS owner,"
             " title AS title,"
             " cast(strftime('%%s',mtime) as int) as mtime,"
Changes to src/json_timeline.c.
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
static const JsonPageDef JsonPageDefs_Timeline[] = {
/* the short forms are only enabled in CLI mode, to avoid
   that we end up with HTTP clients using 3 different names
   for the same requests.
*/
{"branch", json_timeline_branch, 0},
{"checkin", json_timeline_ci, 0},
{"ci", json_timeline_ci, -1},
{"t", json_timeline_ticket, -1},
{"ticket", json_timeline_ticket, 0},
{"w", json_timeline_wiki, -1},
{"wiki", json_timeline_wiki, 0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*







<
<

<







33
34
35
36
37
38
39


40

41
42
43
44
45
46
47
static const JsonPageDef JsonPageDefs_Timeline[] = {
/* the short forms are only enabled in CLI mode, to avoid
   that we end up with HTTP clients using 3 different names
   for the same requests.
*/
{"branch", json_timeline_branch, 0},
{"checkin", json_timeline_ci, 0},


{"ticket", json_timeline_ticket, 0},

{"wiki", json_timeline_wiki, 0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
**
** pSql is the target blob to append the query [subset]
** to.
**
** Returns a positive value if it modifies pSql, 0 if it
** does not. It returns a negative value if the tag
** provided to the request was not found (pSql is not modified
** in that case.
**
** If payload is not NULL then on success its "tag" or "branch"
** property is set to the tag/branch name found in the request.
**
** Only one of "tag" or "branch" modes will work at a time, and if
** both are specified, which one takes precedence is unspecified.
*/







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
**
** pSql is the target blob to append the query [subset]
** to.
**
** Returns a positive value if it modifies pSql, 0 if it
** does not. It returns a negative value if the tag
** provided to the request was not found (pSql is not modified
** in that case).
**
** If payload is not NULL then on success its "tag" or "branch"
** property is set to the tag/branch name found in the request.
**
** Only one of "tag" or "branch" modes will work at a time, and if
** both are specified, which one takes precedence is unspecified.
*/
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
** Tries to figure out a timeline query length limit base on
** environment parameters. If it can it returns that value,
** else it returns some statically defined default value.
**
** Never returns a negative value. 0 means no limit.
*/
static int json_timeline_limit(){
  static const int defaultLimit = 20;
  int limit = -1;
  if(!g.isHTTP){/* CLI mode */
    char const * arg = find_option("limit","n",1);
    if(arg && *arg){
      limit = atoi(arg);
    }
  }







|
<







228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
/*
** Tries to figure out a timeline query length limit base on
** environment parameters. If it can it returns that value,
** else it returns some statically defined default value.
**
** Never returns a negative value. 0 means no limit.
*/
static int json_timeline_limit(int defaultLimit){

  int limit = -1;
  if(!g.isHTTP){/* CLI mode */
    char const * arg = find_option("limit","n",1);
    if(arg && *arg){
      limit = atoi(arg);
    }
  }
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  blob_append(pSql, "INSERT OR IGNORE INTO json_timeline ", -1);
  blob_append(pSql, json_timeline_query(), -1 );
  blob_appendf(pSql, " AND event.type IN(%Q) ", zEventType);
  if( json_timeline_add_tag_branch_clause(pSql, pPayload) < 0 ){
    return FSL_JSON_E_INVALID_ARGS;
  }
  json_timeline_add_time_clause(pSql);
  limit = json_timeline_limit();
  if(limit>=0){
    blob_appendf(pSql,"LIMIT %d ",limit);
  }
  if(pPayload){
    cson_object_set(pPayload, "limit", json_new_int(limit));
  }
  return 0;
}







|
|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  blob_append(pSql, "INSERT OR IGNORE INTO json_timeline ", -1);
  blob_append(pSql, json_timeline_query(), -1 );
  blob_appendf(pSql, " AND event.type IN(%Q) ", zEventType);
  if( json_timeline_add_tag_branch_clause(pSql, pPayload) < 0 ){
    return FSL_JSON_E_INVALID_ARGS;
  }
  json_timeline_add_time_clause(pSql);
  limit = json_timeline_limit(20);
  if(limit>0){
    blob_appendf(pSql,"LIMIT %d ",limit);
  }
  if(pPayload){
    cson_object_set(pPayload, "limit", json_new_int(limit));
  }
  return 0;
}
351
352
353
354
355
356
357

358
359
360
361
362
363
364
  return rowsV;
}

static cson_value * json_timeline_branch(){
  cson_value * pay = NULL;
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;

  if(!g.perm.Read){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  json_timeline_temp_table();
  blob_append(&sql,







>







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  return rowsV;
}

static cson_value * json_timeline_branch(){
  cson_value * pay = NULL;
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;
  int limit = 0;
  if(!g.perm.Read){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  json_timeline_temp_table();
  blob_append(&sql,
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

  blob_appendf(&sql,
               " AND event.type='ci'"
               " AND blob.rid IN (SELECT rid FROM tagxref"
               "  WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
               " ORDER BY event.mtime DESC",
               TAG_BRANCH);




  db_prepare(&q,"%s", blob_str(&sql));
  blob_reset(&sql);
  pay = json_stmt_to_array_of_obj(&q, NULL);
  db_finalize(&q);
  assert(NULL != pay);
  if(pay){
    /* get the array-form tags of each record. */
    cson_string * tags = cson_new_string("tags",4);
    cson_string * isLeaf = cson_new_string("isLeaf",6);
    cson_value_add_reference( cson_string_value(tags) );
    cson_value_add_reference( cson_string_value(isLeaf) );
    cson_array * ar = cson_value_get_array(pay);
    unsigned int i = 0;
    unsigned int len = cson_array_length_get(ar);
    for( ; i < len; ++i ){
      cson_object * row = cson_value_get_object(cson_array_get(ar,i));
      int rid = cson_value_get_integer(cson_object_get(row,"rid"));
      if(row>0) {
        cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
        cson_object_set_s(row, isLeaf, json_value_to_bool(cson_object_get(row,"isLeaf")));
      }
    }
    cson_value_free( cson_string_value(tags) );
    cson_value_free( cson_string_value(isLeaf) );
  }
   
  goto end;
  error:
  assert( 0 != g.json.resultCode );
  cson_value_free(pay);

  end:
  return pay;
}

/*
** Implementation of /json/timeline/ci.
**
** Still a few TODOs (like figuring out how to structure
** inheritance info).
*/
static cson_value * json_timeline_ci(){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  char showFiles = -1/*magic number*/;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;
  char warnStringToArrayFailed = 0;
  Blob sql = empty_blob;
  if( !g.perm.Read ){
    /* IMO this falls more under the category of g.perm.History, but
       i'm following the original timeline impl here.
    */
    json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
    return NULL;
  }
  showFiles = json_find_option_bool("files",NULL,"f",0);
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "ci", &sql, pay );
  if(check){







>
>
>
>

















|
|
|
<




<
<
<
<
<
<
<



















<

|
|
|

|







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

  blob_appendf(&sql,
               " AND event.type='ci'"
               " AND blob.rid IN (SELECT rid FROM tagxref"
               "  WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
               " ORDER BY event.mtime DESC",
               TAG_BRANCH);
  limit = json_timeline_limit(20);
  if(limit>0){
    blob_appendf(&sql," LIMIT %d ",limit);
  }
  db_prepare(&q,"%s", blob_str(&sql));
  blob_reset(&sql);
  pay = json_stmt_to_array_of_obj(&q, NULL);
  db_finalize(&q);
  assert(NULL != pay);
  if(pay){
    /* get the array-form tags of each record. */
    cson_string * tags = cson_new_string("tags",4);
    cson_string * isLeaf = cson_new_string("isLeaf",6);
    cson_value_add_reference( cson_string_value(tags) );
    cson_value_add_reference( cson_string_value(isLeaf) );
    cson_array * ar = cson_value_get_array(pay);
    unsigned int i = 0;
    unsigned int len = cson_array_length_get(ar);
    for( ; i < len; ++i ){
      cson_object * row = cson_value_get_object(cson_array_get(ar,i));
      int rid = cson_value_get_integer(cson_object_get(row,"rid"));
      assert( rid > 0 );
      cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
      cson_object_set_s(row, isLeaf, json_value_to_bool(cson_object_get(row,"isLeaf")));

    }
    cson_value_free( cson_string_value(tags) );
    cson_value_free( cson_string_value(isLeaf) );
  }







  return pay;
}

/*
** Implementation of /json/timeline/ci.
**
** Still a few TODOs (like figuring out how to structure
** inheritance info).
*/
static cson_value * json_timeline_ci(){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  char showFiles = -1/*magic number*/;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;

  Blob sql = empty_blob;
  if( !g.perm.History ){
    /* Reminder to self: HTML impl requires 'o' (Read)
       rights.
    */
    json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
    return NULL;
  }
  showFiles = json_find_option_bool("files",NULL,"f",0);
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "ci", &sql, pay );
  if(check){
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
  tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
  SET("timelineSql");
#endif
  db_multi_exec(blob_buffer(&sql));
  blob_reset(&sql);
  db_prepare(&q, "SELECT "
             " rid AS rid"
#if 0
             " uuid AS uuid,"
             " mtime AS timestamp,"
#  if 0
             " timestampString AS timestampString,"
#  endif
             " comment AS comment, "
             " user AS user,"
             " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */
             " bgColor AS bgColor," /* why always null? */
             " eventType AS eventType"
#  if 0
             " tags AS tags"
             /*tagId is always null?*/
             " tagId AS tagId"
#  endif
#endif
             " FROM json_timeline"
             " ORDER BY rowid");
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  tmp = listV;
  SET("timeline");
  while( (SQLITE_ROW == db_step(&q) )){







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







452
453
454
455
456
457
458

















459
460
461
462
463
464
465
  tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
  SET("timelineSql");
#endif
  db_multi_exec(blob_buffer(&sql));
  blob_reset(&sql);
  db_prepare(&q, "SELECT "
             " rid AS rid"

















             " FROM json_timeline"
             " ORDER BY rowid");
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  tmp = listV;
  SET("timeline");
  while( (SQLITE_ROW == db_step(&q) )){
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
** Implementation of /json/timeline/wiki.
**
*/
cson_value * json_timeline_wiki(){
  /* This code is 95% the same as json_timeline_ci(), by the way. */
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err( FSL_JSON_E_DENIED, "Wiki timeline requires 'o' or 'j' access.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "w", &sql, pay );
  if(check){
    json_set_err(check, "Query initialization failed.");
    goto error;
  }

#define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
    json_set_err((cson_rc.AllocError==check)        \
                 ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN,       \
                 "Object property insertion failed."); \
    goto error;\
  } (void)0
#if 0
  /* only for testing! */
  tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
  SET("timelineSql");
#endif
  db_multi_exec(blob_buffer(&sql));
  blob_reset(&sql);







<
















<
<
<
<
<
<







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
** Implementation of /json/timeline/wiki.
**
*/
cson_value * json_timeline_wiki(){
  /* This code is 95% the same as json_timeline_ci(), by the way. */
  cson_value * payV = NULL;
  cson_object * pay = NULL;

  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err( FSL_JSON_E_DENIED, "Wiki timeline requires 'o' or 'j' access.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "w", &sql, pay );
  if(check){
    json_set_err(check, "Query initialization failed.");
    goto error;
  }







#if 0
  /* only for testing! */
  tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
  SET("timelineSql");
#endif
  db_multi_exec(blob_buffer(&sql));
  blob_reset(&sql);
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
                                a JSON array*/
             " tagId AS tagId,"
#endif
             " FROM json_timeline"
             " ORDER BY rowid",
             -1);
  list = cson_new_array();
  tmp = cson_array_value(list);
  SET("timeline");
  json_stmt_to_array_of_obj(&q, list);
#undef SET

  goto ok;
  error:
  assert( 0 != g.json.resultCode );
  cson_value_free(payV);
  payV = NULL;
  ok:
  db_finalize(&q);







<
<

<
>







534
535
536
537
538
539
540


541

542
543
544
545
546
547
548
549
                                a JSON array*/
             " tagId AS tagId,"
#endif
             " FROM json_timeline"
             " ORDER BY rowid",
             -1);
  list = cson_new_array();


  json_stmt_to_array_of_obj(&q, list);

  cson_object_set(pay, "timeline", cson_array_value(list));
  goto ok;
  error:
  assert( 0 != g.json.resultCode );
  cson_value_free(payV);
  payV = NULL;
  ok:
  db_finalize(&q);
Changes to src/json_user.c.
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
**
** On error g.json's error state is set one of the FSL_JSON_E_xxx
** values from FossilJsonCodes is returned.
**
** On success the db record for the given user is updated.
**
** Requires either Admin, Setup, or Password access. Non-admin/setup
** users can only change their own information.
**
** TODOs:
**
** - Admin non-Setup users cannot change the information for Setup
** users.
**
*/
int json_user_update_from_json( cson_object * pUser ){
#define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
  char const * zName = CSTR("name");
  char const * zNameNew = zName;
  char * zNameFree = NULL;
  char const * zInfo = CSTR("info");
  char const * zCap = CSTR("capabilities");
  char const * zPW = CSTR("password");
  cson_value const * forceLogout = cson_object_get(pUser, "forceLogout");
  int gotFields = 0;
#undef CSTR
  cson_int_t uid = cson_value_get_integer( cson_object_get(pUser, "uid") );


  Blob sql = empty_blob;
  Stmt q = empty_Stmt;

  if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
    return json_set_err( FSL_JSON_E_DENIED,
                         "Password change requires 'a', 's', "
                         "or 'p' permissions.");







|
<
<
<
|
|














>
>







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
**
** On error g.json's error state is set one of the FSL_JSON_E_xxx
** values from FossilJsonCodes is returned.
**
** On success the db record for the given user is updated.
**
** Requires either Admin, Setup, or Password access. Non-admin/setup
** users can only change their own information. Non-setup users may



** not modify the 's' permission. Admin users without setup
** permissions may not edit any other user who has the 's' permission.
**
*/
int json_user_update_from_json( cson_object * pUser ){
#define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
  char const * zName = CSTR("name");
  char const * zNameNew = zName;
  char * zNameFree = NULL;
  char const * zInfo = CSTR("info");
  char const * zCap = CSTR("capabilities");
  char const * zPW = CSTR("password");
  cson_value const * forceLogout = cson_object_get(pUser, "forceLogout");
  int gotFields = 0;
#undef CSTR
  cson_int_t uid = cson_value_get_integer( cson_object_get(pUser, "uid") );
  char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
  char tgtHadSetup = 0;
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;

  if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
    return json_set_err( FSL_JSON_E_DENIED,
                         "Password change requires 'a', 's', "
                         "or 'p' permissions.");
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    }
    zName = zNameFree;
  }else if(-1==uid){
    /* try to create a new user */
    if(!g.perm.Admin && !g.perm.Setup){
      return json_set_err(FSL_JSON_E_DENIED,
                          "Requires 'a' or 's' privileges.");
    } else if(!zName || !*zName){
      return json_set_err(FSL_JSON_E_MISSING_ARGS,
                          "No name specified for new user.");
    }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
      return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
                          "User %s already exists.", zName);
    }else{
      Stmt ins = empty_Stmt;







|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    }
    zName = zNameFree;
  }else if(-1==uid){
    /* try to create a new user */
    if(!g.perm.Admin && !g.perm.Setup){
      return json_set_err(FSL_JSON_E_DENIED,
                          "Requires 'a' or 's' privileges.");
    }else if(!zName || !*zName){
      return json_set_err(FSL_JSON_E_MISSING_ARGS,
                          "No name specified for new user.");
    }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
      return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
                          "User %s already exists.", zName);
    }else{
      Stmt ins = empty_Stmt;
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
  }

  /* Maintenance note: all error-returns from here on out should go
     via 'goto error' in order to clean up.
  */
  
  if(uid != g.userUid){
    /*
      TODO: do not allow an admin user to modify a setup user
      unless the admin is also a setup user. setup.c uses
      that logic. There is a corner case for a NEW Setup user
      which the admin is just installing. Hmm.      
    */
    if(!g.perm.Admin && !g.perm.Setup){
      json_set_err(FSL_JSON_E_DENIED,
                   "Changing another user's data requires "
                   "'a' or 's' privileges.");
    }
  }



  














  blob_append(&sql, "UPDATE USER SET",-1 );
  blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);

  if((uid>0) && zNameNew){
    /* Check for name change... */
    if( (!g.perm.Admin && !g.perm.Setup)
        && zNameNew && (zName != zNameNew)
        && (0!=strcmp(zNameNew,zName))){







<
<
<
<
<
<






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







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
  }

  /* Maintenance note: all error-returns from here on out should go
     via 'goto error' in order to clean up.
  */
  
  if(uid != g.userUid){






    if(!g.perm.Admin && !g.perm.Setup){
      json_set_err(FSL_JSON_E_DENIED,
                   "Changing another user's data requires "
                   "'a' or 's' privileges.");
    }
  }
  /* check if the target uid currently has setup rights. */
  tgtHadSetup = db_int(0,"SELECT 1 FROM user where uid=%d"
                       " AND cap GLOB '*s*'", uid);

  if((tgtHasSetup || tgtHadSetup) && !g.perm.Setup){
    /*
      Do not allow a non-setup user to set or remove setup
      privileges. setup.c uses similar logic.
    */
    return json_set_err(FSL_JSON_E_DENIED,
                        "Modifying 's' users/privileges requires "
                        "'s' privileges.");
  }
  /*
    Potential todo: do not allow a setup user to remove 's' from
    himself, to avoid locking himself out?
  */

  blob_append(&sql, "UPDATE user SET",-1 );
  blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);

  if((uid>0) && zNameNew){
    /* Check for name change... */
    if( (!g.perm.Admin && !g.perm.Setup)
        && zNameNew && (zName != zNameNew)
        && (0!=strcmp(zNameNew,zName))){
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
    ++gotFields;
  }

  if( zCap ){
    blob_appendf(&sql, ", cap=%Q", zCap);
    ++gotFields;
  }

  if( zPW ){

    char * zPWHash = NULL;
    ++gotFields;
    zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
    blob_appendf(&sql, ", pw=%Q", zPWHash);
    free(zPWHash);







  }

  if( zInfo ){
    blob_appendf(&sql, ", info=%Q", zInfo);
    ++gotFields;
  }

  if((g.perm.Admin || g.perm.Setup)
     && forceLogout && cson_value_get_bool(forceLogout)){
    blob_append(&sql, ", cookie=NULL, cexpire=NULL", -1);
    ++gotFields;
  }
  
  if(!gotFields){
    json_set_err( FSL_JSON_E_MISSING_ARGS,
                  "Required user data are missing.");
    goto error;
  }
  assert(uid>0);

  blob_appendf(&sql, " WHERE uid=%d", uid);

  free( zNameFree );

#if 0
  puts(blob_str(&sql));
  cson_output_FILE( cson_object_value(pUser), stdout, NULL );
#endif
  db_prepare(&q, "%s", blob_str(&sql));
  blob_reset(&sql);
  db_exec(&q);
  db_finalize(&q);


























  return 0;

  error:
  assert(0 != g.json.resultCode);
  free(zNameFree);
  blob_reset(&sql);
  return g.json.resultCode;
}


/*
** Impl of /json/user/save.
**
** TODOs:
**
** - Return something useful in the payload (at least the id of the
** modified/created user).
*/
static cson_value * json_user_save(){
  /* try to get user info from GET/CLI args and construct
     a JSON form of it... */
  cson_object * u = cson_new_object();
  char const * str = NULL;
  char b = -1;







|

>





>
>
>
>
>
>
>



















>

>
|
>





<


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












<
<
<
<
<







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
    ++gotFields;
  }

  if( zCap ){
    blob_appendf(&sql, ", cap=%Q", zCap);
    ++gotFields;
  }
#define TRY_LOGIN_GROUP 0 /* login group support is not yet implemented. */
  if( zPW ){
#if !TRY_LOGIN_GROUP
    char * zPWHash = NULL;
    ++gotFields;
    zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
    blob_appendf(&sql, ", pw=%Q", zPWHash);
    free(zPWHash);
#else
    ++gotFields;
    blob_appendf(&sql, ", pw=coalesce(shared_secret(%Q,%Q,"
                 "(SELECT value FROM config WHERE name='project-code')))",
                 zPW, zNameNew ? zNameNew : zName);
    /* shared_secret() func is undefined? */
#endif
  }

  if( zInfo ){
    blob_appendf(&sql, ", info=%Q", zInfo);
    ++gotFields;
  }

  if((g.perm.Admin || g.perm.Setup)
     && forceLogout && cson_value_get_bool(forceLogout)){
    blob_append(&sql, ", cookie=NULL, cexpire=NULL", -1);
    ++gotFields;
  }
  
  if(!gotFields){
    json_set_err( FSL_JSON_E_MISSING_ARGS,
                  "Required user data are missing.");
    goto error;
  }
  assert(uid>0);
#if !TRY_LOGIN_GROUP
  blob_appendf(&sql, " WHERE uid=%d", uid);
#else /* need name for login group support :/ */
  blob_appendf(&sql, " WHERE login=%Q", zName);
#endif
#if 0
  puts(blob_str(&sql));
  cson_output_FILE( cson_object_value(pUser), stdout, NULL );
#endif
  db_prepare(&q, "%s", blob_str(&sql));

  db_exec(&q);
  db_finalize(&q);
#if TRY_LOGIN_GROUP
  if( zPW || forceLogout ){
    Blob groupSql = empty_blob;
    char * zErr = NULL;
    blob_appendf(&groupSql,
      "INSERT INTO user(login)"
      "  SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
      zName, zName
    );
    blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
    login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
    blob_reset(&groupSql);
    if( zErr ){
      json_set_err( FSL_JSON_E_UNKNOWN,
                    "Repo-group update at least partially failed: %s",
                    zErr);
      free(zErr);
      goto error;
    }
  }
#endif /* TRY_LOGIN_GROUP */

#undef TRY_LOGIN_GROUP

  free( zNameFree );
  blob_reset(&sql);
  return 0;

  error:
  assert(0 != g.json.resultCode);
  free(zNameFree);
  blob_reset(&sql);
  return g.json.resultCode;
}


/*
** Impl of /json/user/save.





*/
static cson_value * json_user_save(){
  /* try to get user info from GET/CLI args and construct
     a JSON form of it... */
  cson_object * u = cson_new_object();
  char const * str = NULL;
  char b = -1;
Changes to src/json_wiki.c.
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
#include "json_detail.h"
#endif

static cson_value * json_wiki_create();
static cson_value * json_wiki_get();
static cson_value * json_wiki_list();
static cson_value * json_wiki_save();

/*
** Mapping of /json/wiki/XXX commands/paths to callbacks.
*/
static const JsonPageDef JsonPageDefs_Wiki[] = {
{"create", json_wiki_create, 1},

{"get", json_wiki_get, 0},
{"list", json_wiki_list, 0},
{"save", json_wiki_save, 1},
{"timeline", json_timeline_wiki,0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki(){
  return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
}












/*
** Loads the given wiki page and creates a JSON object representation
** of it. If the page is not found then NULL is returned. If doParse
** is true then the page content is HTML-ized using fossil's
** conventional wiki format, else it is not parsed.




**
** The returned value, if not NULL, is-a JSON Object owned by the
** caller.
*/
cson_value * json_get_wiki_page_by_name(char const * zPageName, char doParse){
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  db_prepare(&q,
             "SELECT x.rid, b.uuid FROM tag t, tagxref x, blob b"
             " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "

             " AND b.rid=x.rid"
             " ORDER BY x.mtime DESC LIMIT 1",
             zPageName 
             );
  if( (SQLITE_ROW != db_step(&q)) ){
    db_finalize(&q);
    return NULL;
  }
  rid = db_column_int(&q,0);
  zUuid = db_column_malloc(&q,1);
  db_finalize(&q);
  if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
    zBody = pWiki->zWiki;
  }

  {
    unsigned int len;
    cson_object * pay = cson_new_object();



    cson_object_set(pay,"name",json_new_string(zPageName));
    cson_object_set(pay,"uuid",json_new_string(zUuid));
    free(zUuid);
    zUuid = NULL;





    /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/
    cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser));
    cson_object_set(pay,FossilJsonKeys.timestamp, json_julian_to_timestamp(pWiki->rDate));


    cson_object_set(pay,"contentFormat",json_new_string(zFormat));

    if( doParse ){


      Blob content = empty_blob;
      Blob raw = empty_blob;

      blob_append(&raw,zBody,-1);
      wiki_convert(&raw,&content,0);
      len = strlen(zBody);
      len = (unsigned int)blob_size(&content);

      cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
      cson_object_set(pay,"content",
                      cson_value_new_string(blob_buffer(&content),len));
      blob_reset(&content);
      blob_reset(&raw);
    }else{

      len = zBody ? strlen(zBody) : 0;
      cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
      cson_object_set(pay,"content",cson_value_new_string(zBody,len));



    }
    /*TODO: add 'T' (tag) fields*/
    /*TODO: add the 'A' card (file attachment) entries?*/
    manifest_destroy(pWiki);
    return cson_object_value(pay);
  }






















}


/*
** Searches for a wiki page with the given rid. If found it behaves
** like json_get_wiki_page_by_name(pageName, doParse), else it returns

** NULL.






*/
cson_value * json_get_wiki_page_by_rid(int rid, char doParse){
  char * zPageName = NULL;





  cson_value * rc = NULL;


  zPageName = db_text(NULL,
                      "SELECT substr(t.tagname,6) AS name "
                      " FROM tag t, tagxref x, blob b "
                      " WHERE b.rid=%d "
                      " AND t.tagname GLOB 'wiki-*'"
                      " AND x.tagid=t.tagid AND b.rid=x.rid ",
                      rid);

  if( zPageName ){
    rc = json_get_wiki_page_by_name(zPageName, doParse);
    free(zPageName);

  }
  return rc;
}

/*
** Implementation of /json/wiki/get.
**
*/
static cson_value * json_wiki_get(){
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zPageName;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' or 'j' access.");
    return NULL;
  }
  zPageName = json_find_option_cstr("name",NULL,"n")
      /* Damn... fossil automatically sets name to the PATH
         part after /json, so we need a workaround down here....
      */
      ;
  if( zPageName && (NULL != strstr(zPageName, "/"))){
      /* Assume that we picked up a path remnant. */
      zPageName = NULL;
  }
  if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
      zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
  }
  if(!zPageName){
    zPageName = json_command_arg(g.json.dispatchDepth+1);
  }



  if(!zPageName||!*zPageName){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "'name' argument is missing.");
    return NULL;
  }




  zFormat = json_find_option_cstr("format",NULL,"f");

  if(!zFormat || !*zFormat){












    zFormat = "raw";
  }
  if( 'r' != *zFormat ){
    zFormat = "html";
  }
  return json_get_wiki_page_by_name(zPageName, 'h'==*zFormat);
}

/*
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
** and the page already exists then a
** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered.  If
** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is
** triggered if the page does not already exists.
**
** Note that the error triggered when createMode==0 and no such page
** exists is rather arbitrary - we could just as well create the entry
** here if it doesn't already exist. With that, save/create would
** become one operation. That said, i expect there are people who
** would categorize such behaviour as "being too clever" or "doing too
** much automatically" (and i would likely agree with them).
**
** If allowCreateIfExists is true then this function will allow a new
** page to be created even if createMode is false.
*/
static cson_value * json_wiki_create_or_save(char createMode,
                                             char allowCreateIfExists){
  Blob content = empty_blob;
  cson_value * nameV;

  cson_value * contentV;
  cson_value * emptyContent = NULL;
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  cson_string const * jstr = NULL;
  char const * zContent;
  char const * zBody = NULL;
  char const * zPageName;
  unsigned int contentLen = 0;
  int rid;
  if( (createMode && !g.perm.NewWiki)
      || (!createMode && !g.perm.WrWiki)){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires '%c' permissions.",
                 (createMode ? 'f' : 'k'));







|




|
>


|














>
|
>
>
>
>
>
>
>
>
>

|
|
|
|
>
>
>
>


|

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

|
<
<
<
<
<
<
|
<
|

>
>
>
|



>
>
>
>
>


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





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




|
|
>
|
>
>
>
>
>
>

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

|







<
<
<


|
|




















>
>
>
|

|



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

<
















|



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







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
#include "json_detail.h"
#endif

static cson_value * json_wiki_create();
static cson_value * json_wiki_get();
static cson_value * json_wiki_list();
static cson_value * json_wiki_save();
static cson_value * json_wiki_diff();
/*
** Mapping of /json/wiki/XXX commands/paths to callbacks.
*/
static const JsonPageDef JsonPageDefs_Wiki[] = {
{"create", json_wiki_create, 0},
{"diff", json_wiki_diff, 0},
{"get", json_wiki_get, 0},
{"list", json_wiki_list, 0},
{"save", json_wiki_save, 0},
{"timeline", json_timeline_wiki,0},
/* Last entry MUST have a NULL name. */
{NULL,NULL,0}
};


/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki(){
  return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
}

char * json_wiki_get_uuid_for_rid( int rid )
{
  return db_text(NULL,
             "SELECT b.uuid FROM tag t, tagxref x, blob b"
             " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
             " AND b.rid=x.rid AND b.rid=%d"
             " ORDER BY x.mtime DESC LIMIT 1",
             rid
             );
}

/*
** Tries to load a wiki page from the given rid creates a JSON object
** representation of it. If the page is not found then NULL is
** returned. If contentFormat is positive then the page content
** is HTML-ized using fossil's conventional wiki format, if it is
** negative then no parsing is performed, if it is 0 then the content
** is not returned in the response. If contentFormat is 0 then the
** contentSize reflects the number of bytes, not characters, stored in
** the page.
**
** The returned value, if not NULL, is-a JSON Object owned by the
** caller. If it returns NULL then it may set g.json's error state.
*/
cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){

  Manifest * pWiki = NULL;


  if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){




    json_set_err( FSL_JSON_E_UNKNOWN,
                  "Error reading wiki page from manifest (rid=%d).",


                  rid );


    return NULL;
  }else{






    /*char const * zFormat = NULL;*/

    unsigned int len = 0;
    cson_object * pay = cson_new_object();
    char const * zBody = pWiki->zWiki;
    char const * zFormat = NULL;
    char * zUuid = json_wiki_get_uuid_for_rid(rid);
    cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
    cson_object_set(pay,"uuid",json_new_string(zUuid));
    free(zUuid);
    zUuid = NULL;
    if( pWiki->nParent > 0 ){
      cson_object_set( pay, "parent", json_new_string(pWiki->azParent[0]) )
        /* Reminder: wiki pages do not branch and have only one parent
           (except for the initial version, which has no parents). */;
    }
    /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/
    cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser));
    cson_object_set(pay,FossilJsonKeys.timestamp,
                    json_julian_to_timestamp(pWiki->rDate));
    if(0 == contentFormat){
      cson_object_set(pay,"contentLength",
                      json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
    }else{
      if( contentFormat>0 ){/*HTML-ize it*/
        zFormat = "html";
        Blob content = empty_blob;
        Blob raw = empty_blob;
        if(zBody && *zBody){
          blob_append(&raw,zBody,-1);
          wiki_convert(&raw,&content,0);

          len = (unsigned int)blob_size(&content);
        }
        cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
        cson_object_set(pay,"content",
                        cson_value_new_string(blob_buffer(&content),len));
        blob_reset(&content);
        blob_reset(&raw);
      }else{/*raw format*/
        zFormat = "raw";
        len = zBody ? strlen(zBody) : 0;
        cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
        cson_object_set(pay,"content",cson_value_new_string(zBody,len));
      }
      cson_object_set(pay,"contentFormat",json_new_string(zFormat));

    }
    /*TODO: add 'T' (tag) fields*/
    /*TODO: add the 'A' card (file attachment) entries?*/
    manifest_destroy(pWiki);
    return cson_object_value(pay);
  }  
}

/*
** Searches for the latest version of a wiki page with the given
** name. If found it behaves like json_get_wiki_page_by_rid(theRid,
** contentFormat), else it returns NULL.
*/
cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){
  int rid;
  rid = db_int(0,
               "SELECT x.rid FROM tag t, tagxref x, blob b"
               " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
               " AND b.rid=x.rid"
               " ORDER BY x.mtime DESC LIMIT 1",
               zPageName 
             );
  if( 0==rid ){
    json_set_err( FSL_JSON_E_RESOURCE_NOT_FOUND, "Wiki page not found: %s",
                  zPageName );
    return NULL;
  }
  return json_get_wiki_page_by_rid(rid, contentFormat);
}


/*
** Searches json_find_option_ctr("format",NULL,"f") for a flag.
** If not found it returns defaultValue else it returns a value
** depending on the first character of the format option:
**
** [h]tml = 1
** [n]one = 0
** [r]aw = -1
**
** The return value is intended for use with
** json_get_wiki_page_by_rid() and friends.
*/
char json_wiki_get_content_format_flag( char defaultValue ){
  char contentFormat = defaultValue;
  char const * zFormat = json_find_option_cstr("format",NULL,"f");
  if( !zFormat || !*zFormat ){
    return contentFormat;
  }
  else if('r'==*zFormat){
    contentFormat = -1;
  }
  else if('h'==*zFormat){
    contentFormat = 1;






  }
  else if('n'==*zFormat){


    contentFormat = 0;
  }
  return contentFormat;
}

/*
** Implementation of /json/wiki/get.
**
*/
static cson_value * json_wiki_get(){



  char const * zPageName;
  char const * zFormat = NULL;
  char const * zSymName = NULL;
  char contentFormat = -1;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' or 'j' access.");
    return NULL;
  }
  zPageName = json_find_option_cstr("name",NULL,"n")
      /* Damn... fossil automatically sets name to the PATH
         part after /json, so we need a workaround down here....
      */
      ;
  if( zPageName && (NULL != strstr(zPageName, "/"))){
      /* Assume that we picked up a path remnant. */
      zPageName = NULL;
  }
  if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
      zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
  }
  if(!zPageName){
    zPageName = json_command_arg(g.json.dispatchDepth+1);
  }

  zSymName = json_find_option_cstr("uuid",NULL,"u");
  
  if((!zPageName||!*zPageName) && (!zSymName || !*zSymName)){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "At least one of the 'name' or 'uuid' arguments must be provided.");
    return NULL;
  }

  /* TODO: see if we have a page named zPageName. If not, try to resolve
     zPageName as a UUID.
  */
  
  contentFormat = json_wiki_get_content_format_flag(contentFormat);
  if(!zSymName || !*zSymName){
    return json_get_wiki_page_by_name(zPageName, contentFormat);
  }else{
    int rid = symbolic_name_to_rid( zSymName ? zSymName : zPageName, "w" );
    if(rid<0){
      json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
                   "UUID [%s] is ambiguious.", zSymName);
      return NULL;
    }else if(rid==0){
      json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
                   "UUID [%s] does not resolve to a wiki page.", zSymName);
      return NULL;
    }else{
      return json_get_wiki_page_by_rid(rid, contentFormat);
    }


  }

}

/*
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
** and the page already exists then a
** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered.  If
** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is
** triggered if the page does not already exists.
**
** Note that the error triggered when createMode==0 and no such page
** exists is rather arbitrary - we could just as well create the entry
** here if it doesn't already exist. With that, save/create would
** become one operation. That said, i expect there are people who
** would categorize such behaviour as "being too clever" or "doing too
** much automatically" (and i would likely agree with them).
**
** If allowCreateIfNotExists is true then this function will allow a new
** page to be created even if createMode is false.
*/
static cson_value * json_wiki_create_or_save(char createMode,
                                             char allowCreateIfNotExists){
  Blob content = empty_blob;  /* wiki  page content */
  cson_value * nameV;         /* wiki page name */
  char const * zPageName;     /* cstr form of page name */
  cson_value * contentV;      /* passed-in content */
  cson_value * emptyContent = NULL;  /* placeholder for empty content. */
  cson_value * payV = NULL;   /* payload/return value */

  cson_string const * jstr = NULL;  /* temp for cson_value-to-cson_string conversions. */



  unsigned int contentLen = 0;
  int rid;
  if( (createMode && !g.perm.NewWiki)
      || (!createMode && !g.perm.WrWiki)){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires '%c' permissions.",
                 (createMode ? 'f' : 'k'));
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
  if(rid){
    if(createMode){
      json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
                   "Wiki page '%s' already exists.",
                   zPageName);
      goto error;
    }
  }else if(!allowCreateIfExists){
    json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
                 "Wiki page '%s' not found.",
                 zPageName);
    goto error;
  }

  contentV = json_req_payload_get("content");
  if( !contentV ){
    if( createMode || (!rid && allowCreateIfExists) ){
      contentV = emptyContent = cson_value_new_string("",0);
    }else{
      json_set_err(FSL_JSON_E_MISSING_ARGS,
                   "'content' parameter is missing.");
      goto error;
    }
  }
  if( !cson_value_is_string(nameV)
      || !cson_value_is_string(contentV)){
    json_set_err(FSL_JSON_E_INVALID_ARGS,
                 "'name' and 'content' parameters must be strings.");
    goto error;
  }
  jstr = cson_value_get_string(contentV);
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }
  wiki_cmd_commit(zPageName, 0==rid, &content);
  blob_reset(&content);





  payV = cson_value_new_object();

  pay = cson_value_get_object(payV);
  cson_object_set( pay, "name", nameV );
  cson_object_set( pay, FossilJsonKeys.timestamp,
                   json_new_timestamp(-1) );

  goto ok;
  error:
  assert( 0 != g.json.resultCode );
  cson_value_free(payV);
  payV = NULL;
  ok:
  if( emptyContent ){
    /* We have some potentially tricky memory ownership
       here, which is why we handle emptyContent separately.

       This is, in fact, overkill because cson_value_new_string("",0)
       actually returns a shared singleton instance (i.e. doesn't







|








|




















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



<
|







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
  if(rid){
    if(createMode){
      json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
                   "Wiki page '%s' already exists.",
                   zPageName);
      goto error;
    }
  }else if(!createMode && !allowCreateIfNotExists){
    json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
                 "Wiki page '%s' not found.",
                 zPageName);
    goto error;
  }

  contentV = json_req_payload_get("content");
  if( !contentV ){
    if( createMode || (!rid && allowCreateIfNotExists) ){
      contentV = emptyContent = cson_value_new_string("",0);
    }else{
      json_set_err(FSL_JSON_E_MISSING_ARGS,
                   "'content' parameter is missing.");
      goto error;
    }
  }
  if( !cson_value_is_string(nameV)
      || !cson_value_is_string(contentV)){
    json_set_err(FSL_JSON_E_INVALID_ARGS,
                 "'name' and 'content' parameters must be strings.");
    goto error;
  }
  jstr = cson_value_get_string(contentV);
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }
  wiki_cmd_commit(zPageName, 0==rid, &content);
  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(
           cson_string_cstr(
             cson_value_get_string(nameV)),



             0);
  goto ok;
  error:
  assert( 0 != g.json.resultCode );

  assert( NULL == payV );
  ok:
  if( emptyContent ){
    /* We have some potentially tricky memory ownership
       here, which is why we handle emptyContent separately.

       This is, in fact, overkill because cson_value_new_string("",0)
       actually returns a shared singleton instance (i.e. doesn't
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
/*
** Implementation of /json/wiki/list.
*/
static cson_value * json_wiki_list(){
  cson_value * listV = NULL;
  cson_array * list = NULL;
  Stmt q;


  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' or 'o' permissions.");
    return NULL;
  }
  db_prepare(&q,"SELECT"
             " substr(tagname,6) as name"
             " FROM tag WHERE tagname GLOB 'wiki-*'"
             " ORDER BY lower(name)");
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  while( SQLITE_ROW == db_step(&q) ){





    cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0);

    if(!v){
      json_set_err(FSL_JSON_E_UNKNOWN,
                   "Could not convert wiki name column to JSON.");
      goto error;
    }else if( 0 != cson_array_append( list, v ) ){
      cson_value_free(v);
      json_set_err(FSL_JSON_E_ALLOC,"Could not append wiki page name to array.")







>
>












>
>
>
>
>
|
>







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
/*
** Implementation of /json/wiki/list.
*/
static cson_value * json_wiki_list(){
  cson_value * listV = NULL;
  cson_array * list = NULL;
  Stmt q;
  char const verbose = json_find_option_bool("verbose",NULL,"v",0);

  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' or 'o' permissions.");
    return NULL;
  }
  db_prepare(&q,"SELECT"
             " substr(tagname,6) as name"
             " FROM tag WHERE tagname GLOB 'wiki-*'"
             " ORDER BY lower(name)");
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  while( SQLITE_ROW == db_step(&q) ){
    cson_value * v;
    if( verbose ){
      char const * name = db_column_text(&q,0);
      v = json_get_wiki_page_by_name(name,0);
    }else{
      v = cson_sqlite3_column_to_value(q.pStmt,0);
    }
    if(!v){
      json_set_err(FSL_JSON_E_UNKNOWN,
                   "Could not convert wiki name column to JSON.");
      goto error;
    }else if( 0 != cson_array_append( list, v ) ){
      cson_value_free(v);
      json_set_err(FSL_JSON_E_ALLOC,"Could not append wiki page name to array.")
360
361
362
363
364
365
366








































































































367
  assert(0 != g.json.resultCode);
  cson_value_free(listV);
  listV = NULL;
  end:
  db_finalize(&q);
  return listV;
}








































































































#endif /* FOSSIL_ENABLE_JSON */







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

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
  assert(0 != g.json.resultCode);
  cson_value_free(listV);
  listV = NULL;
  end:
  db_finalize(&q);
  return listV;
}

static cson_value * json_wiki_diff(){
  char const * zV1 = NULL;
  char const * zV2 = NULL;
  char const * zContent = NULL;
  cson_object * pay = NULL;
  int argPos = g.json.dispatchDepth;
  int r1 = 0, r2 = 0;
  Manifest * pW1 = NULL, *pW2 = NULL;
  Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
  char const * zErrTag = NULL;
  int diffFlags;
  char * zUuid = NULL;
  if( !g.perm.History ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'h' permissions.");
    return NULL;
  }

  
  zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );
  zV2 = json_find_option_cstr2( "v2",NULL, NULL, ++argPos );
  if(!zV1 || !*zV1 || !zV2 || !*zV2) {
    json_set_err(FSL_JSON_E_INVALID_ARGS,
                 "Requires both 'v1' and 'v2' arguments.");
    return NULL;
  }
  
  r1 = symbolic_name_to_rid( zV1, "w" );
  zErrTag = zV1;
  if(r1<0){
    goto ambiguous;
  }else if(0==r1){
    goto invalid;
  }

  r2 = symbolic_name_to_rid( zV2, "w" );
  zErrTag = zV2;
  if(r2<0){
    goto ambiguous;
  }else if(0==r2){
    goto invalid;
  }

  zErrTag = zV1;
  pW1 = manifest_get(r1, CFTYPE_WIKI);
  if( pW1==0 ) {
    goto manifest;
  }
  zErrTag = zV2;
  pW2 = manifest_get(r2, CFTYPE_WIKI);
  if( pW2==0 ) {
    goto manifest;
  }

  blob_init(&w1, pW1->zWiki, -1);
  blob_zero(&w2);
  blob_init(&w2, pW2->zWiki, -1);
  blob_zero(&d);
  diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
  text_diff(&w2, &w1, &d, diffFlags);
  blob_reset(&w1);
  blob_reset(&w2);

  pay = cson_new_object();
  
  zUuid = json_wiki_get_uuid_for_rid( pW1->rid );
  cson_object_set(pay, "v1", json_new_string(zUuid) );
  free(zUuid);
  zUuid = json_wiki_get_uuid_for_rid( pW2->rid );
  cson_object_set(pay, "v2", json_new_string(zUuid) );
  free(zUuid);
  zUuid = NULL;

  manifest_destroy(pW1);
  manifest_destroy(pW2);

  cson_object_set(pay, "diff",
                  cson_value_new_string( blob_str(&d),
                                         (unsigned int)blob_size(&d)));
  
  return cson_object_value(pay);

  manifest:
  json_set_err(FSL_JSON_E_UNKNOWN,
               "Could not load wiki manifest for UUID [%s].",
               zErrTag);
  goto end;

  ambiguous:
  json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
               "UUID [%s] is ambiguous.", zErrTag);
  goto end;

  invalid:
  json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
               "UUID [%s] not found.", zErrTag);
  goto end;

  end:
  cson_free_object(pay);
  return NULL;
}

#endif /* FOSSIL_ENABLE_JSON */
Changes to src/main.c.
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  g.json.outOpt.addNewline = 1;
  g.json.outOpt.indentation = 1 /* in CGI/server mode this can be configured */;
#endif /* FOSSIL_ENABLE_JSON */
  expand_args_option();
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( argc<2 ){
    fossil_print(
       "Usage: %s COMMAND ...\n"
       "   or: %s help           -- for a list of common commands\n"
       "   or: %s help COMMMAND  -- for help with the named command\n"







|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  g.json.outOpt.addNewline = 1;
  g.json.outOpt.indentation = 1 /* in CGI/server mode this can be configured */;
#endif /* FOSSIL_ENABLE_JSON */
  expand_args_option();
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( argc<2 ){
    fossil_print(
       "Usage: %s COMMAND ...\n"
       "   or: %s help           -- for a list of common commands\n"
       "   or: %s help COMMMAND  -- for help with the named command\n"
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
          i++;
          continue;
        }
        zRepo[j] = '.';
      }

      if( szFile<1024 ){

        if( zNotFound ){
          cgi_redirect(zNotFound);
        }else{
#ifdef FOSSIL_ENABLE_JSON
          if(g.json.isJsonMode){
            json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
            return;







>







1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
          i++;
          continue;
        }
        zRepo[j] = '.';
      }

      if( szFile<1024 ){
        set_base_url();
        if( zNotFound ){
          cgi_redirect(zNotFound);
        }else{
#ifdef FOSSIL_ENABLE_JSON
          if(g.json.isJsonMode){
            json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
            return;
1368
1369
1370
1371
1372
1373
1374


1375
1376
1377
1378
1379
1380
1381
**
**      #!/usr/bin/fossil
**      repository: /home/somebody/project.db
**
** The second line defines the name of the repository.  After locating
** the repository, fossil will generate a webpage on stdout based on
** the values of standard CGI environment variables.


*/
void cmd_cgi(void){
  const char *zFile;
  const char *zNotFound = 0;
  char **azRedirect = 0;             /* List of repositories to redirect to */
  int nRedirect = 0;                 /* Number of entries in azRedirect */
  Blob config, line, key, value, value2;







>
>







1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
**
**      #!/usr/bin/fossil
**      repository: /home/somebody/project.db
**
** The second line defines the name of the repository.  After locating
** the repository, fossil will generate a webpage on stdout based on
** the values of standard CGI environment variables.
**
** See also: http, server, winsrv
*/
void cmd_cgi(void){
  const char *zFile;
  const char *zNotFound = 0;
  char **azRedirect = 0;             /* List of repositories to redirect to */
  int nRedirect = 0;                 /* Number of entries in azRedirect */
  Blob config, line, key, value, value2;
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
**
**        fossil http REPOSITORY INFILE OUTFILE IPADDR
**
** The argv==6 form is used by the win32 server only.
**
** COMMAND: http*
**
** Usage: %fossil http REPOSITORY [--notfound URL] [--host HOSTNAME] [--https]
**
** 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 respositories
** with names of the form "*.fossil" then the first element of the URL
** pathname selects among the various repositories.  If the pathname does
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
**
** The --host option can be used to specify the hostname for the server.
** The --https option indicates that the request came from HTTPS rather
** than HTTP.

**


** Other options:
**

**    --localauth      Password signin is not required if this is true and
**                     the input comes from 127.0.0.1 and the "localauth"
**                     setting is not disabled.



**
**    --nossl          SSL connections are not available so do not
**                     redirect from http: to https:.

*/
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  const char *zHost;
  zNotFound = find_option("notfound", 0, 1);
  g.useLocalauth = find_option("localauth", 0, 0)!=0;







|














|
>

>
>
|

>
|
<
|
>
>
>

<
<
>







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
**
**        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 respositories
** with names of the form "*.fossil" then the first element of the URL
** pathname selects among the various repositories.  If the pathname does
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
**
** The --host option can be used to specify the hostname for the server.
** The --https option indicates that the request came from HTTPS rather
** than HTTP. If --nossl is given, then SSL connections will not be available,
** thus also no redirecting from http: to https: will take place.
**
** If the --localauth option is given, then automatic login is performed
** for requests coming from localhost, if the "localauth" setting is not
** enabled.
**
** Options:
**   --localauth    enable automatic login for local connections

**   --host NAME    specify hostname of the server
**   --https        signal a request coming in via https
**   --nossl        signal that no SSL connections are available
**   --notfound URL use URL as "HTTP 404, object not found" page.
**


** See also: cgi, server, winsrv
*/
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  const char *zHost;
  zNotFound = find_option("notfound", 0, 1);
  g.useLocalauth = find_option("localauth", 0, 0)!=0;
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
/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
  login_set_capabilities("s", 0);


  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  cgi_handle_http_request(0);
  process_one_web_page(0);
}

#if !defined(_WIN32)
#if !defined(__DARWIN__) && !defined(__APPLE__)
/*
** Search for an executable on the PATH environment variable.
** Return true (1) if found and false (0) if not found.
*/
static int binaryOnPath(const char *zBinary){
  const char *zPath = getenv("PATH");
  char *zFull;
  int i;
  int bExists;
  while( zPath && zPath[0] ){
    while( zPath[0]==':' ) zPath++;
    for(i=0; zPath[i] && zPath[i]!=':'; i++){}
    zFull = mprintf("%.*s/%s", i, zPath, zBinary);







|
>
>
















|







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
/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
  login_set_capabilities("sx", 0);
  g.useLocalauth = 1;
  cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  cgi_handle_http_request(0);
  process_one_web_page(0);
}

#if !defined(_WIN32)
#if !defined(__DARWIN__) && !defined(__APPLE__)
/*
** Search for an executable on the PATH environment variable.
** Return true (1) if found and false (0) if not found.
*/
static int binaryOnPath(const char *zBinary){
  const char *zPath = fossil_getenv("PATH");
  char *zFull;
  int i;
  int bExists;
  while( zPath && zPath[0] ){
    while( zPath[0]==':' ) zPath++;
    for(i=0; zPath[i] && zPath[i]!=':'; i++){}
    zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
#endif
#endif

/*
** COMMAND: server*
** COMMAND: ui
**
** Usage: %fossil server ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
**    Or: %fossil ui ?-P|--port TCPPORT? -?-R|--root ROOT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or
** --port option.  The optional argument is the name of the repository.
** The repository argument may be omitted if the working directory is
** within an open checkout.
**







|
|







1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
#endif
#endif

/*
** COMMAND: server*
** COMMAND: ui
**
** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
**    Or: %fossil ui ?OPTIONS? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or
** --port option.  The optional argument is the name of the repository.
** The repository argument may be omitted if the working directory is
** within an open checkout.
**
1670
1671
1672
1673
1674
1675
1676








1677
1678
1679
1680
1681
1682
1683
** various repositories.
**
** By default, the "ui" command provides full administrative access without
** having to log in.  This can be disabled by setting turning off the
** "localauth" setting.  Automatic login for the "server" command is available
** if the --localauth option is present and the "localauth" setting is off
** and the connection is from localhost.








*/
void cmd_webserver(void){
  int iPort, mxPort;        /* Range of TCP ports allowed */
  const char *zPort;        /* Value of the --port option */
  char *zBrowser;           /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */







>
>
>
>
>
>
>
>







1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
** various repositories.
**
** By default, the "ui" command provides full administrative access without
** having to log in.  This can be disabled by setting turning off the
** "localauth" setting.  Automatic login for the "server" command is available
** if the --localauth option is present and the "localauth" setting is off
** and the connection is from localhost.
** Options:
**   --localauth         enable automatic login for requests from localhost
**   -P|--port TCPPORT   listen to request on port TCPPORT
**   -R|--root ROOT      map fossil at virtual directory ROOT in reverse 
**                       proxying
**   --th-trace          trace TH1 execution (for debugging purposes)
**
** See also: cgi, http, winsrv
*/
void cmd_webserver(void){
  int iPort, mxPort;        /* Range of TCP ports allowed */
  const char *zPort;        /* Value of the --port option */
  char *zBrowser;           /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */
Changes to src/main.mk.


1

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


# DO NOT EDIT

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
# This file is included by primary Makefile.
#

XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR)


SRC = \
  $(SRCDIR)/add.c \
  $(SRCDIR)/allrepo.c \
  $(SRCDIR)/attach.c \
  $(SRCDIR)/bag.c \
>
>
|
>








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#
##############################################################################
# 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.
#
# This file is included by primary Makefile.
#

XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) -I$(OBJDIR)


SRC = \
  $(SRCDIR)/add.c \
  $(SRCDIR)/allrepo.c \
  $(SRCDIR)/attach.c \
  $(SRCDIR)/bag.c \
48
49
50
51
52
53
54

55

56
57
58
59
60
61
62
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \
  $(SRCDIR)/json.c \
  $(SRCDIR)/json_artifact.c \
  $(SRCDIR)/json_branch.c \

  $(SRCDIR)/json_diff.c \

  $(SRCDIR)/json_login.c \
  $(SRCDIR)/json_query.c \
  $(SRCDIR)/json_report.c \
  $(SRCDIR)/json_tag.c \
  $(SRCDIR)/json_timeline.c \
  $(SRCDIR)/json_user.c \
  $(SRCDIR)/json_wiki.c \







>

>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \
  $(SRCDIR)/json.c \
  $(SRCDIR)/json_artifact.c \
  $(SRCDIR)/json_branch.c \
  $(SRCDIR)/json_config.c \
  $(SRCDIR)/json_diff.c \
  $(SRCDIR)/json_finfo.c \
  $(SRCDIR)/json_login.c \
  $(SRCDIR)/json_query.c \
  $(SRCDIR)/json_report.c \
  $(SRCDIR)/json_tag.c \
  $(SRCDIR)/json_timeline.c \
  $(SRCDIR)/json_user.c \
  $(SRCDIR)/json_wiki.c \
99
100
101
102
103
104
105

106
107
108
109
110
111
112
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \

  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \







>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \
  $(SRCDIR)/xfersetup.c \
  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \
143
144
145
146
147
148
149

150

151
152
153
154
155
156
157
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \
  $(OBJDIR)/json_.c \
  $(OBJDIR)/json_artifact_.c \
  $(OBJDIR)/json_branch_.c \

  $(OBJDIR)/json_diff_.c \

  $(OBJDIR)/json_login_.c \
  $(OBJDIR)/json_query_.c \
  $(OBJDIR)/json_report_.c \
  $(OBJDIR)/json_tag_.c \
  $(OBJDIR)/json_timeline_.c \
  $(OBJDIR)/json_user_.c \
  $(OBJDIR)/json_wiki_.c \







>

>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \
  $(OBJDIR)/json_.c \
  $(OBJDIR)/json_artifact_.c \
  $(OBJDIR)/json_branch_.c \
  $(OBJDIR)/json_config_.c \
  $(OBJDIR)/json_diff_.c \
  $(OBJDIR)/json_finfo_.c \
  $(OBJDIR)/json_login_.c \
  $(OBJDIR)/json_query_.c \
  $(OBJDIR)/json_report_.c \
  $(OBJDIR)/json_tag_.c \
  $(OBJDIR)/json_timeline_.c \
  $(OBJDIR)/json_user_.c \
  $(OBJDIR)/json_wiki_.c \
194
195
196
197
198
199
200

201
202
203
204
205
206
207
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \

  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \







>







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \
  $(OBJDIR)/xfersetup_.c \
  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \
238
239
240
241
242
243
244

245

246
247
248
249
250
251
252
 $(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_diff.o \

 $(OBJDIR)/json_login.o \
 $(OBJDIR)/json_query.o \
 $(OBJDIR)/json_report.o \
 $(OBJDIR)/json_tag.o \
 $(OBJDIR)/json_timeline.o \
 $(OBJDIR)/json_user.o \
 $(OBJDIR)/json_wiki.o \







>

>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
 $(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_finfo.o \
 $(OBJDIR)/json_login.o \
 $(OBJDIR)/json_query.o \
 $(OBJDIR)/json_report.o \
 $(OBJDIR)/json_tag.o \
 $(OBJDIR)/json_timeline.o \
 $(OBJDIR)/json_user.o \
 $(OBJDIR)/json_wiki.o \
289
290
291
292
293
294
295

296
297
298
299
300
301
302
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \

 $(OBJDIR)/zip.o

APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)







>







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)
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

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(OBJDIR)/mkversion:	$(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the testsuite 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 $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(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)




TCL_OBJ.1 =
TCL_OBJ.0 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(TCL_OBJ.$(FOSSIL_ENABLE_TCL))  $(OBJDIR)/cson_amalgamation.o

$(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)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/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_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
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








|
















>
>
>
|
|




















|


|







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

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(OBJDIR)/mkversion:	$(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/mkversion $(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 $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(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_TCL variable may be undefined, set to 0, or set to 1.
# If it is set to 1, then we need to build the Tcl integration code and
# link to the Tcl library.
TCL_OBJ.0 = 
TCL_OBJ.1 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(TCL_OBJ.$(FOSSIL_ENABLE_TCL))  $(OBJDIR)/cson_amalgamation.o

$(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)/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_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_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
	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_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
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

646
647
648
649
650
651
652







653
654
655
656
657
658
659







660
661
662
663
664
665
666
$(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_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_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







>
>
>
>
>
>
>







>
>
>
>
>
>
>







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
$(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_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
1003
1004
1005
1006
1007
1008
1009







1010
1011
1012
1013
1014
1015
1016
$(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)/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







>
>
>
>
>
>
>







1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
$(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
Changes to src/makemake.tcl.
54
55
56
57
58
59
60

61

62
63
64
65
66
67
68
  http_socket
  http_transport
  import
  info
  json
  json_artifact
  json_branch

  json_diff

  json_login
  json_query
  json_report
  json_tag
  json_timeline
  json_user
  json_wiki







>

>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  http_socket
  http_transport
  import
  info
  json
  json_artifact
  json_branch
  json_config
  json_diff
  json_finfo
  json_login
  json_query
  json_report
  json_tag
  json_timeline
  json_user
  json_wiki
105
106
107
108
109
110
111

112
113
114
115
116
117
118
  user
  verify
  vfile
  wiki
  wikiformat
  winhttp
  xfer

  zip
  http_ssl
}

# Name of the final application
#
set name fossil







>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  user
  verify
  vfile
  wiki
  wikiformat
  winhttp
  xfer
  xfersetup
  zip
  http_ssl
}

# Name of the final application
#
set name fossil
137
138
139
140
141
142
143
144



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
##############################################################################
# Start by generating the "main.mk" makefile used for all unix systems.
#
puts "building main.mk"
set output_file [open main.mk w]
fconfigure $output_file -translation binary

writeln {# DO NOT EDIT



#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
# This file is included by primary Makefile.
#

XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR)

}
writeln -nonewline "SRC ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n  \$(SRCDIR)/$s.c"
}
writeln "\n"







|
>
>
>








|







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
##############################################################################
# Start by generating the "main.mk" makefile used for all unix systems.
#
puts "building main.mk"
set output_file [open main.mk 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.
#
# This file is included by primary Makefile.
#

XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) -I$(OBJDIR)

}
writeln -nonewline "SRC ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n  \$(SRCDIR)/$s.c"
}
writeln "\n"
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

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(OBJDIR)/mkversion:	$(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c

# WARNING. DANGER. Running the testsuite 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 $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(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)




TCL_OBJ.1 =
TCL_OBJ.0 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \







|


















>
>
>
|
|







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

$(OBJDIR)/mkindex:	$(SRCDIR)/mkindex.c
	$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c

$(OBJDIR)/mkversion:	$(SRCDIR)/mkversion.c
	$(BCC) -o $(OBJDIR)/mkversion $(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 $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
	$(OBJDIR)/mkversion $(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_TCL variable may be undefined, set to 0, or set to 1.
# If it is set to 1, then we need to build the Tcl integration code and
# link to the Tcl library.
TCL_OBJ.0 = 
TCL_OBJ.1 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
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"







|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
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_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
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"
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
#
puts "building ../win/Makefile.mingw"
set output_file [open ../win/Makefile.mingw w]
fconfigure $output_file -translation binary

writeln {#!/usr/bin/make
#








# This is a makefile for us on windows using mingw.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.
#
#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc





#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL=1




#### The directory in which the zlib compression library is installed.


#

#







































ZLIBDIR = /programs/gnuwin32





#### 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 -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL















TCC += -static -DFOSSIL_ENABLE_SSL=1










endif

#### 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 -lws2_32


# OpenSSL:
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif












LIB += -lmingwex -lz -lws2_32


#### Tcl shell for use in running the fossil testsuite.  This is only
#    used for testing.  If you do not run
#
TCLSH = tclsh

#### Nullsoft installer makensis location
#
MAKENSIS = "c:\Program Files\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







>
>
>
>
>
>
>
>
|








<










>
>
>
>


|

>
>
>
|
>
>

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

>
>
>
>
|





|



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




|



|
>
>
|



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

|
|



|

|







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
#
puts "building ../win/Makefile.mingw"
set output_file [open ../win/Makefile.mingw w]
fconfigure $output_file -translation binary

writeln {#!/usr/bin/make
#
##############################################################################
# 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.
#
# This is a makefile for us on windows using MinGW.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.

#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc

#### 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

#### 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

#### The directories where the zlib include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#
ZINCDIR = $(SRCDIR)/../zlib-1.2.6
ZLIBDIR = $(SRCDIR)/../zlib-1.2.6

#### 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)/../openssl-1.0.0g/include
OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.0g

#### 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
#    here is to use the Sysinternals junction tool to create a hard
#    link between a "tcl-8.x" sub-directory of the Fossil source code
#    directory and the target Tcl directory.  This removes the need to
#    hard-code the necessary paths in this Makefile.
#
TCLDIR = $(SRCDIR)/../tcl-8.6

#### The Tcl source code directory.  This defaults to the same value as
#    TCLDIR macro (above), which may not be correct.  This value will
#    only be used if the FOSSIL_TCL_SOURCE macro is defined.
#
TCLSRCDIR = $(TCLDIR)

#### The Tcl include and library directories.  These values will only be
#    used if the FOSSIL_TCL_SOURCE macro is not defined.
#
TCLINCDIR = $(TCLDIR)/include
TCLLIBDIR = $(TCLDIR)/lib

#### Tcl: Which Tcl library do we want to use (8.4, 8.5, 8.6, etc)?
#
LIBTCL = -ltcl86

#### 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 -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -Dpqueue_insert=pqueue_insert_fossil
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
endif
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
endif

# With Tcl support (statically linked)
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1 -DSTATIC_BUILD
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.  We add the -static option here
#    so that we can build a static executable that will run in a
#    chroot jail.
#
LIB = -static
LIB += -lmingwex -lz

# OpenSSL: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
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
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
else
LIB += -lws2_32
endif

#### 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
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

$(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 testsuite 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:	$(APPNAME)
	$(TCLSH) test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ = \
  $(OBJDIR)/sqlite3.o \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/cson_amalgamation.o





$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires msys to be installed in addition to the mingw, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:	
	rm -rf $(OBJDIR) $(APPNAME)

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./fossil.nsi

}








|


|
|










>
>
>
>







|


|



|







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

$(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

EXTRAOBJ = \
  $(OBJDIR)/sqlite3.o \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires MSYS to be installed in addition to the MinGW, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:
	rm -rf $(OBJDIR) $(APPNAME)

setup: $(OBJDIR) $(APPNAME)
	$(MAKENSIS) ./fossil.nsi

}

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
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt $SQLITE_OPTIONS
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

set opt {}
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"







close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.dmc
#
puts "building ../win/Makefile.dmc"
set output_file [open ../win/Makefile.dmc w]
fconfigure $output_file -translation binary

writeln {# DO NOT EDIT



#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.

B      = ..
SRCDIR = $B\src
OBJDIR = .
O      = .obj
E      = .exe









|












>
>
>
>
>













|
>
>
>


|

>







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
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt $SQLITE_OPTIONS
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"

set opt {}
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln {ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif
}

close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.dmc
#
puts "building ../win/Makefile.dmc"
set output_file [open ../win/Makefile.dmc 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 = .
O      = .obj
E      = .exe


629
630
631
632
633
634
635

636

637
638
639
640
641
642
643

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_diff$O : $(SRCDIR)\json_detail.h

$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h







>

>







751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_finfo$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
666
667
668
669
670
671
672
673



674
675
676
677

678
679
680
681
682
683
684
##############################################################################
# Begin win/Makefile.msc
#
puts "building ../win/Makefile.msc"
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary

writeln {# DO NOT EDIT



#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.

B      = ..
SRCDIR = $B\src
OBJDIR = .
OX     = .
O      = .obj
E      = .exe








|
>
>
>


|

>







790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
##############################################################################
# Begin win/Makefile.msc
#
puts "building ../win/Makefile.msc"
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

782
783
784
785
786
787
788

789

790
791
792
793
794
795
796

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_diff$O : $(SRCDIR)\json_detail.h

$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h







>

>







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_finfo$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
819
820
821
822
823
824
825
826



827
828
829
830
831
832
833
834
835
836
##############################################################################
# Begin win/Makefile.PellesCGMake
#
puts "building ../win/Makefile.PellesCGMake"
set output_file [open ../win/Makefile.PellesCGMake w]
fconfigure $output_file -translation binary

writeln {# DO NOT EDIT



#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.
#
# HowTo
# -----
#
# This is a Makefile to compile fossil with PellesC from
#  http://www.smorgasbordet.com/pellesc/index.htm







|
>
>
>


|







949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
##############################################################################
# Begin win/Makefile.PellesCGMake
#
puts "building ../win/Makefile.PellesCGMake"
set output_file [open ../win/Makefile.PellesCGMake 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.
#
# HowTo
# -----
#
# This is a Makefile to compile fossil with PellesC from
#  http://www.smorgasbordet.com/pellesc/index.htm
Changes to src/manifest.c.
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
    }
  }
  if( p->zBaseline==0 ) return 0;
  fetch_baseline(p, 1);
  pBase = p->pBaseline;
  if( pBase==0 ) return 0;
  for(i=0; i<pBase->nFile; i++){
    if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){
      return &p->aFile[i];
    }
  }
  return 0;
}

/*
** Add mlink table entries associated with manifest cid, pChild.  The







|
|







1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
    }
  }
  if( p->zBaseline==0 ) return 0;
  fetch_baseline(p, 1);
  pBase = p->pBaseline;
  if( pBase==0 ) return 0;
  for(i=0; i<pBase->nFile; i++){
    if( fossil_stricmp(zName, pBase->aFile[i].zName)==0 ){
      return &pBase->aFile[i];
    }
  }
  return 0;
}

/*
** Add mlink table entries associated with manifest cid, pChild.  The
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
  }
  if( p->type==CFTYPE_CONTROL ){
    Blob comment;
    int i;
    const char *zName;
    const char *zValue;
    const char *zUuid;

    blob_zero(&comment);
    for(i=0; i<p->nTag; i++){
      zUuid = p->aTag[i].zUuid;
      if( i==0 || fossil_strcmp(zUuid, p->aTag[i-1].zUuid)!=0 ){
        if( i>0 ) blob_append(&comment, " ", 1);
        blob_appendf(&comment, "Tag changes on [/timeline?dp=%S&n=4 | %S]:",

           zUuid, zUuid);

      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;


































      if( zName[0]=='-' ){
        blob_appendf(&comment, " Cancel");
      }else if( zName[0]=='+' ){
        blob_appendf(&comment, " Add");
      }else{
        blob_appendf(&comment, " Add propagating");
      }
      if( memcmp(&zName[1], "sym-",4)==0 ){
        blob_appendf(&comment, " symbolic tag \"%h\".", &zName[5]);
      }else if( fossil_strcmp(&zName[1], "comment")!=0 && zValue && zValue[0] ){
        blob_appendf(&comment, " %h=%h.", &zName[1], zValue);
      }else{
        blob_appendf(&comment, " %h.", &zName[1]);
      }
    }


    db_multi_exec(
      "REPLACE INTO event(type,mtime,objid,user,comment)"
      "VALUES('g',%.17g,%d,%Q,%Q)",
      p->rDate, rid, p->zUser, blob_str(&comment)
    );
    blob_reset(&comment);
  }







>





|
>

>



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







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
  }
  if( p->type==CFTYPE_CONTROL ){
    Blob comment;
    int i;
    const char *zName;
    const char *zValue;
    const char *zUuid;
    int branchMove = 0;
    blob_zero(&comment);
    for(i=0; i<p->nTag; i++){
      zUuid = p->aTag[i].zUuid;
      if( i==0 || fossil_strcmp(zUuid, p->aTag[i-1].zUuid)!=0 ){
        if( i>0 ) blob_append(&comment, " ", 1);
        blob_appendf(&comment,
           "Edit &#91;[/info/%S | %S]&#93;:",
           zUuid, zUuid);
        branchMove = 0;
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
           " Move to branch [/timeline?r=%h&nd&dp=%S | %h].",
           zValue, zUuid, zValue);
        branchMove = 1;
      }else if( strcmp(zName, "*bgcolor")==0 ){
        blob_appendf(&comment,
           " Change branch background color to \"%h\".", zValue);
      }else if( strcmp(zName, "+bgcolor")==0 ){
        blob_appendf(&comment,
           " Change background color to \"%h\".", zValue);
      }else if( strcmp(zName, "-bgcolor")==0 ){
        blob_appendf(&comment, " Cancel background color.");
      }else if( strcmp(zName, "+comment")==0 ){
        blob_appendf(&comment, " Edit check-in comment.");
      }else if( strcmp(zName, "+user")==0 ){
        blob_appendf(&comment, " Change user to \"%h\".", zValue);
      }else if( strcmp(zName, "+date")==0 ){
        blob_appendf(&comment, " Timestamp %h.", zValue);
      }else if( memcmp(zName, "-sym-",5)==0 ){
        if( !branchMove ) blob_appendf(&comment, " Cancel tag %h.", &zName[5]);
      }else if( memcmp(zName, "*sym-",5)==0 ){
        if( !branchMove ){
          blob_appendf(&comment, " Add propagating tag \"%h\".", &zName[5]);
        }
      }else if( memcmp(zName, "+sym-",5)==0 ){
        blob_appendf(&comment, " Add tag \"%h\".", &zName[5]);
      }else if( memcmp(zName, "-sym-",5)==0 ){
        blob_appendf(&comment, " Cancel tag \"%h\".", &zName[5]);
      }else if( strcmp(zName, "+closed")==0 ){
        blob_appendf(&comment, " Marked \"Closed\".");
      }else if( strcmp(zName, "-closed")==0 ){
        blob_appendf(&comment, " Removed the \"Closed\" mark.");
      }else {
        if( zName[0]=='-' ){
          blob_appendf(&comment, " Cancel \"%h\"", &zName[1]);
        }else if( zName[0]=='+' ){
          blob_appendf(&comment, " Add \"%h\"", &zName[1]);
        }else{
          blob_appendf(&comment, " Add propagating \"%h\"", &zName[1]);
        }


        if( zValue && zValue[0] ){
          blob_appendf(&comment, " with value \"%h\".", zValue);
        }else{
          blob_appendf(&comment, ".");
        }
      }
    }
    /*blob_appendf(&comment, " &#91;[/info/%S | details]&#93;");*/
    db_multi_exec(
      "REPLACE INTO event(type,mtime,objid,user,comment)"
      "VALUES('g',%.17g,%d,%Q,%Q)",
      p->rDate, rid, p->zUser, blob_str(&comment)
    );
    blob_reset(&comment);
  }
Changes to src/merge.c.
18
19
20
21
22
23
24

































25
26
27
28
29
30
31
** This file contains code used to merge two or more branches into
** a single tree.
*/
#include "config.h"
#include "merge.h"
#include <assert.h>



































/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? VERSION
**
** The argument VERSION is a version that should be merged into the







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







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
** This file contains code used to merge two or more branches into
** a single tree.
*/
#include "config.h"
#include "merge.h"
#include <assert.h>

/*
** Print information about a particular check-in.
*/
void print_checkin_description(int rid, int indent, const char *zLabel){
  Stmt q;
  db_prepare(&q,
     "SELECT datetime(mtime,'localtime'),"
     "       coalesce(euser,user), coalesce(ecomment,comment),"
     "       (SELECT uuid FROM blob WHERE rid=%d),"
     "       (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref"
     "         WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid"
     "           AND tagxref.rid=%d AND tagxref.tagtype>0)"
     "  FROM event WHERE objid=%d", rid, rid, rid);
  if( db_step(&q)==SQLITE_ROW ){
    const char *zTagList = db_column_text(&q, 4);
    char *zCom;
    if( zTagList && zTagList[0] ){
      zCom = mprintf("%s (%s)", db_column_text(&q, 2), zTagList);
    }else{
      zCom = mprintf("%s", db_column_text(&q,2));
    }
    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);
}


/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? VERSION
**
** The argument VERSION is a version that should be merged into the
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    pid = name_to_typed_rid(zPivot, "ci");
    if( pid==0 || !is_a_version(pid) ){
      fossil_fatal("not a version: %s", zPivot);
    }
    if( pickFlag ){
      fossil_fatal("incompatible options: --cherrypick & --baseline");
    }
    /* pickFlag = 1;  // Using --baseline is really like doing a cherrypick */
  }else if( pickFlag || backoutFlag ){
    pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
    if( pid<=0 ){
      fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
    }
  }else{
    pivot_set_primary(mid);







<







147
148
149
150
151
152
153

154
155
156
157
158
159
160
    pid = name_to_typed_rid(zPivot, "ci");
    if( pid==0 || !is_a_version(pid) ){
      fossil_fatal("not a version: %s", zPivot);
    }
    if( pickFlag ){
      fossil_fatal("incompatible options: --cherrypick & --baseline");
    }

  }else if( pickFlag || backoutFlag ){
    pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
    if( pid<=0 ){
      fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
    }
  }else{
    pivot_set_primary(mid);
142
143
144
145
146
147
148




149
150
151
152
153
154
155
    int t = pid;
    pid = mid;
    mid = t;
  }
  if( !is_a_version(pid) ){
    fossil_fatal("not a version: record #%d", pid);
  }




  vfile_check_signature(vid, 1, 0);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);
  if( debugFlag ){
    char *z;







>
>
>
>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    int t = pid;
    pid = mid;
    mid = t;
  }
  if( !is_a_version(pid) ){
    fossil_fatal("not a version: record #%d", pid);
  }
  if( detailFlag ){
    print_checkin_description(mid, 12, "merge-from:");
    print_checkin_description(pid, 12, "baseline:");
  }
  vfile_check_signature(vid, 1, 0);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);
  if( debugFlag ){
    char *z;
516
517
518
519
520
521
522


523


524





525
526
527
528
    }
  }

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);


  if( !pickFlag ){


    db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);





  }
  undo_finish();
  db_end_transaction(nochangeFlag);
}







>
>
|
>
>
|
>
>
>
>
>




552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
    }
  }

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
  db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)",
                pickFlag ? -1 : (backoutFlag ? -2 : 0), mid);
  if( pickFlag ){
    /* For a cherry-pick merge, make the default check-in comment the same
    ** as the check-in comment on the check-in that is being merged in. */
    db_multi_exec(
       "REPLACE INTO vvar(name,value)"
       " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
       "  WHERE type='ci' AND objid=%d",
       mid
    );
  }
  undo_finish();
  db_end_transaction(nochangeFlag);
}
Changes to src/merge3.c.
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
  Blob *pPivot,       /* Common ancestor (older) */
  const char *zV1,    /* Name of file for version merging into (mine) */
  Blob *pV2,          /* Version merging from (yours) */
  Blob *pOut          /* Output written here */
){
  Blob v1;            /* Content of zV1 */
  int rc;             /* Return code of subroutines and this routine */




  blob_read_from_file(&v1, zV1);
  rc = blob_merge(pPivot, &v1, pV2, pOut);
  if( rc>0 ){
    char *zPivot;   /* Name of the pivot file */
    char *zOrig;    /* Name of the original content file */
    char *zOther;   /* Name of the merge file */
    const char *zGMerge;   /* Name of the gmerge command */

    zPivot = file_newname(zV1, "baseline", 1);
    blob_write_to_file(pPivot, zPivot);
    zOrig = file_newname(zV1, "original", 1);
    blob_write_to_file(&v1, zOrig);
    zOther = file_newname(zV1, "merge", 1);
    blob_write_to_file(pV2, zOther);




    zGMerge = db_get("gmerge-command", 0);
    if( zGMerge && zGMerge[0] ){
      char *zOut;     /* Temporary output file */
      char *zCmd;     /* Command to invoke */
      const char *azSubst[8];  /* Strings to be substituted */

      zOut = file_newname(zV1, "output", 1);







>
>
>



|
<
<
<








>
>
>
>







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
  Blob *pPivot,       /* Common ancestor (older) */
  const char *zV1,    /* Name of file for version merging into (mine) */
  Blob *pV2,          /* Version merging from (yours) */
  Blob *pOut          /* Output written here */
){
  Blob v1;            /* Content of zV1 */
  int rc;             /* Return code of subroutines and this routine */
  char *zPivot;       /* Name of the pivot file */
  char *zOrig;        /* Name of the original content file */
  char *zOther;       /* Name of the merge file */

  blob_read_from_file(&v1, zV1);
  rc = blob_merge(pPivot, &v1, pV2, pOut);
  if( rc!=0 ){



    const char *zGMerge;   /* Name of the gmerge command */

    zPivot = file_newname(zV1, "baseline", 1);
    blob_write_to_file(pPivot, zPivot);
    zOrig = file_newname(zV1, "original", 1);
    blob_write_to_file(&v1, zOrig);
    zOther = file_newname(zV1, "merge", 1);
    blob_write_to_file(pV2, zOther);
  }
  if( rc>0 ){
    const char *zGMerge;   /* Name of the gmerge command */

    zGMerge = db_get("gmerge-command", 0);
    if( zGMerge && zGMerge[0] ){
      char *zOut;     /* Temporary output file */
      char *zCmd;     /* Command to invoke */
      const char *azSubst[8];  /* Strings to be substituted */

      zOut = file_newname(zV1, "output", 1);
432
433
434
435
436
437
438


439
440
441
442
443
444
445
        file_delete(zOrig);
        file_delete(zOther);
        file_delete(zOut);
      }
      fossil_free(zCmd);
      fossil_free(zOut);
    }


    fossil_free(zPivot);
    fossil_free(zOrig);
    fossil_free(zOther);
  }
  blob_reset(&v1);
  return rc;
}







>
>







436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
        file_delete(zOrig);
        file_delete(zOther);
        file_delete(zOut);
      }
      fossil_free(zCmd);
      fossil_free(zOut);
    }
  }
  if( rc!=0 ){
    fossil_free(zPivot);
    fossil_free(zOrig);
    fossil_free(zOther);
  }
  blob_reset(&v1);
  return rc;
}
Changes to src/name.c.
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
** match any known object.  Or return -1 if the name is ambiguious.
**
** The zType parameter specifies the type of artifact: ci, t, w, e, g. 
** If zType is NULL or "" or "*" then any type of artifact will serve.
** zType is "ci" in most use cases since we are usually searching for
** a check-in.
*/
static int symbolic_name_to_rid(const char *zTag, const char *zType){
  int vid;
  int rid = 0;
  int nTag;
  int i;

  if( zType==0 || zType[0]==0 ) zType = "*";
  if( zTag==0 || zTag[0]==0 ) return 0;







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
** match any known object.  Or return -1 if the name is ambiguious.
**
** The zType parameter specifies the type of artifact: ci, t, w, e, g. 
** If zType is NULL or "" or "*" then any type of artifact will serve.
** zType is "ci" in most use cases since we are usually searching for
** a check-in.
*/
int symbolic_name_to_rid(const char *zTag, const char *zType){
  int vid;
  int rid = 0;
  int nTag;
  int i;

  if( zType==0 || zType[0]==0 ) zType = "*";
  if( zTag==0 || zTag[0]==0 ) return 0;
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
  rid = symbolic_name_to_rid(zName, 0);
  if( rid<0 ){
    fossil_print("Ambiguous artifact name prefix: %s\n", zName);
  }else if( rid==0 ){
    fossil_print("Unknown artifact: %s\n", zName);
  }else{
    Stmt q;

    db_prepare(&q, "SELECT uuid, size, datetime(mtime, 'localtime'), ipaddr"



                   "  FROM blob, rcvfrom"
                   " WHERE rid=%d"
                   "   AND rcvfrom.rcvid=blob.rcvid",
                   rid);
    if( db_step(&q)==SQLITE_ROW ){

      if( fExtra ){
        fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
        fossil_print("received: %s from %s\n",
           db_column_text(&q, 2),
           db_column_text(&q, 3));
      }else{
        fossil_print("artifact: %s\n", db_column_text(&q,0));
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
      }



    }
    db_finalize(&q);
    db_prepare(&q,
       "SELECT type, datetime(mtime,'localtime'),"
       "       coalesce(euser,user), coalesce(ecomment,comment)"
       "  FROM event WHERE objid=%d", rid);
    if( db_step(&q)==SQLITE_ROW ){







>
|
>
>
>
|
|
|
|

>










>
>
>







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
  rid = symbolic_name_to_rid(zName, 0);
  if( rid<0 ){
    fossil_print("Ambiguous artifact name prefix: %s\n", zName);
  }else if( rid==0 ){
    fossil_print("Unknown artifact: %s\n", zName);
  }else{
    Stmt q;
    db_prepare(&q,
       "SELECT uuid, size, datetime(mtime, 'localtime'), ipaddr,"
       "       (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref"
       "         WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid"
       "           AND tagxref.rid=blob.rid AND tagxref.tagtype>0)"
       "  FROM blob, rcvfrom"
       " WHERE rid=%d"
       "   AND rcvfrom.rcvid=blob.rcvid",
       rid);
    if( db_step(&q)==SQLITE_ROW ){
      const char *zTagList = db_column_text(&q, 4);
      if( fExtra ){
        fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
        fossil_print("received: %s from %s\n",
           db_column_text(&q, 2),
           db_column_text(&q, 3));
      }else{
        fossil_print("artifact: %s\n", db_column_text(&q,0));
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
      }
      if( zTagList && zTagList[0] ){
        fossil_print("tags:     %s\n", zTagList);
      }
    }
    db_finalize(&q);
    db_prepare(&q,
       "SELECT type, datetime(mtime,'localtime'),"
       "       coalesce(euser,user), coalesce(ecomment,comment)"
       "  FROM event WHERE objid=%d", rid);
    if( db_step(&q)==SQLITE_ROW ){
Changes to src/path.c.
131
132
133
134
135
136
137
138




139
140
141
142
143
144
145

  path_reset();
  path.pStart = path_new_node(iFrom, 0, 0);
  if( iTo==iFrom ){
    path.pEnd = path.pStart;
    return path.pStart;
  }
  if( oneWayOnly ){




    db_prepare(&s, 
        "SELECT cid, 1 FROM plink WHERE pid=:pid "
    );
  }else if( directOnly ){
    db_prepare(&s, 
        "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
        "UNION ALL "







|
>
>
>
>







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

  path_reset();
  path.pStart = path_new_node(iFrom, 0, 0);
  if( iTo==iFrom ){
    path.pEnd = path.pStart;
    return path.pStart;
  }
  if( oneWayOnly && directOnly ){
    db_prepare(&s, 
        "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim"
    );
  }else if( oneWayOnly ){
    db_prepare(&s, 
        "SELECT cid, 1 FROM plink WHERE pid=:pid "
    );
  }else if( directOnly ){
    db_prepare(&s, 
        "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
        "UNION ALL "
Changes to src/printf.c.
820
821
822
823
824
825
826

827
828
829
830
831
832
833
  assert( toStdErr==0 || toStdErr==1 );
  if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
  fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
  free(zToFree);
#else
  fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
#endif

}

/*
** Write output for user consumption.  If g.cgiOutput is enabled, then
** send the output as part of the CGI reply.  If g.cgiOutput is false,
** then write on standard output.
*/







>







820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
  assert( toStdErr==0 || toStdErr==1 );
  if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
  fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
  free(zToFree);
#else
  fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
#endif
  fflush(toStdErr ? stderr : stdout);
}

/*
** Write output for user consumption.  If g.cgiOutput is enabled, then
** send the output as part of the CGI reply.  If g.cgiOutput is false,
** then write on standard output.
*/
Changes to src/rebuild.c.
422
423
424
425
426
427
428

429
430
431
432
433
434
435
  }
  if( doClustering ) create_cluster();
  if( ttyOutput && !g.fQuiet && totalSize>0 ){
    processCnt += incrSize;
    percent_complete((processCnt*1000)/totalSize);
  }
  if(!g.fQuiet && ttyOutput ){

    fossil_print("\n");
  }
  return errCnt;
}

/*
** Attempt to convert more full-text blobs into delta-blobs for







>







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  }
  if( doClustering ) create_cluster();
  if( ttyOutput && !g.fQuiet && totalSize>0 ){
    processCnt += incrSize;
    percent_complete((processCnt*1000)/totalSize);
  }
  if(!g.fQuiet && ttyOutput ){
    percent_complete(1000);
    fossil_print("\n");
  }
  return errCnt;
}

/*
** Attempt to convert more full-text blobs into delta-blobs for
483
484
485
486
487
488
489




















490
491
492
493
494
495
496
      previd = rid;
    }
  }
  db_finalize(&q);

  db_end_transaction(0);
}





















/*
** COMMAND: rebuild
**
** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
**
** Reconstruct the named repository database from the core







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







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
      previd = rid;
    }
  }
  db_finalize(&q);

  db_end_transaction(0);
}


/* Reconstruct the private table.  The private table contains the rid
** of every manifest that is tagged with "private" and every file that
** is not used by a manifest that is not private.
*/
static void reconstruct_private_table(void){
  db_multi_exec(
    "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);"
    "INSERT INTO private_ckin "
        " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;"
    "INSERT OR IGNORE INTO private"
        " SELECT fid FROM mlink"
        " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;"
    "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;"
    "DROP TABLE private_ckin;", TAG_PRIVATE
  );
  fix_private_blob_dependencies(0);
}


/*
** COMMAND: rebuild
**
** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
**
** Reconstruct the named repository database from the core
549
550
551
552
553
554
555

556
557
558
559
560
561
562
    }
    db_close(1);
    db_open_repository(g.zRepositoryName);
  }
  db_begin_transaction();
  ttyOutput = 1;
  errCnt = rebuild_db(randomizeFlag, 1, doClustering);

  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());",
    CONTENT_SCHEMA, AUX_SCHEMA
  );
  if( errCnt && !forceFlag ){
    fossil_print(







>







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
    }
    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());",
    CONTENT_SCHEMA, AUX_SCHEMA
  );
  if( errCnt && !forceFlag ){
    fossil_print(
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
**
** By default, only passwords are removed.  However, if the --verily option
** is added, then private branches, concealed email addresses, IP
** addresses of correspondents, and similar privacy-sensitive fields
** are also purged.  If the --private option is used, then only private
** branches are removed and all other information is left intact.
**
** This command permanently deletes the scrubbed information.  The effects
** of this command are irreversible.  Use with caution.
**
** The user is prompted to confirm the scrub unless the --force option
** is used.
**
** Options:
**   --force     do not prompt for confirmation
**   --private   only private branches are removed from the repository







|
|







752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
**
** By default, only passwords are removed.  However, if the --verily option
** is added, then private branches, concealed email addresses, IP
** addresses of correspondents, and similar privacy-sensitive fields
** are also purged.  If the --private option is used, then only private
** branches are removed and all other information is left intact.
**
** This command permanently deletes the scrubbed information. THE EFFECTS
** OF THIS COMMAND ARE IRREVERSIBLE. USE WITH CAUTION!
**
** The user is prompted to confirm the scrub unless the --force option
** is used.
**
** Options:
**   --force     do not prompt for confirmation
**   --private   only private branches are removed from the repository
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
    if( blob_str(&ans)[0]!='y' ){
      fossil_exit(1);
    }
  }
  db_begin_transaction();
  if( privateOnly || bVerily ){
    bNeedRebuild = db_exists("SELECT 1 FROM private");
    db_multi_exec(
      "DELETE FROM blob WHERE rid IN private;"
      "DELETE FROM delta WHERE rid IN private;"
      "DELETE FROM private;"
    );
  }
  if( !privateOnly ){
    db_multi_exec(
      "UPDATE user SET pw='';"
      "DELETE FROM config WHERE name GLOB 'last-sync-*';"
      "DELETE FROM config WHERE name GLOB 'peer-*';"
      "DELETE FROM config WHERE name GLOB 'login-group-*';"







<
<
<
|
<







791
792
793
794
795
796
797



798

799
800
801
802
803
804
805
    if( blob_str(&ans)[0]!='y' ){
      fossil_exit(1);
    }
  }
  db_begin_transaction();
  if( privateOnly || bVerily ){
    bNeedRebuild = db_exists("SELECT 1 FROM private");



    delete_private_content();

  }
  if( !privateOnly ){
    db_multi_exec(
      "UPDATE user SET pw='';"
      "DELETE FROM config WHERE name GLOB 'last-sync-*';"
      "DELETE FROM config WHERE name GLOB 'peer-*';"
      "DELETE FROM config WHERE name GLOB 'login-group-*';"
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
  db_initial_setup(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");

  rebuild_db(0, 1, 1);

  /* Reconstruct the private table.  The private table contains the rid
  ** of every manifest that is tagged with "private" and every file that
  ** is not used by a manifest that is not private.
  */
  db_multi_exec(
    "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);"
    "INSERT INTO private_ckin "
        " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;"
    "INSERT OR IGNORE INTO private"
        " SELECT fid FROM mlink"
        " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;"
    "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;"
    "DROP TABLE private_ckin;"
  );

  /* Skip the verify_before_commit() step on a reconstruct.  Most artifacts
  ** will have been changed and verification therefore takes a really, really
  ** long time.
  */
  verify_cancel();
  







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







901
902
903
904
905
906
907
908














909
910
911
912
913
914
915
  db_initial_setup(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");

  rebuild_db(0, 1, 1);
  reconstruct_private_table();















  /* Skip the verify_before_commit() step on a reconstruct.  Most artifacts
  ** will have been changed and verification therefore takes a really, really
  ** long time.
  */
  verify_cancel();
  
Changes to src/report.c.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**  
** Code to generate the ticket listings
*/
#include "config.h"
#include <time.h>
#include "report.h"
#include <assert.h>
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h"
#endif

/* Forward references to static routines */
static void report_format_hints(void);

/*
** WEBPAGE: /reportlist
*/







<
<
<







17
18
19
20
21
22
23



24
25
26
27
28
29
30
**  
** Code to generate the ticket listings
*/
#include "config.h"
#include <time.h>
#include "report.h"
#include <assert.h>




/* Forward references to static routines */
static void report_format_hints(void);

/*
** WEBPAGE: /reportlist
*/
1139
1140
1141
1142
1143
1144
1145
1146
  report_restrict_sql(&zErr1);
  sqlite3_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
  report_unrestrict_sql();
  if( zFilter ){
    free(zSql);
  }
}








<
1136
1137
1138
1139
1140
1141
1142

  report_restrict_sql(&zErr1);
  sqlite3_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
  report_unrestrict_sql();
  if( zFilter ){
    free(zSql);
  }
}

Changes to src/schema.c.
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
@   UNIQUE(pathname,vid)
@ );
@
@ -- This table holds a record of uncommitted merges in the local
@ -- file tree.  If a VFILE entry with id has merged with another
@ -- record, there is an entry in this table with (id,merge) where
@ -- merge is the RECORD table entry that the file merged against.
@ -- An id of 0 here means the version record itself.

@
@ CREATE TABLE vmerge(
@   id INTEGER REFERENCES vfile,      -- VFILE entry that has been merged
@   merge INTEGER,                    -- Merged with this record
@   UNIQUE(id, merge)
@ );
@   







|
>







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
@   UNIQUE(pathname,vid)
@ );
@
@ -- This table holds a record of uncommitted merges in the local
@ -- file tree.  If a VFILE entry with id has merged with another
@ -- record, there is an entry in this table with (id,merge) where
@ -- merge is the RECORD table entry that the file merged against.
@ -- An id of 0 here means the version record itself.  When id==(-1)
@ -- that is a cherrypick merge and id==(-2) is a backout merge.
@
@ CREATE TABLE vmerge(
@   id INTEGER REFERENCES vfile,      -- VFILE entry that has been merged
@   merge INTEGER,                    -- Merged with this record
@   UNIQUE(id, merge)
@ );
@   
Changes to src/setup.c.
71
72
73
74
75
76
77


78
79
80
81
82
83
84
  setup_menu_entry("Timeline", "setup_timeline",
    "Timeline display preferences");
  setup_menu_entry("Login-Group", "setup_login_group",
    "Manage single sign-on between this repository and others"
    " on the same server");
  setup_menu_entry("Tickets", "tktsetup",
    "Configure the trouble-ticketing system for this repository");


  setup_menu_entry("Skins", "setup_skin",
    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
    "Edit the Cascading Style Sheet used by all pages of this repository");
  setup_menu_entry("Header", "setup_header",
    "Edit HTML text inserted at the top of every page");
  setup_menu_entry("Footer", "setup_footer",







>
>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  setup_menu_entry("Timeline", "setup_timeline",
    "Timeline display preferences");
  setup_menu_entry("Login-Group", "setup_login_group",
    "Manage single sign-on between this repository and others"
    " on the same server");
  setup_menu_entry("Tickets", "tktsetup",
    "Configure the trouble-ticketing system for this repository");
  setup_menu_entry("Transfers", "xfersetup",
    "Configure the transfer system for this repository");
  setup_menu_entry("Skins", "setup_skin",
    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
    "Edit the Cascading Style Sheet used by all pages of this repository");
  setup_menu_entry("Header", "setup_header",
    "Edit HTML text inserted at the top of every page");
  setup_menu_entry("Footer", "setup_footer",
Changes to src/shell.c.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
# define readline(p) local_getline(p,stdin)
# define add_history(X)
# define read_history(X)
# define write_history(X)
# define stifle_history(X)
#endif

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







|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
# define readline(p) local_getline(p,stdin,0)
# define add_history(X)
# define read_history(X)
# define write_history(X)
# define stifle_history(X)
#endif

#if defined(_WIN32) || defined(WIN32)
330
331
332
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
*/
static char *local_getline(char *zPrompt, FILE *in){
  char *zLine;
  int nLine;
  int n;


  if( zPrompt && *zPrompt ){
    printf("%s",zPrompt);
    fflush(stdout);
  }
  nLine = 100;
  zLine = malloc( nLine );







|



>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
*/
static char *local_getline(char *zPrompt, FILE *in, int csvFlag){
  char *zLine;
  int nLine;
  int n;
  int inQuote = 0;

  if( zPrompt && *zPrompt ){
    printf("%s",zPrompt);
    fflush(stdout);
  }
  nLine = 100;
  zLine = malloc( nLine );
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
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
      break;
    }
    while( zLine[n] ){ n++; }



    if( n>0 && zLine[n-1]=='\n' ){
      n--;
      if( n>0 && zLine[n-1]=='\r' ) n--;
      zLine[n] = 0;
      break;
    }
  }
  zLine = realloc( zLine, n+1 );
  return zLine;
}

/*
** Retrieve a single line of input text.
**
** zPrior is a string of prior text retrieved.  If not the empty
** string, then issue a continuation prompt.
*/
static char *one_input_line(const char *zPrior, FILE *in){
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    return local_getline(0, in);
  }
  if( zPrior && zPrior[0] ){
    zPrompt = continuePrompt;
  }else{
    zPrompt = mainPrompt;
  }
  zResult = readline(zPrompt);







|
>
>
>
|




















|







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
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
      break;
    }
    while( zLine[n] ){
      if( zLine[n]=='"' ) inQuote = !inQuote;
      n++;
    }
    if( n>0 && zLine[n-1]=='\n' && (!inQuote || !csvFlag) ){
      n--;
      if( n>0 && zLine[n-1]=='\r' ) n--;
      zLine[n] = 0;
      break;
    }
  }
  zLine = realloc( zLine, n+1 );
  return zLine;
}

/*
** Retrieve a single line of input text.
**
** zPrior is a string of prior text retrieved.  If not the empty
** string, then issue a continuation prompt.
*/
static char *one_input_line(const char *zPrior, FILE *in){
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    return local_getline(0, in, 0);
  }
  if( zPrior && zPrior[0] ){
    zPrompt = continuePrompt;
  }else{
    zPrompt = mainPrompt;
  }
  zResult = readline(zPrompt);
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
  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 using ANSI-C rules.  Numbers
** appear outside of quotes.
*/
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;







|
<







614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
  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;
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
  }

  return zIn;
}


/*
** Execute a query statement that has a single result column.  Print

** that result column on a line by itself with a semicolon terminator.
**
** This is used, for example, to show the schema of the database by
** querying the SQLITE_MASTER table.



*/
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;



  rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
    p->nErr++;
    return rc;
  }
  rc = sqlite3_step(pSelect);

  while( rc==SQLITE_ROW ){
    if( zFirstRow ){
      fprintf(p->out, "%s", zFirstRow);
      zFirstRow = 0;
    }

    fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));










    rc = sqlite3_step(pSelect);
  }
  rc = sqlite3_finalize(pSelect);
  if( rc!=SQLITE_OK ){
    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
    p->nErr++;
  }







|
>
|

<
|
>
>
>








>
>
>







>





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







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
  }

  return zIn;
}


/*
** Execute a query statement that will generate SQL output.  Print
** the result columns, comma-separated, on a line and then add a
** semicolon terminator to the end of that line.
**

** 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;
  const char *z;
  rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
    p->nErr++;
    return rc;
  }
  rc = sqlite3_step(pSelect);
  nResult = sqlite3_column_count(pSelect);
  while( rc==SQLITE_ROW ){
    if( zFirstRow ){
      fprintf(p->out, "%s", zFirstRow);
      zFirstRow = 0;
    }
    z = (const char*)sqlite3_column_text(pSelect, 0);
    fprintf(p->out, "%s", z);
    for(i=1; i<nResult; i++){ 
      fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
    }
    if( z==0 ) z = "";
    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
    if( z[0] ){
      fprintf(p->out, "\n;\n");
    }else{
      fprintf(p->out, ";\n");
    }    
    rc = sqlite3_step(pSelect);
  }
  rc = sqlite3_finalize(pSelect);
  if( rc!=SQLITE_OK ){
    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
    p->nErr++;
  }
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

  if( strcmp(zType, "table")==0 ){
    sqlite3_stmt *pTableInfo = 0;
    char *zSelect = 0;
    char *zTableInfo = 0;
    char *zTmp = 0;
    int nRow = 0;

   
    zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
    zTableInfo = appendText(zTableInfo, zTable, '"');
    zTableInfo = appendText(zTableInfo, ");", 0);

    rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
    free(zTableInfo);
    if( rc!=SQLITE_OK || !pTableInfo ){
      return 1;
    }

    zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);





    zTmp = appendText(zTmp, zTable, '"');
    if( zTmp ){
      zSelect = appendText(zSelect, zTmp, '\'');
    }
    zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
    rc = sqlite3_step(pTableInfo);
    while( rc==SQLITE_ROW ){
      const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
      zSelect = appendText(zSelect, "quote(", 0);
      zSelect = appendText(zSelect, zText, '"');
      rc = sqlite3_step(pTableInfo);
      if( rc==SQLITE_ROW ){
        zSelect = appendText(zSelect, ") || ',' || ", 0);
      }else{
        zSelect = appendText(zSelect, ") ", 0);
      }
      nRow++;
    }
    rc = sqlite3_finalize(pTableInfo);
    if( rc!=SQLITE_OK || nRow==0 ){







>












>
>
>
>
>
|











|







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

  if( strcmp(zType, "table")==0 ){
    sqlite3_stmt *pTableInfo = 0;
    char *zSelect = 0;
    char *zTableInfo = 0;
    char *zTmp = 0;
    int nRow = 0;
    int kk;
   
    zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
    zTableInfo = appendText(zTableInfo, zTable, '"');
    zTableInfo = appendText(zTableInfo, ");", 0);

    rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
    free(zTableInfo);
    if( rc!=SQLITE_OK || !pTableInfo ){
      return 1;
    }

    zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
    if( !isalpha(zTable[0]) ){
      kk = 0;
    }else{
      for(kk=1; isalnum(zTable[kk]); kk++){}
    }
    zTmp = appendText(zTmp, zTable, zTable[kk] ? '"' : 0);
    if( zTmp ){
      zSelect = appendText(zSelect, zTmp, '\'');
    }
    zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
    rc = sqlite3_step(pTableInfo);
    while( rc==SQLITE_ROW ){
      const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
      zSelect = appendText(zSelect, "quote(", 0);
      zSelect = appendText(zSelect, zText, '"');
      rc = sqlite3_step(pTableInfo);
      if( rc==SQLITE_ROW ){
        zSelect = appendText(zSelect, "), ", 0);
      }else{
        zSelect = appendText(zSelect, ") ", 0);
      }
      nRow++;
    }
    rc = sqlite3_finalize(pTableInfo);
    if( rc!=SQLITE_OK || nRow==0 ){
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
      fprintf(stderr, "Error: out of memory\n");
      fclose(in);
      sqlite3_finalize(pStmt);
      return 1;
    }
    sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in))!=0 ){
      char *z;

      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){


        if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
          *z = 0;
          i++;
          if( i<nCol ){
            azCol[i] = &z[nSep];
            z += nSep-1;
          }
        }
      } /* end for */
      *z = 0;
      if( i+1!=nCol ){
        fprintf(stderr,
                "Error: %s line %d: expected %d columns of data but found %d\n",
                zFile, lineno, nCol, i+1);
        zCommit = "ROLLBACK";
        free(zLine);
        rc = 1;
        break; /* from while */
      }
      for(i=0; i<nCol; i++){








        sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
      }
      sqlite3_step(pStmt);
      rc = sqlite3_reset(pStmt);
      free(zLine);
      if( rc!=SQLITE_OK ){
        fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));







|
|
>


|
>
>
|



















>
>
>
>
>
>
>
>







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
      fprintf(stderr, "Error: out of memory\n");
      fclose(in);
      sqlite3_finalize(pStmt);
      return 1;
    }
    sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in, 1))!=0 ){
      char *z, c;
      int inQuote = 0;
      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; (c = *z)!=0; z++){
        if( c=='"' ) inQuote = !inQuote;
        if( c=='\n' ) lineno++;
        if( !inQuote && c==p->separator[0] && strncmp(z,p->separator,nSep)==0 ){
          *z = 0;
          i++;
          if( i<nCol ){
            azCol[i] = &z[nSep];
            z += nSep-1;
          }
        }
      } /* end for */
      *z = 0;
      if( i+1!=nCol ){
        fprintf(stderr,
                "Error: %s line %d: expected %d columns of data but found %d\n",
                zFile, lineno, nCol, i+1);
        zCommit = "ROLLBACK";
        free(zLine);
        rc = 1;
        break; /* from while */
      }
      for(i=0; i<nCol; i++){
        if( azCol[i][0]=='"' ){
          int k;
          for(z=azCol[i], j=1, k=0; z[j]; j++){
            if( z[j]=='"' ){ j++; if( z[j]==0 ) break; }
            z[k++] = z[j];
          }
          z[k] = 0;
        }
        sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
      }
      sqlite3_step(pStmt);
      rc = sqlite3_reset(pStmt);
      free(zLine);
      if( rc!=SQLITE_OK ){
        fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
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
  return rc;
}

/*
** Show available command line options
*/
static const char zOptions[] = 
  "   -help                show this message\n"
  "   -init filename       read/process named file\n"
  "   -echo                print commands before execution\n"
  "   -[no]header          turn headers on or off\n"
  "   -bail                stop after hitting an error\n"
  "   -interactive         force interactive I/O\n"
  "   -batch               force batch I/O\n"
  "   -column              set output mode to 'column'\n"

  "   -csv                 set output mode to 'csv'\n"




  "   -html                set output mode to HTML\n"

  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"




  "   -separator 'x'       set output field separator (|)\n"
  "   -stats               print memory stats before each finalize\n"
  "   -nullvalue 'text'    set text string for NULL values\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
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
;
static void usage(int showDetail){
  fprintf(stderr,
      "Usage: %s [OPTIONS] FILENAME [SQL]\n"  
      "FILENAME is the name of an SQLite database. A new database is created\n"
      "if the file does not previously exist.\n", Argv0);
  if( showDetail ){







<
<
<
<

<


>

>
>
>
>

>


>
>
>
>


<





<
<
<







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
  return rc;
}

/*
** Show available command line options
*/
static const char zOptions[] = 




  "   -bail                stop after hitting an error\n"

  "   -batch               force batch I/O\n"
  "   -column              set output mode to 'column'\n"
  "   -cmd command         run \"command\" before reading stdin\n"
  "   -csv                 set output mode to 'csv'\n"
  "   -echo                print commands before execution\n"
  "   -init filename       read/process named file\n"
  "   -[no]header          turn headers on or off\n"
  "   -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"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -nullvalue 'text'    set text string for NULL values\n"
  "   -separator 'x'       set output field separator (|)\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



;
static void usage(int showDetail){
  fprintf(stderr,
      "Usage: %s [OPTIONS] FILENAME [SQL]\n"  
      "FILENAME is the name of an SQLite database. A new database is created\n"
      "if the file does not previously exist.\n", Argv0);
  if( showDetail ){
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
  ** the size of the alternative malloc heap,
  ** and the first command to execute.
  */
  for(i=1; i<argc-1; i++){
    char *z;
    if( argv[i][0]!='-' ) break;
    z = argv[i];
    if( z[0]=='-' && z[1]=='-' ) z++;

    if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){


      i++;
    }else if( strcmp(argv[i],"-init")==0 ){
      i++;
      zInitFile = argv[i];
    /* Need to check for batch mode here to so we can avoid printing
    ** informational messages (like from process_sqliterc) before 
    ** we do the actual processing of arguments later in a second pass.
    */
    }else if( strcmp(argv[i],"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(argv[i],"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      int j, c;
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = argv[++i];
      szHeap = atoi(zSize);
      for(j=0; (c = zSize[j])!=0; j++){
        if( c=='M' ){ szHeap *= 1000000; break; }
        if( c=='K' ){ szHeap *= 1000; break; }
        if( c=='G' ){ szHeap *= 1000000000; break; }
      }
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(argv[i],"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
         int (*xOut)(const char*,void*),
         void *pOutArg,
         int makeDefault
      );
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(argv[i],"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( strcmp(argv[i],"-vfs")==0 ){
      sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
      if( pVfs ){
        sqlite3_vfs_register(pVfs, 1);
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
      }







|
>
|
>
>

|






|

|
















|










|



|







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
  ** the size of the alternative malloc heap,
  ** and the first command to execute.
  */
  for(i=1; i<argc-1; i++){
    char *z;
    if( argv[i][0]!='-' ) break;
    z = argv[i];
    if( z[1]=='-' ) z++;
    if( strcmp(z,"-separator")==0
     || strcmp(z,"-nullvalue")==0
     || strcmp(z,"-cmd")==0
    ){
      i++;
    }else if( strcmp(z,"-init")==0 ){
      i++;
      zInitFile = argv[i];
    /* Need to check for batch mode here to so we can avoid printing
    ** informational messages (like from process_sqliterc) before 
    ** we do the actual processing of arguments later in a second pass.
    */
    }else if( strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      int j, c;
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = argv[++i];
      szHeap = atoi(zSize);
      for(j=0; (c = zSize[j])!=0; j++){
        if( c=='M' ){ szHeap *= 1000000; break; }
        if( c=='K' ){ szHeap *= 1000; break; }
        if( c=='G' ){ szHeap *= 1000000000; break; }
      }
      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,
         int makeDefault
      );
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( strcmp(z,"-vfs")==0 ){
      sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
      if( pVfs ){
        sqlite3_vfs_register(pVfs, 1);
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
      }
2879
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890
2891
2892
2893
2894
2895

2896
2897
2898
2899
2900
2901
2902
      data.mode = MODE_Column;
    }else if( strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.separator,",",2);
    }else if( strcmp(z,"-separator")==0 ){
      i++;
      if(i>=argc){
        fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);

        fprintf(stderr,"Use -help for a list of options.\n");
        return 1;
      }
      sqlite3_snprintf(sizeof(data.separator), data.separator,
                       "%.*s",(int)sizeof(data.separator)-1,argv[i]);
    }else if( strcmp(z,"-nullvalue")==0 ){
      i++;
      if(i>=argc){
        fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);

        fprintf(stderr,"Use -help for a list of options.\n");
        return 1;
      }
      sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
                       "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
    }else if( strcmp(z,"-header")==0 ){
      data.showHeader = 1;







|
>








|
>







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
      data.mode = MODE_Column;
    }else if( strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.separator,",",2);
    }else if( strcmp(z,"-separator")==0 ){
      i++;
      if(i>=argc){
        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
                        Argv0, z);
        fprintf(stderr,"Use -help for a list of options.\n");
        return 1;
      }
      sqlite3_snprintf(sizeof(data.separator), data.separator,
                       "%.*s",(int)sizeof(data.separator)-1,argv[i]);
    }else if( strcmp(z,"-nullvalue")==0 ){
      i++;
      if(i>=argc){
        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
                        Argv0, z);
        fprintf(stderr,"Use -help for a list of options.\n");
        return 1;
      }
      sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
                       "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
    }else if( strcmp(z,"-header")==0 ){
      data.showHeader = 1;
2923
2924
2925
2926
2927
2928
2929
2930
2931


















2932
2933
2934
2935
2936
2937
2938
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
      i++;
#endif
    }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
      usage(1);


















    }else{
      fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
      fprintf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
  }








|

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







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
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
      i++;
#endif
    }else if( strcmp(z,"-help")==0 ){
      usage(1);
    }else if( strcmp(z,"-cmd")==0 ){
      if( i==argc-1 ) break;
      i++;
      z = argv[i];
      if( z[0]=='.' ){
        rc = do_meta_command(z, &data);
        if( rc && bail_on_error ) return rc;
      }else{
        open_db(&data);
        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
        if( zErrMsg!=0 ){
          fprintf(stderr,"Error: %s\n", zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
          fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
          if( bail_on_error ) return rc;
        }
      }
    }else{
      fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
      fprintf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
  }

Changes to src/skins.c.
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
@ }
@ 
@ /* The label/value pairs on (for example) the vinfo page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   color: white;
@   background-color: rgb(20, 20, 20);
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(230, 230, 230);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(200, 200, 200);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(220, 220, 220);
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"







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







151
152
153
154
155
156
157













































158
159
160
161
162
163
164
@ }
@ 
@ /* The label/value pairs on (for example) the vinfo page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;













































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
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
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: #ffffc5;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: #a09048;
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(210, 210, 100);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(190, 200, 110);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(200, 210, 120);
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"







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







353
354
355
356
357
358
359












































360
361
362
363
364
365
366
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;












































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
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
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 6pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.meta {
@   color: white;
@   background-color: black;
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: white;
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: white;
@   text-decoration: line-through;
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: white;
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"







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







589
590
591
592
593
594
595














































596
597
598
599
600
601
602
@ }
@ 
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;














































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
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
@ 
@ table.report tr td {
@   padding: 3px 5px;
@ }
@ 
@ textarea {
@   font-size: 1em;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 6pt;
@   border-collapse:collapse;
@   width: 98%;
@   border: 1px #000 dashed;
@   margin-left: auto;
@   margin-right: auto;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@   vertical-align: top;
@   white-space: pre-wrap;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@   /* border-bottom: 1px solid rgb(220, 220, 220); */
@ }
@
@ table.sbsdiff tr td.srcline {
@   /* max-width: 400px; */
@   /* Note: May partially hide long lines without whitespaces */
@   /* overflow: hidden; */
@   /* border-bottom: 1px solid rgb(220, 220, 220); */
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: rgb(170, 160, 255);
@   padding-top: 0.25em;
@   padding-bottom: 0.25em;
@   text-align: center;
@   -moz-border-radius: 5px;
@   -moz-border-radius: 5px;
@   -webkit-border-radius: 5px;
@   -webkit-border-radius: 5px;
@   -border-radius: 5px;
@   -border-radius: 5px;
@   border-radius: 5px;
@   border-radius: 5px;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(180, 250, 180);
@   /* border-bottom: 1px solid rgb(160, 230, 160); */
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(250, 130, 130);
@   /* border-bottom: 1px solid rgb(230, 110, 110); */
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(210, 210, 200);
@   /* border-bottom: 1px solid rgb(190, 190, 180); */
@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"







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







887
888
889
890
891
892
893



































































894
895
896
897
898
899
900
@ 
@ table.report tr td {
@   padding: 3px 5px;
@ }
@ 
@ textarea {
@   font-size: 1em;



































































@ }');
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
@ <head>
@ <title>$<project_name>: $<title></title>
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@       href="$home/timeline.rss">
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
Changes to src/sqlcmd.c.
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  pOut[2] = nIn>>8 & 0xff;
  pOut[3] = nIn & 0xff;
  compress(&pOut[4], &nOut, pIn, nIn);
  sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
}

/*
** Implementation of the "uncontent(X)" SQL function.  The argument X
** is a blob which was obtained from compress(Y).  The output will be
** the value Y.
*/
static void sqlcmd_decompress(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  pOut[2] = nIn>>8 & 0xff;
  pOut[3] = nIn & 0xff;
  compress(&pOut[4], &nOut, pIn, nIn);
  sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
}

/*
** Implementation of the "decompress(X)" SQL function.  The argument X
** is a blob which was obtained from compress(Y).  The output will be
** the value Y.
*/
static void sqlcmd_decompress(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
Changes to src/sqlite3.c.
1
2
3
4
5
6
7
8
9
10
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.7.10.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other


|







1
2
3
4
5
6
7
8
9
10
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.7.11.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
** 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.7.10"
#define SQLITE_VERSION_NUMBER 3007010
#define SQLITE_SOURCE_ID      "2012-01-11 16:16:08 9e31a275ef494ea8713a1d60a15b84157e57c3ff"

/*
** 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







|
|
|







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
** 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.7.11"
#define SQLITE_VERSION_NUMBER 3007011
#define SQLITE_SOURCE_ID      "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"

/*
** 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
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
/*
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** If F is the filename pointer passed into the xOpen() method of a VFS


** implementation and P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The value of P is true if it is "yes" or "true" or "on" or 




** a non-zero number and is false otherwise.  If P is not a query parameter

** on F then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
** 
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a pathname pointer that SQLite passed into the xOpen VFS method,
** then the behavior of this routine is undefined and probably undesirable.

*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);


/*







|
>
>
|








|
>
>
>
>
|
>
|








|
|
>







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
/*
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** If F is the database filename pointer passed into the xOpen() method of 
** a VFS implementation when the flags parameter to xOpen() has one or 
** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
** value of query parameter P is one of "yes", "true", or "on" in any
** case or if the value begins with a non-zero number.  The 
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero.  If P is not a query
** parameter on F or if the value of P is does not match any of the
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
** 
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);


/*
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
** handle invalid, and will not use it with any other sqlite3_pcache_methods2
** functions.
**
** [[the xShrink() page cache method]]
** ^SQLite invokes the xShrink() method when it wants the page cache to
** free up as much of heap memory as possible.  The page cache implementation
** is not obligated to free any memory, but well-behaved implementions should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
  int iVersion;
  void *pArg;
  int (*xInit)(void*);







|







6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
** handle invalid, and will not use it with any other sqlite3_pcache_methods2
** functions.
**
** [[the xShrink() page cache method]]
** ^SQLite invokes the xShrink() method when it wants the page cache to
** free up as much of heap memory as possible.  The page cache implementation
** is not obligated to free any memory, but well-behaved implementations should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
  int iVersion;
  void *pArg;
  int (*xInit)(void*);
8008
8009
8010
8011
8012
8013
8014




8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))

/*
** The following value as a destructor means to use sqlite3DbFree().




** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT.
*/
#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3DbFree)

/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
** not support Writable Static Data (WSD) such as global and static variables.
** All variables must either be on the stack or dynamically allocated from
** the heap.  When WSD is unsupported, the variable declarations scattered
** throughout the SQLite code must become constants instead.  The SQLITE_WSD







>
>
>
>
|

|







8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))

/*
** The following value as a destructor means to use sqlite3DbFree().
** The sqlite3DbFree() routine requires two parameters instead of the 
** one parameter that destructors normally want.  So we have to introduce 
** this magic value that the code knows to handle differently.  Any 
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3MallocSize)

/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
** not support Writable Static Data (WSD) such as global and static variables.
** All variables must either be on the stack or dynamically allocated from
** the heap.  When WSD is unsupported, the variable declarations scattered
** throughout the SQLite code must become constants instead.  The SQLITE_WSD
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
**
** NOTE:  These values must match the corresponding PAGER_ values in
** pager.h.
*/
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
#define BTREE_MEMORY        4  /* This is an in-memory DB */
#define BTREE_SINGLE        8  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED    16  /* Use of a hash implementation is OK */

SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);







<
|
|
|







8182
8183
8184
8185
8186
8187
8188

8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
**
** NOTE:  These values must match the corresponding PAGER_ values in
** pager.h.
*/
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */

#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861

/*
** Allowed values for the flags parameter to sqlite3PagerOpen().
**
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
#define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
#define PAGER_MEMORY        0x0004    /* In-memory database */

/*
** Valid values for the second argument to sqlite3PagerLockingMode().
*/
#define PAGER_LOCKINGMODE_QUERY      -1
#define PAGER_LOCKINGMODE_NORMAL      0
#define PAGER_LOCKINGMODE_EXCLUSIVE   1







<
|







8857
8858
8859
8860
8861
8862
8863

8864
8865
8866
8867
8868
8869
8870
8871

/*
** Allowed values for the flags parameter to sqlite3PagerOpen().
**
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */

#define PAGER_MEMORY        0x0002    /* In-memory database */

/*
** Valid values for the second argument to sqlite3PagerLockingMode().
*/
#define PAGER_LOCKINGMODE_QUERY      -1
#define PAGER_LOCKINGMODE_NORMAL      0
#define PAGER_LOCKINGMODE_EXCLUSIVE   1
9004
9005
9006
9007
9008
9009
9010
9011
9012

9013
9014
9015
9016
9017
9018
9019
** structure.
*/
struct PgHdr {
  sqlite3_pcache_page *pPage;    /* Pcache object page handle */
  void *pData;                   /* Page data */
  void *pExtra;                  /* Extra content */
  PgHdr *pDirty;                 /* Transient list of dirty pages */
  Pgno pgno;                     /* Page number for this page */
  Pager *pPager;                 /* The pager this page is part of */

#ifdef SQLITE_CHECK_PAGES
  u32 pageHash;                  /* Hash of page content */
#endif
  u16 flags;                     /* PGHDR flags defined below */

  /**********************************************************************
  ** Elements above are public.  All that follows is private to pcache.c







<

>







9014
9015
9016
9017
9018
9019
9020

9021
9022
9023
9024
9025
9026
9027
9028
9029
** structure.
*/
struct PgHdr {
  sqlite3_pcache_page *pPage;    /* Pcache object page handle */
  void *pData;                   /* Page data */
  void *pExtra;                  /* Extra content */
  PgHdr *pDirty;                 /* Transient list of dirty pages */

  Pager *pPager;                 /* The pager this page is part of */
  Pgno pgno;                     /* Page number for this page */
#ifdef SQLITE_CHECK_PAGES
  u32 pageHash;                  /* Hash of page content */
#endif
  u16 flags;                     /* PGHDR flags defined below */

  /**********************************************************************
  ** Elements above are public.  All that follows is private to pcache.c
9233
9234
9235
9236
9237
9238
9239
9240



9241
9242
9243
9244









9245
9246
9247
9248
9249
9250
9251
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif

/*
** Determine if we are dealing with Windows NT.
*/



#if defined(_WIN32_WINNT)
# define SQLITE_OS_WINNT 1
#else
# define SQLITE_OS_WINNT 0









#endif

/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
#if defined(_WIN32_WCE)







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







9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif

/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for win98 or winNT
** using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
** so the above test does not work.  We'll just assume that everything is
** winNT unless the programmer explicitly says otherwise by setting
** SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif

/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
#if defined(_WIN32_WCE)
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668


9669

9670

9671
9672
9673
9674
9675
9676
9677
9678
9679
9680

9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692

9693
9694
9695
9696
9697
9698
9699
9700
9701


9702
9703
9704
9705
9706
9707
9708
*/
struct FuncDefHash {
  FuncDef *a[23];       /* Hash table for functions */
};

/*
** Each database connection is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
** insert statement.  Inserts on views do not affect its value.  Each
** trigger has its own context, so that lastRowid can be updated inside
** triggers as usual.  The previous value will be restored once the trigger
** exits.  Upon entering a before or instead of trigger, lastRowid is no
** longer (since after version 2.8.12) reset to -1.
**
** The sqlite.nChange does not count changes within triggers and keeps no
** context.  It is reset at start of sqlite3_exec.
** The sqlite.lsChange represents the number of changes made by the last
** insert, update, or delete statement.  It remains constant throughout the
** length of a statement and is then updated by OP_SetCounts.  It keeps a
** context stack just like lastRowid so that the count of changes
** within a trigger is not seen outside the trigger.  Changes to views do not
** affect the value of lsChange.
** The sqlite.csChange keeps track of the number of current changes (since
** the last statement) and is used to update sqlite_lsChange.
**
** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16
** store the most recent error code and, if applicable, string. The
** internal function sqlite3Error() is used to set these variables
** consistently.
*/
struct sqlite3 {
  sqlite3_vfs *pVfs;            /* OS Interface */
  int nDb;                      /* Number of backends currently in use */


  Db *aDb;                      /* All backends */

  int flags;                    /* Miscellaneous flags. See below */

  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */

  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  int nTable;                   /* Number of tables in the database */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  u32 magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Value returned by sqlite3_changes() */
  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  sqlite3_mutex *mutex;         /* Connection mutex */
  int aLimit[SQLITE_N_LIMIT];   /* Limits */
  struct sqlite3InitInfo {      /* Information used during initialization */
    int iDb;                    /* When back is being initialized */
    int newTnum;                /* Rootpage of table being initialized */

    u8 busy;                    /* TRUE if currently initializing */
    u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
  } init;
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared library handles */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of VDBEs currently executing */
  int writeVdbeCnt;             /* Number of active VDBEs that are writing */
  int vdbeExecCnt;              /* Number of nested calls to VdbeExec() */


  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   







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



|
>
>

>

>










>

<
<
<



<


<

>



<
<
<



>
>







9657
9658
9659
9660
9661
9662
9663























9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685



9686
9687
9688

9689
9690

9691
9692
9693
9694
9695



9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
*/
struct FuncDefHash {
  FuncDef *a[23];       /* Hash table for functions */
};

/*
** Each database connection is an instance of the following structure.























*/
struct sqlite3 {
  sqlite3_vfs *pVfs;            /* OS Interface */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  sqlite3_mutex *mutex;         /* Connection mutex */
  Db *aDb;                      /* All backends */
  int nDb;                      /* Number of backends currently in use */
  int flags;                    /* Miscellaneous flags. See below */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */



  u32 magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Value returned by sqlite3_changes() */
  int nTotalChange;             /* Value returned by sqlite3_total_changes() */

  int aLimit[SQLITE_N_LIMIT];   /* Limits */
  struct sqlite3InitInfo {      /* Information used during initialization */

    int newTnum;                /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
  } init;



  int activeVdbeCnt;            /* Number of VDBEs currently executing */
  int writeVdbeCnt;             /* Number of active VDBEs that are writing */
  int vdbeExecCnt;              /* Number of nested calls to VdbeExec() */
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared library handles */
  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   
9731
9732
9733
9734
9735
9736
9737

9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749

9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE

  Hash aModule;                 /* populated by sqlite3_create_module() */
  VtabCtx *pVtabCtx;            /* Context for active vtab connect/create */
  VTable **aVTrans;             /* Virtual tables with open transactions */
  int nVTrans;                  /* Allocated size of aVTrans */
  VTable *pDisconnect;    /* Disconnect these in next sqlite3_prepare() */
#endif
  FuncDefHash aFunc;            /* Hash table of connection functions */
  Hash aCollSeq;                /* All collating sequences */
  BusyHandler busyHandler;      /* Busy callback */
  int busyTimeout;              /* Busy handler timeout, in msec */
  Db aDbStatic[2];              /* Static space for the 2 default backends */
  Savepoint *pSavepoint;        /* List of active savepoints */

  int nSavepoint;               /* Number of non-transaction savepoints */
  int nStatement;               /* Number of nested statement-transactions  */
  u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  i64 nDeferredCons;            /* Net deferred constraints this transaction. */
  int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */

#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  /* The following variables are all protected by the STATIC_MASTER 
  ** mutex, not by sqlite3.mutex. They are used by code in notify.c. 
  **







>



<





<


>


<







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
9755
9756
9757
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int nVTrans;                  /* Allocated size of aVTrans */
  Hash aModule;                 /* populated by sqlite3_create_module() */
  VtabCtx *pVtabCtx;            /* Context for active vtab connect/create */
  VTable **aVTrans;             /* Virtual tables with open transactions */

  VTable *pDisconnect;    /* Disconnect these in next sqlite3_prepare() */
#endif
  FuncDefHash aFunc;            /* Hash table of connection functions */
  Hash aCollSeq;                /* All collating sequences */
  BusyHandler busyHandler;      /* Busy callback */

  Db aDbStatic[2];              /* Static space for the 2 default backends */
  Savepoint *pSavepoint;        /* List of active savepoints */
  int busyTimeout;              /* Busy handler timeout, in msec */
  int nSavepoint;               /* Number of non-transaction savepoints */
  int nStatement;               /* Number of nested statement-transactions  */

  i64 nDeferredCons;            /* Net deferred constraints this transaction. */
  int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */

#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  /* The following variables are all protected by the STATIC_MASTER 
  ** mutex, not by sqlite3.mutex. They are used by code in notify.c. 
  **
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00002000  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_SqlTrace       0x00004000  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00008000  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00010000  /* OK to update SQLITE_MASTER */
#define SQLITE_NoReadlock     0x00020000  /* Readlocks are omitted when 
                                          ** accessing read-only databases */
#define SQLITE_IgnoreChecks   0x00040000  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0080000  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00100000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00200000  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00400000  /* Use full fsync for checkpoint */
#define SQLITE_RecoveryMode   0x00800000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x01000000  /* Reverse unordered SELECTs */







|
<







9786
9787
9788
9789
9790
9791
9792
9793

9794
9795
9796
9797
9798
9799
9800
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00002000  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_SqlTrace       0x00004000  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00008000  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00010000  /* OK to update SQLITE_MASTER */
                         /*   0x00020000  Unused */

#define SQLITE_IgnoreChecks   0x00040000  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0080000  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00100000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00200000  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00400000  /* Use full fsync for checkpoint */
#define SQLITE_RecoveryMode   0x00800000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x01000000  /* Reverse unordered SELECTs */
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
/*
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE     0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE     0x02 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM    0x04 /* Ephemeral.  Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
#define SQLITE_FUNC_PRIVATE  0x10 /* Allowed for internal use only */
#define SQLITE_FUNC_COUNT    0x20 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */

/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the initializers for the FuncDef structures.
**







<







9875
9876
9877
9878
9879
9880
9881

9882
9883
9884
9885
9886
9887
9888
/*
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE     0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE     0x02 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM    0x04 /* Ephemeral.  Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */

#define SQLITE_FUNC_COUNT    0x20 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */

/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the initializers for the FuncDef structures.
**
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
** Allowed values for Tabe.tabFlags.
*/
#define TF_Readonly        0x01    /* Read-only system table */
#define TF_Ephemeral       0x02    /* An ephemeral table */
#define TF_HasPrimaryKey   0x04    /* Table has a primary key */
#define TF_Autoincrement   0x08    /* Integer primary key is autoincrement */
#define TF_Virtual         0x10    /* Is a virtual table */
#define TF_NeedMetadata    0x20    /* aCol[].zType and aCol[].pColl missing */



/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/







<
<







10157
10158
10159
10160
10161
10162
10163


10164
10165
10166
10167
10168
10169
10170
** Allowed values for Tabe.tabFlags.
*/
#define TF_Readonly        0x01    /* Read-only system table */
#define TF_Ephemeral       0x02    /* An ephemeral table */
#define TF_HasPrimaryKey   0x04    /* Table has a primary key */
#define TF_Autoincrement   0x08    /* Integer primary key is autoincrement */
#define TF_Virtual         0x10    /* Is a virtual table */




/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
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
** it means this is not a unique index.  Otherwise it is a unique index
** and the value of Index.onError indicate the which conflict resolution 
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
struct Index {
  char *zName;     /* Name of this index */
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  u8 bUnordered;   /* Use this index for == or IN queries only */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */





#ifdef SQLITE_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};








<



<
<
<
<





>
>
>
>
>







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
** it means this is not a unique index.  Otherwise it is a unique index
** and the value of Index.onError indicate the which conflict resolution 
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
struct Index {
  char *zName;     /* Name of this index */

  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */




  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */
  int nColumn;     /* Number of columns in the table used by this index */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  u8 bUnordered;   /* Use this index for == or IN queries only */
#ifdef SQLITE_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

10395
10396
10397
10398
10399
10400
10401
10402
10403

10404
10405
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
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */
  int sortingIdxPTab;     /* Cursor number of pseudo-table */
  ExprList *pGroupBy;     /* The group by clause */
  int nSortingColumn;     /* Number of columns in the sorting index */

  struct AggInfo_col {    /* For each column used in source tables */
    Table *pTab;             /* Source table */
    int iTable;              /* Cursor number of the source table */
    int iColumn;             /* Column number within the source table */
    int iSorterColumn;       /* Column number in the sorting index */
    int iMem;                /* Memory location that acts as accumulator */
    Expr *pExpr;             /* The original expression */
  } *aCol;
  int nColumn;            /* Number of used entries in aCol[] */
  int nColumnAlloc;       /* Number of slots allocated for aCol[] */
  int nAccumulator;       /* Number of columns that show through to the output.
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pExpr;             /* Expression encoding the function */
    FuncDef *pFunc;          /* The aggregate function implementation */
    int iMem;                /* Memory location that acts as accumulator */
    int iDistinct;           /* Ephemeral table used to enforce DISTINCT */
  } *aFunc;
  int nFunc;              /* Number of entries in aFunc[] */
  int nFuncAlloc;         /* Number of slots allocated for aFunc[] */
};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits.  But if SQLITE_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit.  16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user







<

>









<










<







10389
10390
10391
10392
10393
10394
10395

10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406

10407
10408
10409
10410
10411
10412
10413
10414
10415
10416

10417
10418
10419
10420
10421
10422
10423
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */
  int sortingIdxPTab;     /* Cursor number of pseudo-table */

  int nSortingColumn;     /* Number of columns in the sorting index */
  ExprList *pGroupBy;     /* The group by clause */
  struct AggInfo_col {    /* For each column used in source tables */
    Table *pTab;             /* Source table */
    int iTable;              /* Cursor number of the source table */
    int iColumn;             /* Column number within the source table */
    int iSorterColumn;       /* Column number in the sorting index */
    int iMem;                /* Memory location that acts as accumulator */
    Expr *pExpr;             /* The original expression */
  } *aCol;
  int nColumn;            /* Number of used entries in aCol[] */

  int nAccumulator;       /* Number of columns that show through to the output.
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pExpr;             /* Expression encoding the function */
    FuncDef *pFunc;          /* The aggregate function implementation */
    int iMem;                /* Memory location that acts as accumulator */
    int iDistinct;           /* Ephemeral table used to enforce DISTINCT */
  } *aFunc;
  int nFunc;              /* Number of entries in aFunc[] */

};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits.  But if SQLITE_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit.  16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637
10638
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int nAlloc;            /* Number of entries allocated below */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item {
    Expr *pExpr;           /* The list of expressions */
    char *zName;           /* Token associated with this expression */
    char *zSpan;           /* Original text of the expression */
    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
    u8 done;               /* A flag to indicate when processing is finished */
    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
  } *a;                  /* One entry for each expression */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.
*/







<

|







|







10606
10607
10608
10609
10610
10611
10612

10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */

  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;           /* The list of expressions */
    char *zName;           /* Token associated with this expression */
    char *zSpan;           /* Original text of the expression */
    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
    u8 done;               /* A flag to indicate when processing is finished */
    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
  } *a;                  /* Alloc a power of two greater or equal to nExpr */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.
*/
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
*/
struct IdList {
  struct IdList_item {
    char *zName;      /* Name of the identifier */
    int idx;          /* Index in some Table.aCol[] of a column named zName */
  } *a;
  int nId;         /* Number of identifiers on the list */
  int nAlloc;      /* Number of entries allocated for a[] below */
};

/*
** The bitmask datatype defined below is used for various optimizations.
**
** Changing this from a 64-bit to a 32-bit type limits the number of
** tables in a join to 32 instead of 64.  But it also reduces the size







<







10650
10651
10652
10653
10654
10655
10656

10657
10658
10659
10660
10661
10662
10663
*/
struct IdList {
  struct IdList_item {
    char *zName;      /* Name of the identifier */
    int idx;          /* Index in some Table.aCol[] of a column named zName */
  } *a;
  int nId;         /* Number of identifiers on the list */

};

/*
** The bitmask datatype defined below is used for various optimizations.
**
** Changing this from a 64-bit to a 32-bit type limits the number of
** tables in a join to 32 instead of 64.  But it also reduces the size
10903
10904
10905
10906
10907
10908
10909



10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935

10936
10937
10938
10939
10940
10941
10942
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  char affinity;         /* MakeRecord with this affinity for SRT_Set */
  u16 selFlags;          /* Various SF_* values */



  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  Select *pNext;         /* Next select to the left in a compound */
  Select *pRightmost;    /* Right-most select in a compound select statement */
  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
  Expr *pOffset;         /* OFFSET expression. NULL means not used. */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
  double nSelectRow;     /* Estimated number of result rows */
};

/*
** Allowed values for Select.selFlags.  The "SF" prefix stands for
** "Select Flag".
*/
#define SF_Distinct        0x01  /* Output should be DISTINCT */
#define SF_Resolved        0x02  /* Identifiers have been resolved */
#define SF_Aggregate       0x04  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x10  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x40  /* Sort using a sorter */



/*
** The results of a select can be distributed in several ways.  The
** "SRT" prefix means "SELECT Result Type".
*/
#define SRT_Union        1  /* Store result as keys in an index */







>
>
>










<
<
<













>







10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912



10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  char affinity;         /* MakeRecord with this affinity for SRT_Set */
  u16 selFlags;          /* Various SF_* values */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
  double nSelectRow;     /* Estimated number of result rows */
  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  Select *pNext;         /* Next select to the left in a compound */
  Select *pRightmost;    /* Right-most select in a compound select statement */
  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
  Expr *pOffset;         /* OFFSET expression. NULL means not used. */



};

/*
** Allowed values for Select.selFlags.  The "SF" prefix stands for
** "Select Flag".
*/
#define SF_Distinct        0x01  /* Output should be DISTINCT */
#define SF_Resolved        0x02  /* Identifiers have been resolved */
#define SF_Aggregate       0x04  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x10  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x40  /* Sort using a sorter */
#define SF_Values          0x80  /* Synthesized from VALUES clause */


/*
** The results of a select can be distributed in several ways.  The
** "SRT" prefix means "SELECT Result Type".
*/
#define SRT_Union        1  /* Store result as keys in an index */
11006
11007
11008
11009
11010
11011
11012
11013
11014

11015
11016
11017
11018
11019
11020
11021
11022
11023
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
** accessed (or set to 0 for triggers fired as a result of INSERT 
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
struct TriggerPrg {
  Trigger *pTrigger;      /* Trigger this program was coded from */
  int orconf;             /* Default ON CONFLICT policy */
  SubProgram *pProgram;   /* Program implementing pTrigger/orconf */

  u32 aColmask[2];        /* Masks of old.*, new.* columns accessed */
  TriggerPrg *pNext;      /* Next entry in Parse.pTriggerPrg list */
};

/*
** The yDbMask datatype for the bitmask of all attached databases.
*/
#if SQLITE_MAX_ATTACHED>30
  typedef sqlite3_uint64 yDbMask;







|

>

<







10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007

11008
11009
11010
11011
11012
11013
11014
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
** accessed (or set to 0 for triggers fired as a result of INSERT 
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
struct TriggerPrg {
  Trigger *pTrigger;      /* Trigger this program was coded from */
  TriggerPrg *pNext;      /* Next entry in Parse.pTriggerPrg list */
  SubProgram *pProgram;   /* Program implementing pTrigger/orconf */
  int orconf;             /* Default ON CONFLICT policy */
  u32 aColmask[2];        /* Masks of old.*, new.* columns accessed */

};

/*
** The yDbMask datatype for the bitmask of all attached databases.
*/
#if SQLITE_MAX_ATTACHED>30
  typedef sqlite3_uint64 yDbMask;
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048

11049
11050
11051
11052
11053




11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080



11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092

11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104











11105
11106
11107
11108
11109
11110
11111
11112
11113
11114
11115


11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131



11132
11133
11134
11135
11136
11137
11138
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
** used to store the set of table-locks required by the statement being
** compiled. Function sqlite3TableLock() is used to add entries to the
** list.
*/
struct Parse {
  sqlite3 *db;         /* The main database structure */
  int rc;              /* Return code from execution */
  char *zErrMsg;       /* An error message */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */

  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 checkSchema;      /* Causes schema cookie check after an error */
  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  u8 nTempInUse;       /* Number of aTempReg[] currently checked out */




  int aTempReg[8];     /* Holding area for temporary registers */
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nOnce;           /* Number of OP_Once instructions so far */
  int ckBase;          /* Base register of data during check constraints */
  int iCacheLevel;     /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
  int iCacheCnt;       /* Counter used to generate aColCache[].lru values */
  u8 nColCache;        /* Number of entries in aColCache[] */
  u8 iColCache;        /* Next entry in aColCache[] to replace */
  struct yColCache {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */
    u8 tempReg;           /* iReg is a temp register that needs to be freed */
    int iLevel;           /* Nesting level */
    int iReg;             /* Reg with value of this column. 0 means none. */
    int lru;              /* Least recently used entry has the smallest value */
  } aColCache[SQLITE_N_COLCACHE];  /* One for each column cache entry */
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
  u8 isMultiWrite;     /* True if statement may affect/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */



#ifndef SQLITE_OMIT_SHARED_CACHE
  int nTableLock;        /* Number of locks in aTableLock */
  TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
  int regRoot;         /* Register holding root page number for new objects */
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  int nMaxArg;         /* Max args passed to user function by sub-program */

  /* Information used while coding trigger programs. */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */

  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */
  double nQueryLoop;   /* Estimated number of iterations of a query */

  /* Above is constant between recursions.  Below is reset before and after
  ** each recursion */

  int nVar;            /* Number of '?' variables seen in the SQL so far */
  int nzVar;           /* Number of available slots in azVar[] */











  char **azVar;        /* Pointers to names of parameters */
  Vdbe *pReprepare;    /* VM being reprepared (sqlite3Reprepare()) */
  int nAlias;          /* Number of aliased result set columns */
  int *aAlias;         /* Register used to hold aliased result */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */


#ifndef SQLITE_OMIT_VIRTUALTABLE
  Token sArg;                /* Complete text of a module argument */
  u8 declareVtab;            /* True if inside sqlite3_declare_vtab() */
  int nVtabLock;             /* Number of virtual tables to lock */
  Table **apVtabLock;        /* Pointer to virtual tables needing locking */
#endif
  int nHeight;            /* Expression tree height of current sub-select */
  Table *pZombieTab;      /* List of Table objects to delete after code gen */
  TriggerPrg *pTriggerPrg;    /* Linked list of coded triggers */

#ifndef SQLITE_OMIT_EXPLAIN
  int iSelectId;
  int iNextSelectId;
#endif
};




#ifdef SQLITE_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->declareVtab)
#endif

/*







<


>





>
>
>
>











<
<










<
<


>
>
>




<
<

<




>





<




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


>
>

|
<
<
|

<
|
|
<
<
<
<
<


>
>
>







11030
11031
11032
11033
11034
11035
11036

11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059


11060
11061
11062
11063
11064
11065
11066
11067
11068
11069


11070
11071
11072
11073
11074
11075
11076
11077
11078


11079

11080
11081
11082
11083
11084
11085
11086
11087
11088
11089

11090
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108

11109



11110
11111
11112
11113
11114
11115
11116
11117


11118
11119

11120
11121





11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
** used to store the set of table-locks required by the statement being
** compiled. Function sqlite3TableLock() is used to add entries to the
** list.
*/
struct Parse {
  sqlite3 *db;         /* The main database structure */

  char *zErrMsg;       /* An error message */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int rc;              /* Return code from execution */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 checkSchema;      /* Causes schema cookie check after an error */
  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  u8 nTempInUse;       /* Number of aTempReg[] currently checked out */
  u8 nColCache;        /* Number of entries in aColCache[] */
  u8 iColCache;        /* Next entry in aColCache[] to replace */
  u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  int aTempReg[8];     /* Holding area for temporary registers */
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nOnce;           /* Number of OP_Once instructions so far */
  int ckBase;          /* Base register of data during check constraints */
  int iCacheLevel;     /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
  int iCacheCnt;       /* Counter used to generate aColCache[].lru values */


  struct yColCache {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */
    u8 tempReg;           /* iReg is a temp register that needs to be freed */
    int iLevel;           /* Nesting level */
    int iReg;             /* Reg with value of this column. 0 means none. */
    int lru;              /* Least recently used entry has the smallest value */
  } aColCache[SQLITE_N_COLCACHE];  /* One for each column cache entry */
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */


  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
  int regRoot;         /* Register holding root page number for new objects */
  int nMaxArg;         /* Max args passed to user function by sub-program */
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nTableLock;        /* Number of locks in aTableLock */
  TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif


  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */


  /* Information used while coding trigger programs. */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  double nQueryLoop;   /* Estimated number of iterations of a query */
  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */


  /* Above is constant between recursions.  Below is reset before and after
  ** each recursion */

  int nVar;                 /* Number of '?' variables seen in the SQL so far */
  int nzVar;                /* Number of available slots in azVar[] */
  u8 explain;               /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  u8 declareVtab;           /* True if inside sqlite3_declare_vtab() */
  int nVtabLock;            /* Number of virtual tables to lock */
#endif
  int nAlias;               /* Number of aliased result set columns */
  int nHeight;              /* Expression tree height of current sub-select */
#ifndef SQLITE_OMIT_EXPLAIN
  int iSelectId;            /* ID of current select for EXPLAIN output */
  int iNextSelectId;        /* Next available select ID for EXPLAIN output */
#endif
  char **azVar;             /* Pointers to names of parameters */
  Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */

  int *aAlias;              /* Register used to hold aliased result */



  const char *zTail;        /* All SQL text past the last semicolon parsed */
  Table *pNewTable;         /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
  Token sNameToken;         /* Token with unqualified schema object name */
  Token sLastToken;         /* The last token parsed */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  Token sArg;               /* Complete text of a module argument */


  Table **apVtabLock;       /* Pointer to virtual tables needing locking */
#endif

  Table *pZombieTab;        /* List of Table objects to delete after code gen */
  TriggerPrg *pTriggerPrg;  /* Linked list of coded triggers */





};

/*
** Return true if currently inside an sqlite3_declare_vtab() call.
*/
#ifdef SQLITE_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->declareVtab)
#endif

/*
11275
11276
11277
11278
11279
11280
11281
11282
11283

11284
11285
11286
11287
11288
11289
11290

/*
** A pointer to this structure is used to communicate information
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  char **pzErrMsg;    /* Error message stored here */

  int rc;             /* Result code stored here */
} InitData;

/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.







<

>







11270
11271
11272
11273
11274
11275
11276

11277
11278
11279
11280
11281
11282
11283
11284
11285

/*
** A pointer to this structure is used to communicate information
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */

  char **pzErrMsg;    /* Error message stored here */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  int rc;             /* Result code stored here */
} InitData;

/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
SQLITE_PRIVATE   void sqlite3AutoincrementBegin(Parse *pParse);
SQLITE_PRIVATE   void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);







|







11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
SQLITE_PRIVATE   void sqlite3AutoincrementBegin(Parse *pParse);
SQLITE_PRIVATE   void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3AbsInt32(int);
#ifdef SQLITE_ENABLE_8_3_NAMES
SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
#else
# define sqlite3FileSuffix3(X,Y)
#endif
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z);

SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, 
                        void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);







|







11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3AbsInt32(int);
#ifdef SQLITE_ENABLE_8_3_NAMES
SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
#else
# define sqlite3FileSuffix3(X,Y)
#endif
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int);

SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, 
                        void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE    VTable *sqlite3GetVTable(sqlite3*, Table*);
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*);
SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*);
SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);







|







11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE    VTable *sqlite3GetVTable(sqlite3*, Table*);
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*);
SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*);
SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
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
**
** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
** set to NULL if the currently executing frame is the main program.
*/
typedef struct VdbeFrame VdbeFrame;
struct VdbeFrame {
  Vdbe *v;                /* VM this frame belongs to */
  int pc;                 /* Program Counter in parent (calling) frame */
  Op *aOp;                /* Program instructions for parent frame */
  int nOp;                /* Size of aOp array */
  Mem *aMem;              /* Array of memory cells for parent frame */
  int nMem;               /* Number of entries in aMem */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */


  u16 nCursor;            /* Number of entries in apCsr */

  void *token;            /* Copy of SubProgram.token */


  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  int nChange;            /* Statement changes (Vdbe.nChanges)     */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** A value for VdbeCursor.cacheValid that means the cache is always invalid.
*/







|

<

<

<

>
>

>
|
>
>


<

<







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
**
** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
** set to NULL if the currently executing frame is the main program.
*/
typedef struct VdbeFrame VdbeFrame;
struct VdbeFrame {
  Vdbe *v;                /* VM this frame belongs to */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
  Op *aOp;                /* Program instructions for parent frame */

  Mem *aMem;              /* Array of memory cells for parent frame */

  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */

  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  u16 nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */

  int nChange;            /* Statement changes (Vdbe.nChanges)     */

};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** A value for VdbeCursor.cacheValid that means the cache is always invalid.
*/
13035
13036
13037
13038
13039
13040
13041

13042
13043
13044
13045
13046
13047
13048
13049
13050
** (Mem) which are only defined there.
*/
struct sqlite3_context {
  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
  Mem s;                /* The return value is stored here */
  Mem *pMem;            /* Memory cell used to store aggregate context */

  int isError;          /* Error code returned by the function. */
  CollSeq *pColl;       /* Collating sequence */
};

/*
** An Explain object accumulates indented output which is helpful
** in describing recursive data structures.
*/
struct Explain {







>

|







13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
** (Mem) which are only defined there.
*/
struct sqlite3_context {
  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
  Mem s;                /* The return value is stored here */
  Mem *pMem;            /* Memory cell used to store aggregate context */
  CollSeq *pColl;       /* Collating sequence */
  int isError;          /* Error code returned by the function. */
  int skipFlag;         /* Skip skip accumulator loading if true */
};

/*
** An Explain object accumulates indented output which is helpful
** in describing recursive data structures.
*/
struct Explain {
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
  Mem **apArg;            /* Arguments to currently executing user function */
  Mem *aColName;          /* Column names to return */
  Mem *pResultSet;        /* Pointer to an array of results */
  int nMem;               /* Number of memory locations currently allocated */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Number of slots allocated for aOp[] */
  int nLabel;             /* Number of labels used */
  int nLabelAlloc;        /* Number of slots allocated in aLabel[] */
  int *aLabel;            /* Space to hold the labels */
  u16 nResColumn;         /* Number of columns in one row of the result set */
  u16 nCursor;            /* Number of slots in apCsr[] */
  u32 magic;              /* Magic number for sanity checking */
  char *zErrMsg;          /* Error message written here */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */







<







13073
13074
13075
13076
13077
13078
13079

13080
13081
13082
13083
13084
13085
13086
  Mem **apArg;            /* Arguments to currently executing user function */
  Mem *aColName;          /* Column names to return */
  Mem *pResultSet;        /* Pointer to an array of results */
  int nMem;               /* Number of memory locations currently allocated */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Number of slots allocated for aOp[] */
  int nLabel;             /* Number of labels used */

  int *aLabel;            /* Space to hold the labels */
  u16 nResColumn;         /* Number of columns in one row of the result set */
  u16 nCursor;            /* Number of slots in apCsr[] */
  u32 magic;              /* Magic number for sanity checking */
  char *zErrMsg;          /* Error message written here */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
15144
15145
15146
15147
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
*************************************************************************
**
** This file contains low-level memory allocation drivers for when
** SQLite will use the standard C-library malloc/realloc/free interface
** to obtain the memory it needs.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
























*/

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
*/
#ifdef SQLITE_SYSTEM_MALLOC

/*
** Windows systems have malloc_usable_size() but it is called _msize()


*/
#if !defined(HAVE_MALLOC_USABLE_SIZE) && SQLITE_OS_WIN
# define HAVE_MALLOC_USABLE_SIZE 1
# define malloc_usable_size _msize
#endif

#if defined(__APPLE__)

/*
** Use the zone allocator available on apple products

*/
#include <sys/sysctl.h>
#include <malloc/malloc.h>
#include <libkern/OSAtomic.h>
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
#define SQLITE_MALLOCSIZE(x) \
        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))

#else /* if not __APPLE__ */

/*
** Use standard C library malloc and free on non-Apple systems.

*/
#define SQLITE_MALLOC(x)    malloc(x)
#define SQLITE_FREE(x)      free(x)
#define SQLITE_REALLOC(x,y) realloc((x),(y))





#ifdef HAVE_MALLOC_USABLE_SIZE
#include <malloc.h>

#define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)

#else
#undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** Like malloc(), but remember the size of the allocation
** so that we can find it later using sqlite3MemSize().







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










|
>
>

|
|
<


|


|
>














|
>





>
>
>
>

<
>
|
>

|







15139
15140
15141
15142
15143
15144
15145
15146
15147
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
15207
15208
15209
15210
15211
15212
15213
15214
15215
15216
15217
15218
15219

15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
*************************************************************************
**
** This file contains low-level memory allocation drivers for when
** SQLite will use the standard C-library malloc/realloc/free interface
** to obtain the memory it needs.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.  The content of
** this file is only used if SQLITE_SYSTEM_MALLOC is defined.  The
** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined.  The
** default configuration is to use memory allocation routines in this
** file.
**
** C-preprocessor macro summary:
**
**    HAVE_MALLOC_USABLE_SIZE     The configure script sets this symbol if
**                                the malloc_usable_size() interface exists
**                                on the target platform.  Or, this symbol
**                                can be set manually, if desired.
**                                If an equivalent interface exists by
**                                a different name, using a separate -D
**                                option to rename it.
**
**    SQLITE_WITHOUT_ZONEMALLOC   Some older macs lack support for the zone
**                                memory allocator.  Set this symbol to enable
**                                building on older macs.
**
**    SQLITE_WITHOUT_MSIZE        Set this symbol to disable the use of
**                                _msize() on windows systems.  This might
**                                be necessary when compiling for Delphi,
**                                for example.
*/

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
*/
#ifdef SQLITE_SYSTEM_MALLOC

/*
** The MSVCRT has malloc_usable_size() but it is called _msize().
** The use of _msize() is automatic, but can be disabled by compiling
** with -DSQLITE_WITHOUT_MSIZE
*/
#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
# define SQLITE_MALLOCSIZE _msize

#endif

#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)

/*
** Use the zone allocator available on apple products unless the
** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
*/
#include <sys/sysctl.h>
#include <malloc/malloc.h>
#include <libkern/OSAtomic.h>
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
#define SQLITE_MALLOCSIZE(x) \
        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))

#else /* if not __APPLE__ */

/*
** Use standard C library malloc and free on non-Apple systems.  
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
*/
#define SQLITE_MALLOC(x)    malloc(x)
#define SQLITE_FREE(x)      free(x)
#define SQLITE_REALLOC(x,y) realloc((x),(y))

#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
      || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
# include <malloc.h>    /* Needed for malloc_usable_size on linux */
#endif
#ifdef HAVE_MALLOC_USABLE_SIZE

# ifndef SQLITE_MALLOCSIZE
#  define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
# endif
#else
# undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** Like malloc(), but remember the size of the allocation
** so that we can find it later using sqlite3MemSize().
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321
15322
15323
15324
15325
15326
  return ROUND8(n);
}

/*
** Initialize this module.
*/
static int sqlite3MemInit(void *NotUsed){
#if defined(__APPLE__)
  int cpuCount;
  size_t len;
  if( _sqliteZone_ ){
    return SQLITE_OK;
  }
  len = sizeof(cpuCount);
  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */







|







15339
15340
15341
15342
15343
15344
15345
15346
15347
15348
15349
15350
15351
15352
15353
  return ROUND8(n);
}

/*
** Initialize this module.
*/
static int sqlite3MemInit(void *NotUsed){
#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
  int cpuCount;
  size_t len;
  if( _sqliteZone_ ){
    return SQLITE_OK;
  }
  len = sizeof(cpuCount);
  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
24938
24939
24940
24941
24942
24943
24944
24945
24946
24947
24948
24949
24950
24951
24952
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
  unixInodeInfo *pInode;              /* Info about locks on this inode */
  int h;                              /* The file descriptor */
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE







|







24965
24966
24967
24968
24969
24970
24971
24972
24973
24974
24975
24976
24977
24978
24979
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
  unixInodeInfo *pInode;              /* Info about locks on this inode */
  int h;                              /* The file descriptor */
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
24989
24990
24991
24992
24993
24994
24995

24996
24997
24998
24999
25000
25001
25002
#else
# define UNIXFILE_DIRSYNC    0x00
#endif
#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE      0x20     /* Delete on close */
#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */


/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_unix.c ***************/
/************** Begin file os_common.h ***************************************/
/*







>







25016
25017
25018
25019
25020
25021
25022
25023
25024
25025
25026
25027
25028
25029
25030
#else
# define UNIXFILE_DIRSYNC    0x00
#endif
#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE      0x20     /* Delete on close */
#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
#define UNIXFILE_CHOWN      0x100     /* File ownership was changed */

/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_unix.c ***************/
/************** Begin file os_common.h ***************************************/
/*
25353
25354
25355
25356
25357
25358
25359






25360
25361
25362
25363
25364
25365
25366

  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)







}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.







>
>
>
>
>
>







25381
25382
25383
25384
25385
25386
25387
25388
25389
25390
25391
25392
25393
25394
25395
25396
25397
25398
25399
25400

  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)fchown,          0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)

  { "umask",        (sqlite3_syscall_ptr)umask,           0 },
#define osUmask     ((mode_t(*)(mode_t))aSyscall[21].pCurrent)

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
25439
25440
25441
25442
25443
25444
25445

25446













25447
25448
25449








25450



25451
25452
25453
25454
25455
25456
25457
  for(i++; i<ArraySize(aSyscall); i++){
    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
  }
  return 0;
}

/*

** Retry open() calls that fail due to EINTR













*/
static int robust_open(const char *z, int f, int m){
  int rc;








  do{ rc = osOpen(z,f,m); }while( rc<0 && errno==EINTR );



  return rc;
}

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo and
** vxworksFileId objects used by this file, all of which may be 







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

|

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







25473
25474
25475
25476
25477
25478
25479
25480
25481
25482
25483
25484
25485
25486
25487
25488
25489
25490
25491
25492
25493
25494
25495
25496
25497
25498
25499
25500
25501
25502
25503
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514
25515
25516
  for(i++; i<ArraySize(aSyscall); i++){
    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
  }
  return 0;
}

/*
** Invoke open().  Do so multiple times, until it either succeeds or
** files for some reason other than EINTR.
**
** If the file creation mode "m" is 0 then set it to the default for
** SQLite.  The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
** 0644) as modified by the system umask.  If m is not 0, then
** make the file creation mode be exactly m ignoring the umask.
**
** The m parameter will be non-zero only when creating -wal, -journal,
** and -shm files.  We want those files to have *exactly* the same
** permissions as their original database, unadulterated by the umask.
** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int robust_open(const char *z, int f, mode_t m){
  int rc;
  mode_t m2;
  mode_t origM;
  if( m==0 ){
    m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
  }else{
    m2 = m;
    origM = osUmask(0);
  }
  do{ rc = osOpen(z,f,m2); }while( rc<0 && errno==EINTR );
  if( m ){
    osUmask(origM);
  }
  return rc;
}

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo and
** vxworksFileId objects used by this file, all of which may be 
28791
28792
28793
28794
28795
28796
28797
28798
28799
28800
28801
28802
28803
28804
28805
28806
  pInode = pDbFd->pInode;
  pShmNode = pInode->pShmNode;
  if( pShmNode==0 ){
    struct stat sStat;                 /* fstat() info for database file */

    /* Call fstat() to figure out the permissions on the database file. If
    ** a new *-shm file is created, an attempt will be made to create it
    ** with the same permissions. The actual permissions the file is created
    ** with are subject to the current umask setting.
    */
    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
      rc = SQLITE_IOERR_FSTAT;
      goto shm_open_err;
    }

#ifdef SQLITE_SHM_DIRECTORY







|
<







28850
28851
28852
28853
28854
28855
28856
28857

28858
28859
28860
28861
28862
28863
28864
  pInode = pDbFd->pInode;
  pShmNode = pInode->pShmNode;
  if( pShmNode==0 ){
    struct stat sStat;                 /* fstat() info for database file */

    /* Call fstat() to figure out the permissions on the database file. If
    ** a new *-shm file is created, an attempt will be made to create it
    ** with the same permissions.

    */
    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
      rc = SQLITE_IOERR_FSTAT;
      goto shm_open_err;
    }

#ifdef SQLITE_SHM_DIRECTORY
28836
28837
28838
28839
28840
28841
28842
28843
28844
28845
28846










28847
28848
28849
28850
28851
28852
28853
      int openFlags = O_RDWR | O_CREAT;
      if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
        openFlags = O_RDONLY;
        pShmNode->isReadonly = 1;
      }
      pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
      if( pShmNode->h<0 ){
        if( pShmNode->h<0 ){
          rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
          goto shm_open_err;
        }










      }
  
      /* Check to see if another process is holding the dead-man switch.
      ** If not, truncate the file to zero length. 
      */
      rc = SQLITE_OK;
      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){







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







28894
28895
28896
28897
28898
28899
28900

28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918
28919
28920
      int openFlags = O_RDWR | O_CREAT;
      if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
        openFlags = O_RDONLY;
        pShmNode->isReadonly = 1;
      }
      pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
      if( pShmNode->h<0 ){

        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
        goto shm_open_err;
      }

      /* If this process is running as root, make sure that the SHM file
      ** is owned by the same user that owns the original database.  Otherwise,
      ** the original owner will not be able to connect. If this process is
      ** not root, the following fchown() will fail, but we don't care.  The
      ** if(){..} and the UNIXFILE_CHOWN flag are purely to silence compiler
      ** warnings.
      */
      if( osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid)==0 ){
        pDbFd->ctrlFlags |= UNIXFILE_CHOWN;
      }
  
      /* Check to see if another process is holding the dead-man switch.
      ** If not, truncate the file to zero length. 
      */
      rc = SQLITE_OK;
      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
29814
29815
29816
29817
29818
29819
29820
29821
29822
29823
29824
29825
29826
29827
29828
29829
29830
29831
29832
29833
29834
29835
29836
29837
29838
29839
29840


29841
29842
29843


29844
29845
29846
29847
29848
29849
29850
/*
** This function is called by unixOpen() to determine the unix permissions
** to create new files with. If no error occurs, then SQLITE_OK is returned
** and a value suitable for passing as the third argument to open(2) is
** written to *pMode. If an IO error occurs, an SQLite error code is 
** returned and the value of *pMode is not modified.
**
** If the file being opened is a temporary file, it is always created with
** the octal permissions 0600 (read/writable by owner only). If the file
** is a database or master journal file, it is created with the permissions 
** mask SQLITE_DEFAULT_FILE_PERMISSIONS.
**
** Finally, if the file being opened is a WAL or regular journal file, then 
** this function queries the file-system for the permissions on the 
** corresponding database file and sets *pMode to this value. Whenever 
** possible, WAL and journal files are created using the same permissions 
** as the associated database file.
**
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** original filename is unavailable.  But 8_3_NAMES is only used for
** FAT filesystems and permissions do not matter there, so just use
** the default permissions.
*/
static int findCreateFileMode(
  const char *zPath,              /* Path of file (possibly) being created */
  int flags,                      /* Flags passed as 4th argument to xOpen() */
  mode_t *pMode                   /* OUT: Permissions to open file with */


){
  int rc = SQLITE_OK;             /* Return Code */
  *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;


  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
    char zDb[MAX_PATHNAME+1];     /* Database file path */
    int nDb;                      /* Number of valid bytes in zDb */
    struct stat sStat;            /* Output of stat() on database file */

    /* zPath is a path to a WAL or journal file. The following block derives
    ** the path to the associated database file from zPath. This block handles







|
|
<
|
<
|













|
>
>


|
>
>







29881
29882
29883
29884
29885
29886
29887
29888
29889

29890

29891
29892
29893
29894
29895
29896
29897
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908
29909
29910
29911
29912
29913
29914
29915
29916
29917
29918
29919
/*
** This function is called by unixOpen() to determine the unix permissions
** to create new files with. If no error occurs, then SQLITE_OK is returned
** and a value suitable for passing as the third argument to open(2) is
** written to *pMode. If an IO error occurs, an SQLite error code is 
** returned and the value of *pMode is not modified.
**
** In most cases cases, this routine sets *pMode to 0, which will become
** an indication to robust_open() to create the file using

** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.

** But if the file being opened is a WAL or regular journal file, then 
** this function queries the file-system for the permissions on the 
** corresponding database file and sets *pMode to this value. Whenever 
** possible, WAL and journal files are created using the same permissions 
** as the associated database file.
**
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** original filename is unavailable.  But 8_3_NAMES is only used for
** FAT filesystems and permissions do not matter there, so just use
** the default permissions.
*/
static int findCreateFileMode(
  const char *zPath,              /* Path of file (possibly) being created */
  int flags,                      /* Flags passed as 4th argument to xOpen() */
  mode_t *pMode,                  /* OUT: Permissions to open file with */
  uid_t *pUid,                    /* OUT: uid to set on the file */
  gid_t *pGid                     /* OUT: gid to set on the file */
){
  int rc = SQLITE_OK;             /* Return Code */
  *pMode = 0;
  *pUid = 0;
  *pGid = 0;
  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
    char zDb[MAX_PATHNAME+1];     /* Database file path */
    int nDb;                      /* Number of valid bytes in zDb */
    struct stat sStat;            /* Output of stat() on database file */

    /* zPath is a path to a WAL or journal file. The following block derives
    ** the path to the associated database file from zPath. This block handles
29870
29871
29872
29873
29874
29875
29876


29877
29878
29879
29880
29881
29882
29883
    }
#endif
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    if( 0==osStat(zDb, &sStat) ){
      *pMode = sStat.st_mode & 0777;


    }else{
      rc = SQLITE_IOERR_FSTAT;
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
  }
  return rc;







>
>







29939
29940
29941
29942
29943
29944
29945
29946
29947
29948
29949
29950
29951
29952
29953
29954
    }
#endif
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    if( 0==osStat(zDb, &sStat) ){
      *pMode = sStat.st_mode & 0777;
      *pUid = sStat.st_uid;
      *pGid = sStat.st_gid;
    }else{
      rc = SQLITE_IOERR_FSTAT;
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
  }
  return rc;
30016
30017
30018
30019
30020
30021
30022


30023
30024
30025
30026
30027
30028
30029
30030
30031
30032
30033
30034
30035
30036
30037
30038
30039
30040
30041
30042
30043











30044
30045
30046
30047
30048
30049
30050
  if( isReadWrite ) openFlags |= O_RDWR;
  if( isCreate )    openFlags |= O_CREAT;
  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
  openFlags |= (O_LARGEFILE|O_BINARY);

  if( fd<0 ){
    mode_t openMode;              /* Permissions to create file with */


    rc = findCreateFileMode(zName, flags, &openMode);
    if( rc!=SQLITE_OK ){
      assert( !p->pUnused );
      assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
      return rc;
    }
    fd = robust_open(zName, openFlags, openMode);
    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
    if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
      /* Failed to open the file for read/write access. Try read-only. */
      flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
      openFlags &= ~(O_RDWR|O_CREAT);
      flags |= SQLITE_OPEN_READONLY;
      openFlags |= O_RDONLY;
      isReadonly = 1;
      fd = robust_open(zName, openFlags, openMode);
    }
    if( fd<0 ){
      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      goto open_finished;
    }











  }
  assert( fd>=0 );
  if( pOutFlags ){
    *pOutFlags = flags;
  }

  if( p->pUnused ){







>
>
|




















>
>
>
>
>
>
>
>
>
>
>







30087
30088
30089
30090
30091
30092
30093
30094
30095
30096
30097
30098
30099
30100
30101
30102
30103
30104
30105
30106
30107
30108
30109
30110
30111
30112
30113
30114
30115
30116
30117
30118
30119
30120
30121
30122
30123
30124
30125
30126
30127
30128
30129
30130
30131
30132
30133
30134
  if( isReadWrite ) openFlags |= O_RDWR;
  if( isCreate )    openFlags |= O_CREAT;
  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
  openFlags |= (O_LARGEFILE|O_BINARY);

  if( fd<0 ){
    mode_t openMode;              /* Permissions to create file with */
    uid_t uid;                    /* Userid for the file */
    gid_t gid;                    /* Groupid for the file */
    rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
    if( rc!=SQLITE_OK ){
      assert( !p->pUnused );
      assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
      return rc;
    }
    fd = robust_open(zName, openFlags, openMode);
    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
    if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
      /* Failed to open the file for read/write access. Try read-only. */
      flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
      openFlags &= ~(O_RDWR|O_CREAT);
      flags |= SQLITE_OPEN_READONLY;
      openFlags |= O_RDONLY;
      isReadonly = 1;
      fd = robust_open(zName, openFlags, openMode);
    }
    if( fd<0 ){
      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      goto open_finished;
    }

    /* If this process is running as root and if creating a new rollback
    ** journal or WAL file, set the ownership of the journal or WAL to be
    ** the same as the original database.  If we are not running as root,
    ** then the fchown() call will fail, but that's ok.  The "if(){}" and
    ** the setting of the UNIXFILE_CHOWN flag are purely to silence compiler
    ** warnings from gcc.
    */
    if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
      if( osFchown(fd, uid, gid)==0 ){ p->ctrlFlags |= UNIXFILE_CHOWN; }
    }
  }
  assert( fd>=0 );
  if( pOutFlags ){
    *pOutFlags = flags;
  }

  if( p->pUnused ){
30348
30349
30350
30351
30352
30353
30354
30355
30356
30357
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
  ** When testing, initializing zBuf[] to zero is all we do.  That means
  ** that we always use the same random number sequence.  This makes the
  ** tests repeatable.
  */
  memset(zBuf, 0, nBuf);
#if !defined(SQLITE_TEST)
  {
    int pid, fd;
    fd = robust_open("/dev/urandom", O_RDONLY, 0);
    if( fd<0 ){
      time_t t;
      time(&t);
      memcpy(zBuf, &t, sizeof(t));
      pid = getpid();
      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
      nBuf = sizeof(t) + sizeof(pid);
    }else{
      do{ nBuf = osRead(fd, zBuf, nBuf); }while( nBuf<0 && errno==EINTR );
      robust_close(0, fd, __LINE__);
    }
  }
#endif
  return nBuf;
}








|










|







30432
30433
30434
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444
30445
30446
30447
30448
30449
30450
30451
30452
30453
30454
30455
30456
30457
  ** When testing, initializing zBuf[] to zero is all we do.  That means
  ** that we always use the same random number sequence.  This makes the
  ** tests repeatable.
  */
  memset(zBuf, 0, nBuf);
#if !defined(SQLITE_TEST)
  {
    int pid, fd, got;
    fd = robust_open("/dev/urandom", O_RDONLY, 0);
    if( fd<0 ){
      time_t t;
      time(&t);
      memcpy(zBuf, &t, sizeof(t));
      pid = getpid();
      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
      nBuf = sizeof(t) + sizeof(pid);
    }else{
      do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
      robust_close(0, fd, __LINE__);
    }
  }
#endif
  return nBuf;
}

30763
30764
30765
30766
30767
30768
30769
30770
30771
30772
30773
30774
30775
30776
30777
30778
30779
30780
30781
30782
30783
30784
30785
30786
30787
  }else{
    pUnused = sqlite3_malloc(sizeof(*pUnused));
    if( !pUnused ){
      return SQLITE_NOMEM;
    }
  }
  if( fd<0 ){
    fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
    terrno = errno;
    if( fd<0 && errno==ENOENT && islockfile ){
      if( proxyCreateLockPath(path) == SQLITE_OK ){
        fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
      }
    }
  }
  if( fd<0 ){
    openFlags = O_RDONLY;
    fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
    terrno = errno;
  }
  if( fd<0 ){
    if( islockfile ){
      return SQLITE_BUSY;
    }
    switch (terrno) {







|



|





|







30847
30848
30849
30850
30851
30852
30853
30854
30855
30856
30857
30858
30859
30860
30861
30862
30863
30864
30865
30866
30867
30868
30869
30870
30871
  }else{
    pUnused = sqlite3_malloc(sizeof(*pUnused));
    if( !pUnused ){
      return SQLITE_NOMEM;
    }
  }
  if( fd<0 ){
    fd = robust_open(path, openFlags, 0);
    terrno = errno;
    if( fd<0 && errno==ENOENT && islockfile ){
      if( proxyCreateLockPath(path) == SQLITE_OK ){
        fd = robust_open(path, openFlags, 0);
      }
    }
  }
  if( fd<0 ){
    openFlags = O_RDONLY;
    fd = robust_open(path, openFlags, 0);
    terrno = errno;
  }
  if( fd<0 ){
    if( islockfile ){
      return SQLITE_BUSY;
    }
    switch (terrno) {
30897
30898
30899
30900
30901
30902
30903
30904
30905
30906
30907
30908
30909
30910
30911
30912
  /* read the conch content */
  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
  if( readLen<PROXY_PATHINDEX ){
    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
    goto end_breaklock;
  }
  /* write it out to the temporary break file */
  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL),
                   SQLITE_DEFAULT_FILE_PERMISSIONS);
  if( fd<0 ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
    goto end_breaklock;
  }
  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
    goto end_breaklock;







|
<







30981
30982
30983
30984
30985
30986
30987
30988

30989
30990
30991
30992
30993
30994
30995
  /* read the conch content */
  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
  if( readLen<PROXY_PATHINDEX ){
    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
    goto end_breaklock;
  }
  /* write it out to the temporary break file */
  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);

  if( fd<0 ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
    goto end_breaklock;
  }
  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
    goto end_breaklock;
31175
31176
31177
31178
31179
31180
31181
31182
31183
31184
31185
31186
31187
31188
31189
31190
      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
      if( rc==SQLITE_OK && pFile->openFlags ){
        int fd;
        if( pFile->h>=0 ){
          robust_close(pFile, pFile->h, __LINE__);
        }
        pFile->h = -1;
        fd = robust_open(pCtx->dbPath, pFile->openFlags,
                      SQLITE_DEFAULT_FILE_PERMISSIONS);
        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
        if( fd>=0 ){
          pFile->h = fd;
        }else{
          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
           during locking */
        }







|
<







31258
31259
31260
31261
31262
31263
31264
31265

31266
31267
31268
31269
31270
31271
31272
      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
      if( rc==SQLITE_OK && pFile->openFlags ){
        int fd;
        if( pFile->h>=0 ){
          robust_close(pFile, pFile->h, __LINE__);
        }
        pFile->h = -1;
        fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);

        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
        if( fd>=0 ){
          pFile->h = fd;
        }else{
          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
           during locking */
        }
31745
31746
31747
31748
31749
31750
31751
31752
31753
31754
31755
31756
31757
31758
31759
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==20 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}







|







31827
31828
31829
31830
31831
31832
31833
31834
31835
31836
31837
31838
31839
31840
31841
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==22 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}
36784
36785
36786
36787
36788
36789
36790

36791
36792
36793
36794
36795
36796
36797
36798
36799
36800
36801
36802
36803
36804
36805
36806
36807
  PGroup *pGroup;                     /* PGroup this cache belongs to */
  int szPage;                         /* Size of allocated pages in bytes */
  int szExtra;                        /* Size of extra space in bytes */
  int bPurgeable;                     /* True if cache is purgeable */
  unsigned int nMin;                  /* Minimum number of pages reserved */
  unsigned int nMax;                  /* Configured "cache_size" value */
  unsigned int n90pct;                /* nMax*9/10 */


  /* Hash table of all pages. The following variables may only be accessed
  ** when the accessor is holding the PGroup mutex.
  */
  unsigned int nRecyclable;           /* Number of pages in the LRU list */
  unsigned int nPage;                 /* Total number of pages in apHash */
  unsigned int nHash;                 /* Number of slots in apHash[] */
  PgHdr1 **apHash;                    /* Hash table for fast lookup by key */

  unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
};

/*
** Each cache entry is represented by an instance of the following 
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
** in memory.







>








<
<







36866
36867
36868
36869
36870
36871
36872
36873
36874
36875
36876
36877
36878
36879
36880
36881


36882
36883
36884
36885
36886
36887
36888
  PGroup *pGroup;                     /* PGroup this cache belongs to */
  int szPage;                         /* Size of allocated pages in bytes */
  int szExtra;                        /* Size of extra space in bytes */
  int bPurgeable;                     /* True if cache is purgeable */
  unsigned int nMin;                  /* Minimum number of pages reserved */
  unsigned int nMax;                  /* Configured "cache_size" value */
  unsigned int n90pct;                /* nMax*9/10 */
  unsigned int iMaxKey;               /* Largest key seen since xTruncate() */

  /* Hash table of all pages. The following variables may only be accessed
  ** when the accessor is holding the PGroup mutex.
  */
  unsigned int nRecyclable;           /* Number of pages in the LRU list */
  unsigned int nPage;                 /* Total number of pages in apHash */
  unsigned int nHash;                 /* Number of slots in apHash[] */
  PgHdr1 **apHash;                    /* Hash table for fast lookup by key */


};

/*
** Each cache entry is represented by an instance of the following 
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
** in memory.
36837
36838
36839
36840
36841
36842
36843
36844
36845

36846
36847
36848
36849
36850
36851
36852
  int isInit;                    /* True if initialized */
  int szSlot;                    /* Size of each free slot */
  int nSlot;                     /* The number of pcache slots */
  int nReserve;                  /* Try to keep nFreeSlot above this */
  void *pStart, *pEnd;           /* Bounds of pagecache malloc range */
  /* Above requires no mutex.  Use mutex below for variable that follow. */
  sqlite3_mutex *mutex;          /* Mutex for accessing the following: */
  int nFreeSlot;                 /* Number of unused pcache slots */
  PgFreeslot *pFree;             /* Free page blocks */

  /* The following value requires a mutex to change.  We skip the mutex on
  ** reading because (1) most platforms read a 32-bit integer atomically and
  ** (2) even if an incorrect value is read, no great harm is done since this
  ** is really just an optimization. */
  int bUnderPressure;            /* True if low on PAGECACHE memory */
} pcache1_g;








<

>







36918
36919
36920
36921
36922
36923
36924

36925
36926
36927
36928
36929
36930
36931
36932
36933
  int isInit;                    /* True if initialized */
  int szSlot;                    /* Size of each free slot */
  int nSlot;                     /* The number of pcache slots */
  int nReserve;                  /* Try to keep nFreeSlot above this */
  void *pStart, *pEnd;           /* Bounds of pagecache malloc range */
  /* Above requires no mutex.  Use mutex below for variable that follow. */
  sqlite3_mutex *mutex;          /* Mutex for accessing the following: */

  PgFreeslot *pFree;             /* Free page blocks */
  int nFreeSlot;                 /* Number of unused pcache slots */
  /* The following value requires a mutex to change.  We skip the mutex on
  ** reading because (1) most platforms read a 32-bit integer atomically and
  ** (2) even if an incorrect value is read, no great harm is done since this
  ** is really just an optimization. */
  int bUnderPressure;            /* True if low on PAGECACHE memory */
} pcache1_g;

38896
38897
38898
38899
38900
38901
38902
38903
38904
38905
38906
38907
38908
38909
38910
**   sub-codes.
*/
struct Pager {
  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
  u8 useJournal;              /* Use a rollback journal on this file */
  u8 noReadlock;              /* Do not bother to obtain readlocks */
  u8 noSync;                  /* Do not sync the journal if true */
  u8 fullSync;                /* Do extra syncs of the journal for robustness */
  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
  u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8 tempFile;                /* zFilename is a temporary file */
  u8 readOnly;                /* True for a read-only database */







<







38977
38978
38979
38980
38981
38982
38983

38984
38985
38986
38987
38988
38989
38990
**   sub-codes.
*/
struct Pager {
  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
  u8 useJournal;              /* Use a rollback journal on this file */

  u8 noSync;                  /* Do not sync the journal if true */
  u8 fullSync;                /* Do extra syncs of the journal for robustness */
  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
  u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8 tempFile;                /* zFilename is a temporary file */
  u8 readOnly;                /* True for a read-only database */
39144
39145
39146
39147
39148
39149
39150
39151
39152
39153
39154
39155
39156
39157
39158
      assert( pPager->errCode==SQLITE_OK );
      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
      break;

    case PAGER_READER:
      assert( pPager->errCode==SQLITE_OK );
      assert( p->eLock!=UNKNOWN_LOCK );
      assert( p->eLock>=SHARED_LOCK || p->noReadlock );
      break;

    case PAGER_WRITER_LOCKED:
      assert( p->eLock!=UNKNOWN_LOCK );
      assert( pPager->errCode==SQLITE_OK );
      if( !pagerUseWal(pPager) ){
        assert( p->eLock>=RESERVED_LOCK );







|







39224
39225
39226
39227
39228
39229
39230
39231
39232
39233
39234
39235
39236
39237
39238
      assert( pPager->errCode==SQLITE_OK );
      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
      break;

    case PAGER_READER:
      assert( pPager->errCode==SQLITE_OK );
      assert( p->eLock!=UNKNOWN_LOCK );
      assert( p->eLock>=SHARED_LOCK );
      break;

    case PAGER_WRITER_LOCKED:
      assert( p->eLock!=UNKNOWN_LOCK );
      assert( pPager->errCode==SQLITE_OK );
      if( !pagerUseWal(pPager) ){
        assert( p->eLock>=RESERVED_LOCK );
41353
41354
41355
41356
41357
41358
41359
41360
41361
41362
41363
41364
41365
41366
41367
  /* Query the WAL sub-system for the database size. The WalDbsize()
  ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
  ** if the database size is not available. The database size is not
  ** available from the WAL sub-system if the log file is empty or
  ** contains no valid committed transactions.
  */
  assert( pPager->eState==PAGER_OPEN );
  assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock );
  nPage = sqlite3WalDbsize(pPager->pWal);

  /* If the database size was not available from the WAL sub-system,
  ** determine it based on the size of the database file. If the size
  ** of the database file is not an integer multiple of the page-size,
  ** round down to the nearest page. Except, any file larger than 0
  ** bytes in size is considered to contain at least one page.







|







41433
41434
41435
41436
41437
41438
41439
41440
41441
41442
41443
41444
41445
41446
41447
  /* Query the WAL sub-system for the database size. The WalDbsize()
  ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
  ** if the database size is not available. The database size is not
  ** available from the WAL sub-system if the log file is empty or
  ** contains no valid committed transactions.
  */
  assert( pPager->eState==PAGER_OPEN );
  assert( pPager->eLock>=SHARED_LOCK );
  nPage = sqlite3WalDbsize(pPager->pWal);

  /* If the database size was not available from the WAL sub-system,
  ** determine it based on the size of the database file. If the size
  ** of the database file is not an integer multiple of the page-size,
  ** round down to the nearest page. Except, any file larger than 0
  ** bytes in size is considered to contain at least one page.
41408
41409
41410
41411
41412
41413
41414
41415
41416
41417
41418
41419
41420
41421
41422
** a WAL on a none-empty database, this ensures there is no race condition 
** between the xAccess() below and an xDelete() being executed by some 
** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
  int rc = SQLITE_OK;
  assert( pPager->eState==PAGER_OPEN );
  assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock );

  if( !pPager->tempFile ){
    int isWal;                    /* True if WAL file exists */
    Pgno nPage;                   /* Size of the database file */

    rc = pagerPagecount(pPager, &nPage);
    if( rc ) return rc;







|







41488
41489
41490
41491
41492
41493
41494
41495
41496
41497
41498
41499
41500
41501
41502
** a WAL on a none-empty database, this ensures there is no race condition 
** between the xAccess() below and an xDelete() being executed by some 
** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
  int rc = SQLITE_OK;
  assert( pPager->eState==PAGER_OPEN );
  assert( pPager->eLock>=SHARED_LOCK );

  if( !pPager->tempFile ){
    int isWal;                    /* True if WAL file exists */
    Pgno nPage;                   /* Size of the database file */

    rc = pagerPagecount(pPager, &nPage);
    if( rc ) return rc;
42571
42572
42573
42574
42575
42576
42577
42578
42579
42580
42581
42582
42583
42584
42585
**
** The nExtra parameter specifies the number of bytes of space allocated
** along with each page reference. This space is available to the user
** via the sqlite3PagerGetExtra() API.
**
** The flags argument is used to specify properties that affect the
** operation of the pager. It should be passed some bitwise combination
** of the PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK flags.
**
** The vfsFlags parameter is a bitmask to pass to the flags parameter
** of the xOpen() method of the supplied VFS when opening files. 
**
** If the pager object is allocated and the specified file opened 
** successfully, SQLITE_OK is returned and *ppPager set to point to
** the new pager object. If an error occurs, *ppPager is set to NULL







|







42651
42652
42653
42654
42655
42656
42657
42658
42659
42660
42661
42662
42663
42664
42665
**
** The nExtra parameter specifies the number of bytes of space allocated
** along with each page reference. This space is available to the user
** via the sqlite3PagerGetExtra() API.
**
** The flags argument is used to specify properties that affect the
** operation of the pager. It should be passed some bitwise combination
** of the PAGER_* flags.
**
** The vfsFlags parameter is a bitmask to pass to the flags parameter
** of the xOpen() method of the supplied VFS when opening files. 
**
** If the pager object is allocated and the specified file opened 
** successfully, SQLITE_OK is returned and *ppPager set to point to
** the new pager object. If an error occurs, *ppPager is set to NULL
42602
42603
42604
42605
42606
42607
42608
42609
42610
42611
42612
42613
42614
42615
42616
  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
  int memDb = 0;           /* True if this is an in-memory file */
  int readOnly = 0;        /* True if this is a read-only file */
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
  int nPathname = 0;       /* Number of bytes in zPathname */
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;  /* True to omit read-lock */
  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
  const char *zUri = 0;    /* URI args to copy */
  int nUri = 0;            /* Number of bytes of URI args at *zUri */

  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal). This







<







42682
42683
42684
42685
42686
42687
42688

42689
42690
42691
42692
42693
42694
42695
  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
  int memDb = 0;           /* True if this is an in-memory file */
  int readOnly = 0;        /* True if this is a read-only file */
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
  int nPathname = 0;       /* Number of bytes in zPathname */
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */

  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
  const char *zUri = 0;    /* URI args to copy */
  int nUri = 0;            /* Number of bytes of URI args at *zUri */

  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal). This
42809
42810
42811
42812
42813
42814
42815
42816
42817
42818
42819
42820
42821
42822
42823
  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);

  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  pPager->useJournal = (u8)useJournal;
  pPager->noReadlock = (noReadlock && readOnly) ?1:0;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
  /* pPager->stmtSize = 0; */
  /* pPager->stmtJSize = 0; */
  /* pPager->nPage = 0; */
  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;







<







42888
42889
42890
42891
42892
42893
42894

42895
42896
42897
42898
42899
42900
42901
  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);

  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  pPager->useJournal = (u8)useJournal;

  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
  /* pPager->stmtSize = 0; */
  /* pPager->stmtJSize = 0; */
  /* pPager->nPage = 0; */
  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
43031
43032
43033
43034
43035
43036
43037
43038
43039
43040
43041
43042
43043
43044
43045
43046
43047
43048
43049
43050
43051
43052
  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
  if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }

  if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
    int bHotJournal = 1;          /* True if there exists a hot journal-file */

    assert( !MEMDB );
    assert( pPager->noReadlock==0 || pPager->readOnly );

    if( pPager->noReadlock==0 ){
      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
      if( rc!=SQLITE_OK ){
        assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
        goto failed;
      }
    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
    */
    if( pPager->eLock<=SHARED_LOCK ){
      rc = hasHotJournal(pPager, &bHotJournal);







<

<
|
|
|
|
<







43109
43110
43111
43112
43113
43114
43115

43116

43117
43118
43119
43120

43121
43122
43123
43124
43125
43126
43127
  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
  if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }

  if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
    int bHotJournal = 1;          /* True if there exists a hot journal-file */

    assert( !MEMDB );



    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
    if( rc!=SQLITE_OK ){
      assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
      goto failed;

    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
    */
    if( pPager->eLock<=SHARED_LOCK ){
      rc = hasHotJournal(pPager, &bHotJournal);
45046
45047
45048
45049
45050
45051
45052
45053
45054
45055
45056
45057
45058
45059
45060
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
*/
static int pagerOpenWal(Pager *pPager){
  int rc = SQLITE_OK;

  assert( pPager->pWal==0 && pPager->tempFile==0 );
  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK || pPager->noReadlock);

  /* If the pager is already in exclusive-mode, the WAL module will use 
  ** heap-memory for the wal-index instead of the VFS shared-memory 
  ** implementation. Take the exclusive lock now, before opening the WAL
  ** file, to make sure this is safe.
  */
  if( pPager->exclusiveMode ){







|







45121
45122
45123
45124
45125
45126
45127
45128
45129
45130
45131
45132
45133
45134
45135
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
*/
static int pagerOpenWal(Pager *pPager){
  int rc = SQLITE_OK;

  assert( pPager->pWal==0 && pPager->tempFile==0 );
  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );

  /* If the pager is already in exclusive-mode, the WAL module will use 
  ** heap-memory for the wal-index instead of the VFS shared-memory 
  ** implementation. Take the exclusive lock now, before opening the WAL
  ** file, to make sure this is safe.
  */
  if( pPager->exclusiveMode ){
48559
48560
48561
48562
48563
48564
48565
48566
48567
48568
48569
48570
48571
48572
48573
48574
48575
48576
  u8 max1bytePayload;  /* min(maxLocal,127) */
  u16 maxLocal;        /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
  u16 minLocal;        /* Copy of BtShared.minLocal or BtShared.minLeaf */
  u16 cellOffset;      /* Index in aData of first cell pointer */
  u16 nFree;           /* Number of free bytes on the page */
  u16 nCell;           /* Number of cells on this page, local and ovfl */
  u16 maskPage;        /* Mask for page offset */
  struct _OvflCell {   /* Cells that will not fit on aData[] */
    u8 *pCell;          /* Pointers to the body of the overflow cell */
    u16 idx;            /* Insert this cell before idx-th non-overflow cell */
  } aOvfl[5];
  BtShared *pBt;       /* Pointer to BtShared that this page is part of */
  u8 *aData;           /* Pointer to disk image of the page data */
  u8 *aDataEnd;        /* One byte past the end of usable data */
  u8 *aCellIdx;        /* The cell index area */
  DbPage *pDbPage;     /* Pager page handle */
  Pgno pgno;           /* Page number for this page */
};







<
|
|
|







48634
48635
48636
48637
48638
48639
48640

48641
48642
48643
48644
48645
48646
48647
48648
48649
48650
  u8 max1bytePayload;  /* min(maxLocal,127) */
  u16 maxLocal;        /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
  u16 minLocal;        /* Copy of BtShared.minLocal or BtShared.minLeaf */
  u16 cellOffset;      /* Index in aData of first cell pointer */
  u16 nFree;           /* Number of free bytes on the page */
  u16 nCell;           /* Number of cells on this page, local and ovfl */
  u16 maskPage;        /* Mask for page offset */

  u16 aiOvfl[5];       /* Insert the i-th overflow cell before the aiOvfl-th
                       ** non-overflow cell */
  u8 *apOvfl[5];       /* Pointers to the body of overflow cells */
  BtShared *pBt;       /* Pointer to BtShared that this page is part of */
  u8 *aData;           /* Pointer to disk image of the page data */
  u8 *aDataEnd;        /* One byte past the end of usable data */
  u8 *aCellIdx;        /* The cell index area */
  DbPage *pDbPage;     /* Pager page handle */
  Pgno pgno;           /* Page number for this page */
};
48770
48771
48772
48773
48774
48775
48776



48777
48778
48779
48780
48781
48782
48783
48784
48785
48786
48787
48788
48789
48790
48791
48792
48793
48794
48795
** found at self->pBt->mutex. 
*/
struct BtCursor {
  Btree *pBtree;            /* The Btree to which this cursor belongs */
  BtShared *pBt;            /* The BtShared this cursor points to */
  BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */



  Pgno pgnoRoot;            /* The root page of this tree */
  sqlite3_int64 cachedRowid; /* Next rowid cache.  0 means not valid */
  CellInfo info;            /* A parse of the cell we are pointing at */
  i64 nKey;        /* Size of pKey, or last integer key */
  void *pKey;      /* Saved key that was cursor's last known position */
  int skipNext;    /* Prev() is noop if negative. Next() is noop if positive */
  u8 wrFlag;                /* True if writable */
  u8 atLast;                /* Cursor pointing to the last entry */
  u8 validNKey;             /* True if info.nKey is valid */
  u8 eState;                /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB
  Pgno *aOverflow;          /* Cache of overflow page locations */
  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
#endif
  i16 iPage;                            /* Index of current page in apPage */
  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
};








>
>
>











<







48844
48845
48846
48847
48848
48849
48850
48851
48852
48853
48854
48855
48856
48857
48858
48859
48860
48861
48862
48863
48864

48865
48866
48867
48868
48869
48870
48871
** found at self->pBt->mutex. 
*/
struct BtCursor {
  Btree *pBtree;            /* The Btree to which this cursor belongs */
  BtShared *pBt;            /* The BtShared this cursor points to */
  BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
#ifndef SQLITE_OMIT_INCRBLOB
  Pgno *aOverflow;          /* Cache of overflow page locations */
#endif
  Pgno pgnoRoot;            /* The root page of this tree */
  sqlite3_int64 cachedRowid; /* Next rowid cache.  0 means not valid */
  CellInfo info;            /* A parse of the cell we are pointing at */
  i64 nKey;        /* Size of pKey, or last integer key */
  void *pKey;      /* Saved key that was cursor's last known position */
  int skipNext;    /* Prev() is noop if negative. Next() is noop if positive */
  u8 wrFlag;                /* True if writable */
  u8 atLast;                /* Cursor pointing to the last entry */
  u8 validNKey;             /* True if info.nKey is valid */
  u8 eState;                /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB

  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
#endif
  i16 iPage;                            /* Index of current page in apPage */
  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
};

48910
48911
48912
48913
48914
48915
48916
48917
48918

48919
48920
48921
48922
48923
48924
48925
** This structure is passed around through all the sanity checking routines
** in order to keep track of some global state information.
*/
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
  BtShared *pBt;    /* The tree being checked out */
  Pager *pPager;    /* The associated pager.  Also accessible by pBt->pPager */
  Pgno nPage;       /* Number of pages in the database */
  int *anRef;       /* Number of times each page is referenced */

  int mxErr;        /* Stop accumulating errors when this reaches zero */
  int nErr;         /* Number of messages written to zErrMsg so far */
  int mallocFailed; /* A memory allocation error has occurred */
  StrAccum errMsg;  /* Accumulate the error message text here */
};

/*







<

>







48986
48987
48988
48989
48990
48991
48992

48993
48994
48995
48996
48997
48998
48999
49000
49001
** This structure is passed around through all the sanity checking routines
** in order to keep track of some global state information.
*/
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
  BtShared *pBt;    /* The tree being checked out */
  Pager *pPager;    /* The associated pager.  Also accessible by pBt->pPager */

  int *anRef;       /* Number of times each page is referenced */
  Pgno nPage;       /* Number of pages in the database */
  int mxErr;        /* Stop accumulating errors when this reaches zero */
  int nErr;         /* Number of messages written to zErrMsg so far */
  int mallocFailed; /* A memory allocation error has occurred */
  StrAccum errMsg;  /* Accumulate the error message text here */
};

/*
50071
50072
50073
50074
50075
50076
50077
50078
50079
50080
50081
50082
50083
50084
50085
50086
50087
50088
50089
50090
** pages that do contain overflow cells.
*/
static u8 *findOverflowCell(MemPage *pPage, int iCell){
  int i;
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  for(i=pPage->nOverflow-1; i>=0; i--){
    int k;
    struct _OvflCell *pOvfl;
    pOvfl = &pPage->aOvfl[i];
    k = pOvfl->idx;
    if( k<=iCell ){
      if( k==iCell ){
        return pOvfl->pCell;
      }
      iCell--;
    }
  }
  return findCell(pPage, iCell);
}








<
|
<


|







50147
50148
50149
50150
50151
50152
50153

50154

50155
50156
50157
50158
50159
50160
50161
50162
50163
50164
** pages that do contain overflow cells.
*/
static u8 *findOverflowCell(MemPage *pPage, int iCell){
  int i;
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  for(i=pPage->nOverflow-1; i>=0; i--){
    int k;

    k = pPage->aiOvfl[i];

    if( k<=iCell ){
      if( k==iCell ){
        return pPage->apOvfl[i];
      }
      iCell--;
    }
  }
  return findCell(pPage, iCell);
}

50890
50891
50892
50893
50894
50895
50896
50897
50898
50899
50900
50901
50902
50903
50904
50905
50906
50907
50908
** be exclusively in memory, or it might use a disk-based memory cache.
** Either way, the ephemeral database will be automatically deleted 
** when sqlite3BtreeClose() is called.
**
** If zFilename is ":memory:" then an in-memory database is created
** that is automatically destroyed when it is closed.
**
** The "flags" parameter is a bitmask that might contain bits
** BTREE_OMIT_JOURNAL and/or BTREE_NO_READLOCK.  The BTREE_NO_READLOCK
** bit is also set if the SQLITE_NoReadlock flags is set in db->flags.
** These flags are passed through into sqlite3PagerOpen() and must
** be the same values as PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK.
**
** If the database is already opened in the same database connection
** and we are in shared cache mode, then the open will fail with an
** SQLITE_CONSTRAINT error.  We cannot allow two or more BtShared
** objects in the same database connection since doing so will lead
** to problems with locking.
*/







|
|
<
<
<







50964
50965
50966
50967
50968
50969
50970
50971
50972



50973
50974
50975
50976
50977
50978
50979
** be exclusively in memory, or it might use a disk-based memory cache.
** Either way, the ephemeral database will be automatically deleted 
** when sqlite3BtreeClose() is called.
**
** If zFilename is ":memory:" then an in-memory database is created
** that is automatically destroyed when it is closed.
**
** The "flags" parameter is a bitmask that might contain bits like
** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY.



**
** If the database is already opened in the same database connection
** and we are in shared cache mode, then the open will fail with an
** SQLITE_CONSTRAINT error.  We cannot allow two or more BtShared
** objects in the same database connection since doing so will lead
** to problems with locking.
*/
50941
50942
50943
50944
50945
50946
50947
50948
50949
50950
50951
50952
50953
50954
50955
50956
50957

  /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
  assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );

  /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
  assert( (flags & BTREE_SINGLE)==0 || isTempDb );

  if( db->flags & SQLITE_NoReadlock ){
    flags |= BTREE_NO_READLOCK;
  }
  if( isMemdb ){
    flags |= BTREE_MEMORY;
  }
  if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
    vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  }
  p = sqlite3MallocZero(sizeof(Btree));







<
<
<







51012
51013
51014
51015
51016
51017
51018



51019
51020
51021
51022
51023
51024
51025

  /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
  assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );

  /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
  assert( (flags & BTREE_SINGLE)==0 || isTempDb );




  if( isMemdb ){
    flags |= BTREE_MEMORY;
  }
  if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
    vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  }
  p = sqlite3MallocZero(sizeof(Btree));
53395
53396
53397
53398
53399
53400
53401
53402
53403
53404
53405
53406
53407
53408
53409
  pCur->validNKey = 0;
  if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }
  return SQLITE_OK;
}

#ifndef NDEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function 
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
** the page.
*/







|







53463
53464
53465
53466
53467
53468
53469
53470
53471
53472
53473
53474
53475
53476
53477
  pCur->validNKey = 0;
  if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }
  return SQLITE_OK;
}

#if 0
/*
** Page pParent is an internal (non-leaf) tree page. This function 
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
** the page.
*/
53428
53429
53430
53431
53432
53433
53434







53435
53436
53437
53438
53439



53440
53441
53442
53443
53444
53445
53446
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage>0 );
  assert( pCur->apPage[pCur->iPage] );







  assertParentIndex(
    pCur->apPage[pCur->iPage-1], 
    pCur->aiIdx[pCur->iPage-1], 
    pCur->apPage[pCur->iPage]->pgno
  );



  releasePage(pCur->apPage[pCur->iPage]);
  pCur->iPage--;
  pCur->info.nSize = 0;
  pCur->validNKey = 0;
}

/*







>
>
>
>
>
>
>





>
>
>







53496
53497
53498
53499
53500
53501
53502
53503
53504
53505
53506
53507
53508
53509
53510
53511
53512
53513
53514
53515
53516
53517
53518
53519
53520
53521
53522
53523
53524
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage>0 );
  assert( pCur->apPage[pCur->iPage] );

  /* UPDATE: It is actually possible for the condition tested by the assert
  ** below to be untrue if the database file is corrupt. This can occur if
  ** one cursor has modified page pParent while a reference to it is held 
  ** by a second cursor. Which can only happen if a single page is linked
  ** into more than one b-tree structure in a corrupt database.  */
#if 0
  assertParentIndex(
    pCur->apPage[pCur->iPage-1], 
    pCur->aiIdx[pCur->iPage-1], 
    pCur->apPage[pCur->iPage]->pgno
  );
#endif
  testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );

  releasePage(pCur->apPage[pCur->iPage]);
  pCur->iPage--;
  pCur->info.nSize = 0;
  pCur->validNKey = 0;
}

/*
53902
53903
53904
53905
53906
53907
53908






53909
53910
53911
53912
53913
53914
53915
53916
    return SQLITE_OK;
  }
  pCur->skipNext = 0;

  pPage = pCur->apPage[pCur->iPage];
  idx = ++pCur->aiIdx[pCur->iPage];
  assert( pPage->isInit );






  assert( idx<=pPage->nCell );

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ) return rc;







>
>
>
>
>
>
|







53980
53981
53982
53983
53984
53985
53986
53987
53988
53989
53990
53991
53992
53993
53994
53995
53996
53997
53998
53999
54000
    return SQLITE_OK;
  }
  pCur->skipNext = 0;

  pPage = pCur->apPage[pCur->iPage];
  idx = ++pCur->aiIdx[pCur->iPage];
  assert( pPage->isInit );

  /* If the database file is corrupt, it is possible for the value of idx 
  ** to be invalid here. This can only occur if a second cursor modifies
  ** the page while cursor pCur is holding a reference to it. Which can
  ** only happen if the database is corrupt in such a way as to link the
  ** page into more than one b-tree structure. */
  testcase( idx>pPage->nCell );

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ) return rc;
54712
54713
54714
54715
54716
54717
54718
54719
54720
54721
54722
54723
54724
54725
54726
/*
** Insert a new cell on pPage at cell index "i".  pCell points to the
** content of the cell.
**
** If the cell content will fit on the page, then put it there.  If it
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null.  Regardless of pTemp, allocate a new entry
** in pPage->aOvfl[] and make it point to the cell content (either
** in pTemp or the original pCell) and also record its index. 
** Allocating a new entry in pPage->aCell[] implies that 
** pPage->nOverflow is incremented.
**
** If nSkip is non-zero, then do not copy the first nSkip bytes of the
** cell. The caller will overwrite them after this function returns. If
** nSkip is non-zero, then pCell may not point to an invalid memory location 







|







54796
54797
54798
54799
54800
54801
54802
54803
54804
54805
54806
54807
54808
54809
54810
/*
** Insert a new cell on pPage at cell index "i".  pCell points to the
** content of the cell.
**
** If the cell content will fit on the page, then put it there.  If it
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null.  Regardless of pTemp, allocate a new entry
** in pPage->apOvfl[] and make it point to the cell content (either
** in pTemp or the original pCell) and also record its index. 
** Allocating a new entry in pPage->aCell[] implies that 
** pPage->nOverflow is incremented.
**
** If nSkip is non-zero, then do not copy the first nSkip bytes of the
** cell. The caller will overwrite them after this function returns. If
** nSkip is non-zero, then pCell may not point to an invalid memory location 
54746
54747
54748
54749
54750
54751
54752
54753

54754
54755
54756
54757
54758
54759
54760
54761
54762
54763
54764
54765
54766
54767
54768
54769
54770
54771
54772
54773
54774
54775
54776
54777
54778
54779

  int nSkip = (iChild ? 4 : 0);

  if( *pRC ) return;

  assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
  assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 );
  assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) );

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  /* The cell should normally be sized correctly.  However, when moving a
  ** malformed cell from a leaf page to an interior page, if the cell size
  ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
  ** might be less than 8 (leaf-size + pointer) on the interior node.  Hence
  ** the term after the || in the following assert(). */
  assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
  if( pPage->nOverflow || sz+2>pPage->nFree ){
    if( pTemp ){
      memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
      pCell = pTemp;
    }
    if( iChild ){
      put4byte(pCell, iChild);
    }
    j = pPage->nOverflow++;
    assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) );
    pPage->aOvfl[j].pCell = pCell;
    pPage->aOvfl[j].idx = (u16)i;
  }else{
    int rc = sqlite3PagerWrite(pPage->pDbPage);
    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
    }
    assert( sqlite3PagerIswriteable(pPage->pDbPage) );







|
>
















|
|
|







54830
54831
54832
54833
54834
54835
54836
54837
54838
54839
54840
54841
54842
54843
54844
54845
54846
54847
54848
54849
54850
54851
54852
54853
54854
54855
54856
54857
54858
54859
54860
54861
54862
54863
54864

  int nSkip = (iChild ? 4 : 0);

  if( *pRC ) return;

  assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
  assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 );
  assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
  assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  /* The cell should normally be sized correctly.  However, when moving a
  ** malformed cell from a leaf page to an interior page, if the cell size
  ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
  ** might be less than 8 (leaf-size + pointer) on the interior node.  Hence
  ** the term after the || in the following assert(). */
  assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
  if( pPage->nOverflow || sz+2>pPage->nFree ){
    if( pTemp ){
      memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
      pCell = pTemp;
    }
    if( iChild ){
      put4byte(pCell, iChild);
    }
    j = pPage->nOverflow++;
    assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
    pPage->apOvfl[j] = pCell;
    pPage->aiOvfl[j] = (u16)i;
  }else{
    int rc = sqlite3PagerWrite(pPage->pDbPage);
    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
    }
    assert( sqlite3PagerIswriteable(pPage->pDbPage) );
54913
54914
54915
54916
54917
54918
54919
54920
54921
54922
54923
54924
54925
54926
54927
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

  if( rc==SQLITE_OK ){

    u8 *pOut = &pSpace[4];
    u8 *pCell = pPage->aOvfl[0].pCell;
    u16 szCell = cellSizePtr(pPage, pCell);
    u8 *pStop;

    assert( sqlite3PagerIswriteable(pNew->pDbPage) );
    assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
    zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
    assemblePage(pNew, 1, &pCell, &szCell);







|







54998
54999
55000
55001
55002
55003
55004
55005
55006
55007
55008
55009
55010
55011
55012
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

  if( rc==SQLITE_OK ){

    u8 *pOut = &pSpace[4];
    u8 *pCell = pPage->apOvfl[0];
    u16 szCell = cellSizePtr(pPage, pCell);
    u8 *pStop;

    assert( sqlite3PagerIswriteable(pNew->pDbPage) );
    assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
    zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
    assemblePage(pNew, 1, &pCell, &szCell);
55023
55024
55025
55026
55027
55028
55029
55030
55031
55032
55033
55034
55035
55036
55037
** on page pFrom to page pTo. If page pFrom was not a leaf page, then
** the pointer-map entries for each child page are updated so that the
** parent page stored in the pointer map is page pTo. If pFrom contained
** any cells with overflow page pointers, then the corresponding pointer
** map entries are also updated so that the parent page is page pTo.
**
** If pFrom is currently carrying any overflow cells (entries in the
** MemPage.aOvfl[] array), they are not copied to pTo. 
**
** Before returning, page pTo is reinitialized using btreeInitPage().
**
** The performance of this function is not critical. It is only used by 
** the balance_shallower() and balance_deeper() procedures, neither of
** which are called often under normal circumstances.
*/







|







55108
55109
55110
55111
55112
55113
55114
55115
55116
55117
55118
55119
55120
55121
55122
** on page pFrom to page pTo. If page pFrom was not a leaf page, then
** the pointer-map entries for each child page are updated so that the
** parent page stored in the pointer map is page pTo. If pFrom contained
** any cells with overflow page pointers, then the corresponding pointer
** map entries are also updated so that the parent page is page pTo.
**
** If pFrom is currently carrying any overflow cells (entries in the
** MemPage.apOvfl[] array), they are not copied to pTo. 
**
** Before returning, page pTo is reinitialized using btreeInitPage().
**
** The performance of this function is not critical. It is only used by 
** the balance_shallower() and balance_deeper() procedures, neither of
** which are called often under normal circumstances.
*/
55160
55161
55162
55163
55164
55165
55166
55167
55168
55169
55170
55171
55172
55173
55174

  /* At this point pParent may have at most one overflow cell. And if
  ** this overflow cell is present, it must be the cell with 
  ** index iParentIdx. This scenario comes about when this function
  ** is called (indirectly) from sqlite3BtreeDelete().
  */
  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
  assert( pParent->nOverflow==0 || pParent->aOvfl[0].idx==iParentIdx );

  if( !aOvflSpace ){
    return SQLITE_NOMEM;
  }

  /* Find the sibling pages to balance. Also locate the cells in pParent 
  ** that divide the siblings. An attempt is made to find NN siblings on 







|







55245
55246
55247
55248
55249
55250
55251
55252
55253
55254
55255
55256
55257
55258
55259

  /* At this point pParent may have at most one overflow cell. And if
  ** this overflow cell is present, it must be the cell with 
  ** index iParentIdx. This scenario comes about when this function
  ** is called (indirectly) from sqlite3BtreeDelete().
  */
  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
  assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );

  if( !aOvflSpace ){
    return SQLITE_NOMEM;
  }

  /* Find the sibling pages to balance. Also locate the cells in pParent 
  ** that divide the siblings. An attempt is made to find NN siblings on 
55207
55208
55209
55210
55211
55212
55213
55214
55215
55216
55217
55218
55219
55220
55221
55222
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

    if( i+nxDiv==pParent->aOvfl[0].idx && pParent->nOverflow ){
      apDiv[i] = pParent->aOvfl[0].pCell;
      pgno = get4byte(apDiv[i]);
      szNew[i] = cellSizePtr(pParent, apDiv[i]);
      pParent->nOverflow = 0;
    }else{
      apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
      pgno = get4byte(apDiv[i]);
      szNew[i] = cellSizePtr(pParent, apDiv[i]);







|
|







55292
55293
55294
55295
55296
55297
55298
55299
55300
55301
55302
55303
55304
55305
55306
55307
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

    if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
      apDiv[i] = pParent->apOvfl[0];
      pgno = get4byte(apDiv[i]);
      szNew[i] = cellSizePtr(pParent, apDiv[i]);
      pParent->nOverflow = 0;
    }else{
      apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
      pgno = get4byte(apDiv[i]);
      szNew[i] = cellSizePtr(pParent, apDiv[i]);
55649
55650
55651
55652
55653
55654
55655
55656
55657
55658
55659
55660
55661
55662
55663
55664
55665
55666
55667
55668
55669
55670
55671
55672
55673
55674
55675
55676
55677
55678
55679
55680
55681
55682
55683
55684
    ** setting a pointer map entry is a relatively expensive operation, this
    ** code only sets pointer map entries for child or overflow pages that have
    ** actually moved between pages.  */
    MemPage *pNew = apNew[0];
    MemPage *pOld = apCopy[0];
    int nOverflow = pOld->nOverflow;
    int iNextOld = pOld->nCell + nOverflow;
    int iOverflow = (nOverflow ? pOld->aOvfl[0].idx : -1);
    j = 0;                             /* Current 'old' sibling page */
    k = 0;                             /* Current 'new' sibling page */
    for(i=0; i<nCell; i++){
      int isDivider = 0;
      while( i==iNextOld ){
        /* Cell i is the cell immediately following the last cell on old
        ** sibling page j. If the siblings are not leaf pages of an
        ** intkey b-tree, then cell i was a divider cell. */
        assert( j+1 < ArraySize(apCopy) );
        pOld = apCopy[++j];
        iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
        if( pOld->nOverflow ){
          nOverflow = pOld->nOverflow;
          iOverflow = i + !leafData + pOld->aOvfl[0].idx;
        }
        isDivider = !leafData;  
      }

      assert(nOverflow>0 || iOverflow<i );
      assert(nOverflow<2 || pOld->aOvfl[0].idx==pOld->aOvfl[1].idx-1);
      assert(nOverflow<3 || pOld->aOvfl[1].idx==pOld->aOvfl[2].idx-1);
      if( i==iOverflow ){
        isDivider = 1;
        if( (--nOverflow)>0 ){
          iOverflow++;
        }
      }








|













|





|
|







55734
55735
55736
55737
55738
55739
55740
55741
55742
55743
55744
55745
55746
55747
55748
55749
55750
55751
55752
55753
55754
55755
55756
55757
55758
55759
55760
55761
55762
55763
55764
55765
55766
55767
55768
55769
    ** setting a pointer map entry is a relatively expensive operation, this
    ** code only sets pointer map entries for child or overflow pages that have
    ** actually moved between pages.  */
    MemPage *pNew = apNew[0];
    MemPage *pOld = apCopy[0];
    int nOverflow = pOld->nOverflow;
    int iNextOld = pOld->nCell + nOverflow;
    int iOverflow = (nOverflow ? pOld->aiOvfl[0] : -1);
    j = 0;                             /* Current 'old' sibling page */
    k = 0;                             /* Current 'new' sibling page */
    for(i=0; i<nCell; i++){
      int isDivider = 0;
      while( i==iNextOld ){
        /* Cell i is the cell immediately following the last cell on old
        ** sibling page j. If the siblings are not leaf pages of an
        ** intkey b-tree, then cell i was a divider cell. */
        assert( j+1 < ArraySize(apCopy) );
        pOld = apCopy[++j];
        iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
        if( pOld->nOverflow ){
          nOverflow = pOld->nOverflow;
          iOverflow = i + !leafData + pOld->aiOvfl[0];
        }
        isDivider = !leafData;  
      }

      assert(nOverflow>0 || iOverflow<i );
      assert(nOverflow<2 || pOld->aiOvfl[0]==pOld->aiOvfl[1]-1);
      assert(nOverflow<3 || pOld->aiOvfl[1]==pOld->aiOvfl[2]-1);
      if( i==iOverflow ){
        isDivider = 1;
        if( (--nOverflow)>0 ){
          iOverflow++;
        }
      }

55791
55792
55793
55794
55795
55796
55797

55798


55799
55800
55801
55802
55803
55804
55805
  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  assert( pChild->nCell==pRoot->nCell );

  TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));

  /* Copy the overflow cells from pRoot to pChild */

  memcpy(pChild->aOvfl, pRoot->aOvfl, pRoot->nOverflow*sizeof(pRoot->aOvfl[0]));


  pChild->nOverflow = pRoot->nOverflow;

  /* Zero the contents of pRoot. Then install pChild as the right-child. */
  zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
  put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);

  *ppChild = pChild;







>
|
>
>







55876
55877
55878
55879
55880
55881
55882
55883
55884
55885
55886
55887
55888
55889
55890
55891
55892
55893
  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  assert( pChild->nCell==pRoot->nCell );

  TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));

  /* Copy the overflow cells from pRoot to pChild */
  memcpy(pChild->aiOvfl, pRoot->aiOvfl,
         pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
  memcpy(pChild->apOvfl, pRoot->apOvfl,
         pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
  pChild->nOverflow = pRoot->nOverflow;

  /* Zero the contents of pRoot. Then install pChild as the right-child. */
  zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
  put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);

  *ppChild = pChild;
55854
55855
55856
55857
55858
55859
55860
55861
55862
55863
55864
55865
55866
55867
55868
      int const iIdx = pCur->aiIdx[iPage-1];

      rc = sqlite3PagerWrite(pParent->pDbPage);
      if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
        if( pPage->hasData
         && pPage->nOverflow==1
         && pPage->aOvfl[0].idx==pPage->nCell
         && pParent->pgno!=1
         && pParent->nCell==iIdx
        ){
          /* Call balance_quick() to create a new sibling of pPage on which
          ** to store the overflow cell. balance_quick() inserts a new cell
          ** into pParent, which may cause pParent overflow. If this
          ** happens, the next interation of the do-loop will balance pParent 







|







55942
55943
55944
55945
55946
55947
55948
55949
55950
55951
55952
55953
55954
55955
55956
      int const iIdx = pCur->aiIdx[iPage-1];

      rc = sqlite3PagerWrite(pParent->pDbPage);
      if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
        if( pPage->hasData
         && pPage->nOverflow==1
         && pPage->aiOvfl[0]==pPage->nCell
         && pParent->pgno!=1
         && pParent->nCell==iIdx
        ){
          /* Call balance_quick() to create a new sibling of pPage on which
          ** to store the overflow cell. balance_quick() inserts a new cell
          ** into pParent, which may cause pParent overflow. If this
          ** happens, the next interation of the do-loop will balance pParent 
58275
58276
58277
58278
58279
58280
58281

58282
58283
58284
58285
58286
58287
58288
    }
  }

  if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
    memcpy(pMem->zMalloc, pMem->z, pMem->n);
  }
  if( pMem->flags&MEM_Dyn && pMem->xDel ){

    pMem->xDel((void *)(pMem->z));
  }

  pMem->z = pMem->zMalloc;
  if( pMem->z==0 ){
    pMem->flags = MEM_Null;
  }else{







>







58363
58364
58365
58366
58367
58368
58369
58370
58371
58372
58373
58374
58375
58376
58377
    }
  }

  if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
    memcpy(pMem->zMalloc, pMem->z, pMem->n);
  }
  if( pMem->flags&MEM_Dyn && pMem->xDel ){
    assert( pMem->xDel!=SQLITE_DYNAMIC );
    pMem->xDel((void *)(pMem->z));
  }

  pMem->z = pMem->zMalloc;
  if( pMem->z==0 ){
    pMem->flags = MEM_Null;
  }else{
58454
58455
58456
58457
58458
58459
58460

58461
58462
58463
58464
58465
58466
58467
  assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
  if( p->flags&MEM_Agg ){
    sqlite3VdbeMemFinalize(p, p->u.pDef);
    assert( (p->flags & MEM_Agg)==0 );
    sqlite3VdbeMemRelease(p);
  }else if( p->flags&MEM_Dyn && p->xDel ){
    assert( (p->flags&MEM_RowSet)==0 );

    p->xDel((void *)p->z);
    p->xDel = 0;
  }else if( p->flags&MEM_RowSet ){
    sqlite3RowSetClear(p->u.pRowSet);
  }else if( p->flags&MEM_Frame ){
    sqlite3VdbeMemSetNull(p);
  }







>







58543
58544
58545
58546
58547
58548
58549
58550
58551
58552
58553
58554
58555
58556
58557
  assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
  if( p->flags&MEM_Agg ){
    sqlite3VdbeMemFinalize(p, p->u.pDef);
    assert( (p->flags & MEM_Agg)==0 );
    sqlite3VdbeMemRelease(p);
  }else if( p->flags&MEM_Dyn && p->xDel ){
    assert( (p->flags&MEM_RowSet)==0 );
    assert( p->xDel!=SQLITE_DYNAMIC );
    p->xDel((void *)p->z);
    p->xDel = 0;
  }else if( p->flags&MEM_RowSet ){
    sqlite3RowSetClear(p->u.pRowSet);
  }else if( p->flags&MEM_Frame ){
    sqlite3VdbeMemSetNull(p);
  }
58596
58597
58598
58599
58600
58601
58602
58603


58604




58605
58606
58607
58608
58609
58610
58611
  **
  ** The second and third terms in the following conditional enforces
  ** the second condition under the assumption that addition overflow causes
  ** values to wrap around.  On x86 hardware, the third term is always
  ** true and could be omitted.  But we leave it in because other
  ** architectures might behave differently.
  */
  if( pMem->r==(double)pMem->u.i && pMem->u.i>SMALLEST_INT64


      && ALWAYS(pMem->u.i<LARGEST_INT64) ){




    pMem->flags |= MEM_Int;
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/







|
>
>
|
>
>
>
>







58686
58687
58688
58689
58690
58691
58692
58693
58694
58695
58696
58697
58698
58699
58700
58701
58702
58703
58704
58705
58706
58707
  **
  ** The second and third terms in the following conditional enforces
  ** the second condition under the assumption that addition overflow causes
  ** values to wrap around.  On x86 hardware, the third term is always
  ** true and could be omitted.  But we leave it in because other
  ** architectures might behave differently.
  */
  if( pMem->r==(double)pMem->u.i
   && pMem->u.i>SMALLEST_INT64
#if defined(__i486__) || defined(__x86_64__)
   && ALWAYS(pMem->u.i<LARGEST_INT64)
#else
   && pMem->u.i<LARGEST_INT64
#endif
  ){
    pMem->flags |= MEM_Int;
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
59571
59572
59573
59574
59575
59576
59577
59578
59579
59580
59581
59582
59583
59584
59585
59586
59587
59588
59589
59590
59591
59592
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
**
** Zero is returned if a malloc() fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
  int i;
  i = p->nLabel++;
  assert( p->magic==VDBE_MAGIC_INIT );
  if( i>=p->nLabelAlloc ){
    int n = p->nLabelAlloc*2 + 5;
    p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
                                       n*sizeof(p->aLabel[0]));
    p->nLabelAlloc = sqlite3DbMallocSize(p->db, p->aLabel)/sizeof(p->aLabel[0]);
  }
  if( p->aLabel ){
    p->aLabel[i] = -1;
  }
  return -1-i;
}








<
|

|
<
|
|
<







59667
59668
59669
59670
59671
59672
59673

59674
59675
59676

59677
59678

59679
59680
59681
59682
59683
59684
59685
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
**
** Zero is returned if a malloc() fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){

  int i = p->nLabel++;
  assert( p->magic==VDBE_MAGIC_INIT );
  if( (i & (i-1))==0 ){

    p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, 
                                       (i*2+1)*sizeof(p->aLabel[0]));

  }
  if( p->aLabel ){
    p->aLabel[i] = -1;
  }
  return -1-i;
}

61623
61624
61625
61626
61627
61628
61629
61630
61631
61632
61633
61634
61635
61636
61637
61638
61639
61640
61641
61642
      if( eStatementOp!=SAVEPOINT_ROLLBACK ){
        sqlite3VdbeSetChanges(db, p->nChange);
      }else{
        sqlite3VdbeSetChanges(db, 0);
      }
      p->nChange = 0;
    }
  
    /* Rollback or commit any schema changes that occurred. */
    if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){
      sqlite3ResetInternalSchema(db, -1);
      db->flags = (db->flags | SQLITE_InternChanges);
    }

    /* Release the locks */
    sqlite3VdbeLeave(p);
  }

  /* We have successfully halted and closed the VM.  Record this fact. */
  if( p->pc>=0 ){







<
<
<
<
<
<







61716
61717
61718
61719
61720
61721
61722






61723
61724
61725
61726
61727
61728
61729
      if( eStatementOp!=SAVEPOINT_ROLLBACK ){
        sqlite3VdbeSetChanges(db, p->nChange);
      }else{
        sqlite3VdbeSetChanges(db, 0);
      }
      p->nChange = 0;
    }







    /* Release the locks */
    sqlite3VdbeLeave(p);
  }

  /* We have successfully halted and closed the VM.  Record this fact. */
  if( p->pc>=0 ){
66049
66050
66051
66052
66053
66054
66055
66056
66057
66058
66059
66060
66061




66062
66063
66064
66065
66066
66067
66068



66069
66070
66071
66072
66073
66074
66075
  break;

arithmetic_result_is_null:
  sqlite3VdbeMemSetNull(pOut);
  break;
}

/* Opcode: CollSeq * * P4
**
** P4 is a pointer to a CollSeq struct. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
** functions.




**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
** publicly, only to user functions defined in func.c.
*/
case OP_CollSeq: {
  assert( pOp->p4type==P4_COLLSEQ );



  break;
}

/* Opcode: Function P1 P2 P3 P4 P5
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and







|





>
>
>
>







>
>
>







66136
66137
66138
66139
66140
66141
66142
66143
66144
66145
66146
66147
66148
66149
66150
66151
66152
66153
66154
66155
66156
66157
66158
66159
66160
66161
66162
66163
66164
66165
66166
66167
66168
66169
  break;

arithmetic_result_is_null:
  sqlite3VdbeMemSetNull(pOut);
  break;
}

/* Opcode: CollSeq P1 * * P4
**
** P4 is a pointer to a CollSeq struct. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
** functions.
**
** If P1 is not zero, then it is a register that a subsequent min() or
** max() aggregate will set to 1 if the current row is not the minimum or
** maximum.  The P1 register is initialized to 0 by this instruction.
**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
** publicly, only to user functions defined in func.c.
*/
case OP_CollSeq: {
  assert( pOp->p4type==P4_COLLSEQ );
  if( pOp->p1 ){
    sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
  }
  break;
}

/* Opcode: Function P1 P2 P3 P4 P5
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and
67595
67596
67597
67598
67599
67600
67601
67602
67603
67604
67605
67606
67607
67608
67609
** on the file.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
** throw an ABORT exception), a statement transaction may also be opened.
** More specifically, a statement transaction is opened iff the database
** connection is currently not in autocommit mode, or if there are other
** active statements. A statement transaction allows the affects of this
** VDBE to be rolled back after an error without having to roll back the
** entire transaction. If no error is encountered, the statement transaction
** will automatically commit when the VDBE halts.
**
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {







|







67689
67690
67691
67692
67693
67694
67695
67696
67697
67698
67699
67700
67701
67702
67703
** on the file.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
** throw an ABORT exception), a statement transaction may also be opened.
** More specifically, a statement transaction is opened iff the database
** connection is currently not in autocommit mode, or if there are other
** active statements. A statement transaction allows the changes made by this
** VDBE to be rolled back after an error without having to roll back the
** entire transaction. If no error is encountered, the statement transaction
** will automatically commit when the VDBE halts.
**
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {
69639
69640
69641
69642
69643
69644
69645

69646
69647
69648
69649
69650
69651
69652
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
      if( rc==SQLITE_OK ) rc = u.by.initData.rc;
      sqlite3DbFree(db, u.by.zSql);
      db->init.busy = 0;
    }
  }

  if( rc==SQLITE_NOMEM ){
    goto no_mem;
  }
  break;
}

#if !defined(SQLITE_OMIT_ANALYZE)







>







69733
69734
69735
69736
69737
69738
69739
69740
69741
69742
69743
69744
69745
69746
69747
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
      if( rc==SQLITE_OK ) rc = u.by.initData.rc;
      sqlite3DbFree(db, u.by.zSql);
      db->init.busy = 0;
    }
  }
  if( rc ) sqlite3ResetInternalSchema(db, -1);
  if( rc==SQLITE_NOMEM ){
    goto no_mem;
  }
  break;
}

#if !defined(SQLITE_OMIT_ANALYZE)
69981
69982
69983
69984
69985
69986
69987
69988
69989
69990
69991
69992
69993
69994
69995
  p->nMem = u.cc.pFrame->nChildMem;
  p->nCursor = (u16)u.cc.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = u.cc.pProgram->aOp;
  p->nOp = u.cc.pProgram->nOp;
  p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
  p->nOnceFlag = u.cc.pProgram->nOnce;
  p->nOp = u.cc.pProgram->nOp;
  pc = -1;
  memset(p->aOnceFlag, 0, p->nOnceFlag);

  break;
}

/* Opcode: Param P1 P2 * * *







<







70076
70077
70078
70079
70080
70081
70082

70083
70084
70085
70086
70087
70088
70089
  p->nMem = u.cc.pFrame->nChildMem;
  p->nCursor = (u16)u.cc.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = u.cc.pProgram->aOp;
  p->nOp = u.cc.pProgram->nOp;
  p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
  p->nOnceFlag = u.cc.pProgram->nOnce;

  pc = -1;
  memset(p->aOnceFlag, 0, p->nOnceFlag);

  break;
}

/* Opcode: Param P1 P2 * * *
70176
70177
70178
70179
70180
70181
70182

70183
70184
70185
70186
70187
70188
70189
70190
70191
70192
70193





70194
70195
70196
70197
70198
70199
70200
  u.cf.ctx.s.flags = MEM_Null;
  u.cf.ctx.s.z = 0;
  u.cf.ctx.s.zMalloc = 0;
  u.cf.ctx.s.xDel = 0;
  u.cf.ctx.s.db = db;
  u.cf.ctx.isError = 0;
  u.cf.ctx.pColl = 0;

  if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>p->aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.cf.ctx.pColl = pOp[-1].p4.pColl;
  }
  (u.cf.ctx.pFunc->xStep)(&u.cf.ctx, u.cf.n, u.cf.apVal); /* IMP: R-24505-23230 */
  if( u.cf.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s));
    rc = u.cf.ctx.isError;
  }






  sqlite3VdbeMemRelease(&u.cf.ctx.s);

  break;
}

/* Opcode: AggFinal P1 P2 * P4 *







>











>
>
>
>
>







70270
70271
70272
70273
70274
70275
70276
70277
70278
70279
70280
70281
70282
70283
70284
70285
70286
70287
70288
70289
70290
70291
70292
70293
70294
70295
70296
70297
70298
70299
70300
  u.cf.ctx.s.flags = MEM_Null;
  u.cf.ctx.s.z = 0;
  u.cf.ctx.s.zMalloc = 0;
  u.cf.ctx.s.xDel = 0;
  u.cf.ctx.s.db = db;
  u.cf.ctx.isError = 0;
  u.cf.ctx.pColl = 0;
  u.cf.ctx.skipFlag = 0;
  if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>p->aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.cf.ctx.pColl = pOp[-1].p4.pColl;
  }
  (u.cf.ctx.pFunc->xStep)(&u.cf.ctx, u.cf.n, u.cf.apVal); /* IMP: R-24505-23230 */
  if( u.cf.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s));
    rc = u.cf.ctx.isError;
  }
  if( u.cf.ctx.skipFlag ){
    assert( pOp[-1].opcode==OP_CollSeq );
    u.cf.i = pOp[-1].p1;
    if( u.cf.i ) sqlite3VdbeMemSetInt64(&aMem[u.cf.i], 1);
  }

  sqlite3VdbeMemRelease(&u.cf.ctx.s);

  break;
}

/* Opcode: AggFinal P1 P2 * P4 *
71580
71581
71582
71583
71584
71585
71586


71587
71588



71589
71590
71591
71592
71593
71594
71595
71596
71597
71598
71599
71600
71601
71602
71603
71604
71605
71606
71607
71608
71609
71610
71611


71612
71613
71614
71615
71616
71617
71618
**     aTree[] = { X, 0   0, 6    0, 3, 5, 6 }
**
** In other words, each time we advance to the next sorter element, log2(N)
** key comparison operations are required, where N is the number of segments
** being merged (rounded up to the next power of 2).
*/
struct VdbeSorter {


  int nInMemory;                  /* Current size of pRecord list as PMA */
  int nTree;                      /* Used size of aTree/aIter (power of 2) */



  VdbeSorterIter *aIter;          /* Array of iterators to merge */
  int *aTree;                     /* Current state of incremental merge */
  i64 iWriteOff;                  /* Current write offset within file pTemp1 */
  i64 iReadOff;                   /* Current read offset within file pTemp1 */
  sqlite3_file *pTemp1;           /* PMA file 1 */
  int nPMA;                       /* Number of PMAs stored in pTemp1 */
  SorterRecord *pRecord;          /* Head of in-memory record list */
  int mnPmaSize;                  /* Minimum PMA size, in bytes */
  int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
  UnpackedRecord *pUnpacked;      /* Used to unpack keys */
};

/*
** The following type is an iterator for a PMA. It caches the current key in 
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
*/
struct VdbeSorterIter {
  i64 iReadOff;                   /* Current read offset */
  i64 iEof;                       /* 1 byte past EOF for this iterator */
  sqlite3_file *pFile;            /* File iterator is reading from */
  int nAlloc;                     /* Bytes of space at aAlloc */
  u8 *aAlloc;                     /* Allocated space */
  int nKey;                       /* Number of bytes in key */


  u8 *aKey;                       /* Pointer to current key */
};

/*
** A structure to store a single record. All in-memory records are connected
** together into a linked list headed at VdbeSorter.pRecord using the 
** SorterRecord.pNext pointer.







>
>


>
>
>


<
<

<

<
<










<

<

>
>







71680
71681
71682
71683
71684
71685
71686
71687
71688
71689
71690
71691
71692
71693
71694
71695


71696

71697


71698
71699
71700
71701
71702
71703
71704
71705
71706
71707

71708

71709
71710
71711
71712
71713
71714
71715
71716
71717
71718
**     aTree[] = { X, 0   0, 6    0, 3, 5, 6 }
**
** In other words, each time we advance to the next sorter element, log2(N)
** key comparison operations are required, where N is the number of segments
** being merged (rounded up to the next power of 2).
*/
struct VdbeSorter {
  i64 iWriteOff;                  /* Current write offset within file pTemp1 */
  i64 iReadOff;                   /* Current read offset within file pTemp1 */
  int nInMemory;                  /* Current size of pRecord list as PMA */
  int nTree;                      /* Used size of aTree/aIter (power of 2) */
  int nPMA;                       /* Number of PMAs stored in pTemp1 */
  int mnPmaSize;                  /* Minimum PMA size, in bytes */
  int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
  VdbeSorterIter *aIter;          /* Array of iterators to merge */
  int *aTree;                     /* Current state of incremental merge */


  sqlite3_file *pTemp1;           /* PMA file 1 */

  SorterRecord *pRecord;          /* Head of in-memory record list */


  UnpackedRecord *pUnpacked;      /* Used to unpack keys */
};

/*
** The following type is an iterator for a PMA. It caches the current key in 
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
*/
struct VdbeSorterIter {
  i64 iReadOff;                   /* Current read offset */
  i64 iEof;                       /* 1 byte past EOF for this iterator */

  int nAlloc;                     /* Bytes of space at aAlloc */

  int nKey;                       /* Number of bytes in key */
  sqlite3_file *pFile;            /* File iterator is reading from */
  u8 *aAlloc;                     /* Allocated space */
  u8 *aKey;                       /* Pointer to current key */
};

/*
** A structure to store a single record. All in-memory records are connected
** together into a linked list headed at VdbeSorter.pRecord using the 
** SorterRecord.pNext pointer.
75091
75092
75093
75094
75095
75096
75097
75098

75099
75100
75101
75102
75103
75104
75105
75106
  ExprList *pNew;
  struct ExprList_item *pItem, *pOldItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->iECursor = 0;
  pNew->nExpr = pNew->nAlloc = p->nExpr;

  pNew->a = pItem = sqlite3DbMallocRaw(db,  p->nExpr*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  } 
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;







|
>
|







75191
75192
75193
75194
75195
75196
75197
75198
75199
75200
75201
75202
75203
75204
75205
75206
75207
  ExprList *pNew;
  struct ExprList_item *pItem, *pOldItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->iECursor = 0;
  pNew->nExpr = i = p->nExpr;
  if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
  pNew->a = pItem = sqlite3DbMallocRaw(db,  i*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  } 
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
75160
75161
75162
75163
75164
75165
75166
75167
75168
75169
75170
75171
75172



75173
75174
75175
75176
75177
75178
75179
}
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
  IdList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nId = pNew->nAlloc = p->nId;
  pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
  if( pNew->a==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  }



  for(i=0; i<p->nId; i++){
    struct IdList_item *pNewItem = &pNew->a[i];
    struct IdList_item *pOldItem = &p->a[i];
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->idx = pOldItem->idx;
  }
  return pNew;







|





>
>
>







75261
75262
75263
75264
75265
75266
75267
75268
75269
75270
75271
75272
75273
75274
75275
75276
75277
75278
75279
75280
75281
75282
75283
}
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
  IdList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nId = p->nId;
  pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
  if( pNew->a==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  }
  /* Note that because the size of the allocation for p->a[] is not
  ** necessarily a power of two, sqlite3IdListAppend() may not be called
  ** on the duplicate created by this function. */
  for(i=0; i<p->nId; i++){
    struct IdList_item *pNewItem = &pNew->a[i];
    struct IdList_item *pOldItem = &p->a[i];
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->idx = pOldItem->idx;
  }
  return pNew;
75227
75228
75229
75230
75231
75232
75233

75234
75235
75236
75237
75238
75239
75240
75241
75242
75243
75244
75245
75246
75247
75248
75249
75250
75251
){
  sqlite3 *db = pParse->db;
  if( pList==0 ){
    pList = sqlite3DbMallocZero(db, sizeof(ExprList) );
    if( pList==0 ){
      goto no_mem;
    }

    assert( pList->nAlloc==0 );
  }
  if( pList->nAlloc<=pList->nExpr ){
    struct ExprList_item *a;
    int n = pList->nAlloc*2 + 4;
    a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0]));
    if( a==0 ){
      goto no_mem;
    }
    pList->a = a;
    pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]);
  }
  assert( pList->a!=0 );
  if( 1 ){
    struct ExprList_item *pItem = &pList->a[pList->nExpr++];
    memset(pItem, 0, sizeof(*pItem));
    pItem->pExpr = pExpr;
  }







>
|
<
|

|
|




<







75331
75332
75333
75334
75335
75336
75337
75338
75339

75340
75341
75342
75343
75344
75345
75346
75347

75348
75349
75350
75351
75352
75353
75354
){
  sqlite3 *db = pParse->db;
  if( pList==0 ){
    pList = sqlite3DbMallocZero(db, sizeof(ExprList) );
    if( pList==0 ){
      goto no_mem;
    }
    pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0]));
    if( pList->a==0 ) goto no_mem;

  }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
    struct ExprList_item *a;
    assert( pList->nExpr>0 );
    a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
    if( a==0 ){
      goto no_mem;
    }
    pList->a = a;

  }
  assert( pList->a!=0 );
  if( 1 ){
    struct ExprList_item *pItem = &pList->a[pList->nExpr++];
    memset(pItem, 0, sizeof(*pItem));
    pItem->pExpr = pExpr;
  }
75328
75329
75330
75331
75332
75333
75334
75335
75336
75337
75338
75339
75340
75341
75342
75343
/*
** Delete an entire expression list.
*/
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
  int i;
  struct ExprList_item *pItem;
  if( pList==0 ) return;
  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
  assert( pList->nExpr<=pList->nAlloc );
  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
    sqlite3ExprDelete(db, pItem->pExpr);
    sqlite3DbFree(db, pItem->zName);
    sqlite3DbFree(db, pItem->zSpan);
  }
  sqlite3DbFree(db, pList->a);
  sqlite3DbFree(db, pList);







|
<







75431
75432
75433
75434
75435
75436
75437
75438

75439
75440
75441
75442
75443
75444
75445
/*
** Delete an entire expression list.
*/
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
  int i;
  struct ExprList_item *pItem;
  if( pList==0 ) return;
  assert( pList->a!=0 || pList->nExpr==0 );

  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
    sqlite3ExprDelete(db, pItem->pExpr);
    sqlite3DbFree(db, pItem->zName);
    sqlite3DbFree(db, pItem->zSpan);
  }
  sqlite3DbFree(db, pList->a);
  sqlite3DbFree(db, pList);
78010
78011
78012
78013
78014
78015
78016
78017
78018
78019
78020
78021
78022
78023
78024
78025
78026
78027
78028
78029
78030
78031
78032
78033
78034
78035
78036
78037
78038
78039
78040
78041
78042
78043
78044
*/
static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
  int i;
  pInfo->aCol = sqlite3ArrayAllocate(
       db,
       pInfo->aCol,
       sizeof(pInfo->aCol[0]),
       3,
       &pInfo->nColumn,
       &pInfo->nColumnAlloc,
       &i
  );
  return i;
}    

/*
** Add a new element to the pAggInfo->aFunc[] array.  Return the index of
** the new element.  Return a negative number if malloc fails.
*/
static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
  int i;
  pInfo->aFunc = sqlite3ArrayAllocate(
       db, 
       pInfo->aFunc,
       sizeof(pInfo->aFunc[0]),
       3,
       &pInfo->nFunc,
       &pInfo->nFuncAlloc,
       &i
  );
  return i;
}    

/*
** This is the xExprCallback for a tree walker.  It is used to







<

<















<

<







78112
78113
78114
78115
78116
78117
78118

78119

78120
78121
78122
78123
78124
78125
78126
78127
78128
78129
78130
78131
78132
78133
78134

78135

78136
78137
78138
78139
78140
78141
78142
*/
static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
  int i;
  pInfo->aCol = sqlite3ArrayAllocate(
       db,
       pInfo->aCol,
       sizeof(pInfo->aCol[0]),

       &pInfo->nColumn,

       &i
  );
  return i;
}    

/*
** Add a new element to the pAggInfo->aFunc[] array.  Return the index of
** the new element.  Return a negative number if malloc fails.
*/
static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
  int i;
  pInfo->aFunc = sqlite3ArrayAllocate(
       db, 
       pInfo->aFunc,
       sizeof(pInfo->aFunc[0]),

       &pInfo->nFunc,

       &i
  );
  return i;
}    

/*
** This is the xExprCallback for a tree walker.  It is used to
78807
78808
78809
78810
78811
78812
78813
78814
78815
78816
78817
78818
78819
78820
78821
#endif
          "tbl_name = %Q, "
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
            "ELSE name END "
      "WHERE tbl_name=%Q AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, SCHEMA_TABLE(iDb), zName, zName, zName, 
#ifndef SQLITE_OMIT_TRIGGER
      zName,
#endif
      zName, nTabName, zTabName
  );







|







78905
78906
78907
78908
78909
78910
78911
78912
78913
78914
78915
78916
78917
78918
78919
#endif
          "tbl_name = %Q, "
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
            "ELSE name END "
      "WHERE tbl_name=%Q COLLATE nocase AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, SCHEMA_TABLE(iDb), zName, zName, zName, 
#ifndef SQLITE_OMIT_TRIGGER
      zName,
#endif
      zName, nTabName, zTabName
  );
82676
82677
82678
82679
82680
82681
82682
82683
82684
82685
82686
82687
82688
82689
82690
                             sqlite3Strlen30(p->zName),p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      db->mallocFailed = 1;
      return;
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE_InternChanges;

#ifndef SQLITE_OMIT_ALTERTABLE
    if( !p->pSelect ){
      const char *zName = (const char *)pParse->sNameToken.z;
      int nName;
      assert( !pSelect && pCons && pEnd );







<







82774
82775
82776
82777
82778
82779
82780

82781
82782
82783
82784
82785
82786
82787
                             sqlite3Strlen30(p->zName),p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      db->mallocFailed = 1;
      return;
    }
    pParse->pNewTable = 0;

    db->flags |= SQLITE_InternChanges;

#ifndef SQLITE_OMIT_ALTERTABLE
    if( !p->pSelect ){
      const char *zName = (const char *)pParse->sNameToken.z;
      int nName;
      assert( !pSelect && pCons && pEnd );
84097
84098
84099
84100
84101
84102
84103
84104
84105
84106
84107
84108
84109
84110
84111
84112
84113
84114
84115
84116
84117
84118
84119
84120
84121
84122
84123
84124
84125
84126
84127
84128
84129
84130
84131
84132
84133
84134
84135
84136
84137
84138
84139
84140
84141
84142
84143
84144
84145
84146
84147
84148
84149
84150
84151
84152
84153
84154
84155
** might be the same as the pArray parameter or it might be a different
** pointer if the array was resized.
*/
SQLITE_PRIVATE void *sqlite3ArrayAllocate(
  sqlite3 *db,      /* Connection to notify of malloc failures */
  void *pArray,     /* Array of objects.  Might be reallocated */
  int szEntry,      /* Size of each object in the array */
  int initSize,     /* Suggested initial allocation, in elements */
  int *pnEntry,     /* Number of objects currently in use */
  int *pnAlloc,     /* Current size of the allocation, in elements */
  int *pIdx         /* Write the index of a new slot here */
){
  char *z;
  if( *pnEntry >= *pnAlloc ){
    void *pNew;
    int newSize;
    newSize = (*pnAlloc)*2 + initSize;
    pNew = sqlite3DbRealloc(db, pArray, newSize*szEntry);
    if( pNew==0 ){
      *pIdx = -1;
      return pArray;
    }
    *pnAlloc = sqlite3DbMallocSize(db, pNew)/szEntry;
    pArray = pNew;
  }
  z = (char*)pArray;
  memset(&z[*pnEntry * szEntry], 0, szEntry);
  *pIdx = *pnEntry;
  ++*pnEntry;
  return pArray;
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
  int i;
  if( pList==0 ){
    pList = sqlite3DbMallocZero(db, sizeof(IdList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 0;
  }
  pList->a = sqlite3ArrayAllocate(
      db,
      pList->a,
      sizeof(pList->a[0]),
      5,
      &pList->nId,
      &pList->nAlloc,
      &i
  );
  if( i<0 ){
    sqlite3IdListDelete(db, pList);
    return 0;
  }
  pList->a[i].zName = sqlite3NameFromToken(db, pToken);







<

<



|
|
|
<
|




<



|
|















<





<

<







84194
84195
84196
84197
84198
84199
84200

84201

84202
84203
84204
84205
84206
84207

84208
84209
84210
84211
84212

84213
84214
84215
84216
84217
84218
84219
84220
84221
84222
84223
84224
84225
84226
84227
84228
84229
84230
84231
84232

84233
84234
84235
84236
84237

84238

84239
84240
84241
84242
84243
84244
84245
** might be the same as the pArray parameter or it might be a different
** pointer if the array was resized.
*/
SQLITE_PRIVATE void *sqlite3ArrayAllocate(
  sqlite3 *db,      /* Connection to notify of malloc failures */
  void *pArray,     /* Array of objects.  Might be reallocated */
  int szEntry,      /* Size of each object in the array */

  int *pnEntry,     /* Number of objects currently in use */

  int *pIdx         /* Write the index of a new slot here */
){
  char *z;
  int n = *pnEntry;
  if( (n & (n-1))==0 ){
    int sz = (n==0) ? 1 : 2*n;

    void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry);
    if( pNew==0 ){
      *pIdx = -1;
      return pArray;
    }

    pArray = pNew;
  }
  z = (char*)pArray;
  memset(&z[n * szEntry], 0, szEntry);
  *pIdx = n;
  ++*pnEntry;
  return pArray;
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
  int i;
  if( pList==0 ){
    pList = sqlite3DbMallocZero(db, sizeof(IdList) );
    if( pList==0 ) return 0;

  }
  pList->a = sqlite3ArrayAllocate(
      db,
      pList->a,
      sizeof(pList->a[0]),

      &pList->nId,

      &i
  );
  if( i<0 ){
    sqlite3IdListDelete(db, pList);
    return 0;
  }
  pList->a[i].zName = sqlite3NameFromToken(db, pToken);
86000
86001
86002
86003
86004
86005
86006








86007
86008
86009
86010
86011
86012
86013

/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
  return context->pColl;
}









/*
** Implementation of the non-aggregate min() and max() functions
*/
static void minmaxFunc(
  sqlite3_context *context,
  int argc,







>
>
>
>
>
>
>
>







86090
86091
86092
86093
86094
86095
86096
86097
86098
86099
86100
86101
86102
86103
86104
86105
86106
86107
86108
86109
86110
86111

/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
  return context->pColl;
}

/*
** Indicate that the accumulator load should be skipped on this
** iteration of the aggregate loop.
*/
static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
  context->skipFlag = 1;
}

/*
** Implementation of the non-aggregate min() and max() functions
*/
static void minmaxFunc(
  sqlite3_context *context,
  int argc,
86381
86382
86383
86384
86385
86386
86387
86388
86389
86390
86391
86392
86393
86394
86395
    ** (or -9223372036854775808) since when you do abs() of that
    ** number of you get the same value back again.  To do this
    ** in a way that is testable, mask the sign bit off of negative
    ** values, resulting in a positive value.  Then take the 
    ** 2s complement of that positive value.  The end result can
    ** therefore be no less than -9223372036854775807.
    */
    r = -(r ^ (((sqlite3_int64)1)<<63));
  }
  sqlite3_result_int64(context, r);
}

/*
** Implementation of randomblob(N).  Return a random blob
** that is N bytes long.







|







86479
86480
86481
86482
86483
86484
86485
86486
86487
86488
86489
86490
86491
86492
86493
    ** (or -9223372036854775808) since when you do abs() of that
    ** number of you get the same value back again.  To do this
    ** in a way that is testable, mask the sign bit off of negative
    ** values, resulting in a positive value.  Then take the 
    ** 2s complement of that positive value.  The end result can
    ** therefore be no less than -9223372036854775807.
    */
    r = -(r & LARGEST_INT64);
  }
  sqlite3_result_int64(context, r);
}

/*
** Implementation of randomblob(N).  Return a random blob
** that is N bytes long.
87307
87308
87309
87310
87311
87312
87313
87314
87315
87316
87317


87318
87319
87320
87321
87322
87323
87324
87325
87326
87327
87328
87329
87330
87331
87332
87333


87334
87335
87336
87337
87338
87339
87340
87341
87342
87343
87344
87345
87346
87347
87348
87349
87350
  int NotUsed, 
  sqlite3_value **argv
){
  Mem *pArg  = (Mem *)argv[0];
  Mem *pBest;
  UNUSED_PARAMETER(NotUsed);

  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
  if( !pBest ) return;



  if( pBest->flags ){
    int max;
    int cmp;
    CollSeq *pColl = sqlite3GetFuncCollSeq(context);
    /* This step function is used for both the min() and max() aggregates,
    ** the only difference between the two being that the sense of the
    ** comparison is inverted. For the max() aggregate, the
    ** sqlite3_user_data() function returns (void *)-1. For min() it
    ** returns (void *)db, where db is the sqlite3* database pointer.
    ** Therefore the next statement sets variable 'max' to 1 for the max()
    ** aggregate, or 0 for min().
    */
    max = sqlite3_user_data(context)!=0;
    cmp = sqlite3MemCompare(pBest, pArg, pColl);
    if( (max && cmp<0) || (!max && cmp>0) ){
      sqlite3VdbeMemCopy(pBest, pArg);


    }
  }else{
    sqlite3VdbeMemCopy(pBest, pArg);
  }
}
static void minMaxFinalize(sqlite3_context *context){
  sqlite3_value *pRes;
  pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
  if( pRes ){
    if( ALWAYS(pRes->flags) ){
      sqlite3_result_value(context, pRes);
    }
    sqlite3VdbeMemRelease(pRes);
  }
}

/*







<



>
>
|















>
>









|







87405
87406
87407
87408
87409
87410
87411

87412
87413
87414
87415
87416
87417
87418
87419
87420
87421
87422
87423
87424
87425
87426
87427
87428
87429
87430
87431
87432
87433
87434
87435
87436
87437
87438
87439
87440
87441
87442
87443
87444
87445
87446
87447
87448
87449
87450
87451
  int NotUsed, 
  sqlite3_value **argv
){
  Mem *pArg  = (Mem *)argv[0];
  Mem *pBest;
  UNUSED_PARAMETER(NotUsed);


  pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
  if( !pBest ) return;

  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    if( pBest->flags ) sqlite3SkipAccumulatorLoad(context);
  }else if( pBest->flags ){
    int max;
    int cmp;
    CollSeq *pColl = sqlite3GetFuncCollSeq(context);
    /* This step function is used for both the min() and max() aggregates,
    ** the only difference between the two being that the sense of the
    ** comparison is inverted. For the max() aggregate, the
    ** sqlite3_user_data() function returns (void *)-1. For min() it
    ** returns (void *)db, where db is the sqlite3* database pointer.
    ** Therefore the next statement sets variable 'max' to 1 for the max()
    ** aggregate, or 0 for min().
    */
    max = sqlite3_user_data(context)!=0;
    cmp = sqlite3MemCompare(pBest, pArg, pColl);
    if( (max && cmp<0) || (!max && cmp>0) ){
      sqlite3VdbeMemCopy(pBest, pArg);
    }else{
      sqlite3SkipAccumulatorLoad(context);
    }
  }else{
    sqlite3VdbeMemCopy(pBest, pArg);
  }
}
static void minMaxFinalize(sqlite3_context *context){
  sqlite3_value *pRes;
  pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
  if( pRes ){
    if( pRes->flags ){
      sqlite3_result_value(context, pRes);
    }
    sqlite3VdbeMemRelease(pRes);
  }
}

/*
91918
91919
91920
91921
91922
91923
91924
91925

91926
91927
91928
91929
91930
91931
91932
91933
91934
91935
91936
91937
91938
91939
91940
91941
91942
91943
91944
91945
91946
91947
91948
91949
91950
91951
91952
91953
91954
91955
91956
91957
91958
91959
91960
91961
91962
*************************************************************************
** This file contains code used to implement the PRAGMA command.
*/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.

**
** Note that the values returned are one less that the values that
** should be passed into sqlite3BtreeSetSafetyLevel().  The is done
** to support legacy SQL code.  The safety level used to be boolean
** and older scripts may have used numbers 0 for OFF and 1 for ON.
*/
static u8 getSafetyLevel(const char *z){
                             /* 123456789 123456789 */
  static const char zText[] = "onoffalseyestruefull";
  static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
  static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
  static const u8 iValue[] =  {1, 0, 0, 0, 1, 1, 2};
  int i, n;
  if( sqlite3Isdigit(*z) ){
    return (u8)sqlite3Atoi(z);
  }
  n = sqlite3Strlen30(z);
  for(i=0; i<ArraySize(iLength); i++){
    if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
      return iValue[i];
    }
  }
  return 1;
}

/*
** Interpret the given string as a boolean value.
*/
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z){
  return getSafetyLevel(z)&1;
}

/* The sqlite3GetBoolean() function is used by other modules but the
** remainder of this file is specific to PRAGMA processing.  So omit
** the rest of the file if PRAGMAs are omitted from the build.
*/
#if !defined(SQLITE_OMIT_PRAGMA)







|
>






|










|




|





|
|







92019
92020
92021
92022
92023
92024
92025
92026
92027
92028
92029
92030
92031
92032
92033
92034
92035
92036
92037
92038
92039
92040
92041
92042
92043
92044
92045
92046
92047
92048
92049
92050
92051
92052
92053
92054
92055
92056
92057
92058
92059
92060
92061
92062
92063
92064
*************************************************************************
** This file contains code used to implement the PRAGMA command.
*/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.  The FULL option is disallowed
** if the omitFull parameter it 1.
**
** Note that the values returned are one less that the values that
** should be passed into sqlite3BtreeSetSafetyLevel().  The is done
** to support legacy SQL code.  The safety level used to be boolean
** and older scripts may have used numbers 0 for OFF and 1 for ON.
*/
static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
                             /* 123456789 123456789 */
  static const char zText[] = "onoffalseyestruefull";
  static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
  static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
  static const u8 iValue[] =  {1, 0, 0, 0, 1, 1, 2};
  int i, n;
  if( sqlite3Isdigit(*z) ){
    return (u8)sqlite3Atoi(z);
  }
  n = sqlite3Strlen30(z);
  for(i=0; i<ArraySize(iLength)-omitFull; i++){
    if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
      return iValue[i];
    }
  }
  return dflt;
}

/*
** Interpret the given string as a boolean value.
*/
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){
  return getSafetyLevel(z,1,dflt)!=0;
}

/* The sqlite3GetBoolean() function is used by other modules but the
** remainder of this file is specific to PRAGMA processing.  So omit
** the rest of the file if PRAGMAs are omitted from the build.
*/
#if !defined(SQLITE_OMIT_PRAGMA)
92091
92092
92093
92094
92095
92096
92097
92098
92099
92100
92101
92102
92103
92104
92105
    { "vdbe_trace",               SQLITE_VdbeTrace     },
#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },
#endif
    /* The following is VERY experimental */
    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },
    { "omit_readlock",            SQLITE_NoReadlock    },

    /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
    ** flag if there are any active statements. */
    { "read_uncommitted",         SQLITE_ReadUncommitted },
    { "recursive_triggers",       SQLITE_RecTriggers },

    /* This flag may only be set if both foreign-key and trigger support







<







92193
92194
92195
92196
92197
92198
92199

92200
92201
92202
92203
92204
92205
92206
    { "vdbe_trace",               SQLITE_VdbeTrace     },
#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },
#endif
    /* The following is VERY experimental */
    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },


    /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
    ** flag if there are any active statements. */
    { "read_uncommitted",         SQLITE_ReadUncommitted },
    { "recursive_triggers",       SQLITE_RecTriggers },

    /* This flag may only be set if both foreign-key and trigger support
92123
92124
92125
92126
92127
92128
92129
92130
92131
92132
92133
92134
92135
92136
92137
          int mask = p->mask;          /* Mask of bits to set or clear. */
          if( db->autoCommit==0 ){
            /* Foreign key support may not be enabled or disabled while not
            ** in auto-commit mode.  */
            mask &= ~(SQLITE_ForeignKeys);
          }

          if( sqlite3GetBoolean(zRight) ){
            db->flags |= mask;
          }else{
            db->flags &= ~mask;
          }

          /* Many of the flag-pragmas modify the code generated by the SQL 
          ** compiler (eg. count_changes). So add an opcode to expire all







|







92224
92225
92226
92227
92228
92229
92230
92231
92232
92233
92234
92235
92236
92237
92238
          int mask = p->mask;          /* Mask of bits to set or clear. */
          if( db->autoCommit==0 ){
            /* Foreign key support may not be enabled or disabled while not
            ** in auto-commit mode.  */
            mask &= ~(SQLITE_ForeignKeys);
          }

          if( sqlite3GetBoolean(zRight, 0) ){
            db->flags |= mask;
          }else{
            db->flags &= ~mask;
          }

          /* Many of the flag-pragmas modify the code generated by the SQL 
          ** compiler (eg. count_changes). So add an opcode to expire all
92339
92340
92341
92342
92343
92344
92345
92346
92347
92348
92349
92350
92351
92352
92353
  ** flag setting and reports thenew value.
  */
  if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
    Btree *pBt = pDb->pBt;
    int b = -1;
    assert( pBt!=0 );
    if( zRight ){
      b = sqlite3GetBoolean(zRight);
    }
    if( pId2->n==0 && b>=0 ){
      int ii;
      for(ii=0; ii<db->nDb; ii++){
        sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
      }
    }







|







92440
92441
92442
92443
92444
92445
92446
92447
92448
92449
92450
92451
92452
92453
92454
  ** flag setting and reports thenew value.
  */
  if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
    Btree *pBt = pDb->pBt;
    int b = -1;
    assert( pBt!=0 );
    if( zRight ){
      b = sqlite3GetBoolean(zRight, 0);
    }
    if( pId2->n==0 && b>=0 ){
      int ii;
      for(ii=0; ii<db->nDb; ii++){
        sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
      }
    }
92744
92745
92746
92747
92748
92749
92750
92751
92752
92753
92754
92755
92756
92757
92758
    if( !zRight ){
      returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
    }else{
      if( !db->autoCommit ){
        sqlite3ErrorMsg(pParse, 
            "Safety level may not be changed inside a transaction");
      }else{
        pDb->safety_level = getSafetyLevel(zRight)+1;
      }
    }
  }else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */

#ifndef SQLITE_OMIT_FLAG_PRAGMAS
  if( flagPragma(pParse, zLeft, zRight) ){







|







92845
92846
92847
92848
92849
92850
92851
92852
92853
92854
92855
92856
92857
92858
92859
    if( !zRight ){
      returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
    }else{
      if( !db->autoCommit ){
        sqlite3ErrorMsg(pParse, 
            "Safety level may not be changed inside a transaction");
      }else{
        pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
      }
    }
  }else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */

#ifndef SQLITE_OMIT_FLAG_PRAGMAS
  if( flagPragma(pParse, zLeft, zRight) ){
92943
92944
92945
92946
92947
92948
92949
92950
92951
92952
92953
92954
92955
92956
92957
92958
92959
92960
92961
92962
92963
92964
92965
92966
92967
92968
92969
92970
92971
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    if( zRight ){
      if( sqlite3GetBoolean(zRight) ){
        sqlite3ParserTrace(stderr, "parser: ");
      }else{
        sqlite3ParserTrace(0, 0);
      }
    }
  }else
#endif

  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
  ** used will be case sensitive or not depending on the RHS.
  */
  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
    if( zRight ){
      sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight));
    }
  }else

#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
#endif








|













|







93044
93045
93046
93047
93048
93049
93050
93051
93052
93053
93054
93055
93056
93057
93058
93059
93060
93061
93062
93063
93064
93065
93066
93067
93068
93069
93070
93071
93072
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    if( zRight ){
      if( sqlite3GetBoolean(zRight, 0) ){
        sqlite3ParserTrace(stderr, "parser: ");
      }else{
        sqlite3ParserTrace(0, 0);
      }
    }
  }else
#endif

  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
  ** used will be case sensitive or not depending on the RHS.
  */
  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
    if( zRight ){
      sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
    }
  }else

#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
#endif

94383
94384
94385
94386
94387
94388
94389

94390
94391
94392
94393
94394
94395
94396
    pNew = &standin;
    memset(pNew, 0, sizeof(*pNew));
  }
  if( pEList==0 ){
    pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0));
  }
  pNew->pEList = pEList;

  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->selFlags = isDistinct ? SF_Distinct : 0;
  pNew->op = TK_SELECT;







>







94484
94485
94486
94487
94488
94489
94490
94491
94492
94493
94494
94495
94496
94497
94498
    pNew = &standin;
    memset(pNew, 0, sizeof(*pNew));
  }
  if( pEList==0 ){
    pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0));
  }
  pNew->pEList = pEList;
  if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->selFlags = isDistinct ? SF_Distinct : 0;
  pNew->op = TK_SELECT;
95921
95922
95923
95924
95925
95926
95927



95928
95929

95930
95931
95932
95933
95934
95935
95936
  }

  /* Make sure all SELECTs in the statement have the same number of elements
  ** in their result sets.
  */
  assert( p->pEList && pPrior->pEList );
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){



    sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
      " do not have the same number of result columns", selectOpName(p->op));

    rc = 1;
    goto multi_select_end;
  }

  /* Compound SELECTs that have an ORDER BY clause are handled separately.
  */
  if( p->pOrderBy ){







>
>
>
|
|
>







96023
96024
96025
96026
96027
96028
96029
96030
96031
96032
96033
96034
96035
96036
96037
96038
96039
96040
96041
96042
  }

  /* Make sure all SELECTs in the statement have the same number of elements
  ** in their result sets.
  */
  assert( p->pEList && pPrior->pEList );
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
    if( p->selFlags & SF_Values ){
      sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
    }else{
      sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
        " do not have the same number of result columns", selectOpName(p->op));
    }
    rc = 1;
    goto multi_select_end;
  }

  /* Compound SELECTs that have an ORDER BY clause are handled separately.
  */
  if( p->pOrderBy ){
96538
96539
96540
96541
96542
96543
96544
96545
96546
96547
96548
96549
96550
96551
96552
      }
      if( j==nOrderBy ){
        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return SQLITE_NOMEM;
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = i;
        pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
        pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
      }
    }
  }

  /* Compute the comparison permutation and keyinfo that is used with
  ** the permutation used to determine if the next
  ** row of results comes from selectA or selectB.  Also add explicit







|







96644
96645
96646
96647
96648
96649
96650
96651
96652
96653
96654
96655
96656
96657
96658
      }
      if( j==nOrderBy ){
        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return SQLITE_NOMEM;
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = i;
        pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
        if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
      }
    }
  }

  /* Compute the comparison permutation and keyinfo that is used with
  ** the permutation used to determine if the next
  ** row of results comes from selectA or selectB.  Also add explicit
97901
97902
97903
97904
97905
97906
97907


97908
97909
97910
97911
97912
97913
97914
/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
*/
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;


  struct AggInfo_func *pF;
  struct AggInfo_col *pC;

  pAggInfo->directMode = 1;
  sqlite3ExprCacheClear(pParse);
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    int nArg;







>
>







98007
98008
98009
98010
98011
98012
98013
98014
98015
98016
98017
98018
98019
98020
98021
98022
/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
*/
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
  struct AggInfo_func *pF;
  struct AggInfo_col *pC;

  pAggInfo->directMode = 1;
  sqlite3ExprCacheClear(pParse);
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    int nArg;
97936
97937
97938
97939
97940
97941
97942

97943
97944
97945
97946
97947
97948
97949
97950
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
        pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      }
      if( !pColl ){
        pColl = pParse->db->pDfltColl;
      }

      sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                      (void*)pF->pFunc, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, (u8)nArg);
    sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
    if( addrNext ){







>
|







98044
98045
98046
98047
98048
98049
98050
98051
98052
98053
98054
98055
98056
98057
98058
98059
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
        pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      }
      if( !pColl ){
        pColl = pParse->db->pDfltColl;
      }
      if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
      sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                      (void*)pF->pFunc, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, (u8)nArg);
    sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
    if( addrNext ){
97959
97960
97961
97962
97963
97964
97965



97966
97967
97968
97969
97970
97971



97972
97973
97974
97975
97976
97977
97978
  ** to pC->iMem. But by the time the value is used, the original register
  ** may have been used, invalidating the underlying buffer holding the
  ** text or blob value. See ticket [883034dcb5].
  **
  ** Another solution would be to change the OP_SCopy used to copy cached
  ** values to an OP_Copy.
  */



  sqlite3ExprCacheClear(pParse);
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
  }
  pAggInfo->directMode = 0;
  sqlite3ExprCacheClear(pParse);



}

/*
** Add a single OP_Explain instruction to the VDBE to explain a simple
** count(*) query ("SELECT count(*) FROM pTab").
*/
#ifndef SQLITE_OMIT_EXPLAIN







>
>
>






>
>
>







98068
98069
98070
98071
98072
98073
98074
98075
98076
98077
98078
98079
98080
98081
98082
98083
98084
98085
98086
98087
98088
98089
98090
98091
98092
98093
  ** to pC->iMem. But by the time the value is used, the original register
  ** may have been used, invalidating the underlying buffer holding the
  ** text or blob value. See ticket [883034dcb5].
  **
  ** Another solution would be to change the OP_SCopy used to copy cached
  ** values to an OP_Copy.
  */
  if( regHit ){
    addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit);
  }
  sqlite3ExprCacheClear(pParse);
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
  }
  pAggInfo->directMode = 0;
  sqlite3ExprCacheClear(pParse);
  if( addrHitTest ){
    sqlite3VdbeJumpHere(v, addrHitTest);
  }
}

/*
** Add a single OP_Explain instruction to the VDBE to explain a simple
** count(*) query ("SELECT count(*) FROM pTab").
*/
#ifndef SQLITE_OMIT_EXPLAIN
98905
98906
98907
98908
98909
98910
98911
98912
98913
98914
98915
98916
98917
98918
98919
  }
  sqlite3ExplainPrintf(pVdbe, "END");
  sqlite3ExplainPop(pVdbe);
}

/* End of the structure debug printing code
*****************************************************************************/
#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */

/************** End of select.c **********************************************/
/************** Begin file table.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of







|







99020
99021
99022
99023
99024
99025
99026
99027
99028
99029
99030
99031
99032
99033
99034
  }
  sqlite3ExplainPrintf(pVdbe, "END");
  sqlite3ExplainPop(pVdbe);
}

/* End of the structure debug printing code
*****************************************************************************/
#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */

/************** End of select.c **********************************************/
/************** Begin file table.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
101532
101533
101534
101535
101536
101537
101538
101539

101540
101541
101542
101543
101544
101545
101546
101547
101548
101549
101550
101551
101552
** statement.  The module name has been parsed, but the optional list
** of parameters that follow the module name are still pending.
*/
SQLITE_PRIVATE void sqlite3VtabBeginParse(
  Parse *pParse,        /* Parsing context */
  Token *pName1,        /* Name of new table, or database name */
  Token *pName2,        /* Name of new table or NULL */
  Token *pModuleName    /* Name of the module for the virtual table */

){
  int iDb;              /* The database the table is being created in */
  Table *pTable;        /* The new virtual table */
  sqlite3 *db;          /* Database connection */

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
  pTable = pParse->pNewTable;
  if( pTable==0 ) return;
  assert( 0==pTable->pIndex );

  db = pParse->db;
  iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
  assert( iDb>=0 );







|
>





|







101647
101648
101649
101650
101651
101652
101653
101654
101655
101656
101657
101658
101659
101660
101661
101662
101663
101664
101665
101666
101667
101668
** statement.  The module name has been parsed, but the optional list
** of parameters that follow the module name are still pending.
*/
SQLITE_PRIVATE void sqlite3VtabBeginParse(
  Parse *pParse,        /* Parsing context */
  Token *pName1,        /* Name of new table, or database name */
  Token *pName2,        /* Name of new table or NULL */
  Token *pModuleName,   /* Name of the module for the virtual table */
  int ifNotExists       /* No error if the table already exists */
){
  int iDb;              /* The database the table is being created in */
  Table *pTable;        /* The new virtual table */
  sqlite3 *db;          /* Database connection */

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
  pTable = pParse->pNewTable;
  if( pTable==0 ) return;
  assert( 0==pTable->pIndex );

  db = pParse->db;
  iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
  assert( iDb>=0 );
101573
101574
101575
101576
101577
101578
101579
101580
101581
101582
101583
101584
101585
101586
101587

/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
  if( pParse->sArg.z && ALWAYS(pParse->pNewTable) ){
    const char *z = (const char*)pParse->sArg.z;
    int n = pParse->sArg.n;
    sqlite3 *db = pParse->db;
    addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
  }
}








|







101689
101690
101691
101692
101693
101694
101695
101696
101697
101698
101699
101700
101701
101702
101703

/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
  if( pParse->sArg.z && pParse->pNewTable ){
    const char *z = (const char*)pParse->sArg.z;
    int n = pParse->sArg.n;
    sqlite3 *db = pParse->db;
    addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
  }
}

107618
107619
107620
107621
107622
107623
107624








107625
107626
107627
107628
107629
107630
107631
struct TrigEvent { int a; IdList * b; };

/*
** An instance of this structure holds the ATTACH key and the key type.
*/
struct AttachKey { int type;  Token key; };










  /* This is a utility routine used to set the ExprSpan.zStart and
  ** ExprSpan.zEnd values of pOut so that the span covers the complete
  ** range of text beginning with pStart and going to the end of pEnd.
  */
  static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
    pOut->zStart = pStart->z;







>
>
>
>
>
>
>
>







107734
107735
107736
107737
107738
107739
107740
107741
107742
107743
107744
107745
107746
107747
107748
107749
107750
107751
107752
107753
107754
107755
struct TrigEvent { int a; IdList * b; };

/*
** An instance of this structure holds the ATTACH key and the key type.
*/
struct AttachKey { int type;  Token key; };

/*
** One or more VALUES claues
*/
struct ValueList {
  ExprList *pList;
  Select *pSelect;
};


  /* This is a utility routine used to set the ExprSpan.zStart and
  ** ExprSpan.zEnd values of pOut so that the span covers the complete
  ** range of text beginning with pStart and going to the end of pEnd.
  */
  static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
    pOut->zStart = pStart->z;
107741
107742
107743
107744
107745
107746
107747
107748
107749
107750
107751
107752
107753
107754
107755
107756
107757
107758
107759
107760
107761
107762
107763

107764

107765
107766
107767
107768
107769
107770
107771
107772
107773
107774
107775
107776
107777
107778
107779
107780
107781
107782
107783
107784
**    sqlite3ParserARG_FETCH     Code to extract %extra_argument from yypParser
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
#define YYNOCODE 253
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 67
#define sqlite3ParserTOKENTYPE Token
typedef union {
  int yyinit;
  sqlite3ParserTOKENTYPE yy0;
  int yy4;
  struct TrigEvent yy90;
  ExprSpan yy118;
  TriggerStep* yy203;
  u8 yy210;
  struct {int value; int mask;} yy215;
  SrcList* yy259;
  struct LimitVal yy292;
  Expr* yy314;

  ExprList* yy322;

  struct LikeOp yy342;
  IdList* yy384;
  Select* yy387;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
#define YYNSTATE 630
#define YYNRULE 329
#define YYFALLBACK 1
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)

/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */







|






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








|
|







107865
107866
107867
107868
107869
107870
107871
107872
107873
107874
107875
107876
107877
107878

107879
107880
107881
107882
107883
107884
107885
107886
107887
107888
107889
107890
107891
107892
107893
107894
107895
107896
107897
107898
107899
107900
107901
107902
107903
107904
107905
107906
107907
107908
107909
**    sqlite3ParserARG_FETCH     Code to extract %extra_argument from yypParser
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
#define YYNOCODE 251
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 67
#define sqlite3ParserTOKENTYPE Token
typedef union {
  int yyinit;
  sqlite3ParserTOKENTYPE yy0;

  struct LimitVal yy64;
  Expr* yy122;
  Select* yy159;
  IdList* yy180;
  struct {int value; int mask;} yy207;
  u8 yy258;
  struct LikeOp yy318;
  TriggerStep* yy327;
  ExprSpan yy342;
  SrcList* yy347;
  int yy392;
  struct TrigEvent yy410;
  ExprList* yy442;
  struct ValueList yy487;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
#define YYNSTATE 629
#define YYNRULE 327
#define YYFALLBACK 1
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)

/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
107840
107841
107842
107843
107844
107845
107846
107847
107848
107849
107850
107851
107852
107853
107854
107855
107856
107857
107858
107859
107860
107861
107862
107863
107864
107865
107866
107867
107868
107869
107870
107871
107872
107873
107874
107875
107876
107877
107878
107879
107880
107881
107882
107883
107884
107885
107886
107887
107888
107889
107890
107891
107892
107893
107894
107895
107896
107897
107898
107899
107900
107901
107902
107903
107904
107905
107906
107907
107908
107909
107910
107911
107912
107913
107914
107915
107916
107917
107918
107919
107920
107921
107922
107923
107924
107925
107926
107927
107928
107929
107930
107931
107932
107933
107934
107935
107936
107937
107938
107939
107940
107941
107942
107943
107944
107945
107946
107947
107948
107949
107950
107951
107952
107953
107954
107955
107956
107957
107958
107959
107960
107961
107962
107963
107964
107965
107966
107967
107968
107969
107970
107971
107972
107973
107974
107975
107976
107977
107978
107979
107980
107981
107982
107983
107984
107985
107986
107987
107988
107989
107990
107991
107992
107993
107994
107995
107996
107997
107998
107999
108000
108001
108002
108003
108004


108005
108006
108007
108008
108009
108010
108011
108012
108013
108014
108015
108016
108017
108018
108019
108020
108021
108022
108023
108024
108025
108026
108027
108028
108029
108030
108031
108032
108033
108034
108035
108036
108037
108038
108039
108040
108041
108042
108043
108044
108045
108046
108047
108048
108049
108050
108051
108052
108053
108054
108055
108056
108057
108058
108059
108060
108061
108062
108063
108064
108065
108066
108067
108068
108069
108070
108071
108072
108073
108074
108075
108076
108077
108078
108079
108080
108081
108082
108083
108084
108085
108086
108087
108088
108089
108090
108091
108092
108093
108094
108095
108096
108097
108098
108099
108100
108101
108102
108103
108104
108105
108106
108107
108108
108109
108110
108111
108112
108113
108114
108115
108116
108117
108118
108119
108120
108121
108122
108123
108124
108125
108126
108127
108128
108129
108130
108131
108132
108133
108134
108135
108136
108137
108138
108139
108140
108141
108142
108143
108144
108145
108146
108147
108148
108149
108150
108151
108152
108153
108154
108155
108156
108157
108158
108159
108160
108161
108162


108163
108164
108165
108166
108167
108168
108169
108170
108171
108172
108173
108174
108175
108176
108177
108178
108179
108180
108181
108182
108183
108184
108185
108186
108187
108188
108189
108190
108191
108192
108193
108194
108195
108196
108197
108198
108199
108200
108201
108202
108203
108204
108205
108206
108207
108208
108209
108210
108211
108212
108213
108214
108215
108216
108217
108218
108219
108220
108221
108222
108223
108224
108225
108226
108227
108228
108229
108230
108231
108232
108233
108234
108235
108236
108237
108238
108239
108240
108241
108242
108243
108244
108245
108246
108247
108248
108249
108250
108251
108252
108253
108254
108255
108256
108257
108258
108259
108260
108261
108262
108263
108264
108265
108266
108267
108268
108269
108270
108271
108272
108273
108274
108275
108276
108277
108278
108279
108280
108281
108282
108283
108284
108285
108286
108287
108288
108289
108290
108291
108292
108293
108294
108295
108296
108297
108298
108299
108300
108301
108302
108303
108304
108305
108306
108307
108308
108309
108310
108311
108312
108313
108314
108315
108316
108317
108318
108319
108320
**                     yy_action.  Used to detect hash collisions.
**  yy_shift_ofst[]    For each state, the offset into yy_action for
**                     shifting terminals.
**  yy_reduce_ofst[]   For each state, the offset into yy_action for
**                     shifting non-terminals after a reduce.
**  yy_default[]       Default action for each state.
*/
#define YY_ACTTAB_COUNT (1557)
static const YYACTIONTYPE yy_action[] = {
 /*     0 */   313,  960,  186,  419,    2,  172,  627,  597,   55,   55,
 /*    10 */    55,   55,   48,   53,   53,   53,   53,   52,   52,   51,
 /*    20 */    51,   51,   50,  238,  302,  283,  623,  622,  516,  515,
 /*    30 */   590,  584,   55,   55,   55,   55,  282,   53,   53,   53,
 /*    40 */    53,   52,   52,   51,   51,   51,   50,  238,    6,   56,
 /*    50 */    57,   47,  582,  581,  583,  583,   54,   54,   55,   55,
 /*    60 */    55,   55,  608,   53,   53,   53,   53,   52,   52,   51,
 /*    70 */    51,   51,   50,  238,  313,  597,  409,  330,  579,  579,
 /*    80 */    32,   53,   53,   53,   53,   52,   52,   51,   51,   51,
 /*    90 */    50,  238,  330,  217,  620,  619,  166,  411,  624,  382,
 /*   100 */   379,  378,    7,  491,  590,  584,  200,  199,  198,   58,
 /*   110 */   377,  300,  414,  621,  481,   66,  623,  622,  621,  580,
 /*   120 */   254,  601,   94,   56,   57,   47,  582,  581,  583,  583,
 /*   130 */    54,   54,   55,   55,   55,   55,  671,   53,   53,   53,
 /*   140 */    53,   52,   52,   51,   51,   51,   50,  238,  313,  532,
 /*   150 */   226,  506,  507,  133,  177,  139,  284,  385,  279,  384,
 /*   160 */   169,  197,  342,  398,  251,  226,  253,  275,  388,  167,
 /*   170 */   139,  284,  385,  279,  384,  169,  570,  236,  590,  584,
 /*   180 */   672,  240,  275,  157,  620,  619,  554,  437,   51,   51,
 /*   190 */    51,   50,  238,  343,  439,  553,  438,   56,   57,   47,
 /*   200 */   582,  581,  583,  583,   54,   54,   55,   55,   55,   55,
 /*   210 */   465,   53,   53,   53,   53,   52,   52,   51,   51,   51,
 /*   220 */    50,  238,  313,  390,   52,   52,   51,   51,   51,   50,
 /*   230 */   238,  391,  166,  491,  566,  382,  379,  378,  409,  440,
 /*   240 */   579,  579,  252,  440,  607,   66,  377,  513,  621,   49,
 /*   250 */    46,  147,  590,  584,  621,   16,  466,  189,  621,  441,
 /*   260 */   442,  673,  526,  441,  340,  577,  595,   64,  194,  482,
 /*   270 */   434,   56,   57,   47,  582,  581,  583,  583,   54,   54,
 /*   280 */    55,   55,   55,   55,   30,   53,   53,   53,   53,   52,
 /*   290 */    52,   51,   51,   51,   50,  238,  313,  593,  593,  593,
 /*   300 */   387,  578,  606,  493,  259,  351,  258,  411,    1,  623,
 /*   310 */   622,  496,  623,  622,   65,  240,  623,  622,  597,  443,
 /*   320 */   237,  239,  414,  341,  237,  602,  590,  584,   18,  603,
 /*   330 */   166,  601,   87,  382,  379,  378,   67,  623,  622,   38,
 /*   340 */   623,  622,  176,  270,  377,   56,   57,   47,  582,  581,
 /*   350 */   583,  583,   54,   54,   55,   55,   55,   55,  175,   53,
 /*   360 */    53,   53,   53,   52,   52,   51,   51,   51,   50,  238,
 /*   370 */   313,  396,  233,  411,  531,  565,  317,  620,  619,   44,
 /*   380 */   620,  619,  240,  206,  620,  619,  597,  266,  414,  268,
 /*   390 */   409,  597,  579,  579,  352,  184,  505,  601,   73,  533,
 /*   400 */   590,  584,  466,  548,  190,  620,  619,  576,  620,  619,
 /*   410 */   547,  383,  551,   35,  332,  575,  574,  600,  504,   56,
 /*   420 */    57,   47,  582,  581,  583,  583,   54,   54,   55,   55,
 /*   430 */    55,   55,  567,   53,   53,   53,   53,   52,   52,   51,
 /*   440 */    51,   51,   50,  238,  313,  411,  561,  561,  528,  364,
 /*   450 */   259,  351,  258,  183,  361,  549,  524,  374,  411,  597,
 /*   460 */   414,  240,  560,  560,  409,  604,  579,  579,  328,  601,
 /*   470 */    93,  623,  622,  414,  590,  584,  237,  564,  559,  559,
 /*   480 */   520,  402,  601,   87,  409,  210,  579,  579,  168,  421,
 /*   490 */   950,  519,  950,   56,   57,   47,  582,  581,  583,  583,
 /*   500 */    54,   54,   55,   55,   55,   55,  192,   53,   53,   53,
 /*   510 */    53,   52,   52,   51,   51,   51,   50,  238,  313,  600,
 /*   520 */   293,  563,  511,  234,  357,  146,  475,  475,  367,  411,
 /*   530 */   562,  411,  358,  542,  425,  171,  411,  215,  144,  620,
 /*   540 */   619,  544,  318,  353,  414,  203,  414,  275,  590,  584,
 /*   550 */   549,  414,  174,  601,   94,  601,   79,  558,  471,   61,
 /*   560 */   601,   79,  421,  949,  350,  949,   34,   56,   57,   47,
 /*   570 */   582,  581,  583,  583,   54,   54,   55,   55,   55,   55,
 /*   580 */   535,   53,   53,   53,   53,   52,   52,   51,   51,   51,
 /*   590 */    50,  238,  313,  307,  424,  394,  272,   49,   46,  147,
 /*   600 */   349,  322,    4,  411,  491,  312,  321,  425,  568,  492,
 /*   610 */   216,  264,  407,  575,  574,  429,   66,  549,  414,  621,
 /*   620 */   540,  602,  590,  584,   13,  603,  621,  601,   72,   12,
 /*   630 */   618,  617,  616,  202,  210,  621,  546,  469,  422,  319,
 /*   640 */   148,   56,   57,   47,  582,  581,  583,  583,   54,   54,
 /*   650 */    55,   55,   55,   55,  338,   53,   53,   53,   53,   52,
 /*   660 */    52,   51,   51,   51,   50,  238,  313,  600,  600,  411,
 /*   670 */    39,   21,   37,  170,  237,  875,  411,  572,  572,  201,
 /*   680 */   144,  473,  538,  331,  414,  474,  143,  146,  630,  628,
 /*   690 */   334,  414,  353,  601,   68,  168,  590,  584,  132,  365,
 /*   700 */   601,   96,  307,  423,  530,  336,   49,   46,  147,  568,
 /*   710 */   406,  216,  549,  360,  529,   56,   57,   47,  582,  581,
 /*   720 */   583,  583,   54,   54,   55,   55,   55,   55,  411,   53,
 /*   730 */    53,   53,   53,   52,   52,   51,   51,   51,   50,  238,
 /*   740 */   313,  411,  605,  414,  484,  510,  172,  422,  597,  318,
 /*   750 */   496,  485,  601,   99,  411,  142,  414,  411,  231,  411,
 /*   760 */   540,  411,  359,  629,    2,  601,   97,  426,  308,  414,
 /*   770 */   590,  584,  414,   20,  414,  621,  414,  621,  601,  106,
 /*   780 */   503,  601,  105,  601,  108,  601,  109,  204,   28,   56,
 /*   790 */    57,   47,  582,  581,  583,  583,   54,   54,   55,   55,
 /*   800 */    55,   55,  411,   53,   53,   53,   53,   52,   52,   51,
 /*   810 */    51,   51,   50,  238,  313,  411,  597,  414,  411,  276,
 /*   820 */   214,  600,  411,  366,  213,  381,  601,  134,  274,  500,
 /*   830 */   414,  167,  130,  414,  621,  411,  354,  414,  376,  601,
 /*   840 */   135,  129,  601,  100,  590,  584,  601,  104,  522,  521,
 /*   850 */   414,  621,  224,  273,  600,  167,  327,  282,  600,  601,
 /*   860 */   103,  468,  521,   56,   57,   47,  582,  581,  583,  583,
 /*   870 */    54,   54,   55,   55,   55,   55,  411,   53,   53,   53,
 /*   880 */    53,   52,   52,   51,   51,   51,   50,  238,  313,  411,
 /*   890 */    27,  414,  411,  375,  276,  167,  359,  544,   50,  238,
 /*   900 */   601,   95,  128,  223,  414,  411,  165,  414,  411,  621,
 /*   910 */   411,  621,  612,  601,  102,  372,  601,   76,  590,  584,
 /*   920 */   414,  570,  236,  414,  470,  414,  167,  621,  188,  601,
 /*   930 */    98,  225,  601,  138,  601,  137,  232,   56,   45,   47,
 /*   940 */   582,  581,  583,  583,   54,   54,   55,   55,   55,   55,
 /*   950 */   411,   53,   53,   53,   53,   52,   52,   51,   51,   51,
 /*   960 */    50,  238,  313,  276,  276,  414,  411,  276,  544,  459,
 /*   970 */   359,  171,  209,  479,  601,  136,  628,  334,  621,  621,
 /*   980 */   125,  414,  621,  368,  411,  621,  257,  540,  589,  588,
 /*   990 */   601,   75,  590,  584,  458,  446,   23,   23,  124,  414,
 /*  1000 */   326,  325,  621,  427,  324,  309,  600,  288,  601,   92,
 /*  1010 */   586,  585,   57,   47,  582,  581,  583,  583,   54,   54,
 /*  1020 */    55,   55,   55,   55,  411,   53,   53,   53,   53,   52,
 /*  1030 */    52,   51,   51,   51,   50,  238,  313,  587,  411,  414,
 /*  1040 */   411,  207,  611,  476,  171,  472,  160,  123,  601,   91,
 /*  1050 */   323,  261,   15,  414,  464,  414,  411,  621,  411,  354,
 /*  1060 */   222,  411,  601,   74,  601,   90,  590,  584,  159,  264,
 /*  1070 */   158,  414,  461,  414,  621,  600,  414,  121,  120,   25,
 /*  1080 */   601,   89,  601,  101,  621,  601,   88,   47,  582,  581,
 /*  1090 */   583,  583,   54,   54,   55,   55,   55,   55,  544,   53,
 /*  1100 */    53,   53,   53,   52,   52,   51,   51,   51,   50,  238,
 /*  1110 */    43,  405,  263,    3,  610,  264,  140,  415,  622,   24,
 /*  1120 */   410,   11,  456,  594,  118,  155,  219,  452,  408,  621,
 /*  1130 */   621,  621,  156,   43,  405,  621,    3,  286,  621,  113,
 /*  1140 */   415,  622,  111,  445,  411,  400,  557,  403,  545,   10,
 /*  1150 */   411,  408,  264,  110,  205,  436,  541,  566,  453,  414,
 /*  1160 */   621,  621,   63,  621,  435,  414,  411,  621,  601,   94,
 /*  1170 */   403,  621,  411,  337,  601,   86,  150,   40,   41,  534,
 /*  1180 */   566,  414,  242,  264,   42,  413,  412,  414,  600,  595,
 /*  1190 */   601,   85,  191,  333,  107,  451,  601,   84,  621,  539,
 /*  1200 */    40,   41,  420,  230,  411,  149,  316,   42,  413,  412,
 /*  1210 */   398,  127,  595,  315,  621,  399,  278,  625,  181,  414,
 /*  1220 */   593,  593,  593,  592,  591,   14,  450,  411,  601,   71,
 /*  1230 */   240,  621,   43,  405,  264,    3,  615,  180,  264,  415,
 /*  1240 */   622,  614,  414,  593,  593,  593,  592,  591,   14,  621,
 /*  1250 */   408,  601,   70,  621,  417,   33,  405,  613,    3,  411,
 /*  1260 */   264,  411,  415,  622,  418,  626,  178,  509,    8,  403,
 /*  1270 */   241,  416,  126,  408,  414,  621,  414,  449,  208,  566,
 /*  1280 */   240,  221,  621,  601,   83,  601,   82,  599,  297,  277,
 /*  1290 */   296,   30,  403,   31,  395,  264,  295,  397,  489,   40,
 /*  1300 */    41,  411,  566,  220,  621,  294,   42,  413,  412,  271,
 /*  1310 */   621,  595,  600,  621,   59,   60,  414,  269,  267,  623,
 /*  1320 */   622,   36,   40,   41,  621,  601,   81,  598,  235,   42,
 /*  1330 */   413,  412,  621,  621,  595,  265,  344,  411,  248,  556,
 /*  1340 */   173,  185,  593,  593,  593,  592,  591,   14,  218,   29,
 /*  1350 */   621,  543,  414,  305,  304,  303,  179,  301,  411,  566,
 /*  1360 */   454,  601,   80,  289,  335,  593,  593,  593,  592,  591,
 /*  1370 */    14,  411,  287,  414,  151,  392,  246,  260,  411,  196,
 /*  1380 */   195,  523,  601,   69,  411,  245,  414,  526,  537,  285,
 /*  1390 */   389,  595,  621,  414,  536,  601,   17,  362,  153,  414,
 /*  1400 */   466,  463,  601,   78,  154,  414,  462,  152,  601,   77,
 /*  1410 */   355,  255,  621,  455,  601,    9,  621,  386,  444,  517,
 /*  1420 */   247,  621,  593,  593,  593,  621,  621,  244,  621,  243,
 /*  1430 */   430,  518,  292,  621,  329,  621,  145,  393,  280,  513,
 /*  1440 */   291,  131,  621,  514,  621,  621,  311,  621,  259,  346,
 /*  1450 */   249,  621,  621,  229,  314,  621,  228,  512,  227,  240,
 /*  1460 */   494,  488,  310,  164,  487,  486,  373,  480,  163,  262,
 /*  1470 */   369,  371,  162,   26,  212,  478,  477,  161,  141,  363,
 /*  1480 */   467,  122,  339,  187,  119,  348,  347,  117,  116,  115,
 /*  1490 */   114,  112,  182,  457,  320,   22,  433,  432,  448,   19,
 /*  1500 */   609,  431,  428,   62,  193,  596,  573,  298,  555,  552,
 /*  1510 */   571,  404,  290,  380,  498,  510,  495,  306,  281,  499,
 /*  1520 */   250,    5,  497,  460,  345,  447,  569,  550,  238,  299,
 /*  1530 */   527,  525,  508,  961,  502,  501,  961,  401,  961,  211,
 /*  1540 */   490,  356,  256,  961,  483,  961,  961,  961,  961,  961,
 /*  1550 */   961,  961,  961,  961,  961,  961,  370,


};
static const YYCODETYPE yy_lookahead[] = {
 /*     0 */    19,  142,  143,  144,  145,   24,    1,   26,   77,   78,
 /*    10 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
 /*    20 */    89,   90,   91,   92,   15,   98,   26,   27,    7,    8,
 /*    30 */    49,   50,   77,   78,   79,   80,  109,   82,   83,   84,
 /*    40 */    85,   86,   87,   88,   89,   90,   91,   92,   22,   68,
 /*    50 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*    60 */    79,   80,   23,   82,   83,   84,   85,   86,   87,   88,
 /*    70 */    89,   90,   91,   92,   19,   94,  112,   19,  114,  115,
 /*    80 */    25,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*    90 */    91,   92,   19,   22,   94,   95,   96,  150,  150,   99,
 /*   100 */   100,  101,   76,  150,   49,   50,  105,  106,  107,   54,
 /*   110 */   110,  158,  165,  165,  161,  162,   26,   27,  165,  113,
 /*   120 */    16,  174,  175,   68,   69,   70,   71,   72,   73,   74,
 /*   130 */    75,   76,   77,   78,   79,   80,  118,   82,   83,   84,
 /*   140 */    85,   86,   87,   88,   89,   90,   91,   92,   19,   23,
 /*   150 */    92,   97,   98,   24,   96,   97,   98,   99,  100,  101,
 /*   160 */   102,   25,   97,  216,   60,   92,   62,  109,  221,   25,
 /*   170 */    97,   98,   99,  100,  101,  102,   86,   87,   49,   50,
 /*   180 */   118,  116,  109,   25,   94,   95,   32,   97,   88,   89,
 /*   190 */    90,   91,   92,  128,  104,   41,  106,   68,   69,   70,
 /*   200 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   210 */    11,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   220 */    91,   92,   19,   19,   86,   87,   88,   89,   90,   91,
 /*   230 */    92,   27,   96,  150,   66,   99,  100,  101,  112,  150,
 /*   240 */   114,  115,  138,  150,  161,  162,  110,  103,  165,  222,
 /*   250 */   223,  224,   49,   50,  165,   22,   57,   24,  165,  170,
 /*   260 */   171,  118,   94,  170,  171,   23,   98,   25,  185,  186,
 /*   270 */   243,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   280 */    77,   78,   79,   80,  126,   82,   83,   84,   85,   86,
 /*   290 */    87,   88,   89,   90,   91,   92,   19,  129,  130,  131,
 /*   300 */    88,   23,  172,  173,  105,  106,  107,  150,   22,   26,
 /*   310 */    27,  181,   26,   27,   22,  116,   26,   27,   26,  230,
 /*   320 */   231,  197,  165,  230,  231,  113,   49,   50,  204,  117,
 /*   330 */    96,  174,  175,   99,  100,  101,   22,   26,   27,  136,
 /*   340 */    26,   27,  118,   16,  110,   68,   69,   70,   71,   72,
 /*   350 */    73,   74,   75,   76,   77,   78,   79,   80,  118,   82,
 /*   360 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   370 */    19,  214,  215,  150,   23,   23,  155,   94,   95,   22,
 /*   380 */    94,   95,  116,  160,   94,   95,   94,   60,  165,   62,
 /*   390 */   112,   26,  114,  115,  128,   23,   36,  174,  175,   88,
 /*   400 */    49,   50,   57,  120,   22,   94,   95,   23,   94,   95,
 /*   410 */   120,   51,   25,  136,  169,  170,  171,  194,   58,   68,
 /*   420 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   430 */    79,   80,   23,   82,   83,   84,   85,   86,   87,   88,
 /*   440 */    89,   90,   91,   92,   19,  150,   12,   12,   23,  228,
 /*   450 */   105,  106,  107,   23,  233,   25,  165,   19,  150,   94,
 /*   460 */   165,  116,   28,   28,  112,  174,  114,  115,  108,  174,
 /*   470 */   175,   26,   27,  165,   49,   50,  231,   11,   44,   44,
 /*   480 */    46,   46,  174,  175,  112,  160,  114,  115,   50,   22,
 /*   490 */    23,   57,   25,   68,   69,   70,   71,   72,   73,   74,
 /*   500 */    75,   76,   77,   78,   79,   80,  119,   82,   83,   84,
 /*   510 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  194,
 /*   520 */   225,   23,   23,  215,   19,   95,  105,  106,  107,  150,
 /*   530 */    23,  150,   27,   23,   67,   25,  150,  206,  207,   94,
 /*   540 */    95,  166,  104,  218,  165,   22,  165,  109,   49,   50,
 /*   550 */   120,  165,   25,  174,  175,  174,  175,   23,   21,  234,
 /*   560 */   174,  175,   22,   23,  239,   25,   25,   68,   69,   70,
 /*   570 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   580 */   205,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   590 */    91,   92,   19,   22,   23,  216,   23,  222,  223,  224,
 /*   600 */    63,  220,   35,  150,  150,  163,  220,   67,  166,  167,
 /*   610 */   168,  150,  169,  170,  171,  161,  162,   25,  165,  165,
 /*   620 */   150,  113,   49,   50,   25,  117,  165,  174,  175,   35,
 /*   630 */     7,    8,    9,  160,  160,  165,  120,  100,   67,  247,
 /*   640 */   248,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   650 */    77,   78,   79,   80,  193,   82,   83,   84,   85,   86,
 /*   660 */    87,   88,   89,   90,   91,   92,   19,  194,  194,  150,
 /*   670 */   135,   24,  137,   35,  231,  138,  150,  129,  130,  206,
 /*   680 */   207,   30,   27,  213,  165,   34,  118,   95,    0,    1,
 /*   690 */     2,  165,  218,  174,  175,   50,   49,   50,   22,   48,
 /*   700 */   174,  175,   22,   23,   23,  244,  222,  223,  224,  166,
 /*   710 */   167,  168,  120,  239,   23,   68,   69,   70,   71,   72,
 /*   720 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
 /*   730 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   740 */    19,  150,  173,  165,  181,  182,   24,   67,   26,  104,
 /*   750 */   181,  188,  174,  175,  150,   39,  165,  150,   52,  150,
 /*   760 */   150,  150,  150,  144,  145,  174,  175,  249,  250,  165,
 /*   770 */    49,   50,  165,   52,  165,  165,  165,  165,  174,  175,
 /*   780 */    29,  174,  175,  174,  175,  174,  175,  160,   22,   68,
 /*   790 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   800 */    79,   80,  150,   82,   83,   84,   85,   86,   87,   88,
 /*   810 */    89,   90,   91,   92,   19,  150,   94,  165,  150,  150,
 /*   820 */   160,  194,  150,  213,  160,   52,  174,  175,   23,   23,
 /*   830 */   165,   25,   22,  165,  165,  150,  150,  165,   52,  174,
 /*   840 */   175,   22,  174,  175,   49,   50,  174,  175,  190,  191,
 /*   850 */   165,  165,  240,   23,  194,   25,  187,  109,  194,  174,
 /*   860 */   175,  190,  191,   68,   69,   70,   71,   72,   73,   74,
 /*   870 */    75,   76,   77,   78,   79,   80,  150,   82,   83,   84,
 /*   880 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  150,
 /*   890 */    22,  165,  150,   23,  150,   25,  150,  166,   91,   92,
 /*   900 */   174,  175,   22,  217,  165,  150,  102,  165,  150,  165,
 /*   910 */   150,  165,  150,  174,  175,   19,  174,  175,   49,   50,
 /*   920 */   165,   86,   87,  165,   23,  165,   25,  165,   24,  174,
 /*   930 */   175,  187,  174,  175,  174,  175,  205,   68,   69,   70,
 /*   940 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   950 */   150,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   960 */    91,   92,   19,  150,  150,  165,  150,  150,  166,   23,
 /*   970 */   150,   25,  160,   20,  174,  175,    1,    2,  165,  165,
 /*   980 */   104,  165,  165,   43,  150,  165,  240,  150,   49,   50,
 /*   990 */   174,  175,   49,   50,   23,   23,   25,   25,   53,  165,
 /*  1000 */   187,  187,  165,   23,  187,   25,  194,  205,  174,  175,
 /*  1010 */    71,   72,   69,   70,   71,   72,   73,   74,   75,   76,
 /*  1020 */    77,   78,   79,   80,  150,   82,   83,   84,   85,   86,
 /*  1030 */    87,   88,   89,   90,   91,   92,   19,   98,  150,  165,
 /*  1040 */   150,  160,  150,   59,   25,   53,  104,   22,  174,  175,
 /*  1050 */   213,  138,    5,  165,    1,  165,  150,  165,  150,  150,
 /*  1060 */   240,  150,  174,  175,  174,  175,   49,   50,  118,  150,
 /*  1070 */    35,  165,   27,  165,  165,  194,  165,  108,  127,   76,
 /*  1080 */   174,  175,  174,  175,  165,  174,  175,   70,   71,   72,
 /*  1090 */    73,   74,   75,   76,   77,   78,   79,   80,  166,   82,
 /*  1100 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*  1110 */    19,   20,  193,   22,  150,  150,  150,   26,   27,   76,
 /*  1120 */   150,   22,    1,  150,  119,  121,  217,   20,   37,  165,
 /*  1130 */   165,  165,   16,   19,   20,  165,   22,  205,  165,  119,
 /*  1140 */    26,   27,  108,  128,  150,  150,  150,   56,  150,   22,
 /*  1150 */   150,   37,  150,  127,  160,   23,  150,   66,  193,  165,
 /*  1160 */   165,  165,   16,  165,   23,  165,  150,  165,  174,  175,
 /*  1170 */    56,  165,  150,   65,  174,  175,   15,   86,   87,   88,
 /*  1180 */    66,  165,  140,  150,   93,   94,   95,  165,  194,   98,
 /*  1190 */   174,  175,   22,    3,  164,  193,  174,  175,  165,  150,
 /*  1200 */    86,   87,    4,  180,  150,  248,  251,   93,   94,   95,
 /*  1210 */   216,  180,   98,  251,  165,  221,  150,  149,    6,  165,
 /*  1220 */   129,  130,  131,  132,  133,  134,  193,  150,  174,  175,
 /*  1230 */   116,  165,   19,   20,  150,   22,  149,  151,  150,   26,
 /*  1240 */    27,  149,  165,  129,  130,  131,  132,  133,  134,  165,
 /*  1250 */    37,  174,  175,  165,  149,   19,   20,   13,   22,  150,
 /*  1260 */   150,  150,   26,   27,  146,  147,  151,  150,   25,   56,
 /*  1270 */   152,  159,  154,   37,  165,  165,  165,  193,  160,   66,
 /*  1280 */   116,  193,  165,  174,  175,  174,  175,  194,  199,  150,
 /*  1290 */   200,  126,   56,  124,  123,  150,  201,  122,  150,   86,
 /*  1300 */    87,  150,   66,  193,  165,  202,   93,   94,   95,  150,
 /*  1310 */   165,   98,  194,  165,  125,   22,  165,  150,  150,   26,
 /*  1320 */    27,  135,   86,   87,  165,  174,  175,  203,  226,   93,
 /*  1330 */    94,   95,  165,  165,   98,  150,  218,  150,  193,  157,
 /*  1340 */   118,  157,  129,  130,  131,  132,  133,  134,    5,  104,
 /*  1350 */   165,  211,  165,   10,   11,   12,   13,   14,  150,   66,
 /*  1360 */    17,  174,  175,  210,  246,  129,  130,  131,  132,  133,
 /*  1370 */   134,  150,  210,  165,   31,  121,   33,  150,  150,   86,
 /*  1380 */    87,  176,  174,  175,  150,   42,  165,   94,  211,  210,
 /*  1390 */   150,   98,  165,  165,  211,  174,  175,  150,   55,  165,
 /*  1400 */    57,  150,  174,  175,   61,  165,  150,   64,  174,  175,
 /*  1410 */   150,  150,  165,  150,  174,  175,  165,  104,  150,  184,
 /*  1420 */   150,  165,  129,  130,  131,  165,  165,  150,  165,  150,
 /*  1430 */   150,  176,  150,  165,   47,  165,  150,  150,  176,  103,
 /*  1440 */   150,   22,  165,  178,  165,  165,  179,  165,  105,  106,
 /*  1450 */   107,  165,  165,  229,  111,  165,   92,  176,  229,  116,
 /*  1460 */   184,  176,  179,  156,  176,  176,   18,  157,  156,  237,
 /*  1470 */    45,  157,  156,  135,  157,  157,  238,  156,   68,  157,
 /*  1480 */   189,  189,  139,  219,   22,  157,   18,  192,  192,  192,
 /*  1490 */   192,  189,  219,  199,  157,  242,   40,  157,  199,  242,
 /*  1500 */   153,  157,   38,  245,  196,  166,  232,  198,  177,  177,
 /*  1510 */   232,  227,  209,  178,  166,  182,  166,  148,  177,  177,
 /*  1520 */   209,  196,  177,  199,  209,  199,  166,  208,   92,  195,
 /*  1530 */   174,  174,  183,  252,  183,  183,  252,  191,  252,  235,
 /*  1540 */   186,  241,  241,  252,  186,  252,  252,  252,  252,  252,
 /*  1550 */   252,  252,  252,  252,  252,  252,  236,


};
#define YY_SHIFT_USE_DFLT (-74)
#define YY_SHIFT_COUNT (418)
#define YY_SHIFT_MIN   (-73)
#define YY_SHIFT_MAX   (1468)
static const short yy_shift_ofst[] = {
 /*     0 */   975, 1114, 1343, 1114, 1213, 1213,   90,   90,    0,  -19,
 /*    10 */  1213, 1213, 1213, 1213, 1213,  345,  445,  721, 1091, 1213,
 /*    20 */  1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
 /*    30 */  1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
 /*    40 */  1213, 1213, 1213, 1213, 1213, 1213, 1213, 1236, 1213, 1213,
 /*    50 */  1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
 /*    60 */  1213,  199,  445,  445,  835,  835,  365, 1164,   55,  647,
 /*    70 */   573,  499,  425,  351,  277,  203,  129,  795,  795,  795,
 /*    80 */   795,  795,  795,  795,  795,  795,  795,  795,  795,  795,
 /*    90 */   795,  795,  795,  795,  795,  869,  795,  943, 1017, 1017,
 /*   100 */   -69,  -45,  -45,  -45,  -45,  -45,   -1,   58,  138,  100,
 /*   110 */   445,  445,  445,  445,  445,  445,  445,  445,  445,  445,
 /*   120 */   445,  445,  445,  445,  445,  445,  537,  438,  445,  445,
 /*   130 */   445,  445,  445,  365,  807, 1436,  -74,  -74,  -74, 1293,
 /*   140 */    73,  434,  434,  311,  314,  290,  283,  286,  540,  467,
 /*   150 */   445,  445,  445,  445,  445,  445,  445,  445,  445,  445,
 /*   160 */   445,  445,  445,  445,  445,  445,  445,  445,  445,  445,
 /*   170 */   445,  445,  445,  445,  445,  445,  445,  445,  445,  445,
 /*   180 */   445,  445,   65,  722,  722,  722,  688,  266, 1164, 1164,
 /*   190 */  1164,  -74,  -74,  -74,  136,  168,  168,  234,  360,  360,
 /*   200 */   360,  430,  372,  435,  352,  278,  126,  -36,  -36,  -36,
 /*   210 */   -36,  421,  651,  -36,  -36,  592,  292,  212,  623,  158,
 /*   220 */   204,  204,  505,  158,  505,  144,  365,  154,  365,  154,
 /*   230 */   645,  154,  204,  154,  154,  535,  548,  548,  365,  387,
 /*   240 */   508,  233, 1464, 1222, 1222, 1456, 1456, 1222, 1462, 1410,
 /*   250 */  1165, 1468, 1468, 1468, 1468, 1222, 1165, 1462, 1410, 1410,
 /*   260 */  1222, 1448, 1338, 1425, 1222, 1222, 1448, 1222, 1448, 1222,
 /*   270 */  1448, 1419, 1313, 1313, 1313, 1387, 1364, 1364, 1419, 1313,
 /*   280 */  1336, 1313, 1387, 1313, 1313, 1254, 1245, 1254, 1245, 1254,
 /*   290 */  1245, 1222, 1222, 1186, 1189, 1175, 1169, 1171, 1165, 1164,
 /*   300 */  1243, 1244, 1244, 1212, 1212, 1212, 1212,  -74,  -74,  -74,
 /*   310 */   -74,  -74,  -74,  939,  104,  680,  571,  327,    1,  980,
 /*   320 */    26,  972,  971,  946,  901,  870,  830,  806,   54,   21,
 /*   330 */   -73,  510,  242, 1198, 1190, 1170, 1042, 1161, 1108, 1146,
 /*   340 */  1141, 1132, 1015, 1127, 1026, 1034, 1020, 1107, 1004, 1116,
 /*   350 */  1121, 1005, 1099,  951, 1043, 1003,  969, 1045, 1035,  950,
 /*   360 */  1053, 1047, 1025,  942,  913,  992, 1019,  945,  984,  940,
 /*   370 */   876,  904,  953,  896,  748,  804,  880,  786,  868,  819,
 /*   380 */   805,  810,  773,  751,  766,  706,  716,  691,  681,  568,
 /*   390 */   655,  638,  676,  516,  541,  594,  599,  567,  541,  534,
 /*   400 */   507,  527,  498,  523,  466,  382,  409,  384,  357,    6,
 /*   410 */   240,  224,  143,   62,   18,   71,   39,    9,    5,
};
#define YY_REDUCE_USE_DFLT (-142)
#define YY_REDUCE_COUNT (312)
#define YY_REDUCE_MIN   (-141)
#define YY_REDUCE_MAX   (1369)
static const short yy_reduce_ofst[] = {
 /*     0 */  -141,  994, 1118,  223,  157,  -53,   93,   89,   83,  375,
 /*    10 */   386,  381,  379,  308,  295,  325,  -47,   27, 1240, 1234,
 /*    20 */  1228, 1221, 1208, 1187, 1151, 1111, 1109, 1077, 1054, 1022,
 /*    30 */  1016, 1000,  911,  908,  906,  890,  888,  874,  834,  816,
 /*    40 */   800,  760,  758,  755,  742,  739,  726,  685,  672,  668,
 /*    50 */   665,  652,  611,  609,  607,  604,  591,  578,  526,  519,
 /*    60 */   453,  474,  454,  461,  443,  245,  442,  473,  484,  484,
 /*    70 */   484,  484,  484,  484,  484,  484,  484,  484,  484,  484,
 /*    80 */   484,  484,  484,  484,  484,  484,  484,  484,  484,  484,
 /*    90 */   484,  484,  484,  484,  484,  484,  484,  484,  484,  484,
 /*   100 */   484,  484,  484,  484,  484,  484,  484,  130,  484,  484,
 /*   110 */  1145,  909, 1110, 1088, 1084, 1033, 1002,  965,  820,  837,
 /*   120 */   746,  686,  612,  817,  610,  919,  221,  563,  814,  813,
 /*   130 */   744,  669,  470,  543,  484,  484,  484,  484,  484,  291,
 /*   140 */   569,  671,  658,  970, 1290, 1287, 1286, 1282,  518,  518,
 /*   150 */  1280, 1279, 1277, 1270, 1268, 1263, 1261, 1260, 1256, 1251,
 /*   160 */  1247, 1227, 1185, 1168, 1167, 1159, 1148, 1139, 1117, 1066,
 /*   170 */  1049, 1006,  998,  996,  995,  973,  970,  966,  964,  892,
 /*   180 */   762,  -52,  881,  932,  802,  731,  619,  812,  664,  660,
 /*   190 */   627,  392,  331,  124, 1358, 1357, 1356, 1354, 1352, 1351,
 /*   200 */  1349, 1319, 1334, 1346, 1334, 1334, 1334, 1334, 1334, 1334,
 /*   210 */  1334, 1320, 1304, 1334, 1334, 1319, 1360, 1325, 1369, 1326,
 /*   220 */  1315, 1311, 1301, 1324, 1300, 1335, 1350, 1345, 1348, 1342,
 /*   230 */  1333, 1341, 1303, 1332, 1331, 1284, 1278, 1274, 1339, 1309,
 /*   240 */  1308, 1347, 1258, 1344, 1340, 1257, 1253, 1337, 1273, 1302,
 /*   250 */  1299, 1298, 1297, 1296, 1295, 1328, 1294, 1264, 1292, 1291,
 /*   260 */  1322, 1321, 1238, 1232, 1318, 1317, 1316, 1314, 1312, 1310,
 /*   270 */  1307, 1283, 1289, 1288, 1285, 1276, 1229, 1224, 1267, 1281,
 /*   280 */  1265, 1262, 1235, 1255, 1205, 1183, 1179, 1177, 1162, 1140,
 /*   290 */  1153, 1184, 1182, 1102, 1124, 1103, 1095, 1090, 1089, 1093,
 /*   300 */  1112, 1115, 1086, 1105, 1092, 1087, 1068,  962,  955,  957,
 /*   310 */  1031, 1023, 1030,
};
static const YYACTIONTYPE yy_default[] = {
 /*     0 */   635,  870,  959,  959,  959,  870,  899,  899,  959,  759,
 /*    10 */   959,  959,  959,  959,  868,  959,  959,  933,  959,  959,
 /*    20 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*    30 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*    40 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*    50 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*    60 */   959,  959,  959,  959,  899,  899,  674,  763,  794,  959,
 /*    70 */   959,  959,  959,  959,  959,  959,  959,  932,  934,  809,
 /*    80 */   808,  802,  801,  912,  774,  799,  792,  785,  796,  871,
 /*    90 */   864,  865,  863,  867,  872,  959,  795,  831,  848,  830,
 /*   100 */   842,  847,  854,  846,  843,  833,  832,  666,  834,  835,
 /*   110 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   120 */   959,  959,  959,  959,  959,  959,  661,  728,  959,  959,
 /*   130 */   959,  959,  959,  959,  836,  837,  851,  850,  849,  959,
 /*   140 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   150 */   959,  939,  937,  959,  883,  959,  959,  959,  959,  959,
 /*   160 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   170 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   180 */   959,  641,  959,  759,  759,  759,  635,  959,  959,  959,
 /*   190 */   959,  951,  763,  753,  719,  959,  959,  959,  959,  959,
 /*   200 */   959,  959,  959,  959,  959,  959,  959,  804,  742,  922,
 /*   210 */   924,  959,  905,  740,  663,  761,  676,  751,  643,  798,
 /*   220 */   776,  776,  917,  798,  917,  700,  959,  788,  959,  788,
 /*   230 */   697,  788,  776,  788,  788,  866,  959,  959,  959,  760,
 /*   240 */   751,  959,  944,  767,  767,  936,  936,  767,  810,  732,
 /*   250 */   798,  739,  739,  739,  739,  767,  798,  810,  732,  732,
 /*   260 */   767,  658,  911,  909,  767,  767,  658,  767,  658,  767,
 /*   270 */   658,  876,  730,  730,  730,  715,  880,  880,  876,  730,
 /*   280 */   700,  730,  715,  730,  730,  780,  775,  780,  775,  780,
 /*   290 */   775,  767,  767,  959,  793,  781,  791,  789,  798,  959,
 /*   300 */   718,  651,  651,  640,  640,  640,  640,  956,  956,  951,
 /*   310 */   702,  702,  684,  959,  959,  959,  959,  959,  959,  959,
 /*   320 */   885,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   330 */   959,  959,  959,  959,  636,  946,  959,  959,  943,  959,
 /*   340 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   350 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  915,
 /*   360 */   959,  959,  959,  959,  959,  959,  908,  907,  959,  959,
 /*   370 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   380 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  959,
 /*   390 */   959,  959,  959,  959,  790,  959,  782,  959,  869,  959,
 /*   400 */   959,  959,  959,  959,  959,  959,  959,  959,  959,  745,
 /*   410 */   819,  959,  818,  822,  817,  668,  959,  649,  959,  632,
 /*   420 */   637,  955,  958,  957,  954,  953,  952,  947,  945,  942,
 /*   430 */   941,  940,  938,  935,  931,  889,  887,  894,  893,  892,
 /*   440 */   891,  890,  888,  886,  884,  805,  803,  800,  797,  930,
 /*   450 */   882,  741,  738,  737,  657,  948,  914,  923,  921,  811,
 /*   460 */   920,  919,  918,  916,  913,  900,  807,  806,  733,  874,
 /*   470 */   873,  660,  904,  903,  902,  906,  910,  901,  769,  659,
 /*   480 */   656,  665,  722,  721,  729,  727,  726,  725,  724,  723,
 /*   490 */   720,  667,  675,  686,  714,  699,  698,  879,  881,  878,
 /*   500 */   877,  707,  706,  712,  711,  710,  709,  708,  705,  704,
 /*   510 */   703,  696,  695,  701,  694,  717,  716,  713,  693,  736,
 /*   520 */   735,  734,  731,  692,  691,  690,  822,  689,  688,  828,
 /*   530 */   827,  815,  858,  756,  755,  754,  766,  765,  778,  777,
 /*   540 */   813,  812,  779,  764,  758,  757,  773,  772,  771,  770,
 /*   550 */   762,  752,  784,  787,  786,  783,  860,  768,  857,  929,
 /*   560 */   928,  927,  926,  925,  862,  861,  829,  826,  679,  680,
 /*   570 */   898,  896,  897,  895,  682,  681,  678,  677,  859,  747,
 /*   580 */   746,  855,  852,  844,  840,  856,  853,  845,  841,  839,
 /*   590 */   838,  824,  823,  821,  820,  816,  825,  670,  748,  744,
 /*   600 */   743,  814,  750,  749,  687,  685,  683,  664,  662,  655,
 /*   610 */   653,  652,  654,  650,  648,  647,  646,  645,  644,  673,
 /*   620 */   672,  671,  669,  668,  642,  639,  638,  634,  633,  631,
};

/* The next table maps tokens into fallback tokens.  If a construct
** like the following:
** 
**      %fallback ID X Y Z.
**







|

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


|

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|


|
|
|
|
|
|
|

|
|
|
|
|

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

|
|
|
|
|


|
|
|
|
|
|


|
|
|
|
|


|
|
|
|
|
|

|
|
|
|
|
|
|

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

|
|
|
|

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

|
|
|
|

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


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







107965
107966
107967
107968
107969
107970
107971
107972
107973
107974
107975
107976
107977
107978
107979
107980
107981
107982
107983
107984
107985
107986
107987
107988
107989
107990
107991
107992
107993
107994
107995
107996
107997
107998
107999
108000
108001
108002
108003
108004
108005
108006
108007
108008
108009
108010
108011
108012
108013
108014
108015
108016
108017
108018
108019
108020
108021
108022
108023
108024
108025
108026
108027
108028
108029
108030
108031
108032
108033
108034
108035
108036
108037
108038
108039
108040
108041
108042
108043
108044
108045
108046
108047
108048
108049
108050
108051
108052
108053
108054
108055
108056
108057
108058
108059
108060
108061
108062
108063
108064
108065
108066
108067
108068
108069
108070
108071
108072
108073
108074
108075
108076
108077
108078
108079
108080
108081
108082
108083
108084
108085
108086
108087
108088
108089
108090
108091
108092
108093
108094
108095
108096
108097
108098
108099
108100
108101
108102
108103
108104
108105
108106
108107
108108
108109
108110
108111
108112
108113
108114
108115
108116
108117
108118
108119
108120
108121
108122
108123
108124
108125
108126
108127
108128
108129
108130
108131
108132
108133
108134
108135
108136
108137
108138
108139
108140
108141
108142
108143
108144
108145
108146
108147
108148
108149
108150
108151
108152
108153
108154
108155
108156
108157
108158
108159
108160
108161
108162
108163
108164
108165
108166
108167
108168
108169
108170
108171
108172
108173
108174
108175
108176
108177
108178
108179
108180
108181
108182
108183
108184
108185
108186
108187
108188
108189
108190
108191
108192
108193
108194
108195
108196
108197
108198
108199
108200
108201
108202
108203
108204
108205
108206
108207
108208
108209
108210
108211
108212
108213
108214
108215
108216
108217
108218
108219
108220
108221
108222
108223
108224
108225
108226
108227
108228
108229
108230
108231
108232
108233
108234
108235
108236
108237
108238
108239
108240
108241
108242
108243
108244
108245
108246
108247
108248
108249
108250
108251
108252
108253
108254
108255
108256
108257
108258
108259
108260
108261
108262
108263
108264
108265
108266
108267
108268
108269
108270
108271
108272
108273
108274
108275
108276
108277
108278
108279
108280
108281
108282
108283
108284
108285
108286
108287
108288
108289
108290
108291
108292
108293
108294
108295
108296
108297
108298
108299
108300
108301
108302
108303
108304
108305
108306
108307
108308
108309
108310
108311
108312
108313
108314
108315
108316
108317
108318
108319
108320
108321
108322
108323
108324
108325
108326
108327
108328
108329
108330
108331
108332
108333
108334
108335
108336
108337
108338
108339
108340
108341
108342
108343
108344
108345
108346
108347
108348
108349
108350
108351
108352
108353
108354
108355
108356
108357
108358
108359
108360
108361
108362
108363
108364
108365
108366
108367
108368
108369
108370
108371
108372
108373
108374
108375
108376

108377
108378
108379
108380
108381
108382
108383
108384
108385
108386
108387
108388
108389
108390
108391
108392
108393
108394
108395
108396
108397
108398
108399
108400
108401
108402
108403
108404
108405
108406
108407
108408
108409
108410
108411
108412
108413
108414
108415
108416
108417
108418
108419
108420
108421
108422
108423
108424
108425
108426
108427
108428
108429
108430
108431
108432
108433
108434
108435
108436
108437
108438
108439
108440
108441
108442
108443
108444
108445
108446
108447
108448
**                     yy_action.  Used to detect hash collisions.
**  yy_shift_ofst[]    For each state, the offset into yy_action for
**                     shifting terminals.
**  yy_reduce_ofst[]   For each state, the offset into yy_action for
**                     shifting non-terminals after a reduce.
**  yy_default[]       Default action for each state.
*/
#define YY_ACTTAB_COUNT (1580)
static const YYACTIONTYPE yy_action[] = {
 /*     0 */   310,  328,  574,  573,   15,  172,  187,  596,   56,   56,
 /*    10 */    56,   56,   49,   54,   54,   54,   54,   53,   53,   52,
 /*    20 */    52,   52,   51,  234,  622,  621,  626,  622,  621,  299,
 /*    30 */   589,  583,   56,   56,   56,   56,  236,   54,   54,   54,
 /*    40 */    54,   53,   53,   52,   52,   52,   51,  234,  351,   57,
 /*    50 */    58,   48,  581,  580,  582,  582,   55,   55,   56,   56,
 /*    60 */    56,   56,  570,   54,   54,   54,   54,   53,   53,   52,
 /*    70 */    52,   52,   51,  234,  310,  596,  326,  607,  233,  232,
 /*    80 */    33,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*    90 */    51,  234,  619,  618,  326,  619,  618,  166,  605,  492,
 /*   100 */   381,  378,  377,  235,  589,  583,  554,  495,    1,   59,
 /*   110 */    19,  376,  622,  621,   53,   53,   52,   52,   52,   51,
 /*   120 */   234,  571,  571,   57,   58,   48,  581,  580,  582,  582,
 /*   130 */    55,   55,   56,   56,   56,   56,  215,   54,   54,   54,
 /*   140 */    54,   53,   53,   52,   52,   52,   51,  234,  310,  224,
 /*   150 */    50,   47,  147,  177,  139,  281,  384,  276,  383,  169,
 /*   160 */   408,  553,  578,  578,  622,  621,  272,  224,  439,  550,
 /*   170 */   552,  410,  139,  281,  384,  276,  383,  169,  589,  583,
 /*   180 */   619,  618,  280,  620,  272,  195,  413,  309,  440,  441,
 /*   190 */   567,  491,  214,  279,  560,  600,   92,   57,   58,   48,
 /*   200 */   581,  580,  582,  582,   55,   55,   56,   56,   56,   56,
 /*   210 */   559,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   220 */    51,  234,  310,  464,  233,  232,  558,  133,  519,   50,
 /*   230 */    47,  147,  619,  618,  565,  436,  397,  515,  514,  518,
 /*   240 */   410,  387,  438,  389,  437,  622,  621,  442,  570,  433,
 /*   250 */   203,  390,  589,  583,    6,  413,  166,  670,  250,  381,
 /*   260 */   378,  377,  525,  190,  600,   92,  594,  571,  571,  465,
 /*   270 */   376,   57,   58,   48,  581,  580,  582,  582,   55,   55,
 /*   280 */    56,   56,   56,   56,  599,   54,   54,   54,   54,   53,
 /*   290 */    53,   52,   52,   52,   51,  234,  310,  592,  592,  592,
 /*   300 */   490,  182,  247,  548,  249,  397,  273,  410,    7,  439,
 /*   310 */   398,  606,   67,  619,  618,  620,  472,  256,  347,  255,
 /*   320 */   473,  620,  413,  576,  620,   65,  589,  583,  236,  440,
 /*   330 */   336,  600,   92,   68,  364,  192,  481,  622,  621,  547,
 /*   340 */   622,  621,  560,  323,  207,   57,   58,   48,  581,  580,
 /*   350 */   582,  582,   55,   55,   56,   56,   56,   56,  559,   54,
 /*   360 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  234,
 /*   370 */   310,  410,  397,  146,  558,  531,  401,  348,  599,  166,
 /*   380 */   248,  204,  381,  378,  377,  541,  413,  171,  337,  570,
 /*   390 */   622,  621,   40,  376,   38,  600,   74,  465,  548,  490,
 /*   400 */   589,  583,  532,  350,  579,  619,  618,  297,  619,  618,
 /*   410 */   480,   67,  470,   39,  620,  599,  406,  574,  573,   57,
 /*   420 */    58,   48,  581,  580,  582,  582,   55,   55,   56,   56,
 /*   430 */    56,   56,  577,   54,   54,   54,   54,   53,   53,   52,
 /*   440 */    52,   52,   51,  234,  310,  256,  347,  255,  530,   52,
 /*   450 */    52,   52,   51,  234,  345,  564,  236,  386,  619,  618,
 /*   460 */   957,  185,  418,    2,  408,  410,  578,  578,  198,  197,
 /*   470 */   196,  499,  183,  167,  589,  583,  671,  570,  505,  506,
 /*   480 */   413,  267,  601,  672,  546,  208,  602,   36,  601,  600,
 /*   490 */    91,  468,  602,   57,   58,   48,  581,  580,  582,  582,
 /*   500 */    55,   55,   56,   56,   56,   56,  202,   54,   54,   54,
 /*   510 */    54,   53,   53,   52,   52,   52,   51,  234,  310,  599,
 /*   520 */   157,  408,  527,  578,  578,  263,  490,  265,  410,  873,
 /*   530 */   410,  474,  474,  366,  373,  410,  504,  428,   67,  290,
 /*   540 */   599,  620,  352,  413,  408,  413,  578,  578,  589,  583,
 /*   550 */   413,  382,  600,   92,  600,   16,  543,   62,  503,  600,
 /*   560 */    92,  408,  346,  578,  578,  168,   45,   57,   58,   48,
 /*   570 */   581,  580,  582,  582,   55,   55,   56,   56,   56,   56,
 /*   580 */   200,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   590 */    51,  234,  310,  393,  395,  534,  510,  617,  616,  615,
 /*   600 */   318,  314,  172,   66,  596,  410,  338,  596,  324,  571,
 /*   610 */   571,   50,   47,  147,  599,  629,  627,  330,  539,  315,
 /*   620 */   413,   30,  589,  583,  272,  236,  199,  144,  176,  600,
 /*   630 */    73,  420,  947,  620,  947,  420,  946,  351,  946,  175,
 /*   640 */   596,   57,   58,   48,  581,  580,  582,  582,   55,   55,
 /*   650 */    56,   56,   56,   56,  410,   54,   54,   54,   54,   53,
 /*   660 */    53,   52,   52,   52,   51,  234,  310,  261,  410,  413,
 /*   670 */   269,  208,  596,  363,  410,  596,  424,  360,  600,   69,
 /*   680 */   424,  327,  620,  413,   50,   47,  147,  410,  358,  413,
 /*   690 */   575,  553,  600,   94,  483,  509,  589,  583,  600,   97,
 /*   700 */   552,  484,  413,  620,  188,  599,  551,  563,  596,  566,
 /*   710 */   334,  600,   95,  205,  201,   57,   58,   48,  581,  580,
 /*   720 */   582,  582,   55,   55,   56,   56,   56,   56,  352,   54,
 /*   730 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  234,
 /*   740 */   310,  410,  261,  410,  167,   22,  356,  599,  359,  623,
 /*   750 */    50,   47,  147,  548,  357,  562,  413,  620,  413,  332,
 /*   760 */   523,  270,  410,  167,  620,  600,  104,  600,  103,  603,
 /*   770 */   589,  583,  339,  539,  304,  423,  222,  413,  174,  304,
 /*   780 */   422,  561,  567,  405,  214,  260,  600,  106,  620,   57,
 /*   790 */    58,   48,  581,  580,  582,  582,   55,   55,   56,   56,
 /*   800 */    56,   56,  410,   54,   54,   54,   54,   53,   53,   52,
 /*   810 */    52,   52,   51,  234,  310,  410,  557,  413,  410,  421,
 /*   820 */   273,   35,  512,  146,  421,   12,  600,  107,  213,  144,
 /*   830 */   413,  410,   32,  413,  410,  620,  365,  353,  358,  600,
 /*   840 */   134,   11,  600,  135,  589,  583,  413,   21,  548,  413,
 /*   850 */   316,  148,  620,  620,  170,  600,   98,  223,  600,  102,
 /*   860 */   374,  168,  167,   57,   58,   48,  581,  580,  582,  582,
 /*   870 */    55,   55,   56,   56,   56,   56,  410,   54,   54,   54,
 /*   880 */    54,   53,   53,   52,   52,   52,   51,  234,  310,  410,
 /*   890 */   273,  413,  410,  273,  212,  469,  410,  167,  628,    2,
 /*   900 */   600,  101,  545,  221,  413,  620,  130,  413,  620,  410,
 /*   910 */   539,  413,  537,  600,   93,  315,  600,  100,  589,  583,
 /*   920 */   600,   77,  425,  305,  413,  620,  254,  322,  599,  458,
 /*   930 */   320,  171,  543,  600,   96,  521,  520,   57,   58,   48,
 /*   940 */   581,  580,  582,  582,   55,   55,   56,   56,   56,   56,
 /*   950 */   410,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   960 */    51,  234,  310,  410,  273,  413,  410,  457,  358,   35,
 /*   970 */   426,  230,  306,  319,  600,  138,  467,  520,  413,  620,
 /*   980 */   143,  413,  410,  620,  410,  353,  529,  600,  137,  142,
 /*   990 */   600,  136,  589,  583,  604,  261,  528,  413,  229,  413,
 /*  1000 */   620,  321,  495,   28,  543,  543,  600,   76,  600,   90,
 /*  1010 */   620,   57,   46,   48,  581,  580,  582,  582,   55,   55,
 /*  1020 */    56,   56,   56,   56,  410,   54,   54,   54,   54,   53,
 /*  1030 */    53,   52,   52,   52,   51,  234,  310,  261,  451,  413,
 /*  1040 */   410,  211,  611,  285,  283,  610,  609,  502,  600,   89,
 /*  1050 */   380,  217,  620,  128,  140,  413,  220,  620,  410,  409,
 /*  1060 */   620,  620,  588,  587,  600,   75,  589,  583,  271,  620,
 /*  1070 */    51,  234,  127,  413,  620,  599,  627,  330,   27,  375,
 /*  1080 */   449,  279,  600,   88,  585,  584,   58,   48,  581,  580,
 /*  1090 */   582,  582,   55,   55,   56,   56,   56,   56,  410,   54,
 /*  1100 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  234,
 /*  1110 */   310,  586,  410,  413,  410,  261,  593,  165,  399,  556,
 /*  1120 */   126,  371,  600,   87,  478,  186,  123,  413,  367,  413,
 /*  1130 */   620,  620,  410,  620,  620,  410,  600,   99,  600,   86,
 /*  1140 */   589,  583,  475,  122,  258,  171,  471,  413,  160,  121,
 /*  1150 */   413,   14,  159,  463,   25,   24,  600,   17,  448,  600,
 /*  1160 */    85,   48,  581,  580,  582,  582,   55,   55,   56,   56,
 /*  1170 */    56,   56,  158,   54,   54,   54,   54,   53,   53,   52,
 /*  1180 */    52,   52,   51,  234,   44,  404,  261,    3,  544,  261,
 /*  1190 */   540,  414,  621,  460,  119,  118,  538,  275,   10,  349,
 /*  1200 */     4,  620,  407,  620,  620,  620,  116,   44,  404,  410,
 /*  1210 */     3,  620,  620,  410,  414,  621,  456,  454,  252,  450,
 /*  1220 */   508,  402,  111,  109,  413,  407,  155,  444,  413,  447,
 /*  1230 */   435,  565,  219,  600,   84,  620,  108,  600,   83,   64,
 /*  1240 */   434,  417,  625,  150,  402,  333,  410,  237,  238,  124,
 /*  1250 */   274,   41,   42,  533,  565,  206,  189,  261,   43,  412,
 /*  1260 */   411,  413,  261,  594,  488,  620,  329,  149,  419,  268,
 /*  1270 */   600,   72,  620,  266,   41,   42,  181,  620,  410,  620,
 /*  1280 */   105,   43,  412,  411,  620,  624,  594,  614,  620,  599,
 /*  1290 */   228,  125,  313,  413,  592,  592,  592,  591,  590,   13,
 /*  1300 */   218,  410,  600,   71,  236,  244,   44,  404,  264,    3,
 /*  1310 */   312,  613,  340,  414,  621,  180,  413,  592,  592,  592,
 /*  1320 */   591,  590,   13,  620,  407,  600,   82,  410,  416,   34,
 /*  1330 */   404,  410,    3,  410,  262,  410,  414,  621,  612,  331,
 /*  1340 */   178,  415,  413,  402,    8,  236,  413,  407,  413,  620,
 /*  1350 */   413,  600,   81,  565,  257,  600,   80,  600,   70,  600,
 /*  1360 */    18,  598,  361,  462,  461,   30,  402,  294,   31,  620,
 /*  1370 */   293,  354,  251,   41,   42,  410,  565,  620,  620,  620,
 /*  1380 */    43,  412,  411,  453,  396,  594,  620,  620,  394,   61,
 /*  1390 */   413,  292,  443,  622,  621,  243,   41,   42,  620,  600,
 /*  1400 */    79,  597,  291,   43,  412,  411,   60,  620,  594,  240,
 /*  1410 */   620,  410,  231,   37,  555,  173,  592,  592,  592,  591,
 /*  1420 */   590,   13,  216,  239,  620,  184,  413,  302,  301,  300,
 /*  1430 */   179,  298,  388,  565,  452,  600,   78,  286,  620,  592,
 /*  1440 */   592,  592,  591,  590,   13,  429,   29,  413,  151,  289,
 /*  1450 */   242,  145,  392,  194,  193,  288,  600,    9,  542,  241,
 /*  1460 */   620,  525,  391,  284,  620,  594,  620,  620,  522,  536,
 /*  1470 */   620,  535,  153,  385,  465,  516,  282,  325,  154,  517,
 /*  1480 */   277,  152,  512,  511,  513,  129,  226,  308,  487,  486,
 /*  1490 */   485,  164,  372,  493,  307,  227,  592,  592,  592,  225,
 /*  1500 */   479,  163,  368,  370,  162,  476,  210,  477,   26,  259,
 /*  1510 */   161,  466,  362,  141,  132,  120,  117,  455,  156,  115,
 /*  1520 */   344,  343,  256,  342,  245,  114,  113,  446,  311,  112,
 /*  1530 */    23,  317,  432,  236,  131,  431,  110,  430,   20,  427,
 /*  1540 */   608,  595,  295,   63,  379,  287,  509,  191,  278,  403,
 /*  1550 */   572,  569,  497,  498,  496,  494,  335,  459,  445,  303,
 /*  1560 */   296,  246,  341,  355,    5,  568,  369,  507,  253,  549,
 /*  1570 */   526,  209,  400,  501,  500,  524,  234,  958,  489,  482,
};
static const YYCODETYPE yy_lookahead[] = {
 /*     0 */    19,  169,  170,  171,   22,   24,   24,   26,   77,   78,
 /*    10 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
 /*    20 */    89,   90,   91,   92,   26,   27,    1,   26,   27,   15,
 /*    30 */    49,   50,   77,   78,   79,   80,  116,   82,   83,   84,
 /*    40 */    85,   86,   87,   88,   89,   90,   91,   92,  128,   68,
 /*    50 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*    60 */    79,   80,  230,   82,   83,   84,   85,   86,   87,   88,
 /*    70 */    89,   90,   91,   92,   19,   94,   19,   23,   86,   87,
 /*    80 */    25,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*    90 */    91,   92,   94,   95,   19,   94,   95,   96,  172,  173,
 /*   100 */    99,  100,  101,  197,   49,   50,  177,  181,   22,   54,
 /*   110 */   204,  110,   26,   27,   86,   87,   88,   89,   90,   91,
 /*   120 */    92,  129,  130,   68,   69,   70,   71,   72,   73,   74,
 /*   130 */    75,   76,   77,   78,   79,   80,   22,   82,   83,   84,
 /*   140 */    85,   86,   87,   88,   89,   90,   91,   92,   19,   92,
 /*   150 */   221,  222,  223,   96,   97,   98,   99,  100,  101,  102,
 /*   160 */   112,   32,  114,  115,   26,   27,  109,   92,  150,   25,
 /*   170 */    41,  150,   97,   98,   99,  100,  101,  102,   49,   50,
 /*   180 */    94,   95,   98,  165,  109,   25,  165,  163,  170,  171,
 /*   190 */   166,  167,  168,  109,   12,  174,  175,   68,   69,   70,
 /*   200 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   210 */    28,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   220 */    91,   92,   19,   11,   86,   87,   44,   24,   46,  221,
 /*   230 */   222,  223,   94,   95,   66,   97,  215,    7,    8,   57,
 /*   240 */   150,  220,  104,   19,  106,   26,   27,  229,  230,  241,
 /*   250 */   160,   27,   49,   50,   22,  165,   96,  118,   16,   99,
 /*   260 */   100,  101,   94,  119,  174,  175,   98,  129,  130,   57,
 /*   270 */   110,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   280 */    77,   78,   79,   80,  194,   82,   83,   84,   85,   86,
 /*   290 */    87,   88,   89,   90,   91,   92,   19,  129,  130,  131,
 /*   300 */   150,   23,   60,   25,   62,  215,  150,  150,   76,  150,
 /*   310 */   220,  161,  162,   94,   95,  165,   30,  105,  106,  107,
 /*   320 */    34,  165,  165,   23,  165,   25,   49,   50,  116,  170,
 /*   330 */   171,  174,  175,   22,   48,  185,  186,   26,   27,  120,
 /*   340 */    26,   27,   12,  187,  160,   68,   69,   70,   71,   72,
 /*   350 */    73,   74,   75,   76,   77,   78,   79,   80,   28,   82,
 /*   360 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   370 */    19,  150,  215,   95,   44,   23,   46,  220,  194,   96,
 /*   380 */   138,  160,   99,  100,  101,   23,  165,   25,  229,  230,
 /*   390 */    26,   27,  135,  110,  137,  174,  175,   57,  120,  150,
 /*   400 */    49,   50,   88,  219,  113,   94,   95,  158,   94,   95,
 /*   410 */   161,  162,   21,  136,  165,  194,  169,  170,  171,   68,
 /*   420 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   430 */    79,   80,   23,   82,   83,   84,   85,   86,   87,   88,
 /*   440 */    89,   90,   91,   92,   19,  105,  106,  107,   23,   88,
 /*   450 */    89,   90,   91,   92,   63,   23,  116,   88,   94,   95,
 /*   460 */   142,  143,  144,  145,  112,  150,  114,  115,  105,  106,
 /*   470 */   107,   23,   23,   25,   49,   50,  118,  230,   97,   98,
 /*   480 */   165,   16,  113,  118,  120,  160,  117,  136,  113,  174,
 /*   490 */   175,  100,  117,   68,   69,   70,   71,   72,   73,   74,
 /*   500 */    75,   76,   77,   78,   79,   80,  160,   82,   83,   84,
 /*   510 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  194,
 /*   520 */    25,  112,   23,  114,  115,   60,  150,   62,  150,  138,
 /*   530 */   150,  105,  106,  107,   19,  150,   36,  161,  162,  224,
 /*   540 */   194,  165,  217,  165,  112,  165,  114,  115,   49,   50,
 /*   550 */   165,   51,  174,  175,  174,  175,  166,  232,   58,  174,
 /*   560 */   175,  112,  237,  114,  115,   50,   22,   68,   69,   70,
 /*   570 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   580 */   160,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   590 */    91,   92,   19,  215,  214,  205,   23,    7,    8,    9,
 /*   600 */   215,  155,   24,   22,   26,  150,   97,   26,  108,  129,
 /*   610 */   130,  221,  222,  223,  194,    0,    1,    2,  150,  104,
 /*   620 */   165,  126,   49,   50,  109,  116,  206,  207,  118,  174,
 /*   630 */   175,   22,   23,  165,   25,   22,   23,  128,   25,  118,
 /*   640 */    26,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   650 */    77,   78,   79,   80,  150,   82,   83,   84,   85,   86,
 /*   660 */    87,   88,   89,   90,   91,   92,   19,  150,  150,  165,
 /*   670 */    23,  160,   94,  227,  150,   94,   67,  231,  174,  175,
 /*   680 */    67,  213,  165,  165,  221,  222,  223,  150,  150,  165,
 /*   690 */    23,   32,  174,  175,  181,  182,   49,   50,  174,  175,
 /*   700 */    41,  188,  165,  165,   22,  194,  177,   11,   94,   23,
 /*   710 */   193,  174,  175,  160,   22,   68,   69,   70,   71,   72,
 /*   720 */    73,   74,   75,   76,   77,   78,   79,   80,  217,   82,
 /*   730 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   740 */    19,  150,  150,  150,   25,   24,   19,  194,  237,  150,
 /*   750 */   221,  222,  223,   25,   27,   23,  165,  165,  165,  242,
 /*   760 */   165,   23,  150,   25,  165,  174,  175,  174,  175,  174,
 /*   770 */    49,   50,  219,  150,   22,   23,  238,  165,   25,   22,
 /*   780 */    23,   23,  166,  167,  168,  193,  174,  175,  165,   68,
 /*   790 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   800 */    79,   80,  150,   82,   83,   84,   85,   86,   87,   88,
 /*   810 */    89,   90,   91,   92,   19,  150,   23,  165,  150,   67,
 /*   820 */   150,   25,  103,   95,   67,   35,  174,  175,  206,  207,
 /*   830 */   165,  150,   25,  165,  150,  165,  213,  150,  150,  174,
 /*   840 */   175,   35,  174,  175,   49,   50,  165,   52,  120,  165,
 /*   850 */   245,  246,  165,  165,   35,  174,  175,  187,  174,  175,
 /*   860 */    23,   50,   25,   68,   69,   70,   71,   72,   73,   74,
 /*   870 */    75,   76,   77,   78,   79,   80,  150,   82,   83,   84,
 /*   880 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  150,
 /*   890 */   150,  165,  150,  150,  160,   23,  150,   25,  144,  145,
 /*   900 */   174,  175,  120,  216,  165,  165,   22,  165,  165,  150,
 /*   910 */   150,  165,   27,  174,  175,  104,  174,  175,   49,   50,
 /*   920 */   174,  175,  247,  248,  165,  165,  238,  187,  194,   23,
 /*   930 */   187,   25,  166,  174,  175,  190,  191,   68,   69,   70,
 /*   940 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   950 */   150,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   960 */    91,   92,   19,  150,  150,  165,  150,   23,  150,   25,
 /*   970 */    23,  205,   25,  213,  174,  175,  190,  191,  165,  165,
 /*   980 */   118,  165,  150,  165,  150,  150,   23,  174,  175,   39,
 /*   990 */   174,  175,   49,   50,  173,  150,   23,  165,   52,  165,
 /*  1000 */   165,  187,  181,   22,  166,  166,  174,  175,  174,  175,
 /*  1010 */   165,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*  1020 */    77,   78,   79,   80,  150,   82,   83,   84,   85,   86,
 /*  1030 */    87,   88,   89,   90,   91,   92,   19,  150,  193,  165,
 /*  1040 */   150,  160,  150,  205,  205,  150,  150,   29,  174,  175,
 /*  1050 */    52,  216,  165,   22,  150,  165,  238,  165,  150,  150,
 /*  1060 */   165,  165,   49,   50,  174,  175,   49,   50,   23,  165,
 /*  1070 */    91,   92,   22,  165,  165,  194,    1,    2,   22,   52,
 /*  1080 */   193,  109,  174,  175,   71,   72,   69,   70,   71,   72,
 /*  1090 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
 /*  1100 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*  1110 */    19,   98,  150,  165,  150,  150,  150,  102,  150,  150,
 /*  1120 */    22,   19,  174,  175,   20,   24,  104,  165,   43,  165,
 /*  1130 */   165,  165,  150,  165,  165,  150,  174,  175,  174,  175,
 /*  1140 */    49,   50,   59,   53,  138,   25,   53,  165,  104,   22,
 /*  1150 */   165,    5,  118,    1,   76,   76,  174,  175,  193,  174,
 /*  1160 */   175,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*  1170 */    79,   80,   35,   82,   83,   84,   85,   86,   87,   88,
 /*  1180 */    89,   90,   91,   92,   19,   20,  150,   22,  150,  150,
 /*  1190 */   150,   26,   27,   27,  108,  127,  150,  150,   22,   25,
 /*  1200 */    22,  165,   37,  165,  165,  165,  119,   19,   20,  150,
 /*  1210 */    22,  165,  165,  150,   26,   27,   23,    1,   16,   20,
 /*  1220 */   150,   56,  119,  108,  165,   37,  121,  128,  165,  193,
 /*  1230 */    23,   66,  193,  174,  175,  165,  127,  174,  175,   16,
 /*  1240 */    23,  146,  147,   15,   56,   65,  150,  152,  140,  154,
 /*  1250 */   150,   86,   87,   88,   66,  160,   22,  150,   93,   94,
 /*  1260 */    95,  165,  150,   98,  150,  165,    3,  246,    4,  150,
 /*  1270 */   174,  175,  165,  150,   86,   87,    6,  165,  150,  165,
 /*  1280 */   164,   93,   94,   95,  165,  149,   98,  149,  165,  194,
 /*  1290 */   180,  180,  249,  165,  129,  130,  131,  132,  133,  134,
 /*  1300 */   193,  150,  174,  175,  116,  193,   19,   20,  150,   22,
 /*  1310 */   249,  149,  217,   26,   27,  151,  165,  129,  130,  131,
 /*  1320 */   132,  133,  134,  165,   37,  174,  175,  150,  149,   19,
 /*  1330 */    20,  150,   22,  150,  150,  150,   26,   27,   13,  244,
 /*  1340 */   151,  159,  165,   56,   25,  116,  165,   37,  165,  165,
 /*  1350 */   165,  174,  175,   66,  150,  174,  175,  174,  175,  174,
 /*  1360 */   175,  194,  150,  150,  150,  126,   56,  199,  124,  165,
 /*  1370 */   200,  150,  150,   86,   87,  150,   66,  165,  165,  165,
 /*  1380 */    93,   94,   95,  150,  122,   98,  165,  165,  123,   22,
 /*  1390 */   165,  201,  150,   26,   27,  150,   86,   87,  165,  174,
 /*  1400 */   175,  203,  202,   93,   94,   95,  125,  165,   98,  150,
 /*  1410 */   165,  150,  225,  135,  157,  118,  129,  130,  131,  132,
 /*  1420 */   133,  134,    5,  150,  165,  157,  165,   10,   11,   12,
 /*  1430 */    13,   14,  150,   66,   17,  174,  175,  210,  165,  129,
 /*  1440 */   130,  131,  132,  133,  134,  150,  104,  165,   31,  150,
 /*  1450 */    33,  150,  150,   86,   87,  150,  174,  175,  211,   42,
 /*  1460 */   165,   94,  121,  210,  165,   98,  165,  165,  176,  211,
 /*  1470 */   165,  211,   55,  104,   57,  184,  210,   47,   61,  176,
 /*  1480 */   176,   64,  103,  176,  178,   22,   92,  179,  176,  176,
 /*  1490 */   176,  156,   18,  184,  179,  228,  129,  130,  131,  228,
 /*  1500 */   157,  156,   45,  157,  156,  236,  157,  157,  135,  235,
 /*  1510 */   156,  189,  157,   68,  218,  189,   22,  199,  156,  192,
 /*  1520 */   157,   18,  105,  106,  107,  192,  192,  199,  111,  192,
 /*  1530 */   240,  157,   40,  116,  218,  157,  189,  157,  240,   38,
 /*  1540 */   153,  166,  198,  243,  178,  209,  182,  196,  177,  226,
 /*  1550 */   230,  230,  166,  177,  177,  166,  139,  199,  199,  148,
 /*  1560 */   195,  209,  209,  239,  196,  166,  234,  183,  239,  208,
 /*  1570 */   174,  233,  191,  183,  183,  174,   92,  250,  186,  186,
};
#define YY_SHIFT_USE_DFLT (-81)
#define YY_SHIFT_COUNT (417)
#define YY_SHIFT_MIN   (-80)
#define YY_SHIFT_MAX   (1503)
static const short yy_shift_ofst[] = {
 /*     0 */  1075, 1188, 1417, 1188, 1287, 1287,  138,  138,    1,  -19,
 /*    10 */  1287, 1287, 1287, 1287,  340,   -2,  129,  129,  795, 1165,
 /*    20 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    30 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    40 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
 /*    50 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    60 */  1287, 1287,  212,   -2,   -2,   -8,   -8,  614, 1229,   55,
 /*    70 */   721,  647,  573,  499,  425,  351,  277,  203,  869,  869,
 /*    80 */   869,  869,  869,  869,  869,  869,  869,  869,  869,  869,
 /*    90 */   869,  869,  869,  943,  869, 1017, 1091, 1091,  -69,  -45,
 /*   100 */   -45,  -45,  -45,  -45,   -1,   57,   28,  361,   -2,   -2,
 /*   110 */    -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
 /*   120 */    -2,   -2,   -2,   -2,  391,  515,   -2,   -2,   -2,   -2,
 /*   130 */    -2,  509,  -80,  614,  979, 1484,  -81,  -81,  -81, 1367,
 /*   140 */    75,  182,  182,  314,  311,  364,  219,   86,  613,  609,
 /*   150 */    -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
 /*   160 */    -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
 /*   170 */    -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
 /*   180 */    -2,   -2,  578,  578,  578,  615, 1229, 1229, 1229,  -81,
 /*   190 */   -81,  -81,  160,  168,  168,  283,  500,  500,  500,  278,
 /*   200 */   449,  330,  432,  409,  352,   48,   48,   48,   48,  426,
 /*   210 */   286,   48,   48,  728,  581,  369,  590,  495,  224,  224,
 /*   220 */   727,  495,  727,  719,  614,  659,  614,  659,  811,  659,
 /*   230 */   224,  257,  480,  480,  614,  144,  375,  -18, 1501, 1297,
 /*   240 */  1297, 1492, 1492, 1297, 1494, 1445, 1239, 1503, 1503, 1503,
 /*   250 */  1503, 1297, 1474, 1239, 1494, 1445, 1445, 1297, 1474, 1373,
 /*   260 */  1457, 1297, 1297, 1474, 1297, 1474, 1297, 1474, 1463, 1369,
 /*   270 */  1369, 1369, 1430, 1394, 1394, 1463, 1369, 1379, 1369, 1430,
 /*   280 */  1369, 1369, 1341, 1342, 1341, 1342, 1341, 1342, 1297, 1297,
 /*   290 */  1278, 1281, 1262, 1244, 1265, 1239, 1229, 1319, 1325, 1325,
 /*   300 */  1270, 1270, 1270, 1270,  -81,  -81,  -81,  -81,  -81,  -81,
 /*   310 */  1013,  242,  757,  752,  465,  363,  947,  232,  944,  906,
 /*   320 */   872,  837,  738,  448,  381,  230,   84,  362,  300, 1264,
 /*   330 */  1263, 1234, 1108, 1228, 1180, 1223, 1217, 1207, 1099, 1174,
 /*   340 */  1109, 1115, 1103, 1199, 1105, 1202, 1216, 1087, 1193, 1178,
 /*   350 */  1174, 1176, 1068, 1079, 1078, 1086, 1166, 1137, 1034, 1152,
 /*   360 */  1146, 1127, 1044, 1006, 1093, 1120, 1090, 1083, 1085, 1022,
 /*   370 */  1101, 1104, 1102,  972, 1015, 1098, 1027, 1056, 1050, 1045,
 /*   380 */  1031,  998, 1018,  981,  946,  950,  973,  963,  862,  885,
 /*   390 */   819,  884,  782,  796,  806,  807,  790,  796,  793,  758,
 /*   400 */   753,  732,  692,  696,  682,  686,  667,  544,  291,  521,
 /*   410 */   510,  365,  358,  139,  114,   54,   14,   25,
};
#define YY_REDUCE_USE_DFLT (-169)
#define YY_REDUCE_COUNT (309)
#define YY_REDUCE_MIN   (-168)
#define YY_REDUCE_MAX   (1411)
static const short yy_reduce_ofst[] = {
 /*     0 */   318,   90, 1095,  221,  157,   21,  159,   18,  150,  390,
 /*    10 */   385,  378,  380,  315,  325,  249,  529,  -71,    8, 1282,
 /*    20 */  1261, 1225, 1185, 1183, 1181, 1177, 1151, 1128, 1096, 1063,
 /*    30 */  1059,  985,  982,  964,  962,  948,  908,  890,  874,  834,
 /*    40 */   832,  816,  813,  800,  759,  746,  742,  739,  726,  684,
 /*    50 */   681,  668,  665,  652,  612,  593,  591,  537,  524,  518,
 /*    60 */   504,  455,  511,  376,  517,  247, -168,   24,  420,  463,
 /*    70 */   463,  463,  463,  463,  463,  463,  463,  463,  463,  463,
 /*    80 */   463,  463,  463,  463,  463,  463,  463,  463,  463,  463,
 /*    90 */   463,  463,  463,  463,  463,  463,  463,  463,  463,  463,
 /*   100 */   463,  463,  463,  463,  463,  -74,  463,  463, 1112,  835,
 /*   110 */  1107, 1039, 1036,  965,  887,  845,  818,  760,  688,  687,
 /*   120 */   538,  743,  623,  592,  446,  513,  814,  740,  670,  156,
 /*   130 */   468,  553,  184,  616,  463,  463,  463,  463,  463,  595,
 /*   140 */   821,  786,  745,  909, 1305, 1302, 1301, 1299,  675,  675,
 /*   150 */  1295, 1273, 1259, 1245, 1242, 1233, 1222, 1221, 1214, 1213,
 /*   160 */  1212, 1204, 1184, 1158, 1123, 1119, 1114, 1100, 1070, 1047,
 /*   170 */  1046, 1040, 1038,  969,  968,  966,  909,  904,  896,  895,
 /*   180 */   892,  599,  839,  838,  766,  754,  881,  734,  346,  605,
 /*   190 */   622,  -94, 1393, 1401, 1396, 1392, 1391, 1390, 1384, 1361,
 /*   200 */  1365, 1381, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1332,
 /*   210 */  1338, 1365, 1365, 1361, 1399, 1368, 1411, 1359, 1353, 1352,
 /*   220 */  1329, 1358, 1324, 1366, 1389, 1377, 1386, 1376, 1364, 1371,
 /*   230 */  1336, 1323, 1321, 1320, 1375, 1344, 1351, 1387, 1300, 1380,
 /*   240 */  1378, 1298, 1290, 1374, 1316, 1347, 1328, 1337, 1334, 1333,
 /*   250 */  1327, 1363, 1362, 1318, 1296, 1326, 1322, 1355, 1354, 1269,
 /*   260 */  1274, 1350, 1349, 1348, 1346, 1345, 1343, 1335, 1315, 1314,
 /*   270 */  1313, 1312, 1309, 1271, 1267, 1308, 1307, 1306, 1304, 1291,
 /*   280 */  1303, 1292, 1260, 1266, 1258, 1253, 1247, 1227, 1268, 1257,
 /*   290 */  1187, 1198, 1200, 1190, 1170, 1168, 1167, 1182, 1189, 1164,
 /*   300 */  1179, 1162, 1138, 1136, 1061, 1043, 1021, 1111, 1110, 1116,

};
static const YYACTIONTYPE yy_default[] = {
 /*     0 */   634,  868,  956,  956,  868,  868,  956,  956,  956,  758,
 /*    10 */   956,  956,  956,  866,  956,  956,  786,  786,  930,  956,
 /*    20 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*    30 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*    40 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*    50 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*    60 */   956,  956,  956,  956,  956,  956,  956,  673,  762,  792,
 /*    70 */   956,  956,  956,  956,  956,  956,  956,  956,  929,  931,
 /*    80 */   800,  799,  909,  773,  797,  790,  794,  869,  862,  863,
 /*    90 */   861,  865,  870,  956,  793,  829,  846,  828,  840,  845,
 /*   100 */   852,  844,  841,  831,  830,  665,  832,  833,  956,  956,
 /*   110 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   120 */   956,  956,  956,  956,  660,  727,  956,  956,  956,  956,
 /*   130 */   956,  956,  956,  956,  834,  835,  849,  848,  847,  956,
 /*   140 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   150 */   956,  936,  934,  956,  881,  956,  956,  956,  956,  956,
 /*   160 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   170 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   180 */   956,  640,  758,  758,  758,  634,  956,  956,  956,  948,
 /*   190 */   762,  752,  718,  956,  956,  956,  956,  956,  956,  956,
 /*   200 */   956,  956,  956,  956,  956,  802,  741,  919,  921,  956,
 /*   210 */   902,  739,  662,  760,  675,  750,  642,  796,  775,  775,
 /*   220 */   914,  796,  914,  699,  956,  786,  956,  786,  696,  786,
 /*   230 */   775,  864,  956,  956,  956,  759,  750,  956,  941,  766,
 /*   240 */   766,  933,  933,  766,  808,  731,  796,  738,  738,  738,
 /*   250 */   738,  766,  657,  796,  808,  731,  731,  766,  657,  908,
 /*   260 */   906,  766,  766,  657,  766,  657,  766,  657,  874,  729,
 /*   270 */   729,  729,  714,  878,  878,  874,  729,  699,  729,  714,
 /*   280 */   729,  729,  779,  774,  779,  774,  779,  774,  766,  766,
 /*   290 */   956,  791,  780,  789,  787,  796,  956,  717,  650,  650,
 /*   300 */   639,  639,  639,  639,  953,  953,  948,  701,  701,  683,
 /*   310 */   956,  956,  956,  956,  956,  956,  956,  883,  956,  956,
 /*   320 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   330 */   635,  943,  956,  956,  940,  956,  956,  956,  956,  801,
 /*   340 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   350 */   918,  956,  956,  956,  956,  956,  956,  956,  912,  956,
 /*   360 */   956,  956,  956,  956,  956,  905,  904,  956,  956,  956,
 /*   370 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   380 */   956,  956,  956,  956,  956,  956,  956,  956,  956,  956,
 /*   390 */   956,  956,  956,  788,  956,  781,  956,  867,  956,  956,
 /*   400 */   956,  956,  956,  956,  956,  956,  956,  956,  744,  817,
 /*   410 */   956,  816,  820,  815,  667,  956,  648,  956,  631,  636,
 /*   420 */   952,  955,  954,  951,  950,  949,  944,  942,  939,  938,
 /*   430 */   937,  935,  932,  928,  887,  885,  892,  891,  890,  889,
 /*   440 */   888,  886,  884,  882,  803,  798,  795,  927,  880,  740,
 /*   450 */   737,  736,  656,  945,  911,  920,  807,  806,  809,  917,
 /*   460 */   916,  915,  913,  910,  897,  805,  804,  732,  872,  871,
 /*   470 */   659,  901,  900,  899,  903,  907,  898,  768,  658,  655,
 /*   480 */   664,  721,  720,  728,  726,  725,  724,  723,  722,  719,
 /*   490 */   666,  674,  685,  713,  698,  697,  877,  879,  876,  875,
 /*   500 */   706,  705,  711,  710,  709,  708,  707,  704,  703,  702,
 /*   510 */   695,  694,  700,  693,  716,  715,  712,  692,  735,  734,
 /*   520 */   733,  730,  691,  690,  689,  820,  688,  687,  826,  825,
 /*   530 */   813,  856,  755,  754,  753,  765,  764,  777,  776,  811,
 /*   540 */   810,  778,  763,  757,  756,  772,  771,  770,  769,  761,
 /*   550 */   751,  783,  785,  784,  782,  858,  767,  855,  926,  925,
 /*   560 */   924,  923,  922,  860,  859,  827,  824,  678,  679,  895,
 /*   570 */   894,  896,  893,  681,  680,  677,  676,  857,  746,  745,
 /*   580 */   853,  850,  842,  838,  854,  851,  843,  839,  837,  836,
 /*   590 */   822,  821,  819,  818,  814,  823,  669,  747,  743,  742,
 /*   600 */   812,  749,  748,  686,  684,  682,  663,  661,  654,  652,
 /*   610 */   651,  653,  649,  647,  646,  645,  644,  643,  672,  671,
 /*   620 */   670,  668,  667,  641,  638,  637,  633,  632,  630,
};

/* The next table maps tokens into fallback tokens.  If a construct
** like the following:
** 
**      %fallback ID X Y Z.
**
108519
108520
108521
108522
108523
108524
108525
108526
108527
108528
108529
108530
108531
108532
108533
108534
108535
108536
108537
108538
108539
108540
108541
108542
  "init_deferred_pred_opt",  "conslist",      "tcons",         "idxlist",     
  "defer_subclause_opt",  "orconf",        "resolvetype",   "raisetype",   
  "ifexists",      "fullname",      "oneselect",     "multiselect_op",
  "distinct",      "selcollist",    "from",          "where_opt",   
  "groupby_opt",   "having_opt",    "orderby_opt",   "limit_opt",   
  "sclp",          "as",            "seltablist",    "stl_prefix",  
  "joinop",        "indexed_opt",   "on_opt",        "using_opt",   
  "joinop2",       "inscollist",    "sortlist",      "sortitem",    
  "nexprlist",     "setlist",       "insert_cmd",    "inscollist_opt",
  "itemlist",      "exprlist",      "likeop",        "between_op",  
  "in_op",         "case_operand",  "case_exprlist",  "case_else",   
  "uniqueflag",    "collate",       "nmnum",         "plus_opt",    
  "number",        "trigger_decl",  "trigger_cmd_list",  "trigger_time",
  "trigger_event",  "foreach_clause",  "when_clause",   "trigger_cmd", 
  "trnm",          "tridxby",       "database_kw_opt",  "key_opt",     
  "add_column_fullname",  "kwcolumn_opt",  "create_vtab",   "vtabarglist", 
  "vtabarg",       "vtabargtoken",  "lp",            "anylist",     
};
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {







|
|
|
|
|
|
|
|
|
|







108647
108648
108649
108650
108651
108652
108653
108654
108655
108656
108657
108658
108659
108660
108661
108662
108663
108664
108665
108666
108667
108668
108669
108670
  "init_deferred_pred_opt",  "conslist",      "tcons",         "idxlist",     
  "defer_subclause_opt",  "orconf",        "resolvetype",   "raisetype",   
  "ifexists",      "fullname",      "oneselect",     "multiselect_op",
  "distinct",      "selcollist",    "from",          "where_opt",   
  "groupby_opt",   "having_opt",    "orderby_opt",   "limit_opt",   
  "sclp",          "as",            "seltablist",    "stl_prefix",  
  "joinop",        "indexed_opt",   "on_opt",        "using_opt",   
  "joinop2",       "inscollist",    "sortlist",      "nexprlist",   
  "setlist",       "insert_cmd",    "inscollist_opt",  "valuelist",   
  "exprlist",      "likeop",        "between_op",    "in_op",       
  "case_operand",  "case_exprlist",  "case_else",     "uniqueflag",  
  "collate",       "nmnum",         "number",        "trigger_decl",
  "trigger_cmd_list",  "trigger_time",  "trigger_event",  "foreach_clause",
  "when_clause",   "trigger_cmd",   "trnm",          "tridxby",     
  "database_kw_opt",  "key_opt",       "add_column_fullname",  "kwcolumn_opt",
  "create_vtab",   "vtabarglist",   "vtabarg",       "vtabargtoken",
  "lp",            "anylist",     
};
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
108689
108690
108691
108692
108693
108694
108695
108696
108697
108698
108699
108700
108701
108702
108703
108704
108705
108706
108707
108708
108709
108710
108711
108712
108713
108714
108715
108716
108717
108718
108719
108720
108721
108722
108723
108724
108725
108726
108727
108728
108729

108730
108731
108732
108733
108734
108735
108736
108737
108738
108739
108740
108741
108742

108743
108744
108745
108746
108747
108748
108749
108750
108751
108752
108753
108754
108755
108756
108757
108758
108759
108760
108761
108762
108763
108764
108765
108766
108767
108768
108769
108770
108771
108772
108773
108774
108775
108776
108777

108778
108779
108780
108781
108782
108783
108784
108785
108786
108787
108788
108789
108790
108791
108792
108793
108794
108795

108796
108797
108798
108799
108800
108801
108802
108803
108804
108805
108806
108807
108808
108809
108810
108811
108812
108813
108814
108815
108816
108817
108818
108819
108820
108821
108822
108823
108824
108825
108826
108827
108828
108829
108830
108831
108832
108833
108834
108835
108836
108837
108838
108839
108840
108841
108842
108843
108844
108845
108846
108847
108848
108849
108850
108851
108852
108853
108854
108855
108856
108857
108858
108859
108860
108861
108862
108863
108864
108865
108866
108867
108868
108869
108870
108871
108872
108873
108874
108875
108876
108877
108878
 /* 146 */ "indexed_opt ::=",
 /* 147 */ "indexed_opt ::= INDEXED BY nm",
 /* 148 */ "indexed_opt ::= NOT INDEXED",
 /* 149 */ "using_opt ::= USING LP inscollist RP",
 /* 150 */ "using_opt ::=",
 /* 151 */ "orderby_opt ::=",
 /* 152 */ "orderby_opt ::= ORDER BY sortlist",
 /* 153 */ "sortlist ::= sortlist COMMA sortitem sortorder",
 /* 154 */ "sortlist ::= sortitem sortorder",
 /* 155 */ "sortitem ::= expr",
 /* 156 */ "sortorder ::= ASC",
 /* 157 */ "sortorder ::= DESC",
 /* 158 */ "sortorder ::=",
 /* 159 */ "groupby_opt ::=",
 /* 160 */ "groupby_opt ::= GROUP BY nexprlist",
 /* 161 */ "having_opt ::=",
 /* 162 */ "having_opt ::= HAVING expr",
 /* 163 */ "limit_opt ::=",
 /* 164 */ "limit_opt ::= LIMIT expr",
 /* 165 */ "limit_opt ::= LIMIT expr OFFSET expr",
 /* 166 */ "limit_opt ::= LIMIT expr COMMA expr",
 /* 167 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
 /* 168 */ "where_opt ::=",
 /* 169 */ "where_opt ::= WHERE expr",
 /* 170 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
 /* 171 */ "setlist ::= setlist COMMA nm EQ expr",
 /* 172 */ "setlist ::= nm EQ expr",
 /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
 /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
 /* 175 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
 /* 176 */ "insert_cmd ::= INSERT orconf",
 /* 177 */ "insert_cmd ::= REPLACE",
 /* 178 */ "itemlist ::= itemlist COMMA expr",
 /* 179 */ "itemlist ::= expr",
 /* 180 */ "inscollist_opt ::=",
 /* 181 */ "inscollist_opt ::= LP inscollist RP",
 /* 182 */ "inscollist ::= inscollist COMMA nm",
 /* 183 */ "inscollist ::= nm",
 /* 184 */ "expr ::= term",
 /* 185 */ "expr ::= LP expr RP",
 /* 186 */ "term ::= NULL",

 /* 187 */ "expr ::= id",
 /* 188 */ "expr ::= JOIN_KW",
 /* 189 */ "expr ::= nm DOT nm",
 /* 190 */ "expr ::= nm DOT nm DOT nm",
 /* 191 */ "term ::= INTEGER|FLOAT|BLOB",
 /* 192 */ "term ::= STRING",
 /* 193 */ "expr ::= REGISTER",
 /* 194 */ "expr ::= VARIABLE",
 /* 195 */ "expr ::= expr COLLATE ids",
 /* 196 */ "expr ::= CAST LP expr AS typetoken RP",
 /* 197 */ "expr ::= ID LP distinct exprlist RP",
 /* 198 */ "expr ::= ID LP STAR RP",
 /* 199 */ "term ::= CTIME_KW",

 /* 200 */ "expr ::= expr AND expr",
 /* 201 */ "expr ::= expr OR expr",
 /* 202 */ "expr ::= expr LT|GT|GE|LE expr",
 /* 203 */ "expr ::= expr EQ|NE expr",
 /* 204 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
 /* 205 */ "expr ::= expr PLUS|MINUS expr",
 /* 206 */ "expr ::= expr STAR|SLASH|REM expr",
 /* 207 */ "expr ::= expr CONCAT expr",
 /* 208 */ "likeop ::= LIKE_KW",
 /* 209 */ "likeop ::= NOT LIKE_KW",
 /* 210 */ "likeop ::= MATCH",
 /* 211 */ "likeop ::= NOT MATCH",
 /* 212 */ "expr ::= expr likeop expr",
 /* 213 */ "expr ::= expr likeop expr ESCAPE expr",
 /* 214 */ "expr ::= expr ISNULL|NOTNULL",
 /* 215 */ "expr ::= expr NOT NULL",
 /* 216 */ "expr ::= expr IS expr",
 /* 217 */ "expr ::= expr IS NOT expr",
 /* 218 */ "expr ::= NOT expr",
 /* 219 */ "expr ::= BITNOT expr",
 /* 220 */ "expr ::= MINUS expr",
 /* 221 */ "expr ::= PLUS expr",
 /* 222 */ "between_op ::= BETWEEN",
 /* 223 */ "between_op ::= NOT BETWEEN",
 /* 224 */ "expr ::= expr between_op expr AND expr",
 /* 225 */ "in_op ::= IN",
 /* 226 */ "in_op ::= NOT IN",
 /* 227 */ "expr ::= expr in_op LP exprlist RP",
 /* 228 */ "expr ::= LP select RP",
 /* 229 */ "expr ::= expr in_op LP select RP",
 /* 230 */ "expr ::= expr in_op nm dbnm",
 /* 231 */ "expr ::= EXISTS LP select RP",
 /* 232 */ "expr ::= CASE case_operand case_exprlist case_else END",
 /* 233 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
 /* 234 */ "case_exprlist ::= WHEN expr THEN expr",

 /* 235 */ "case_else ::= ELSE expr",
 /* 236 */ "case_else ::=",
 /* 237 */ "case_operand ::= expr",
 /* 238 */ "case_operand ::=",
 /* 239 */ "exprlist ::= nexprlist",
 /* 240 */ "exprlist ::=",
 /* 241 */ "nexprlist ::= nexprlist COMMA expr",
 /* 242 */ "nexprlist ::= expr",
 /* 243 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
 /* 244 */ "uniqueflag ::= UNIQUE",
 /* 245 */ "uniqueflag ::=",
 /* 246 */ "idxlist_opt ::=",
 /* 247 */ "idxlist_opt ::= LP idxlist RP",
 /* 248 */ "idxlist ::= idxlist COMMA nm collate sortorder",
 /* 249 */ "idxlist ::= nm collate sortorder",
 /* 250 */ "collate ::=",
 /* 251 */ "collate ::= COLLATE ids",
 /* 252 */ "cmd ::= DROP INDEX ifexists fullname",

 /* 253 */ "cmd ::= VACUUM",
 /* 254 */ "cmd ::= VACUUM nm",
 /* 255 */ "cmd ::= PRAGMA nm dbnm",
 /* 256 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
 /* 257 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
 /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
 /* 259 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
 /* 260 */ "nmnum ::= plus_num",
 /* 261 */ "nmnum ::= nm",
 /* 262 */ "nmnum ::= ON",
 /* 263 */ "nmnum ::= DELETE",
 /* 264 */ "nmnum ::= DEFAULT",
 /* 265 */ "plus_num ::= plus_opt number",
 /* 266 */ "minus_num ::= MINUS number",
 /* 267 */ "number ::= INTEGER|FLOAT",
 /* 268 */ "plus_opt ::= PLUS",
 /* 269 */ "plus_opt ::=",
 /* 270 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
 /* 271 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
 /* 272 */ "trigger_time ::= BEFORE",
 /* 273 */ "trigger_time ::= AFTER",
 /* 274 */ "trigger_time ::= INSTEAD OF",
 /* 275 */ "trigger_time ::=",
 /* 276 */ "trigger_event ::= DELETE|INSERT",
 /* 277 */ "trigger_event ::= UPDATE",
 /* 278 */ "trigger_event ::= UPDATE OF inscollist",
 /* 279 */ "foreach_clause ::=",
 /* 280 */ "foreach_clause ::= FOR EACH ROW",
 /* 281 */ "when_clause ::=",
 /* 282 */ "when_clause ::= WHEN expr",
 /* 283 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
 /* 284 */ "trigger_cmd_list ::= trigger_cmd SEMI",
 /* 285 */ "trnm ::= nm",
 /* 286 */ "trnm ::= nm DOT nm",
 /* 287 */ "tridxby ::=",
 /* 288 */ "tridxby ::= INDEXED BY nm",
 /* 289 */ "tridxby ::= NOT INDEXED",
 /* 290 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
 /* 291 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP",
 /* 292 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
 /* 293 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
 /* 294 */ "trigger_cmd ::= select",
 /* 295 */ "expr ::= RAISE LP IGNORE RP",
 /* 296 */ "expr ::= RAISE LP raisetype COMMA nm RP",
 /* 297 */ "raisetype ::= ROLLBACK",
 /* 298 */ "raisetype ::= ABORT",
 /* 299 */ "raisetype ::= FAIL",
 /* 300 */ "cmd ::= DROP TRIGGER ifexists fullname",
 /* 301 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
 /* 302 */ "cmd ::= DETACH database_kw_opt expr",
 /* 303 */ "key_opt ::=",
 /* 304 */ "key_opt ::= KEY expr",
 /* 305 */ "database_kw_opt ::= DATABASE",
 /* 306 */ "database_kw_opt ::=",
 /* 307 */ "cmd ::= REINDEX",
 /* 308 */ "cmd ::= REINDEX nm dbnm",
 /* 309 */ "cmd ::= ANALYZE",
 /* 310 */ "cmd ::= ANALYZE nm dbnm",
 /* 311 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
 /* 312 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
 /* 313 */ "add_column_fullname ::= fullname",
 /* 314 */ "kwcolumn_opt ::=",
 /* 315 */ "kwcolumn_opt ::= COLUMNKW",
 /* 316 */ "cmd ::= create_vtab",
 /* 317 */ "cmd ::= create_vtab LP vtabarglist RP",
 /* 318 */ "create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm",
 /* 319 */ "vtabarglist ::= vtabarg",
 /* 320 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
 /* 321 */ "vtabarg ::=",
 /* 322 */ "vtabarg ::= vtabarg vtabargtoken",
 /* 323 */ "vtabargtoken ::= ANY",
 /* 324 */ "vtabargtoken ::= lp anylist RP",
 /* 325 */ "lp ::= LP",
 /* 326 */ "anylist ::=",
 /* 327 */ "anylist ::= anylist LP anylist RP",
 /* 328 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */


#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.







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


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







108817
108818
108819
108820
108821
108822
108823
108824
108825
108826
108827
108828
108829
108830
108831
108832
108833
108834
108835
108836

108837
108838
108839
108840
108841
108842
108843
108844
108845
108846
108847
108848
108849
108850
108851
108852
108853
108854
108855
108856
108857
108858
108859
108860

108861
108862
108863
108864
108865
108866
108867
108868
108869
108870
108871
108872
108873
108874
108875
108876
108877
108878
108879
108880
108881
108882
108883
108884
108885
108886
108887
108888
108889
108890
108891

108892
108893
108894
108895
108896
108897
108898
108899
108900
108901
108902
108903
108904
108905
108906
108907
108908

108909
108910
108911
108912
108913
108914
108915
108916
108917
108918
108919
108920
108921
108922
108923
108924
108925
108926
108927
108928
108929
108930
108931
108932
108933
108934
108935
108936
108937
108938


108939
108940
108941
108942
108943
108944
108945
108946
108947
108948
108949
108950
108951
108952
108953
108954
108955
108956
108957
108958
108959
108960
108961
108962
108963
108964
108965
108966
108967
108968
108969
108970
108971
108972
108973
108974
108975
108976
108977
108978
108979
108980
108981
108982
108983
108984
108985
108986
108987
108988
108989
108990
108991
108992
108993
108994
108995
108996
108997
108998
108999
109000
109001
109002
109003
109004
 /* 146 */ "indexed_opt ::=",
 /* 147 */ "indexed_opt ::= INDEXED BY nm",
 /* 148 */ "indexed_opt ::= NOT INDEXED",
 /* 149 */ "using_opt ::= USING LP inscollist RP",
 /* 150 */ "using_opt ::=",
 /* 151 */ "orderby_opt ::=",
 /* 152 */ "orderby_opt ::= ORDER BY sortlist",
 /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
 /* 154 */ "sortlist ::= expr sortorder",
 /* 155 */ "sortorder ::= ASC",
 /* 156 */ "sortorder ::= DESC",
 /* 157 */ "sortorder ::=",
 /* 158 */ "groupby_opt ::=",
 /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
 /* 160 */ "having_opt ::=",
 /* 161 */ "having_opt ::= HAVING expr",
 /* 162 */ "limit_opt ::=",
 /* 163 */ "limit_opt ::= LIMIT expr",
 /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
 /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",

 /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
 /* 167 */ "where_opt ::=",
 /* 168 */ "where_opt ::= WHERE expr",
 /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
 /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
 /* 171 */ "setlist ::= nm EQ expr",
 /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
 /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
 /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
 /* 175 */ "insert_cmd ::= INSERT orconf",
 /* 176 */ "insert_cmd ::= REPLACE",
 /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
 /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
 /* 179 */ "inscollist_opt ::=",
 /* 180 */ "inscollist_opt ::= LP inscollist RP",
 /* 181 */ "inscollist ::= inscollist COMMA nm",
 /* 182 */ "inscollist ::= nm",
 /* 183 */ "expr ::= term",
 /* 184 */ "expr ::= LP expr RP",
 /* 185 */ "term ::= NULL",
 /* 186 */ "expr ::= id",
 /* 187 */ "expr ::= JOIN_KW",
 /* 188 */ "expr ::= nm DOT nm",
 /* 189 */ "expr ::= nm DOT nm DOT nm",

 /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
 /* 191 */ "term ::= STRING",
 /* 192 */ "expr ::= REGISTER",
 /* 193 */ "expr ::= VARIABLE",
 /* 194 */ "expr ::= expr COLLATE ids",
 /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
 /* 196 */ "expr ::= ID LP distinct exprlist RP",
 /* 197 */ "expr ::= ID LP STAR RP",
 /* 198 */ "term ::= CTIME_KW",
 /* 199 */ "expr ::= expr AND expr",
 /* 200 */ "expr ::= expr OR expr",
 /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
 /* 202 */ "expr ::= expr EQ|NE expr",
 /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
 /* 204 */ "expr ::= expr PLUS|MINUS expr",
 /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
 /* 206 */ "expr ::= expr CONCAT expr",
 /* 207 */ "likeop ::= LIKE_KW",
 /* 208 */ "likeop ::= NOT LIKE_KW",
 /* 209 */ "likeop ::= MATCH",
 /* 210 */ "likeop ::= NOT MATCH",
 /* 211 */ "expr ::= expr likeop expr",
 /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
 /* 213 */ "expr ::= expr ISNULL|NOTNULL",
 /* 214 */ "expr ::= expr NOT NULL",
 /* 215 */ "expr ::= expr IS expr",
 /* 216 */ "expr ::= expr IS NOT expr",
 /* 217 */ "expr ::= NOT expr",
 /* 218 */ "expr ::= BITNOT expr",
 /* 219 */ "expr ::= MINUS expr",
 /* 220 */ "expr ::= PLUS expr",

 /* 221 */ "between_op ::= BETWEEN",
 /* 222 */ "between_op ::= NOT BETWEEN",
 /* 223 */ "expr ::= expr between_op expr AND expr",
 /* 224 */ "in_op ::= IN",
 /* 225 */ "in_op ::= NOT IN",
 /* 226 */ "expr ::= expr in_op LP exprlist RP",
 /* 227 */ "expr ::= LP select RP",
 /* 228 */ "expr ::= expr in_op LP select RP",
 /* 229 */ "expr ::= expr in_op nm dbnm",
 /* 230 */ "expr ::= EXISTS LP select RP",
 /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
 /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
 /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
 /* 234 */ "case_else ::= ELSE expr",
 /* 235 */ "case_else ::=",
 /* 236 */ "case_operand ::= expr",
 /* 237 */ "case_operand ::=",

 /* 238 */ "exprlist ::= nexprlist",
 /* 239 */ "exprlist ::=",
 /* 240 */ "nexprlist ::= nexprlist COMMA expr",
 /* 241 */ "nexprlist ::= expr",
 /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
 /* 243 */ "uniqueflag ::= UNIQUE",
 /* 244 */ "uniqueflag ::=",
 /* 245 */ "idxlist_opt ::=",
 /* 246 */ "idxlist_opt ::= LP idxlist RP",
 /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
 /* 248 */ "idxlist ::= nm collate sortorder",
 /* 249 */ "collate ::=",
 /* 250 */ "collate ::= COLLATE ids",
 /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
 /* 252 */ "cmd ::= VACUUM",
 /* 253 */ "cmd ::= VACUUM nm",
 /* 254 */ "cmd ::= PRAGMA nm dbnm",
 /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
 /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
 /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
 /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
 /* 259 */ "nmnum ::= plus_num",
 /* 260 */ "nmnum ::= nm",
 /* 261 */ "nmnum ::= ON",
 /* 262 */ "nmnum ::= DELETE",
 /* 263 */ "nmnum ::= DEFAULT",
 /* 264 */ "plus_num ::= PLUS number",
 /* 265 */ "plus_num ::= number",
 /* 266 */ "minus_num ::= MINUS number",
 /* 267 */ "number ::= INTEGER|FLOAT",


 /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
 /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
 /* 270 */ "trigger_time ::= BEFORE",
 /* 271 */ "trigger_time ::= AFTER",
 /* 272 */ "trigger_time ::= INSTEAD OF",
 /* 273 */ "trigger_time ::=",
 /* 274 */ "trigger_event ::= DELETE|INSERT",
 /* 275 */ "trigger_event ::= UPDATE",
 /* 276 */ "trigger_event ::= UPDATE OF inscollist",
 /* 277 */ "foreach_clause ::=",
 /* 278 */ "foreach_clause ::= FOR EACH ROW",
 /* 279 */ "when_clause ::=",
 /* 280 */ "when_clause ::= WHEN expr",
 /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
 /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
 /* 283 */ "trnm ::= nm",
 /* 284 */ "trnm ::= nm DOT nm",
 /* 285 */ "tridxby ::=",
 /* 286 */ "tridxby ::= INDEXED BY nm",
 /* 287 */ "tridxby ::= NOT INDEXED",
 /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
 /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
 /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
 /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
 /* 292 */ "trigger_cmd ::= select",
 /* 293 */ "expr ::= RAISE LP IGNORE RP",
 /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
 /* 295 */ "raisetype ::= ROLLBACK",
 /* 296 */ "raisetype ::= ABORT",
 /* 297 */ "raisetype ::= FAIL",
 /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
 /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
 /* 300 */ "cmd ::= DETACH database_kw_opt expr",
 /* 301 */ "key_opt ::=",
 /* 302 */ "key_opt ::= KEY expr",
 /* 303 */ "database_kw_opt ::= DATABASE",
 /* 304 */ "database_kw_opt ::=",
 /* 305 */ "cmd ::= REINDEX",
 /* 306 */ "cmd ::= REINDEX nm dbnm",
 /* 307 */ "cmd ::= ANALYZE",
 /* 308 */ "cmd ::= ANALYZE nm dbnm",
 /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
 /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
 /* 311 */ "add_column_fullname ::= fullname",
 /* 312 */ "kwcolumn_opt ::=",
 /* 313 */ "kwcolumn_opt ::= COLUMNKW",
 /* 314 */ "cmd ::= create_vtab",
 /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
 /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
 /* 317 */ "vtabarglist ::= vtabarg",
 /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
 /* 319 */ "vtabarg ::=",
 /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
 /* 321 */ "vtabargtoken ::= ANY",
 /* 322 */ "vtabargtoken ::= lp anylist RP",
 /* 323 */ "lp ::= LP",
 /* 324 */ "anylist ::=",
 /* 325 */ "anylist ::= anylist LP anylist RP",
 /* 326 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */


#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.
108946
108947
108948
108949
108950
108951
108952
108953
108954
108955
108956
108957
108958
108959
108960
108961
108962
108963
108964
108965
108966
108967
108968
108969
108970
108971
108972
108973
108974
108975
108976
108977
108978
108979
108980
108981
108982
108983
108984
108985
108986
108987
108988
108989
108990
108991
108992
108993
108994
108995
108996
108997
108998
108999
109000
109001
109002
109003
109004








109005
109006
109007
109008
109009
109010
109011
109012
109013
109014
109015
109016
109017
109018
109019
109020
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are not used
    ** inside the C code.
    */
    case 160: /* select */
    case 194: /* oneselect */
{
sqlite3SelectDelete(pParse->db, (yypminor->yy387));
}
      break;
    case 174: /* term */
    case 175: /* expr */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy118).pExpr);
}
      break;
    case 179: /* idxlist_opt */
    case 187: /* idxlist */
    case 197: /* selcollist */
    case 200: /* groupby_opt */
    case 202: /* orderby_opt */
    case 204: /* sclp */
    case 214: /* sortlist */
    case 216: /* nexprlist */
    case 217: /* setlist */
    case 220: /* itemlist */
    case 221: /* exprlist */
    case 226: /* case_exprlist */
{
sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
}
      break;
    case 193: /* fullname */
    case 198: /* from */
    case 206: /* seltablist */
    case 207: /* stl_prefix */
{
sqlite3SrcListDelete(pParse->db, (yypminor->yy259));
}
      break;
    case 199: /* where_opt */
    case 201: /* having_opt */
    case 210: /* on_opt */
    case 215: /* sortitem */
    case 225: /* case_operand */
    case 227: /* case_else */
    case 238: /* when_clause */
    case 243: /* key_opt */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy314));
}
      break;
    case 211: /* using_opt */
    case 213: /* inscollist */
    case 219: /* inscollist_opt */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy384));
}
      break;








    case 234: /* trigger_cmd_list */
    case 239: /* trigger_cmd */
{
sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203));
}
      break;
    case 236: /* trigger_event */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy90).b);
}
      break;
    default:  break;   /* If no destructor action specified: do nothing */
  }
}

/*







|





|









|
|
|
<
|

|







|





<
|
|
|
|

|




|

|


>
>
>
>
>
>
>
>
|
|

|


|

|







109072
109073
109074
109075
109076
109077
109078
109079
109080
109081
109082
109083
109084
109085
109086
109087
109088
109089
109090
109091
109092
109093
109094
109095
109096
109097

109098
109099
109100
109101
109102
109103
109104
109105
109106
109107
109108
109109
109110
109111
109112
109113

109114
109115
109116
109117
109118
109119
109120
109121
109122
109123
109124
109125
109126
109127
109128
109129
109130
109131
109132
109133
109134
109135
109136
109137
109138
109139
109140
109141
109142
109143
109144
109145
109146
109147
109148
109149
109150
109151
109152
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are not used
    ** inside the C code.
    */
    case 160: /* select */
    case 194: /* oneselect */
{
sqlite3SelectDelete(pParse->db, (yypminor->yy159));
}
      break;
    case 174: /* term */
    case 175: /* expr */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr);
}
      break;
    case 179: /* idxlist_opt */
    case 187: /* idxlist */
    case 197: /* selcollist */
    case 200: /* groupby_opt */
    case 202: /* orderby_opt */
    case 204: /* sclp */
    case 214: /* sortlist */
    case 215: /* nexprlist */
    case 216: /* setlist */
    case 220: /* exprlist */

    case 225: /* case_exprlist */
{
sqlite3ExprListDelete(pParse->db, (yypminor->yy442));
}
      break;
    case 193: /* fullname */
    case 198: /* from */
    case 206: /* seltablist */
    case 207: /* stl_prefix */
{
sqlite3SrcListDelete(pParse->db, (yypminor->yy347));
}
      break;
    case 199: /* where_opt */
    case 201: /* having_opt */
    case 210: /* on_opt */

    case 224: /* case_operand */
    case 226: /* case_else */
    case 236: /* when_clause */
    case 241: /* key_opt */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy122));
}
      break;
    case 211: /* using_opt */
    case 213: /* inscollist */
    case 218: /* inscollist_opt */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy180));
}
      break;
    case 219: /* valuelist */
{

  sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList);
  sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect);

}
      break;
    case 232: /* trigger_cmd_list */
    case 237: /* trigger_cmd */
{
sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327));
}
      break;
    case 234: /* trigger_event */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy410).b);
}
      break;
    default:  break;   /* If no destructor action specified: do nothing */
  }
}

/*
109406
109407
109408
109409
109410
109411
109412
109413
109414
109415
109416
109417
109418
109419
109420
109421
109422
109423
109424
109425
109426
109427
109428
109429
109430
109431
109432
109433
109434
109435
109436
109437
109438
109439


109440
109441
109442
109443
109444
109445
109446
  { 209, 2 },
  { 211, 4 },
  { 211, 0 },
  { 202, 0 },
  { 202, 3 },
  { 214, 4 },
  { 214, 2 },
  { 215, 1 },
  { 177, 1 },
  { 177, 1 },
  { 177, 0 },
  { 200, 0 },
  { 200, 3 },
  { 201, 0 },
  { 201, 2 },
  { 203, 0 },
  { 203, 2 },
  { 203, 4 },
  { 203, 4 },
  { 147, 5 },
  { 199, 0 },
  { 199, 2 },
  { 147, 7 },
  { 217, 5 },
  { 217, 3 },
  { 147, 8 },
  { 147, 5 },
  { 147, 6 },
  { 218, 2 },
  { 218, 1 },
  { 220, 3 },
  { 220, 1 },
  { 219, 0 },
  { 219, 3 },


  { 213, 3 },
  { 213, 1 },
  { 175, 1 },
  { 175, 3 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },







<















|
|
|


|
|
<
<
|
|
>
>







109538
109539
109540
109541
109542
109543
109544

109545
109546
109547
109548
109549
109550
109551
109552
109553
109554
109555
109556
109557
109558
109559
109560
109561
109562
109563
109564
109565
109566


109567
109568
109569
109570
109571
109572
109573
109574
109575
109576
109577
  { 209, 2 },
  { 211, 4 },
  { 211, 0 },
  { 202, 0 },
  { 202, 3 },
  { 214, 4 },
  { 214, 2 },

  { 177, 1 },
  { 177, 1 },
  { 177, 0 },
  { 200, 0 },
  { 200, 3 },
  { 201, 0 },
  { 201, 2 },
  { 203, 0 },
  { 203, 2 },
  { 203, 4 },
  { 203, 4 },
  { 147, 5 },
  { 199, 0 },
  { 199, 2 },
  { 147, 7 },
  { 216, 5 },
  { 216, 3 },
  { 147, 5 },
  { 147, 5 },
  { 147, 6 },
  { 217, 2 },
  { 217, 1 },


  { 219, 4 },
  { 219, 5 },
  { 218, 0 },
  { 218, 3 },
  { 213, 3 },
  { 213, 1 },
  { 175, 1 },
  { 175, 3 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },
109459
109460
109461
109462
109463
109464
109465
109466
109467
109468
109469
109470
109471
109472
109473
109474
109475
109476
109477
109478
109479
109480
109481
109482
109483
109484
109485
109486
109487
109488
109489
109490
109491
109492
109493
109494
109495
109496
109497
109498
109499
109500
109501
109502
109503
109504
109505
109506
109507
109508
109509
109510
109511
109512
109513
109514
109515
109516
109517
109518
109519
109520
109521
109522
109523

109524
109525
109526
109527
109528
109529
109530
109531
109532
109533
109534
109535
109536
109537
109538
109539
109540
109541
109542
109543
109544
109545
109546
109547
109548
109549
109550
109551
109552
109553
109554
109555
109556
109557
109558
109559
109560
109561
109562
109563
109564
109565
109566
109567
109568
109569
109570
109571
109572
109573
109574
109575



109576

109577
109578
109579
109580
109581
109582
109583
109584
109585
109586
109587
109588
109589
109590
109591
109592
109593
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 222, 1 },
  { 222, 2 },
  { 222, 1 },
  { 222, 2 },
  { 175, 3 },
  { 175, 5 },
  { 175, 2 },
  { 175, 3 },
  { 175, 3 },
  { 175, 4 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 223, 1 },
  { 223, 2 },
  { 175, 5 },
  { 224, 1 },
  { 224, 2 },
  { 175, 5 },
  { 175, 3 },
  { 175, 5 },
  { 175, 4 },
  { 175, 4 },
  { 175, 5 },
  { 226, 5 },
  { 226, 4 },
  { 227, 2 },
  { 227, 0 },
  { 225, 1 },
  { 225, 0 },
  { 221, 1 },
  { 221, 0 },
  { 216, 3 },
  { 216, 1 },
  { 147, 11 },
  { 228, 1 },
  { 228, 0 },
  { 179, 0 },
  { 179, 3 },
  { 187, 5 },
  { 187, 3 },
  { 229, 0 },
  { 229, 2 },
  { 147, 4 },
  { 147, 1 },
  { 147, 2 },
  { 147, 3 },
  { 147, 5 },
  { 147, 6 },
  { 147, 5 },
  { 147, 6 },
  { 230, 1 },
  { 230, 1 },
  { 230, 1 },
  { 230, 1 },
  { 230, 1 },
  { 170, 2 },

  { 171, 2 },
  { 232, 1 },
  { 231, 1 },
  { 231, 0 },
  { 147, 5 },
  { 233, 11 },
  { 235, 1 },
  { 235, 1 },
  { 235, 2 },
  { 235, 0 },
  { 236, 1 },
  { 236, 1 },
  { 236, 3 },
  { 237, 0 },
  { 237, 3 },
  { 238, 0 },
  { 238, 2 },
  { 234, 3 },
  { 234, 2 },
  { 240, 1 },
  { 240, 3 },
  { 241, 0 },
  { 241, 3 },
  { 241, 2 },
  { 239, 7 },
  { 239, 8 },
  { 239, 5 },
  { 239, 5 },
  { 239, 1 },
  { 175, 4 },
  { 175, 6 },
  { 191, 1 },
  { 191, 1 },
  { 191, 1 },
  { 147, 4 },
  { 147, 6 },
  { 147, 3 },
  { 243, 0 },
  { 243, 2 },
  { 242, 1 },
  { 242, 0 },
  { 147, 1 },
  { 147, 3 },
  { 147, 1 },
  { 147, 3 },
  { 147, 6 },
  { 147, 6 },
  { 244, 1 },
  { 245, 0 },
  { 245, 1 },
  { 147, 1 },
  { 147, 4 },



  { 246, 7 },

  { 247, 1 },
  { 247, 3 },
  { 248, 0 },
  { 248, 2 },
  { 249, 1 },
  { 249, 3 },
  { 250, 1 },
  { 251, 0 },
  { 251, 4 },
  { 251, 2 },
};

static void yy_accept(yyParser*);  /* Forward Declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.







|
|
|
|










|
|

|
|






|
|
|
|
|
|
|
|
|
|

|
|




|
|








|
|
|
|
|

>

|
<
<

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








|
|
|
|






|
|
|


>
>
>
|
>


|
<
|
|
<
<
<
|







109590
109591
109592
109593
109594
109595
109596
109597
109598
109599
109600
109601
109602
109603
109604
109605
109606
109607
109608
109609
109610
109611
109612
109613
109614
109615
109616
109617
109618
109619
109620
109621
109622
109623
109624
109625
109626
109627
109628
109629
109630
109631
109632
109633
109634
109635
109636
109637
109638
109639
109640
109641
109642
109643
109644
109645
109646
109647
109648
109649
109650
109651
109652
109653
109654
109655
109656
109657


109658
109659
109660
109661
109662
109663
109664
109665
109666
109667
109668
109669
109670
109671
109672
109673
109674
109675
109676
109677
109678
109679
109680
109681
109682
109683
109684
109685
109686
109687
109688
109689
109690
109691
109692
109693
109694
109695
109696
109697
109698
109699
109700
109701
109702
109703
109704
109705
109706
109707
109708
109709
109710
109711
109712
109713

109714
109715



109716
109717
109718
109719
109720
109721
109722
109723
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 221, 1 },
  { 221, 2 },
  { 221, 1 },
  { 221, 2 },
  { 175, 3 },
  { 175, 5 },
  { 175, 2 },
  { 175, 3 },
  { 175, 3 },
  { 175, 4 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 222, 1 },
  { 222, 2 },
  { 175, 5 },
  { 223, 1 },
  { 223, 2 },
  { 175, 5 },
  { 175, 3 },
  { 175, 5 },
  { 175, 4 },
  { 175, 4 },
  { 175, 5 },
  { 225, 5 },
  { 225, 4 },
  { 226, 2 },
  { 226, 0 },
  { 224, 1 },
  { 224, 0 },
  { 220, 1 },
  { 220, 0 },
  { 215, 3 },
  { 215, 1 },
  { 147, 11 },
  { 227, 1 },
  { 227, 0 },
  { 179, 0 },
  { 179, 3 },
  { 187, 5 },
  { 187, 3 },
  { 228, 0 },
  { 228, 2 },
  { 147, 4 },
  { 147, 1 },
  { 147, 2 },
  { 147, 3 },
  { 147, 5 },
  { 147, 6 },
  { 147, 5 },
  { 147, 6 },
  { 229, 1 },
  { 229, 1 },
  { 229, 1 },
  { 229, 1 },
  { 229, 1 },
  { 170, 2 },
  { 170, 1 },
  { 171, 2 },
  { 230, 1 },


  { 147, 5 },
  { 231, 11 },
  { 233, 1 },
  { 233, 1 },
  { 233, 2 },
  { 233, 0 },
  { 234, 1 },
  { 234, 1 },
  { 234, 3 },
  { 235, 0 },
  { 235, 3 },
  { 236, 0 },
  { 236, 2 },
  { 232, 3 },
  { 232, 2 },
  { 238, 1 },
  { 238, 3 },
  { 239, 0 },
  { 239, 3 },
  { 239, 2 },
  { 237, 7 },
  { 237, 5 },
  { 237, 5 },
  { 237, 5 },
  { 237, 1 },
  { 175, 4 },
  { 175, 6 },
  { 191, 1 },
  { 191, 1 },
  { 191, 1 },
  { 147, 4 },
  { 147, 6 },
  { 147, 3 },
  { 241, 0 },
  { 241, 2 },
  { 240, 1 },
  { 240, 0 },
  { 147, 1 },
  { 147, 3 },
  { 147, 1 },
  { 147, 3 },
  { 147, 6 },
  { 147, 6 },
  { 242, 1 },
  { 243, 0 },
  { 243, 1 },
  { 147, 1 },
  { 147, 4 },
  { 244, 8 },
  { 245, 1 },
  { 245, 3 },
  { 246, 0 },
  { 246, 2 },
  { 247, 1 },
  { 247, 3 },
  { 248, 1 },

  { 249, 0 },
  { 249, 4 },



  { 249, 2 },
};

static void yy_accept(yyParser*);  /* Forward Declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
109647
109648
109649
109650
109651
109652
109653
109654
109655
109656
109657
109658
109659
109660
109661
109662
109663
109664
109665
109666
109667
109668
109669
109670
109671
      case 7: /* explain ::= EXPLAIN QUERY PLAN */
{ sqlite3BeginParse(pParse, 2); }
        break;
      case 8: /* cmdx ::= cmd */
{ sqlite3FinishCoding(pParse); }
        break;
      case 9: /* cmd ::= BEGIN transtype trans_opt */
{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);}
        break;
      case 13: /* transtype ::= */
{yygotominor.yy4 = TK_DEFERRED;}
        break;
      case 14: /* transtype ::= DEFERRED */
      case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
      case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
      case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
      case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
{yygotominor.yy4 = yymsp[0].major;}
        break;
      case 17: /* cmd ::= COMMIT trans_opt */
      case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
{sqlite3CommitTransaction(pParse);}
        break;
      case 19: /* cmd ::= ROLLBACK trans_opt */
{sqlite3RollbackTransaction(pParse);}







|


|






|







109777
109778
109779
109780
109781
109782
109783
109784
109785
109786
109787
109788
109789
109790
109791
109792
109793
109794
109795
109796
109797
109798
109799
109800
109801
      case 7: /* explain ::= EXPLAIN QUERY PLAN */
{ sqlite3BeginParse(pParse, 2); }
        break;
      case 8: /* cmdx ::= cmd */
{ sqlite3FinishCoding(pParse); }
        break;
      case 9: /* cmd ::= BEGIN transtype trans_opt */
{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);}
        break;
      case 13: /* transtype ::= */
{yygotominor.yy392 = TK_DEFERRED;}
        break;
      case 14: /* transtype ::= DEFERRED */
      case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
      case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
      case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
      case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
{yygotominor.yy392 = yymsp[0].major;}
        break;
      case 17: /* cmd ::= COMMIT trans_opt */
      case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
{sqlite3CommitTransaction(pParse);}
        break;
      case 19: /* cmd ::= ROLLBACK trans_opt */
{sqlite3RollbackTransaction(pParse);}
109683
109684
109685
109686
109687
109688
109689
109690
109691
109692
109693
109694
109695
109696
109697
109698
109699
109700
109701
109702
109703
109704
109705
109706
109707
109708
109709
109710
109711
109712
109713
109714
109715
109716
109717
109718
109719
109720
109721
109722
109723
109724
109725
109726
109727
109728
109729
109730
109731
109732
109733
109734
109735
109736
109737
109738
      case 24: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
  sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
        break;
      case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4);
}
        break;
      case 27: /* createkw ::= CREATE */
{
  pParse->db->lookaside.bEnabled = 0;
  yygotominor.yy0 = yymsp[0].minor.yy0;
}
        break;
      case 28: /* ifnotexists ::= */
      case 31: /* temp ::= */ yytestcase(yyruleno==31);
      case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
      case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
      case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
      case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
      case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
      case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
      case 222: /* between_op ::= BETWEEN */ yytestcase(yyruleno==222);
      case 225: /* in_op ::= IN */ yytestcase(yyruleno==225);
{yygotominor.yy4 = 0;}
        break;
      case 29: /* ifnotexists ::= IF NOT EXISTS */
      case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
      case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
      case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
      case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
      case 223: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==223);
      case 226: /* in_op ::= NOT IN */ yytestcase(yyruleno==226);
{yygotominor.yy4 = 1;}
        break;
      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
}
        break;
      case 33: /* create_table_args ::= AS select */
{
  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy387);
  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387);
}
        break;
      case 36: /* column ::= columnid type carglist */
{
  yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
  yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}







|


















|
|
|







|
|
|








|
|







109813
109814
109815
109816
109817
109818
109819
109820
109821
109822
109823
109824
109825
109826
109827
109828
109829
109830
109831
109832
109833
109834
109835
109836
109837
109838
109839
109840
109841
109842
109843
109844
109845
109846
109847
109848
109849
109850
109851
109852
109853
109854
109855
109856
109857
109858
109859
109860
109861
109862
109863
109864
109865
109866
109867
109868
      case 24: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
  sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
        break;
      case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392);
}
        break;
      case 27: /* createkw ::= CREATE */
{
  pParse->db->lookaside.bEnabled = 0;
  yygotominor.yy0 = yymsp[0].minor.yy0;
}
        break;
      case 28: /* ifnotexists ::= */
      case 31: /* temp ::= */ yytestcase(yyruleno==31);
      case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
      case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
      case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
      case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
      case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
      case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
      case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
      case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
{yygotominor.yy392 = 0;}
        break;
      case 29: /* ifnotexists ::= IF NOT EXISTS */
      case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
      case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
      case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
      case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
      case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
      case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
{yygotominor.yy392 = 1;}
        break;
      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
}
        break;
      case 33: /* create_table_args ::= AS select */
{
  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159);
  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
}
        break;
      case 36: /* column ::= columnid type carglist */
{
  yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
  yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}
109751
109752
109753
109754
109755
109756
109757
109758
109759
109760
109761
109762
109763

109764
109765
109766
109767
109768
109769
109770
109771
109772
109773
109774
      case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
      case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
      case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
      case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
      case 128: /* as ::= ids */ yytestcase(yyruleno==128);
      case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
      case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
      case 251: /* collate ::= COLLATE ids */ yytestcase(yyruleno==251);
      case 260: /* nmnum ::= plus_num */ yytestcase(yyruleno==260);
      case 261: /* nmnum ::= nm */ yytestcase(yyruleno==261);
      case 262: /* nmnum ::= ON */ yytestcase(yyruleno==262);
      case 263: /* nmnum ::= DELETE */ yytestcase(yyruleno==263);
      case 264: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==264);

      case 265: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==265);
      case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
      case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
      case 285: /* trnm ::= nm */ yytestcase(yyruleno==285);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
        break;
      case 45: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
        break;
      case 47: /* typetoken ::= typename LP signed RP */
{







|
|
|
|
|
|
>
|


|







109881
109882
109883
109884
109885
109886
109887
109888
109889
109890
109891
109892
109893
109894
109895
109896
109897
109898
109899
109900
109901
109902
109903
109904
109905
      case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
      case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
      case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
      case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
      case 128: /* as ::= ids */ yytestcase(yyruleno==128);
      case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
      case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
      case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
      case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
      case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
      case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
      case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
      case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
      case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
      case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
      case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
      case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
      case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
        break;
      case 45: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
        break;
      case 47: /* typetoken ::= typename LP signed RP */
{
109783
109784
109785
109786
109787
109788
109789
109790
109791
109792
109793
109794
109795
109796
109797
109798
109799
109800
109801
109802
109803
109804
109805
109806
109807
109808
109809
109810
109811
109812
109813
109814
109815
109816
109817
109818
109819
109820
109821
109822
109823
109824
109825
109826
109827
109828
109829
109830
109831
109832
109833
109834
109835
109836
109837
109838
109839
109840
109841
109842
109843
109844
109845
109846
109847
109848
109849
109850
109851
109852
109853
109854
109855
109856
109857
109858
109859
109860
109861
109862
109863
109864
109865
109866
109867
109868
109869
109870
109871
109872
109873
109874
109875
109876
109877
109878
109879
109880
109881
109882
109883
109884
109885
109886
109887
109888
109889
109890
109891
109892
109893
109894
109895
109896
109897
109898
109899
109900
109901
109902
109903
109904
109905
109906
109907
109908
109909
109910
109911
109912
109913
109914
109915
109916
109917
109918
109919
109920
109921
109922
109923
109924
109925
109926
109927
109928
109929
109930
109931
109932
109933
109934
109935
109936
109937
109938
109939
109940
109941
109942
109943
109944
109945
109946
109947
109948
109949
109950
109951
109952
109953
109954
109955
109956
109957
109958
109959
109960
109961
109962
109963
109964
109965
109966
109967
109968
109969
109970
109971
109972
109973
109974
109975
109976
109977
109978
109979
109980
109981
109982
109983
109984
109985
109986
109987
109988
109989
109990
109991
109992
109993
109994
109995
109996
109997
109998
109999
110000
110001
110002
110003
110004
110005
110006
110007
110008
110009
110010
110011
110012
110013
110014
110015
110016
110017
110018
110019
110020
110021
110022
110023
110024
110025
110026
110027
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042
110043
110044
110045
110046
110047
110048
110049
110050
110051
110052
110053
110054
110055
110056
110057
110058
110059
110060
110061
110062
110063
110064
110065
110066
110067
110068
110069
110070
110071
110072
110073
110074
110075
110076
110077
110078
110079
110080
110081
110082
110083
110084
110085
110086
110087
110088
110089
110090
110091
110092
110093
110094
110095
110096



110097
110098



110099
110100
110101
110102
110103
110104
110105
110106
110107
110108
110109
110110
110111
110112
110113
110114
110115
110116
110117
110118
110119
110120
110121
110122
110123
110124
110125
110126









110127
110128
110129
110130
110131
110132
110133
110134
110135
110136
110137
110138
110139
110140
110141
110142
110143
110144
110145
110146


110147

110148
110149



110150


110151




110152
110153
110154


110155


110156
110157
110158
110159
110160
110161
110162
110163
110164
110165
110166
110167
110168
110169
110170
110171
110172
110173
110174
110175
110176
110177
110178
110179
110180
110181
110182
110183
110184
110185
110186
110187
110188
110189
110190
110191
110192
110193
110194
110195
110196
110197
110198
110199
110200
110201
110202
110203
110204
110205
110206
110207
110208
110209
110210
110211
110212
110213
110214
110215
110216
110217
110218
110219
110220
110221
110222
110223
110224
110225
110226
110227
110228
110229
110230
110231
110232
110233
110234
110235
110236
110237
110238
110239
110240
110241
110242
110243
110244
110245
110246
110247
110248
110249
110250
110251
110252
110253
110254
110255
110256
110257
110258
110259
110260
110261
110262
110263
110264
110265
110266
110267
110268
110269




110270
110271
110272
110273
110274
110275
110276
110277
110278
110279
110280
110281
110282
110283
110284
110285
110286
110287
110288
110289
110290
110291
110292
110293
110294
110295
110296
110297
110298
110299
110300
110301
110302
110303
110304
110305
110306
110307
110308
110309
110310
110311
110312
110313
110314
110315
110316
110317
110318
110319
110320
110321
110322
110323
110324
110325
110326
110327
110328
110329
110330
110331
110332
110333
110334
110335
110336
110337
110338
110339
110340
110341
110342
110343
110344
110345
110346
110347
110348
110349
110350
110351
110352
110353
110354
110355
110356
110357
110358
110359
110360
110361
110362
110363
110364
110365
110366
110367
110368
110369
110370
110371
110372
110373
110374
110375
110376
110377
110378
110379
110380
110381
110382
110383
110384
110385
110386
110387
110388
110389
110390
110391
110392
110393
110394
110395
110396
110397
110398
110399
110400
110401
110402
110403
110404
110405
110406
110407
110408
110409
110410
110411
110412
110413
110414
110415
110416
110417
110418
110419
110420
110421
110422
110423
110424
110425
110426
110427
110428
110429
110430
110431
110432
110433
110434
110435
110436
110437
110438
110439
110440
110441
110442
110443
110444
110445
110446
110447
110448
110449
110450
110451
110452
110453
110454
110455
110456






110457
110458
110459
110460
110461
110462
110463
110464
110465
110466
110467
110468
110469
110470
110471
110472
110473
110474
110475
110476
110477
110478
110479
110480
110481
110482
110483
110484
110485
110486
110487
110488
110489
110490
110491
110492
110493
110494
110495
110496
110497
110498
110499
110500
110501
110502
110503
110504
110505
110506
110507
110508
110509
110510
110511
110512
110513
110514
110515
110516
110517
110518
110519
110520
110521
110522
110523
110524
110525
110526
110527
110528
110529
110530
110531
110532
110533
110534
110535
110536
110537
110538
110539
110540
110541
110542
110543
110544
110545
110546
110547
110548
110549
110550
110551
110552
110553
110554
110555
110556
110557
110558
110559
110560
110561
110562
110563
110564
110565
110566
110567
110568
110569
110570
110571
110572
110573
110574
110575
110576
110577
110578
110579
110580
110581
110582
110583
110584
110585
110586
110587
110588
110589
110590
110591
110592
110593
110594
110595
110596
110597
110598
110599
110600
110601
110602
110603
110604
110605
110606
110607
110608
110609
110610
110611
110612
110613
110614
110615
110616
110617
110618
110619
110620
110621
110622
110623
110624
110625
110626
110627
110628
110629
110630
110631
110632
110633
110634
110635
110636
110637
110638
110639
110640
110641
110642
110643
110644
110645
110646
110647
110648
110649
110650
110651
110652
110653
110654
110655
110656
110657
110658
110659
110660
110661
110662
110663
110664
110665
110666
110667
110668
110669
110670
110671
110672
110673
110674
110675
110676
110677
110678
110679
110680
110681
110682
110683
110684
110685
110686
110687
110688
110689
110690
110691
110692
110693
110694
110695
110696
110697
110698
110699
110700
110701
110702
110703
110704
110705
}
        break;
      case 50: /* typename ::= typename ids */
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
        break;
      case 57: /* ccons ::= DEFAULT term */
      case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy118);}
        break;
      case 58: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy118);}
        break;
      case 60: /* ccons ::= DEFAULT MINUS term */
{
  ExprSpan v;
  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy118.pExpr, 0, 0);
  v.zStart = yymsp[-1].minor.yy0.z;
  v.zEnd = yymsp[0].minor.yy118.zEnd;
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 61: /* ccons ::= DEFAULT id */
{
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 63: /* ccons ::= NOT NULL onconf */
{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);}
        break;
      case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);}
        break;
      case 65: /* ccons ::= UNIQUE onconf */
{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0);}
        break;
      case 66: /* ccons ::= CHECK LP expr RP */
{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy118.pExpr);}
        break;
      case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);}
        break;
      case 68: /* ccons ::= defer_subclause */
{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);}
        break;
      case 69: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
        break;
      case 72: /* refargs ::= */
{ yygotominor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */}
        break;
      case 73: /* refargs ::= refargs refarg */
{ yygotominor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; }
        break;
      case 74: /* refarg ::= MATCH nm */
      case 75: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==75);
{ yygotominor.yy215.value = 0;     yygotominor.yy215.mask = 0x000000; }
        break;
      case 76: /* refarg ::= ON DELETE refact */
{ yygotominor.yy215.value = yymsp[0].minor.yy4;     yygotominor.yy215.mask = 0x0000ff; }
        break;
      case 77: /* refarg ::= ON UPDATE refact */
{ yygotominor.yy215.value = yymsp[0].minor.yy4<<8;  yygotominor.yy215.mask = 0x00ff00; }
        break;
      case 78: /* refact ::= SET NULL */
{ yygotominor.yy4 = OE_SetNull;  /* EV: R-33326-45252 */}
        break;
      case 79: /* refact ::= SET DEFAULT */
{ yygotominor.yy4 = OE_SetDflt;  /* EV: R-33326-45252 */}
        break;
      case 80: /* refact ::= CASCADE */
{ yygotominor.yy4 = OE_Cascade;  /* EV: R-33326-45252 */}
        break;
      case 81: /* refact ::= RESTRICT */
{ yygotominor.yy4 = OE_Restrict; /* EV: R-33326-45252 */}
        break;
      case 82: /* refact ::= NO ACTION */
{ yygotominor.yy4 = OE_None;     /* EV: R-33326-45252 */}
        break;
      case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
      case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
      case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
      case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
{yygotominor.yy4 = yymsp[0].minor.yy4;}
        break;
      case 88: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
        break;
      case 89: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
        break;
      case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);}
        break;
      case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0);}
        break;
      case 96: /* tcons ::= CHECK LP expr RP onconf */
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy118.pExpr);}
        break;
      case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4);
    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4);
}
        break;
      case 100: /* onconf ::= */
{yygotominor.yy4 = OE_Default;}
        break;
      case 102: /* orconf ::= */
{yygotominor.yy210 = OE_Default;}
        break;
      case 103: /* orconf ::= OR resolvetype */
{yygotominor.yy210 = (u8)yymsp[0].minor.yy4;}
        break;
      case 105: /* resolvetype ::= IGNORE */
{yygotominor.yy4 = OE_Ignore;}
        break;
      case 106: /* resolvetype ::= REPLACE */
{yygotominor.yy4 = OE_Replace;}
        break;
      case 107: /* cmd ::= DROP TABLE ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4);
}
        break;
      case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
{
  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy387, yymsp[-6].minor.yy4, yymsp[-4].minor.yy4);
}
        break;
      case 111: /* cmd ::= DROP VIEW ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4);
}
        break;
      case 112: /* cmd ::= select */
{
  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
  sqlite3Select(pParse, yymsp[0].minor.yy387, &dest);
  sqlite3ExplainBegin(pParse->pVdbe);
  sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy387);
  sqlite3ExplainFinish(pParse->pVdbe);
  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387);
}
        break;
      case 113: /* select ::= oneselect */
{yygotominor.yy387 = yymsp[0].minor.yy387;}
        break;
      case 114: /* select ::= select multiselect_op oneselect */
{
  if( yymsp[0].minor.yy387 ){
    yymsp[0].minor.yy387->op = (u8)yymsp[-1].minor.yy4;
    yymsp[0].minor.yy387->pPrior = yymsp[-2].minor.yy387;
  }else{
    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy387);
  }
  yygotominor.yy387 = yymsp[0].minor.yy387;
}
        break;
      case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy4 = TK_ALL;}
        break;
      case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
  yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy4,yymsp[0].minor.yy292.pLimit,yymsp[0].minor.yy292.pOffset);
}
        break;
      case 122: /* sclp ::= selcollist COMMA */
      case 247: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==247);
{yygotominor.yy322 = yymsp[-1].minor.yy322;}
        break;
      case 123: /* sclp ::= */
      case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
      case 159: /* groupby_opt ::= */ yytestcase(yyruleno==159);
      case 240: /* exprlist ::= */ yytestcase(yyruleno==240);
      case 246: /* idxlist_opt ::= */ yytestcase(yyruleno==246);
{yygotominor.yy322 = 0;}
        break;
      case 124: /* selcollist ::= sclp expr as */
{
   yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, yymsp[-1].minor.yy118.pExpr);
   if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[0].minor.yy0, 1);
   sqlite3ExprListSetSpan(pParse,yygotominor.yy322,&yymsp[-1].minor.yy118);
}
        break;
      case 125: /* selcollist ::= sclp STAR */
{
  Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
  yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy322, p);
}
        break;
      case 126: /* selcollist ::= sclp nm DOT STAR */
{
  Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
  Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, pDot);
}
        break;
      case 129: /* as ::= */
{yygotominor.yy0.n = 0;}
        break;
      case 130: /* from ::= */
{yygotominor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy259));}
        break;
      case 131: /* from ::= FROM seltablist */
{
  yygotominor.yy259 = yymsp[0].minor.yy259;
  sqlite3SrcListShiftJoinType(yygotominor.yy259);
}
        break;
      case 132: /* stl_prefix ::= seltablist joinop */
{
   yygotominor.yy259 = yymsp[-1].minor.yy259;
   if( ALWAYS(yygotominor.yy259 && yygotominor.yy259->nSrc>0) ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = (u8)yymsp[0].minor.yy4;
}
        break;
      case 133: /* stl_prefix ::= */
{yygotominor.yy259 = 0;}
        break;
      case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
  yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
  sqlite3SrcListIndexedBy(pParse, yygotominor.yy259, &yymsp[-2].minor.yy0);
}
        break;
      case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
    yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
  }
        break;
      case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
    if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){
      yygotominor.yy259 = yymsp[-4].minor.yy259;
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259);
      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,0,0,0);
      yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
    }
  }
        break;
      case 137: /* dbnm ::= */
      case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
        break;
      case 139: /* fullname ::= nm dbnm */
{yygotominor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 140: /* joinop ::= COMMA|JOIN */
{ yygotominor.yy4 = JT_INNER; }
        break;
      case 141: /* joinop ::= JOIN_KW JOIN */
{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
        break;
      case 142: /* joinop ::= JOIN_KW nm JOIN */
{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
        break;
      case 143: /* joinop ::= JOIN_KW nm nm JOIN */
{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
        break;
      case 144: /* on_opt ::= ON expr */
      case 155: /* sortitem ::= expr */ yytestcase(yyruleno==155);
      case 162: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==162);
      case 169: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==169);
      case 235: /* case_else ::= ELSE expr */ yytestcase(yyruleno==235);
      case 237: /* case_operand ::= expr */ yytestcase(yyruleno==237);
{yygotominor.yy314 = yymsp[0].minor.yy118.pExpr;}
        break;
      case 145: /* on_opt ::= */
      case 161: /* having_opt ::= */ yytestcase(yyruleno==161);
      case 168: /* where_opt ::= */ yytestcase(yyruleno==168);
      case 236: /* case_else ::= */ yytestcase(yyruleno==236);
      case 238: /* case_operand ::= */ yytestcase(yyruleno==238);
{yygotominor.yy314 = 0;}
        break;
      case 148: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
        break;
      case 149: /* using_opt ::= USING LP inscollist RP */
      case 181: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==181);
{yygotominor.yy384 = yymsp[-1].minor.yy384;}
        break;
      case 150: /* using_opt ::= */
      case 180: /* inscollist_opt ::= */ yytestcase(yyruleno==180);
{yygotominor.yy384 = 0;}
        break;
      case 152: /* orderby_opt ::= ORDER BY sortlist */
      case 160: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==160);
      case 239: /* exprlist ::= nexprlist */ yytestcase(yyruleno==239);
{yygotominor.yy322 = yymsp[0].minor.yy322;}
        break;
      case 153: /* sortlist ::= sortlist COMMA sortitem sortorder */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy314);
  if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
        break;
      case 154: /* sortlist ::= sortitem sortorder */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy314);
  if( yygotominor.yy322 && ALWAYS(yygotominor.yy322->a) ) yygotominor.yy322->a[0].sortOrder = (u8)yymsp[0].minor.yy4;
}
        break;
      case 156: /* sortorder ::= ASC */
      case 158: /* sortorder ::= */ yytestcase(yyruleno==158);
{yygotominor.yy4 = SQLITE_SO_ASC;}
        break;
      case 157: /* sortorder ::= DESC */
{yygotominor.yy4 = SQLITE_SO_DESC;}
        break;



      case 163: /* limit_opt ::= */
{yygotominor.yy292.pLimit = 0; yygotominor.yy292.pOffset = 0;}



        break;
      case 164: /* limit_opt ::= LIMIT expr */
{yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr; yygotominor.yy292.pOffset = 0;}
        break;
      case 165: /* limit_opt ::= LIMIT expr OFFSET expr */
{yygotominor.yy292.pLimit = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pOffset = yymsp[0].minor.yy118.pExpr;}
        break;
      case 166: /* limit_opt ::= LIMIT expr COMMA expr */
{yygotominor.yy292.pOffset = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr;}
        break;
      case 167: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0);
  sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314);
}
        break;
      case 170: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0);
  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); 
  sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy210);
}
        break;
      case 171: /* setlist ::= setlist COMMA nm EQ expr */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy118.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
}









        break;
      case 172: /* setlist ::= nm EQ expr */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy118.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
{sqlite3Insert(pParse, yymsp[-5].minor.yy259, yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy384, yymsp[-7].minor.yy210);}
        break;
      case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);}
        break;
      case 175: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
{sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy210);}
        break;
      case 176: /* insert_cmd ::= INSERT orconf */
{yygotominor.yy210 = yymsp[0].minor.yy210;}
        break;
      case 177: /* insert_cmd ::= REPLACE */


{yygotominor.yy210 = OE_Replace;}

        break;
      case 178: /* itemlist ::= itemlist COMMA expr */



      case 241: /* nexprlist ::= nexprlist COMMA expr */ yytestcase(yyruleno==241);


{yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy118.pExpr);}




        break;
      case 179: /* itemlist ::= expr */
      case 242: /* nexprlist ::= expr */ yytestcase(yyruleno==242);


{yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy118.pExpr);}


        break;
      case 182: /* inscollist ::= inscollist COMMA nm */
{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);}
        break;
      case 183: /* inscollist ::= nm */
{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
        break;
      case 184: /* expr ::= term */
{yygotominor.yy118 = yymsp[0].minor.yy118;}
        break;
      case 185: /* expr ::= LP expr RP */
{yygotominor.yy118.pExpr = yymsp[-1].minor.yy118.pExpr; spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 186: /* term ::= NULL */
      case 191: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==191);
      case 192: /* term ::= STRING */ yytestcase(yyruleno==192);
{spanExpr(&yygotominor.yy118, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
        break;
      case 187: /* expr ::= id */
      case 188: /* expr ::= JOIN_KW */ yytestcase(yyruleno==188);
{spanExpr(&yygotominor.yy118, pParse, TK_ID, &yymsp[0].minor.yy0);}
        break;
      case 189: /* expr ::= nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 190: /* expr ::= nm DOT nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 193: /* expr ::= REGISTER */
{
  /* When doing a nested parse, one can include terms in an expression
  ** that look like this:   #1 #2 ...  These terms refer to registers
  ** in the virtual machine.  #N is the N-th register. */
  if( pParse->nested==0 ){
    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
    yygotominor.yy118.pExpr = 0;
  }else{
    yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
    if( yygotominor.yy118.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy118.pExpr->iTable);
  }
  spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 194: /* expr ::= VARIABLE */
{
  spanExpr(&yygotominor.yy118, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
  sqlite3ExprAssignVarNumber(pParse, yygotominor.yy118.pExpr);
  spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 195: /* expr ::= expr COLLATE ids */
{
  yygotominor.yy118.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy118.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart;
  yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 196: /* expr ::= CAST LP expr AS typetoken RP */
{
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy118.pExpr, 0, &yymsp[-1].minor.yy0);
  spanSet(&yygotominor.yy118,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 197: /* expr ::= ID LP distinct exprlist RP */
{
  if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
  }
  yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0);
  spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
  if( yymsp[-2].minor.yy4 && yygotominor.yy118.pExpr ){
    yygotominor.yy118.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 198: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
  spanSet(&yygotominor.yy118,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 199: /* term ::= CTIME_KW */
{
  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
  ** treated as functions that return constants */
  yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
  if( yygotominor.yy118.pExpr ){
    yygotominor.yy118.pExpr->op = TK_CONST_FUNC;  
  }
  spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 200: /* expr ::= expr AND expr */
      case 201: /* expr ::= expr OR expr */ yytestcase(yyruleno==201);
      case 202: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==202);
      case 203: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==203);
      case 204: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==204);
      case 205: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==205);
      case 206: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==206);
      case 207: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==207);
{spanBinaryExpr(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);}
        break;




      case 208: /* likeop ::= LIKE_KW */
      case 210: /* likeop ::= MATCH */ yytestcase(yyruleno==210);
{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.not = 0;}
        break;
      case 209: /* likeop ::= NOT LIKE_KW */
      case 211: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==211);
{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.not = 1;}
        break;
      case 212: /* expr ::= expr likeop expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy118.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy118.pExpr);
  yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy342.eOperator);
  if( yymsp[-1].minor.yy342.not ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
  yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart;
  yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
  if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 213: /* expr ::= expr likeop expr ESCAPE expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy118.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr);
  yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy342.eOperator);
  if( yymsp[-3].minor.yy342.not ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
  yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
  yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
  if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 214: /* expr ::= expr ISNULL|NOTNULL */
{spanUnaryPostfix(&yygotominor.yy118,pParse,yymsp[0].major,&yymsp[-1].minor.yy118,&yymsp[0].minor.yy0);}
        break;
      case 215: /* expr ::= expr NOT NULL */
{spanUnaryPostfix(&yygotominor.yy118,pParse,TK_NOTNULL,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy0);}
        break;
      case 216: /* expr ::= expr IS expr */
{
  spanBinaryExpr(&yygotominor.yy118,pParse,TK_IS,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_ISNULL);
}
        break;
      case 217: /* expr ::= expr IS NOT expr */
{
  spanBinaryExpr(&yygotominor.yy118,pParse,TK_ISNOT,&yymsp[-3].minor.yy118,&yymsp[0].minor.yy118);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_NOTNULL);
}
        break;
      case 218: /* expr ::= NOT expr */
      case 219: /* expr ::= BITNOT expr */ yytestcase(yyruleno==219);
{spanUnaryPrefix(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
        break;
      case 220: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UMINUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
        break;
      case 221: /* expr ::= PLUS expr */
{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UPLUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
        break;
      case 224: /* expr ::= expr between_op expr AND expr */
{
  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr);
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy118.pExpr, 0, 0);
  if( yygotominor.yy118.pExpr ){
    yygotominor.yy118.pExpr->x.pList = pList;
  }else{
    sqlite3ExprListDelete(pParse->db, pList);
  } 
  if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
  yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
  yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
}
        break;
      case 227: /* expr ::= expr in_op LP exprlist RP */
{
    if( yymsp[-1].minor.yy322==0 ){
      /* Expressions of the form
      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy4]);
      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy118.pExpr);
    }else{
      yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0);
      if( yygotominor.yy118.pExpr ){
        yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy322;
        sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
      }else{
        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322);
      }
      if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
    }
    yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
    yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 228: /* expr ::= LP select RP */
{
    yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
    if( yygotominor.yy118.pExpr ){
      yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387;
      ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
    }
    yygotominor.yy118.zStart = yymsp[-2].minor.yy0.z;
    yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 229: /* expr ::= expr in_op LP select RP */
{
    yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0);
    if( yygotominor.yy118.pExpr ){
      yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387;
      ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
    }
    if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
    yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
    yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 230: /* expr ::= expr in_op nm dbnm */
{
    SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
    yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy118.pExpr, 0, 0);
    if( yygotominor.yy118.pExpr ){
      yygotominor.yy118.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
      ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
    }else{
      sqlite3SrcListDelete(pParse->db, pSrc);
    }
    if( yymsp[-2].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
    yygotominor.yy118.zStart = yymsp[-3].minor.yy118.zStart;
    yygotominor.yy118.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
  }
        break;
      case 231: /* expr ::= EXISTS LP select RP */
{
    Expr *p = yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
    if( p ){
      p->x.pSelect = yymsp[-1].minor.yy387;
      ExprSetProperty(p, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, p);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
    }
    yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z;
    yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 232: /* expr ::= CASE case_operand case_exprlist case_else END */
{
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, yymsp[-1].minor.yy314, 0);
  if( yygotominor.yy118.pExpr ){
    yygotominor.yy118.pExpr->x.pList = yymsp[-2].minor.yy322;
    sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
  }else{
    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322);
  }
  yygotominor.yy118.zStart = yymsp[-4].minor.yy0.z;
  yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 233: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy118.pExpr);
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr);
}
        break;
      case 234: /* case_exprlist ::= WHEN expr THEN expr */
{
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr);
}
        break;






      case 243: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
  sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, 
                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy322, yymsp[-9].minor.yy4,
                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy4);
}
        break;
      case 244: /* uniqueflag ::= UNIQUE */
      case 298: /* raisetype ::= ABORT */ yytestcase(yyruleno==298);
{yygotominor.yy4 = OE_Abort;}
        break;
      case 245: /* uniqueflag ::= */
{yygotominor.yy4 = OE_None;}
        break;
      case 248: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, p);
  sqlite3ExprListSetName(pParse,yygotominor.yy322,&yymsp[-2].minor.yy0,1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index");
  if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
        break;
      case 249: /* idxlist ::= nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, p);
  sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index");
  if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
        break;
      case 250: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
        break;
      case 252: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);}
        break;
      case 253: /* cmd ::= VACUUM */
      case 254: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==254);
{sqlite3Vacuum(pParse);}
        break;
      case 255: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
        break;
      case 256: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
        break;
      case 257: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
        break;
      case 258: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
        break;
      case 259: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
        break;
      case 270: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
  Token all;
  all.z = yymsp[-3].minor.yy0.z;
  all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all);
}
        break;
      case 271: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4);
  yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
        break;
      case 272: /* trigger_time ::= BEFORE */
      case 275: /* trigger_time ::= */ yytestcase(yyruleno==275);
{ yygotominor.yy4 = TK_BEFORE; }
        break;
      case 273: /* trigger_time ::= AFTER */
{ yygotominor.yy4 = TK_AFTER;  }
        break;
      case 274: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy4 = TK_INSTEAD;}
        break;
      case 276: /* trigger_event ::= DELETE|INSERT */
      case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277);
{yygotominor.yy90.a = yymsp[0].major; yygotominor.yy90.b = 0;}
        break;
      case 278: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy90.a = TK_UPDATE; yygotominor.yy90.b = yymsp[0].minor.yy384;}
        break;
      case 281: /* when_clause ::= */
      case 303: /* key_opt ::= */ yytestcase(yyruleno==303);
{ yygotominor.yy314 = 0; }
        break;
      case 282: /* when_clause ::= WHEN expr */
      case 304: /* key_opt ::= KEY expr */ yytestcase(yyruleno==304);
{ yygotominor.yy314 = yymsp[0].minor.yy118.pExpr; }
        break;
      case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
  assert( yymsp[-2].minor.yy203!=0 );
  yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203;
  yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203;
  yygotominor.yy203 = yymsp[-2].minor.yy203;
}
        break;
      case 284: /* trigger_cmd_list ::= trigger_cmd SEMI */
{ 
  assert( yymsp[-1].minor.yy203!=0 );
  yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203;
  yygotominor.yy203 = yymsp[-1].minor.yy203;
}
        break;
      case 286: /* trnm ::= nm DOT nm */
{
  yygotominor.yy0 = yymsp[0].minor.yy0;
  sqlite3ErrorMsg(pParse, 
        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
        "statements within triggers");
}
        break;
      case 288: /* tridxby ::= INDEXED BY nm */
{
  sqlite3ErrorMsg(pParse,
        "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 289: /* tridxby ::= NOT INDEXED */
{
  sqlite3ErrorMsg(pParse,
        "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 290: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
{ yygotominor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy314, yymsp[-5].minor.yy210); }
        break;
      case 291: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP */
{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy384, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy210);}
        break;
      case 292: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, 0, yymsp[0].minor.yy387, yymsp[-4].minor.yy210);}
        break;
      case 293: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
{yygotominor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy314);}
        break;
      case 294: /* trigger_cmd ::= select */
{yygotominor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy387); }
        break;
      case 295: /* expr ::= RAISE LP IGNORE RP */
{
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
  if( yygotominor.yy118.pExpr ){
    yygotominor.yy118.pExpr->affinity = OE_Ignore;
  }
  yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z;
  yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 296: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
  yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
  if( yygotominor.yy118.pExpr ) {
    yygotominor.yy118.pExpr->affinity = (char)yymsp[-3].minor.yy4;
  }
  yygotominor.yy118.zStart = yymsp[-5].minor.yy0.z;
  yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 297: /* raisetype ::= ROLLBACK */
{yygotominor.yy4 = OE_Rollback;}
        break;
      case 299: /* raisetype ::= FAIL */
{yygotominor.yy4 = OE_Fail;}
        break;
      case 300: /* cmd ::= DROP TRIGGER ifexists fullname */
{
  sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4);
}
        break;
      case 301: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
  sqlite3Attach(pParse, yymsp[-3].minor.yy118.pExpr, yymsp[-1].minor.yy118.pExpr, yymsp[0].minor.yy314);
}
        break;
      case 302: /* cmd ::= DETACH database_kw_opt expr */
{
  sqlite3Detach(pParse, yymsp[0].minor.yy118.pExpr);
}
        break;
      case 307: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
        break;
      case 308: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 309: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
        break;
      case 310: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 311: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0);
}
        break;
      case 312: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
  sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
        break;
      case 313: /* add_column_fullname ::= fullname */
{
  pParse->db->lookaside.bEnabled = 0;
  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259);
}
        break;
      case 316: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
        break;
      case 317: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
        break;
      case 318: /* create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm */
{
    sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 321: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
        break;
      case 323: /* vtabargtoken ::= ANY */
      case 324: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==324);
      case 325: /* lp ::= LP */ yytestcase(yyruleno==325);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
        break;
      default:
      /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
      /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
      /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
      /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);







|


|




|

|











|


|


|


|


|


|





|


|



|


|


|


|


|


|


|


|





|








|


|


|



|
|



|


|


|


|


|



|




|




|





|

|

|



|



|
|
|

|

|



|



|



|
|



|
|
|
|



|
|
|





|







|






|



|
|




|
|



|



|
|




|




|
|


|
|
|








|


|


|


|


|


<
|
|
|
|
|


|
|
|
|
|





|
|


|
|


|
|
|

|

|
|


|

|
|


|
|
|

|
|

>
>
>
|
|
>
>
>

<
<
<
|
<
<
<
|

|

|
|


|

|
|
|


|

|
|

>
>
>
>
>
>
>
>
>

<
<
<
<
<
<
|
|

|
|

|
|

|
|

|
>
>
|
>

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

|
|

|
|

|
|

|
|

|
|
|
|

|
|
|

|



|
|


|





|
|


|






|

|
|

|


|

|
|
|


|

|
|
|


|

|
|


|

|


|
|
|
|



|

|
|


|



|
|
|

|


|
|
|
|
|
|
|
|
|

>
>
>
>
|
<
<
<
<
|
|

|


|
|
|
|
|
|
|


|


|
|
|
|
|
|
|
|


|
|

|
|

|

|
|


|

|
|


|
|
|

|
|

|
|

|

|
|
|
|
|



|
|
|


|

|








|
|

|
|
|
|

|

|

|
|


|

|
|
|
|
|

|

|
|


|

|
|
|
|
|

|

|
|
|


|


|
|
|
|
|



|
|
|


|

|

|



|

|
|


|

|
|
|
|

|

|
|


|

|
|


|

|
|


>
>
>
>
>
>
|


|
|


|
|
|

|
|

|






|
|
|
|


|






|
|
|
|


|


|
|

|
|


|


|


|


|


|


|




|


|

|



|
|
|

|
|

|
|

|
|
|

|
|

|
|
|

|
|
|

|

|
|
|
|


|

|
|
|


|







|






|






|
|

|
|

|
|

|
|

|
|

|

|
|
|

|
|


|

|
|
|

|
|


|
|

|
|

|

|


|

|


|

|


|


|


|


|


|

|


|




|


|


|


|


|

|


|


|
|
|







109914
109915
109916
109917
109918
109919
109920
109921
109922
109923
109924
109925
109926
109927
109928
109929
109930
109931
109932
109933
109934
109935
109936
109937
109938
109939
109940
109941
109942
109943
109944
109945
109946
109947
109948
109949
109950
109951
109952
109953
109954
109955
109956
109957
109958
109959
109960
109961
109962
109963
109964
109965
109966
109967
109968
109969
109970
109971
109972
109973
109974
109975
109976
109977
109978
109979
109980
109981
109982
109983
109984
109985
109986
109987
109988
109989
109990
109991
109992
109993
109994
109995
109996
109997
109998
109999
110000
110001
110002
110003
110004
110005
110006
110007
110008
110009
110010
110011
110012
110013
110014
110015
110016
110017
110018
110019
110020
110021
110022
110023
110024
110025
110026
110027
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042
110043
110044
110045
110046
110047
110048
110049
110050
110051
110052
110053
110054
110055
110056
110057
110058
110059
110060
110061
110062
110063
110064
110065
110066
110067
110068
110069
110070
110071
110072
110073
110074
110075
110076
110077
110078
110079
110080
110081
110082
110083
110084
110085
110086
110087
110088
110089
110090
110091
110092
110093
110094
110095
110096
110097
110098
110099
110100
110101
110102
110103
110104
110105
110106
110107
110108
110109
110110
110111
110112
110113
110114
110115
110116
110117
110118
110119
110120
110121
110122
110123
110124
110125
110126
110127
110128
110129
110130
110131
110132
110133
110134
110135
110136
110137
110138
110139
110140
110141
110142
110143
110144
110145
110146
110147
110148
110149
110150
110151
110152
110153
110154
110155
110156
110157
110158
110159
110160
110161
110162
110163
110164
110165
110166
110167
110168
110169
110170
110171
110172
110173
110174
110175
110176
110177
110178

110179
110180
110181
110182
110183
110184
110185
110186
110187
110188
110189
110190
110191
110192
110193
110194
110195
110196
110197
110198
110199
110200
110201
110202
110203
110204
110205
110206
110207
110208
110209
110210
110211
110212
110213
110214
110215
110216
110217
110218
110219
110220
110221
110222
110223
110224
110225
110226
110227
110228
110229
110230
110231
110232
110233
110234
110235



110236



110237
110238
110239
110240
110241
110242
110243
110244
110245
110246
110247
110248
110249
110250
110251
110252
110253
110254
110255
110256
110257
110258
110259
110260
110261
110262
110263
110264
110265
110266






110267
110268
110269
110270
110271
110272
110273
110274
110275
110276
110277
110278
110279
110280
110281
110282
110283
110284
110285
110286
110287
110288
110289
110290
110291
110292
110293
110294
110295
110296
110297
110298
110299
110300
110301
110302
110303
110304
110305
110306
110307
110308
110309
110310
110311
110312
110313
110314
110315
110316
110317
110318
110319
110320
110321
110322
110323
110324
110325
110326
110327
110328
110329
110330
110331
110332
110333
110334
110335
110336
110337
110338
110339
110340
110341
110342
110343
110344
110345
110346
110347
110348
110349
110350
110351
110352
110353
110354
110355
110356
110357
110358
110359
110360
110361
110362
110363
110364
110365
110366
110367
110368
110369
110370
110371
110372
110373
110374
110375
110376
110377
110378
110379
110380
110381
110382
110383
110384
110385
110386
110387
110388
110389
110390
110391
110392
110393
110394
110395
110396
110397
110398
110399
110400
110401
110402
110403
110404
110405
110406
110407
110408
110409
110410
110411
110412
110413
110414
110415
110416
110417
110418
110419
110420
110421
110422
110423




110424
110425
110426
110427
110428
110429
110430
110431
110432
110433
110434
110435
110436
110437
110438
110439
110440
110441
110442
110443
110444
110445
110446
110447
110448
110449
110450
110451
110452
110453
110454
110455
110456
110457
110458
110459
110460
110461
110462
110463
110464
110465
110466
110467
110468
110469
110470
110471
110472
110473
110474
110475
110476
110477
110478
110479
110480
110481
110482
110483
110484
110485
110486
110487
110488
110489
110490
110491
110492
110493
110494
110495
110496
110497
110498
110499
110500
110501
110502
110503
110504
110505
110506
110507
110508
110509
110510
110511
110512
110513
110514
110515
110516
110517
110518
110519
110520
110521
110522
110523
110524
110525
110526
110527
110528
110529
110530
110531
110532
110533
110534
110535
110536
110537
110538
110539
110540
110541
110542
110543
110544
110545
110546
110547
110548
110549
110550
110551
110552
110553
110554
110555
110556
110557
110558
110559
110560
110561
110562
110563
110564
110565
110566
110567
110568
110569
110570
110571
110572
110573
110574
110575
110576
110577
110578
110579
110580
110581
110582
110583
110584
110585
110586
110587
110588
110589
110590
110591
110592
110593
110594
110595
110596
110597
110598
110599
110600
110601
110602
110603
110604
110605
110606
110607
110608
110609
110610
110611
110612
110613
110614
110615
110616
110617
110618
110619
110620
110621
110622
110623
110624
110625
110626
110627
110628
110629
110630
110631
110632
110633
110634
110635
110636
110637
110638
110639
110640
110641
110642
110643
110644
110645
110646
110647
110648
110649
110650
110651
110652
110653
110654
110655
110656
110657
110658
110659
110660
110661
110662
110663
110664
110665
110666
110667
110668
110669
110670
110671
110672
110673
110674
110675
110676
110677
110678
110679
110680
110681
110682
110683
110684
110685
110686
110687
110688
110689
110690
110691
110692
110693
110694
110695
110696
110697
110698
110699
110700
110701
110702
110703
110704
110705
110706
110707
110708
110709
110710
110711
110712
110713
110714
110715
110716
110717
110718
110719
110720
110721
110722
110723
110724
110725
110726
110727
110728
110729
110730
110731
110732
110733
110734
110735
110736
110737
110738
110739
110740
110741
110742
110743
110744
110745
110746
110747
110748
110749
110750
110751
110752
110753
110754
110755
110756
110757
110758
110759
110760
110761
110762
110763
110764
110765
110766
110767
110768
110769
110770
110771
110772
110773
110774
110775
110776
110777
110778
110779
110780
110781
110782
110783
110784
110785
110786
110787
110788
110789
110790
110791
110792
110793
110794
110795
110796
110797
110798
110799
110800
110801
110802
110803
110804
110805
110806
110807
110808
110809
110810
110811
110812
110813
110814
110815
110816
110817
110818
110819
110820
110821
110822
110823
110824
110825
110826
110827
110828
110829
110830
110831
110832
110833
110834
110835
110836
110837
110838
110839
110840
110841
110842
110843
110844
110845
110846
110847
110848
110849
110850
110851
110852
110853
110854
110855
110856
110857
110858
110859
110860
}
        break;
      case 50: /* typename ::= typename ids */
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
        break;
      case 57: /* ccons ::= DEFAULT term */
      case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
        break;
      case 58: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);}
        break;
      case 60: /* ccons ::= DEFAULT MINUS term */
{
  ExprSpan v;
  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0);
  v.zStart = yymsp[-1].minor.yy0.z;
  v.zEnd = yymsp[0].minor.yy342.zEnd;
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 61: /* ccons ::= DEFAULT id */
{
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 63: /* ccons ::= NOT NULL onconf */
{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);}
        break;
      case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);}
        break;
      case 65: /* ccons ::= UNIQUE onconf */
{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);}
        break;
      case 66: /* ccons ::= CHECK LP expr RP */
{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);}
        break;
      case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);}
        break;
      case 68: /* ccons ::= defer_subclause */
{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);}
        break;
      case 69: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
        break;
      case 72: /* refargs ::= */
{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */}
        break;
      case 73: /* refargs ::= refargs refarg */
{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
        break;
      case 74: /* refarg ::= MATCH nm */
      case 75: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==75);
{ yygotominor.yy207.value = 0;     yygotominor.yy207.mask = 0x000000; }
        break;
      case 76: /* refarg ::= ON DELETE refact */
{ yygotominor.yy207.value = yymsp[0].minor.yy392;     yygotominor.yy207.mask = 0x0000ff; }
        break;
      case 77: /* refarg ::= ON UPDATE refact */
{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8;  yygotominor.yy207.mask = 0x00ff00; }
        break;
      case 78: /* refact ::= SET NULL */
{ yygotominor.yy392 = OE_SetNull;  /* EV: R-33326-45252 */}
        break;
      case 79: /* refact ::= SET DEFAULT */
{ yygotominor.yy392 = OE_SetDflt;  /* EV: R-33326-45252 */}
        break;
      case 80: /* refact ::= CASCADE */
{ yygotominor.yy392 = OE_Cascade;  /* EV: R-33326-45252 */}
        break;
      case 81: /* refact ::= RESTRICT */
{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */}
        break;
      case 82: /* refact ::= NO ACTION */
{ yygotominor.yy392 = OE_None;     /* EV: R-33326-45252 */}
        break;
      case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
      case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
      case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
      case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
{yygotominor.yy392 = yymsp[0].minor.yy392;}
        break;
      case 88: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
        break;
      case 89: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
        break;
      case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
        break;
      case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
        break;
      case 96: /* tcons ::= CHECK LP expr RP onconf */
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
        break;
      case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
}
        break;
      case 100: /* onconf ::= */
{yygotominor.yy392 = OE_Default;}
        break;
      case 102: /* orconf ::= */
{yygotominor.yy258 = OE_Default;}
        break;
      case 103: /* orconf ::= OR resolvetype */
{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
        break;
      case 105: /* resolvetype ::= IGNORE */
{yygotominor.yy392 = OE_Ignore;}
        break;
      case 106: /* resolvetype ::= REPLACE */
{yygotominor.yy392 = OE_Replace;}
        break;
      case 107: /* cmd ::= DROP TABLE ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
}
        break;
      case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
{
  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
}
        break;
      case 111: /* cmd ::= DROP VIEW ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
}
        break;
      case 112: /* cmd ::= select */
{
  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
  sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
  sqlite3ExplainBegin(pParse->pVdbe);
  sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
  sqlite3ExplainFinish(pParse->pVdbe);
  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
}
        break;
      case 113: /* select ::= oneselect */
{yygotominor.yy159 = yymsp[0].minor.yy159;}
        break;
      case 114: /* select ::= select multiselect_op oneselect */
{
  if( yymsp[0].minor.yy159 ){
    yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
    yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
  }else{
    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
  }
  yygotominor.yy159 = yymsp[0].minor.yy159;
}
        break;
      case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy392 = TK_ALL;}
        break;
      case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
}
        break;
      case 122: /* sclp ::= selcollist COMMA */
      case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
        break;
      case 123: /* sclp ::= */
      case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
      case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
      case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
      case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
{yygotominor.yy442 = 0;}
        break;
      case 124: /* selcollist ::= sclp expr as */
{
   yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
   if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
   sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
}
        break;
      case 125: /* selcollist ::= sclp STAR */
{
  Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
}
        break;
      case 126: /* selcollist ::= sclp nm DOT STAR */
{
  Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
  Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
}
        break;
      case 129: /* as ::= */
{yygotominor.yy0.n = 0;}
        break;
      case 130: /* from ::= */
{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
        break;
      case 131: /* from ::= FROM seltablist */
{
  yygotominor.yy347 = yymsp[0].minor.yy347;
  sqlite3SrcListShiftJoinType(yygotominor.yy347);
}
        break;
      case 132: /* stl_prefix ::= seltablist joinop */
{
   yygotominor.yy347 = yymsp[-1].minor.yy347;
   if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
}
        break;
      case 133: /* stl_prefix ::= */
{yygotominor.yy347 = 0;}
        break;
      case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
  yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
  sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
}
        break;
      case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
    yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
  }
        break;
      case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
    if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
      yygotominor.yy347 = yymsp[-4].minor.yy347;
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
    }
  }
        break;
      case 137: /* dbnm ::= */
      case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
        break;
      case 139: /* fullname ::= nm dbnm */
{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 140: /* joinop ::= COMMA|JOIN */
{ yygotominor.yy392 = JT_INNER; }
        break;
      case 141: /* joinop ::= JOIN_KW JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
        break;
      case 142: /* joinop ::= JOIN_KW nm JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
        break;
      case 143: /* joinop ::= JOIN_KW nm nm JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
        break;
      case 144: /* on_opt ::= ON expr */

      case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
      case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
      case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
      case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
        break;
      case 145: /* on_opt ::= */
      case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
      case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
      case 235: /* case_else ::= */ yytestcase(yyruleno==235);
      case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
{yygotominor.yy122 = 0;}
        break;
      case 148: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
        break;
      case 149: /* using_opt ::= USING LP inscollist RP */
      case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
{yygotominor.yy180 = yymsp[-1].minor.yy180;}
        break;
      case 150: /* using_opt ::= */
      case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
{yygotominor.yy180 = 0;}
        break;
      case 152: /* orderby_opt ::= ORDER BY sortlist */
      case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
      case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
{yygotominor.yy442 = yymsp[0].minor.yy442;}
        break;
      case 153: /* sortlist ::= sortlist COMMA expr sortorder */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 154: /* sortlist ::= expr sortorder */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
  if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 155: /* sortorder ::= ASC */
      case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
{yygotominor.yy392 = SQLITE_SO_ASC;}
        break;
      case 156: /* sortorder ::= DESC */
{yygotominor.yy392 = SQLITE_SO_DESC;}
        break;
      case 162: /* limit_opt ::= */
{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
        break;
      case 163: /* limit_opt ::= LIMIT expr */
{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
        break;
      case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
        break;



      case 165: /* limit_opt ::= LIMIT expr COMMA expr */



{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
        break;
      case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
  sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
}
        break;
      case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); 
  sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
}
        break;
      case 170: /* setlist ::= setlist COMMA nm EQ expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 171: /* setlist ::= nm EQ expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
        break;






      case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
        break;
      case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
        break;
      case 175: /* insert_cmd ::= INSERT orconf */
{yygotominor.yy258 = yymsp[0].minor.yy258;}
        break;
      case 176: /* insert_cmd ::= REPLACE */
{yygotominor.yy258 = OE_Replace;}
        break;
      case 177: /* valuelist ::= VALUES LP nexprlist RP */
{
  yygotominor.yy487.pList = yymsp[-1].minor.yy442;
  yygotominor.yy487.pSelect = 0;
}
        break;
      case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
{
  Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
  if( yymsp[-4].minor.yy487.pList ){
    yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
    yymsp[-4].minor.yy487.pList = 0;
  }
  yygotominor.yy487.pList = 0;
  if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){
    sqlite3SelectDelete(pParse->db, pRight);
    sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect);
    yygotominor.yy487.pSelect = 0;
  }else{
    pRight->op = TK_ALL;
    pRight->pPrior = yymsp[-4].minor.yy487.pSelect;
    pRight->selFlags |= SF_Values;
    pRight->pPrior->selFlags |= SF_Values;
    yygotominor.yy487.pSelect = pRight;
  }
}
        break;
      case 181: /* inscollist ::= inscollist COMMA nm */
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
        break;
      case 182: /* inscollist ::= nm */
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
        break;
      case 183: /* expr ::= term */
{yygotominor.yy342 = yymsp[0].minor.yy342;}
        break;
      case 184: /* expr ::= LP expr RP */
{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 185: /* term ::= NULL */
      case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
      case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
        break;
      case 186: /* expr ::= id */
      case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
        break;
      case 188: /* expr ::= nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 189: /* expr ::= nm DOT nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 192: /* expr ::= REGISTER */
{
  /* When doing a nested parse, one can include terms in an expression
  ** that look like this:   #1 #2 ...  These terms refer to registers
  ** in the virtual machine.  #N is the N-th register. */
  if( pParse->nested==0 ){
    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
    yygotominor.yy342.pExpr = 0;
  }else{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
    if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
  }
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 193: /* expr ::= VARIABLE */
{
  spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
  sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 194: /* expr ::= expr COLLATE ids */
{
  yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 195: /* expr ::= CAST LP expr AS typetoken RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 196: /* expr ::= ID LP distinct exprlist RP */
{
  if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
  }
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
  if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 197: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 198: /* term ::= CTIME_KW */
{
  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
  ** treated as functions that return constants */
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->op = TK_CONST_FUNC;  
  }
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 199: /* expr ::= expr AND expr */
      case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
      case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
      case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
      case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
      case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
      case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
      case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
        break;
      case 207: /* likeop ::= LIKE_KW */
      case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 0;}
        break;
      case 208: /* likeop ::= NOT LIKE_KW */




      case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 1;}
        break;
      case 211: /* expr ::= expr likeop expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
  if( yymsp[-1].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 212: /* expr ::= expr likeop expr ESCAPE expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
  if( yymsp[-3].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 213: /* expr ::= expr ISNULL|NOTNULL */
{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
        break;
      case 214: /* expr ::= expr NOT NULL */
{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
        break;
      case 215: /* expr ::= expr IS expr */
{
  spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
}
        break;
      case 216: /* expr ::= expr IS NOT expr */
{
  spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
}
        break;
      case 217: /* expr ::= NOT expr */
      case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 219: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 220: /* expr ::= PLUS expr */
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 223: /* expr ::= expr between_op expr AND expr */
{
  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->x.pList = pList;
  }else{
    sqlite3ExprListDelete(pParse->db, pList);
  } 
  if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
}
        break;
      case 226: /* expr ::= expr in_op LP exprlist RP */
{
    if( yymsp[-1].minor.yy442==0 ){
      /* Expressions of the form
      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]);
      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr);
    }else{
      yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
      if( yygotominor.yy342.pExpr ){
        yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442;
        sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
      }else{
        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442);
      }
      if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    }
    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 227: /* expr ::= LP select RP */
{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 228: /* expr ::= expr in_op LP select RP */
{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 229: /* expr ::= expr in_op nm dbnm */
{
    SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
    }else{
      sqlite3SrcListDelete(pParse->db, pSrc);
    }
    if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
    yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
  }
        break;
      case 230: /* expr ::= EXISTS LP select RP */
{
    Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
    if( p ){
      p->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(p, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, p);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
    sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
  }else{
    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442);
  }
  yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 233: /* case_exprlist ::= WHEN expr THEN expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 240: /* nexprlist ::= nexprlist COMMA expr */
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
        break;
      case 241: /* nexprlist ::= expr */
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
        break;
      case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
  sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, 
                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
}
        break;
      case 243: /* uniqueflag ::= UNIQUE */
      case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
{yygotominor.yy392 = OE_Abort;}
        break;
      case 244: /* uniqueflag ::= */
{yygotominor.yy392 = OE_None;}
        break;
      case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
  sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 248: /* idxlist ::= nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 249: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
        break;
      case 251: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
        break;
      case 252: /* cmd ::= VACUUM */
      case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
{sqlite3Vacuum(pParse);}
        break;
      case 254: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
        break;
      case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
        break;
      case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
        break;
      case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
        break;
      case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
        break;
      case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
  Token all;
  all.z = yymsp[-3].minor.yy0.z;
  all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
}
        break;
      case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
  yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
        break;
      case 270: /* trigger_time ::= BEFORE */
      case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
{ yygotominor.yy392 = TK_BEFORE; }
        break;
      case 271: /* trigger_time ::= AFTER */
{ yygotominor.yy392 = TK_AFTER;  }
        break;
      case 272: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy392 = TK_INSTEAD;}
        break;
      case 274: /* trigger_event ::= DELETE|INSERT */
      case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
        break;
      case 276: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
        break;
      case 279: /* when_clause ::= */
      case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
{ yygotominor.yy122 = 0; }
        break;
      case 280: /* when_clause ::= WHEN expr */
      case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
        break;
      case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
  assert( yymsp[-2].minor.yy327!=0 );
  yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
  yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
  yygotominor.yy327 = yymsp[-2].minor.yy327;
}
        break;
      case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
{ 
  assert( yymsp[-1].minor.yy327!=0 );
  yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
  yygotominor.yy327 = yymsp[-1].minor.yy327;
}
        break;
      case 284: /* trnm ::= nm DOT nm */
{
  yygotominor.yy0 = yymsp[0].minor.yy0;
  sqlite3ErrorMsg(pParse, 
        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
        "statements within triggers");
}
        break;
      case 286: /* tridxby ::= INDEXED BY nm */
{
  sqlite3ErrorMsg(pParse,
        "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 287: /* tridxby ::= NOT INDEXED */
{
  sqlite3ErrorMsg(pParse,
        "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
        break;
      case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
        break;
      case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
        break;
      case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
        break;
      case 292: /* trigger_cmd ::= select */
{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
        break;
      case 293: /* expr ::= RAISE LP IGNORE RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->affinity = OE_Ignore;
  }
  yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
  if( yygotominor.yy342.pExpr ) {
    yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
  }
  yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 295: /* raisetype ::= ROLLBACK */
{yygotominor.yy392 = OE_Rollback;}
        break;
      case 297: /* raisetype ::= FAIL */
{yygotominor.yy392 = OE_Fail;}
        break;
      case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
{
  sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
}
        break;
      case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
  sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
}
        break;
      case 300: /* cmd ::= DETACH database_kw_opt expr */
{
  sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 305: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
        break;
      case 306: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 307: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
        break;
      case 308: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
}
        break;
      case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
  sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
        break;
      case 311: /* add_column_fullname ::= fullname */
{
  pParse->db->lookaside.bEnabled = 0;
  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
}
        break;
      case 314: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
        break;
      case 315: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
        break;
      case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
    sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
}
        break;
      case 319: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
        break;
      case 321: /* vtabargtoken ::= ANY */
      case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
      case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
        break;
      default:
      /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
      /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
      /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
      /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
110720
110721
110722
110723
110724
110725
110726
110727
110728
110729
110730
110731
110732
110733
110734
110735
110736
110737
110738
110739
110740
110741
110742
110743
110744
110745
110746
110747
110748
      /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
      /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
      /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
      /* (90) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==90);
      /* (91) conslist ::= conslist tcons */ yytestcase(yyruleno==91);
      /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
      /* (93) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
      /* (268) plus_opt ::= PLUS */ yytestcase(yyruleno==268);
      /* (269) plus_opt ::= */ yytestcase(yyruleno==269);
      /* (279) foreach_clause ::= */ yytestcase(yyruleno==279);
      /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280);
      /* (287) tridxby ::= */ yytestcase(yyruleno==287);
      /* (305) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==305);
      /* (306) database_kw_opt ::= */ yytestcase(yyruleno==306);
      /* (314) kwcolumn_opt ::= */ yytestcase(yyruleno==314);
      /* (315) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==315);
      /* (319) vtabarglist ::= vtabarg */ yytestcase(yyruleno==319);
      /* (320) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==320);
      /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322);
      /* (326) anylist ::= */ yytestcase(yyruleno==326);
      /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327);
      /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328);
        break;
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
  if( yyact < YYNSTATE ){







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







110875
110876
110877
110878
110879
110880
110881


110882
110883
110884
110885
110886
110887
110888
110889
110890
110891
110892
110893
110894
110895
110896
110897
110898
110899
110900
110901
      /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
      /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
      /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
      /* (90) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==90);
      /* (91) conslist ::= conslist tcons */ yytestcase(yyruleno==91);
      /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
      /* (93) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);


      /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
      /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
      /* (285) tridxby ::= */ yytestcase(yyruleno==285);
      /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
      /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
      /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
      /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
      /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
      /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
      /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
      /* (324) anylist ::= */ yytestcase(yyruleno==324);
      /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
      /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
        break;
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
  if( yyact < YYNSTATE ){
115165
115166
115167
115168
115169
115170
115171

115172
115173
115174
115175
115176
115177
115178
115179
}

/*
** Return a boolean value for a query parameter.
*/
SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
  const char *z = sqlite3_uri_parameter(zFilename, zParam);

  return z ? sqlite3GetBoolean(z) : (bDflt!=0);
}

/*
** Return a 64-bit integer value for a query parameter.
*/
SQLITE_API sqlite3_int64 sqlite3_uri_int64(
  const char *zFilename,    /* Filename as passed to xOpen */







>
|







115318
115319
115320
115321
115322
115323
115324
115325
115326
115327
115328
115329
115330
115331
115332
115333
}

/*
** Return a boolean value for a query parameter.
*/
SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
  const char *z = sqlite3_uri_parameter(zFilename, zParam);
  bDflt = bDflt!=0;
  return z ? sqlite3GetBoolean(z, bDflt) : bDflt;
}

/*
** Return a 64-bit integer value for a query parameter.
*/
SQLITE_API sqlite3_int64 sqlite3_uri_int64(
  const char *zFilename,    /* Filename as passed to xOpen */
116501
116502
116503
116504
116505
116506
116507
116508
116509
116510
116511
116512
116513
116514
116515


/* fts3_write.c */
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
  sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
  Fts3Table*,int,const char*,int,int,Fts3SegReader**);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);







|







116655
116656
116657
116658
116659
116660
116661
116662
116663
116664
116665
116666
116667
116668
116669


/* fts3_write.c */
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
  sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
  Fts3Table*,int,const char*,int,int,Fts3SegReader**);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
118929
118930
118931
118932
118933
118934
118935

118936

118937
118938
118939
118940
118941
118942
118943
        sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
        rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
        if( rc!=SQLITE_OK ) goto finished;
        if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
      }
 
      rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 

          iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg

      );
      if( rc!=SQLITE_OK ) goto finished;
      rc = fts3SegReaderCursorAppend(pCsr, pSeg);
    }
  }

 finished:







>
|
>







119083
119084
119085
119086
119087
119088
119089
119090
119091
119092
119093
119094
119095
119096
119097
119098
119099
        sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
        rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
        if( rc!=SQLITE_OK ) goto finished;
        if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
      }
 
      rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 
          (isPrefix==0 && isScan==0),
          iStartBlock, iLeavesEndBlock, 
          iEndBlock, zRoot, nRoot, &pSeg
      );
      if( rc!=SQLITE_OK ) goto finished;
      rc = fts3SegReaderCursorAppend(pCsr, pSeg);
    }
  }

 finished:
124751
124752
124753
124754
124755
124756
124757

124758
124759
124760
124761
124762
124763
124764
**
**   fts3SegReaderNext()
**   fts3SegReaderFirstDocid()
**   fts3SegReaderNextDocid()
*/
struct Fts3SegReader {
  int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */


  sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
  sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
  sqlite3_int64 iEndBlock;        /* Rowid of final block in segment (or 0) */
  sqlite3_int64 iCurrentBlock;    /* Current leaf block (or 0) */

  char *aNode;                    /* Pointer to node data (or NULL) */







>







124907
124908
124909
124910
124911
124912
124913
124914
124915
124916
124917
124918
124919
124920
124921
**
**   fts3SegReaderNext()
**   fts3SegReaderFirstDocid()
**   fts3SegReaderNextDocid()
*/
struct Fts3SegReader {
  int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */
  int bLookup;                    /* True for a lookup only */

  sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
  sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
  sqlite3_int64 iEndBlock;        /* Rowid of final block in segment (or 0) */
  sqlite3_int64 iCurrentBlock;    /* Current leaf block (or 0) */

  char *aNode;                    /* Pointer to node data (or NULL) */
125728
125729
125730
125731
125732
125733
125734












125735
125736
125737
125738
125739
125740
125741
  while( pReader->pBlob && rc==SQLITE_OK 
     &&  (pFrom - pReader->aNode + nByte)>pReader->nPopulate
  ){
    rc = fts3SegReaderIncrRead(pReader);
  }
  return rc;
}













/*
** Move the iterator passed as the first argument to the next term in the
** segment. If successful, SQLITE_OK is returned. If there is no next term,
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(







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







125885
125886
125887
125888
125889
125890
125891
125892
125893
125894
125895
125896
125897
125898
125899
125900
125901
125902
125903
125904
125905
125906
125907
125908
125909
125910
  while( pReader->pBlob && rc==SQLITE_OK 
     &&  (pFrom - pReader->aNode + nByte)>pReader->nPopulate
  ){
    rc = fts3SegReaderIncrRead(pReader);
  }
  return rc;
}

/*
** Set an Fts3SegReader cursor to point at EOF.
*/
static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
  if( !fts3SegReaderIsRootOnly(pSeg) ){
    sqlite3_free(pSeg->aNode);
    sqlite3_blob_close(pSeg->pBlob);
    pSeg->pBlob = 0;
  }
  pSeg->aNode = 0;
}

/*
** Move the iterator passed as the first argument to the next term in the
** segment. If successful, SQLITE_OK is returned. If there is no next term,
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(
125768
125769
125770
125771
125772
125773
125774
125775
125776
125777
125778
125779
125780
125781
125782
125783
125784
125785
125786
125787
        pReader->aNode = pReader->aDoclist = pList->aData;
        pReader->ppNextElem++;
        assert( pReader->aNode );
      }
      return SQLITE_OK;
    }

    if( !fts3SegReaderIsRootOnly(pReader) ){
      sqlite3_free(pReader->aNode);
      sqlite3_blob_close(pReader->pBlob);
      pReader->pBlob = 0;
    }
    pReader->aNode = 0;

    /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
    ** blocks have already been traversed.  */
    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
    if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
      return SQLITE_OK;
    }







|
<
<
<
<
<







125937
125938
125939
125940
125941
125942
125943
125944





125945
125946
125947
125948
125949
125950
125951
        pReader->aNode = pReader->aDoclist = pList->aData;
        pReader->ppNextElem++;
        assert( pReader->aNode );
      }
      return SQLITE_OK;
    }

    fts3SegReaderSetEof(pReader);






    /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
    ** blocks have already been traversed.  */
    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
    if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
      return SQLITE_OK;
    }
126020
126021
126022
126023
126024
126025
126026

126027
126028
126029
126030
126031
126032
126033
}

/*
** Allocate a new SegReader object.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
  int iAge,                       /* Segment "age". */

  sqlite3_int64 iStartLeaf,       /* First leaf to traverse */
  sqlite3_int64 iEndLeaf,         /* Final leaf to traverse */
  sqlite3_int64 iEndBlock,        /* Final block of segment */
  const char *zRoot,              /* Buffer containing root node */
  int nRoot,                      /* Size of buffer containing root node */
  Fts3SegReader **ppReader        /* OUT: Allocated Fts3SegReader */
){







>







126184
126185
126186
126187
126188
126189
126190
126191
126192
126193
126194
126195
126196
126197
126198
}

/*
** Allocate a new SegReader object.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
  int iAge,                       /* Segment "age". */
  int bLookup,                    /* True for a lookup only */
  sqlite3_int64 iStartLeaf,       /* First leaf to traverse */
  sqlite3_int64 iEndLeaf,         /* Final leaf to traverse */
  sqlite3_int64 iEndBlock,        /* Final block of segment */
  const char *zRoot,              /* Buffer containing root node */
  int nRoot,                      /* Size of buffer containing root node */
  Fts3SegReader **ppReader        /* OUT: Allocated Fts3SegReader */
){
126041
126042
126043
126044
126045
126046
126047

126048
126049
126050
126051
126052
126053
126054

  pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  if( !pReader ){
    return SQLITE_NOMEM;
  }
  memset(pReader, 0, sizeof(Fts3SegReader));
  pReader->iIdx = iAge;

  pReader->iStartBlock = iStartLeaf;
  pReader->iLeafEndBlock = iEndLeaf;
  pReader->iEndBlock = iEndBlock;

  if( nExtra ){
    /* The entire segment is stored in the root node. */
    pReader->aNode = (char *)&pReader[1];







>







126206
126207
126208
126209
126210
126211
126212
126213
126214
126215
126216
126217
126218
126219
126220

  pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  if( !pReader ){
    return SQLITE_NOMEM;
  }
  memset(pReader, 0, sizeof(Fts3SegReader));
  pReader->iIdx = iAge;
  pReader->bLookup = bLookup;
  pReader->iStartBlock = iStartLeaf;
  pReader->iLeafEndBlock = iEndLeaf;
  pReader->iEndBlock = iEndBlock;

  if( nExtra ){
    /* The entire segment is stored in the root node. */
    pReader->aNode = (char *)&pReader[1];
127043
127044
127045
127046
127047
127048
127049

127050
127051
127052
127053
127054




127055
127056
127057
127058
127059
127060
127061
  /* If the Fts3SegFilter defines a specific term (or term prefix) to search 
  ** for, then advance each segment iterator until it points to a term of
  ** equal or greater value than the specified term. This prevents many
  ** unnecessary merge/sort operations for the case where single segment
  ** b-tree leaf nodes contain more than one term.
  */
  for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){

    Fts3SegReader *pSeg = pCsr->apSegment[i];
    do {
      int rc = fts3SegReaderNext(p, pSeg, 0);
      if( rc!=SQLITE_OK ) return rc;
    }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );




  }
  fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);

  return SQLITE_OK;
}

SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(







>




|
>
>
>
>







127209
127210
127211
127212
127213
127214
127215
127216
127217
127218
127219
127220
127221
127222
127223
127224
127225
127226
127227
127228
127229
127230
127231
127232
  /* If the Fts3SegFilter defines a specific term (or term prefix) to search 
  ** for, then advance each segment iterator until it points to a term of
  ** equal or greater value than the specified term. This prevents many
  ** unnecessary merge/sort operations for the case where single segment
  ** b-tree leaf nodes contain more than one term.
  */
  for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
    int res = 0;
    Fts3SegReader *pSeg = pCsr->apSegment[i];
    do {
      int rc = fts3SegReaderNext(p, pSeg, 0);
      if( rc!=SQLITE_OK ) return rc;
    }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );

    if( pSeg->bLookup && res!=0 ){
      fts3SegReaderSetEof(pSeg);
    }
  }
  fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);

  return SQLITE_OK;
}

SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
127168
127169
127170
127171
127172
127173
127174




127175

127176
127177
127178
127179
127180
127181
127182
    int nMerge;
    int i;
  
    /* Advance the first pCsr->nAdvance entries in the apSegment[] array
    ** forward. Then sort the list in order of current term again.  
    */
    for(i=0; i<pCsr->nAdvance; i++){




      rc = fts3SegReaderNext(p, apSegment[i], 0);

      if( rc!=SQLITE_OK ) return rc;
    }
    fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
    pCsr->nAdvance = 0;

    /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
    assert( rc==SQLITE_OK );







>
>
>
>
|
>







127339
127340
127341
127342
127343
127344
127345
127346
127347
127348
127349
127350
127351
127352
127353
127354
127355
127356
127357
127358
    int nMerge;
    int i;
  
    /* Advance the first pCsr->nAdvance entries in the apSegment[] array
    ** forward. Then sort the list in order of current term again.  
    */
    for(i=0; i<pCsr->nAdvance; i++){
      Fts3SegReader *pSeg = apSegment[i];
      if( pSeg->bLookup ){
        fts3SegReaderSetEof(pSeg);
      }else{
        rc = fts3SegReaderNext(p, pSeg, 0);
      }
      if( rc!=SQLITE_OK ) return rc;
    }
    fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
    pCsr->nAdvance = 0;

    /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
    assert( rc==SQLITE_OK );
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.7.10"
#define SQLITE_VERSION_NUMBER 3007010
#define SQLITE_SOURCE_ID      "2012-01-11 16:16:08 9e31a275ef494ea8713a1d60a15b84157e57c3ff"

/*
** 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.7.11"
#define SQLITE_VERSION_NUMBER 3007011
#define SQLITE_SOURCE_ID      "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"

/*
** 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
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
/*
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** If F is the filename pointer passed into the xOpen() method of a VFS


** implementation and P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The value of P is true if it is "yes" or "true" or "on" or 




** a non-zero number and is false otherwise.  If P is not a query parameter

** on F then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
** 
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a pathname pointer that SQLite passed into the xOpen VFS method,
** then the behavior of this routine is undefined and probably undesirable.

*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);


/*







|
>
>
|








|
>
>
>
>
|
>
|








|
|
>







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
/*
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** If F is the database filename pointer passed into the xOpen() method of 
** a VFS implementation when the flags parameter to xOpen() has one or 
** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
** value of query parameter P is one of "yes", "true", or "on" in any
** case or if the value begins with a non-zero number.  The 
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero.  If P is not a query
** parameter on F or if the value of P is does not match any of the
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
** 
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);


/*
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
** handle invalid, and will not use it with any other sqlite3_pcache_methods2
** functions.
**
** [[the xShrink() page cache method]]
** ^SQLite invokes the xShrink() method when it wants the page cache to
** free up as much of heap memory as possible.  The page cache implementation
** is not obligated to free any memory, but well-behaved implementions should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
  int iVersion;
  void *pArg;
  int (*xInit)(void*);







|







6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
** handle invalid, and will not use it with any other sqlite3_pcache_methods2
** functions.
**
** [[the xShrink() page cache method]]
** ^SQLite invokes the xShrink() method when it wants the page cache to
** free up as much of heap memory as possible.  The page cache implementation
** is not obligated to free any memory, but well-behaved implementations should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
  int iVersion;
  void *pArg;
  int (*xInit)(void*);
Changes to src/style.c.
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
@
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }
@
@ /* Side-by-side diff */
@ table.sbsdiff {
@   background-color: white;
@   font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
@   font-size: 8pt;
@   border-collapse:collapse;
@   white-space: pre;
@   width: 98%;
@   border: 1px #000 dashed;
@   margin-left: auto;
@   margin-right: auto;
@ }
@
@ table.sbsdiff th.diffhdr {
@   border-bottom: dotted;
@   border-width: 1px;
@ }
@
@ table.sbsdiff tr td {
@   white-space: pre;
@   padding-left: 3px;
@   padding-right: 3px;
@   margin: 0px;
@   vertical-align: top;
@ }
@
@ table.sbsdiff tr td.lineno {
@   text-align: right;
@ }
@
@ table.sbsdiff tr td.srcline {
@ }
@
@ table.sbsdiff tr td.meta {
@   background-color: rgb(170, 160, 255);
@   text-align: center;
@ }
@
@ table.sbsdiff tr td.added {
@   background-color: rgb(180, 250, 180);
@ }
@ table.sbsdiff tr td.addedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
@ table.sbsdiff tr td.removed {
@   background-color: rgb(250, 130, 130);
@ }
@ table.sbsdiff tr td.removedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
@ table.sbsdiff tr td.changed {
@   background-color: rgb(210, 210, 200);
@ }
@ table.sbsdiff tr td.changedvoid {
@   background-color: rgb(190, 190, 180);
@ }
@
;


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/







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







396
397
398
399
400
401
402




























































403
404
405
406
407
408
409
@
@ /* The label/value pairs on (for example) the ci page */
@ table.label-value th {
@   vertical-align: top;
@   text-align: right;
@   padding: 0.2ex 2ex;
@ }




























































;


/* The following table contains bits of default CSS that must
** be included if they are not found in the application-defined
** CSS.
*/
768
769
770
771
772
773
774





775
776
777
778
779
780
781
    @   color: red;
  },
  { "p.tktsetupError",
    "format for tktsetup errors",
    @   color: red;
    @   font-weight: bold;
  },





  { "p.thmainError",
    "format for th script errors",
    @   color: red;
    @   font-weight: bold;
  },
  { "span.thTrace",
    "format for th script trace messages",







>
>
>
>
>







708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
    @   color: red;
  },
  { "p.tktsetupError",
    "format for tktsetup errors",
    @   color: red;
    @   font-weight: bold;
  },
  { "p.xfersetupError",
    "format for xfersetup errors",
    @   color: red;
    @   font-weight: bold;
  },
  { "p.thmainError",
    "format for th script errors",
    @   color: red;
    @   font-weight: bold;
  },
  { "span.thTrace",
    "format for th script trace messages",
804
805
806
807
808
809
810































811
812
813
814
815
816
817
    @   color: red;
  },
  { "ul.filelist",
    "List of files in a timeline",
    @   margin-top: 3px;
    @   line-height: 100%;
  },































  { 0,
    0,
    0
  }
};

/*







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







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
    @   color: red;
  },
  { "ul.filelist",
    "List of files in a timeline",
    @   margin-top: 3px;
    @   line-height: 100%;
  },
  { "div.sbsdiff",
    "side-by-side diff display",
    @   font-family: monospace;
    @   font-size: smaller;
    @   white-space: pre;
  },
  { "div.udiff",
    "context diff display",
    @   font-family: monospace;
    @   white-space: pre;
  },
  { "span.diffchng",
    "changes in a diff",
    @   background-color: #c0c0ff;
  },
  { "span.diffadd",
    "added code in a diff",
    @   background-color: #c0ffc0;
  },
  { "span.diffrm",
    "deleted in a diff",
    @   background-color: #ffc8c8;
  },
  { "span.diffhr",
    "suppressed lines in a diff",
    @   color: #0000ff;
  },
  { "span.diffln",
    "line nubmers in a diff",
    @   color: #a0a0a0;
  },
  { 0,
    0,
    0
  }
};

/*
Changes to src/tar.c.
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** 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.
*/







|







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  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.
*/
Changes to src/th_main.c.
567
568
569
570
571
572
573
574
575
576
577
578
** COMMAND: test-th-render
*/
void test_th_render(void){
  Blob in;
  if( g.argc<3 ){
    usage("FILE");
  }
  db_open_config(0); /* Needed for "tcl" setting. */
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
}







|




567
568
569
570
571
572
573
574
575
576
577
578
** COMMAND: test-th-render
*/
void test_th_render(void){
  Blob in;
  if( g.argc<3 ){
    usage("FILE");
  }
  db_open_config(0); /* Needed for global "tcl" setting. */
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
}
Changes to src/timeline.c.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
** This file contains code to implement the timeline web page
**
*/
#include <string.h>
#include <time.h>
#include "config.h"
#include "timeline.h"
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h"
#endif

/*
** 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;







<
<
<







18
19
20
21
22
23
24



25
26
27
28
29
30
31
** This file contains code to implement the timeline web page
**
*/
#include <string.h>
#include <time.h>
#include "config.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;
362
363
364
365
366
367
368





369
370
371
372
373
374
375
      char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
                            g.zTop, zUser, zDate);
      @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
      fossil_free(zLink);
    }else{
      @ (user: %h(zUser)%s(zTagList?",":"\051")
    }






    /* Generate the "tags: TAGLIST" at the end of the comment, together
    ** with hyperlinks to the tag list.
    */
    if( zTagList ){
      if( g.perm.History ){
        int i;







>
>
>
>
>







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
      char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
                            g.zTop, zUser, zDate);
      @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
      fossil_free(zLink);
    }else{
      @ (user: %h(zUser)%s(zTagList?",":"\051")
    }

    /* Generate a "detail" link for tags. */
    if( zType[0]=='g' && g.perm.History ){
      @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>]
    }

    /* Generate the "tags: TAGLIST" at the end of the comment, together
    ** with hyperlinks to the tag list.
    */
    if( zTagList ){
      if( g.perm.History ){
        int i;
391
392
393
394
395
396
397

398
399
400
401
402
403
404
        }
        @ tags: %s(blob_str(&links)))
        blob_reset(&links);
      }else{
        @ tags: %h(zTagList))
      }
    }


    /* Generate extra hyperlinks at the end of the comment */
    if( xExtra ){
      xExtra(rid);
    }

    /* Generate the file-change list if requested */







>







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
        }
        @ tags: %s(blob_str(&links)))
        blob_reset(&links);
      }else{
        @ tags: %h(zTagList))
      }
    }


    /* Generate extra hyperlinks at the end of the comment */
    if( xExtra ){
      xExtra(rid);
    }

    /* Generate the file-change list if requested */
Changes to src/tkt.c.
240
241
242
243
244
245
246










247
248
249
250
251
252
253
*/
void ticket_init(void){
  const char *zConfig;
  Th_FossilInit();
  zConfig = ticket_common_code();
  Th_Eval(g.interp, 0, zConfig, -1);
}











/*
** Recreate the ticket table.
*/
void ticket_create_table(int separateConnection){
  const char *zSql;








>
>
>
>
>
>
>
>
>
>







240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
*/
void ticket_init(void){
  const char *zConfig;
  Th_FossilInit();
  zConfig = ticket_common_code();
  Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Create the subscript interpreter and load the "change" code.
*/
int ticket_change(void){
  const char *zConfig;
  Th_FossilInit();
  zConfig = ticket_change_code();
  return Th_Eval(g.interp, 0, zConfig, -1);
}

/*
** Recreate the ticket table.
*/
void ticket_create_table(int separateConnection){
  const char *zSql;

485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
      fossil_panic("trouble committing ticket: %s", g.zErrMsg);
    }
    manifest_crosslink_begin();
    manifest_crosslink(rid, &tktchng);
    assert( blob_is_reset(&tktchng) );
    manifest_crosslink_end();
  }
  return TH_RETURN;
}


/*
** WEBPAGE: tktnew
** WEBPAGE: debug_tktnew
**







|







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
      fossil_panic("trouble committing ticket: %s", g.zErrMsg);
    }
    manifest_crosslink_begin();
    manifest_crosslink(rid, &tktchng);
    assert( blob_is_reset(&tktchng) );
    manifest_crosslink_end();
  }
  return ticket_change();
}


/*
** WEBPAGE: tktnew
** WEBPAGE: debug_tktnew
**
Changes to src/tktsetup.c.
36
37
38
39
40
41
42


43
44
45
46
47
48
49
  @ <table border="0" cellspacing="20">
  setup_menu_entry("Table", "tktsetup_tab",
    "Specify the schema of the  \"ticket\" table in the database.");
  setup_menu_entry("Timeline", "tktsetup_timeline",
    "How to display ticket status in the timeline");
  setup_menu_entry("Common", "tktsetup_com",
    "Common TH1 code run before all ticket processing.");


  setup_menu_entry("New Ticket Page", "tktsetup_newpage",
    "HTML with embedded TH1 code for the \"new ticket\" webpage.");
  setup_menu_entry("View Ticket Page", "tktsetup_viewpage",
    "HTML with embedded TH1 code for the \"view ticket\" webpage.");
  setup_menu_entry("Edit Ticket Page", "tktsetup_editpage",
    "HTML with embedded TH1 code for the \"edit ticket\" webpage.");
  setup_menu_entry("Report List Page", "tktsetup_reportlist",







>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  @ <table border="0" cellspacing="20">
  setup_menu_entry("Table", "tktsetup_tab",
    "Specify the schema of the  \"ticket\" table in the database.");
  setup_menu_entry("Timeline", "tktsetup_timeline",
    "How to display ticket status in the timeline");
  setup_menu_entry("Common", "tktsetup_com",
    "Common TH1 code run before all ticket processing.");
  setup_menu_entry("Change", "tktsetup_change",
    "The TH1 code run after a ticket is edited or created.");
  setup_menu_entry("New Ticket Page", "tktsetup_newpage",
    "HTML with embedded TH1 code for the \"new ticket\" webpage.");
  setup_menu_entry("View Ticket Page", "tktsetup_viewpage",
    "HTML with embedded TH1 code for the \"view ticket\" webpage.");
  setup_menu_entry("Edit Ticket Page", "tktsetup_editpage",
    "HTML with embedded TH1 code for the \"edit ticket\" webpage.");
  setup_menu_entry("Report List Page", "tktsetup_reportlist",
236
237
238
239
240
241
242






























243
244
245
246
247
248
249
  ;
  tktsetup_generic(
    "Ticket Common Script",
    "ticket-common",
    zDefaultTicketCommon,
    zDesc,
    0,






























    0,
    30
  );
}

static const char zDefaultNew[] =
@ <th1>







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







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
  ;
  tktsetup_generic(
    "Ticket Common Script",
    "ticket-common",
    zDefaultTicketCommon,
    zDesc,
    0,
    0,
    30
  );
}

static const char zDefaultTicketChange[] =
@ return
;

/*
** Return the ticket change code.
*/
const char *ticket_change_code(void){
  return db_get("ticket-change", (char*)zDefaultTicketChange);
}

/*
** WEBPAGE: tktsetup_change
*/
void tktsetup_change_page(void){
  static const char zDesc[] =
  @ Enter TH1 script that runs after processing the ticket editing
  @ and creation pages.
  ;
  tktsetup_generic(
    "Ticket Change Script",
    "ticket-change",
    zDefaultTicketChange,
    zDesc,
    0,
    0,
    30
  );
}

static const char zDefaultNew[] =
@ <th1>
Changes to src/undo.c.
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
  undo_all_filesystem(0);
}

/*
** COMMAND: undo
** COMMAND: redo*
**
** Usage: %fossil undo ?--explain? ?FILENAME...?
**    or: %fossil redo ?--explain? ?FILENAME...?
**
** Undo the changes to the working checkout caused by the most recent
** of the following operations:
**
**    (1) fossil update             (5) fossil stash apply
**    (2) fossil merge              (6) fossil stash drop
**    (3) fossil revert             (7) fossil stash goto
**    (4) fossil stash pop
**
** If FILENAME is specified then restore the content of the named
** file(s) but otherwise leave the update or merge or revert in effect. 
** The redo command undoes the effect of the most recent undo.
**
** If the --explain option is present, no changes are made and instead
** the undo or redo command explains what actions the undo or redo would
** have done had the --explain been omitted.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.





*/
void undo_cmd(void){
  int isRedo = g.argv[1][0]=='r';
  int undo_available;
  int explainFlag = find_option("explain", 0, 0)!=0;
  const char *zCmd = isRedo ? "redo" : "undo";
  db_must_be_within_tree();







|
|



















>
>
>
>
>







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
  undo_all_filesystem(0);
}

/*
** COMMAND: undo
** COMMAND: redo*
**
** Usage: %fossil undo ?OPTIONS? ?FILENAME...?
**    or: %fossil redo ?OPTIONS? ?FILENAME...?
**
** Undo the changes to the working checkout caused by the most recent
** of the following operations:
**
**    (1) fossil update             (5) fossil stash apply
**    (2) fossil merge              (6) fossil stash drop
**    (3) fossil revert             (7) fossil stash goto
**    (4) fossil stash pop
**
** If FILENAME is specified then restore the content of the named
** file(s) but otherwise leave the update or merge or revert in effect. 
** The redo command undoes the effect of the most recent undo.
**
** If the --explain option is present, no changes are made and instead
** the undo or redo command explains what actions the undo or redo would
** have done had the --explain been omitted.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
**
** Options:
**   --explain    do not make changes but show what would be done
**
** See also: commit, status
*/
void undo_cmd(void){
  int isRedo = g.argv[1][0]=='r';
  int undo_available;
  int explainFlag = find_option("explain", 0, 0)!=0;
  const char *zCmd = isRedo ? "redo" : "undo";
  db_must_be_within_tree();
Changes to src/update.c.
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  g.argv = savedArgv;
  return internalConflictCnt;
}

/*
** COMMAND: update
**
** Usage: %fossil update ?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







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  g.argv = savedArgv;
  return internalConflictCnt;
}

/*
** 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
81
82
83
84
85
86
87








88
89
90
91
92
93
94
**
** The -n or --nochange 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.








*/
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 nochangeFlag;     /* -n or --nochange.  Do a dry run */







>
>
>
>
>
>
>
>







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
**
** The -n or --nochange 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:
**   --debug          print debug information on stdout
**   --latest         acceptable in place of VERSION, update to latest version
**   -n|--nochange    do not perform changes but show what would be done
**   -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 nochangeFlag;     /* -n or --nochange.  Do a dry run */
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
  );

  /*
  ** Add islink information
  */
  db_multi_exec(
    "UPDATE fv SET"
    " islinkv=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnt),0),"

    " islinkt=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnt),0)",

    vid, tid
  );


  if( debugFlag ){
    db_prepare(&q,
       "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe, islinkv, islinkt FROM fv"

    );
    while( db_step(&q)==SQLITE_ROW ){
       fossil_print("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d islinkv=%d  islinkt=%d\n",

          db_column_int(&q, 0),
          db_column_int(&q, 4),
          db_column_int(&q, 5),
          db_column_int(&q, 3),
          db_column_int(&q, 6),
          db_column_int(&q, 7),
          db_column_int(&q, 8));







|
>
|
>






|
>


|
>







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
  );

  /*
  ** Add islink information
  */
  db_multi_exec(
    "UPDATE fv SET"
    " islinkv=coalesce((SELECT islink FROM vfile"
                       " WHERE vid=%d AND pathname=fnt),0),"
    " islinkt=coalesce((SELECT islink FROM vfile"
                       " WHERE vid=%d AND pathname=fnt),0)",
    vid, tid
  );


  if( debugFlag ){
    db_prepare(&q,
       "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe,"
       "       islinkv, islinkt FROM fv"
    );
    while( db_step(&q)==SQLITE_ROW ){
       fossil_print("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d"
                    " islinkv=%d  islinkt=%d\n",
          db_column_int(&q, 0),
          db_column_int(&q, 4),
          db_column_int(&q, 5),
          db_column_int(&q, 3),
          db_column_int(&q, 6),
          db_column_int(&q, 7),
          db_column_int(&q, 8));
323
324
325
326
327
328
329
330

331
332
333
334
335
336
337
  }

  /*
  ** Alter the content of the checkout so that it conforms with the
  ** target
  */
  db_prepare(&q, 
    "SELECT fn, idv, ridv, idt, ridt, chnged, fnt, isexe, islinkv, islinkt FROM fv ORDER BY 1"

  );
  db_prepare(&mtimeXfer,
    "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)"
    " WHERE id=:idt"
  );
  assert( g.zLocalRoot!=0 );
  assert( strlen(g.zLocalRoot)>1 );







|
>







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  }

  /*
  ** Alter the content of the checkout so that it conforms with the
  ** target
  */
  db_prepare(&q, 
    "SELECT fn, idv, ridv, idt, ridt, chnged, fnt,"
    "       isexe, islinkv, islinkt FROM fv ORDER BY 1"
  );
  db_prepare(&mtimeXfer,
    "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)"
    " WHERE id=:idt"
  );
  assert( g.zLocalRoot!=0 );
  assert( strlen(g.zLocalRoot)>1 );
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  */
  if( !nochangeFlag ){
    if( nConflict ){
      if( internalUpdate ){
        internalConflictCnt = nConflict;
        nConflict = 0;
      }else{
        fossil_print("WARNING: %d merge conflicts", nConflict);
      }
    }
    if( nOverwrite ){
      fossil_warning("WARNING: %d unmanaged files were overwritten",
                     nOverwrite);
    }
  }







|







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  */
  if( !nochangeFlag ){
    if( nConflict ){
      if( internalUpdate ){
        internalConflictCnt = nConflict;
        nConflict = 0;
      }else{
        fossil_warning("WARNING: %d merge conflicts", nConflict);
      }
    }
    if( nOverwrite ){
      fossil_warning("WARNING: %d unmanaged files were overwritten",
                     nOverwrite);
    }
  }
608
609
610
611
612
613
614





615
616
617
618
619
620
621
** the version associated with baseline REVISION if the -r flag
** appears.
**
** Revert all files if no file name is provided.
**
** If a file is reverted accidently, it can be restored using
** the "fossil undo" command.





*/
void revert_cmd(void){
  const char *zFile;
  const char *zRevision;
  Blob record;
  int i;
  int errCode;







>
>
>
>
>







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
** the version associated with baseline REVISION if the -r flag
** appears.
**
** Revert all files if no file name is provided.
**
** If a file is reverted accidently, it can be restored using
** the "fossil undo" command.
**
** Options:
**   -r REVISION    revert given FILE(s) back to given REVISION
**
** See also: redo, undo, update
*/
void revert_cmd(void){
  const char *zFile;
  const char *zRevision;
  Blob record;
  int i;
  int errCode;
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
  }
  while( db_step(&q)==SQLITE_ROW ){
    int isExe = 0;
    int isLink = 0;
    char *zFull;
    zFile = db_column_text(&q, 0);
    zFull = mprintf("%/%/", g.zLocalRoot, zFile);
    errCode = historical_version_of_file(zRevision, zFile, &record, &isLink, &isExe,2);

    if( errCode==2 ){
      if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
        fossil_print("UNMANAGE: %s\n", zFile);
      }else{
        undo_save(zFile);
        file_delete(zFull);
        fossil_print("DELETE: %s\n", zFile);







|
>







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  }
  while( db_step(&q)==SQLITE_ROW ){
    int isExe = 0;
    int isLink = 0;
    char *zFull;
    zFile = db_column_text(&q, 0);
    zFull = mprintf("%/%/", g.zLocalRoot, zFile);
    errCode = historical_version_of_file(zRevision, zFile, &record,
                                         &isLink, &isExe,2);
    if( errCode==2 ){
      if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
        fossil_print("UNMANAGE: %s\n", zFile);
      }else{
        undo_save(zFile);
        file_delete(zFull);
        fossil_print("DELETE: %s\n", zFile);
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
        blob_write_to_file(&record, zFull);
      }
      file_wd_setexe(zFull, isExe);
      fossil_print("REVERTED: %s\n", zFile);
      mtime = file_wd_mtime(zFull);
      db_multi_exec(
         "UPDATE vfile"
         "   SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid,"
         "       pathname=coalesce(origname,pathname), origname=NULL"     
         " WHERE pathname=%Q",
         mtime, isExe, isLink, zFile
      );
    }
    blob_reset(&record);
    free(zFull);
  }
  db_finalize(&q);
  undo_finish();
  db_end_transaction(0);
}







|












709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
        blob_write_to_file(&record, zFull);
      }
      file_wd_setexe(zFull, isExe);
      fossil_print("REVERTED: %s\n", zFile);
      mtime = file_wd_mtime(zFull);
      db_multi_exec(
         "UPDATE vfile"
         "   SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid,"
         "       pathname=coalesce(origname,pathname), origname=NULL"     
         " WHERE pathname=%Q",
         mtime, isExe, isLink, zFile
      );
    }
    blob_reset(&record);
    free(zFull);
  }
  db_finalize(&q);
  undo_finish();
  db_end_transaction(0);
}
Changes to src/url.c.
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
*/
void url_enable_proxy(const char *zMsg){
  const char *zProxy;
  zProxy = zProxyOpt;
  if( zProxy==0 ){
    zProxy = db_get("proxy", 0);
    if( zProxy==0 || zProxy[0]==0 || is_truth(zProxy) ){
      zProxy = getenv("http_proxy");
    }
  }
  if( zProxy && zProxy[0] && !is_false(zProxy) ){
    char *zOriginalUrl = g.urlCanonical;
    char *zOriginalHost = g.urlHostname;
    char *zOriginalUser = g.urlUser;
    char *zOriginalPasswd = g.urlPasswd;







|







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
*/
void url_enable_proxy(const char *zMsg){
  const char *zProxy;
  zProxy = zProxyOpt;
  if( zProxy==0 ){
    zProxy = db_get("proxy", 0);
    if( zProxy==0 || zProxy[0]==0 || is_truth(zProxy) ){
      zProxy = fossil_getenv("http_proxy");
    }
  }
  if( zProxy && zProxy[0] && !is_false(zProxy) ){
    char *zOriginalUrl = g.urlCanonical;
    char *zOriginalHost = g.urlHostname;
    char *zOriginalUser = g.urlUser;
    char *zOriginalPasswd = g.urlPasswd;
Changes to src/user.c.
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    }
  }

  if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;

  if( attempt_user(db_get("default-user", 0)) ) return;

  if( attempt_user(getenv("USER")) ) return;

  db_prepare(&s,
    "SELECT uid, login FROM user"
    " WHERE login NOT IN ('anonymous','nobody','reader','developer')"
  );
  if( db_step(&s)==SQLITE_ROW ){
    g.userUid = db_column_int(&s, 0);







|







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    }
  }

  if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;

  if( attempt_user(db_get("default-user", 0)) ) return;

  if( attempt_user(fossil_getenv("USER")) ) return;

  db_prepare(&s,
    "SELECT uid, login FROM user"
    " WHERE login NOT IN ('anonymous','nobody','reader','developer')"
  );
  if( db_step(&s)==SQLITE_ROW ){
    g.userUid = db_column_int(&s, 0);
Changes to src/vfile.c.
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
      if( notFileIsFatal ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }
    if( origSize!=currentSize ){
      if( chnged==0 ){
        /* A file size change is definitive - the file has changed.  No
        ** need to check the mtime or sha1sum */
        chnged = 1;
      }
    }else if( chnged==1 && rid!=0 && !isDeleted ){
      /* File is believed to have changed but it is the same size.
      ** Double check that it really has changed by looking at content. */







|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
      if( notFileIsFatal ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }
    if( origSize!=currentSize ){
      if( chnged!=1 ){
        /* A file size change is definitive - the file has changed.  No
        ** need to check the mtime or sha1sum */
        chnged = 1;
      }
    }else if( chnged==1 && rid!=0 && !isDeleted ){
      /* File is believed to have changed but it is the same size.
      ** Double check that it really has changed by looking at content. */
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348











349
350
351
352
353
354
355
  db_finalize(&q);
  db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
}

/*
** Check to see if the directory named in zPath is the top of a checkout.
** In other words, check to see if directory pPath contains a file named
** "_FOSSIL_" or ".fos".  Return true or false.
*/
int vfile_top_of_checkout(const char *zPath){
  char *zFile;
  int fileFound = 0;

  zFile = mprintf("%s/_FOSSIL_", zPath);
  fileFound = file_size(zFile)>=1024;
  fossil_free(zFile);











  if( !fileFound ){
    zFile = mprintf("%s/.fos", zPath);
    fileFound = file_size(zFile)>=1024;
    fossil_free(zFile);
  }
  return fileFound;
}







|








>
>
>
>
>
>
>
>
>
>
>







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
  db_finalize(&q);
  db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
}

/*
** Check to see if the directory named in zPath is the top of a checkout.
** In other words, check to see if directory pPath contains a file named
** "_FOSSIL_" or ".fslckout".  Return true or false.
*/
int vfile_top_of_checkout(const char *zPath){
  char *zFile;
  int fileFound = 0;

  zFile = mprintf("%s/_FOSSIL_", zPath);
  fileFound = file_size(zFile)>=1024;
  fossil_free(zFile);
  if( !fileFound ){
    zFile = mprintf("%s/.fslckout", zPath);
    fileFound = file_size(zFile)>=1024;
    fossil_free(zFile);
  }

  /* Check for ".fos" for legacy support.  But the use of ".fos" as the
  ** per-checkout database name is deprecated.  At some point, all support
  ** for ".fos" will end and this code should be removed.  This comment
  ** added on 2012-02-04.
  */
  if( !fileFound ){
    zFile = mprintf("%s/.fos", zPath);
    fileFound = file_size(zFile)>=1024;
    fossil_free(zFile);
  }
  return fileFound;
}
Changes to src/wiki.c.
591
592
593
594
595
596
597

598
599
600
601
602
603
604
*/
void wdiff_page(void){
  char *zTitle;
  int rid1, rid2;
  const char *zPageName;
  Manifest *pW1, *pW2 = 0;
  Blob w1, w2, d;


  login_check_credentials();
  rid1 = atoi(PD("a","0"));
  if( !g.perm.History ){ login_needed(); return; }
  if( rid1==0 ) fossil_redirect_home();
  rid2 = atoi(PD("b","0"));
  zPageName = PD("name","");







>







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
*/
void wdiff_page(void){
  char *zTitle;
  int rid1, rid2;
  const char *zPageName;
  Manifest *pW1, *pW2 = 0;
  Blob w1, w2, d;
  int diffFlags;

  login_check_credentials();
  rid1 = atoi(PD("a","0"));
  if( !g.perm.History ){ login_needed(); return; }
  if( rid1==0 ) fossil_redirect_home();
  rid2 = atoi(PD("b","0"));
  zPageName = PD("name","");
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
  if( pW1==0 ) fossil_redirect_home();
  blob_init(&w1, pW1->zWiki, -1);
  blob_zero(&w2);
  if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
    blob_init(&w2, pW2->zWiki, -1);
  }
  blob_zero(&d);

  text_diff(&w2, &w1, &d, 5 | DIFF_IGNORE_EOLWS);
  @ <pre>
  @ %h(blob_str(&d))
  @ </pre>
  manifest_destroy(pW1);
  manifest_destroy(pW2);
  style_footer();
}

/*
** prepare()s pStmt with a query requesting:







>
|
|
|
|







620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
  if( pW1==0 ) fossil_redirect_home();
  blob_init(&w1, pW1->zWiki, -1);
  blob_zero(&w2);
  if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
    blob_init(&w2, pW2->zWiki, -1);
  }
  blob_zero(&d);
  diffFlags = construct_diff_flags(1,0);
  text_diff(&w2, &w1, &d, diffFlags | DIFF_HTML | DIFF_LINENO);
  @ <div class="udiff">
  @ %s(blob_str(&d))
  @ </div>
  manifest_destroy(pW1);
  manifest_destroy(pW2);
  style_footer();
}

/*
** prepare()s pStmt with a query requesting:
Changes to src/xfer.c.
125
126
127
128
129
130
131

132
133
134
135

136
137
138
139
140
141
142
    return;
  }
  blob_zero(&content);
  blob_zero(&hash);
  blob_extract(pXfer->pIn, n, &content);
  if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
    /* Ignore files that have been shunned */

    return;
  }
  if( isPriv && !g.perm.Private ){
    /* Do not accept private files if not authorized */

    return;
  }
  if( cloneFlag ){
    if( pXfer->nToken==4 ){
      srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
      pXfer->nDeltaRcvd++;
    }else{







>




>







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    return;
  }
  blob_zero(&content);
  blob_zero(&hash);
  blob_extract(pXfer->pIn, n, &content);
  if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
    /* Ignore files that have been shunned */
    blob_reset(&content);
    return;
  }
  if( isPriv && !g.perm.Private ){
    /* Do not accept private files if not authorized */
    blob_reset(&content);
    return;
  }
  if( cloneFlag ){
    if( pXfer->nToken==4 ){
      srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
      pXfer->nDeltaRcvd++;
    }else{
154
155
156
157
158
159
160


161
162
163
164
165
166
167
    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);


      return;
    }
    pXfer->nDeltaRcvd++;
    blob_delta_apply(&src, &content, &next);
    blob_reset(&src);
    blob_reset(&content);
    content = next;







>
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    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;
233
234
235
236
237
238
239

240
241
242
243
244
245
246
    /* Do not accept private files if not authorized */
    return;
  }
  blob_zero(&content);
  blob_extract(pXfer->pIn, szC, &content);
  if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
    /* Ignore files that have been shunned */

    return;
  }
  if( pXfer->nToken==5 ){
    srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
    pXfer->nDeltaRcvd++;
  }else{
    srcid = 0;







>







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    /* Do not accept private files if not authorized */
    return;
  }
  blob_zero(&content);
  blob_extract(pXfer->pIn, szC, &content);
  if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
    /* Ignore files that have been shunned */
    blob_reset(&content);
    return;
  }
  if( pXfer->nToken==5 ){
    srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
    pXfer->nDeltaRcvd++;
  }else{
    srcid = 0;
418
419
420
421
422
423
424

425
426
427
428
429
430
431
      if( isPriv ) blob_append(pXfer->pOut, "private\n", -1);
      blob_appendf(pXfer->pOut, "file %b %d\n", pUuid, size);
      blob_append(pXfer->pOut, blob_buffer(&content), size);
      pXfer->nFileSent++;
    }else{
      pXfer->nDeltaSent++;
    }

  }
  remote_has(rid);
  blob_reset(&uuid);
#if 0
  if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
    blob_appendf(pXfer->pOut, "\n", 1);
  }







>







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
      if( isPriv ) blob_append(pXfer->pOut, "private\n", -1);
      blob_appendf(pXfer->pOut, "file %b %d\n", pUuid, size);
      blob_append(pXfer->pOut, blob_buffer(&content), size);
      pXfer->nFileSent++;
    }else{
      pXfer->nDeltaSent++;
    }
    blob_reset(&content);
  }
  remote_has(rid);
  blob_reset(&uuid);
#if 0
  if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
    blob_appendf(pXfer->pOut, "\n", 1);
  }
788
789
790
791
792
793
794

























795
796
797
798
799
800
801
** Called when there is an attempt to transfer private content to and
** from a server without authorization.
*/
static void server_private_xfer_not_authorized(void){
  @ error not\sauthorized\sto\ssync\sprivate\scontent
}



























/*
** If this variable is set, disable login checks.  Used for debugging
** only.
*/
static int disableLogin = 0;








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







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
** Called when there is an attempt to transfer private content to and
** from a server without authorization.
*/
static void server_private_xfer_not_authorized(void){
  @ error not\sauthorized\sto\ssync\sprivate\scontent
}

/*
** Run the specified TH1 script, if any, and returns the return code or TH_OK
** when there is no script.
*/
static int run_script(const char *zScript){
  if( !zScript ){
    return TH_OK; /* No script, return success. */
  }
  Th_FossilInit(); /* Make sure TH1 is ready. */
  return Th_Eval(g.interp, 0, zScript, -1);
}

/*
** Run the pre-transfer TH1 script, if any, and returns the return code.
*/
static int run_common_script(void){
  return run_script(db_get("xfer-common-script", 0));
}

/*
** Run the post-push TH1 script, if any, and returns the return code.
*/
static int run_push_script(void){
  return run_script(db_get("xfer-push-script", 0));
}

/*
** If this variable is set, disable login checks.  Used for debugging
** only.
*/
static int disableLogin = 0;

845
846
847
848
849
850
851





852
853
854
855
856
857
858
  g.xferPanic = 1;

  db_begin_transaction();
  db_multi_exec(
     "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
  );
  manifest_crosslink_begin();





  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







>
>
>
>
>







876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
  g.xferPanic = 1;

  db_begin_transaction();
  db_multi_exec(
     "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
  );
  manifest_crosslink_begin();
  if( run_common_script()==TH_ERROR ){
    cgi_reset_content();
    @ error common\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
    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
1158
1159
1160
1161
1162
1163
1164





1165
1166
1167
1168
1169
1170
1171
    {
      cgi_reset_content();
      @ error bad\scommand:\s%F(blob_str(&xfer.line))
    }
    blobarray_reset(xfer.aToken, xfer.nToken);
  }
  if( isPush ){





    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 respository.  This will
    ** cause the client to create phantoms for all artifacts, which will







>
>
>
>
>







1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
    {
      cgi_reset_content();
      @ error bad\scommand:\s%F(blob_str(&xfer.line))
    }
    blobarray_reset(xfer.aToken, xfer.nToken);
  }
  if( isPush ){
    if( run_push_script()==TH_ERROR ){
      cgi_reset_content();
      @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
      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 respository.  This will
    ** cause the client to create phantoms for all artifacts, which will
Added src/xfersetup.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
/*
** Copyright (c) 2007 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/
**
*******************************************************************************
**
** This file contains code to implement the transfer configuration
** setup screens.
*/
#include "config.h"
#include "xfersetup.h"
#include <assert.h>

/*
** Main sub-menu for configuring the transfer system.
** WEBPAGE: xfersetup
*/
void xfersetup_page(void){
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }

  style_header("Transfer Setup");
  @ <table border="0" cellspacing="20">
  setup_menu_entry("Common", "xfersetup_com",
    "Common TH1 code run before all transfer request processing.");
  setup_menu_entry("Push", "xfersetup_push",
    "Specific TH1 code to run after \"push\" transfer requests.");
  @ </table>
  style_footer();
}

/*
** Common implementation for the transfer setup editor pages.
*/
static void xfersetup_generic(
  const char *zTitle,           /* Page title */
  const char *zDbField,         /* Configuration field being edited */
  const char *zDfltValue,       /* Default text value */
  const char *zDesc,            /* Description of this field */
  char *(*xText)(const char*),  /* Validitity test or NULL */
  void (*xRebuild)(void),       /* Run after successulf update */
  int height                    /* Height of the edit box */
){
  const char *z;
  int isSubmit;

  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  if( P("setup") ){
    cgi_redirect("xfersetup");
  }
  isSubmit = P("submit")!=0;
  z = P("x");
  if( z==0 ){
    z = db_get(zDbField, (char*)zDfltValue);
  }
  style_header("Edit %s", zTitle);
  if( P("clear")!=0 ){
    login_verify_csrf_secret();
    db_unset(zDbField, 0);
    if( xRebuild ) xRebuild();
    z = zDfltValue;
  }else if( isSubmit ){
    char *zErr = 0;
    login_verify_csrf_secret();
    if( xText && (zErr = xText(z))!=0 ){
      @ <p class="xfersetupError">ERROR: %h(zErr)</p>
    }else{
      db_set(zDbField, z, 0);
      if( xRebuild ) xRebuild();
      cgi_redirect("xfersetup");
    }
  }
  @ <form action="%s(g.zTop)/%s(g.zPath)" method="post"><div>
  login_insert_csrf_secret();
  @ <p>%s(zDesc)</p>
  @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
  @ <blockquote><p>
  @ <input type="submit" name="submit" value="Apply Changes" />
  @ <input type="submit" name="clear" value="Revert To Default" />
  @ <input type="submit" name="setup" value="Cancel" />
  @ </p></blockquote>
  @ </div></form>
  @ <hr />
  if ( zDfltValue ){
    @ <h2>Default %s(zTitle)</h2>
    @ <blockquote><pre>
    @ %h(zDfltValue)
    @ </pre></blockquote>
  }
  style_footer();
}

static const char *zDefaultXferCommon = 0;

/*
** WEBPAGE: xfersetup_com
*/
void xfersetup_com_page(void){
  static const char zDesc[] =
  @ Enter TH1 script that initializes variables prior to running
  @ any of the transfer request scripts.
  ;
  xfersetup_generic(
    "Transfer Common Script",
    "xfer-common-script",
    zDefaultXferCommon,
    zDesc,
    0,
    0,
    30
  );
}

static const char *zDefaultXferPush = 0;

/*
** WEBPAGE: xfersetup_push
*/
void xfersetup_push_page(void){
  static const char zDesc[] =
  @ Enter TH1 script that runs after processing "push" transfer requests.
  ;
  xfersetup_generic(
    "Transfer Push Script",
    "xfer-push-script",
    zDefaultXferPush,
    zDesc,
    0,
    0,
    30
  );
}
Changes to src/zip.c.
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  blob_reset(&filename);
  zip_close(pZip);
}

/*
** COMMAND: zip*
**
** Usage: %fossil zip VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** Generate a ZIP archive for a specified version.  If the --name option is
** used, it argument becomes the name of the top-level directory in the
** resulting ZIP archive.  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.
*/







|







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  blob_reset(&filename);
  zip_close(pZip);
}

/*
** COMMAND: zip*
**
** Usage: %fossil zip VERSION OUTPUTFILE [--name DIRECTORYNAME] [-R|--repository REPO]
**
** Generate a ZIP archive for a specified version.  If the --name option is
** used, it argument becomes the name of the top-level directory in the
** resulting ZIP archive.  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.
*/
Added test/diff-test-1.wiki.






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<title>Graph Test One</title>

This page contains list of URLs of interesting diffs.
Click on all URLs, one by one, to verify 
the correct operation of the diff logic.

  *  <a href="../../../info/030035345c#chunk59" target="testwindow">
     Multiple edits on a single line.</a>  This is an SQLite version
     update diff.  It is a large diff and contains many other interesting
     features.  Scan the whole diff.
  *  <a href="../../../fdiff?v1=6da016415dc52d61&v2=af6df3466e3c4a88"
     target="testwindow">Tricky alignment and multiple edits per line</a>.
  *  <a href="../../../fdiff?v1=7108d4748b111d23&v2=2303a98525b39d19#chunk3"
     target="testwindow">Add a column to a table</a>

External:

  *  <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
     Code indentation change.</a>
Changes to test/release-checklist.wiki.
11
12
13
14
15
16
17





18
19
20
21
22
23
24
Verify that there are no errors.

<li><p>
Click on each of the links in in the
[./graph-test-1.wiki] document and verify that all graphs are
rendered correctly.






<li><p>
Verify correct name-change tracking behavior (no net changes) for:
<blockquote><b>
fossil test-name-changes --debug  b120bc8b262ac 374920b20944b
</b></blockquote>

<li><p>







>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Verify that there are no errors.

<li><p>
Click on each of the links in in the
[./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>
Verify correct name-change tracking behavior (no net changes) for:
<blockquote><b>
fossil test-name-changes --debug  b120bc8b262ac 374920b20944b
</b></blockquote>

<li><p>
Changes to win/Makefile.PellesCGMake.


1

2
3
4
5
6
7
8
9
10
11


# DO NOT EDIT

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.
#
# HowTo
# -----
#
# This is a Makefile to compile fossil with PellesC from
#  http://www.smorgasbordet.com/pellesc/index.htm
>
>
|
>


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#
##############################################################################
# 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.
#
# HowTo
# -----
#
# This is a Makefile to compile fossil with PellesC from
#  http://www.smorgasbordet.com/pellesc/index.htm
Changes to win/Makefile.dmc.


1

2
3
4
5

6
7
8
9
10
11
12


# DO NOT EDIT

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.

B      = ..
SRCDIR = $B\src
OBJDIR = .
O      = .obj
E      = .exe


>
>
|
>


|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
##############################################################################
# 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 = .
O      = .obj
E      = .exe


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
CFLAGS = -o
BCC    = $(DMDIR)\bin\dmc $(CFLAGS)
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32

SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.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_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.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)\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_diff$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$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 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_diff json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c







|

|

















|







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
CFLAGS = -o
BCC    = $(DMDIR)\bin\dmc $(CFLAGS)
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32

SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.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_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.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)\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_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$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 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_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
90
91
92
93
94
95
96

97

98
99
100
101
102
103
104

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_diff$O : $(SRCDIR)\json_detail.h

$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h







>

>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_finfo$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
346
347
348
349
350
351
352






353
354
355
356
357
358






359
360
361
362
363
364
365
	+translate$E $** > $@

$(OBJDIR)\json_branch$O : json_branch_.c json_branch.h
	$(TCC) -o$@ -c json_branch_.c

json_branch_.c : $(SRCDIR)\json_branch.c
	+translate$E $** > $@







$(OBJDIR)\json_diff$O : json_diff_.c json_diff.h
	$(TCC) -o$@ -c json_diff_.c

json_diff_.c : $(SRCDIR)\json_diff.c
	+translate$E $** > $@







$(OBJDIR)\json_login$O : json_login_.c json_login.h
	$(TCC) -o$@ -c json_login_.c

json_login_.c : $(SRCDIR)\json_login.c
	+translate$E $** > $@








>
>
>
>
>
>






>
>
>
>
>
>







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
	+translate$E $** > $@

$(OBJDIR)\json_branch$O : json_branch_.c json_branch.h
	$(TCC) -o$@ -c json_branch_.c

json_branch_.c : $(SRCDIR)\json_branch.c
	+translate$E $** > $@

$(OBJDIR)\json_config$O : json_config_.c json_config.h
	$(TCC) -o$@ -c json_config_.c

json_config_.c : $(SRCDIR)\json_config.c
	+translate$E $** > $@

$(OBJDIR)\json_diff$O : json_diff_.c json_diff.h
	$(TCC) -o$@ -c json_diff_.c

json_diff_.c : $(SRCDIR)\json_diff.c
	+translate$E $** > $@

$(OBJDIR)\json_finfo$O : json_finfo_.c json_finfo.h
	$(TCC) -o$@ -c json_finfo_.c

json_finfo_.c : $(SRCDIR)\json_finfo.c
	+translate$E $** > $@

$(OBJDIR)\json_login$O : json_login_.c json_login.h
	$(TCC) -o$@ -c json_login_.c

json_login_.c : $(SRCDIR)\json_login.c
	+translate$E $** > $@

652
653
654
655
656
657
658






659
660
661
662
663
664
665
666
667
668
	+translate$E $** > $@

$(OBJDIR)\xfer$O : xfer_.c xfer.h
	$(TCC) -o$@ -c xfer_.c

xfer_.c : $(SRCDIR)\xfer.c
	+translate$E $** > $@







$(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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers







>
>
>
>
>
>








|

670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
	+translate$E $** > $@

$(OBJDIR)\xfer$O : xfer_.c xfer.h
	$(TCC) -o$@ -c xfer_.c

xfer_.c : $(SRCDIR)\xfer.c
	+translate$E $** > $@

$(OBJDIR)\xfersetup$O : xfersetup_.c xfersetup.h
	$(TCC) -o$@ -c xfersetup_.c

xfersetup_.c : $(SRCDIR)\xfersetup.c
	+translate$E $** > $@

$(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 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_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers
Changes to win/Makefile.mingw.
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
#!/usr/bin/make
#








# This is a makefile for us on windows using mingw.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.
#
#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc





#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL=1




#### The directory in which the zlib compression library is installed.


#

#







































ZLIBDIR = /programs/gnuwin32





#### 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 -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL















TCC += -static -DFOSSIL_ENABLE_SSL=1










endif

#### 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 -lws2_32


# OpenSSL:
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif












LIB += -lmingwex -lz -lws2_32


#### Tcl shell for use in running the fossil testsuite.  This is only
#    used for testing.  If you do not run
#
TCLSH = tclsh

#### Nullsoft installer makensis location
#
MAKENSIS = "c:\Program Files\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


>
>
>
>
>
>
>
>
|








<










>
>
>
>


|

>
>
>
|
>
>

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

>
>
>
>
|





|



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




|



|
>
>
|



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

|
|



|

|







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
#!/usr/bin/make
#
##############################################################################
# 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.
#
# This is a makefile for us on windows using MinGW.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.

#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc

#### 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

#### 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

#### The directories where the zlib include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#
ZINCDIR = $(SRCDIR)/../zlib-1.2.6
ZLIBDIR = $(SRCDIR)/../zlib-1.2.6

#### 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)/../openssl-1.0.0g/include
OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.0g

#### 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
#    here is to use the Sysinternals junction tool to create a hard
#    link between a "tcl-8.x" sub-directory of the Fossil source code
#    directory and the target Tcl directory.  This removes the need to
#    hard-code the necessary paths in this Makefile.
#
TCLDIR = $(SRCDIR)/../tcl-8.6

#### The Tcl source code directory.  This defaults to the same value as
#    TCLDIR macro (above), which may not be correct.  This value will
#    only be used if the FOSSIL_TCL_SOURCE macro is defined.
#
TCLSRCDIR = $(TCLDIR)

#### The Tcl include and library directories.  These values will only be
#    used if the FOSSIL_TCL_SOURCE macro is not defined.
#
TCLINCDIR = $(TCLDIR)/include
TCLLIBDIR = $(TCLDIR)/lib

#### Tcl: Which Tcl library do we want to use (8.4, 8.5, 8.6, etc)?
#
LIBTCL = -ltcl86

#### 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 -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -Dpqueue_insert=pqueue_insert_fossil
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
endif
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
endif

# With Tcl support (statically linked)
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1 -DSTATIC_BUILD
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.  We add the -static option here
#    so that we can build a static executable that will run in a
#    chroot jail.
#
LIB = -static
LIB += -lmingwex -lz

# OpenSSL: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
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
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
else
LIB += -lws2_32
endif

#### 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
111
112
113
114
115
116
117

118

119
120
121
122
123
124
125
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \
  $(SRCDIR)/json.c \
  $(SRCDIR)/json_artifact.c \
  $(SRCDIR)/json_branch.c \

  $(SRCDIR)/json_diff.c \

  $(SRCDIR)/json_login.c \
  $(SRCDIR)/json_query.c \
  $(SRCDIR)/json_report.c \
  $(SRCDIR)/json_tag.c \
  $(SRCDIR)/json_timeline.c \
  $(SRCDIR)/json_user.c \
  $(SRCDIR)/json_wiki.c \







>

>







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \
  $(SRCDIR)/json.c \
  $(SRCDIR)/json_artifact.c \
  $(SRCDIR)/json_branch.c \
  $(SRCDIR)/json_config.c \
  $(SRCDIR)/json_diff.c \
  $(SRCDIR)/json_finfo.c \
  $(SRCDIR)/json_login.c \
  $(SRCDIR)/json_query.c \
  $(SRCDIR)/json_report.c \
  $(SRCDIR)/json_tag.c \
  $(SRCDIR)/json_timeline.c \
  $(SRCDIR)/json_user.c \
  $(SRCDIR)/json_wiki.c \
162
163
164
165
166
167
168

169
170
171
172
173
174
175
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \

  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \







>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \
  $(SRCDIR)/xfersetup.c \
  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \
206
207
208
209
210
211
212

213

214
215
216
217
218
219
220
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \
  $(OBJDIR)/json_.c \
  $(OBJDIR)/json_artifact_.c \
  $(OBJDIR)/json_branch_.c \

  $(OBJDIR)/json_diff_.c \

  $(OBJDIR)/json_login_.c \
  $(OBJDIR)/json_query_.c \
  $(OBJDIR)/json_report_.c \
  $(OBJDIR)/json_tag_.c \
  $(OBJDIR)/json_timeline_.c \
  $(OBJDIR)/json_user_.c \
  $(OBJDIR)/json_wiki_.c \







>

>







309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \
  $(OBJDIR)/json_.c \
  $(OBJDIR)/json_artifact_.c \
  $(OBJDIR)/json_branch_.c \
  $(OBJDIR)/json_config_.c \
  $(OBJDIR)/json_diff_.c \
  $(OBJDIR)/json_finfo_.c \
  $(OBJDIR)/json_login_.c \
  $(OBJDIR)/json_query_.c \
  $(OBJDIR)/json_report_.c \
  $(OBJDIR)/json_tag_.c \
  $(OBJDIR)/json_timeline_.c \
  $(OBJDIR)/json_user_.c \
  $(OBJDIR)/json_wiki_.c \
257
258
259
260
261
262
263

264
265
266
267
268
269
270
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \

  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \







>







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \
  $(OBJDIR)/xfersetup_.c \
  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \
301
302
303
304
305
306
307

308

309
310
311
312
313
314
315
 $(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_diff.o \

 $(OBJDIR)/json_login.o \
 $(OBJDIR)/json_query.o \
 $(OBJDIR)/json_report.o \
 $(OBJDIR)/json_tag.o \
 $(OBJDIR)/json_timeline.o \
 $(OBJDIR)/json_user.o \
 $(OBJDIR)/json_wiki.o \







>

>







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
 $(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_finfo.o \
 $(OBJDIR)/json_login.o \
 $(OBJDIR)/json_query.o \
 $(OBJDIR)/json_report.o \
 $(OBJDIR)/json_tag.o \
 $(OBJDIR)/json_timeline.o \
 $(OBJDIR)/json_user.o \
 $(OBJDIR)/json_wiki.o \
352
353
354
355
356
357
358

359
360
361
362
363
364
365
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \

 $(OBJDIR)/zip.o

APPNAME = fossil.exe
TRANSLATE   = $(subst /,\\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\\,$(OBJDIR)/version.exe)







>







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME = fossil.exe
TRANSLATE   = $(subst /,\\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\\,$(OBJDIR)/version.exe)
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

$(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 testsuite 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:	$(APPNAME)
	$(TCLSH) test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/cson_amalgamation.o





$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires msys to be installed in addition to the mingw, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:	
	rm -rf $(OBJDIR) $(APPNAME)

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 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(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








|


|
|





>
>
>
>







|


|



|









|







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

$(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

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires MSYS to be installed in addition to the MinGW, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:
	rm -rf $(OBJDIR) $(APPNAME)

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 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.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_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile
Makefile:
$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

711
712
713
714
715
716
717







718
719
720
721
722
723
724







725
726
727
728
729
730
731
$(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

json_branch.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

json_diff.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

json_login.h:	$(OBJDIR)/headers







>
>
>
>
>
>
>







>
>
>
>
>
>
>







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
$(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

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

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

json_diff.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

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

json_login.h:	$(OBJDIR)/headers
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





$(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

xfer.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

zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -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 -DCSON_FOSSIL_MODE

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o













>
>
>
>
>
>
>













|
>









>
>
>
>
>
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
$(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

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

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

zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -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 -DCSON_FOSSIL_MODE

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif

Changes to win/Makefile.mingw.mistachkin.
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
#!/usr/bin/make
#








# This is a makefile for us on windows using mingw.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.
#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc





#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
FOSSIL_ENABLE_SSL=1

#### Enable scripting support via Tcl/Tk
#
FOSSIL_ENABLE_TCL=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

#### The directory where the zlib library source code is located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#

ZLIBDIR = $(SRCDIR)/../zlib-1.2.5

#### The directory where the OpenSSL library source code is 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.
#

OPENSSLDIR = $(SRCDIR)/../openssl-1.0.0e

#### 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
#    here is to use the Sysinternals junction tool to create a hard
#    link between a "tcl-8.x" sub-directory of the Fossil source code
#    directory and the target Tcl directory.  This removes the need to
#    hard-code the necessary paths in this Makefile.
#
TCLDIR = $(SRCDIR)/../tcl-8.6

















#### 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 -Os -Wall -L$(ZLIBDIR) -I$(ZLIBDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL

TCC += -L$(OPENSSLDIR) -I$(OPENSSLDIR)/include
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLDIR)/win -I$(TCLDIR)/generic -I$(TCLDIR)/win
else
TCC += -L$(TCLDIR)/lib -I$(TCLDIR)/include
endif
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
endif

# With Tcl support (statically linked)
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1 -DSTATIC_BUILD
endif






#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.  We add the -static option here
#    so that we can build a static executable that will run in a
#    chroot jail.
#
LIB = -static
LIB += -lmingwex -lz

# OpenSSL: Add the necessary libaries required.
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Which Tcl library do we want to use (8.4, 8.5, 8.6, etc)?
ifdef FOSSIL_ENABLE_TCL
LIB += -ltcl86
endif

#### These libraries MUST appear in the same order as they do for Tcl
#    or linking with it will not work (exact reason unknown).
#

LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32




#### Tcl shell for use in running the fossil testsuite.  This is only
#    used for testing.  If you do not run
#
TCLSH = tclsh

#### Nullsoft installer makensis location
#
MAKENSIS = "c:\Program Files\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


>
>
>
>
>
>
>
>
|

















>
>
>
>



|



|




|

|




>
|

|




>
|













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







|



>
|





|

|












>
>
>
>
>










|




|

|





>

>
>
>

|
|



|

|







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
#!/usr/bin/make
#
##############################################################################
# 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.
#
# This is a makefile for us on windows using MinGW.
#
#### The toplevel directory of the source tree.  Fossil can be built
#    in a directory that is separate from the source tree.  Just change
#    the following to point from the build directory to the src/ folder.
#
SRCDIR = src

#### The directory into which object code files should be written.
#
OBJDIR = wbld

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.  This is used
#    to compile code-generator programs as part of the build process.
#    See TCC below for the C compiler for building the finished binary.
#
BCC = gcc

#### 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

#### 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

#### The directories where the zlib include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#
ZINCDIR = $(SRCDIR)/../zlib-1.2.6
ZLIBDIR = $(SRCDIR)/../zlib-1.2.6

#### 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)/../openssl-1.0.0g/include
OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.0g

#### 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
#    here is to use the Sysinternals junction tool to create a hard
#    link between a "tcl-8.x" sub-directory of the Fossil source code
#    directory and the target Tcl directory.  This removes the need to
#    hard-code the necessary paths in this Makefile.
#
TCLDIR = $(SRCDIR)/../tcl-8.6

#### The Tcl source code directory.  This defaults to the same value as
#    TCLDIR macro (above), which may not be correct.  This value will
#    only be used if the FOSSIL_TCL_SOURCE macro is defined.
#
TCLSRCDIR = $(TCLDIR)

#### The Tcl include and library directories.  These values will only be
#    used if the FOSSIL_TCL_SOURCE macro is not defined.
#
TCLINCDIR = $(TCLDIR)/include
TCLLIBDIR = $(TCLDIR)/lib

#### Tcl: Which Tcl library do we want to use (8.4, 8.5, 8.6, etc)?
#
LIBTCL = -ltcl86

#### 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 -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -Dpqueue_insert=pqueue_insert_fossil
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
else
TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
endif
endif

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -DFOSSIL_ENABLE_SSL=1
endif

# With Tcl support (statically linked)
ifdef FOSSIL_ENABLE_TCL
TCC += -DFOSSIL_ENABLE_TCL=1 -DSTATIC_BUILD
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
endif

#### Extra arguments for linking the finished binary.  Fossil needs
#    to link against the Z-Lib compression library.  There are no
#    other mandatory dependencies.  We add the -static option here
#    so that we can build a static executable that will run in a
#    chroot jail.
#
LIB = -static
LIB += -lmingwex -lz

# OpenSSL: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_SSL
LIB += -lssl -lcrypto -lgdi32
endif

# Tcl: Add the necessary libaries required, if enabled.
ifdef FOSSIL_ENABLE_TCL
LIB += $(LIBTCL)
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
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
else
LIB += -lws2_32
endif

#### 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
168
169
170
171
172
173
174












175
176
177
178
179
180
181
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \












  $(SRCDIR)/leaf.c \
  $(SRCDIR)/login.c \
  $(SRCDIR)/main.c \
  $(SRCDIR)/manifest.c \
  $(SRCDIR)/md5.c \
  $(SRCDIR)/merge.c \
  $(SRCDIR)/merge3.c \







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







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
  $(SRCDIR)/gzip.c \
  $(SRCDIR)/http.c \
  $(SRCDIR)/http_socket.c \
  $(SRCDIR)/http_ssl.c \
  $(SRCDIR)/http_transport.c \
  $(SRCDIR)/import.c \
  $(SRCDIR)/info.c \
  $(SRCDIR)/json.c \
  $(SRCDIR)/json_artifact.c \
  $(SRCDIR)/json_branch.c \
  $(SRCDIR)/json_config.c \
  $(SRCDIR)/json_diff.c \
  $(SRCDIR)/json_login.c \
  $(SRCDIR)/json_query.c \
  $(SRCDIR)/json_report.c \
  $(SRCDIR)/json_tag.c \
  $(SRCDIR)/json_timeline.c \
  $(SRCDIR)/json_user.c \
  $(SRCDIR)/json_wiki.c \
  $(SRCDIR)/leaf.c \
  $(SRCDIR)/login.c \
  $(SRCDIR)/main.c \
  $(SRCDIR)/manifest.c \
  $(SRCDIR)/md5.c \
  $(SRCDIR)/merge.c \
  $(SRCDIR)/merge3.c \
211
212
213
214
215
216
217

218
219
220
221
222
223
224
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \

  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \







>







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  $(SRCDIR)/user.c \
  $(SRCDIR)/verify.c \
  $(SRCDIR)/vfile.c \
  $(SRCDIR)/wiki.c \
  $(SRCDIR)/wikiformat.c \
  $(SRCDIR)/winhttp.c \
  $(SRCDIR)/xfer.c \
  $(SRCDIR)/xfersetup.c \
  $(SRCDIR)/zip.c

TRANS_SRC = \
  $(OBJDIR)/add_.c \
  $(OBJDIR)/allrepo_.c \
  $(OBJDIR)/attach_.c \
  $(OBJDIR)/bag_.c \
252
253
254
255
256
257
258












259
260
261
262
263
264
265
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \












  $(OBJDIR)/leaf_.c \
  $(OBJDIR)/login_.c \
  $(OBJDIR)/main_.c \
  $(OBJDIR)/manifest_.c \
  $(OBJDIR)/md5_.c \
  $(OBJDIR)/merge_.c \
  $(OBJDIR)/merge3_.c \







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







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
  $(OBJDIR)/gzip_.c \
  $(OBJDIR)/http_.c \
  $(OBJDIR)/http_socket_.c \
  $(OBJDIR)/http_ssl_.c \
  $(OBJDIR)/http_transport_.c \
  $(OBJDIR)/import_.c \
  $(OBJDIR)/info_.c \
  $(OBJDIR)/json_.c \
  $(OBJDIR)/json_artifact_.c \
  $(OBJDIR)/json_branch_.c \
  $(OBJDIR)/json_config_.c \
  $(OBJDIR)/json_diff_.c \
  $(OBJDIR)/json_login_.c \
  $(OBJDIR)/json_query_.c \
  $(OBJDIR)/json_report_.c \
  $(OBJDIR)/json_tag_.c \
  $(OBJDIR)/json_timeline_.c \
  $(OBJDIR)/json_user_.c \
  $(OBJDIR)/json_wiki_.c \
  $(OBJDIR)/leaf_.c \
  $(OBJDIR)/login_.c \
  $(OBJDIR)/main_.c \
  $(OBJDIR)/manifest_.c \
  $(OBJDIR)/md5_.c \
  $(OBJDIR)/merge_.c \
  $(OBJDIR)/merge3_.c \
295
296
297
298
299
300
301

302
303
304
305
306
307
308
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \

  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \







>







360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  $(OBJDIR)/user_.c \
  $(OBJDIR)/verify_.c \
  $(OBJDIR)/vfile_.c \
  $(OBJDIR)/wiki_.c \
  $(OBJDIR)/wikiformat_.c \
  $(OBJDIR)/winhttp_.c \
  $(OBJDIR)/xfer_.c \
  $(OBJDIR)/xfersetup_.c \
  $(OBJDIR)/zip_.c

OBJ = \
 $(OBJDIR)/add.o \
 $(OBJDIR)/allrepo.o \
 $(OBJDIR)/attach.o \
 $(OBJDIR)/bag.o \
336
337
338
339
340
341
342












343
344
345
346
347
348
349
 $(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)/leaf.o \
 $(OBJDIR)/login.o \
 $(OBJDIR)/main.o \
 $(OBJDIR)/manifest.o \
 $(OBJDIR)/md5.o \
 $(OBJDIR)/merge.o \
 $(OBJDIR)/merge3.o \







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







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
 $(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_login.o \
 $(OBJDIR)/json_query.o \
 $(OBJDIR)/json_report.o \
 $(OBJDIR)/json_tag.o \
 $(OBJDIR)/json_timeline.o \
 $(OBJDIR)/json_user.o \
 $(OBJDIR)/json_wiki.o \
 $(OBJDIR)/leaf.o \
 $(OBJDIR)/login.o \
 $(OBJDIR)/main.o \
 $(OBJDIR)/manifest.o \
 $(OBJDIR)/md5.o \
 $(OBJDIR)/merge.o \
 $(OBJDIR)/merge3.o \
379
380
381
382
383
384
385

386
387
388
389
390
391
392
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \

 $(OBJDIR)/zip.o

APPNAME = fossil.exe
TRANSLATE   = $(subst /,\\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\\,$(OBJDIR)/version.exe)







>







457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
 $(OBJDIR)/user.o \
 $(OBJDIR)/verify.o \
 $(OBJDIR)/vfile.o \
 $(OBJDIR)/wiki.o \
 $(OBJDIR)/wikiformat.o \
 $(OBJDIR)/winhttp.o \
 $(OBJDIR)/xfer.o \
 $(OBJDIR)/xfersetup.o \
 $(OBJDIR)/zip.o

APPNAME = fossil.exe
TRANSLATE   = $(subst /,\\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\\,$(OBJDIR)/version.exe)
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

$(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 testsuite 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

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires msys to be installed in addition to the mingw, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:
	rm -rf $(OBJDIR) $(APPNAME)

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 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(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








|








|














|













|







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

$(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

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.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

# Requires MSYS to be installed in addition to the MinGW, for the "rm"
# command.  "del" will not work here because it is not a separate command
# but a MSDOS-shell builtin.
#
clean:
	rm -rf $(OBJDIR) $(APPNAME)

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 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
	echo Done >$(OBJDIR)/headers

$(OBJDIR)/headers: Makefile
Makefile:
$(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c

721
722
723
724
725
726
727




















































































728
729
730
731
732
733
734
$(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

info.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

leaf.h:	$(OBJDIR)/headers







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







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
$(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

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

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

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

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

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

json_diff.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

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

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

json_report.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

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

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

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

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

leaf.h:	$(OBJDIR)/headers
1022
1023
1024
1025
1026
1027
1028







1029
1030
1031
1032
1033
1034
1035
1036
1037





1038
1039
1040
1041
1042
1043
1044
$(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

xfer.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

zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o






$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o








>
>
>
>
>
>
>








|
>
>
>
>
>







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
$(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

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

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

zip.h:	$(OBJDIR)/headers
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -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 -DCSON_FOSSIL_MODE

$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

Changes to win/Makefile.msc.


1

2
3
4
5

6
7
8
9
10
11
12


# DO NOT EDIT

#
# This file is automatically generated.  Instead of editing this
# file, edit "makemake.tcl" then run "tclsh src/makemake.tcl"
# to regenerate this file.

B      = ..
SRCDIR = $B\src
OBJDIR = .
OX     = .
O      = .obj
E      = .exe

>
>
|
>


|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
##############################################################################
# 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

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
BCC    = $(CC) $(CFLAGS)
TCC    = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
LIBS   = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)

SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.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_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 

OBJ   = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(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 $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_diff$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O 


APPNAME = $(OX)\fossil$(E)

all: $(OX) $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts







|

|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
BCC    = $(CC) $(CFLAGS)
TCC    = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
LIBS   = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)

SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.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_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c 

OBJ   = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(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 $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_config$O $(OX)\json_diff$O $(OX)\json_finfo$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\xfersetup$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O 


APPNAME = $(OX)\fossil$(E)

all: $(OX) $(APPNAME)

$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
89
90
91
92
93
94
95

96

97
98
99
100
101
102
103
	echo $(OX)\http_ssl.obj >> $@
	echo $(OX)\http_transport.obj >> $@
	echo $(OX)\import.obj >> $@
	echo $(OX)\info.obj >> $@
	echo $(OX)\json.obj >> $@
	echo $(OX)\json_artifact.obj >> $@
	echo $(OX)\json_branch.obj >> $@

	echo $(OX)\json_diff.obj >> $@

	echo $(OX)\json_login.obj >> $@
	echo $(OX)\json_query.obj >> $@
	echo $(OX)\json_report.obj >> $@
	echo $(OX)\json_tag.obj >> $@
	echo $(OX)\json_timeline.obj >> $@
	echo $(OX)\json_user.obj >> $@
	echo $(OX)\json_wiki.obj >> $@







>

>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	echo $(OX)\http_ssl.obj >> $@
	echo $(OX)\http_transport.obj >> $@
	echo $(OX)\import.obj >> $@
	echo $(OX)\info.obj >> $@
	echo $(OX)\json.obj >> $@
	echo $(OX)\json_artifact.obj >> $@
	echo $(OX)\json_branch.obj >> $@
	echo $(OX)\json_config.obj >> $@
	echo $(OX)\json_diff.obj >> $@
	echo $(OX)\json_finfo.obj >> $@
	echo $(OX)\json_login.obj >> $@
	echo $(OX)\json_query.obj >> $@
	echo $(OX)\json_report.obj >> $@
	echo $(OX)\json_tag.obj >> $@
	echo $(OX)\json_timeline.obj >> $@
	echo $(OX)\json_user.obj >> $@
	echo $(OX)\json_wiki.obj >> $@
144
145
146
147
148
149
150

151
152
153
154
155
156
157
	echo $(OX)\user.obj >> $@
	echo $(OX)\verify.obj >> $@
	echo $(OX)\vfile.obj >> $@
	echo $(OX)\wiki.obj >> $@
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\xfer.obj >> $@

	echo $(OX)\zip.obj >> $@
	echo $(LIBS) >> $@




$(OX):







>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	echo $(OX)\user.obj >> $@
	echo $(OX)\verify.obj >> $@
	echo $(OX)\vfile.obj >> $@
	echo $(OX)\wiki.obj >> $@
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\xfer.obj >> $@
	echo $(OX)\xfersetup.obj >> $@
	echo $(OX)\zip.obj >> $@
	echo $(LIBS) >> $@




$(OX):
196
197
198
199
200
201
202

203

204
205
206
207
208
209
210

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_diff$O : $(SRCDIR)\json_detail.h

$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h







>

>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

realclean:
	-del $(APPNAME) translate$E mkindex$E makeheaders$E 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_finfo$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
451
452
453
454
455
456
457






458
459
460
461
462
463






464
465
466
467
468
469
470
	translate$E $** > $@

$(OX)\json_branch$O : json_branch_.c json_branch.h
	$(TCC) /Fo$@ -c json_branch_.c

json_branch_.c : $(SRCDIR)\json_branch.c
	translate$E $** > $@







$(OX)\json_diff$O : json_diff_.c json_diff.h
	$(TCC) /Fo$@ -c json_diff_.c

json_diff_.c : $(SRCDIR)\json_diff.c
	translate$E $** > $@







$(OX)\json_login$O : json_login_.c json_login.h
	$(TCC) /Fo$@ -c json_login_.c

json_login_.c : $(SRCDIR)\json_login.c
	translate$E $** > $@








>
>
>
>
>
>






>
>
>
>
>
>







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
	translate$E $** > $@

$(OX)\json_branch$O : json_branch_.c json_branch.h
	$(TCC) /Fo$@ -c json_branch_.c

json_branch_.c : $(SRCDIR)\json_branch.c
	translate$E $** > $@

$(OX)\json_config$O : json_config_.c json_config.h
	$(TCC) /Fo$@ -c json_config_.c

json_config_.c : $(SRCDIR)\json_config.c
	translate$E $** > $@

$(OX)\json_diff$O : json_diff_.c json_diff.h
	$(TCC) /Fo$@ -c json_diff_.c

json_diff_.c : $(SRCDIR)\json_diff.c
	translate$E $** > $@

$(OX)\json_finfo$O : json_finfo_.c json_finfo.h
	$(TCC) /Fo$@ -c json_finfo_.c

json_finfo_.c : $(SRCDIR)\json_finfo.c
	translate$E $** > $@

$(OX)\json_login$O : json_login_.c json_login.h
	$(TCC) /Fo$@ -c json_login_.c

json_login_.c : $(SRCDIR)\json_login.c
	translate$E $** > $@

757
758
759
760
761
762
763






764
765
766
767
768
769
770
771
772
773
	translate$E $** > $@

$(OX)\xfer$O : xfer_.c xfer.h
	$(TCC) /Fo$@ -c xfer_.c

xfer_.c : $(SRCDIR)\xfer.c
	translate$E $** > $@







$(OX)\zip$O : zip_.c zip.h
	$(TCC) /Fo$@ -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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h 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
787
788
789
790
791
792
793
794
795
796
797
798
799
800
	translate$E $** > $@

$(OX)\xfer$O : xfer_.c xfer.h
	$(TCC) /Fo$@ -c xfer_.c

xfer_.c : $(SRCDIR)\xfer.c
	translate$E $** > $@

$(OX)\xfersetup$O : xfersetup_.c xfersetup.h
	$(TCC) /Fo$@ -c xfersetup_.c

xfersetup_.c : $(SRCDIR)\xfersetup.c
	translate$E $** > $@

$(OX)\zip$O : zip_.c zip.h
	$(TCC) /Fo$@ -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 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_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers
Changes to www/build.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
27
28
29


30
31
32
33
34
35
36
37
<title>Building and Installing Fossil</title>

<h2>0.0 Using A Pre-compiled Binary</h2>

<p>You can skip all of the following by downloading
a <a href="http://www.fossil-scm.org/download.html">pre-compiled binary</a>


appropriate for your platform and putting that self-contained binary
someplace on your $PATH.
To uninstall, simply delete the binary.
To upgrade from an older release, just overwrite the older binary with
the newer one.</p>

<h2>0.1 Executive Summary</h2>

<p>Building and installing is very simple.  Three steps:</p>

<ol>
<li> Download and unpack a source tarball or ZIP.
<li> <b>./configure; make</b>
<li> Move or copy the resulting "fossil" executable to someplace
     on your $PATH.
</ol>

<p><hr>

<h2>1.0 Obtaining The Source Code</h2>

<p>Fossil is self-hosting, so you can obtain a ZIP archive containing
a snapshot of the latest version directly from fossil's own fossil


repository.  Follow these steps:</p>

<ol>
<li><p>Point your web browser at
<a href="http://www.fossil-scm.org/">
http://www.fossil-scm.org/</a>.  Click on the "Login" menu button.</p></li>

<li><p>Log in as anonymous.  The password is shown on screen.




|
|
>
>
|
|




















|
>
>
|







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
<title>Building and Installing Fossil</title>

<h2>0.0 Using A Pre-compiled Binary</h2>

<p>Released versions of fossil come with
<a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and
a source archive</a> for that release. You can thus skip the following if you
want to run or build a release version of fossil. Just download
the appropriate package from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>
and put it on your $PATH.
To uninstall, simply delete the binary.
To upgrade from an older release, just overwrite the older binary with
the newer one.</p>

<h2>0.1 Executive Summary</h2>

<p>Building and installing is very simple.  Three steps:</p>

<ol>
<li> Download and unpack a source tarball or ZIP.
<li> <b>./configure; make</b>
<li> Move or copy the resulting "fossil" executable to someplace
     on your $PATH.
</ol>

<p><hr>

<h2>1.0 Obtaining The Source Code</h2>

<p>Fossil is self-hosting, so you can obtain a ZIP archive containing
a snapshot of the <em>latest</em> version directly from fossil's own fossil
repository. Additionally, source archives of <em>released</em> versions of
fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>.
To obtain a development version of fossil, follow these steps:</p>

<ol>
<li><p>Point your web browser at
<a href="http://www.fossil-scm.org/">
http://www.fossil-scm.org/</a>.  Click on the "Login" menu button.</p></li>

<li><p>Log in as anonymous.  The password is shown on screen.
Changes to www/changes.wiki.
1













2
3
4
5
6
7
8
<title>Change Log</title>














<h2>Changes For Version 1.21 (2011-12-13)</h2>
  *  Added side-by-side diffs in the command-line interface
  *  Automatically enable hyperlinks if the UserAgent string in the 
     HTTP header suggests that the requestor is a human and not a bot.
  *  Show only commonly used commands with "fossil help".  Use
     "fossil help --all" to see the complete list now.

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







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<title>Change Log</title>

<h2>Changes For Version 1.22 (2012-02-xx)</h2>
  *  Greatly improved "diff" processing including the new --brief option,
     partial line matching, colorized in-line diffs, and better performance.
  *  Promote "allow-symlinks" to a versionable setting
  *  Harden the CGI processing logic against DOS attacks
  *  Add the ability to run TH1 scripts after sync requests
  *  Store the repository name in _FOSSIL_ as it is type in the "open" command,
     possibly as a relative pathname.
  *  Make ".fslckout" the alternative name for the "_FOSSIL_" file. 
  *  Change the "ssh:" transfer method to allow all access regardless of
     user permission.
  *  Various minor bug fixes

<h2>Changes For Version 1.21 (2011-12-13)</h2>
  *  Added side-by-side diffs in the command-line interface
  *  Automatically enable hyperlinks if the UserAgent string in the 
     HTTP header suggests that the requestor is a human and not a bot.
  *  Show only commonly used commands with "fossil help".  Use
     "fossil help --all" to see the complete list now.
Changes to www/stats.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


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
<title>Fossil Performance</title>
<h1 align="center">Performance Statistics</h1>

The questions will inevitably arise:  How does Fossil perform? 
Does it use a lot of disk space or bandwidth?  Is it scalable?

In an attempt to answers these questions, this report looks at five
projects that use fossil for configuration management and examines how
well they are working.  The following table is a summary of the results.

Explanation and analysis follows the table.

<table border=1>
<tr>
<th>Project</th>
<th>Number Of Artifacts</th>
<th>Number Of Check-ins</th>
<th>Project&nbsp;Duration<br>(as of 2009-08-23)</th>
<th>Average Check-ins Per Day</th>
<th>Uncompressed Size</th>
<th>Repository Size</th>
<th>Compression Ratio</th>
<th>Clone Bandwidth</th>
</tr>

<tr align="center">

<td>SQLite


<td>28643


<td>6755







<td>3373&nbsp;days<br>9.24&nbsp;yrs
<td>2.00
<td>1.27&nbsp;GB
<td>35.4&nbsp;MB
<td>35:1
<td>982&nbsp;KB&nbsp;up<br>12.4&nbsp;MB&nbsp;down
</tr>

<tr align="center">
<td>Fossil
<td>4981
<td>1272
<td>764&nbsp;days<br>2.1&nbsp;yrs
<td>1.66
<td>144&nbsp;MB
<td>8.74&nbsp;MB
<td>16:1
<td>128&nbsp;KB&nbsp;up<br>4.49&nbsp;MB&nbsp;down
</tr>

<tr align="center">
<td>SLT
<td>2062
<td>67
<td>266&nbsp;days
<td>0.25
<td>1.76&nbsp;GB
<td>147&nbsp;MB
<td>11:1
<td>1.1&nbsp;MB&nbsp;up<br>141&nbsp;MB&nbsp;down
</tr>

<tr align="center">
<td>TH3
<td>1999
<td>429
<td>331&nbsp;days
<td>1.30
<td>70.5&nbsp;MB
<td>6.3&nbsp;MB
<td>11:1
<td>55&nbsp;KB&nbsp;up<br>4.66&nbsp;MB&nbsp;down
</tr>

<tr align="center">
<td>SQLite Docs
<td>1787
<td>444
<td>650&nbsp;days<br>1.78&nbsp;yrs
<td>0.68
<td>43&nbsp;MB
<td>4.9&nbsp;MB
<td>8:1
<td>46&nbsp;KB&nbsp;up<br>3.35&nbsp;MB&nbsp;down
</tr>

</table>

<h2>The Five Projects</h2>

The five projects listed above were chosen because they have been in
existance for a long time (relative to the age of fossil) or because
they have larges amounts of content.  The most important project using
fossil is SQLite.  Fossil itself
is built on top of SQLite and so obviously SQLite has to predate fossil.
SQLite was originally versioned using CVS, but recently the entire 9-year
and 320-MB CVS history of SQLite was converted over to Fossil.  This is
an important datapoint because it demonstrates fossil's ability to manage
a significant and long-running project.
The next-longest running fossil project is fossil itself, at 2.1 years.
The documentation for SQLite
(identified above as "SQLite Docs") was split off of the main SQLite 
source tree and into its own fossil repository about 1.75 years ago.
The "SQL Logic Test" or "SLT" project is a massive
collection of SQL statements and their output used to compare the 
processing of SQLite against MySQL, PostgreSQL, Microsoft SQL Server,
and Oracle.  
Finally "TH3" is a proprietary set of test cases for SQLite used to give
100% branch test coverage of SQLite on embedded platforms.  All projects
except for TH3 are open-source.

<h2>Measured Attributes</h2>

In fossil, every version of every file, every wiki page, every change to
every ticket, and every check-in is a separate "artifact".  One way to
think of a fossil project is as a bag of artifacts.  Of course, there is
a lot more than this going on in fossil.  Many of the artifacts have meaning
and are related to other artifacts.  But at a low level (for example when
synchronizing two instances of the same project) the only thing that matters
is the unordered collection of artifacts.  In fact, one of the key 
characteristics of fossil is that the entire project history can be
reconstructed simply by scanning the artifacts in an arbitrary order.

The number of check-ins is the number of times that the "commit" command
has been run.  A single check-in might change a 3 or 4 files, or it might
change several dozen different files.  Regardless of the number of files
changed, it still only counts as one check-in.

The "Uncompressed Size" is the total size of all the artifacts within
the fossil repository assuming they were all uncompressed and stored 
separately on the disk.  Fossil makes use of delta compression between related
versions of the same file, and then uses zlib compression on the resulting
deltas.  The total resulting repository size is shown after the uncompressed

size.  


On the right end of the table, we show the "Clone Bandwidth".  This is the
total number of bytes sent from client to server ("uplink") and from server
back to client ("downlink") in order to clone a repository.  These byte counts
include HTTP protocol overhead.

In the table and throughout this article,
"GB" means gigabytes (10<sup><small>9</small></sup> bytes)
not <a href="http://en.wikipedia.org/wiki/Gibibyte">gibibytes</a>
(2<sup><small>30</small></sup> bytes).  Similarly, "MB" and "KB"
means megabytes and kilobytes, not mebibytes and kibibytes.

<h2>Analysis And Supplimental Data</h2>

Perhaps the two most interesting datapoints in the above table are SQLite
and SLT.  SQLite is a long-running project with long revision chains.
Some of the files in SQLite have been edited close to a thousand times.
Each of these edits is stored as a delta, and hence the SQLite project
gets excellent 35:1 compression.  SLT, on the other hand, consists of
many large (megabyte-sized) SQL scripts that have one or maybe two
versions.  There is very little delta compression occurring and so the
overall repository compression ratio is much lower.  Note also that
quite a bit more bandwidth is required to clone SLT than SQLite.

For the first nine years of its development, SQLite was versioned by CVS.
The resulting CVS repository measured over 320MB in size.  So, the
developers were
pleasently surprised to see that this entire project could be cloned in



fossil using only about 13MB of network traffic.  The "sync" protocol
used by fossil has turned out to be surprisingly efficient.  A typical
check-in on SQLite might use 3 or 4KB of network bandwidth total.  Hardly
worth measuring.  The sync protocol is efficient enough that, once cloned,
fossil could easily be used over a dial-up connection.






|


>
















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



|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|




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


|

|
|



|




|



|



>
|
>


|
|
|











|

|

|





<
|
>
>
>
|



|
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
<title>Fossil Performance</title>
<h1 align="center">Performance Statistics</h1>

The questions will inevitably arise:  How does Fossil perform? 
Does it use a lot of disk space or bandwidth?  Is it scalable?

In an attempt to answers these questions, this report looks at several
projects that use fossil for configuration management and examines how
well they are working.  The following table is a summary of the results.
(Last updated on 2012-02-26.)
Explanation and analysis follows the table.

<table border=1>
<tr>
<th>Project</th>
<th>Number Of Artifacts</th>
<th>Number Of Check-ins</th>
<th>Project&nbsp;Duration<br>(as of 2009-08-23)</th>
<th>Average Check-ins Per Day</th>
<th>Uncompressed Size</th>
<th>Repository Size</th>
<th>Compression Ratio</th>
<th>Clone Bandwidth</th>
</tr>

<tr align="center">
<td>[http://www.sqlite.org/src/timeline | SQLite]
<td>41113
<td>9943
<td>4290&nbsp;days<br>11.75&nbsp;yrs
<td>2.32
<td>2.09&nbsp;GB
<td>33.2&nbsp;MB
<td>63:1
<td>23.2&nbsp;MB
</tr>

<tr align="center">
<td>[http://core.tcl.tk/tcl/timeline | TCL]
<td>74806
<td>13541
<td>5085&nbsp;days<br>13.92&nbsp;yrs
<td>2.66
<td>5.2&nbsp;GB
<td>86&nbsp;MB
<td>60:1
<td>67.0&nbsp;MB
</tr>

<tr align="center">
<td>[/timeline | Fossil]
<td>15561
<td>3764
<td>1681&nbsp;days<br>4.6&nbsp;yrs
<td>2.24
<td>721&nbsp;MB
<td>18.8&nbsp;MB
<td>38:1
<td>12.0&nbsp;MB
</tr>

<tr align="center">
<td>[http://www.sqlite.org/slt/timeline | SLT]
<td>2174
<td>100
<td>1183&nbsp;days<br>3.24&nbsp;yrs
<td>0.08
<td>1.94&nbsp;GB
<td>143&nbsp;MB
<td>12:1
<td>141&nbsp;MB
</tr>

<tr align="center">
<td>[http://www.sqlite.org/th3.html | TH3]
<td>5624
<td>1472
<td>1248&nbsp;days<br>3.42&nbsp;yrs
<td>1.78
<td>252&nbsp;MB
<td>12.5&nbsp;MB
<td>20:1
<td>12.2&nbsp;MB
</tr>

<tr align="center">
<td>[http://www.sqlite.org/docsrc/timeline | SQLite Docs]
<td>3664
<td>1003
<td>1567&nbsp;days<br>4.29&nbsp;yrs
<td>0.64
<td>108&nbsp;MB
<td>6.6&nbsp;MB
<td>16:1
<td>5.71&nbsp;MB
</tr>

</table>
























<h2>Measured Attributes</h2>

In Fossil, every version of every file, every wiki page, every change to
every ticket, and every check-in is a separate "artifact".  One way to
think of a Fossil project is as a bag of artifacts.  Of course, there is
a lot more than this going on in Fossil.  Many of the artifacts have meaning
and are related to other artifacts.  But at a low level (for example when
synchronizing two instances of the same project) the only thing that matters
is the unordered collection of artifacts.  In fact, one of the key 
characteristics of Fossil is that the entire project history can be
reconstructed simply by scanning the artifacts in an arbitrary order.

The number of check-ins is the number of times that the "commit" command
has been run.  A single check-in might change a 3 or 4 files, or it might
change dozens or hundreds of files.  Regardless of the number of files
changed, it still only counts as one check-in.

The "Uncompressed Size" is the total size of all the artifacts within
the repository assuming they were all uncompressed and stored 
separately on the disk.  Fossil makes use of delta compression between related
versions of the same file, and then uses zlib compression on the resulting
deltas.  The total resulting repository size is shown after the uncompressed
size.  For this chart, "fossil rebuild --compress" was run on each repository
prior to measuring its compressed size.  Repository sizes would typically 
be 20% larger without that rebuild.

On the right end of the table, we show the "Clone Bandwidth".  This is the
total number of bytes sent from server back to the client.  The number of
bytes sent from client to server is neglible in comparison.
These byte counts include HTTP protocol overhead.

In the table and throughout this article,
"GB" means gigabytes (10<sup><small>9</small></sup> bytes)
not <a href="http://en.wikipedia.org/wiki/Gibibyte">gibibytes</a>
(2<sup><small>30</small></sup> bytes).  Similarly, "MB" and "KB"
means megabytes and kilobytes, not mebibytes and kibibytes.

<h2>Analysis And Supplimental Data</h2>

Perhaps the two most interesting datapoints in the above table are SQLite
and SLT.  SQLite is a long-running project with long revision chains.
Some of the files in SQLite have been edited over a thousand times.
Each of these edits is stored as a delta, and hence the SQLite project
gets excellent 63:1 compression.  SLT, on the other hand, consists of
many large (megabyte-sized) SQL scripts that have one or maybe two
edits each.  There is very little delta compression occurring and so the
overall repository compression ratio is much lower.  Note also that
quite a bit more bandwidth is required to clone SLT than SQLite.

For the first nine years of its development, SQLite was versioned by CVS.
The resulting CVS repository measured over 320MB in size.  So, the

developers were surprised to see that this entire project could be cloned in
fossil using only about 23.2MB of network traffic.  (This 23.2MB includes
all the changes to SQLite that have been made since the conversion from
CVS.  Of those changes are omitted, the clone bandwidth drops to 13MB.)
The "sync" protocol
used by fossil has turned out to be surprisingly efficient.  A typical
check-in on SQLite might use 3 or 4KB of network bandwidth total.  Hardly
worth measuring.  The sync protocol is efficient enough that, once cloned,
Fossil could easily be used over a dial-up connection.
Changes to www/tech_overview.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<title>Technical Overview</title>
<h2 align="center">
A Technical Overview<br>Of The Design And Implementation<br>Of Fossil
</h2>

<h2>1.0 Introduction</h2>

At its lowest level, a Fossil repository consists of an unordered set
of immutable "artifacts".  You might think of these artifacts as "files",
since in many cases the artifacts exactly correspond to source code files
that are stored in the Fossil repository.  But other "control artifacts" 
are also included in the mix.  These control artifacts define the relationships
between artifacts - which files go together to form a particular
version of the project, who checked in that version and when, what was
the check-in comment, what wiki pages are included with the project, what
are the edit histories of each wiki page, what bug reports or tickets are
included, who contributed to the evolution of each ticket, and so forth,
and so on.  This low-level file format is called the "global state" of
the repository, since this is the information that is synced to peer
repositories using push and pull operations.   The low-level file format
is also called "enduring" since it is intended to last for many years.
The details of the low-level, enduring, global file format 
are [./fileformat.wiki | described separately].

This article is about how Fossil is currently implemented.  Instead of
dealing with vague abstractions of "enduring file formats" as the
[./fileformat.wiki | that other document] does, this article provides
some detail on how Fossil actually stores information on disk.  

<h2>2.0 Three Databases</h2>

Fossil stores state information in 
[http://www.sqlite.org/ | SQLite] database files.
SQLite keeps an entire relational database, including multiple tables and
indices, in a single disk file.  The SQLite library allows the database
files to be efficiently queried and updated using the industry-standard
SQL language.  And SQLite makes updates to these database files atomic,
even if a system crashes or power failure occurs in the middle of the
update, meaning that repository content is protected even during severe
malfunctions.

Fossil uses three separate classes of SQLite databases:

<ol>
<li>The configuration database
<li>Repository databases
<li>Checkout databases









|
<





|
|








|









|
|
<
<







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
<title>Technical Overview</title>
<h2 align="center">
A Technical Overview<br>Of The Design And Implementation<br>Of Fossil
</h2>

<h2>1.0 Introduction</h2>

At its lowest level, a Fossil repository consists of an unordered set
of immutable "artifacts".  You might think of these artifacts as "files",
since in many cases the artifacts exactly that.  But other "control artifacts" 

are also included in the mix.  These control artifacts define the relationships
between artifacts - which files go together to form a particular
version of the project, who checked in that version and when, what was
the check-in comment, what wiki pages are included with the project, what
are the edit histories of each wiki page, what bug reports or tickets are
included, who contributed to the evolution of each ticket, and so forth.
This low-level file format is called the "global state" of
the repository, since this is the information that is synced to peer
repositories using push and pull operations.   The low-level file format
is also called "enduring" since it is intended to last for many years.
The details of the low-level, enduring, global file format 
are [./fileformat.wiki | described separately].

This article is about how Fossil is currently implemented.  Instead of
dealing with vague abstractions of "enduring file formats" as the
[./fileformat.wiki | other document] does, this article provides
some detail on how Fossil actually stores information on disk.  

<h2>2.0 Three Databases</h2>

Fossil stores state information in 
[http://www.sqlite.org/ | SQLite] database files.
SQLite keeps an entire relational database, including multiple tables and
indices, in a single disk file.  The SQLite library allows the database
files to be efficiently queried and updated using the industry-standard
SQL language.  SQLite updates are atomic, so even in the event of
a system crashes or power failure the repository content is protected.



Fossil uses three separate classes of SQLite databases:

<ol>
<li>The configuration database
<li>Repository databases
<li>Checkout databases
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
of the artifacts that comprise the 
[./fileformat.wiki | enduring, global, shared state] of the project.
The artifacts are stored as BLOBs, compressed using
[http://www.zlib.net/ | zlib compression] and, where applicable,
using [./delta_encoder_algorithm.wiki | delta compression].
The combination of zlib and delta compression results in a considerable
space savings.  For the SQLite project, at the time of this writing,
the total size of all artifacts is over 1.7 GB but thanks to the
combined zlib and delta compression, that content only takes up
51.4 MB of space in the repository database, for a compression ratio
of about 33:1.


Note that the zlib and delta compression is not an inherent part of the
Fossil file format; it is just an optimization.  
The enduring file format for Fossil is the unordered
set of artifacts. The compression techniques are just a detail of
how the current implementation of Fossil happens to store these artifacts
efficiently on disk.







|

|
|
>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
of the artifacts that comprise the 
[./fileformat.wiki | enduring, global, shared state] of the project.
The artifacts are stored as BLOBs, compressed using
[http://www.zlib.net/ | zlib compression] and, where applicable,
using [./delta_encoder_algorithm.wiki | delta compression].
The combination of zlib and delta compression results in a considerable
space savings.  For the SQLite project, at the time of this writing,
the total size of all artifacts is over 2.0 GB but thanks to the
combined zlib and delta compression, that content only takes up
32 MB of space in the repository database, for a compression ratio
of about 64:1.  The average size of a content BLOB in the database
is around 500 bytes.

Note that the zlib and delta compression is not an inherent part of the
Fossil file format; it is just an optimization.  
The enduring file format for Fossil is the unordered
set of artifacts. The compression techniques are just a detail of
how the current implementation of Fossil happens to store these artifacts
efficiently on disk.
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
works by reading the input git-fast-export stream and using it to construct
corresponding artifacts which are then written into the repository database.

<h4>2.2.2 Project Metadata</h4>

The global project state information in the repository database is
supplemented by computed metadata that makes querying the project state
more efficient.  Metadata includes but information such as the following:

  *  The names for all files found in any checkin.
  *  All check-ins that modify a given file
  *  Parents and children of each checkin.
  *  Potential timeline rows.
  *  The names of all symbolic tags and the checkins they apply to.
  *  The names of all wiki pages and the artifacts that comprise each
     wiki page.
  *  Attachments and the wiki pages or tickets they apply to.
  *  Current content of each ticket.
  *  Cross-references between tickets, checkins, and wiki pages.

The metadata is held in various SQL tables in the repository database.
The metadata is designed to facilitate queries for the various timelines and
reports that Fossil generates.  
As the functionality of Fossil evolves,
the schema for the metadata can and does change from time to time.
But schema changes do no invalidate the repository.  Remember that the
metadata contains no new information - only information that has been
extracted from the canonical artifacts and saved in a more useful form.
Hence, when the metadata schema changes, the prior metadata can be discarded
and the entire metadata corpus can be recomputed from the canonical
artifacts.  That is what the
[/help/rebuild | fossil rebuild] command does.







|














|

|







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
works by reading the input git-fast-export stream and using it to construct
corresponding artifacts which are then written into the repository database.

<h4>2.2.2 Project Metadata</h4>

The global project state information in the repository database is
supplemented by computed metadata that makes querying the project state
more efficient.  Metadata includes information such as the following:

  *  The names for all files found in any checkin.
  *  All check-ins that modify a given file
  *  Parents and children of each checkin.
  *  Potential timeline rows.
  *  The names of all symbolic tags and the checkins they apply to.
  *  The names of all wiki pages and the artifacts that comprise each
     wiki page.
  *  Attachments and the wiki pages or tickets they apply to.
  *  Current content of each ticket.
  *  Cross-references between tickets, checkins, and wiki pages.

The metadata is held in various SQL tables in the repository database.
The metadata is designed to facilitate queries for the various timelines and
reports that Fossil generates.
As the functionality of Fossil evolves,
the schema for the metadata can and does change.
But schema changes do no invalidate the repository.  Remember that the
metadata contains no new information - only information that has been
extracted from the canonical artifacts and saved in a more useful form.
Hence, when the metadata schema changes, the prior metadata can be discarded
and the entire metadata corpus can be recomputed from the canonical
artifacts.  That is what the
[/help/rebuild | fossil rebuild] command does.
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
privileges on the remote repository.

<h4>2.2.5 Shunned Artifact List</h4>

The set of canonical artifacts for a project - the global state for the
project - is intended to be an append-only database.  In other words,
new artifacts can be added but artifacts can never be removed.  But
it sometimes happens that inappropriate content can be mistakenly or
maliciously added to a repository.  When that happens, the only way
to get rid of the content is to [./shunning.wiki | "shun"] it.
The "shun" table in the repository database records the SHA1 hash of 
all shunned artifacts.

The shun table can be pushed or pulled using
the [/help/config | fossil config] command with the "shun" AREA argument.
The shun table is also copied during a [/help/clone | clone].

<h3>2.3 Checkout Databases</h3>

Unlike several other popular DVCSes, Fossil allows a single repository
to have multiple working checkouts.  Each working checkout has a single
database in its root directory that records the state of that checkout.
The checkout database is named "_FOSSIL_" by default, but can be renamed
to ".fos" if desired.  (Future versions of Fossil might make ".fos" the
default name.)  The checkout database records information such as the
following:

  *  The full pathname of the repository database file.
  *  The version that is currently checked out.
  *  Files that have been [/help/add | added],
     [/help/rm | removed], or [/help/mv | renamed] but not
     yet committed.
  *  The mtime and size of files as they were originally checked out,







|
|
|













|
|
|







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
privileges on the remote repository.

<h4>2.2.5 Shunned Artifact List</h4>

The set of canonical artifacts for a project - the global state for the
project - is intended to be an append-only database.  In other words,
new artifacts can be added but artifacts can never be removed.  But
it sometimes happens that inappropriate content is mistakenly or
maliciously added to a repository.  The only way to get rid of
the undesired content is to [./shunning.wiki | "shun"] it.
The "shun" table in the repository database records the SHA1 hash of 
all shunned artifacts.

The shun table can be pushed or pulled using
the [/help/config | fossil config] command with the "shun" AREA argument.
The shun table is also copied during a [/help/clone | clone].

<h3>2.3 Checkout Databases</h3>

Unlike several other popular DVCSes, Fossil allows a single repository
to have multiple working checkouts.  Each working checkout has a single
database in its root directory that records the state of that checkout.
The checkout database is named "_FOSSIL_" by default, but can be renamed
to ".fslckout" if desired.  (Future versions of Fossil might make
".fslckout" the default name.)  The checkout database records information
such as the following:

  *  The full pathname of the repository database file.
  *  The version that is currently checked out.
  *  Files that have been [/help/add | added],
     [/help/rm | removed], or [/help/mv | renamed] but not
     yet committed.
  *  The mtime and size of files as they were originally checked out,