Fossil SCM

Merge updates from trunk.

mistachkin 2013-01-07 17:21 UTC th1Hooks merge
Commit 4f365f7b77c70a858d02a3a7c149d7b92cbf8a26
+1 -1
--- src/add.c
+++ src/add.c
@@ -140,11 +140,11 @@
140140
const char *zPath, /* Tree-name of file to add. */
141141
int vid, /* Add to this VFILE */
142142
int caseSensitive /* True if filenames are case sensitive */
143143
){
144144
const char *zCollate = caseSensitive ? "binary" : "nocase";
145
- if( !file_is_simple_pathname(zPath) ){
145
+ if( !file_is_simple_pathname(zPath, 1) ){
146146
fossil_warning("filename contains illegal characters: %s", zPath);
147147
return 0;
148148
}
149149
if( db_exists("SELECT 1 FROM vfile"
150150
" WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
151151
--- src/add.c
+++ src/add.c
@@ -140,11 +140,11 @@
140 const char *zPath, /* Tree-name of file to add. */
141 int vid, /* Add to this VFILE */
142 int caseSensitive /* True if filenames are case sensitive */
143 ){
144 const char *zCollate = caseSensitive ? "binary" : "nocase";
145 if( !file_is_simple_pathname(zPath) ){
146 fossil_warning("filename contains illegal characters: %s", zPath);
147 return 0;
148 }
149 if( db_exists("SELECT 1 FROM vfile"
150 " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
151
--- src/add.c
+++ src/add.c
@@ -140,11 +140,11 @@
140 const char *zPath, /* Tree-name of file to add. */
141 int vid, /* Add to this VFILE */
142 int caseSensitive /* True if filenames are case sensitive */
143 ){
144 const char *zCollate = caseSensitive ? "binary" : "nocase";
145 if( !file_is_simple_pathname(zPath, 1) ){
146 fossil_warning("filename contains illegal characters: %s", zPath);
147 return 0;
148 }
149 if( db_exists("SELECT 1 FROM vfile"
150 " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
151
+1 -1
--- src/bisect.c
+++ src/bisect.c
@@ -123,11 +123,11 @@
123123
for(p=path_last(), n=0; p; p=p->pFrom, n++){
124124
if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){
125125
nHidden++;
126126
continue;
127127
}else if( nHidden ){
128
- fossil_print(" ... eliding %d check-ins\n", nHidden);
128
+ fossil_print(" ... %d other check-ins omitted\n", nHidden);
129129
nHidden = 0;
130130
}
131131
db_bind_int(&s, ":rid", p->rid);
132132
if( db_step(&s)==SQLITE_ROW ){
133133
const char *zUuid = db_column_text(&s, 0);
134134
--- src/bisect.c
+++ src/bisect.c
@@ -123,11 +123,11 @@
123 for(p=path_last(), n=0; p; p=p->pFrom, n++){
124 if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){
125 nHidden++;
126 continue;
127 }else if( nHidden ){
128 fossil_print(" ... eliding %d check-ins\n", nHidden);
129 nHidden = 0;
130 }
131 db_bind_int(&s, ":rid", p->rid);
132 if( db_step(&s)==SQLITE_ROW ){
133 const char *zUuid = db_column_text(&s, 0);
134
--- src/bisect.c
+++ src/bisect.c
@@ -123,11 +123,11 @@
123 for(p=path_last(), n=0; p; p=p->pFrom, n++){
124 if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){
125 nHidden++;
126 continue;
127 }else if( nHidden ){
128 fossil_print(" ... %d other check-ins omitted\n", nHidden);
129 nHidden = 0;
130 }
131 db_bind_int(&s, ":rid", p->rid);
132 if( db_step(&s)==SQLITE_ROW ){
133 const char *zUuid = db_column_text(&s, 0);
134
+1
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,11 @@
2121
** formatting function and its cousins, and routines to encode and
2222
** decode strings in HTML or HTTP.
2323
*/
2424
#include "config.h"
2525
#ifdef _WIN32
26
+# include <winsock2.h>
2627
# include <ws2tcpip.h>
2728
#else
2829
# include <sys/socket.h>
2930
# include <netinet/in.h>
3031
# include <arpa/inet.h>
3132
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,11 @@
21 ** formatting function and its cousins, and routines to encode and
22 ** decode strings in HTML or HTTP.
23 */
24 #include "config.h"
25 #ifdef _WIN32
 
26 # include <ws2tcpip.h>
27 #else
28 # include <sys/socket.h>
29 # include <netinet/in.h>
30 # include <arpa/inet.h>
31
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,11 @@
21 ** formatting function and its cousins, and routines to encode and
22 ** decode strings in HTML or HTTP.
23 */
24 #include "config.h"
25 #ifdef _WIN32
26 # include <winsock2.h>
27 # include <ws2tcpip.h>
28 #else
29 # include <sys/socket.h>
30 # include <netinet/in.h>
31 # include <arpa/inet.h>
32
+2 -2
--- src/checkin.c
+++ src/checkin.c
@@ -316,11 +316,11 @@
316316
** unless overridden by the --abs-paths or --rel-paths options.
317317
**
318318
** Options:
319319
** --abs-paths Display absolute pathnames.
320320
** --dotfiles include files beginning with a dot (".")
321
-** --ignore <CSG> ignore files matching patterns from the
321
+** --ignore <CSG> ignore files matching patterns from the argument
322322
** --rel-paths Display pathnames relative to the current working
323323
** directory.
324324
**
325325
** See also: changes, clean, status
326326
*/
@@ -1144,11 +1144,11 @@
11441144
}
11451145
11461146
/* So that older versions of Fossil (that do not understand delta-
11471147
** manifest) can continue to use this repository, do not create a new
11481148
** delta-manifest unless this repository already contains one or more
1149
- ** delta-manifets, or unless the delta-manifest is explicitly requested
1149
+ ** delta-manifests, or unless the delta-manifest is explicitly requested
11501150
** by the --delta option.
11511151
*/
11521152
if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
11531153
forceBaseline = 1;
11541154
}
11551155
--- src/checkin.c
+++ src/checkin.c
@@ -316,11 +316,11 @@
316 ** unless overridden by the --abs-paths or --rel-paths options.
317 **
318 ** Options:
319 ** --abs-paths Display absolute pathnames.
320 ** --dotfiles include files beginning with a dot (".")
321 ** --ignore <CSG> ignore files matching patterns from the
322 ** --rel-paths Display pathnames relative to the current working
323 ** directory.
324 **
325 ** See also: changes, clean, status
326 */
@@ -1144,11 +1144,11 @@
1144 }
1145
1146 /* So that older versions of Fossil (that do not understand delta-
1147 ** manifest) can continue to use this repository, do not create a new
1148 ** delta-manifest unless this repository already contains one or more
1149 ** delta-manifets, or unless the delta-manifest is explicitly requested
1150 ** by the --delta option.
1151 */
1152 if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
1153 forceBaseline = 1;
1154 }
1155
--- src/checkin.c
+++ src/checkin.c
@@ -316,11 +316,11 @@
316 ** unless overridden by the --abs-paths or --rel-paths options.
317 **
318 ** Options:
319 ** --abs-paths Display absolute pathnames.
320 ** --dotfiles include files beginning with a dot (".")
321 ** --ignore <CSG> ignore files matching patterns from the argument
322 ** --rel-paths Display pathnames relative to the current working
323 ** directory.
324 **
325 ** See also: changes, clean, status
326 */
@@ -1144,11 +1144,11 @@
1144 }
1145
1146 /* So that older versions of Fossil (that do not understand delta-
1147 ** manifest) can continue to use this repository, do not create a new
1148 ** delta-manifest unless this repository already contains one or more
1149 ** delta-manifests, or unless the delta-manifest is explicitly requested
1150 ** by the --delta option.
1151 */
1152 if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
1153 forceBaseline = 1;
1154 }
1155
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1422,11 +1422,10 @@
14221422
extern "C" {
14231423
#endif
14241424
14251425
14261426
1427
-
14281427
/**
14291428
This type holds the "vtbl" for type-specific operations when
14301429
working with cson_value objects.
14311430
14321431
All cson_values of a given logical type share a pointer to a single
@@ -1524,13 +1523,11 @@
15241523
*/
15251524
#define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ }
15261525
/**
15271526
Empty-initialized cson_value object.
15281527
*/
1529
-extern const cson_value cson_value_empty;
1530
-
1531
-const cson_value cson_value_empty = cson_value_empty_m;
1528
+static const cson_value cson_value_empty = cson_value_empty_m;
15321529
const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m;
15331530
const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m;
15341531
const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m;
15351532
const cson_buffer cson_buffer_empty = cson_buffer_empty_m;
15361533
const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m;
@@ -1661,11 +1658,11 @@
16611658
{
16621659
if((m >= (void const *)&CSON_EMPTY_HOLDER)
16631660
&& ( m < (void const *)(&CSON_EMPTY_HOLDER+1)))
16641661
return 1;
16651662
else return
1666
- ((m > (void const *)&CSON_SPECIAL_VALUES[0])
1663
+ ((m >= (void const *)&CSON_SPECIAL_VALUES[0])
16671664
&& ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) )
16681665
? 1
16691666
: 0;
16701667
}
16711668
@@ -1711,13 +1708,13 @@
17111708
malloc/free funcs because fossil's lack of header files
17121709
means we would have to #include "main.c" here to
17131710
get the declarations.
17141711
*/
17151712
#if defined(CSON_FOSSIL_MODE)
1716
-void *fossil_malloc(size_t n);
1717
-void fossil_free(void *p);
1718
-void *fossil_realloc(void *p, size_t n);
1713
+extern void *fossil_malloc(size_t n);
1714
+extern void fossil_free(void *p);
1715
+extern void *fossil_realloc(void *p, size_t n);
17191716
# define CSON_MALLOC_IMPL fossil_malloc
17201717
# define CSON_FREE_IMPL fossil_free
17211718
# define CSON_REALLOC_IMPL fossil_realloc
17221719
#endif
17231720
@@ -4380,11 +4377,11 @@
43804377
arg MUST be a (cson_buffer*). This function appends n bytes at
43814378
position arg->used, expanding the buffer as necessary.
43824379
*/
43834380
static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
43844381
{
4385
- if( ! arg || (n<0) ) return cson_rc.ArgError;
4382
+ if( !arg ) return cson_rc.ArgError;
43864383
else if( ! n ) return 0;
43874384
else
43884385
{
43894386
cson_buffer * sb = (cson_buffer*)arg;
43904387
char const * data = (char const *)data_;
@@ -4500,11 +4497,10 @@
45004497
cson_value * cv = NULL;
45014498
cson_object const * curObj = obj;
45024499
enum { BufSize = 128 };
45034500
char buf[BufSize];
45044501
memset( buf, 0, BufSize );
4505
- rc = cson_rc.RangeError;
45064502
45074503
while( cson_next_token( &beg, sep, &end ) )
45084504
{
45094505
if( beg == end ) break;
45104506
else
45114507
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1422,11 +1422,10 @@
1422 extern "C" {
1423 #endif
1424
1425
1426
1427
1428 /**
1429 This type holds the "vtbl" for type-specific operations when
1430 working with cson_value objects.
1431
1432 All cson_values of a given logical type share a pointer to a single
@@ -1524,13 +1523,11 @@
1524 */
1525 #define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ }
1526 /**
1527 Empty-initialized cson_value object.
1528 */
1529 extern const cson_value cson_value_empty;
1530
1531 const cson_value cson_value_empty = cson_value_empty_m;
1532 const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m;
1533 const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m;
1534 const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m;
1535 const cson_buffer cson_buffer_empty = cson_buffer_empty_m;
1536 const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m;
@@ -1661,11 +1658,11 @@
1661 {
1662 if((m >= (void const *)&CSON_EMPTY_HOLDER)
1663 && ( m < (void const *)(&CSON_EMPTY_HOLDER+1)))
1664 return 1;
1665 else return
1666 ((m > (void const *)&CSON_SPECIAL_VALUES[0])
1667 && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) )
1668 ? 1
1669 : 0;
1670 }
1671
@@ -1711,13 +1708,13 @@
1711 malloc/free funcs because fossil's lack of header files
1712 means we would have to #include "main.c" here to
1713 get the declarations.
1714 */
1715 #if defined(CSON_FOSSIL_MODE)
1716 void *fossil_malloc(size_t n);
1717 void fossil_free(void *p);
1718 void *fossil_realloc(void *p, size_t n);
1719 # define CSON_MALLOC_IMPL fossil_malloc
1720 # define CSON_FREE_IMPL fossil_free
1721 # define CSON_REALLOC_IMPL fossil_realloc
1722 #endif
1723
@@ -4380,11 +4377,11 @@
4380 arg MUST be a (cson_buffer*). This function appends n bytes at
4381 position arg->used, expanding the buffer as necessary.
4382 */
4383 static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
4384 {
4385 if( ! arg || (n<0) ) return cson_rc.ArgError;
4386 else if( ! n ) return 0;
4387 else
4388 {
4389 cson_buffer * sb = (cson_buffer*)arg;
4390 char const * data = (char const *)data_;
@@ -4500,11 +4497,10 @@
4500 cson_value * cv = NULL;
4501 cson_object const * curObj = obj;
4502 enum { BufSize = 128 };
4503 char buf[BufSize];
4504 memset( buf, 0, BufSize );
4505 rc = cson_rc.RangeError;
4506
4507 while( cson_next_token( &beg, sep, &end ) )
4508 {
4509 if( beg == end ) break;
4510 else
4511
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1422,11 +1422,10 @@
1422 extern "C" {
1423 #endif
1424
1425
1426
 
1427 /**
1428 This type holds the "vtbl" for type-specific operations when
1429 working with cson_value objects.
1430
1431 All cson_values of a given logical type share a pointer to a single
@@ -1524,13 +1523,11 @@
1523 */
1524 #define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ }
1525 /**
1526 Empty-initialized cson_value object.
1527 */
1528 static const cson_value cson_value_empty = cson_value_empty_m;
 
 
1529 const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m;
1530 const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m;
1531 const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m;
1532 const cson_buffer cson_buffer_empty = cson_buffer_empty_m;
1533 const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m;
@@ -1661,11 +1658,11 @@
1658 {
1659 if((m >= (void const *)&CSON_EMPTY_HOLDER)
1660 && ( m < (void const *)(&CSON_EMPTY_HOLDER+1)))
1661 return 1;
1662 else return
1663 ((m >= (void const *)&CSON_SPECIAL_VALUES[0])
1664 && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) )
1665 ? 1
1666 : 0;
1667 }
1668
@@ -1711,13 +1708,13 @@
1708 malloc/free funcs because fossil's lack of header files
1709 means we would have to #include "main.c" here to
1710 get the declarations.
1711 */
1712 #if defined(CSON_FOSSIL_MODE)
1713 extern void *fossil_malloc(size_t n);
1714 extern void fossil_free(void *p);
1715 extern void *fossil_realloc(void *p, size_t n);
1716 # define CSON_MALLOC_IMPL fossil_malloc
1717 # define CSON_FREE_IMPL fossil_free
1718 # define CSON_REALLOC_IMPL fossil_realloc
1719 #endif
1720
@@ -4380,11 +4377,11 @@
4377 arg MUST be a (cson_buffer*). This function appends n bytes at
4378 position arg->used, expanding the buffer as necessary.
4379 */
4380 static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
4381 {
4382 if( !arg ) return cson_rc.ArgError;
4383 else if( ! n ) return 0;
4384 else
4385 {
4386 cson_buffer * sb = (cson_buffer*)arg;
4387 char const * data = (char const *)data_;
@@ -4500,11 +4497,10 @@
4497 cson_value * cv = NULL;
4498 cson_object const * curObj = obj;
4499 enum { BufSize = 128 };
4500 char buf[BufSize];
4501 memset( buf, 0, BufSize );
 
4502
4503 while( cson_next_token( &beg, sep, &end ) )
4504 {
4505 if( beg == end ) break;
4506 else
4507
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1236,11 +1236,14 @@
12361236
eventually either free the value using cson_value_free() or
12371237
inserting it into a container (array or object), which transfers
12381238
ownership to the container. See the cson_value class documentation
12391239
for more details.
12401240
1241
- Returns NULL on allocation error.
1241
+ Semantically speaking this function Returns NULL on allocation
1242
+ error, but the implementation never actually allocates for this
1243
+ case. Nonetheless, it must be treated as if it were an allocated
1244
+ value.
12421245
*/
12431246
cson_value * cson_value_new_bool( char v );
12441247
12451248
12461249
/**
@@ -1927,11 +1930,12 @@
19271930
modified.
19281931
19291932
buf->mem is owned by buf and must eventually be freed by passing an
19301933
n value of 0 to this function.
19311934
1932
- buf->used is never modified by this function.
1935
+ buf->used is never modified by this function unless n is 0, in which case
1936
+ it is reset.
19331937
*/
19341938
int cson_buffer_reserve( cson_buffer * buf, cson_size_t n );
19351939
19361940
/**
19371941
Fills all bytes of the given buffer with the given character.
19381942
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1236,11 +1236,14 @@
1236 eventually either free the value using cson_value_free() or
1237 inserting it into a container (array or object), which transfers
1238 ownership to the container. See the cson_value class documentation
1239 for more details.
1240
1241 Returns NULL on allocation error.
 
 
 
1242 */
1243 cson_value * cson_value_new_bool( char v );
1244
1245
1246 /**
@@ -1927,11 +1930,12 @@
1927 modified.
1928
1929 buf->mem is owned by buf and must eventually be freed by passing an
1930 n value of 0 to this function.
1931
1932 buf->used is never modified by this function.
 
1933 */
1934 int cson_buffer_reserve( cson_buffer * buf, cson_size_t n );
1935
1936 /**
1937 Fills all bytes of the given buffer with the given character.
1938
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1236,11 +1236,14 @@
1236 eventually either free the value using cson_value_free() or
1237 inserting it into a container (array or object), which transfers
1238 ownership to the container. See the cson_value class documentation
1239 for more details.
1240
1241 Semantically speaking this function Returns NULL on allocation
1242 error, but the implementation never actually allocates for this
1243 case. Nonetheless, it must be treated as if it were an allocated
1244 value.
1245 */
1246 cson_value * cson_value_new_bool( char v );
1247
1248
1249 /**
@@ -1927,11 +1930,12 @@
1930 modified.
1931
1932 buf->mem is owned by buf and must eventually be freed by passing an
1933 n value of 0 to this function.
1934
1935 buf->used is never modified by this function unless n is 0, in which case
1936 it is reset.
1937 */
1938 int cson_buffer_reserve( cson_buffer * buf, cson_size_t n );
1939
1940 /**
1941 Fills all bytes of the given buffer with the given character.
1942
+5 -1
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
16181618
16191619
/*
16201620
** This function registers auxiliary functions when the SQLite
16211621
** database connection is first established.
16221622
*/
1623
-LOCAL void db_connection_init(void){
1623
+void db_connection_init(void){
16241624
sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
16251625
sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
16261626
sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
16271627
sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
16281628
sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
16331633
g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
16341634
);
16351635
if( g.fSqlTrace ){
16361636
sqlite3_trace(g.db, db_sql_trace, 0);
16371637
}
1638
+ re_add_sql_func(g.db);
16381639
}
16391640
16401641
/*
16411642
** Return true if the string zVal represents "true" (or "false").
16421643
*/
@@ -2129,10 +2130,13 @@
21292130
** file named .fossil-settings/PROPERTY in the checked out files, if that
21302131
** file exists.
21312132
**
21322133
** The "unset" command clears a property setting.
21332134
**
2135
+**
2136
+** access-log If enabled, record successful and failed login attempts
2137
+** in the "accesslog" table. Default: off
21342138
**
21352139
** allow-symlinks If enabled, don't follow symlinks, and instead treat
21362140
** (versionable) them as symlinks on Unix. Has no effect on Windows
21372141
** (existing links in repository created on Unix become
21382142
** plain-text files with link destination path inside).
21392143
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
1618
1619 /*
1620 ** This function registers auxiliary functions when the SQLite
1621 ** database connection is first established.
1622 */
1623 LOCAL void db_connection_init(void){
1624 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1625 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1626 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1627 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1628 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
1633 g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1634 );
1635 if( g.fSqlTrace ){
1636 sqlite3_trace(g.db, db_sql_trace, 0);
1637 }
 
1638 }
1639
1640 /*
1641 ** Return true if the string zVal represents "true" (or "false").
1642 */
@@ -2129,10 +2130,13 @@
2129 ** file named .fossil-settings/PROPERTY in the checked out files, if that
2130 ** file exists.
2131 **
2132 ** The "unset" command clears a property setting.
2133 **
 
 
 
2134 **
2135 ** allow-symlinks If enabled, don't follow symlinks, and instead treat
2136 ** (versionable) them as symlinks on Unix. Has no effect on Windows
2137 ** (existing links in repository created on Unix become
2138 ** plain-text files with link destination path inside).
2139
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
1618
1619 /*
1620 ** This function registers auxiliary functions when the SQLite
1621 ** database connection is first established.
1622 */
1623 void db_connection_init(void){
1624 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1625 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1626 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1627 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1628 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
1633 g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1634 );
1635 if( g.fSqlTrace ){
1636 sqlite3_trace(g.db, db_sql_trace, 0);
1637 }
1638 re_add_sql_func(g.db);
1639 }
1640
1641 /*
1642 ** Return true if the string zVal represents "true" (or "false").
1643 */
@@ -2129,10 +2130,13 @@
2130 ** file named .fossil-settings/PROPERTY in the checked out files, if that
2131 ** file exists.
2132 **
2133 ** The "unset" command clears a property setting.
2134 **
2135 **
2136 ** access-log If enabled, record successful and failed login attempts
2137 ** in the "accesslog" table. Default: off
2138 **
2139 ** allow-symlinks If enabled, don't follow symlinks, and instead treat
2140 ** (versionable) them as symlinks on Unix. Has no effect on Windows
2141 ** (existing links in repository created on Unix become
2142 ** plain-text files with link destination path inside).
2143
+5 -1
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
16181618
16191619
/*
16201620
** This function registers auxiliary functions when the SQLite
16211621
** database connection is first established.
16221622
*/
1623
-LOCAL void db_connection_init(void){
1623
+void db_connection_init(void){
16241624
sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
16251625
sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
16261626
sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
16271627
sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
16281628
sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
16331633
g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
16341634
);
16351635
if( g.fSqlTrace ){
16361636
sqlite3_trace(g.db, db_sql_trace, 0);
16371637
}
1638
+ re_add_sql_func(g.db);
16381639
}
16391640
16401641
/*
16411642
** Return true if the string zVal represents "true" (or "false").
16421643
*/
@@ -2129,10 +2130,13 @@
21292130
** file named .fossil-settings/PROPERTY in the checked out files, if that
21302131
** file exists.
21312132
**
21322133
** The "unset" command clears a property setting.
21332134
**
2135
+**
2136
+** access-log If enabled, record successful and failed login attempts
2137
+** in the "accesslog" table. Default: off
21342138
**
21352139
** allow-symlinks If enabled, don't follow symlinks, and instead treat
21362140
** (versionable) them as symlinks on Unix. Has no effect on Windows
21372141
** (existing links in repository created on Unix become
21382142
** plain-text files with link destination path inside).
21392143
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
1618
1619 /*
1620 ** This function registers auxiliary functions when the SQLite
1621 ** database connection is first established.
1622 */
1623 LOCAL void db_connection_init(void){
1624 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1625 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1626 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1627 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1628 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
1633 g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1634 );
1635 if( g.fSqlTrace ){
1636 sqlite3_trace(g.db, db_sql_trace, 0);
1637 }
 
1638 }
1639
1640 /*
1641 ** Return true if the string zVal represents "true" (or "false").
1642 */
@@ -2129,10 +2130,13 @@
2129 ** file named .fossil-settings/PROPERTY in the checked out files, if that
2130 ** file exists.
2131 **
2132 ** The "unset" command clears a property setting.
2133 **
 
 
 
2134 **
2135 ** allow-symlinks If enabled, don't follow symlinks, and instead treat
2136 ** (versionable) them as symlinks on Unix. Has no effect on Windows
2137 ** (existing links in repository created on Unix become
2138 ** plain-text files with link destination path inside).
2139
--- src/db.c
+++ src/db.c
@@ -1618,11 +1618,11 @@
1618
1619 /*
1620 ** This function registers auxiliary functions when the SQLite
1621 ** database connection is first established.
1622 */
1623 void db_connection_init(void){
1624 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1625 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1626 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1627 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1628 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
@@ -1633,10 +1633,11 @@
1633 g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1634 );
1635 if( g.fSqlTrace ){
1636 sqlite3_trace(g.db, db_sql_trace, 0);
1637 }
1638 re_add_sql_func(g.db);
1639 }
1640
1641 /*
1642 ** Return true if the string zVal represents "true" (or "false").
1643 */
@@ -2129,10 +2130,13 @@
2130 ** file named .fossil-settings/PROPERTY in the checked out files, if that
2131 ** file exists.
2132 **
2133 ** The "unset" command clears a property setting.
2134 **
2135 **
2136 ** access-log If enabled, record successful and failed login attempts
2137 ** in the "accesslog" table. Default: off
2138 **
2139 ** allow-symlinks If enabled, don't follow symlinks, and instead treat
2140 ** (versionable) them as symlinks on Unix. Has no effect on Windows
2141 ** (existing links in repository created on Unix become
2142 ** plain-text files with link destination path inside).
2143
+267 -87
--- src/diff.c
+++ src/diff.c
@@ -23,11 +23,12 @@
2323
#include <assert.h>
2424
2525
2626
#if INTERFACE
2727
/*
28
-** Allowed flag parameters to the text_diff() and html_sbsdiff() functions:
28
+** Flag parameters to the text_diff() routine used to control the formatting
29
+** of the diff output.
2930
*/
3031
#define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
3132
#define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
3233
#define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */
3334
#define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */
@@ -37,10 +38,11 @@
3738
#define DIFF_HTML ((u64)0x10000000) /* Render for HTML */
3839
#define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */
3940
#define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */
4041
#define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
4142
#define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
43
+#define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */
4244
4345
/*
4446
** These error messages are shared in multiple locations. They are defined
4547
** here for consistency.
4648
*/
@@ -52,11 +54,11 @@
5254
5355
#define looks_like_binary(blob) (looks_like_utf8((blob)) == 0)
5456
#endif /* INTERFACE */
5557
5658
/*
57
-** Maximum length of a line in a text file, in bytes. (8192)
59
+** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
5860
*/
5961
#define LENGTH_MASK_SZ 13
6062
#define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
6163
6264
/*
@@ -116,10 +118,13 @@
116118
** more. If trailing whitespace is ignored, the "patch" command gets
117119
** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b]
118120
**
119121
** Return 0 if the file is binary or contains a line that is
120122
** too long.
123
+**
124
+** Profiling show that in most cases this routine consumes the bulk of
125
+** the CPU time on a diff.
121126
*/
122127
static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){
123128
int nLine, i, j, k, x;
124129
unsigned int h, h2;
125130
DLine *a;
@@ -407,34 +412,50 @@
407412
** Return true if two DLine elements are identical.
408413
*/
409414
static int same_dline(DLine *pA, DLine *pB){
410415
return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
411416
}
417
+
418
+/*
419
+** Return true if the regular expression *pRe matches any of the
420
+** N dlines
421
+*/
422
+static int re_dline_match(
423
+ ReCompiled *pRe, /* The regular expression to be matched */
424
+ DLine *aDLine, /* First of N DLines to compare against */
425
+ int N /* Number of DLines to check */
426
+){
427
+ while( N-- ){
428
+ if( re_match(pRe, (const unsigned char *)aDLine->z, LENGTH(aDLine)) ){
429
+ return 1;
430
+ }
431
+ aDLine++;
432
+ }
433
+ return 0;
434
+}
412435
413436
/*
414437
** Append a single line of context-diff output to pOut.
415438
*/
416439
static void appendDiffLine(
417440
Blob *pOut, /* Where to write the line of output */
418441
char cPrefix, /* One of " ", "+", or "-" */
419442
DLine *pLine, /* The line to be output */
420
- int html /* True if generating HTML. False for plain text */
443
+ int html, /* True if generating HTML. False for plain text */
444
+ ReCompiled *pRe /* Colorize only if line matches this Regex */
421445
){
422
- int i;
423446
blob_append(pOut, &cPrefix, 1);
424447
if( html ){
425448
char *zHtml;
426
- if( cPrefix=='+' ){
449
+ if( pRe && re_dline_match(pRe, pLine, 1)==0 ){
450
+ cPrefix = ' ';
451
+ }else if( cPrefix=='+' ){
427452
blob_append(pOut, "<span class=\"diffadd\">", -1);
428453
}else if( cPrefix=='-' ){
429454
blob_append(pOut, "<span class=\"diffrm\">", -1);
430455
}
431456
zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK));
432
- for(i=0; i<strlen(zHtml); i++){
433
- char c = zHtml[i];
434
- if( c=='\t' || c=='\r' || c=='\f' ) zHtml[i] = ' ';
435
- }
436457
blob_append(pOut, zHtml, -1);
437458
fossil_free(zHtml);
438459
if( cPrefix!=' ' ){
439460
blob_append(pOut, "</span>", -1);
440461
}
@@ -444,11 +465,11 @@
444465
blob_append(pOut, "\n", 1);
445466
}
446467
447468
/*
448469
** Add two line numbers to the beginning of an output line for a context
449
-** diff. One or of the other of the two numbers might be zero, which means
470
+** diff. One or the other of the two numbers might be zero, which means
450471
** to leave that number field blank. The "html" parameter means to format
451472
** the output for HTML.
452473
*/
453474
static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){
454475
if( html ) blob_append(pOut, "<span class=\"diffln\">", -1);
@@ -463,21 +484,19 @@
463484
blob_append(pOut, " ", 8);
464485
}
465486
if( html ) blob_append(pOut, "</span>", -1);
466487
}
467488
468
-
469489
/*
470490
** Given a raw diff p[] in which the p->aEdit[] array has been filled
471491
** in, compute a context diff into pOut.
472492
*/
473493
static void contextDiff(
474494
DContext *p, /* The difference */
475495
Blob *pOut, /* Output a context diff to here */
476
- int nContext, /* Number of lines of context */
477
- int showLn, /* Show line numbers */
478
- int html /* Render as HTML */
496
+ ReCompiled *pRe, /* Only show changes that match this regex */
497
+ u64 diffFlags /* Flags controlling the diff format */
479498
){
480499
DLine *A; /* Left side of the diff */
481500
DLine *B; /* Right side of the diff */
482501
int a = 0; /* Index of next line in A[] */
483502
int b = 0; /* Index of next line in B[] */
@@ -488,11 +507,18 @@
488507
int na, nb; /* Number of lines shown from A and B */
489508
int i, j; /* Loop counters */
490509
int m; /* Number of lines to output */
491510
int skip; /* Number of lines to skip */
492511
int nChunk = 0; /* Number of diff chunks seen so far */
512
+ int nContext; /* Number of lines of context */
513
+ int showLn; /* Show line numbers */
514
+ int html; /* Render as HTML */
515
+ int showDivider = 0; /* True to show the divider between diff blocks */
493516
517
+ nContext = diff_context_lines(diffFlags);
518
+ showLn = (diffFlags & DIFF_LINENO)!=0;
519
+ html = (diffFlags & DIFF_HTML)!=0;
494520
A = p->aFrom;
495521
B = p->aTo;
496522
R = p->aEdit;
497523
mxr = p->nEdit;
498524
while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
@@ -499,10 +525,35 @@
499525
for(r=0; r<mxr; r += 3*nr){
500526
/* Figure out how many triples to show in a single block */
501527
for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
502528
/* printf("r=%d nr=%d\n", r, nr); */
503529
530
+ /* If there is a regex, skip this block (generate no diff output)
531
+ ** if the regex matches or does not match both insert and delete.
532
+ ** Only display the block if one side matches but the other side does
533
+ ** not.
534
+ */
535
+ if( pRe ){
536
+ int hideBlock = 1;
537
+ int xa = a, xb = b;
538
+ for(i=0; hideBlock && i<nr; i++){
539
+ int c1, c2;
540
+ xa += R[r+i*3];
541
+ xb += R[r+i*3];
542
+ c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]);
543
+ c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]);
544
+ hideBlock = c1==c2;
545
+ xa += R[r+i*3+1];
546
+ xb += R[r+i*3+2];
547
+ }
548
+ if( hideBlock ){
549
+ a = xa;
550
+ b = xb;
551
+ continue;
552
+ }
553
+ }
554
+
504555
/* For the current block comprising nr triples, figure out
505556
** how many lines of A and B are to be displayed
506557
*/
507558
if( R[r]>nContext ){
508559
na = nb = nContext;
@@ -526,17 +577,18 @@
526577
na += R[r+i*3];
527578
nb += R[r+i*3];
528579
}
529580
530581
/* Show the header for this block, or if we are doing a modified
531
- ** context diff that contains line numbers, show the separate from
582
+ ** context diff that contains line numbers, show the separator from
532583
** the previous block.
533584
*/
534585
nChunk++;
535586
if( showLn ){
536
- if( r==0 ){
587
+ if( !showDivider ){
537588
/* Do not show a top divider */
589
+ showDivider = 1;
538590
}else if( html ){
539591
blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
540592
blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
541593
}else{
542594
blob_appendf(pOut, "%.80c\n", '.');
@@ -559,34 +611,36 @@
559611
a += skip;
560612
b += skip;
561613
m = R[r] - skip;
562614
for(j=0; j<m; j++){
563615
if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
564
- appendDiffLine(pOut, ' ', &A[a+j], html);
616
+ appendDiffLine(pOut, ' ', &A[a+j], html, 0);
565617
}
566618
a += m;
567619
b += m;
568620
569621
/* Show the differences */
570622
for(i=0; i<nr; i++){
571623
m = R[r+i*3+1];
572624
for(j=0; j<m; j++){
625
+ char cMark = '-';
573626
if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html);
574
- appendDiffLine(pOut, '-', &A[a+j], html);
627
+ if( pRe && re_dline_match(pRe, &A[a+j], 1)==0 ) cMark = ' ';
628
+ appendDiffLine(pOut, '-', &A[a+j], html, pRe);
575629
}
576630
a += m;
577631
m = R[r+i*3+2];
578632
for(j=0; j<m; j++){
579633
if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html);
580
- appendDiffLine(pOut, '+', &B[b+j], html);
634
+ appendDiffLine(pOut, '+', &B[b+j], html, pRe);
581635
}
582636
b += m;
583637
if( i<nr-1 ){
584638
m = R[r+i*3+3];
585639
for(j=0; j<m; j++){
586640
if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
587
- appendDiffLine(pOut, ' ', &B[b+j], html);
641
+ appendDiffLine(pOut, ' ', &B[b+j], html, 0);
588642
}
589643
b += m;
590644
a += m;
591645
}
592646
}
@@ -595,11 +649,11 @@
595649
assert( nr==i );
596650
m = R[r+nr*3];
597651
if( m>nContext ) m = nContext;
598652
for(j=0; j<m; j++){
599653
if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
600
- appendDiffLine(pOut, ' ', &B[b+j], html);
654
+ appendDiffLine(pOut, ' ', &B[b+j], html, 0);
601655
}
602656
}
603657
}
604658
605659
/*
@@ -615,10 +669,11 @@
615669
const char *zStart; /* A <span> tag */
616670
int iEnd; /* Write </span> prior to character iEnd */
617671
int iStart2; /* Write zStart2 prior to character iStart2 */
618672
const char *zStart2; /* A <span> tag */
619673
int iEnd2; /* Write </span> prior to character iEnd2 */
674
+ ReCompiled *pRe; /* Only colorize matching lines, if not NULL */
620675
};
621676
622677
/*
623678
** Flags for sbsWriteText()
624679
*/
@@ -640,13 +695,17 @@
640695
int k; /* Cursor position */
641696
int needEndSpan = 0;
642697
const char *zIn = pLine->z;
643698
char *z = &p->zLine[p->n];
644699
int w = p->width;
700
+ int colorize = p->escHtml;
701
+ if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
702
+ colorize = 0;
703
+ }
645704
for(i=j=k=0; k<w && i<n; i++, k++){
646705
char c = zIn[i];
647
- if( p->escHtml ){
706
+ if( colorize ){
648707
if( i==p->iStart ){
649708
int x = strlen(p->zStart);
650709
memcpy(z+j, p->zStart, x);
651710
j += x;
652711
needEndSpan = 1;
@@ -797,10 +856,41 @@
797856
}
798857
}
799858
}
800859
return rc;
801860
}
861
+
862
+/*
863
+** Try to shift iStart as far as possible to the left.
864
+*/
865
+static void sbsShiftLeft(SbsLine *p, const char *z){
866
+ int i, j;
867
+ while( (i=p->iStart)>0 && z[i-1]==z[i] ){
868
+ for(j=i+1; j<p->iEnd && z[j-1]==z[j]; j++){}
869
+ if( j<p->iEnd ) break;
870
+ p->iStart--;
871
+ p->iEnd--;
872
+ }
873
+}
874
+
875
+/*
876
+** Simplify iStart and iStart2:
877
+**
878
+** * If iStart is a null-change then move iStart2 into iStart
879
+** * Make sure any null-changes are in canonoical form.
880
+*/
881
+static void sbsSimplifyLine(SbsLine *p){
882
+ if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
883
+ if( p->iStart==p->iEnd ){
884
+ p->iStart = p->iStart2;
885
+ p->iEnd = p->iEnd2;
886
+ p->zStart = p->zStart2;
887
+ p->iStart2 = 0;
888
+ p->iEnd2 = 0;
889
+ }
890
+ if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
891
+}
802892
803893
/*
804894
** Write out lines that have been edited. Adjust the highlight to cover
805895
** only those parts of the line that actually changed.
806896
*/
@@ -891,41 +981,35 @@
891981
&& textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS)
892982
){
893983
sbsWriteLineno(p, lnLeft);
894984
p->iStart = nPrefix;
895985
p->iEnd = nPrefix + aLCS[0];
896
- p->zStart = aLCS[2]==0 ? zClassRm : zClassChng;
986
+ if( aLCS[2]==0 ){
987
+ sbsShiftLeft(p, pLeft->z);
988
+ p->zStart = zClassRm;
989
+ }else{
990
+ p->zStart = zClassChng;
991
+ }
897992
p->iStart2 = nPrefix + aLCS[1];
898993
p->iEnd2 = nLeft - nSuffix;
899994
p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng;
900
- if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
901
- if( p->iStart==p->iEnd ){
902
- p->iStart = p->iStart2;
903
- p->iEnd = p->iEnd2;
904
- p->zStart = p->zStart2;
905
- p->iStart2 = 0;
906
- p->iEnd2 = 0;
907
- }
908
- if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
995
+ sbsSimplifyLine(p);
909996
sbsWriteText(p, pLeft, SBS_PAD);
910997
sbsWrite(p, " | ", 3);
911998
sbsWriteLineno(p, lnRight);
912999
p->iStart = nPrefix;
9131000
p->iEnd = nPrefix + aLCS[2];
914
- p->zStart = aLCS[0]==0 ? zClassAdd : zClassChng;
1001
+ if( aLCS[0]==0 ){
1002
+ sbsShiftLeft(p, pRight->z);
1003
+ p->zStart = zClassAdd;
1004
+ }else{
1005
+ p->zStart = zClassChng;
1006
+ }
9151007
p->iStart2 = nPrefix + aLCS[3];
9161008
p->iEnd2 = nRight - nSuffix;
9171009
p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng;
918
- if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
919
- if( p->iStart==p->iEnd ){
920
- p->iStart = p->iStart2;
921
- p->iEnd = p->iEnd2;
922
- p->zStart = p->zStart2;
923
- p->iStart2 = 0;
924
- p->iEnd2 = 0;
925
- }
926
- if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
1010
+ sbsSimplifyLine(p);
9271011
sbsWriteText(p, pRight, SBS_NEWLINE);
9281012
return;
9291013
}
9301014
9311015
/* If all else fails, show a single big change between left and right */
@@ -1018,13 +1102,16 @@
10181102
**
10191103
** The return value is a buffer of unsigned characters, obtained from
10201104
** fossil_malloc(). (The caller needs to free the return value using
10211105
** fossil_free().) Entries in the returned array have values as follows:
10221106
**
1023
-** 1. Delete the next line of pLeft.
1024
-** 2. The next line of pLeft changes into the next line of pRight.
1025
-** 3. Insert the next line of pRight.
1107
+** 1. Delete the next line of pLeft.
1108
+** 2. Insert the next line of pRight.
1109
+** 3. The next line of pLeft changes into the next line of pRight.
1110
+** 4. Delete one line from pLeft and add one line to pRight.
1111
+**
1112
+** Values larger than three indicate better matches.
10261113
**
10271114
** The length of the returned array will be just large enough to cause
10281115
** all elements of pLeft and pRight to be consumed.
10291116
**
10301117
** Algorithm: Wagner's minimum edit-distance algorithm, modified by
@@ -1039,27 +1126,32 @@
10391126
){
10401127
int i, j, k; /* Loop counters */
10411128
int *a; /* One row of the Wagner matrix */
10421129
int *pToFree; /* Space that needs to be freed */
10431130
unsigned char *aM; /* Wagner result matrix */
1131
+ int nMatch, iMatch; /* Number of matching lines and match score */
1132
+ int mnLen; /* MIN(nLeft, nRight) */
1133
+ int mxLen; /* MAX(nLeft, nRight) */
10441134
int aBuf[100]; /* Stack space for a[] if nRight not to big */
10451135
10461136
aM = fossil_malloc( (nLeft+1)*(nRight+1) );
10471137
if( nLeft==0 ){
1048
- memset(aM, 3, nRight);
1138
+ memset(aM, 2, nRight);
10491139
return aM;
10501140
}
10511141
if( nRight==0 ){
10521142
memset(aM, 1, nLeft);
10531143
return aM;
10541144
}
10551145
10561146
/* This algorithm is O(N**2). So if N is too big, bail out with a
10571147
** simple (but stupid and ugly) result that doesn't take too long. */
1148
+ mnLen = nLeft<nRight ? nLeft : nRight;
10581149
if( nLeft*nRight>100000 ){
1059
- memset(aM, 3, nRight);
1060
- memset(aM+nRight, 1, nLeft);
1150
+ memset(aM, 4, mnLen);
1151
+ if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen);
1152
+ if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen);
10611153
return aM;
10621154
}
10631155
10641156
if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
10651157
pToFree = 0;
@@ -1068,30 +1160,30 @@
10681160
a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
10691161
}
10701162
10711163
/* Compute the best alignment */
10721164
for(i=0; i<=nRight; i++){
1073
- aM[i] = 3;
1165
+ aM[i] = 2;
10741166
a[i] = i*50;
10751167
}
10761168
aM[0] = 0;
10771169
for(j=1; j<=nLeft; j++){
10781170
int p = a[0];
10791171
a[0] = p+50;
10801172
aM[j*(nRight+1)] = 1;
10811173
for(i=1; i<=nRight; i++){
10821174
int m = a[i-1]+50;
1083
- int d = 3;
1175
+ int d = 2;
10841176
if( m>a[i]+50 ){
10851177
m = a[i]+50;
10861178
d = 1;
10871179
}
10881180
if( m>p ){
10891181
int score = match_dline(&aLeft[j-1], &aRight[i-1]);
1090
- if( (score<66 || (i<j+1 && i>j-1)) && m>p+score ){
1182
+ if( (score<=63 || (i<j+1 && i>j-1)) && m>p+score ){
10911183
m = p+score;
1092
- d = 2;
1184
+ d = 3 | score*4;
10931185
}
10941186
}
10951187
p = a[i];
10961188
a[i] = m;
10971189
aM[j*(nRight+1)+i] = d;
@@ -1100,28 +1192,50 @@
11001192
11011193
/* Compute the lowest-cost path back through the matrix */
11021194
i = nRight;
11031195
j = nLeft;
11041196
k = (nRight+1)*(nLeft+1)-1;
1197
+ nMatch = iMatch = 0;
11051198
while( i+j>0 ){
1106
- unsigned char c = aM[k--];
1107
- if( c==2 ){
1199
+ unsigned char c = aM[k];
1200
+ if( c>=3 ){
11081201
assert( i>0 && j>0 );
11091202
i--;
11101203
j--;
1111
- }else if( c==3 ){
1204
+ nMatch++;
1205
+ iMatch += (c>>2);
1206
+ aM[k] = 3;
1207
+ }else if( c==2 ){
11121208
assert( i>0 );
11131209
i--;
11141210
}else{
11151211
assert( j>0 );
11161212
j--;
11171213
}
1214
+ k--;
11181215
aM[k] = aM[j*(nRight+1)+i];
11191216
}
11201217
k++;
11211218
i = (nRight+1)*(nLeft+1) - k;
11221219
memmove(aM, &aM[k], i);
1220
+
1221
+ /* If:
1222
+ ** (1) the alignment is more than 25% longer than the longest side, and
1223
+ ** (2) the average match cost exceeds 15
1224
+ ** Then this is probably an alignment that will be difficult for humans
1225
+ ** to read. So instead, just show all of the right side inserted followed
1226
+ ** by all of the left side deleted.
1227
+ **
1228
+ ** The coefficients for conditions (1) and (2) above are determined by
1229
+ ** experimentation.
1230
+ */
1231
+ mxLen = nLeft>nRight ? nLeft : nRight;
1232
+ if( i*4>mxLen*5 && (nMatch==0 || iMatch/nMatch>15) ){
1233
+ memset(aM, 4, mnLen);
1234
+ if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen);
1235
+ if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen);
1236
+ }
11231237
11241238
/* Return the result */
11251239
fossil_free(pToFree);
11261240
return aM;
11271241
}
@@ -1141,13 +1255,12 @@
11411255
** in, compute a side-by-side diff into pOut.
11421256
*/
11431257
static void sbsDiff(
11441258
DContext *p, /* The computed diff */
11451259
Blob *pOut, /* Write the results here */
1146
- int nContext, /* Number of lines of context around each change */
1147
- int width, /* Width of each column of output */
1148
- int escHtml /* True to generate HTML output */
1260
+ ReCompiled *pRe, /* Only show changes that match this regex */
1261
+ u64 diffFlags /* Flags controlling the diff */
11491262
){
11501263
DLine *A; /* Left side of the diff */
11511264
DLine *B; /* Right side of the diff */
11521265
int a = 0; /* Index of next line in A[] */
11531266
int b = 0; /* Index of next line in B[] */
@@ -1159,16 +1272,20 @@
11591272
int i, j; /* Loop counters */
11601273
int m, ma, mb;/* Number of lines to output */
11611274
int skip; /* Number of lines to skip */
11621275
int nChunk = 0; /* Number of chunks of diff output seen so far */
11631276
SbsLine s; /* Output line buffer */
1277
+ int nContext; /* Lines of context above and below each change */
1278
+ int showDivider = 0; /* True to show the divider */
11641279
11651280
memset(&s, 0, sizeof(s));
1166
- s.zLine = fossil_malloc( 15*width + 200 );
1281
+ s.width = diff_width(diffFlags);
1282
+ s.zLine = fossil_malloc( 15*s.width + 200 );
11671283
if( s.zLine==0 ) return;
1168
- s.width = width;
1169
- s.escHtml = escHtml;
1284
+ nContext = diff_context_lines(diffFlags);
1285
+ s.escHtml = (diffFlags & DIFF_HTML)!=0;
1286
+ s.pRe = pRe;
11701287
s.iStart = -1;
11711288
s.iStart2 = 0;
11721289
s.iEnd = -1;
11731290
A = p->aFrom;
11741291
B = p->aTo;
@@ -1177,10 +1294,35 @@
11771294
while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
11781295
for(r=0; r<mxr; r += 3*nr){
11791296
/* Figure out how many triples to show in a single block */
11801297
for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
11811298
/* printf("r=%d nr=%d\n", r, nr); */
1299
+
1300
+ /* If there is a regex, skip this block (generate no diff output)
1301
+ ** if the regex matches or does not match both insert and delete.
1302
+ ** Only display the block if one side matches but the other side does
1303
+ ** not.
1304
+ */
1305
+ if( pRe ){
1306
+ int hideBlock = 1;
1307
+ int xa = a, xb = b;
1308
+ for(i=0; hideBlock && i<nr; i++){
1309
+ int c1, c2;
1310
+ xa += R[r+i*3];
1311
+ xb += R[r+i*3];
1312
+ c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]);
1313
+ c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]);
1314
+ hideBlock = c1==c2;
1315
+ xa += R[r+i*3+1];
1316
+ xb += R[r+i*3+2];
1317
+ }
1318
+ if( hideBlock ){
1319
+ a = xa;
1320
+ b = xb;
1321
+ continue;
1322
+ }
1323
+ }
11821324
11831325
/* For the current block comprising nr triples, figure out
11841326
** how many lines of A and B are to be displayed
11851327
*/
11861328
if( R[r]>nContext ){
@@ -1205,20 +1347,21 @@
12051347
na += R[r+i*3];
12061348
nb += R[r+i*3];
12071349
}
12081350
12091351
/* Draw the separator between blocks */
1210
- if( r>0 ){
1211
- if( escHtml ){
1352
+ if( showDivider ){
1353
+ if( s.escHtml ){
12121354
blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n",
1213
- width*2+16, '.');
1355
+ s.width*2+16, '.');
12141356
}else{
1215
- blob_appendf(pOut, "%.*c\n", width*2+16, '.');
1357
+ blob_appendf(pOut, "%.*c\n", s.width*2+16, '.');
12161358
}
12171359
}
1360
+ showDivider = 1;
12181361
nChunk++;
1219
- if( escHtml ){
1362
+ if( s.escHtml ){
12201363
blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
12211364
}
12221365
12231366
/* Show the initial common area */
12241367
a += skip;
@@ -1254,38 +1397,41 @@
12541397
}
12551398
12561399
alignment = sbsAlignment(&A[a], ma, &B[b], mb);
12571400
for(j=0; ma+mb>0; j++){
12581401
if( alignment[j]==1 ){
1402
+ /* Delete one line from the left */
12591403
s.n = 0;
12601404
sbsWriteLineno(&s, a);
12611405
s.iStart = 0;
12621406
s.zStart = "<span class=\"diffrm\">";
12631407
s.iEnd = s.width;
12641408
sbsWriteText(&s, &A[a], SBS_PAD);
1265
- if( escHtml ){
1409
+ if( s.escHtml ){
12661410
sbsWrite(&s, " &lt;\n", 6);
12671411
}else{
12681412
sbsWrite(&s, " <\n", 3);
12691413
}
12701414
blob_append(pOut, s.zLine, s.n);
12711415
assert( ma>0 );
12721416
ma--;
12731417
a++;
1274
- }else if( alignment[j]==2 ){
1418
+ }else if( alignment[j]==3 ){
1419
+ /* The left line is changed into the right line */
12751420
s.n = 0;
12761421
sbsWriteLineChange(&s, &A[a], a, &B[b], b);
12771422
blob_append(pOut, s.zLine, s.n);
12781423
assert( ma>0 && mb>0 );
12791424
ma--;
12801425
mb--;
12811426
a++;
12821427
b++;
1283
- }else{
1428
+ }else if( alignment[j]==2 ){
1429
+ /* Insert one line on the right */
12841430
s.n = 0;
1285
- sbsWriteSpace(&s, width + 7);
1286
- if( escHtml ){
1431
+ sbsWriteSpace(&s, s.width + 7);
1432
+ if( s.escHtml ){
12871433
sbsWrite(&s, " &gt; ", 6);
12881434
}else{
12891435
sbsWrite(&s, " > ", 3);
12901436
}
12911437
sbsWriteLineno(&s, b);
@@ -1295,11 +1441,31 @@
12951441
sbsWriteText(&s, &B[b], SBS_NEWLINE);
12961442
blob_append(pOut, s.zLine, s.n);
12971443
assert( mb>0 );
12981444
mb--;
12991445
b++;
1446
+ }else{
1447
+ /* Delete from the left and insert on the right */
1448
+ s.n = 0;
1449
+ sbsWriteLineno(&s, a);
1450
+ s.iStart = 0;
1451
+ s.zStart = "<span class=\"diffrm\">";
1452
+ s.iEnd = s.width;
1453
+ sbsWriteText(&s, &A[a], SBS_PAD);
1454
+ sbsWrite(&s, " | ", 3);
1455
+ sbsWriteLineno(&s, b);
1456
+ s.iStart = 0;
1457
+ s.zStart = "<span class=\"diffadd\">";
1458
+ s.iEnd = s.width;
1459
+ sbsWriteText(&s, &B[b], SBS_NEWLINE);
1460
+ blob_append(pOut, s.zLine, s.n);
1461
+ ma--;
1462
+ mb--;
1463
+ a++;
1464
+ b++;
13001465
}
1466
+
13011467
}
13021468
fossil_free(alignment);
13031469
if( i<nr-1 ){
13041470
m = R[r+i*3+3];
13051471
for(j=0; j<m; j++){
@@ -1723,11 +1889,11 @@
17231889
** Extract the number of lines of context from diffFlags. Supply an
17241890
** appropriate default if no context width is specified.
17251891
*/
17261892
int diff_context_lines(u64 diffFlags){
17271893
int n = diffFlags & DIFF_CONTEXT_MASK;
1728
- if( n==0 ) n = 5;
1894
+ if( n==0 && (diffFlags & DIFF_CONTEXT_EX)==0 ) n = 5;
17291895
return n;
17301896
}
17311897
17321898
/*
17331899
** Extract the width of columns for side-by-side diff. Supply an
@@ -1755,22 +1921,21 @@
17551921
*/
17561922
int *text_diff(
17571923
Blob *pA_Blob, /* FROM file */
17581924
Blob *pB_Blob, /* TO file */
17591925
Blob *pOut, /* Write diff here if not NULL */
1926
+ ReCompiled *pRe, /* Only output changes where this Regexp matches */
17601927
u64 diffFlags /* DIFF_* flags defined above */
17611928
){
17621929
int ignoreEolWs; /* Ignore whitespace at the end of lines */
1763
- int nContext; /* Amount of context to display */
17641930
DContext c;
17651931
17661932
if( diffFlags & DIFF_INVERT ){
17671933
Blob *pTemp = pA_Blob;
17681934
pA_Blob = pB_Blob;
17691935
pB_Blob = pTemp;
17701936
}
1771
- nContext = diff_context_lines(diffFlags);
17721937
ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
17731938
17741939
/* Prepare the input files */
17751940
memset(&c, 0, sizeof(c));
17761941
c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
@@ -1790,17 +1955,14 @@
17901955
diff_all(&c);
17911956
if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);
17921957
17931958
if( pOut ){
17941959
/* Compute a context or side-by-side diff into pOut */
1795
- int escHtml = (diffFlags & DIFF_HTML)!=0;
17961960
if( diffFlags & DIFF_SIDEBYSIDE ){
1797
- int width = diff_width(diffFlags);
1798
- sbsDiff(&c, pOut, nContext, width, escHtml);
1961
+ sbsDiff(&c, pOut, pRe, diffFlags);
17991962
}else{
1800
- int showLn = (diffFlags & DIFF_LINENO)!=0;
1801
- contextDiff(&c, pOut, nContext, showLn, escHtml);
1963
+ contextDiff(&c, pOut, pRe, diffFlags);
18021964
}
18031965
fossil_free(c.aFrom);
18041966
fossil_free(c.aTo);
18051967
fossil_free(c.aEdit);
18061968
return 0;
@@ -1826,19 +1988,19 @@
18261988
** --noopt Disable optimization DIFF_NOOPT
18271989
** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
18281990
** --unified Unified diff. ~DIFF_SIDEBYSIDE
18291991
** --width|-W N N character lines. DIFF_WIDTH_MASK
18301992
*/
1831
-int diff_options(void){
1993
+u64 diff_options(void){
18321994
u64 diffFlags = 0;
18331995
const char *z;
18341996
int f;
18351997
if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
18361998
if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE;
1837
- if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){
1999
+ if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){
18382000
if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
1839
- diffFlags |= f;
2001
+ diffFlags |= f + DIFF_CONTEXT_EX;
18402002
}
18412003
if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
18422004
f *= DIFF_CONTEXT_MASK+1;
18432005
if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
18442006
diffFlags |= f;
@@ -1863,34 +2025,52 @@
18632025
if( g.argc<4 ) usage("FILE1 FILE2 ...");
18642026
blob_read_from_file(&a, g.argv[2]);
18652027
for(i=3; i<g.argc; i++){
18662028
if( i>3 ) fossil_print("-------------------------------\n");
18672029
blob_read_from_file(&b, g.argv[i]);
1868
- R = text_diff(&a, &b, 0, diffFlags);
2030
+ R = text_diff(&a, &b, 0, 0, diffFlags);
18692031
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
18702032
fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
18712033
}
18722034
/* free(R); */
18732035
blob_reset(&b);
18742036
}
18752037
}
18762038
18772039
/*
1878
-** COMMAND: test-udiff
2040
+** COMMAND: test-diff
2041
+**
2042
+** Usage: %fossil [options] FILE1 FILE2
18792043
**
18802044
** Print the difference between two files. The usual diff options apply.
18812045
*/
1882
-void test_udiff_cmd(void){
2046
+void test_diff_cmd(void){
18832047
Blob a, b, out;
1884
- u64 diffFlag = diff_options();
2048
+ u64 diffFlag;
2049
+ const char *zRe; /* Regex filter for diff output */
2050
+ ReCompiled *pRe = 0; /* Regex filter for diff output */
18852051
2052
+ if( find_option("tk",0,0)!=0 ){
2053
+ diff_tk("test-diff", 2);
2054
+ return;
2055
+ }
2056
+ find_option("i",0,0);
2057
+ zRe = find_option("regexp","e",1);
2058
+ if( zRe ){
2059
+ const char *zErr = re_compile(&pRe, zRe, 0);
2060
+ if( zErr ) fossil_fatal("regex error: %s", zErr);
2061
+ }
2062
+ diffFlag = diff_options();
2063
+ verify_all_options();
18862064
if( g.argc!=4 ) usage("FILE1 FILE2");
2065
+ diff_print_filenames(g.argv[2], g.argv[3], diffFlag);
18872066
blob_read_from_file(&a, g.argv[2]);
18882067
blob_read_from_file(&b, g.argv[3]);
18892068
blob_zero(&out);
1890
- text_diff(&a, &b, &out, diffFlag);
2069
+ text_diff(&a, &b, &out, pRe, diffFlag);
18912070
blob_write_to_file(&out, "-");
2071
+ re_free(pRe);
18922072
}
18932073
18942074
/**************************************************************************
18952075
** The basic difference engine is above. What follows is the annotation
18962076
** engine. Both are in the same file since they share many components.
18972077
--- src/diff.c
+++ src/diff.c
@@ -23,11 +23,12 @@
23 #include <assert.h>
24
25
26 #if INTERFACE
27 /*
28 ** Allowed flag parameters to the text_diff() and html_sbsdiff() functions:
 
29 */
30 #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
31 #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
32 #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */
33 #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */
@@ -37,10 +38,11 @@
37 #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */
38 #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */
39 #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */
40 #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
41 #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
 
42
43 /*
44 ** These error messages are shared in multiple locations. They are defined
45 ** here for consistency.
46 */
@@ -52,11 +54,11 @@
52
53 #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0)
54 #endif /* INTERFACE */
55
56 /*
57 ** Maximum length of a line in a text file, in bytes. (8192)
58 */
59 #define LENGTH_MASK_SZ 13
60 #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
61
62 /*
@@ -116,10 +118,13 @@
116 ** more. If trailing whitespace is ignored, the "patch" command gets
117 ** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b]
118 **
119 ** Return 0 if the file is binary or contains a line that is
120 ** too long.
 
 
 
121 */
122 static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){
123 int nLine, i, j, k, x;
124 unsigned int h, h2;
125 DLine *a;
@@ -407,34 +412,50 @@
407 ** Return true if two DLine elements are identical.
408 */
409 static int same_dline(DLine *pA, DLine *pB){
410 return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
411 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
413 /*
414 ** Append a single line of context-diff output to pOut.
415 */
416 static void appendDiffLine(
417 Blob *pOut, /* Where to write the line of output */
418 char cPrefix, /* One of " ", "+", or "-" */
419 DLine *pLine, /* The line to be output */
420 int html /* True if generating HTML. False for plain text */
 
421 ){
422 int i;
423 blob_append(pOut, &cPrefix, 1);
424 if( html ){
425 char *zHtml;
426 if( cPrefix=='+' ){
 
 
427 blob_append(pOut, "<span class=\"diffadd\">", -1);
428 }else if( cPrefix=='-' ){
429 blob_append(pOut, "<span class=\"diffrm\">", -1);
430 }
431 zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK));
432 for(i=0; i<strlen(zHtml); i++){
433 char c = zHtml[i];
434 if( c=='\t' || c=='\r' || c=='\f' ) zHtml[i] = ' ';
435 }
436 blob_append(pOut, zHtml, -1);
437 fossil_free(zHtml);
438 if( cPrefix!=' ' ){
439 blob_append(pOut, "</span>", -1);
440 }
@@ -444,11 +465,11 @@
444 blob_append(pOut, "\n", 1);
445 }
446
447 /*
448 ** Add two line numbers to the beginning of an output line for a context
449 ** diff. One or of the other of the two numbers might be zero, which means
450 ** to leave that number field blank. The "html" parameter means to format
451 ** the output for HTML.
452 */
453 static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){
454 if( html ) blob_append(pOut, "<span class=\"diffln\">", -1);
@@ -463,21 +484,19 @@
463 blob_append(pOut, " ", 8);
464 }
465 if( html ) blob_append(pOut, "</span>", -1);
466 }
467
468
469 /*
470 ** Given a raw diff p[] in which the p->aEdit[] array has been filled
471 ** in, compute a context diff into pOut.
472 */
473 static void contextDiff(
474 DContext *p, /* The difference */
475 Blob *pOut, /* Output a context diff to here */
476 int nContext, /* Number of lines of context */
477 int showLn, /* Show line numbers */
478 int html /* Render as HTML */
479 ){
480 DLine *A; /* Left side of the diff */
481 DLine *B; /* Right side of the diff */
482 int a = 0; /* Index of next line in A[] */
483 int b = 0; /* Index of next line in B[] */
@@ -488,11 +507,18 @@
488 int na, nb; /* Number of lines shown from A and B */
489 int i, j; /* Loop counters */
490 int m; /* Number of lines to output */
491 int skip; /* Number of lines to skip */
492 int nChunk = 0; /* Number of diff chunks seen so far */
 
 
 
 
493
 
 
 
494 A = p->aFrom;
495 B = p->aTo;
496 R = p->aEdit;
497 mxr = p->nEdit;
498 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
@@ -499,10 +525,35 @@
499 for(r=0; r<mxr; r += 3*nr){
500 /* Figure out how many triples to show in a single block */
501 for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
502 /* printf("r=%d nr=%d\n", r, nr); */
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504 /* For the current block comprising nr triples, figure out
505 ** how many lines of A and B are to be displayed
506 */
507 if( R[r]>nContext ){
508 na = nb = nContext;
@@ -526,17 +577,18 @@
526 na += R[r+i*3];
527 nb += R[r+i*3];
528 }
529
530 /* Show the header for this block, or if we are doing a modified
531 ** context diff that contains line numbers, show the separate from
532 ** the previous block.
533 */
534 nChunk++;
535 if( showLn ){
536 if( r==0 ){
537 /* Do not show a top divider */
 
538 }else if( html ){
539 blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
540 blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
541 }else{
542 blob_appendf(pOut, "%.80c\n", '.');
@@ -559,34 +611,36 @@
559 a += skip;
560 b += skip;
561 m = R[r] - skip;
562 for(j=0; j<m; j++){
563 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
564 appendDiffLine(pOut, ' ', &A[a+j], html);
565 }
566 a += m;
567 b += m;
568
569 /* Show the differences */
570 for(i=0; i<nr; i++){
571 m = R[r+i*3+1];
572 for(j=0; j<m; j++){
 
573 if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html);
574 appendDiffLine(pOut, '-', &A[a+j], html);
 
575 }
576 a += m;
577 m = R[r+i*3+2];
578 for(j=0; j<m; j++){
579 if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html);
580 appendDiffLine(pOut, '+', &B[b+j], html);
581 }
582 b += m;
583 if( i<nr-1 ){
584 m = R[r+i*3+3];
585 for(j=0; j<m; j++){
586 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
587 appendDiffLine(pOut, ' ', &B[b+j], html);
588 }
589 b += m;
590 a += m;
591 }
592 }
@@ -595,11 +649,11 @@
595 assert( nr==i );
596 m = R[r+nr*3];
597 if( m>nContext ) m = nContext;
598 for(j=0; j<m; j++){
599 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
600 appendDiffLine(pOut, ' ', &B[b+j], html);
601 }
602 }
603 }
604
605 /*
@@ -615,10 +669,11 @@
615 const char *zStart; /* A <span> tag */
616 int iEnd; /* Write </span> prior to character iEnd */
617 int iStart2; /* Write zStart2 prior to character iStart2 */
618 const char *zStart2; /* A <span> tag */
619 int iEnd2; /* Write </span> prior to character iEnd2 */
 
620 };
621
622 /*
623 ** Flags for sbsWriteText()
624 */
@@ -640,13 +695,17 @@
640 int k; /* Cursor position */
641 int needEndSpan = 0;
642 const char *zIn = pLine->z;
643 char *z = &p->zLine[p->n];
644 int w = p->width;
 
 
 
 
645 for(i=j=k=0; k<w && i<n; i++, k++){
646 char c = zIn[i];
647 if( p->escHtml ){
648 if( i==p->iStart ){
649 int x = strlen(p->zStart);
650 memcpy(z+j, p->zStart, x);
651 j += x;
652 needEndSpan = 1;
@@ -797,10 +856,41 @@
797 }
798 }
799 }
800 return rc;
801 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
803 /*
804 ** Write out lines that have been edited. Adjust the highlight to cover
805 ** only those parts of the line that actually changed.
806 */
@@ -891,41 +981,35 @@
891 && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS)
892 ){
893 sbsWriteLineno(p, lnLeft);
894 p->iStart = nPrefix;
895 p->iEnd = nPrefix + aLCS[0];
896 p->zStart = aLCS[2]==0 ? zClassRm : zClassChng;
 
 
 
 
 
897 p->iStart2 = nPrefix + aLCS[1];
898 p->iEnd2 = nLeft - nSuffix;
899 p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng;
900 if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
901 if( p->iStart==p->iEnd ){
902 p->iStart = p->iStart2;
903 p->iEnd = p->iEnd2;
904 p->zStart = p->zStart2;
905 p->iStart2 = 0;
906 p->iEnd2 = 0;
907 }
908 if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
909 sbsWriteText(p, pLeft, SBS_PAD);
910 sbsWrite(p, " | ", 3);
911 sbsWriteLineno(p, lnRight);
912 p->iStart = nPrefix;
913 p->iEnd = nPrefix + aLCS[2];
914 p->zStart = aLCS[0]==0 ? zClassAdd : zClassChng;
 
 
 
 
 
915 p->iStart2 = nPrefix + aLCS[3];
916 p->iEnd2 = nRight - nSuffix;
917 p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng;
918 if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
919 if( p->iStart==p->iEnd ){
920 p->iStart = p->iStart2;
921 p->iEnd = p->iEnd2;
922 p->zStart = p->zStart2;
923 p->iStart2 = 0;
924 p->iEnd2 = 0;
925 }
926 if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
927 sbsWriteText(p, pRight, SBS_NEWLINE);
928 return;
929 }
930
931 /* If all else fails, show a single big change between left and right */
@@ -1018,13 +1102,16 @@
1018 **
1019 ** The return value is a buffer of unsigned characters, obtained from
1020 ** fossil_malloc(). (The caller needs to free the return value using
1021 ** fossil_free().) Entries in the returned array have values as follows:
1022 **
1023 ** 1. Delete the next line of pLeft.
1024 ** 2. The next line of pLeft changes into the next line of pRight.
1025 ** 3. Insert the next line of pRight.
 
 
 
1026 **
1027 ** The length of the returned array will be just large enough to cause
1028 ** all elements of pLeft and pRight to be consumed.
1029 **
1030 ** Algorithm: Wagner's minimum edit-distance algorithm, modified by
@@ -1039,27 +1126,32 @@
1039 ){
1040 int i, j, k; /* Loop counters */
1041 int *a; /* One row of the Wagner matrix */
1042 int *pToFree; /* Space that needs to be freed */
1043 unsigned char *aM; /* Wagner result matrix */
 
 
 
1044 int aBuf[100]; /* Stack space for a[] if nRight not to big */
1045
1046 aM = fossil_malloc( (nLeft+1)*(nRight+1) );
1047 if( nLeft==0 ){
1048 memset(aM, 3, nRight);
1049 return aM;
1050 }
1051 if( nRight==0 ){
1052 memset(aM, 1, nLeft);
1053 return aM;
1054 }
1055
1056 /* This algorithm is O(N**2). So if N is too big, bail out with a
1057 ** simple (but stupid and ugly) result that doesn't take too long. */
 
1058 if( nLeft*nRight>100000 ){
1059 memset(aM, 3, nRight);
1060 memset(aM+nRight, 1, nLeft);
 
1061 return aM;
1062 }
1063
1064 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1065 pToFree = 0;
@@ -1068,30 +1160,30 @@
1068 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1069 }
1070
1071 /* Compute the best alignment */
1072 for(i=0; i<=nRight; i++){
1073 aM[i] = 3;
1074 a[i] = i*50;
1075 }
1076 aM[0] = 0;
1077 for(j=1; j<=nLeft; j++){
1078 int p = a[0];
1079 a[0] = p+50;
1080 aM[j*(nRight+1)] = 1;
1081 for(i=1; i<=nRight; i++){
1082 int m = a[i-1]+50;
1083 int d = 3;
1084 if( m>a[i]+50 ){
1085 m = a[i]+50;
1086 d = 1;
1087 }
1088 if( m>p ){
1089 int score = match_dline(&aLeft[j-1], &aRight[i-1]);
1090 if( (score<66 || (i<j+1 && i>j-1)) && m>p+score ){
1091 m = p+score;
1092 d = 2;
1093 }
1094 }
1095 p = a[i];
1096 a[i] = m;
1097 aM[j*(nRight+1)+i] = d;
@@ -1100,28 +1192,50 @@
1100
1101 /* Compute the lowest-cost path back through the matrix */
1102 i = nRight;
1103 j = nLeft;
1104 k = (nRight+1)*(nLeft+1)-1;
 
1105 while( i+j>0 ){
1106 unsigned char c = aM[k--];
1107 if( c==2 ){
1108 assert( i>0 && j>0 );
1109 i--;
1110 j--;
1111 }else if( c==3 ){
 
 
 
1112 assert( i>0 );
1113 i--;
1114 }else{
1115 assert( j>0 );
1116 j--;
1117 }
 
1118 aM[k] = aM[j*(nRight+1)+i];
1119 }
1120 k++;
1121 i = (nRight+1)*(nLeft+1) - k;
1122 memmove(aM, &aM[k], i);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1123
1124 /* Return the result */
1125 fossil_free(pToFree);
1126 return aM;
1127 }
@@ -1141,13 +1255,12 @@
1141 ** in, compute a side-by-side diff into pOut.
1142 */
1143 static void sbsDiff(
1144 DContext *p, /* The computed diff */
1145 Blob *pOut, /* Write the results here */
1146 int nContext, /* Number of lines of context around each change */
1147 int width, /* Width of each column of output */
1148 int escHtml /* True to generate HTML output */
1149 ){
1150 DLine *A; /* Left side of the diff */
1151 DLine *B; /* Right side of the diff */
1152 int a = 0; /* Index of next line in A[] */
1153 int b = 0; /* Index of next line in B[] */
@@ -1159,16 +1272,20 @@
1159 int i, j; /* Loop counters */
1160 int m, ma, mb;/* Number of lines to output */
1161 int skip; /* Number of lines to skip */
1162 int nChunk = 0; /* Number of chunks of diff output seen so far */
1163 SbsLine s; /* Output line buffer */
 
 
1164
1165 memset(&s, 0, sizeof(s));
1166 s.zLine = fossil_malloc( 15*width + 200 );
 
1167 if( s.zLine==0 ) return;
1168 s.width = width;
1169 s.escHtml = escHtml;
 
1170 s.iStart = -1;
1171 s.iStart2 = 0;
1172 s.iEnd = -1;
1173 A = p->aFrom;
1174 B = p->aTo;
@@ -1177,10 +1294,35 @@
1177 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
1178 for(r=0; r<mxr; r += 3*nr){
1179 /* Figure out how many triples to show in a single block */
1180 for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
1181 /* printf("r=%d nr=%d\n", r, nr); */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
1183 /* For the current block comprising nr triples, figure out
1184 ** how many lines of A and B are to be displayed
1185 */
1186 if( R[r]>nContext ){
@@ -1205,20 +1347,21 @@
1205 na += R[r+i*3];
1206 nb += R[r+i*3];
1207 }
1208
1209 /* Draw the separator between blocks */
1210 if( r>0 ){
1211 if( escHtml ){
1212 blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n",
1213 width*2+16, '.');
1214 }else{
1215 blob_appendf(pOut, "%.*c\n", width*2+16, '.');
1216 }
1217 }
 
1218 nChunk++;
1219 if( escHtml ){
1220 blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
1221 }
1222
1223 /* Show the initial common area */
1224 a += skip;
@@ -1254,38 +1397,41 @@
1254 }
1255
1256 alignment = sbsAlignment(&A[a], ma, &B[b], mb);
1257 for(j=0; ma+mb>0; j++){
1258 if( alignment[j]==1 ){
 
1259 s.n = 0;
1260 sbsWriteLineno(&s, a);
1261 s.iStart = 0;
1262 s.zStart = "<span class=\"diffrm\">";
1263 s.iEnd = s.width;
1264 sbsWriteText(&s, &A[a], SBS_PAD);
1265 if( escHtml ){
1266 sbsWrite(&s, " &lt;\n", 6);
1267 }else{
1268 sbsWrite(&s, " <\n", 3);
1269 }
1270 blob_append(pOut, s.zLine, s.n);
1271 assert( ma>0 );
1272 ma--;
1273 a++;
1274 }else if( alignment[j]==2 ){
 
1275 s.n = 0;
1276 sbsWriteLineChange(&s, &A[a], a, &B[b], b);
1277 blob_append(pOut, s.zLine, s.n);
1278 assert( ma>0 && mb>0 );
1279 ma--;
1280 mb--;
1281 a++;
1282 b++;
1283 }else{
 
1284 s.n = 0;
1285 sbsWriteSpace(&s, width + 7);
1286 if( escHtml ){
1287 sbsWrite(&s, " &gt; ", 6);
1288 }else{
1289 sbsWrite(&s, " > ", 3);
1290 }
1291 sbsWriteLineno(&s, b);
@@ -1295,11 +1441,31 @@
1295 sbsWriteText(&s, &B[b], SBS_NEWLINE);
1296 blob_append(pOut, s.zLine, s.n);
1297 assert( mb>0 );
1298 mb--;
1299 b++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1300 }
 
1301 }
1302 fossil_free(alignment);
1303 if( i<nr-1 ){
1304 m = R[r+i*3+3];
1305 for(j=0; j<m; j++){
@@ -1723,11 +1889,11 @@
1723 ** Extract the number of lines of context from diffFlags. Supply an
1724 ** appropriate default if no context width is specified.
1725 */
1726 int diff_context_lines(u64 diffFlags){
1727 int n = diffFlags & DIFF_CONTEXT_MASK;
1728 if( n==0 ) n = 5;
1729 return n;
1730 }
1731
1732 /*
1733 ** Extract the width of columns for side-by-side diff. Supply an
@@ -1755,22 +1921,21 @@
1755 */
1756 int *text_diff(
1757 Blob *pA_Blob, /* FROM file */
1758 Blob *pB_Blob, /* TO file */
1759 Blob *pOut, /* Write diff here if not NULL */
 
1760 u64 diffFlags /* DIFF_* flags defined above */
1761 ){
1762 int ignoreEolWs; /* Ignore whitespace at the end of lines */
1763 int nContext; /* Amount of context to display */
1764 DContext c;
1765
1766 if( diffFlags & DIFF_INVERT ){
1767 Blob *pTemp = pA_Blob;
1768 pA_Blob = pB_Blob;
1769 pB_Blob = pTemp;
1770 }
1771 nContext = diff_context_lines(diffFlags);
1772 ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
1773
1774 /* Prepare the input files */
1775 memset(&c, 0, sizeof(c));
1776 c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
@@ -1790,17 +1955,14 @@
1790 diff_all(&c);
1791 if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);
1792
1793 if( pOut ){
1794 /* Compute a context or side-by-side diff into pOut */
1795 int escHtml = (diffFlags & DIFF_HTML)!=0;
1796 if( diffFlags & DIFF_SIDEBYSIDE ){
1797 int width = diff_width(diffFlags);
1798 sbsDiff(&c, pOut, nContext, width, escHtml);
1799 }else{
1800 int showLn = (diffFlags & DIFF_LINENO)!=0;
1801 contextDiff(&c, pOut, nContext, showLn, escHtml);
1802 }
1803 fossil_free(c.aFrom);
1804 fossil_free(c.aTo);
1805 fossil_free(c.aEdit);
1806 return 0;
@@ -1826,19 +1988,19 @@
1826 ** --noopt Disable optimization DIFF_NOOPT
1827 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
1828 ** --unified Unified diff. ~DIFF_SIDEBYSIDE
1829 ** --width|-W N N character lines. DIFF_WIDTH_MASK
1830 */
1831 int diff_options(void){
1832 u64 diffFlags = 0;
1833 const char *z;
1834 int f;
1835 if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
1836 if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE;
1837 if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){
1838 if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
1839 diffFlags |= f;
1840 }
1841 if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
1842 f *= DIFF_CONTEXT_MASK+1;
1843 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
1844 diffFlags |= f;
@@ -1863,34 +2025,52 @@
1863 if( g.argc<4 ) usage("FILE1 FILE2 ...");
1864 blob_read_from_file(&a, g.argv[2]);
1865 for(i=3; i<g.argc; i++){
1866 if( i>3 ) fossil_print("-------------------------------\n");
1867 blob_read_from_file(&b, g.argv[i]);
1868 R = text_diff(&a, &b, 0, diffFlags);
1869 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
1870 fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
1871 }
1872 /* free(R); */
1873 blob_reset(&b);
1874 }
1875 }
1876
1877 /*
1878 ** COMMAND: test-udiff
 
 
1879 **
1880 ** Print the difference between two files. The usual diff options apply.
1881 */
1882 void test_udiff_cmd(void){
1883 Blob a, b, out;
1884 u64 diffFlag = diff_options();
 
 
1885
 
 
 
 
 
 
 
 
 
 
 
 
1886 if( g.argc!=4 ) usage("FILE1 FILE2");
 
1887 blob_read_from_file(&a, g.argv[2]);
1888 blob_read_from_file(&b, g.argv[3]);
1889 blob_zero(&out);
1890 text_diff(&a, &b, &out, diffFlag);
1891 blob_write_to_file(&out, "-");
 
1892 }
1893
1894 /**************************************************************************
1895 ** The basic difference engine is above. What follows is the annotation
1896 ** engine. Both are in the same file since they share many components.
1897
--- src/diff.c
+++ src/diff.c
@@ -23,11 +23,12 @@
23 #include <assert.h>
24
25
26 #if INTERFACE
27 /*
28 ** Flag parameters to the text_diff() routine used to control the formatting
29 ** of the diff output.
30 */
31 #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
32 #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
33 #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */
34 #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */
@@ -37,10 +38,11 @@
38 #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */
39 #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */
40 #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */
41 #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
42 #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
43 #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */
44
45 /*
46 ** These error messages are shared in multiple locations. They are defined
47 ** here for consistency.
48 */
@@ -52,11 +54,11 @@
54
55 #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0)
56 #endif /* INTERFACE */
57
58 /*
59 ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
60 */
61 #define LENGTH_MASK_SZ 13
62 #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
63
64 /*
@@ -116,10 +118,13 @@
118 ** more. If trailing whitespace is ignored, the "patch" command gets
119 ** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b]
120 **
121 ** Return 0 if the file is binary or contains a line that is
122 ** too long.
123 **
124 ** Profiling show that in most cases this routine consumes the bulk of
125 ** the CPU time on a diff.
126 */
127 static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){
128 int nLine, i, j, k, x;
129 unsigned int h, h2;
130 DLine *a;
@@ -407,34 +412,50 @@
412 ** Return true if two DLine elements are identical.
413 */
414 static int same_dline(DLine *pA, DLine *pB){
415 return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
416 }
417
418 /*
419 ** Return true if the regular expression *pRe matches any of the
420 ** N dlines
421 */
422 static int re_dline_match(
423 ReCompiled *pRe, /* The regular expression to be matched */
424 DLine *aDLine, /* First of N DLines to compare against */
425 int N /* Number of DLines to check */
426 ){
427 while( N-- ){
428 if( re_match(pRe, (const unsigned char *)aDLine->z, LENGTH(aDLine)) ){
429 return 1;
430 }
431 aDLine++;
432 }
433 return 0;
434 }
435
436 /*
437 ** Append a single line of context-diff output to pOut.
438 */
439 static void appendDiffLine(
440 Blob *pOut, /* Where to write the line of output */
441 char cPrefix, /* One of " ", "+", or "-" */
442 DLine *pLine, /* The line to be output */
443 int html, /* True if generating HTML. False for plain text */
444 ReCompiled *pRe /* Colorize only if line matches this Regex */
445 ){
 
446 blob_append(pOut, &cPrefix, 1);
447 if( html ){
448 char *zHtml;
449 if( pRe && re_dline_match(pRe, pLine, 1)==0 ){
450 cPrefix = ' ';
451 }else if( cPrefix=='+' ){
452 blob_append(pOut, "<span class=\"diffadd\">", -1);
453 }else if( cPrefix=='-' ){
454 blob_append(pOut, "<span class=\"diffrm\">", -1);
455 }
456 zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK));
 
 
 
 
457 blob_append(pOut, zHtml, -1);
458 fossil_free(zHtml);
459 if( cPrefix!=' ' ){
460 blob_append(pOut, "</span>", -1);
461 }
@@ -444,11 +465,11 @@
465 blob_append(pOut, "\n", 1);
466 }
467
468 /*
469 ** Add two line numbers to the beginning of an output line for a context
470 ** diff. One or the other of the two numbers might be zero, which means
471 ** to leave that number field blank. The "html" parameter means to format
472 ** the output for HTML.
473 */
474 static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){
475 if( html ) blob_append(pOut, "<span class=\"diffln\">", -1);
@@ -463,21 +484,19 @@
484 blob_append(pOut, " ", 8);
485 }
486 if( html ) blob_append(pOut, "</span>", -1);
487 }
488
 
489 /*
490 ** Given a raw diff p[] in which the p->aEdit[] array has been filled
491 ** in, compute a context diff into pOut.
492 */
493 static void contextDiff(
494 DContext *p, /* The difference */
495 Blob *pOut, /* Output a context diff to here */
496 ReCompiled *pRe, /* Only show changes that match this regex */
497 u64 diffFlags /* Flags controlling the diff format */
 
498 ){
499 DLine *A; /* Left side of the diff */
500 DLine *B; /* Right side of the diff */
501 int a = 0; /* Index of next line in A[] */
502 int b = 0; /* Index of next line in B[] */
@@ -488,11 +507,18 @@
507 int na, nb; /* Number of lines shown from A and B */
508 int i, j; /* Loop counters */
509 int m; /* Number of lines to output */
510 int skip; /* Number of lines to skip */
511 int nChunk = 0; /* Number of diff chunks seen so far */
512 int nContext; /* Number of lines of context */
513 int showLn; /* Show line numbers */
514 int html; /* Render as HTML */
515 int showDivider = 0; /* True to show the divider between diff blocks */
516
517 nContext = diff_context_lines(diffFlags);
518 showLn = (diffFlags & DIFF_LINENO)!=0;
519 html = (diffFlags & DIFF_HTML)!=0;
520 A = p->aFrom;
521 B = p->aTo;
522 R = p->aEdit;
523 mxr = p->nEdit;
524 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
@@ -499,10 +525,35 @@
525 for(r=0; r<mxr; r += 3*nr){
526 /* Figure out how many triples to show in a single block */
527 for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
528 /* printf("r=%d nr=%d\n", r, nr); */
529
530 /* If there is a regex, skip this block (generate no diff output)
531 ** if the regex matches or does not match both insert and delete.
532 ** Only display the block if one side matches but the other side does
533 ** not.
534 */
535 if( pRe ){
536 int hideBlock = 1;
537 int xa = a, xb = b;
538 for(i=0; hideBlock && i<nr; i++){
539 int c1, c2;
540 xa += R[r+i*3];
541 xb += R[r+i*3];
542 c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]);
543 c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]);
544 hideBlock = c1==c2;
545 xa += R[r+i*3+1];
546 xb += R[r+i*3+2];
547 }
548 if( hideBlock ){
549 a = xa;
550 b = xb;
551 continue;
552 }
553 }
554
555 /* For the current block comprising nr triples, figure out
556 ** how many lines of A and B are to be displayed
557 */
558 if( R[r]>nContext ){
559 na = nb = nContext;
@@ -526,17 +577,18 @@
577 na += R[r+i*3];
578 nb += R[r+i*3];
579 }
580
581 /* Show the header for this block, or if we are doing a modified
582 ** context diff that contains line numbers, show the separator from
583 ** the previous block.
584 */
585 nChunk++;
586 if( showLn ){
587 if( !showDivider ){
588 /* Do not show a top divider */
589 showDivider = 1;
590 }else if( html ){
591 blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
592 blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
593 }else{
594 blob_appendf(pOut, "%.80c\n", '.');
@@ -559,34 +611,36 @@
611 a += skip;
612 b += skip;
613 m = R[r] - skip;
614 for(j=0; j<m; j++){
615 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
616 appendDiffLine(pOut, ' ', &A[a+j], html, 0);
617 }
618 a += m;
619 b += m;
620
621 /* Show the differences */
622 for(i=0; i<nr; i++){
623 m = R[r+i*3+1];
624 for(j=0; j<m; j++){
625 char cMark = '-';
626 if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html);
627 if( pRe && re_dline_match(pRe, &A[a+j], 1)==0 ) cMark = ' ';
628 appendDiffLine(pOut, '-', &A[a+j], html, pRe);
629 }
630 a += m;
631 m = R[r+i*3+2];
632 for(j=0; j<m; j++){
633 if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html);
634 appendDiffLine(pOut, '+', &B[b+j], html, pRe);
635 }
636 b += m;
637 if( i<nr-1 ){
638 m = R[r+i*3+3];
639 for(j=0; j<m; j++){
640 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
641 appendDiffLine(pOut, ' ', &B[b+j], html, 0);
642 }
643 b += m;
644 a += m;
645 }
646 }
@@ -595,11 +649,11 @@
649 assert( nr==i );
650 m = R[r+nr*3];
651 if( m>nContext ) m = nContext;
652 for(j=0; j<m; j++){
653 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html);
654 appendDiffLine(pOut, ' ', &B[b+j], html, 0);
655 }
656 }
657 }
658
659 /*
@@ -615,10 +669,11 @@
669 const char *zStart; /* A <span> tag */
670 int iEnd; /* Write </span> prior to character iEnd */
671 int iStart2; /* Write zStart2 prior to character iStart2 */
672 const char *zStart2; /* A <span> tag */
673 int iEnd2; /* Write </span> prior to character iEnd2 */
674 ReCompiled *pRe; /* Only colorize matching lines, if not NULL */
675 };
676
677 /*
678 ** Flags for sbsWriteText()
679 */
@@ -640,13 +695,17 @@
695 int k; /* Cursor position */
696 int needEndSpan = 0;
697 const char *zIn = pLine->z;
698 char *z = &p->zLine[p->n];
699 int w = p->width;
700 int colorize = p->escHtml;
701 if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
702 colorize = 0;
703 }
704 for(i=j=k=0; k<w && i<n; i++, k++){
705 char c = zIn[i];
706 if( colorize ){
707 if( i==p->iStart ){
708 int x = strlen(p->zStart);
709 memcpy(z+j, p->zStart, x);
710 j += x;
711 needEndSpan = 1;
@@ -797,10 +856,41 @@
856 }
857 }
858 }
859 return rc;
860 }
861
862 /*
863 ** Try to shift iStart as far as possible to the left.
864 */
865 static void sbsShiftLeft(SbsLine *p, const char *z){
866 int i, j;
867 while( (i=p->iStart)>0 && z[i-1]==z[i] ){
868 for(j=i+1; j<p->iEnd && z[j-1]==z[j]; j++){}
869 if( j<p->iEnd ) break;
870 p->iStart--;
871 p->iEnd--;
872 }
873 }
874
875 /*
876 ** Simplify iStart and iStart2:
877 **
878 ** * If iStart is a null-change then move iStart2 into iStart
879 ** * Make sure any null-changes are in canonoical form.
880 */
881 static void sbsSimplifyLine(SbsLine *p){
882 if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0;
883 if( p->iStart==p->iEnd ){
884 p->iStart = p->iStart2;
885 p->iEnd = p->iEnd2;
886 p->zStart = p->zStart2;
887 p->iStart2 = 0;
888 p->iEnd2 = 0;
889 }
890 if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1;
891 }
892
893 /*
894 ** Write out lines that have been edited. Adjust the highlight to cover
895 ** only those parts of the line that actually changed.
896 */
@@ -891,41 +981,35 @@
981 && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS)
982 ){
983 sbsWriteLineno(p, lnLeft);
984 p->iStart = nPrefix;
985 p->iEnd = nPrefix + aLCS[0];
986 if( aLCS[2]==0 ){
987 sbsShiftLeft(p, pLeft->z);
988 p->zStart = zClassRm;
989 }else{
990 p->zStart = zClassChng;
991 }
992 p->iStart2 = nPrefix + aLCS[1];
993 p->iEnd2 = nLeft - nSuffix;
994 p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng;
995 sbsSimplifyLine(p);
 
 
 
 
 
 
 
 
996 sbsWriteText(p, pLeft, SBS_PAD);
997 sbsWrite(p, " | ", 3);
998 sbsWriteLineno(p, lnRight);
999 p->iStart = nPrefix;
1000 p->iEnd = nPrefix + aLCS[2];
1001 if( aLCS[0]==0 ){
1002 sbsShiftLeft(p, pRight->z);
1003 p->zStart = zClassAdd;
1004 }else{
1005 p->zStart = zClassChng;
1006 }
1007 p->iStart2 = nPrefix + aLCS[3];
1008 p->iEnd2 = nRight - nSuffix;
1009 p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng;
1010 sbsSimplifyLine(p);
 
 
 
 
 
 
 
 
1011 sbsWriteText(p, pRight, SBS_NEWLINE);
1012 return;
1013 }
1014
1015 /* If all else fails, show a single big change between left and right */
@@ -1018,13 +1102,16 @@
1102 **
1103 ** The return value is a buffer of unsigned characters, obtained from
1104 ** fossil_malloc(). (The caller needs to free the return value using
1105 ** fossil_free().) Entries in the returned array have values as follows:
1106 **
1107 ** 1. Delete the next line of pLeft.
1108 ** 2. Insert the next line of pRight.
1109 ** 3. The next line of pLeft changes into the next line of pRight.
1110 ** 4. Delete one line from pLeft and add one line to pRight.
1111 **
1112 ** Values larger than three indicate better matches.
1113 **
1114 ** The length of the returned array will be just large enough to cause
1115 ** all elements of pLeft and pRight to be consumed.
1116 **
1117 ** Algorithm: Wagner's minimum edit-distance algorithm, modified by
@@ -1039,27 +1126,32 @@
1126 ){
1127 int i, j, k; /* Loop counters */
1128 int *a; /* One row of the Wagner matrix */
1129 int *pToFree; /* Space that needs to be freed */
1130 unsigned char *aM; /* Wagner result matrix */
1131 int nMatch, iMatch; /* Number of matching lines and match score */
1132 int mnLen; /* MIN(nLeft, nRight) */
1133 int mxLen; /* MAX(nLeft, nRight) */
1134 int aBuf[100]; /* Stack space for a[] if nRight not to big */
1135
1136 aM = fossil_malloc( (nLeft+1)*(nRight+1) );
1137 if( nLeft==0 ){
1138 memset(aM, 2, nRight);
1139 return aM;
1140 }
1141 if( nRight==0 ){
1142 memset(aM, 1, nLeft);
1143 return aM;
1144 }
1145
1146 /* This algorithm is O(N**2). So if N is too big, bail out with a
1147 ** simple (but stupid and ugly) result that doesn't take too long. */
1148 mnLen = nLeft<nRight ? nLeft : nRight;
1149 if( nLeft*nRight>100000 ){
1150 memset(aM, 4, mnLen);
1151 if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen);
1152 if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen);
1153 return aM;
1154 }
1155
1156 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1157 pToFree = 0;
@@ -1068,30 +1160,30 @@
1160 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1161 }
1162
1163 /* Compute the best alignment */
1164 for(i=0; i<=nRight; i++){
1165 aM[i] = 2;
1166 a[i] = i*50;
1167 }
1168 aM[0] = 0;
1169 for(j=1; j<=nLeft; j++){
1170 int p = a[0];
1171 a[0] = p+50;
1172 aM[j*(nRight+1)] = 1;
1173 for(i=1; i<=nRight; i++){
1174 int m = a[i-1]+50;
1175 int d = 2;
1176 if( m>a[i]+50 ){
1177 m = a[i]+50;
1178 d = 1;
1179 }
1180 if( m>p ){
1181 int score = match_dline(&aLeft[j-1], &aRight[i-1]);
1182 if( (score<=63 || (i<j+1 && i>j-1)) && m>p+score ){
1183 m = p+score;
1184 d = 3 | score*4;
1185 }
1186 }
1187 p = a[i];
1188 a[i] = m;
1189 aM[j*(nRight+1)+i] = d;
@@ -1100,28 +1192,50 @@
1192
1193 /* Compute the lowest-cost path back through the matrix */
1194 i = nRight;
1195 j = nLeft;
1196 k = (nRight+1)*(nLeft+1)-1;
1197 nMatch = iMatch = 0;
1198 while( i+j>0 ){
1199 unsigned char c = aM[k];
1200 if( c>=3 ){
1201 assert( i>0 && j>0 );
1202 i--;
1203 j--;
1204 nMatch++;
1205 iMatch += (c>>2);
1206 aM[k] = 3;
1207 }else if( c==2 ){
1208 assert( i>0 );
1209 i--;
1210 }else{
1211 assert( j>0 );
1212 j--;
1213 }
1214 k--;
1215 aM[k] = aM[j*(nRight+1)+i];
1216 }
1217 k++;
1218 i = (nRight+1)*(nLeft+1) - k;
1219 memmove(aM, &aM[k], i);
1220
1221 /* If:
1222 ** (1) the alignment is more than 25% longer than the longest side, and
1223 ** (2) the average match cost exceeds 15
1224 ** Then this is probably an alignment that will be difficult for humans
1225 ** to read. So instead, just show all of the right side inserted followed
1226 ** by all of the left side deleted.
1227 **
1228 ** The coefficients for conditions (1) and (2) above are determined by
1229 ** experimentation.
1230 */
1231 mxLen = nLeft>nRight ? nLeft : nRight;
1232 if( i*4>mxLen*5 && (nMatch==0 || iMatch/nMatch>15) ){
1233 memset(aM, 4, mnLen);
1234 if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen);
1235 if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen);
1236 }
1237
1238 /* Return the result */
1239 fossil_free(pToFree);
1240 return aM;
1241 }
@@ -1141,13 +1255,12 @@
1255 ** in, compute a side-by-side diff into pOut.
1256 */
1257 static void sbsDiff(
1258 DContext *p, /* The computed diff */
1259 Blob *pOut, /* Write the results here */
1260 ReCompiled *pRe, /* Only show changes that match this regex */
1261 u64 diffFlags /* Flags controlling the diff */
 
1262 ){
1263 DLine *A; /* Left side of the diff */
1264 DLine *B; /* Right side of the diff */
1265 int a = 0; /* Index of next line in A[] */
1266 int b = 0; /* Index of next line in B[] */
@@ -1159,16 +1272,20 @@
1272 int i, j; /* Loop counters */
1273 int m, ma, mb;/* Number of lines to output */
1274 int skip; /* Number of lines to skip */
1275 int nChunk = 0; /* Number of chunks of diff output seen so far */
1276 SbsLine s; /* Output line buffer */
1277 int nContext; /* Lines of context above and below each change */
1278 int showDivider = 0; /* True to show the divider */
1279
1280 memset(&s, 0, sizeof(s));
1281 s.width = diff_width(diffFlags);
1282 s.zLine = fossil_malloc( 15*s.width + 200 );
1283 if( s.zLine==0 ) return;
1284 nContext = diff_context_lines(diffFlags);
1285 s.escHtml = (diffFlags & DIFF_HTML)!=0;
1286 s.pRe = pRe;
1287 s.iStart = -1;
1288 s.iStart2 = 0;
1289 s.iEnd = -1;
1290 A = p->aFrom;
1291 B = p->aTo;
@@ -1177,10 +1294,35 @@
1294 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
1295 for(r=0; r<mxr; r += 3*nr){
1296 /* Figure out how many triples to show in a single block */
1297 for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
1298 /* printf("r=%d nr=%d\n", r, nr); */
1299
1300 /* If there is a regex, skip this block (generate no diff output)
1301 ** if the regex matches or does not match both insert and delete.
1302 ** Only display the block if one side matches but the other side does
1303 ** not.
1304 */
1305 if( pRe ){
1306 int hideBlock = 1;
1307 int xa = a, xb = b;
1308 for(i=0; hideBlock && i<nr; i++){
1309 int c1, c2;
1310 xa += R[r+i*3];
1311 xb += R[r+i*3];
1312 c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]);
1313 c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]);
1314 hideBlock = c1==c2;
1315 xa += R[r+i*3+1];
1316 xb += R[r+i*3+2];
1317 }
1318 if( hideBlock ){
1319 a = xa;
1320 b = xb;
1321 continue;
1322 }
1323 }
1324
1325 /* For the current block comprising nr triples, figure out
1326 ** how many lines of A and B are to be displayed
1327 */
1328 if( R[r]>nContext ){
@@ -1205,20 +1347,21 @@
1347 na += R[r+i*3];
1348 nb += R[r+i*3];
1349 }
1350
1351 /* Draw the separator between blocks */
1352 if( showDivider ){
1353 if( s.escHtml ){
1354 blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n",
1355 s.width*2+16, '.');
1356 }else{
1357 blob_appendf(pOut, "%.*c\n", s.width*2+16, '.');
1358 }
1359 }
1360 showDivider = 1;
1361 nChunk++;
1362 if( s.escHtml ){
1363 blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk);
1364 }
1365
1366 /* Show the initial common area */
1367 a += skip;
@@ -1254,38 +1397,41 @@
1397 }
1398
1399 alignment = sbsAlignment(&A[a], ma, &B[b], mb);
1400 for(j=0; ma+mb>0; j++){
1401 if( alignment[j]==1 ){
1402 /* Delete one line from the left */
1403 s.n = 0;
1404 sbsWriteLineno(&s, a);
1405 s.iStart = 0;
1406 s.zStart = "<span class=\"diffrm\">";
1407 s.iEnd = s.width;
1408 sbsWriteText(&s, &A[a], SBS_PAD);
1409 if( s.escHtml ){
1410 sbsWrite(&s, " &lt;\n", 6);
1411 }else{
1412 sbsWrite(&s, " <\n", 3);
1413 }
1414 blob_append(pOut, s.zLine, s.n);
1415 assert( ma>0 );
1416 ma--;
1417 a++;
1418 }else if( alignment[j]==3 ){
1419 /* The left line is changed into the right line */
1420 s.n = 0;
1421 sbsWriteLineChange(&s, &A[a], a, &B[b], b);
1422 blob_append(pOut, s.zLine, s.n);
1423 assert( ma>0 && mb>0 );
1424 ma--;
1425 mb--;
1426 a++;
1427 b++;
1428 }else if( alignment[j]==2 ){
1429 /* Insert one line on the right */
1430 s.n = 0;
1431 sbsWriteSpace(&s, s.width + 7);
1432 if( s.escHtml ){
1433 sbsWrite(&s, " &gt; ", 6);
1434 }else{
1435 sbsWrite(&s, " > ", 3);
1436 }
1437 sbsWriteLineno(&s, b);
@@ -1295,11 +1441,31 @@
1441 sbsWriteText(&s, &B[b], SBS_NEWLINE);
1442 blob_append(pOut, s.zLine, s.n);
1443 assert( mb>0 );
1444 mb--;
1445 b++;
1446 }else{
1447 /* Delete from the left and insert on the right */
1448 s.n = 0;
1449 sbsWriteLineno(&s, a);
1450 s.iStart = 0;
1451 s.zStart = "<span class=\"diffrm\">";
1452 s.iEnd = s.width;
1453 sbsWriteText(&s, &A[a], SBS_PAD);
1454 sbsWrite(&s, " | ", 3);
1455 sbsWriteLineno(&s, b);
1456 s.iStart = 0;
1457 s.zStart = "<span class=\"diffadd\">";
1458 s.iEnd = s.width;
1459 sbsWriteText(&s, &B[b], SBS_NEWLINE);
1460 blob_append(pOut, s.zLine, s.n);
1461 ma--;
1462 mb--;
1463 a++;
1464 b++;
1465 }
1466
1467 }
1468 fossil_free(alignment);
1469 if( i<nr-1 ){
1470 m = R[r+i*3+3];
1471 for(j=0; j<m; j++){
@@ -1723,11 +1889,11 @@
1889 ** Extract the number of lines of context from diffFlags. Supply an
1890 ** appropriate default if no context width is specified.
1891 */
1892 int diff_context_lines(u64 diffFlags){
1893 int n = diffFlags & DIFF_CONTEXT_MASK;
1894 if( n==0 && (diffFlags & DIFF_CONTEXT_EX)==0 ) n = 5;
1895 return n;
1896 }
1897
1898 /*
1899 ** Extract the width of columns for side-by-side diff. Supply an
@@ -1755,22 +1921,21 @@
1921 */
1922 int *text_diff(
1923 Blob *pA_Blob, /* FROM file */
1924 Blob *pB_Blob, /* TO file */
1925 Blob *pOut, /* Write diff here if not NULL */
1926 ReCompiled *pRe, /* Only output changes where this Regexp matches */
1927 u64 diffFlags /* DIFF_* flags defined above */
1928 ){
1929 int ignoreEolWs; /* Ignore whitespace at the end of lines */
 
1930 DContext c;
1931
1932 if( diffFlags & DIFF_INVERT ){
1933 Blob *pTemp = pA_Blob;
1934 pA_Blob = pB_Blob;
1935 pB_Blob = pTemp;
1936 }
 
1937 ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
1938
1939 /* Prepare the input files */
1940 memset(&c, 0, sizeof(c));
1941 c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
@@ -1790,17 +1955,14 @@
1955 diff_all(&c);
1956 if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);
1957
1958 if( pOut ){
1959 /* Compute a context or side-by-side diff into pOut */
 
1960 if( diffFlags & DIFF_SIDEBYSIDE ){
1961 sbsDiff(&c, pOut, pRe, diffFlags);
 
1962 }else{
1963 contextDiff(&c, pOut, pRe, diffFlags);
 
1964 }
1965 fossil_free(c.aFrom);
1966 fossil_free(c.aTo);
1967 fossil_free(c.aEdit);
1968 return 0;
@@ -1826,19 +1988,19 @@
1988 ** --noopt Disable optimization DIFF_NOOPT
1989 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
1990 ** --unified Unified diff. ~DIFF_SIDEBYSIDE
1991 ** --width|-W N N character lines. DIFF_WIDTH_MASK
1992 */
1993 u64 diff_options(void){
1994 u64 diffFlags = 0;
1995 const char *z;
1996 int f;
1997 if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
1998 if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE;
1999 if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){
2000 if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
2001 diffFlags |= f + DIFF_CONTEXT_EX;
2002 }
2003 if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
2004 f *= DIFF_CONTEXT_MASK+1;
2005 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
2006 diffFlags |= f;
@@ -1863,34 +2025,52 @@
2025 if( g.argc<4 ) usage("FILE1 FILE2 ...");
2026 blob_read_from_file(&a, g.argv[2]);
2027 for(i=3; i<g.argc; i++){
2028 if( i>3 ) fossil_print("-------------------------------\n");
2029 blob_read_from_file(&b, g.argv[i]);
2030 R = text_diff(&a, &b, 0, 0, diffFlags);
2031 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
2032 fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
2033 }
2034 /* free(R); */
2035 blob_reset(&b);
2036 }
2037 }
2038
2039 /*
2040 ** COMMAND: test-diff
2041 **
2042 ** Usage: %fossil [options] FILE1 FILE2
2043 **
2044 ** Print the difference between two files. The usual diff options apply.
2045 */
2046 void test_diff_cmd(void){
2047 Blob a, b, out;
2048 u64 diffFlag;
2049 const char *zRe; /* Regex filter for diff output */
2050 ReCompiled *pRe = 0; /* Regex filter for diff output */
2051
2052 if( find_option("tk",0,0)!=0 ){
2053 diff_tk("test-diff", 2);
2054 return;
2055 }
2056 find_option("i",0,0);
2057 zRe = find_option("regexp","e",1);
2058 if( zRe ){
2059 const char *zErr = re_compile(&pRe, zRe, 0);
2060 if( zErr ) fossil_fatal("regex error: %s", zErr);
2061 }
2062 diffFlag = diff_options();
2063 verify_all_options();
2064 if( g.argc!=4 ) usage("FILE1 FILE2");
2065 diff_print_filenames(g.argv[2], g.argv[3], diffFlag);
2066 blob_read_from_file(&a, g.argv[2]);
2067 blob_read_from_file(&b, g.argv[3]);
2068 blob_zero(&out);
2069 text_diff(&a, &b, &out, pRe, diffFlag);
2070 blob_write_to_file(&out, "-");
2071 re_free(pRe);
2072 }
2073
2074 /**************************************************************************
2075 ** The basic difference engine is above. What follows is the annotation
2076 ** engine. Both are in the same file since they share many components.
2077
+9 -3
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -109,11 +109,11 @@
109109
if( blob_compare(pFile1, &file2) ){
110110
fossil_print("CHANGED %s\n", zName);
111111
}
112112
}else{
113113
blob_zero(&out);
114
- text_diff(pFile1, &file2, &out, diffFlags);
114
+ text_diff(pFile1, &file2, &out, 0, diffFlags);
115115
if( blob_size(&out) ){
116116
diff_print_filenames(zName, zName2, diffFlags);
117117
fossil_print("%s\n", blob_str(&out));
118118
}
119119
blob_reset(&out);
@@ -210,11 +210,11 @@
210210
if( diffFlags & DIFF_BRIEF ) return;
211211
if( zDiffCmd==0 ){
212212
Blob out; /* Diff output text */
213213
214214
blob_zero(&out);
215
- text_diff(pFile1, pFile2, &out, diffFlags);
215
+ text_diff(pFile1, pFile2, &out, 0, diffFlags);
216216
diff_print_filenames(zName, zName, diffFlags);
217217
fossil_print("%s\n", blob_str(&out));
218218
219219
/* Release memory resources */
220220
blob_reset(&out);
@@ -659,12 +659,18 @@
659659
char *zCmd;
660660
blob_zero(&script);
661661
blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i",
662662
g.nameOfExe, zSubCmd);
663663
for(i=firstArg; i<g.argc; i++){
664
+ const char *z = g.argv[i];
665
+ if( z[0]=='-' ){
666
+ if( strglob("*-html",z) ) continue;
667
+ if( strglob("*-y",z) ) continue;
668
+ if( strglob("*-i",z) ) continue;
669
+ }
664670
blob_append(&script, " ", 1);
665
- shell_escape(&script, g.argv[i]);
671
+ shell_escape(&script, z);
666672
}
667673
blob_appendf(&script, "}\n%s", zDiffScript);
668674
zTempFile = write_blob_to_temp_file(&script);
669675
zCmd = mprintf("tclsh \"%s\"", zTempFile);
670676
fossil_system(zCmd);
671677
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -109,11 +109,11 @@
109 if( blob_compare(pFile1, &file2) ){
110 fossil_print("CHANGED %s\n", zName);
111 }
112 }else{
113 blob_zero(&out);
114 text_diff(pFile1, &file2, &out, diffFlags);
115 if( blob_size(&out) ){
116 diff_print_filenames(zName, zName2, diffFlags);
117 fossil_print("%s\n", blob_str(&out));
118 }
119 blob_reset(&out);
@@ -210,11 +210,11 @@
210 if( diffFlags & DIFF_BRIEF ) return;
211 if( zDiffCmd==0 ){
212 Blob out; /* Diff output text */
213
214 blob_zero(&out);
215 text_diff(pFile1, pFile2, &out, diffFlags);
216 diff_print_filenames(zName, zName, diffFlags);
217 fossil_print("%s\n", blob_str(&out));
218
219 /* Release memory resources */
220 blob_reset(&out);
@@ -659,12 +659,18 @@
659 char *zCmd;
660 blob_zero(&script);
661 blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i",
662 g.nameOfExe, zSubCmd);
663 for(i=firstArg; i<g.argc; i++){
 
 
 
 
 
 
664 blob_append(&script, " ", 1);
665 shell_escape(&script, g.argv[i]);
666 }
667 blob_appendf(&script, "}\n%s", zDiffScript);
668 zTempFile = write_blob_to_temp_file(&script);
669 zCmd = mprintf("tclsh \"%s\"", zTempFile);
670 fossil_system(zCmd);
671
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -109,11 +109,11 @@
109 if( blob_compare(pFile1, &file2) ){
110 fossil_print("CHANGED %s\n", zName);
111 }
112 }else{
113 blob_zero(&out);
114 text_diff(pFile1, &file2, &out, 0, diffFlags);
115 if( blob_size(&out) ){
116 diff_print_filenames(zName, zName2, diffFlags);
117 fossil_print("%s\n", blob_str(&out));
118 }
119 blob_reset(&out);
@@ -210,11 +210,11 @@
210 if( diffFlags & DIFF_BRIEF ) return;
211 if( zDiffCmd==0 ){
212 Blob out; /* Diff output text */
213
214 blob_zero(&out);
215 text_diff(pFile1, pFile2, &out, 0, diffFlags);
216 diff_print_filenames(zName, zName, diffFlags);
217 fossil_print("%s\n", blob_str(&out));
218
219 /* Release memory resources */
220 blob_reset(&out);
@@ -659,12 +659,18 @@
659 char *zCmd;
660 blob_zero(&script);
661 blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i",
662 g.nameOfExe, zSubCmd);
663 for(i=firstArg; i<g.argc; i++){
664 const char *z = g.argv[i];
665 if( z[0]=='-' ){
666 if( strglob("*-html",z) ) continue;
667 if( strglob("*-y",z) ) continue;
668 if( strglob("*-i",z) ) continue;
669 }
670 blob_append(&script, " ", 1);
671 shell_escape(&script, z);
672 }
673 blob_appendf(&script, "}\n%s", zDiffScript);
674 zTempFile = write_blob_to_temp_file(&script);
675 zCmd = mprintf("tclsh \"%s\"", zTempFile);
676 fossil_system(zCmd);
677
+2 -2
--- src/doc.c
+++ src/doc.c
@@ -380,15 +380,15 @@
380380
g.zPath = mprintf("%s/%s", g.zPath, zName);
381381
memcpy(zBaseline, zName, i);
382382
zBaseline[i] = 0;
383383
zName += i;
384384
while( zName[0]=='/' ){ zName++; }
385
- if( !file_is_simple_pathname(zName) ){
385
+ if( !file_is_simple_pathname(zName, 1) ){
386386
int n = strlen(zName);
387387
if( n>0 && zName[n-1]=='/' ){
388388
zName = mprintf("%sindex.html", zName);
389
- if( !file_is_simple_pathname(zName) ){
389
+ if( !file_is_simple_pathname(zName, 1) ){
390390
goto doc_not_found;
391391
}
392392
}else{
393393
goto doc_not_found;
394394
}
395395
--- src/doc.c
+++ src/doc.c
@@ -380,15 +380,15 @@
380 g.zPath = mprintf("%s/%s", g.zPath, zName);
381 memcpy(zBaseline, zName, i);
382 zBaseline[i] = 0;
383 zName += i;
384 while( zName[0]=='/' ){ zName++; }
385 if( !file_is_simple_pathname(zName) ){
386 int n = strlen(zName);
387 if( n>0 && zName[n-1]=='/' ){
388 zName = mprintf("%sindex.html", zName);
389 if( !file_is_simple_pathname(zName) ){
390 goto doc_not_found;
391 }
392 }else{
393 goto doc_not_found;
394 }
395
--- src/doc.c
+++ src/doc.c
@@ -380,15 +380,15 @@
380 g.zPath = mprintf("%s/%s", g.zPath, zName);
381 memcpy(zBaseline, zName, i);
382 zBaseline[i] = 0;
383 zName += i;
384 while( zName[0]=='/' ){ zName++; }
385 if( !file_is_simple_pathname(zName, 1) ){
386 int n = strlen(zName);
387 if( n>0 && zName[n-1]=='/' ){
388 zName = mprintf("%sindex.html", zName);
389 if( !file_is_simple_pathname(zName, 1) ){
390 goto doc_not_found;
391 }
392 }else{
393 goto doc_not_found;
394 }
395
+31 -24
--- src/file.c
+++ src/file.c
@@ -487,43 +487,50 @@
487487
** * Does not contain any path element named "." or ".."
488488
** * Does not contain any of these characters in the path: "\"
489489
** * Does not end with "/".
490490
** * Does not contain two or more "/" characters in a row.
491491
** * Contains at least one character
492
+**
493
+** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494
+** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495
+** ignored.
492496
*/
493
-int file_is_simple_pathname(const char *z){
497
+int file_is_simple_pathname(const char *z, int bStrictUtf8){
494498
int i;
495499
char c = z[0];
500
+ char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
496501
if( c=='/' || c==0 ) return 0;
497502
if( c=='.' ){
498503
if( z[1]=='/' || z[1]==0 ) return 0;
499504
if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
500505
}
501506
for(i=0; (c=z[i])!=0; i++){
502
- if( (c & 0xf0) == 0xf0 ) {
503
- /* Unicode characters > U+FFFF are not supported.
504
- * Windows XP and earlier cannot handle them.
505
- */
506
- return 0;
507
- }
508
- if( (c & 0xf0) == 0xe0 ) {
509
- /* This is a 3-byte UTF-8 character */
510
- if ( (c & 0xfe) == 0xee ){
511
- /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
512
- if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){
513
- /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4),
514
- * which contain valid characters. */
515
- continue;
516
- }
517
- /* Unicode character in the range U+E000 - U+F8FF are for
518
- * private use, they shouldn't occur in filenames. */
519
- return 0;
520
- }
521
- if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
522
- /* Unicode character in the range U+D800 - U+DFFF are for
523
- * surrogate pairs, they shouldn't occur in filenames. */
524
- return 0;
507
+ if( c & maskNonAscii ){
508
+ if( (c & 0xf0) == 0xf0 ) {
509
+ /* Unicode characters > U+FFFF are not supported.
510
+ * Windows XP and earlier cannot handle them.
511
+ */
512
+ return 0;
513
+ }
514
+ if( (c & 0xf0) == 0xe0 ) {
515
+ /* This is a 3-byte UTF-8 character */
516
+ if ( (c & 0xfe) == 0xee ){
517
+ /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
518
+ if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){
519
+ /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4),
520
+ * which contain valid characters. */
521
+ continue;
522
+ }
523
+ /* Unicode character in the range U+E000 - U+F8FF are for
524
+ * private use, they shouldn't occur in filenames. */
525
+ return 0;
526
+ }
527
+ if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
528
+ /* Unicode character in the range U+D800 - U+DFFF are for
529
+ * surrogate pairs, they shouldn't occur in filenames. */
530
+ return 0;
531
+ }
525532
}
526533
}
527534
if( c=='\\' ){
528535
return 0;
529536
}
530537
--- src/file.c
+++ src/file.c
@@ -487,43 +487,50 @@
487 ** * Does not contain any path element named "." or ".."
488 ** * Does not contain any of these characters in the path: "\"
489 ** * Does not end with "/".
490 ** * Does not contain two or more "/" characters in a row.
491 ** * Contains at least one character
 
 
 
 
492 */
493 int file_is_simple_pathname(const char *z){
494 int i;
495 char c = z[0];
 
496 if( c=='/' || c==0 ) return 0;
497 if( c=='.' ){
498 if( z[1]=='/' || z[1]==0 ) return 0;
499 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
500 }
501 for(i=0; (c=z[i])!=0; i++){
502 if( (c & 0xf0) == 0xf0 ) {
503 /* Unicode characters > U+FFFF are not supported.
504 * Windows XP and earlier cannot handle them.
505 */
506 return 0;
507 }
508 if( (c & 0xf0) == 0xe0 ) {
509 /* This is a 3-byte UTF-8 character */
510 if ( (c & 0xfe) == 0xee ){
511 /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
512 if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){
513 /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4),
514 * which contain valid characters. */
515 continue;
516 }
517 /* Unicode character in the range U+E000 - U+F8FF are for
518 * private use, they shouldn't occur in filenames. */
519 return 0;
520 }
521 if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
522 /* Unicode character in the range U+D800 - U+DFFF are for
523 * surrogate pairs, they shouldn't occur in filenames. */
524 return 0;
 
 
525 }
526 }
527 if( c=='\\' ){
528 return 0;
529 }
530
--- src/file.c
+++ src/file.c
@@ -487,43 +487,50 @@
487 ** * Does not contain any path element named "." or ".."
488 ** * Does not contain any of these characters in the path: "\"
489 ** * Does not end with "/".
490 ** * Does not contain two or more "/" characters in a row.
491 ** * Contains at least one character
492 **
493 ** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494 ** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495 ** ignored.
496 */
497 int file_is_simple_pathname(const char *z, int bStrictUtf8){
498 int i;
499 char c = z[0];
500 char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
501 if( c=='/' || c==0 ) return 0;
502 if( c=='.' ){
503 if( z[1]=='/' || z[1]==0 ) return 0;
504 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
505 }
506 for(i=0; (c=z[i])!=0; i++){
507 if( c & maskNonAscii ){
508 if( (c & 0xf0) == 0xf0 ) {
509 /* Unicode characters > U+FFFF are not supported.
510 * Windows XP and earlier cannot handle them.
511 */
512 return 0;
513 }
514 if( (c & 0xf0) == 0xe0 ) {
515 /* This is a 3-byte UTF-8 character */
516 if ( (c & 0xfe) == 0xee ){
517 /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
518 if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){
519 /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4),
520 * which contain valid characters. */
521 continue;
522 }
523 /* Unicode character in the range U+E000 - U+F8FF are for
524 * private use, they shouldn't occur in filenames. */
525 return 0;
526 }
527 if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
528 /* Unicode character in the range U+D800 - U+DFFF are for
529 * surrogate pairs, they shouldn't occur in filenames. */
530 return 0;
531 }
532 }
533 }
534 if( c=='\\' ){
535 return 0;
536 }
537
--- src/http_socket.c
+++ src/http_socket.c
@@ -27,14 +27,12 @@
2727
*/
2828
2929
#include "config.h"
3030
#include "http_socket.h"
3131
#if defined(_WIN32)
32
-# if defined(__MINGW32__)
33
-# include <ws2tcpip.h>
34
-# endif
35
-# include <windows.h>
32
+# include <winsock2.h>
33
+# include <ws2tcpip.h>
3634
#else
3735
# include <netinet/in.h>
3836
# include <arpa/inet.h>
3937
# include <sys/socket.h>
4038
# include <netdb.h>
4139
--- src/http_socket.c
+++ src/http_socket.c
@@ -27,14 +27,12 @@
27 */
28
29 #include "config.h"
30 #include "http_socket.h"
31 #if defined(_WIN32)
32 # if defined(__MINGW32__)
33 # include <ws2tcpip.h>
34 # endif
35 # include <windows.h>
36 #else
37 # include <netinet/in.h>
38 # include <arpa/inet.h>
39 # include <sys/socket.h>
40 # include <netdb.h>
41
--- src/http_socket.c
+++ src/http_socket.c
@@ -27,14 +27,12 @@
27 */
28
29 #include "config.h"
30 #include "http_socket.h"
31 #if defined(_WIN32)
32 # include <winsock2.h>
33 # include <ws2tcpip.h>
 
 
34 #else
35 # include <netinet/in.h>
36 # include <arpa/inet.h>
37 # include <sys/socket.h>
38 # include <netdb.h>
39
+53 -17
--- src/info.c
+++ src/info.c
@@ -287,13 +287,18 @@
287287
}
288288
}
289289
290290
291291
/*
292
-** Append the difference between two RIDs to the output
292
+** Append the difference between artifacts to the output
293293
*/
294
-static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){
294
+static void append_diff(
295
+ const char *zFrom, /* Diff from this artifact */
296
+ const char *zTo, /* ... to this artifact */
297
+ u64 diffFlags, /* Diff formatting flags */
298
+ ReCompiled *pRe /* Only show change matching this regex */
299
+){
295300
int fromid;
296301
int toid;
297302
Blob from, to, out;
298303
if( zFrom ){
299304
fromid = uuid_to_rid(zFrom, 0);
@@ -307,16 +312,16 @@
307312
}else{
308313
blob_zero(&to);
309314
}
310315
blob_zero(&out);
311316
if( diffFlags & DIFF_SIDEBYSIDE ){
312
- text_diff(&from, &to, &out, diffFlags | DIFF_HTML);
317
+ text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML);
313318
@ <div class="sbsdiff">
314319
@ %s(blob_str(&out))
315320
@ </div>
316321
}else{
317
- text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML);
322
+ text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML);
318323
@ <div class="udiff">
319324
@ %s(blob_str(&out))
320325
@ </div>
321326
}
322327
blob_reset(&from);
@@ -333,10 +338,11 @@
333338
const char *zName, /* Name of the file that has changed */
334339
const char *zOld, /* blob.uuid before change. NULL for added files */
335340
const char *zNew, /* blob.uuid after change. NULL for deletes */
336341
const char *zOldName, /* Prior name. NULL if no name change. */
337342
u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */
343
+ ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */
338344
int mperm /* executable or symlink permission for zNew */
339345
){
340346
if( !g.perm.Hyperlink ){
341347
if( zNew==0 ){
342348
@ <p>Deleted %h(zName)</p>
@@ -350,21 +356,21 @@
350356
}else{
351357
@ <p>Changes to %h(zName)</p>
352358
}
353359
if( diffFlags ){
354360
@ <pre style="white-space:pre;">
355
- append_diff(zOld, zNew, diffFlags);
361
+ append_diff(zOld, zNew, diffFlags, pRe);
356362
@ </pre>
357363
}
358364
}else{
359365
if( zOld && zNew ){
360366
if( fossil_strcmp(zOld, zNew)!=0 ){
361367
@ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
362368
@ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
363369
@ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
364370
}else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
365
- @ <p>Name change from
371
+ @ <p>Name change
366372
@ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
367373
@ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
368374
}else{
369375
@ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
370376
@ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@@ -376,11 +382,11 @@
376382
@ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
377383
@ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
378384
}
379385
if( diffFlags ){
380386
@ <pre style="white-space:pre;">
381
- append_diff(zOld, zNew, diffFlags);
387
+ append_diff(zOld, zNew, diffFlags, pRe);
382388
@ </pre>
383389
}else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
384390
@ &nbsp;&nbsp;
385391
@ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
386392
}
@@ -444,10 +450,12 @@
444450
int sideBySide; /* True for side-by-side diffs */
445451
u64 diffFlags; /* Flag parameter for text_diff() */
446452
const char *zName; /* Name of the checkin to be displayed */
447453
const char *zUuid; /* UUID of zName */
448454
const char *zParent; /* UUID of the parent checkin (if any) */
455
+ const char *zRe; /* regex parameter */
456
+ ReCompiled *pRe = 0; /* regex */
449457
450458
login_check_credentials();
451459
if( !g.perm.Read ){ login_needed(); return; }
452460
zName = P("name");
453461
rid = name_to_rid_www("name");
@@ -455,10 +463,12 @@
455463
style_header("Check-in Information Error");
456464
@ No such object: %h(g.argv[2])
457465
style_footer();
458466
return;
459467
}
468
+ zRe = P("regex");
469
+ if( zRe ) re_compile(&pRe, zRe, 0);
460470
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
461471
zParent = db_text(0,
462472
"SELECT uuid FROM plink, blob"
463473
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
464474
rid
@@ -479,13 +489,13 @@
479489
char *zEUser, *zEComment;
480490
const char *zUser;
481491
const char *zComment;
482492
const char *zDate;
483493
const char *zOrigDate;
494
+#if 0
484495
char *zThisBranch;
485496
double thisMtime;
486
-#if 0
487497
int seenDiffTitle = 0;
488498
#endif
489499
490500
style_header(zTitle);
491501
login_anonymous_available();
@@ -498,11 +508,13 @@
498508
TAG_COMMENT, rid);
499509
zUser = db_column_text(&q, 2);
500510
zComment = db_column_text(&q, 3);
501511
zDate = db_column_text(&q,1);
502512
zOrigDate = db_column_text(&q, 4);
513
+#if 0
503514
thisMtime = db_column_double(&q, 5);
515
+#endif
504516
@ <div class="section">Overview</div>
505517
@ <table class="label-value">
506518
@ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
507519
if( g.perm.Setup ){
508520
@ (Record ID: %d(rid))
@@ -567,17 +579,17 @@
567579
const char *zTagName = db_column_text(&q, 0);
568580
@ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
569581
}
570582
db_finalize(&q);
571583
584
+#if 0
572585
/* Select a few other branches to diff against */
573586
zThisBranch = db_text("trunk", "SELECT value FROM tagxref"
574587
" WHERE tagid=%d AND tagtype>0"
575588
" AND rid=%d",
576589
TAG_BRANCH, rid);
577590
578
-#if 0
579591
/* Find nearby leaves to offer to diff against */
580592
db_prepare(&q,
581593
"SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)"
582594
" FROM leaf, event, tagxref, blob"
583595
" WHERE event.mtime BETWEEN %.17g AND %.17g"
@@ -690,29 +702,35 @@
690702
@ show&nbsp;side-by-side&nbsp;diffs</a>
691703
}
692704
}
693705
@ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
694706
@ patch</a></div>
707
+ if( pRe ){
708
+ @ <p><b>Only differences that match regular expression "%h(zRe)"
709
+ @ are shown.</b></p>
710
+ }
695711
db_prepare(&q,
696712
"SELECT name,"
697713
" mperm,"
698714
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
699715
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
700716
" (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
701717
" FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
702718
" WHERE mlink.mid=%d"
719
+ " AND (mlink.fid>0"
720
+ " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
703721
" ORDER BY name /*sort*/",
704
- rid
722
+ rid, rid
705723
);
706724
diffFlags = construct_diff_flags(showDiff, sideBySide);
707725
while( db_step(&q)==SQLITE_ROW ){
708726
const char *zName = db_column_text(&q,0);
709727
int mperm = db_column_int(&q, 1);
710728
const char *zOld = db_column_text(&q,2);
711729
const char *zNew = db_column_text(&q,3);
712730
const char *zOldName = db_column_text(&q, 4);
713
- append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm);
731
+ append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
714732
}
715733
db_finalize(&q);
716734
}
717735
style_footer();
718736
}
@@ -931,15 +949,19 @@
931949
Manifest *pFrom, *pTo;
932950
ManifestFile *pFileFrom, *pFileTo;
933951
const char *zBranch;
934952
const char *zFrom;
935953
const char *zTo;
954
+ const char *zRe;
955
+ ReCompiled *pRe = 0;
936956
937957
login_check_credentials();
938958
if( !g.perm.Read ){ login_needed(); return; }
939959
login_anonymous_available();
940960
961
+ zRe = P("regex");
962
+ if( zRe ) re_compile(&pRe, zRe, 0);
941963
zBranch = P("branch");
942964
if( zBranch && zBranch[0] ){
943965
cgi_replace_parameter("from", mprintf("root:%s", zBranch));
944966
cgi_replace_parameter("to", zBranch);
945967
}
@@ -967,11 +989,16 @@
967989
style_header("Check-in Differences");
968990
@ <h2>Difference From:</h2><blockquote>
969991
checkin_description(ridFrom);
970992
@ </blockquote><h2>To:</h2><blockquote>
971993
checkin_description(ridTo);
972
- @ </blockquote><hr /><p>
994
+ @ </blockquote>
995
+ if( pRe ){
996
+ @ <p><b>Only differences that match regular expression "%h(zRe)"
997
+ @ are shown.</b></p>
998
+ }
999
+ @<hr /><p>
9731000
9741001
manifest_file_rewind(pFrom);
9751002
pFileFrom = manifest_file_next(pFrom, 0);
9761003
manifest_file_rewind(pTo);
9771004
pFileTo = manifest_file_next(pTo, 0);
@@ -985,25 +1012,25 @@
9851012
}else{
9861013
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
9871014
}
9881015
if( cmp<0 ){
9891016
append_file_change_line(pFileFrom->zName,
990
- pFileFrom->zUuid, 0, 0, diffFlags, 0);
1017
+ pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
9911018
pFileFrom = manifest_file_next(pFrom, 0);
9921019
}else if( cmp>0 ){
9931020
append_file_change_line(pFileTo->zName,
994
- 0, pFileTo->zUuid, 0, diffFlags,
1021
+ 0, pFileTo->zUuid, 0, diffFlags, pRe,
9951022
manifest_file_mperm(pFileTo));
9961023
pFileTo = manifest_file_next(pTo, 0);
9971024
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
9981025
/* No changes */
9991026
pFileFrom = manifest_file_next(pFrom, 0);
10001027
pFileTo = manifest_file_next(pTo, 0);
10011028
}else{
10021029
append_file_change_line(pFileFrom->zName,
10031030
pFileFrom->zUuid,
1004
- pFileTo->zUuid, 0, diffFlags,
1031
+ pFileTo->zUuid, 0, diffFlags, pRe,
10051032
manifest_file_mperm(pFileTo));
10061033
pFileFrom = manifest_file_next(pFrom, 0);
10071034
pFileTo = manifest_file_next(pTo, 0);
10081035
}
10091036
}
@@ -1252,11 +1279,11 @@
12521279
}
12531280
12541281
12551282
/*
12561283
** WEBPAGE: fdiff
1257
-** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
1284
+** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN&regex=REGEX
12581285
**
12591286
** Two arguments, v1 and v2, identify the files to be diffed. Show the
12601287
** difference between the two artifacts. Show diff side by side unless sbs
12611288
** is 0. Generate plaintext if "patch" is present.
12621289
*/
@@ -1265,12 +1292,15 @@
12651292
int isPatch;
12661293
int sideBySide;
12671294
Blob c1, c2, diff, *pOut;
12681295
char *zV1;
12691296
char *zV2;
1297
+ const char *zRe;
1298
+ ReCompiled *pRe = 0;
12701299
u64 diffFlags;
12711300
const char *zStyle = "sbsdiff";
1301
+ const char *zReErr = 0;
12721302
12731303
login_check_credentials();
12741304
if( !g.perm.Read ){ login_needed(); return; }
12751305
v1 = name_to_rid_www("v1");
12761306
v2 = name_to_rid_www("v2");
@@ -1292,13 +1322,15 @@
12921322
}else{
12931323
diffFlags |= DIFF_LINENO;
12941324
zStyle = "udiff";
12951325
}
12961326
}
1327
+ zRe = P("regex");
1328
+ if( zRe ) zReErr = re_compile(&pRe, zRe, 0);
12971329
content_get(v1, &c1);
12981330
content_get(v2, &c2);
1299
- text_diff(&c1, &c2, pOut, diffFlags);
1331
+ text_diff(&c1, &c2, pOut, pRe, diffFlags);
13001332
blob_reset(&c1);
13011333
blob_reset(&c2);
13021334
if( !isPatch ){
13031335
style_header("Diff");
13041336
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
@@ -1322,10 +1354,14 @@
13221354
@ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
13231355
object_description(v1, 0, 0);
13241356
@ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
13251357
object_description(v2, 0, 0);
13261358
}
1359
+ if( pRe ){
1360
+ @ <b>Only differences that match regular expression "%h(zRe)"
1361
+ @ are shown.</b>
1362
+ }
13271363
@ <hr />
13281364
@ <div class="%s(zStyle)">
13291365
@ %s(blob_str(&diff))
13301366
@ </div>
13311367
blob_reset(&diff);
13321368
--- src/info.c
+++ src/info.c
@@ -287,13 +287,18 @@
287 }
288 }
289
290
291 /*
292 ** Append the difference between two RIDs to the output
293 */
294 static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){
 
 
 
 
 
295 int fromid;
296 int toid;
297 Blob from, to, out;
298 if( zFrom ){
299 fromid = uuid_to_rid(zFrom, 0);
@@ -307,16 +312,16 @@
307 }else{
308 blob_zero(&to);
309 }
310 blob_zero(&out);
311 if( diffFlags & DIFF_SIDEBYSIDE ){
312 text_diff(&from, &to, &out, diffFlags | DIFF_HTML);
313 @ <div class="sbsdiff">
314 @ %s(blob_str(&out))
315 @ </div>
316 }else{
317 text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML);
318 @ <div class="udiff">
319 @ %s(blob_str(&out))
320 @ </div>
321 }
322 blob_reset(&from);
@@ -333,10 +338,11 @@
333 const char *zName, /* Name of the file that has changed */
334 const char *zOld, /* blob.uuid before change. NULL for added files */
335 const char *zNew, /* blob.uuid after change. NULL for deletes */
336 const char *zOldName, /* Prior name. NULL if no name change. */
337 u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */
 
338 int mperm /* executable or symlink permission for zNew */
339 ){
340 if( !g.perm.Hyperlink ){
341 if( zNew==0 ){
342 @ <p>Deleted %h(zName)</p>
@@ -350,21 +356,21 @@
350 }else{
351 @ <p>Changes to %h(zName)</p>
352 }
353 if( diffFlags ){
354 @ <pre style="white-space:pre;">
355 append_diff(zOld, zNew, diffFlags);
356 @ </pre>
357 }
358 }else{
359 if( zOld && zNew ){
360 if( fossil_strcmp(zOld, zNew)!=0 ){
361 @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
362 @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
363 @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
364 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
365 @ <p>Name change from
366 @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
367 @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
368 }else{
369 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
370 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@@ -376,11 +382,11 @@
376 @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
377 @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
378 }
379 if( diffFlags ){
380 @ <pre style="white-space:pre;">
381 append_diff(zOld, zNew, diffFlags);
382 @ </pre>
383 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
384 @ &nbsp;&nbsp;
385 @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
386 }
@@ -444,10 +450,12 @@
444 int sideBySide; /* True for side-by-side diffs */
445 u64 diffFlags; /* Flag parameter for text_diff() */
446 const char *zName; /* Name of the checkin to be displayed */
447 const char *zUuid; /* UUID of zName */
448 const char *zParent; /* UUID of the parent checkin (if any) */
 
 
449
450 login_check_credentials();
451 if( !g.perm.Read ){ login_needed(); return; }
452 zName = P("name");
453 rid = name_to_rid_www("name");
@@ -455,10 +463,12 @@
455 style_header("Check-in Information Error");
456 @ No such object: %h(g.argv[2])
457 style_footer();
458 return;
459 }
 
 
460 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
461 zParent = db_text(0,
462 "SELECT uuid FROM plink, blob"
463 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
464 rid
@@ -479,13 +489,13 @@
479 char *zEUser, *zEComment;
480 const char *zUser;
481 const char *zComment;
482 const char *zDate;
483 const char *zOrigDate;
 
484 char *zThisBranch;
485 double thisMtime;
486 #if 0
487 int seenDiffTitle = 0;
488 #endif
489
490 style_header(zTitle);
491 login_anonymous_available();
@@ -498,11 +508,13 @@
498 TAG_COMMENT, rid);
499 zUser = db_column_text(&q, 2);
500 zComment = db_column_text(&q, 3);
501 zDate = db_column_text(&q,1);
502 zOrigDate = db_column_text(&q, 4);
 
503 thisMtime = db_column_double(&q, 5);
 
504 @ <div class="section">Overview</div>
505 @ <table class="label-value">
506 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
507 if( g.perm.Setup ){
508 @ (Record ID: %d(rid))
@@ -567,17 +579,17 @@
567 const char *zTagName = db_column_text(&q, 0);
568 @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
569 }
570 db_finalize(&q);
571
 
572 /* Select a few other branches to diff against */
573 zThisBranch = db_text("trunk", "SELECT value FROM tagxref"
574 " WHERE tagid=%d AND tagtype>0"
575 " AND rid=%d",
576 TAG_BRANCH, rid);
577
578 #if 0
579 /* Find nearby leaves to offer to diff against */
580 db_prepare(&q,
581 "SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)"
582 " FROM leaf, event, tagxref, blob"
583 " WHERE event.mtime BETWEEN %.17g AND %.17g"
@@ -690,29 +702,35 @@
690 @ show&nbsp;side-by-side&nbsp;diffs</a>
691 }
692 }
693 @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
694 @ patch</a></div>
 
 
 
 
695 db_prepare(&q,
696 "SELECT name,"
697 " mperm,"
698 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
699 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
700 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
701 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
702 " WHERE mlink.mid=%d"
 
 
703 " ORDER BY name /*sort*/",
704 rid
705 );
706 diffFlags = construct_diff_flags(showDiff, sideBySide);
707 while( db_step(&q)==SQLITE_ROW ){
708 const char *zName = db_column_text(&q,0);
709 int mperm = db_column_int(&q, 1);
710 const char *zOld = db_column_text(&q,2);
711 const char *zNew = db_column_text(&q,3);
712 const char *zOldName = db_column_text(&q, 4);
713 append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm);
714 }
715 db_finalize(&q);
716 }
717 style_footer();
718 }
@@ -931,15 +949,19 @@
931 Manifest *pFrom, *pTo;
932 ManifestFile *pFileFrom, *pFileTo;
933 const char *zBranch;
934 const char *zFrom;
935 const char *zTo;
 
 
936
937 login_check_credentials();
938 if( !g.perm.Read ){ login_needed(); return; }
939 login_anonymous_available();
940
 
 
941 zBranch = P("branch");
942 if( zBranch && zBranch[0] ){
943 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
944 cgi_replace_parameter("to", zBranch);
945 }
@@ -967,11 +989,16 @@
967 style_header("Check-in Differences");
968 @ <h2>Difference From:</h2><blockquote>
969 checkin_description(ridFrom);
970 @ </blockquote><h2>To:</h2><blockquote>
971 checkin_description(ridTo);
972 @ </blockquote><hr /><p>
 
 
 
 
 
973
974 manifest_file_rewind(pFrom);
975 pFileFrom = manifest_file_next(pFrom, 0);
976 manifest_file_rewind(pTo);
977 pFileTo = manifest_file_next(pTo, 0);
@@ -985,25 +1012,25 @@
985 }else{
986 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
987 }
988 if( cmp<0 ){
989 append_file_change_line(pFileFrom->zName,
990 pFileFrom->zUuid, 0, 0, diffFlags, 0);
991 pFileFrom = manifest_file_next(pFrom, 0);
992 }else if( cmp>0 ){
993 append_file_change_line(pFileTo->zName,
994 0, pFileTo->zUuid, 0, diffFlags,
995 manifest_file_mperm(pFileTo));
996 pFileTo = manifest_file_next(pTo, 0);
997 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
998 /* No changes */
999 pFileFrom = manifest_file_next(pFrom, 0);
1000 pFileTo = manifest_file_next(pTo, 0);
1001 }else{
1002 append_file_change_line(pFileFrom->zName,
1003 pFileFrom->zUuid,
1004 pFileTo->zUuid, 0, diffFlags,
1005 manifest_file_mperm(pFileTo));
1006 pFileFrom = manifest_file_next(pFrom, 0);
1007 pFileTo = manifest_file_next(pTo, 0);
1008 }
1009 }
@@ -1252,11 +1279,11 @@
1252 }
1253
1254
1255 /*
1256 ** WEBPAGE: fdiff
1257 ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
1258 **
1259 ** Two arguments, v1 and v2, identify the files to be diffed. Show the
1260 ** difference between the two artifacts. Show diff side by side unless sbs
1261 ** is 0. Generate plaintext if "patch" is present.
1262 */
@@ -1265,12 +1292,15 @@
1265 int isPatch;
1266 int sideBySide;
1267 Blob c1, c2, diff, *pOut;
1268 char *zV1;
1269 char *zV2;
 
 
1270 u64 diffFlags;
1271 const char *zStyle = "sbsdiff";
 
1272
1273 login_check_credentials();
1274 if( !g.perm.Read ){ login_needed(); return; }
1275 v1 = name_to_rid_www("v1");
1276 v2 = name_to_rid_www("v2");
@@ -1292,13 +1322,15 @@
1292 }else{
1293 diffFlags |= DIFF_LINENO;
1294 zStyle = "udiff";
1295 }
1296 }
 
 
1297 content_get(v1, &c1);
1298 content_get(v2, &c2);
1299 text_diff(&c1, &c2, pOut, diffFlags);
1300 blob_reset(&c1);
1301 blob_reset(&c2);
1302 if( !isPatch ){
1303 style_header("Diff");
1304 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
@@ -1322,10 +1354,14 @@
1322 @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
1323 object_description(v1, 0, 0);
1324 @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
1325 object_description(v2, 0, 0);
1326 }
 
 
 
 
1327 @ <hr />
1328 @ <div class="%s(zStyle)">
1329 @ %s(blob_str(&diff))
1330 @ </div>
1331 blob_reset(&diff);
1332
--- src/info.c
+++ src/info.c
@@ -287,13 +287,18 @@
287 }
288 }
289
290
291 /*
292 ** Append the difference between artifacts to the output
293 */
294 static void append_diff(
295 const char *zFrom, /* Diff from this artifact */
296 const char *zTo, /* ... to this artifact */
297 u64 diffFlags, /* Diff formatting flags */
298 ReCompiled *pRe /* Only show change matching this regex */
299 ){
300 int fromid;
301 int toid;
302 Blob from, to, out;
303 if( zFrom ){
304 fromid = uuid_to_rid(zFrom, 0);
@@ -307,16 +312,16 @@
312 }else{
313 blob_zero(&to);
314 }
315 blob_zero(&out);
316 if( diffFlags & DIFF_SIDEBYSIDE ){
317 text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML);
318 @ <div class="sbsdiff">
319 @ %s(blob_str(&out))
320 @ </div>
321 }else{
322 text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML);
323 @ <div class="udiff">
324 @ %s(blob_str(&out))
325 @ </div>
326 }
327 blob_reset(&from);
@@ -333,10 +338,11 @@
338 const char *zName, /* Name of the file that has changed */
339 const char *zOld, /* blob.uuid before change. NULL for added files */
340 const char *zNew, /* blob.uuid after change. NULL for deletes */
341 const char *zOldName, /* Prior name. NULL if no name change. */
342 u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */
343 ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */
344 int mperm /* executable or symlink permission for zNew */
345 ){
346 if( !g.perm.Hyperlink ){
347 if( zNew==0 ){
348 @ <p>Deleted %h(zName)</p>
@@ -350,21 +356,21 @@
356 }else{
357 @ <p>Changes to %h(zName)</p>
358 }
359 if( diffFlags ){
360 @ <pre style="white-space:pre;">
361 append_diff(zOld, zNew, diffFlags, pRe);
362 @ </pre>
363 }
364 }else{
365 if( zOld && zNew ){
366 if( fossil_strcmp(zOld, zNew)!=0 ){
367 @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
368 @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
369 @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
370 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
371 @ <p>Name change
372 @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
373 @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
374 }else{
375 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
376 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@@ -376,11 +382,11 @@
382 @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
383 @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
384 }
385 if( diffFlags ){
386 @ <pre style="white-space:pre;">
387 append_diff(zOld, zNew, diffFlags, pRe);
388 @ </pre>
389 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
390 @ &nbsp;&nbsp;
391 @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
392 }
@@ -444,10 +450,12 @@
450 int sideBySide; /* True for side-by-side diffs */
451 u64 diffFlags; /* Flag parameter for text_diff() */
452 const char *zName; /* Name of the checkin to be displayed */
453 const char *zUuid; /* UUID of zName */
454 const char *zParent; /* UUID of the parent checkin (if any) */
455 const char *zRe; /* regex parameter */
456 ReCompiled *pRe = 0; /* regex */
457
458 login_check_credentials();
459 if( !g.perm.Read ){ login_needed(); return; }
460 zName = P("name");
461 rid = name_to_rid_www("name");
@@ -455,10 +463,12 @@
463 style_header("Check-in Information Error");
464 @ No such object: %h(g.argv[2])
465 style_footer();
466 return;
467 }
468 zRe = P("regex");
469 if( zRe ) re_compile(&pRe, zRe, 0);
470 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
471 zParent = db_text(0,
472 "SELECT uuid FROM plink, blob"
473 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
474 rid
@@ -479,13 +489,13 @@
489 char *zEUser, *zEComment;
490 const char *zUser;
491 const char *zComment;
492 const char *zDate;
493 const char *zOrigDate;
494 #if 0
495 char *zThisBranch;
496 double thisMtime;
 
497 int seenDiffTitle = 0;
498 #endif
499
500 style_header(zTitle);
501 login_anonymous_available();
@@ -498,11 +508,13 @@
508 TAG_COMMENT, rid);
509 zUser = db_column_text(&q, 2);
510 zComment = db_column_text(&q, 3);
511 zDate = db_column_text(&q,1);
512 zOrigDate = db_column_text(&q, 4);
513 #if 0
514 thisMtime = db_column_double(&q, 5);
515 #endif
516 @ <div class="section">Overview</div>
517 @ <table class="label-value">
518 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
519 if( g.perm.Setup ){
520 @ (Record ID: %d(rid))
@@ -567,17 +579,17 @@
579 const char *zTagName = db_column_text(&q, 0);
580 @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
581 }
582 db_finalize(&q);
583
584 #if 0
585 /* Select a few other branches to diff against */
586 zThisBranch = db_text("trunk", "SELECT value FROM tagxref"
587 " WHERE tagid=%d AND tagtype>0"
588 " AND rid=%d",
589 TAG_BRANCH, rid);
590
 
591 /* Find nearby leaves to offer to diff against */
592 db_prepare(&q,
593 "SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)"
594 " FROM leaf, event, tagxref, blob"
595 " WHERE event.mtime BETWEEN %.17g AND %.17g"
@@ -690,29 +702,35 @@
702 @ show&nbsp;side-by-side&nbsp;diffs</a>
703 }
704 }
705 @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
706 @ patch</a></div>
707 if( pRe ){
708 @ <p><b>Only differences that match regular expression "%h(zRe)"
709 @ are shown.</b></p>
710 }
711 db_prepare(&q,
712 "SELECT name,"
713 " mperm,"
714 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
715 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
716 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
717 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
718 " WHERE mlink.mid=%d"
719 " AND (mlink.fid>0"
720 " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
721 " ORDER BY name /*sort*/",
722 rid, rid
723 );
724 diffFlags = construct_diff_flags(showDiff, sideBySide);
725 while( db_step(&q)==SQLITE_ROW ){
726 const char *zName = db_column_text(&q,0);
727 int mperm = db_column_int(&q, 1);
728 const char *zOld = db_column_text(&q,2);
729 const char *zNew = db_column_text(&q,3);
730 const char *zOldName = db_column_text(&q, 4);
731 append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
732 }
733 db_finalize(&q);
734 }
735 style_footer();
736 }
@@ -931,15 +949,19 @@
949 Manifest *pFrom, *pTo;
950 ManifestFile *pFileFrom, *pFileTo;
951 const char *zBranch;
952 const char *zFrom;
953 const char *zTo;
954 const char *zRe;
955 ReCompiled *pRe = 0;
956
957 login_check_credentials();
958 if( !g.perm.Read ){ login_needed(); return; }
959 login_anonymous_available();
960
961 zRe = P("regex");
962 if( zRe ) re_compile(&pRe, zRe, 0);
963 zBranch = P("branch");
964 if( zBranch && zBranch[0] ){
965 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
966 cgi_replace_parameter("to", zBranch);
967 }
@@ -967,11 +989,16 @@
989 style_header("Check-in Differences");
990 @ <h2>Difference From:</h2><blockquote>
991 checkin_description(ridFrom);
992 @ </blockquote><h2>To:</h2><blockquote>
993 checkin_description(ridTo);
994 @ </blockquote>
995 if( pRe ){
996 @ <p><b>Only differences that match regular expression "%h(zRe)"
997 @ are shown.</b></p>
998 }
999 @<hr /><p>
1000
1001 manifest_file_rewind(pFrom);
1002 pFileFrom = manifest_file_next(pFrom, 0);
1003 manifest_file_rewind(pTo);
1004 pFileTo = manifest_file_next(pTo, 0);
@@ -985,25 +1012,25 @@
1012 }else{
1013 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
1014 }
1015 if( cmp<0 ){
1016 append_file_change_line(pFileFrom->zName,
1017 pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
1018 pFileFrom = manifest_file_next(pFrom, 0);
1019 }else if( cmp>0 ){
1020 append_file_change_line(pFileTo->zName,
1021 0, pFileTo->zUuid, 0, diffFlags, pRe,
1022 manifest_file_mperm(pFileTo));
1023 pFileTo = manifest_file_next(pTo, 0);
1024 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
1025 /* No changes */
1026 pFileFrom = manifest_file_next(pFrom, 0);
1027 pFileTo = manifest_file_next(pTo, 0);
1028 }else{
1029 append_file_change_line(pFileFrom->zName,
1030 pFileFrom->zUuid,
1031 pFileTo->zUuid, 0, diffFlags, pRe,
1032 manifest_file_mperm(pFileTo));
1033 pFileFrom = manifest_file_next(pFrom, 0);
1034 pFileTo = manifest_file_next(pTo, 0);
1035 }
1036 }
@@ -1252,11 +1279,11 @@
1279 }
1280
1281
1282 /*
1283 ** WEBPAGE: fdiff
1284 ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN&regex=REGEX
1285 **
1286 ** Two arguments, v1 and v2, identify the files to be diffed. Show the
1287 ** difference between the two artifacts. Show diff side by side unless sbs
1288 ** is 0. Generate plaintext if "patch" is present.
1289 */
@@ -1265,12 +1292,15 @@
1292 int isPatch;
1293 int sideBySide;
1294 Blob c1, c2, diff, *pOut;
1295 char *zV1;
1296 char *zV2;
1297 const char *zRe;
1298 ReCompiled *pRe = 0;
1299 u64 diffFlags;
1300 const char *zStyle = "sbsdiff";
1301 const char *zReErr = 0;
1302
1303 login_check_credentials();
1304 if( !g.perm.Read ){ login_needed(); return; }
1305 v1 = name_to_rid_www("v1");
1306 v2 = name_to_rid_www("v2");
@@ -1292,13 +1322,15 @@
1322 }else{
1323 diffFlags |= DIFF_LINENO;
1324 zStyle = "udiff";
1325 }
1326 }
1327 zRe = P("regex");
1328 if( zRe ) zReErr = re_compile(&pRe, zRe, 0);
1329 content_get(v1, &c1);
1330 content_get(v2, &c2);
1331 text_diff(&c1, &c2, pOut, pRe, diffFlags);
1332 blob_reset(&c1);
1333 blob_reset(&c2);
1334 if( !isPatch ){
1335 style_header("Diff");
1336 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
@@ -1322,10 +1354,14 @@
1354 @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
1355 object_description(v1, 0, 0);
1356 @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
1357 object_description(v2, 0, 0);
1358 }
1359 if( pRe ){
1360 @ <b>Only differences that match regular expression "%h(zRe)"
1361 @ are shown.</b>
1362 }
1363 @ <hr />
1364 @ <div class="%s(zStyle)">
1365 @ %s(blob_str(&diff))
1366 @ </div>
1367 blob_reset(&diff);
1368
+1 -1
--- src/json_diff.c
+++ src/json_diff.c
@@ -58,11 +58,11 @@
5858
return NULL;
5959
}
6060
content_get(fromid, &from);
6161
content_get(toid, &to);
6262
blob_zero(&out);
63
- text_diff(&from, &to, &out, flags);
63
+ text_diff(&from, &to, &out, 0, flags);
6464
blob_reset(&from);
6565
blob_reset(&to);
6666
outLen = blob_size(&out);
6767
if(outLen>=0){
6868
rc = cson_value_new_string(blob_buffer(&out),
6969
--- src/json_diff.c
+++ src/json_diff.c
@@ -58,11 +58,11 @@
58 return NULL;
59 }
60 content_get(fromid, &from);
61 content_get(toid, &to);
62 blob_zero(&out);
63 text_diff(&from, &to, &out, flags);
64 blob_reset(&from);
65 blob_reset(&to);
66 outLen = blob_size(&out);
67 if(outLen>=0){
68 rc = cson_value_new_string(blob_buffer(&out),
69
--- src/json_diff.c
+++ src/json_diff.c
@@ -58,11 +58,11 @@
58 return NULL;
59 }
60 content_get(fromid, &from);
61 content_get(toid, &to);
62 blob_zero(&out);
63 text_diff(&from, &to, &out, 0, flags);
64 blob_reset(&from);
65 blob_reset(&to);
66 outLen = blob_size(&out);
67 if(outLen>=0){
68 rc = cson_value_new_string(blob_buffer(&out),
69
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -90,11 +90,11 @@
9090
9191
/*
9292
** Return a pointer to a constant string that forms the basis
9393
** for a timeline query for the JSON interface.
9494
*/
95
-const char const * json_timeline_query(void){
95
+char const * json_timeline_query(void){
9696
/* Field order MUST match that from json_timeline_temp_table()!!! */
9797
static const char zBaseSql[] =
9898
@ SELECT
9999
@ NULL,
100100
@ blob.rid,
101101
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -90,11 +90,11 @@
90
91 /*
92 ** Return a pointer to a constant string that forms the basis
93 ** for a timeline query for the JSON interface.
94 */
95 const char const * json_timeline_query(void){
96 /* Field order MUST match that from json_timeline_temp_table()!!! */
97 static const char zBaseSql[] =
98 @ SELECT
99 @ NULL,
100 @ blob.rid,
101
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -90,11 +90,11 @@
90
91 /*
92 ** Return a pointer to a constant string that forms the basis
93 ** for a timeline query for the JSON interface.
94 */
95 char const * json_timeline_query(void){
96 /* Field order MUST match that from json_timeline_temp_table()!!! */
97 static const char zBaseSql[] =
98 @ SELECT
99 @ NULL,
100 @ blob.rid,
101
+1 -1
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -543,11 +543,11 @@
543543
blob_init(&w1, pW1->zWiki, -1);
544544
blob_zero(&w2);
545545
blob_init(&w2, pW2->zWiki, -1);
546546
blob_zero(&d);
547547
diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
548
- text_diff(&w2, &w1, &d, diffFlags);
548
+ text_diff(&w2, &w1, &d, 0, diffFlags);
549549
blob_reset(&w1);
550550
blob_reset(&w2);
551551
552552
pay = cson_new_object();
553553
554554
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -543,11 +543,11 @@
543 blob_init(&w1, pW1->zWiki, -1);
544 blob_zero(&w2);
545 blob_init(&w2, pW2->zWiki, -1);
546 blob_zero(&d);
547 diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
548 text_diff(&w2, &w1, &d, diffFlags);
549 blob_reset(&w1);
550 blob_reset(&w2);
551
552 pay = cson_new_object();
553
554
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -543,11 +543,11 @@
543 blob_init(&w1, pW1->zWiki, -1);
544 blob_zero(&w2);
545 blob_init(&w2, pW2->zWiki, -1);
546 blob_zero(&d);
547 diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
548 text_diff(&w2, &w1, &d, 0, diffFlags);
549 blob_reset(&w1);
550 blob_reset(&w2);
551
552 pay = cson_new_object();
553
554
+2 -2
--- src/login.c
+++ src/login.c
@@ -397,11 +397,11 @@
397397
}
398398
if( memcmp(zAgent, "Mozilla/", 8)==0 ){
399399
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
400400
if( strglob("*Firefox/[1-9]*", zAgent) ) return 1;
401401
if( strglob("*Chrome/[1-9]*", zAgent) ) return 1;
402
- if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1;
402
+ if( strglob("*(compatible;?MSIE?[1789]*", zAgent) ) return 1;
403403
if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1;
404404
return 0;
405405
}
406406
if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
407407
if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -625,11 +625,11 @@
625625
@ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
626626
}
627627
if( zAnonPw ){
628628
unsigned int uSeed = captcha_seed();
629629
char const *zDecoded = captcha_decode(uSeed);
630
- int bAutoCaptcha = db_get_boolean("auto-captcha", 1);
630
+ int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
631631
char *zCaptcha = captcha_render(zDecoded);
632632
633633
@ <p><input type="hidden" name="cs" value="%u(uSeed)" />
634634
@ Visitors may enter <b>anonymous</b> as the user-ID with
635635
@ the 8-character hexadecimal password shown below:</p>
636636
--- src/login.c
+++ src/login.c
@@ -397,11 +397,11 @@
397 }
398 if( memcmp(zAgent, "Mozilla/", 8)==0 ){
399 if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
400 if( strglob("*Firefox/[1-9]*", zAgent) ) return 1;
401 if( strglob("*Chrome/[1-9]*", zAgent) ) return 1;
402 if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1;
403 if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1;
404 return 0;
405 }
406 if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
407 if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -625,11 +625,11 @@
625 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
626 }
627 if( zAnonPw ){
628 unsigned int uSeed = captcha_seed();
629 char const *zDecoded = captcha_decode(uSeed);
630 int bAutoCaptcha = db_get_boolean("auto-captcha", 1);
631 char *zCaptcha = captcha_render(zDecoded);
632
633 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
634 @ Visitors may enter <b>anonymous</b> as the user-ID with
635 @ the 8-character hexadecimal password shown below:</p>
636
--- src/login.c
+++ src/login.c
@@ -397,11 +397,11 @@
397 }
398 if( memcmp(zAgent, "Mozilla/", 8)==0 ){
399 if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
400 if( strglob("*Firefox/[1-9]*", zAgent) ) return 1;
401 if( strglob("*Chrome/[1-9]*", zAgent) ) return 1;
402 if( strglob("*(compatible;?MSIE?[1789]*", zAgent) ) return 1;
403 if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1;
404 return 0;
405 }
406 if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
407 if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -625,11 +625,11 @@
625 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
626 }
627 if( zAnonPw ){
628 unsigned int uSeed = captcha_seed();
629 char const *zDecoded = captcha_decode(uSeed);
630 int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
631 char *zCaptcha = captcha_render(zDecoded);
632
633 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
634 @ Visitors may enter <b>anonymous</b> as the user-ID with
635 @ the 8-character hexadecimal password shown below:</p>
636
+3 -1
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932932
*/
933933
void verify_all_options(void){
934934
int i;
935935
for(i=1; i<g.argc; i++){
936936
if( g.argv[i][0]=='-' ){
937
- fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]);
937
+ fossil_fatal(
938
+ "unrecognized command-line option, or missing argument: %s",
939
+ g.argv[i]);
938940
}
939941
}
940942
}
941943
942944
/*
943945
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932 */
933 void verify_all_options(void){
934 int i;
935 for(i=1; i<g.argc; i++){
936 if( g.argv[i][0]=='-' ){
937 fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]);
 
 
938 }
939 }
940 }
941
942 /*
943
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932 */
933 void verify_all_options(void){
934 int i;
935 for(i=1; i<g.argc; i++){
936 if( g.argv[i][0]=='-' ){
937 fossil_fatal(
938 "unrecognized command-line option, or missing argument: %s",
939 g.argv[i]);
940 }
941 }
942 }
943
944 /*
945
+3 -1
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932932
*/
933933
void verify_all_options(void){
934934
int i;
935935
for(i=1; i<g.argc; i++){
936936
if( g.argv[i][0]=='-' ){
937
- fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]);
937
+ fossil_fatal(
938
+ "unrecognized command-line option, or missing argument: %s",
939
+ g.argv[i]);
938940
}
939941
}
940942
}
941943
942944
/*
943945
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932 */
933 void verify_all_options(void){
934 int i;
935 for(i=1; i<g.argc; i++){
936 if( g.argv[i][0]=='-' ){
937 fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]);
 
 
938 }
939 }
940 }
941
942 /*
943
--- src/main.c
+++ src/main.c
@@ -932,11 +932,13 @@
932 */
933 void verify_all_options(void){
934 int i;
935 for(i=1; i<g.argc; i++){
936 if( g.argv[i][0]=='-' ){
937 fossil_fatal(
938 "unrecognized command-line option, or missing argument: %s",
939 g.argv[i]);
940 }
941 }
942 }
943
944 /*
945
+21 -1
--- src/main.mk
+++ src/main.mk
@@ -81,10 +81,11 @@
8181
$(SRCDIR)/pivot.c \
8282
$(SRCDIR)/popen.c \
8383
$(SRCDIR)/pqueue.c \
8484
$(SRCDIR)/printf.c \
8585
$(SRCDIR)/rebuild.c \
86
+ $(SRCDIR)/regexp.c \
8687
$(SRCDIR)/report.c \
8788
$(SRCDIR)/rss.c \
8889
$(SRCDIR)/schema.c \
8990
$(SRCDIR)/search.c \
9091
$(SRCDIR)/setup.c \
@@ -101,10 +102,11 @@
101102
$(SRCDIR)/th_main.c \
102103
$(SRCDIR)/timeline.c \
103104
$(SRCDIR)/tkt.c \
104105
$(SRCDIR)/tktsetup.c \
105106
$(SRCDIR)/undo.c \
107
+ $(SRCDIR)/unicode.c \
106108
$(SRCDIR)/update.c \
107109
$(SRCDIR)/url.c \
108110
$(SRCDIR)/user.c \
109111
$(SRCDIR)/utf8.c \
110112
$(SRCDIR)/verify.c \
@@ -185,10 +187,11 @@
185187
$(OBJDIR)/pivot_.c \
186188
$(OBJDIR)/popen_.c \
187189
$(OBJDIR)/pqueue_.c \
188190
$(OBJDIR)/printf_.c \
189191
$(OBJDIR)/rebuild_.c \
192
+ $(OBJDIR)/regexp_.c \
190193
$(OBJDIR)/report_.c \
191194
$(OBJDIR)/rss_.c \
192195
$(OBJDIR)/schema_.c \
193196
$(OBJDIR)/search_.c \
194197
$(OBJDIR)/setup_.c \
@@ -205,10 +208,11 @@
205208
$(OBJDIR)/th_main_.c \
206209
$(OBJDIR)/timeline_.c \
207210
$(OBJDIR)/tkt_.c \
208211
$(OBJDIR)/tktsetup_.c \
209212
$(OBJDIR)/undo_.c \
213
+ $(OBJDIR)/unicode_.c \
210214
$(OBJDIR)/update_.c \
211215
$(OBJDIR)/url_.c \
212216
$(OBJDIR)/user_.c \
213217
$(OBJDIR)/utf8_.c \
214218
$(OBJDIR)/verify_.c \
@@ -289,10 +293,11 @@
289293
$(OBJDIR)/pivot.o \
290294
$(OBJDIR)/popen.o \
291295
$(OBJDIR)/pqueue.o \
292296
$(OBJDIR)/printf.o \
293297
$(OBJDIR)/rebuild.o \
298
+ $(OBJDIR)/regexp.o \
294299
$(OBJDIR)/report.o \
295300
$(OBJDIR)/rss.o \
296301
$(OBJDIR)/schema.o \
297302
$(OBJDIR)/search.o \
298303
$(OBJDIR)/setup.o \
@@ -309,10 +314,11 @@
309314
$(OBJDIR)/th_main.o \
310315
$(OBJDIR)/timeline.o \
311316
$(OBJDIR)/tkt.o \
312317
$(OBJDIR)/tktsetup.o \
313318
$(OBJDIR)/undo.o \
319
+ $(OBJDIR)/unicode.o \
314320
$(OBJDIR)/update.o \
315321
$(OBJDIR)/url.o \
316322
$(OBJDIR)/user.o \
317323
$(OBJDIR)/utf8.o \
318324
$(OBJDIR)/verify.o \
@@ -390,11 +396,11 @@
390396
391397
392398
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
393399
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
394400
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
395
- $(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_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_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)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/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)/utf8_.c:$(OBJDIR)/utf8.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)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
401
+ $(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_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_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)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/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)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
396402
touch $(OBJDIR)/headers
397403
$(OBJDIR)/headers: Makefile
398404
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
399405
Makefile:
400406
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -878,10 +884,17 @@
878884
879885
$(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
880886
$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
881887
882888
$(OBJDIR)/rebuild.h: $(OBJDIR)/headers
889
+$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
890
+ $(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
891
+
892
+$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
893
+ $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
894
+
895
+$(OBJDIR)/regexp.h: $(OBJDIR)/headers
883896
$(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
884897
$(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c
885898
886899
$(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
887900
$(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c
@@ -1018,10 +1031,17 @@
10181031
10191032
$(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
10201033
$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
10211034
10221035
$(OBJDIR)/undo.h: $(OBJDIR)/headers
1036
+$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1037
+ $(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1038
+
1039
+$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1040
+ $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1041
+
1042
+$(OBJDIR)/unicode.h: $(OBJDIR)/headers
10231043
$(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
10241044
$(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c
10251045
10261046
$(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
10271047
$(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c
10281048
--- src/main.mk
+++ src/main.mk
@@ -81,10 +81,11 @@
81 $(SRCDIR)/pivot.c \
82 $(SRCDIR)/popen.c \
83 $(SRCDIR)/pqueue.c \
84 $(SRCDIR)/printf.c \
85 $(SRCDIR)/rebuild.c \
 
86 $(SRCDIR)/report.c \
87 $(SRCDIR)/rss.c \
88 $(SRCDIR)/schema.c \
89 $(SRCDIR)/search.c \
90 $(SRCDIR)/setup.c \
@@ -101,10 +102,11 @@
101 $(SRCDIR)/th_main.c \
102 $(SRCDIR)/timeline.c \
103 $(SRCDIR)/tkt.c \
104 $(SRCDIR)/tktsetup.c \
105 $(SRCDIR)/undo.c \
 
106 $(SRCDIR)/update.c \
107 $(SRCDIR)/url.c \
108 $(SRCDIR)/user.c \
109 $(SRCDIR)/utf8.c \
110 $(SRCDIR)/verify.c \
@@ -185,10 +187,11 @@
185 $(OBJDIR)/pivot_.c \
186 $(OBJDIR)/popen_.c \
187 $(OBJDIR)/pqueue_.c \
188 $(OBJDIR)/printf_.c \
189 $(OBJDIR)/rebuild_.c \
 
190 $(OBJDIR)/report_.c \
191 $(OBJDIR)/rss_.c \
192 $(OBJDIR)/schema_.c \
193 $(OBJDIR)/search_.c \
194 $(OBJDIR)/setup_.c \
@@ -205,10 +208,11 @@
205 $(OBJDIR)/th_main_.c \
206 $(OBJDIR)/timeline_.c \
207 $(OBJDIR)/tkt_.c \
208 $(OBJDIR)/tktsetup_.c \
209 $(OBJDIR)/undo_.c \
 
210 $(OBJDIR)/update_.c \
211 $(OBJDIR)/url_.c \
212 $(OBJDIR)/user_.c \
213 $(OBJDIR)/utf8_.c \
214 $(OBJDIR)/verify_.c \
@@ -289,10 +293,11 @@
289 $(OBJDIR)/pivot.o \
290 $(OBJDIR)/popen.o \
291 $(OBJDIR)/pqueue.o \
292 $(OBJDIR)/printf.o \
293 $(OBJDIR)/rebuild.o \
 
294 $(OBJDIR)/report.o \
295 $(OBJDIR)/rss.o \
296 $(OBJDIR)/schema.o \
297 $(OBJDIR)/search.o \
298 $(OBJDIR)/setup.o \
@@ -309,10 +314,11 @@
309 $(OBJDIR)/th_main.o \
310 $(OBJDIR)/timeline.o \
311 $(OBJDIR)/tkt.o \
312 $(OBJDIR)/tktsetup.o \
313 $(OBJDIR)/undo.o \
 
314 $(OBJDIR)/update.o \
315 $(OBJDIR)/url.o \
316 $(OBJDIR)/user.o \
317 $(OBJDIR)/utf8.o \
318 $(OBJDIR)/verify.o \
@@ -390,11 +396,11 @@
390
391
392 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
393 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
394 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
395 $(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_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_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)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/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)/utf8_.c:$(OBJDIR)/utf8.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)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
396 touch $(OBJDIR)/headers
397 $(OBJDIR)/headers: Makefile
398 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
399 Makefile:
400 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -878,10 +884,17 @@
878
879 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
880 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
881
882 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
883 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
884 $(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c
885
886 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
887 $(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c
@@ -1018,10 +1031,17 @@
1018
1019 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1020 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1021
1022 $(OBJDIR)/undo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
1023 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1024 $(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1025
1026 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1027 $(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c
1028
--- src/main.mk
+++ src/main.mk
@@ -81,10 +81,11 @@
81 $(SRCDIR)/pivot.c \
82 $(SRCDIR)/popen.c \
83 $(SRCDIR)/pqueue.c \
84 $(SRCDIR)/printf.c \
85 $(SRCDIR)/rebuild.c \
86 $(SRCDIR)/regexp.c \
87 $(SRCDIR)/report.c \
88 $(SRCDIR)/rss.c \
89 $(SRCDIR)/schema.c \
90 $(SRCDIR)/search.c \
91 $(SRCDIR)/setup.c \
@@ -101,10 +102,11 @@
102 $(SRCDIR)/th_main.c \
103 $(SRCDIR)/timeline.c \
104 $(SRCDIR)/tkt.c \
105 $(SRCDIR)/tktsetup.c \
106 $(SRCDIR)/undo.c \
107 $(SRCDIR)/unicode.c \
108 $(SRCDIR)/update.c \
109 $(SRCDIR)/url.c \
110 $(SRCDIR)/user.c \
111 $(SRCDIR)/utf8.c \
112 $(SRCDIR)/verify.c \
@@ -185,10 +187,11 @@
187 $(OBJDIR)/pivot_.c \
188 $(OBJDIR)/popen_.c \
189 $(OBJDIR)/pqueue_.c \
190 $(OBJDIR)/printf_.c \
191 $(OBJDIR)/rebuild_.c \
192 $(OBJDIR)/regexp_.c \
193 $(OBJDIR)/report_.c \
194 $(OBJDIR)/rss_.c \
195 $(OBJDIR)/schema_.c \
196 $(OBJDIR)/search_.c \
197 $(OBJDIR)/setup_.c \
@@ -205,10 +208,11 @@
208 $(OBJDIR)/th_main_.c \
209 $(OBJDIR)/timeline_.c \
210 $(OBJDIR)/tkt_.c \
211 $(OBJDIR)/tktsetup_.c \
212 $(OBJDIR)/undo_.c \
213 $(OBJDIR)/unicode_.c \
214 $(OBJDIR)/update_.c \
215 $(OBJDIR)/url_.c \
216 $(OBJDIR)/user_.c \
217 $(OBJDIR)/utf8_.c \
218 $(OBJDIR)/verify_.c \
@@ -289,10 +293,11 @@
293 $(OBJDIR)/pivot.o \
294 $(OBJDIR)/popen.o \
295 $(OBJDIR)/pqueue.o \
296 $(OBJDIR)/printf.o \
297 $(OBJDIR)/rebuild.o \
298 $(OBJDIR)/regexp.o \
299 $(OBJDIR)/report.o \
300 $(OBJDIR)/rss.o \
301 $(OBJDIR)/schema.o \
302 $(OBJDIR)/search.o \
303 $(OBJDIR)/setup.o \
@@ -309,10 +314,11 @@
314 $(OBJDIR)/th_main.o \
315 $(OBJDIR)/timeline.o \
316 $(OBJDIR)/tkt.o \
317 $(OBJDIR)/tktsetup.o \
318 $(OBJDIR)/undo.o \
319 $(OBJDIR)/unicode.o \
320 $(OBJDIR)/update.o \
321 $(OBJDIR)/url.o \
322 $(OBJDIR)/user.o \
323 $(OBJDIR)/utf8.o \
324 $(OBJDIR)/verify.o \
@@ -390,11 +396,11 @@
396
397
398 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
399 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
400 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
401 $(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_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_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)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/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)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
402 touch $(OBJDIR)/headers
403 $(OBJDIR)/headers: Makefile
404 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
405 Makefile:
406 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -878,10 +884,17 @@
884
885 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
886 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
887
888 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
889 $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
890 $(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
891
892 $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
893 $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
894
895 $(OBJDIR)/regexp.h: $(OBJDIR)/headers
896 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
897 $(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c
898
899 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
900 $(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c
@@ -1018,10 +1031,17 @@
1031
1032 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1033 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1034
1035 $(OBJDIR)/undo.h: $(OBJDIR)/headers
1036 $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1037 $(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1038
1039 $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1040 $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1041
1042 $(OBJDIR)/unicode.h: $(OBJDIR)/headers
1043 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1044 $(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1045
1046 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1047 $(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c
1048
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -84,10 +84,11 @@
8484
pivot
8585
popen
8686
pqueue
8787
printf
8888
rebuild
89
+ regexp
8990
report
9091
rss
9192
schema
9293
search
9394
setup
@@ -104,10 +105,11 @@
104105
th_main
105106
timeline
106107
tkt
107108
tktsetup
108109
undo
110
+ unicode
109111
update
110112
url
111113
user
112114
utf8
113115
verify
@@ -401,11 +403,11 @@
401403
402404
#### Check if the workaround for the MinGW command line handling needs to
403405
# be enabled by default.
404406
#
405407
ifndef BROKEN_MINGW_CMDLINE
406
-ifeq ($(PREFIX),)
408
+ifeq (,$(findstring w64-mingw32,$(PREFIX)))
407409
BROKEN_MINGW_CMDLINE = 1
408410
endif
409411
endif
410412
411413
#### The directories where the zlib include and library files are located.
412414
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -84,10 +84,11 @@
84 pivot
85 popen
86 pqueue
87 printf
88 rebuild
 
89 report
90 rss
91 schema
92 search
93 setup
@@ -104,10 +105,11 @@
104 th_main
105 timeline
106 tkt
107 tktsetup
108 undo
 
109 update
110 url
111 user
112 utf8
113 verify
@@ -401,11 +403,11 @@
401
402 #### Check if the workaround for the MinGW command line handling needs to
403 # be enabled by default.
404 #
405 ifndef BROKEN_MINGW_CMDLINE
406 ifeq ($(PREFIX),)
407 BROKEN_MINGW_CMDLINE = 1
408 endif
409 endif
410
411 #### The directories where the zlib include and library files are located.
412
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -84,10 +84,11 @@
84 pivot
85 popen
86 pqueue
87 printf
88 rebuild
89 regexp
90 report
91 rss
92 schema
93 search
94 setup
@@ -104,10 +105,11 @@
105 th_main
106 timeline
107 tkt
108 tktsetup
109 undo
110 unicode
111 update
112 url
113 user
114 utf8
115 verify
@@ -401,11 +403,11 @@
403
404 #### Check if the workaround for the MinGW command line handling needs to
405 # be enabled by default.
406 #
407 ifndef BROKEN_MINGW_CMDLINE
408 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
409 BROKEN_MINGW_CMDLINE = 1
410 endif
411 endif
412
413 #### The directories where the zlib include and library files are located.
414
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -430,11 +430,11 @@
430430
zTarget = next_token(&x, &nTarget);
431431
zSrc = next_token(&x, &nSrc);
432432
if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
433433
if( p->zAttachName!=0 ) goto manifest_syntax_error;
434434
defossilize(zName);
435
- if( !file_is_simple_pathname(zName) ){
435
+ if( !file_is_simple_pathname(zName, 0) ){
436436
SYNTAX("invalid filename on A-card");
437437
}
438438
defossilize(zTarget);
439439
if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
440440
&& !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
@@ -524,11 +524,11 @@
524524
case 'F': {
525525
char *zName, *zPerm, *zPriorName;
526526
zName = next_token(&x,0);
527527
if( zName==0 ) SYNTAX("missing filename on F-card");
528528
defossilize(zName);
529
- if( !file_is_simple_pathname(zName) ){
529
+ if( !file_is_simple_pathname(zName, 0) ){
530530
SYNTAX("F-card filename is not a simple path");
531531
}
532532
zUuid = next_token(&x, &sz);
533533
if( p->zBaseline==0 || zUuid!=0 ){
534534
if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size");
@@ -536,11 +536,11 @@
536536
}
537537
zPerm = next_token(&x,0);
538538
zPriorName = next_token(&x,0);
539539
if( zPriorName ){
540540
defossilize(zPriorName);
541
- if( !file_is_simple_pathname(zPriorName) ){
541
+ if( !file_is_simple_pathname(zPriorName, 0) ){
542542
SYNTAX("F-card old filename is not a simple path");
543543
}
544544
}
545545
if( p->nFile>=p->nFileAlloc ){
546546
p->nFileAlloc = p->nFileAlloc*2 + 10;
@@ -1983,5 +1983,23 @@
19831983
manifest_destroy(p);
19841984
}
19851985
assert( blob_is_reset(pContent) );
19861986
return 1;
19871987
}
1988
+
1989
+/*
1990
+** COMMAND: test-crosslink
1991
+**
1992
+** Usage: %fossil test-crosslink RECORDID
1993
+**
1994
+** Run the manifest_crosslink() routine on the artifact with the given
1995
+** record ID. This is typically done in the debugger.
1996
+*/
1997
+void test_crosslink_cmd(void){
1998
+ int rid;
1999
+ Blob content;
2000
+ db_find_and_open_repository(0, 0);
2001
+ if( g.argc!=3 ) usage("RECORDID");
2002
+ rid = name_to_rid(g.argv[2]);
2003
+ content_get(rid, &content);
2004
+ manifest_crosslink(rid, &content);
2005
+}
19882006
--- src/manifest.c
+++ src/manifest.c
@@ -430,11 +430,11 @@
430 zTarget = next_token(&x, &nTarget);
431 zSrc = next_token(&x, &nSrc);
432 if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
433 if( p->zAttachName!=0 ) goto manifest_syntax_error;
434 defossilize(zName);
435 if( !file_is_simple_pathname(zName) ){
436 SYNTAX("invalid filename on A-card");
437 }
438 defossilize(zTarget);
439 if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
440 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
@@ -524,11 +524,11 @@
524 case 'F': {
525 char *zName, *zPerm, *zPriorName;
526 zName = next_token(&x,0);
527 if( zName==0 ) SYNTAX("missing filename on F-card");
528 defossilize(zName);
529 if( !file_is_simple_pathname(zName) ){
530 SYNTAX("F-card filename is not a simple path");
531 }
532 zUuid = next_token(&x, &sz);
533 if( p->zBaseline==0 || zUuid!=0 ){
534 if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size");
@@ -536,11 +536,11 @@
536 }
537 zPerm = next_token(&x,0);
538 zPriorName = next_token(&x,0);
539 if( zPriorName ){
540 defossilize(zPriorName);
541 if( !file_is_simple_pathname(zPriorName) ){
542 SYNTAX("F-card old filename is not a simple path");
543 }
544 }
545 if( p->nFile>=p->nFileAlloc ){
546 p->nFileAlloc = p->nFileAlloc*2 + 10;
@@ -1983,5 +1983,23 @@
1983 manifest_destroy(p);
1984 }
1985 assert( blob_is_reset(pContent) );
1986 return 1;
1987 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1988
--- src/manifest.c
+++ src/manifest.c
@@ -430,11 +430,11 @@
430 zTarget = next_token(&x, &nTarget);
431 zSrc = next_token(&x, &nSrc);
432 if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
433 if( p->zAttachName!=0 ) goto manifest_syntax_error;
434 defossilize(zName);
435 if( !file_is_simple_pathname(zName, 0) ){
436 SYNTAX("invalid filename on A-card");
437 }
438 defossilize(zTarget);
439 if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
440 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
@@ -524,11 +524,11 @@
524 case 'F': {
525 char *zName, *zPerm, *zPriorName;
526 zName = next_token(&x,0);
527 if( zName==0 ) SYNTAX("missing filename on F-card");
528 defossilize(zName);
529 if( !file_is_simple_pathname(zName, 0) ){
530 SYNTAX("F-card filename is not a simple path");
531 }
532 zUuid = next_token(&x, &sz);
533 if( p->zBaseline==0 || zUuid!=0 ){
534 if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size");
@@ -536,11 +536,11 @@
536 }
537 zPerm = next_token(&x,0);
538 zPriorName = next_token(&x,0);
539 if( zPriorName ){
540 defossilize(zPriorName);
541 if( !file_is_simple_pathname(zPriorName, 0) ){
542 SYNTAX("F-card old filename is not a simple path");
543 }
544 }
545 if( p->nFile>=p->nFileAlloc ){
546 p->nFileAlloc = p->nFileAlloc*2 + 10;
@@ -1983,5 +1983,23 @@
1983 manifest_destroy(p);
1984 }
1985 assert( blob_is_reset(pContent) );
1986 return 1;
1987 }
1988
1989 /*
1990 ** COMMAND: test-crosslink
1991 **
1992 ** Usage: %fossil test-crosslink RECORDID
1993 **
1994 ** Run the manifest_crosslink() routine on the artifact with the given
1995 ** record ID. This is typically done in the debugger.
1996 */
1997 void test_crosslink_cmd(void){
1998 int rid;
1999 Blob content;
2000 db_find_and_open_repository(0, 0);
2001 if( g.argc!=3 ) usage("RECORDID");
2002 rid = name_to_rid(g.argv[2]);
2003 content_get(rid, &content);
2004 manifest_crosslink(rid, &content);
2005 }
2006
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -87,11 +87,11 @@
8787
** option overrides the "binary-glob" setting.
8888
**
8989
** --nochange | -n Dryrun: do not actually make any changes; just
9090
** show what would have happened.
9191
**
92
-** --case-sensitive BOOL Overwrite the case-sensitive setting. If false,
92
+** --case-sensitive BOOL Override the case-sensitive setting. If false,
9393
** files whose names differ only in case are taken
9494
** to be the same file.
9595
**
9696
** --force | -f Force the merge even if it would be a no-op.
9797
*/
9898
--- src/merge.c
+++ src/merge.c
@@ -87,11 +87,11 @@
87 ** option overrides the "binary-glob" setting.
88 **
89 ** --nochange | -n Dryrun: do not actually make any changes; just
90 ** show what would have happened.
91 **
92 ** --case-sensitive BOOL Overwrite the case-sensitive setting. If false,
93 ** files whose names differ only in case are taken
94 ** to be the same file.
95 **
96 ** --force | -f Force the merge even if it would be a no-op.
97 */
98
--- src/merge.c
+++ src/merge.c
@@ -87,11 +87,11 @@
87 ** option overrides the "binary-glob" setting.
88 **
89 ** --nochange | -n Dryrun: do not actually make any changes; just
90 ** show what would have happened.
91 **
92 ** --case-sensitive BOOL Override the case-sensitive setting. If false,
93 ** files whose names differ only in case are taken
94 ** to be the same file.
95 **
96 ** --force | -f Force the merge even if it would be a no-op.
97 */
98
+2 -2
--- src/merge3.c
+++ src/merge3.c
@@ -175,12 +175,12 @@
175175
** is the number of lines of text to copy directly from the pivot,
176176
** the second integer is the number of lines of text to omit from the
177177
** pivot, and the third integer is the number of lines of text that are
178178
** inserted. The edit array ends with a triple of 0,0,0.
179179
*/
180
- aC1 = text_diff(pPivot, pV1, 0, 0);
181
- aC2 = text_diff(pPivot, pV2, 0, 0);
180
+ aC1 = text_diff(pPivot, pV1, 0, 0, 0);
181
+ aC2 = text_diff(pPivot, pV2, 0, 0, 0);
182182
if( aC1==0 || aC2==0 ){
183183
free(aC1);
184184
free(aC2);
185185
return -1;
186186
}
187187
188188
ADDED src/regexp.c
--- src/merge3.c
+++ src/merge3.c
@@ -175,12 +175,12 @@
175 ** is the number of lines of text to copy directly from the pivot,
176 ** the second integer is the number of lines of text to omit from the
177 ** pivot, and the third integer is the number of lines of text that are
178 ** inserted. The edit array ends with a triple of 0,0,0.
179 */
180 aC1 = text_diff(pPivot, pV1, 0, 0);
181 aC2 = text_diff(pPivot, pV2, 0, 0);
182 if( aC1==0 || aC2==0 ){
183 free(aC1);
184 free(aC2);
185 return -1;
186 }
187
188 DDED src/regexp.c
--- src/merge3.c
+++ src/merge3.c
@@ -175,12 +175,12 @@
175 ** is the number of lines of text to copy directly from the pivot,
176 ** the second integer is the number of lines of text to omit from the
177 ** pivot, and the third integer is the number of lines of text that are
178 ** inserted. The edit array ends with a triple of 0,0,0.
179 */
180 aC1 = text_diff(pPivot, pV1, 0, 0, 0);
181 aC2 = text_diff(pPivot, pV2, 0, 0, 0);
182 if( aC1==0 || aC2==0 ){
183 free(aC1);
184 free(aC2);
185 return -1;
186 }
187
188 DDED src/regexp.c
+55
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -0,0 +1,55 @@
1
+/*
2
+** Co#ifndef SQL(sizeof(aSp*
3
+** Co#ifndef SQLITE_MAX_REGEXP_REPEAT
4
+# define SQLITE_MAX_REGEXP_REPEAT 999
5
+#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
6
+*/
7
+int re_maxlen(void){
8
+ return 1000) : 1000;
9
+}re_maxlen(), noCase) Co0);
10
+ /, 0 <= p,q <= 999*
11
+** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
12
+** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
13
+*/
14
+static void grepprintfREPEAT
15
+# define SQLITE_MAX_REGEXP_REPEAT 999
16
+#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
17
+*/
18
+int re_maxlen(void){
19
+ return 1000) : 1000;
20
+}re_maxlen(), noCase) Co0);
21
+ /, 0 <= p,q <= 999*
22
+** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
23
+** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
24
+*/
25
+static void grepprintf har const
26
+ int argc, resqlite3char zInit[12];
27
+** Co#ifnde** Co#ifndef SQLITE_MAX_REGEXP_REPEAT
28
+# define SQLITE_MAX_REGEXP_REPEAT 999
29
+#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
30
+*/
31
+int re_maxlen(void){
32
+ return 1000) : 1000;
33
+}re_maxlen(), noCase) Co0);
34
+ /, 0 <= p,q <= 999*
35
+** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
36
+** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
37
+*/
38
+static void grepprintfREPEAT
39
+# define SQLITE_MAX_REGEXP_REPEAT 999
40
+#endifcharacter3CC_INC>0 &&ute a reasonable limit on X Where XXX is any number ofn the length of the REGEXP NF
41
+ return 1000) : 1000;
42
+}re_maxlen(), noCase) Co0);
43
+ /, 0 <= p,q <= 999*
44
+** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
45
+** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
46
+*/
47
+static void grepprintf har const
48
+ int argc, resqlite3 strncmp(zIn+in.i, mem if( re_hex(zIn[1],&v) ){
49
+ += 3v;
50
+ }5v = 0;
51
+v = 0;
52
+ for(i=1; p->sIn.i<p->sIn.mx && re_hex(p->sIn.z[p->sIn.i+i], &v); i++){}
53
+ if( i>1 ){
54
+{
55
+ return 1000) :/
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -0,0 +1,55 @@
1 /*
2 ** Co#ifndef SQL(sizeof(aSp*
3 ** Co#ifndef SQLITE_MAX_REGEXP_REPEAT
4 # define SQLITE_MAX_REGEXP_REPEAT 999
5 #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
6 */
7 int re_maxlen(void){
8 return 1000) : 1000;
9 }re_maxlen(), noCase) Co0);
10 /, 0 <= p,q <= 999*
11 ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
12 ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
13 */
14 static void grepprintfREPEAT
15 # define SQLITE_MAX_REGEXP_REPEAT 999
16 #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
17 */
18 int re_maxlen(void){
19 return 1000) : 1000;
20 }re_maxlen(), noCase) Co0);
21 /, 0 <= p,q <= 999*
22 ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
23 ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
24 */
25 static void grepprintf har const
26 int argc, resqlite3char zInit[12];
27 ** Co#ifnde** Co#ifndef SQLITE_MAX_REGEXP_REPEAT
28 # define SQLITE_MAX_REGEXP_REPEAT 999
29 #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA.
30 */
31 int re_maxlen(void){
32 return 1000) : 1000;
33 }re_maxlen(), noCase) Co0);
34 /, 0 <= p,q <= 999*
35 ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
36 ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
37 */
38 static void grepprintfREPEAT
39 # define SQLITE_MAX_REGEXP_REPEAT 999
40 #endifcharacter3CC_INC>0 &&ute a reasonable limit on X Where XXX is any number ofn the length of the REGEXP NF
41 return 1000) : 1000;
42 }re_maxlen(), noCase) Co0);
43 /, 0 <= p,q <= 999*
44 ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax
45 ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1
46 */
47 static void grepprintf har const
48 int argc, resqlite3 strncmp(zIn+in.i, mem if( re_hex(zIn[1],&v) ){
49 += 3v;
50 }5v = 0;
51 v = 0;
52 for(i=1; p->sIn.i<p->sIn.mx && re_hex(p->sIn.z[p->sIn.i+i], &v); i++){}
53 if( i>1 ){
54 {
55 return 1000) :/
--- src/report.c
+++ src/report.c
@@ -172,10 +172,11 @@
172172
break;
173173
}
174174
case SQLITE_READ: {
175175
static const char *const azAllowed[] = {
176176
"ticket",
177
+ "ticketchng",
177178
"blob",
178179
"filename",
179180
"mlink",
180181
"plink",
181182
"event",
182183
--- src/report.c
+++ src/report.c
@@ -172,10 +172,11 @@
172 break;
173 }
174 case SQLITE_READ: {
175 static const char *const azAllowed[] = {
176 "ticket",
 
177 "blob",
178 "filename",
179 "mlink",
180 "plink",
181 "event",
182
--- src/report.c
+++ src/report.c
@@ -172,10 +172,11 @@
172 break;
173 }
174 case SQLITE_READ: {
175 static const char *const azAllowed[] = {
176 "ticket",
177 "ticketchng",
178 "blob",
179 "filename",
180 "mlink",
181 "plink",
182 "event",
183
+47 -1
--- src/setup.c
+++ src/setup.c
@@ -94,11 +94,11 @@
9494
"Edit HTML text inserted at the top of every page");
9595
setup_menu_entry("Footer", "setup_footer",
9696
"Edit HTML text inserted at the bottom of every page");
9797
setup_menu_entry("Moderation", "setup_modreq",
9898
"Enable/Disable requiring moderator approval of Wiki and/or Ticket"
99
- "edits and attachments.");
99
+ " changes and attachments.");
100100
setup_menu_entry("Ad-Unit", "setup_adunit",
101101
"Edit HTML text for an ad unit inserted after the menu bar");
102102
setup_menu_entry("Logo", "setup_logo",
103103
"Change the logo and background images for the server");
104104
setup_menu_entry("Shunned", "shun",
@@ -109,10 +109,12 @@
109109
"A record of login attempts");
110110
setup_menu_entry("Stats", "stat",
111111
"Display repository statistics");
112112
setup_menu_entry("SQL", "admin_sql",
113113
"Enter raw SQL commands");
114
+ setup_menu_entry("TH1", "admin_th1",
115
+ "Enter raw TH1 commands");
114116
@ </table>
115117
116118
style_footer();
117119
}
118120
@@ -1759,8 +1761,52 @@
17591761
@ </tr>
17601762
}
17611763
sqlite3_finalize(pStmt);
17621764
@ </table>
17631765
}
1766
+ }
1767
+ style_footer();
1768
+}
1769
+
1770
+
1771
+/*
1772
+** WEBPAGE: admin_th1
1773
+**
1774
+** Run raw TH1 commands using the web interface. If Tcl integration was
1775
+** enabled at compile-time and the "tcl" setting is enabled, Tcl commands
1776
+** may be run as well.
1777
+*/
1778
+void th1_page(void){
1779
+ const char *zQ = P("q");
1780
+ int go = P("go")!=0;
1781
+ login_check_credentials();
1782
+ if( !g.perm.Setup ){
1783
+ login_needed();
1784
+ }
1785
+ db_begin_transaction();
1786
+ style_header("Raw TH1 Commands");
1787
+ @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
1788
+ @ run by this page. If Tcl integration was enabled at compile-time and
1789
+ @ the "tcl" setting is enabled, Tcl commands may be run as well.</p>
1790
+ @
1791
+ @ <form method="post" action="%s(g.zTop)/admin_th1">
1792
+ login_insert_csrf_secret();
1793
+ @ TH1:<br />
1794
+ @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br />
1795
+ @ <input type="submit" name="go" value="Run TH1">
1796
+ @ </form>
1797
+ if( go ){
1798
+ const char *zR;
1799
+ int rc;
1800
+ int n;
1801
+ @ <hr />
1802
+ login_verify_csrf_secret();
1803
+ rc = Th_Eval(g.interp, 0, zQ, -1);
1804
+ zR = Th_GetResult(g.interp, &n);
1805
+ if( rc==TH_OK ){
1806
+ @ <pre class="th1result">%h(zR)</pre>
1807
+ }else{
1808
+ @ <pre class="th1error">%h(zR)</pre>
1809
+ }
17641810
}
17651811
style_footer();
17661812
}
17671813
--- src/setup.c
+++ src/setup.c
@@ -94,11 +94,11 @@
94 "Edit HTML text inserted at the top of every page");
95 setup_menu_entry("Footer", "setup_footer",
96 "Edit HTML text inserted at the bottom of every page");
97 setup_menu_entry("Moderation", "setup_modreq",
98 "Enable/Disable requiring moderator approval of Wiki and/or Ticket"
99 "edits and attachments.");
100 setup_menu_entry("Ad-Unit", "setup_adunit",
101 "Edit HTML text for an ad unit inserted after the menu bar");
102 setup_menu_entry("Logo", "setup_logo",
103 "Change the logo and background images for the server");
104 setup_menu_entry("Shunned", "shun",
@@ -109,10 +109,12 @@
109 "A record of login attempts");
110 setup_menu_entry("Stats", "stat",
111 "Display repository statistics");
112 setup_menu_entry("SQL", "admin_sql",
113 "Enter raw SQL commands");
 
 
114 @ </table>
115
116 style_footer();
117 }
118
@@ -1759,8 +1761,52 @@
1759 @ </tr>
1760 }
1761 sqlite3_finalize(pStmt);
1762 @ </table>
1763 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1764 }
1765 style_footer();
1766 }
1767
--- src/setup.c
+++ src/setup.c
@@ -94,11 +94,11 @@
94 "Edit HTML text inserted at the top of every page");
95 setup_menu_entry("Footer", "setup_footer",
96 "Edit HTML text inserted at the bottom of every page");
97 setup_menu_entry("Moderation", "setup_modreq",
98 "Enable/Disable requiring moderator approval of Wiki and/or Ticket"
99 " changes and attachments.");
100 setup_menu_entry("Ad-Unit", "setup_adunit",
101 "Edit HTML text for an ad unit inserted after the menu bar");
102 setup_menu_entry("Logo", "setup_logo",
103 "Change the logo and background images for the server");
104 setup_menu_entry("Shunned", "shun",
@@ -109,10 +109,12 @@
109 "A record of login attempts");
110 setup_menu_entry("Stats", "stat",
111 "Display repository statistics");
112 setup_menu_entry("SQL", "admin_sql",
113 "Enter raw SQL commands");
114 setup_menu_entry("TH1", "admin_th1",
115 "Enter raw TH1 commands");
116 @ </table>
117
118 style_footer();
119 }
120
@@ -1759,8 +1761,52 @@
1761 @ </tr>
1762 }
1763 sqlite3_finalize(pStmt);
1764 @ </table>
1765 }
1766 }
1767 style_footer();
1768 }
1769
1770
1771 /*
1772 ** WEBPAGE: admin_th1
1773 **
1774 ** Run raw TH1 commands using the web interface. If Tcl integration was
1775 ** enabled at compile-time and the "tcl" setting is enabled, Tcl commands
1776 ** may be run as well.
1777 */
1778 void th1_page(void){
1779 const char *zQ = P("q");
1780 int go = P("go")!=0;
1781 login_check_credentials();
1782 if( !g.perm.Setup ){
1783 login_needed();
1784 }
1785 db_begin_transaction();
1786 style_header("Raw TH1 Commands");
1787 @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
1788 @ run by this page. If Tcl integration was enabled at compile-time and
1789 @ the "tcl" setting is enabled, Tcl commands may be run as well.</p>
1790 @
1791 @ <form method="post" action="%s(g.zTop)/admin_th1">
1792 login_insert_csrf_secret();
1793 @ TH1:<br />
1794 @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br />
1795 @ <input type="submit" name="go" value="Run TH1">
1796 @ </form>
1797 if( go ){
1798 const char *zR;
1799 int rc;
1800 int n;
1801 @ <hr />
1802 login_verify_csrf_secret();
1803 rc = Th_Eval(g.interp, 0, zQ, -1);
1804 zR = Th_GetResult(g.interp, &n);
1805 if( rc==TH_OK ){
1806 @ <pre class="th1result">%h(zR)</pre>
1807 }else{
1808 @ <pre class="th1error">%h(zR)</pre>
1809 }
1810 }
1811 style_footer();
1812 }
1813
--- src/shell.c
+++ src/shell.c
@@ -1477,10 +1477,16 @@
14771477
p->zDbFilename, sqlite3_errmsg(db));
14781478
exit(1);
14791479
}
14801480
#ifndef SQLITE_OMIT_LOAD_EXTENSION
14811481
sqlite3_enable_load_extension(p->db, 1);
1482
+#endif
1483
+#ifdef SQLITE_ENABLE_REGEXP
1484
+ {
1485
+ extern int sqlite3_add_regexp_func(sqlite3*);
1486
+ sqlite3_add_regexp_func(db);
1487
+ }
14821488
#endif
14831489
}
14841490
}
14851491
14861492
/*
14871493
--- src/shell.c
+++ src/shell.c
@@ -1477,10 +1477,16 @@
1477 p->zDbFilename, sqlite3_errmsg(db));
1478 exit(1);
1479 }
1480 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1481 sqlite3_enable_load_extension(p->db, 1);
 
 
 
 
 
 
1482 #endif
1483 }
1484 }
1485
1486 /*
1487
--- src/shell.c
+++ src/shell.c
@@ -1477,10 +1477,16 @@
1477 p->zDbFilename, sqlite3_errmsg(db));
1478 exit(1);
1479 }
1480 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1481 sqlite3_enable_load_extension(p->db, 1);
1482 #endif
1483 #ifdef SQLITE_ENABLE_REGEXP
1484 {
1485 extern int sqlite3_add_regexp_func(sqlite3*);
1486 sqlite3_add_regexp_func(db);
1487 }
1488 #endif
1489 }
1490 }
1491
1492 /*
1493
+12 -7
--- src/skins.c
+++ src/skins.c
@@ -355,12 +355,13 @@
355355
@ div.footer a:visited { color: white; }
356356
@ div.footer a:hover { background-color: white; color: #558195; }
357357
@
358358
@ /* <verbatim> blocks */
359359
@ pre.verbatim {
360
-@ background-color: #f5f5f5;
361
-@ padding: 0.5em;
360
+@ background-color: #f5f5f5;
361
+@ padding: 0.5em;
362
+@ white-space: pre-wrap;
362363
@ }
363364
@
364365
@ /* The label/value pairs on (for example) the ci page */
365366
@ table.label-value th {
366367
@ vertical-align: top;
@@ -595,12 +596,13 @@
595596
@ color: #555;
596597
@ }
597598
@
598599
@ /* <verbatim> blocks */
599600
@ pre.verbatim {
600
-@ background-color: #f5f5f5;
601
-@ padding: 0.5em;
601
+@ background-color: #f5f5f5;
602
+@ padding: 0.5em;
603
+@ white-space: pre-wrap;
602604
@ }
603605
@
604606
@ /* The label/value pairs on (for example) the ci page */
605607
@ table.label-value th {
606608
@ vertical-align: top;
@@ -1083,13 +1085,14 @@
10831085
@ div.footer a:visited { color: white; }
10841086
@ div.footer a:hover { background-color: white; color: #558195; }
10851087
@
10861088
@ /* verbatim blocks */
10871089
@ pre.verbatim {
1088
-@ background-color: #f5f5f5;
1089
-@ padding: 0.5em;
1090
-@}
1090
+@ background-color: #f5f5f5;
1091
+@ padding: 0.5em;
1092
+@ white-space: pre-wrap;
1093
+@ }
10911094
@
10921095
@ /* The label/value pairs on (for example) the ci page */
10931096
@ table.label-value th {
10941097
@ vertical-align: top;
10951098
@ text-align: right;
@@ -1226,10 +1229,12 @@
12261229
@ }
12271230
@ set version [getVersion $manifest_version]
12281231
@ set tclVersion [getTclVersion]
12291232
@ set fossilUrl http://www.fossil-scm.org
12301233
@ </th1>
1234
+@ This page was generated in about
1235
+@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
12311236
@ <a href="$fossilUrl/">Fossil</a>
12321237
@ version $release_version $tclVersion
12331238
@ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
12341239
@ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
12351240
@ </div>
12361241
--- src/skins.c
+++ src/skins.c
@@ -355,12 +355,13 @@
355 @ div.footer a:visited { color: white; }
356 @ div.footer a:hover { background-color: white; color: #558195; }
357 @
358 @ /* <verbatim> blocks */
359 @ pre.verbatim {
360 @ background-color: #f5f5f5;
361 @ padding: 0.5em;
 
362 @ }
363 @
364 @ /* The label/value pairs on (for example) the ci page */
365 @ table.label-value th {
366 @ vertical-align: top;
@@ -595,12 +596,13 @@
595 @ color: #555;
596 @ }
597 @
598 @ /* <verbatim> blocks */
599 @ pre.verbatim {
600 @ background-color: #f5f5f5;
601 @ padding: 0.5em;
 
602 @ }
603 @
604 @ /* The label/value pairs on (for example) the ci page */
605 @ table.label-value th {
606 @ vertical-align: top;
@@ -1083,13 +1085,14 @@
1083 @ div.footer a:visited { color: white; }
1084 @ div.footer a:hover { background-color: white; color: #558195; }
1085 @
1086 @ /* verbatim blocks */
1087 @ pre.verbatim {
1088 @ background-color: #f5f5f5;
1089 @ padding: 0.5em;
1090 @}
 
1091 @
1092 @ /* The label/value pairs on (for example) the ci page */
1093 @ table.label-value th {
1094 @ vertical-align: top;
1095 @ text-align: right;
@@ -1226,10 +1229,12 @@
1226 @ }
1227 @ set version [getVersion $manifest_version]
1228 @ set tclVersion [getTclVersion]
1229 @ set fossilUrl http://www.fossil-scm.org
1230 @ </th1>
 
 
1231 @ <a href="$fossilUrl/">Fossil</a>
1232 @ version $release_version $tclVersion
1233 @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
1234 @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
1235 @ </div>
1236
--- src/skins.c
+++ src/skins.c
@@ -355,12 +355,13 @@
355 @ div.footer a:visited { color: white; }
356 @ div.footer a:hover { background-color: white; color: #558195; }
357 @
358 @ /* <verbatim> blocks */
359 @ pre.verbatim {
360 @ background-color: #f5f5f5;
361 @ padding: 0.5em;
362 @ white-space: pre-wrap;
363 @ }
364 @
365 @ /* The label/value pairs on (for example) the ci page */
366 @ table.label-value th {
367 @ vertical-align: top;
@@ -595,12 +596,13 @@
596 @ color: #555;
597 @ }
598 @
599 @ /* <verbatim> blocks */
600 @ pre.verbatim {
601 @ background-color: #f5f5f5;
602 @ padding: 0.5em;
603 @ white-space: pre-wrap;
604 @ }
605 @
606 @ /* The label/value pairs on (for example) the ci page */
607 @ table.label-value th {
608 @ vertical-align: top;
@@ -1083,13 +1085,14 @@
1085 @ div.footer a:visited { color: white; }
1086 @ div.footer a:hover { background-color: white; color: #558195; }
1087 @
1088 @ /* verbatim blocks */
1089 @ pre.verbatim {
1090 @ background-color: #f5f5f5;
1091 @ padding: 0.5em;
1092 @ white-space: pre-wrap;
1093 @ }
1094 @
1095 @ /* The label/value pairs on (for example) the ci page */
1096 @ table.label-value th {
1097 @ vertical-align: top;
1098 @ text-align: right;
@@ -1226,10 +1229,12 @@
1229 @ }
1230 @ set version [getVersion $manifest_version]
1231 @ set tclVersion [getTclVersion]
1232 @ set fossilUrl http://www.fossil-scm.org
1233 @ </th1>
1234 @ This page was generated in about
1235 @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
1236 @ <a href="$fossilUrl/">Fossil</a>
1237 @ version $release_version $tclVersion
1238 @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
1239 @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
1240 @ </div>
1241
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -118,10 +118,11 @@
118118
sqlcmd_content, 0, 0);
119119
sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
120120
sqlcmd_compress, 0, 0);
121121
sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
122122
sqlcmd_decompress, 0, 0);
123
+ re_add_sql_func(db);
123124
g.repositoryOpen = 1;
124125
g.db = db;
125126
return SQLITE_OK;
126127
}
127128
128129
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -118,10 +118,11 @@
118 sqlcmd_content, 0, 0);
119 sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
120 sqlcmd_compress, 0, 0);
121 sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
122 sqlcmd_decompress, 0, 0);
 
123 g.repositoryOpen = 1;
124 g.db = db;
125 return SQLITE_OK;
126 }
127
128
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -118,10 +118,11 @@
118 sqlcmd_content, 0, 0);
119 sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
120 sqlcmd_compress, 0, 0);
121 sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
122 sqlcmd_decompress, 0, 0);
123 re_add_sql_func(db);
124 g.repositoryOpen = 1;
125 g.db = db;
126 return SQLITE_OK;
127 }
128
129
+904 -484
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.7.15. By combining all the individual C code files into this
3
+** version 3.7.16. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -671,13 +671,13 @@
671671
**
672672
** See also: [sqlite3_libversion()],
673673
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674674
** [sqlite_version()] and [sqlite_source_id()].
675675
*/
676
-#define SQLITE_VERSION "3.7.15"
677
-#define SQLITE_VERSION_NUMBER 3007015
678
-#define SQLITE_SOURCE_ID "2012-12-05 14:31:13 9f6c68856b694373b7ffb124abd996e519ba5921"
676
+#define SQLITE_VERSION "3.7.16"
677
+#define SQLITE_VERSION_NUMBER 3007016
678
+#define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503"
679679
680680
/*
681681
** CAPI3REF: Run-Time Library Version Numbers
682682
** KEYWORDS: sqlite3_version, sqlite3_sourceid
683683
**
@@ -1421,11 +1421,10 @@
14211421
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
14221422
** that the VFS encountered an error while handling the [PRAGMA] and the
14231423
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
14241424
** file control occurs at the beginning of pragma statement analysis and so
14251425
** it is able to override built-in [PRAGMA] statements.
1426
-** </ul>
14271426
**
14281427
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
14291428
** ^This file-control may be invoked by SQLite on the database file handle
14301429
** shortly after it is opened in order to provide a custom VFS with access
14311430
** to the connections busy-handler callback. The argument is of type (void **)
@@ -1433,10 +1432,20 @@
14331432
** to a function of type (int (*)(void *)). In order to invoke the connections
14341433
** busy-handler, this function should be invoked with the second (void *) in
14351434
** the array as the only argument. If it returns non-zero, then the operation
14361435
** should be retried. If it returns zero, the custom VFS should abandon the
14371436
** current operation.
1437
+**
1438
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
1439
+** ^Application can invoke this file-control to have SQLite generate a
1440
+** temporary filename using the same algorithm that is followed to generate
1441
+** temporary filenames for TEMP tables and other internal uses. The
1442
+** argument should be a char** which will be filled with the filename
1443
+** written into memory obtained from [sqlite3_malloc()]. The caller should
1444
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
1445
+**
1446
+** </ul>
14381447
*/
14391448
#define SQLITE_FCNTL_LOCKSTATE 1
14401449
#define SQLITE_GET_LOCKPROXYFILE 2
14411450
#define SQLITE_SET_LOCKPROXYFILE 3
14421451
#define SQLITE_LAST_ERRNO 4
@@ -1449,10 +1458,11 @@
14491458
#define SQLITE_FCNTL_OVERWRITE 11
14501459
#define SQLITE_FCNTL_VFSNAME 12
14511460
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
14521461
#define SQLITE_FCNTL_PRAGMA 14
14531462
#define SQLITE_FCNTL_BUSYHANDLER 15
1463
+#define SQLITE_FCNTL_TEMPFILENAME 16
14541464
14551465
/*
14561466
** CAPI3REF: Mutex Handle
14571467
**
14581468
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -2146,11 +2156,11 @@
21462156
** database connection is opened. By default, URI handling is globally
21472157
** disabled. The default value may be changed by compiling with the
21482158
** [SQLITE_USE_URI] symbol defined.
21492159
**
21502160
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
2151
-** <dd> This option taks a single integer argument which is interpreted as
2161
+** <dd> This option takes a single integer argument which is interpreted as
21522162
** a boolean in order to enable or disable the use of covering indices for
21532163
** full table scans in the query optimizer. The default setting is determined
21542164
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
21552165
** if that compile-time option is omitted.
21562166
** The ability to disable the use of covering indices for full table scans
@@ -10209,23 +10219,11 @@
1020910219
/*
1021010220
** A "Collating Sequence" is defined by an instance of the following
1021110221
** structure. Conceptually, a collating sequence consists of a name and
1021210222
** a comparison routine that defines the order of that sequence.
1021310223
**
10214
-** There may two separate implementations of the collation function, one
10215
-** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
10216
-** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
10217
-** native byte order. When a collation sequence is invoked, SQLite selects
10218
-** the version that will require the least expensive encoding
10219
-** translations, if any.
10220
-**
10221
-** The CollSeq.pUser member variable is an extra parameter that passed in
10222
-** as the first argument to the UTF-8 comparison function, xCmp.
10223
-** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
10224
-** xCmp16.
10225
-**
10226
-** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
10224
+** If CollSeq.xCmp is NULL, it means that the
1022710225
** collating sequence is undefined. Indices built on an undefined
1022810226
** collating sequence may not be read or written.
1022910227
*/
1023010228
struct CollSeq {
1023110229
char *zName; /* Name of the collating sequence, UTF-8 encoded */
@@ -10555,24 +10553,24 @@
1055510553
** and the value of Index.onError indicate the which conflict resolution
1055610554
** algorithm to employ whenever an attempt is made to insert a non-unique
1055710555
** element.
1055810556
*/
1055910557
struct Index {
10560
- char *zName; /* Name of this index */
10561
- int *aiColumn; /* Which columns are used by this index. 1st is 0 */
10562
- tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
10563
- Table *pTable; /* The SQL table being indexed */
10564
- char *zColAff; /* String defining the affinity of each column */
10565
- Index *pNext; /* The next index associated with the same table */
10566
- Schema *pSchema; /* Schema containing this index */
10567
- u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
10568
- char **azColl; /* Array of collation sequence names for index */
10569
- int nColumn; /* Number of columns in the table used by this index */
10570
- int tnum; /* Page containing root of this index in database file */
10571
- u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10572
- u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
10573
- u8 bUnordered; /* Use this index for == or IN queries only */
10558
+ char *zName; /* Name of this index */
10559
+ int *aiColumn; /* Which columns are used by this index. 1st is 0 */
10560
+ tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
10561
+ Table *pTable; /* The SQL table being indexed */
10562
+ char *zColAff; /* String defining the affinity of each column */
10563
+ Index *pNext; /* The next index associated with the same table */
10564
+ Schema *pSchema; /* Schema containing this index */
10565
+ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10566
+ char **azColl; /* Array of collation sequence names for index */
10567
+ int tnum; /* DB Page containing root of this index */
10568
+ u16 nColumn; /* Number of columns in table used by this index */
10569
+ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10570
+ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10571
+ unsigned bUnordered:1; /* Use this index for == or IN queries only */
1057410572
#ifdef SQLITE_ENABLE_STAT3
1057510573
int nSample; /* Number of elements in aSample[] */
1057610574
tRowcnt avgEq; /* Average nEq value for key values not in aSample */
1057710575
IndexSample *aSample; /* Samples of the left-most key */
1057810576
#endif
@@ -10749,11 +10747,10 @@
1074910747
Expr *pRight; /* Right subnode */
1075010748
union {
1075110749
ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
1075210750
Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
1075310751
} x;
10754
- CollSeq *pColl; /* The collation type of the column or 0 */
1075510752
1075610753
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
1075710754
** space is allocated for the fields below this point. An attempt to
1075810755
** access them will result in a segfault or malfunction.
1075910756
*********************************************************************/
@@ -10785,11 +10782,11 @@
1078510782
#define EP_Error 0x0008 /* Expression contains one or more errors */
1078610783
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
1078710784
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
1078810785
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
1078910786
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
10790
-#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
10787
+#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
1079110788
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
1079210789
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
1079310790
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
1079410791
#define EP_Hint 0x1000 /* Not used */
1079510792
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
@@ -10843,22 +10840,31 @@
1084310840
** name. An expr/name combination can be used in several ways, such
1084410841
** as the list of "expr AS ID" fields following a "SELECT" or in the
1084510842
** list of "ID = expr" items in an UPDATE. A list of expressions can
1084610843
** also be used as the argument to a function, in which case the a.zName
1084710844
** field is not used.
10845
+**
10846
+** By default the Expr.zSpan field holds a human-readable description of
10847
+** the expression that is used in the generation of error messages and
10848
+** column labels. In this case, Expr.zSpan is typically the text of a
10849
+** column expression as it exists in a SELECT statement. However, if
10850
+** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
10851
+** of the result column in the form: DATABASE.TABLE.COLUMN. This later
10852
+** form is used for name resolution with nested FROM clauses.
1084810853
*/
1084910854
struct ExprList {
1085010855
int nExpr; /* Number of expressions on the list */
1085110856
int iECursor; /* VDBE Cursor associated with this ExprList */
1085210857
struct ExprList_item { /* For each expression in the list */
10853
- Expr *pExpr; /* The list of expressions */
10854
- char *zName; /* Token associated with this expression */
10855
- char *zSpan; /* Original text of the expression */
10856
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
10857
- u8 done; /* A flag to indicate when processing is finished */
10858
- u16 iOrderByCol; /* For ORDER BY, column number in result set */
10859
- u16 iAlias; /* Index into Parse.aAlias[] for zName */
10858
+ Expr *pExpr; /* The list of expressions */
10859
+ char *zName; /* Token associated with this expression */
10860
+ char *zSpan; /* Original text of the expression */
10861
+ u8 sortOrder; /* 1 for DESC or 0 for ASC */
10862
+ unsigned done :1; /* A flag to indicate when processing is finished */
10863
+ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
10864
+ u16 iOrderByCol; /* For ORDER BY, column number in result set */
10865
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
1086010866
} *a; /* Alloc a power of two greater or equal to nExpr */
1086110867
};
1086210868
1086310869
/*
1086410870
** An instance of this structure is used by the parser to record both
@@ -11174,10 +11180,11 @@
1117411180
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
1117511181
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
1117611182
#define SF_UseSorter 0x0040 /* Sort using a sorter */
1117711183
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
1117811184
#define SF_Materialize 0x0100 /* Force materialization of views */
11185
+#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
1117911186
1118011187
1118111188
/*
1118211189
** The results of a select can be distributed in several ways. The
1118311190
** "SRT" prefix means "SELECT Result Type".
@@ -11402,10 +11409,11 @@
1140211409
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
1140311410
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
1140411411
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
1140511412
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
1140611413
#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
11414
+#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
1140711415
1140811416
/*
1140911417
* Each trigger present in the database schema is stored as an instance of
1141011418
* struct Trigger.
1141111419
*
@@ -11885,11 +11893,11 @@
1188511893
SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
1188611894
Token*, int, int);
1188711895
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
1188811896
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
1188911897
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
11890
- Expr*,ExprList*,int,Expr*,Expr*);
11898
+ Expr*,ExprList*,u16,Expr*,Expr*);
1189111899
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
1189211900
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
1189311901
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
1189411902
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
1189511903
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -12093,12 +12101,13 @@
1209312101
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
1209412102
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
1209512103
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
1209612104
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
1209712105
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
12098
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
12099
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
12106
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
12107
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
12108
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
1210012109
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
1210112110
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
1210212111
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
1210312112
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
1210412113
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
@@ -12141,10 +12150,11 @@
1214112150
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
1214212151
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
1214312152
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
1214412153
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
1214512154
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
12155
+SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
1214612156
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
1214712157
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
1214812158
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
1214912159
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
1215012160
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -12279,12 +12289,14 @@
1227912289
#define sqlite3FkOldmask(a,b) 0
1228012290
#define sqlite3FkRequired(a,b,c,d) 0
1228112291
#endif
1228212292
#ifndef SQLITE_OMIT_FOREIGN_KEY
1228312293
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
12294
+SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
1228412295
#else
1228512296
#define sqlite3FkDelete(a,b)
12297
+ #define sqlite3FkLocateIndex(a,b,c,d,e)
1228612298
#endif
1228712299
1228812300
1228912301
/*
1229012302
** Available fault injectors. Should be numbered beginning with 0.
@@ -23287,15 +23299,11 @@
2328723299
{ "pwrite64", (sqlite3_syscall_ptr)0, 0 },
2328823300
#endif
2328923301
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
2329023302
aSyscall[13].pCurrent)
2329123303
23292
-#if SQLITE_ENABLE_LOCKING_STYLE
2329323304
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
23294
-#else
23295
- { "fchmod", (sqlite3_syscall_ptr)0, 0 },
23296
-#endif
2329723305
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
2329823306
2329923307
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
2330023308
{ "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
2330123309
#else
@@ -23316,13 +23324,10 @@
2331623324
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
2331723325
2331823326
{ "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
2331923327
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
2332023328
23321
- { "umask", (sqlite3_syscall_ptr)umask, 0 },
23322
-#define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent)
23323
-
2332423329
}; /* End of the overrideable system calls */
2332523330
2332623331
/*
2332723332
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
2332823333
** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -23423,31 +23428,29 @@
2342323428
** process that is able to write to the database will also be able to
2342423429
** recover the hot journals.
2342523430
*/
2342623431
static int robust_open(const char *z, int f, mode_t m){
2342723432
int fd;
23428
- mode_t m2;
23429
- mode_t origM = 0;
23430
- if( m==0 ){
23431
- m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
23432
- }else{
23433
- m2 = m;
23434
- origM = osUmask(0);
23435
- }
23433
+ mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
2343623434
do{
2343723435
#if defined(O_CLOEXEC)
2343823436
fd = osOpen(z,f|O_CLOEXEC,m2);
2343923437
#else
2344023438
fd = osOpen(z,f,m2);
2344123439
#endif
2344223440
}while( fd<0 && errno==EINTR );
23443
- if( m ){
23444
- osUmask(origM);
23445
- }
23441
+ if( fd>=0 ){
23442
+ if( m!=0 ){
23443
+ struct stat statbuf;
23444
+ if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){
23445
+ osFchmod(fd, m);
23446
+ }
23447
+ }
2344623448
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
23447
- if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
23449
+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
2344823450
#endif
23451
+ }
2344923452
return fd;
2345023453
}
2345123454
2345223455
/*
2345323456
** Helper functions to obtain and relinquish the global mutex. The
@@ -26456,10 +26459,13 @@
2645626459
}else{
2645726460
pFile->ctrlFlags |= mask;
2645826461
}
2645926462
}
2646026463
26464
+/* Forward declaration */
26465
+static int unixGetTempname(int nBuf, char *zBuf);
26466
+
2646126467
/*
2646226468
** Information and control of an open file handle.
2646326469
*/
2646426470
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
2646526471
unixFile *pFile = (unixFile*)id;
@@ -26492,10 +26498,18 @@
2649226498
return SQLITE_OK;
2649326499
}
2649426500
case SQLITE_FCNTL_VFSNAME: {
2649526501
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
2649626502
return SQLITE_OK;
26503
+ }
26504
+ case SQLITE_FCNTL_TEMPFILENAME: {
26505
+ char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
26506
+ if( zTFile ){
26507
+ unixGetTempname(pFile->pVfs->mxPathname, zTFile);
26508
+ *(char**)pArg = zTFile;
26509
+ }
26510
+ return SQLITE_OK;
2649726511
}
2649826512
#ifdef SQLITE_DEBUG
2649926513
/* The pager calls this method to signal that it has done
2650026514
** a rollback and that the database is therefore unchanged and
2650126515
** it hence it is OK for the transaction change counter to be
@@ -29858,11 +29872,11 @@
2985829872
};
2985929873
unsigned int i; /* Loop counter */
2986029874
2986129875
/* Double-check that the aSyscall[] array has been constructed
2986229876
** correctly. See ticket [bb3a86e890c8e96ab] */
29863
- assert( ArraySize(aSyscall)==22 );
29877
+ assert( ArraySize(aSyscall)==21 );
2986429878
2986529879
/* Register all VFSes defined in the aVfs[] array */
2986629880
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
2986729881
sqlite3_vfs_register(&aVfs[i], i==0);
2986829882
}
@@ -32782,10 +32796,13 @@
3278232796
}else{
3278332797
pFile->ctrlFlags |= mask;
3278432798
}
3278532799
}
3278632800
32801
+/* Forward declaration */
32802
+static int getTempname(int nBuf, char *zBuf);
32803
+
3278732804
/*
3278832805
** Control and query of the open file handle.
3278932806
*/
3279032807
static int winFileControl(sqlite3_file *id, int op, void *pArg){
3279132808
winFile *pFile = (winFile*)id;
@@ -32841,10 +32858,18 @@
3284132858
win32IoerrRetryDelay = a[1];
3284232859
}else{
3284332860
a[1] = win32IoerrRetryDelay;
3284432861
}
3284532862
return SQLITE_OK;
32863
+ }
32864
+ case SQLITE_FCNTL_TEMPFILENAME: {
32865
+ char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
32866
+ if( zTFile ){
32867
+ getTempname(pFile->pVfs->mxPathname, zTFile);
32868
+ *(char**)pArg = zTFile;
32869
+ }
32870
+ return SQLITE_OK;
3284632871
}
3284732872
}
3284832873
return SQLITE_NOTFOUND;
3284932874
}
3285032875
@@ -56313,11 +56338,11 @@
5631356338
sqlite3BtreeLeave(p);
5631456339
return 0;
5631556340
}
5631656341
i = PENDING_BYTE_PAGE(pBt);
5631756342
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
56318
- sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
56343
+ sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
5631956344
sCheck.errMsg.useMalloc = 2;
5632056345
5632156346
/* Check the integrity of the freelist
5632256347
*/
5632356348
checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
@@ -56848,11 +56873,16 @@
5684856873
/*
5684956874
** Parameter zSrcData points to a buffer containing the data for
5685056875
** page iSrcPg from the source database. Copy this data into the
5685156876
** destination database.
5685256877
*/
56853
-static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
56878
+static int backupOnePage(
56879
+ sqlite3_backup *p, /* Backup handle */
56880
+ Pgno iSrcPg, /* Source database page to backup */
56881
+ const u8 *zSrcData, /* Source database page data */
56882
+ int bUpdate /* True for an update, false otherwise */
56883
+){
5685456884
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
5685556885
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
5685656886
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
5685756887
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
5685856888
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
@@ -56921,10 +56951,13 @@
5692156951
** cached parse of the page). MemPage.isInit is marked
5692256952
** "MUST BE FIRST" for this purpose.
5692356953
*/
5692456954
memcpy(zOut, zIn, nCopy);
5692556955
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
56956
+ if( iOff==0 && bUpdate==0 ){
56957
+ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
56958
+ }
5692656959
}
5692756960
sqlite3PagerUnref(pDestPg);
5692856961
}
5692956962
5693056963
return rc;
@@ -57027,11 +57060,11 @@
5702757060
const Pgno iSrcPg = p->iNext; /* Source page number */
5702857061
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
5702957062
DbPage *pSrcPg; /* Source page object */
5703057063
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
5703157064
if( rc==SQLITE_OK ){
57032
- rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
57065
+ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
5703357066
sqlite3PagerUnref(pSrcPg);
5703457067
}
5703557068
}
5703657069
p->iNext++;
5703757070
}
@@ -57275,11 +57308,11 @@
5727557308
** the new data into the backup.
5727657309
*/
5727757310
int rc;
5727857311
assert( p->pDestDb );
5727957312
sqlite3_mutex_enter(p->pDestDb->mutex);
57280
- rc = backupOnePage(p, iPage, aData);
57313
+ rc = backupOnePage(p, iPage, aData, 1);
5728157314
sqlite3_mutex_leave(p->pDestDb->mutex);
5728257315
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
5728357316
if( rc!=SQLITE_OK ){
5728457317
p->rc = rc;
5728557318
}
@@ -59392,26 +59425,22 @@
5939259425
assert( pKeyInfo->aSortOrder!=0 );
5939359426
sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
5939459427
i = sqlite3Strlen30(zTemp);
5939559428
for(j=0; j<pKeyInfo->nField; j++){
5939659429
CollSeq *pColl = pKeyInfo->aColl[j];
59397
- if( pColl ){
59398
- int n = sqlite3Strlen30(pColl->zName);
59399
- if( i+n>nTemp-6 ){
59400
- memcpy(&zTemp[i],",...",4);
59401
- break;
59402
- }
59403
- zTemp[i++] = ',';
59404
- if( pKeyInfo->aSortOrder[j] ){
59405
- zTemp[i++] = '-';
59406
- }
59407
- memcpy(&zTemp[i], pColl->zName,n+1);
59408
- i += n;
59409
- }else if( i+4<nTemp-6 ){
59410
- memcpy(&zTemp[i],",nil",4);
59411
- i += 4;
59412
- }
59430
+ const char *zColl = pColl ? pColl->zName : "nil";
59431
+ int n = sqlite3Strlen30(zColl);
59432
+ if( i+n>nTemp-6 ){
59433
+ memcpy(&zTemp[i],",...",4);
59434
+ break;
59435
+ }
59436
+ zTemp[i++] = ',';
59437
+ if( pKeyInfo->aSortOrder[j] ){
59438
+ zTemp[i++] = '-';
59439
+ }
59440
+ memcpy(&zTemp[i], zColl, n+1);
59441
+ i += n;
5941359442
}
5941459443
zTemp[i++] = ')';
5941559444
zTemp[i] = 0;
5941659445
assert( i<nTemp );
5941759446
break;
@@ -63797,11 +63826,13 @@
6379763826
#ifdef SQLITE_DEBUG
6379863827
/*
6379963828
** Print the value of a register for tracing purposes:
6380063829
*/
6380163830
static void memTracePrint(FILE *out, Mem *p){
63802
- if( p->flags & MEM_Null ){
63831
+ if( p->flags & MEM_Invalid ){
63832
+ fprintf(out, " undefined");
63833
+ }else if( p->flags & MEM_Null ){
6380363834
fprintf(out, " NULL");
6380463835
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
6380563836
fprintf(out, " si:%lld", p->u.i);
6380663837
}else if( p->flags & MEM_Int ){
6380763838
fprintf(out, " i:%lld", p->u.i);
@@ -64070,10 +64101,11 @@
6407064101
} af;
6407164102
struct OP_Concat_stack_vars {
6407264103
i64 nByte;
6407364104
} ag;
6407464105
struct OP_Remainder_stack_vars {
64106
+ char bIntint; /* Started out as two integer operands */
6407564107
int flags; /* Combined MEM_* flags from both inputs */
6407664108
i64 iA; /* Integer value of left operand */
6407764109
i64 iB; /* Integer value of right operand */
6407864110
double rA; /* Real value of left operand */
6407964111
double rB; /* Real value of right operand */
@@ -64979,10 +65011,13 @@
6497965011
pOut = &aMem[pOp->p2];
6498065012
assert( pOut!=pIn1 );
6498165013
while( 1 ){
6498265014
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
6498365015
Deephemeralize(pOut);
65016
+#ifdef SQLITE_DEBUG
65017
+ pOut->pScopyFrom = 0;
65018
+#endif
6498465019
REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
6498565020
if( (u.ae.n--)==0 ) break;
6498665021
pOut++;
6498765022
pIn1++;
6498865023
}
@@ -65172,10 +65207,11 @@
6517265207
case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
6517365208
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
6517465209
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
6517565210
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
6517665211
#if 0 /* local variables moved into u.ah */
65212
+ char bIntint; /* Started out as two integer operands */
6517765213
int flags; /* Combined MEM_* flags from both inputs */
6517865214
i64 iA; /* Integer value of left operand */
6517965215
i64 iB; /* Integer value of right operand */
6518065216
double rA; /* Real value of left operand */
6518165217
double rB; /* Real value of right operand */
@@ -65189,10 +65225,11 @@
6518965225
u.ah.flags = pIn1->flags | pIn2->flags;
6519065226
if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
6519165227
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
6519265228
u.ah.iA = pIn1->u.i;
6519365229
u.ah.iB = pIn2->u.i;
65230
+ u.ah.bIntint = 1;
6519465231
switch( pOp->opcode ){
6519565232
case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
6519665233
case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
6519765234
case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
6519865235
case OP_Divide: {
@@ -65209,10 +65246,11 @@
6520965246
}
6521065247
}
6521165248
pOut->u.i = u.ah.iB;
6521265249
MemSetTypeFlag(pOut, MEM_Int);
6521365250
}else{
65251
+ u.ah.bIntint = 0;
6521465252
fp_math:
6521565253
u.ah.rA = sqlite3VdbeRealValue(pIn1);
6521665254
u.ah.rB = sqlite3VdbeRealValue(pIn2);
6521765255
switch( pOp->opcode ){
6521865256
case OP_Add: u.ah.rB += u.ah.rA; break;
@@ -65240,11 +65278,11 @@
6524065278
if( sqlite3IsNaN(u.ah.rB) ){
6524165279
goto arithmetic_result_is_null;
6524265280
}
6524365281
pOut->r = u.ah.rB;
6524465282
MemSetTypeFlag(pOut, MEM_Real);
65245
- if( (u.ah.flags & MEM_Real)==0 ){
65283
+ if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
6524665284
sqlite3VdbeIntegerAffinity(pOut);
6524765285
}
6524865286
#endif
6524965287
}
6525065288
break;
@@ -65801,26 +65839,31 @@
6580165839
/* Opcode: Permutation * * * P4 *
6580265840
**
6580365841
** Set the permutation used by the OP_Compare operator to be the array
6580465842
** of integers in P4.
6580565843
**
65806
-** The permutation is only valid until the next OP_Permutation, OP_Compare,
65807
-** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur
65808
-** immediately prior to the OP_Compare.
65844
+** The permutation is only valid until the next OP_Compare that has
65845
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
65846
+** occur immediately prior to the OP_Compare.
6580965847
*/
6581065848
case OP_Permutation: {
6581165849
assert( pOp->p4type==P4_INTARRAY );
6581265850
assert( pOp->p4.ai );
6581365851
aPermute = pOp->p4.ai;
6581465852
break;
6581565853
}
6581665854
65817
-/* Opcode: Compare P1 P2 P3 P4 *
65855
+/* Opcode: Compare P1 P2 P3 P4 P5
6581865856
**
6581965857
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
6582065858
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
6582165859
** the comparison for use by the next OP_Jump instruct.
65860
+**
65861
+** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
65862
+** determined by the most recent OP_Permutation operator. If the
65863
+** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
65864
+** order.
6582265865
**
6582365866
** P4 is a KeyInfo structure that defines collating sequences and sort
6582465867
** orders for the comparison. The permutation applies to registers
6582565868
** only. The KeyInfo elements are used sequentially.
6582665869
**
@@ -65838,10 +65881,11 @@
6583865881
int idx;
6583965882
CollSeq *pColl; /* Collating sequence to use on this term */
6584065883
int bRev; /* True for DESCENDING sort order */
6584165884
#endif /* local variables moved into u.al */
6584265885
65886
+ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
6584365887
u.al.n = pOp->p3;
6584465888
u.al.pKeyInfo = pOp->p4.pKeyInfo;
6584565889
assert( u.al.n>0 );
6584665890
assert( u.al.pKeyInfo!=0 );
6584765891
u.al.p1 = pOp->p1;
@@ -65983,12 +66027,10 @@
6598366027
6598466028
/* Opcode: Once P1 P2 * * *
6598566029
**
6598666030
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
6598766031
** set the flag and fall through to the next instruction.
65988
-**
65989
-** See also: JumpOnce
6599066032
*/
6599166033
case OP_Once: { /* jump */
6599266034
assert( pOp->p1<p->nOnceFlag );
6599366035
if( p->aOnceFlag[pOp->p1] ){
6599466036
pc = pOp->p2-1;
@@ -71860,10 +71902,18 @@
7186071902
p->pReal = pReal;
7186171903
if( p->iSize>0 ){
7186271904
assert(p->iSize<=p->nBuf);
7186371905
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
7186471906
}
71907
+ if( rc!=SQLITE_OK ){
71908
+ /* If an error occurred while writing to the file, close it before
71909
+ ** returning. This way, SQLite uses the in-memory journal data to
71910
+ ** roll back changes made to the internal page-cache before this
71911
+ ** function was called. */
71912
+ sqlite3OsClose(pReal);
71913
+ p->pReal = 0;
71914
+ }
7186571915
}
7186671916
}
7186771917
return rc;
7186871918
}
7186971919
@@ -72523,10 +72573,19 @@
7252372573
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
7252472574
**
7252572575
** The result of random()%5 in the GROUP BY clause is probably different
7252672576
** from the result in the result-set. We might fix this someday. Or
7252772577
** then again, we might not...
72578
+**
72579
+** If the reference is followed by a COLLATE operator, then make sure
72580
+** the COLLATE operator is preserved. For example:
72581
+**
72582
+** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
72583
+**
72584
+** Should be transformed into:
72585
+**
72586
+** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
7252872587
**
7252972588
** The nSubquery parameter specifies how many levels of subquery the
7253072589
** alias is removed from the original expression. The usually value is
7253172590
** zero but it might be more if the alias is contained within a subquery
7253272591
** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
@@ -72547,45 +72606,40 @@
7254772606
assert( iCol>=0 && iCol<pEList->nExpr );
7254872607
pOrig = pEList->a[iCol].pExpr;
7254972608
assert( pOrig!=0 );
7255072609
assert( pOrig->flags & EP_Resolved );
7255172610
db = pParse->db;
72611
+ pDup = sqlite3ExprDup(db, pOrig, 0);
72612
+ if( pDup==0 ) return;
7255272613
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
72553
- pDup = sqlite3ExprDup(db, pOrig, 0);
7255472614
incrAggFunctionDepth(pDup, nSubquery);
7255572615
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
7255672616
if( pDup==0 ) return;
7255772617
if( pEList->a[iCol].iAlias==0 ){
7255872618
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
7255972619
}
7256072620
pDup->iTable = pEList->a[iCol].iAlias;
72561
- }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
72562
- pDup = sqlite3ExprDup(db, pOrig, 0);
72563
- if( pDup==0 ) return;
72564
- }else{
72565
- char *zToken = pOrig->u.zToken;
72566
- assert( zToken!=0 );
72567
- pOrig->u.zToken = 0;
72568
- pDup = sqlite3ExprDup(db, pOrig, 0);
72569
- pOrig->u.zToken = zToken;
72570
- if( pDup==0 ) return;
72571
- assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
72572
- pDup->flags2 |= EP2_MallocedToken;
72573
- pDup->u.zToken = sqlite3DbStrDup(db, zToken);
72574
- }
72575
- if( pExpr->flags & EP_ExpCollate ){
72576
- pDup->pColl = pExpr->pColl;
72577
- pDup->flags |= EP_ExpCollate;
72621
+ }
72622
+ if( pExpr->op==TK_COLLATE ){
72623
+ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
7257872624
}
7257972625
7258072626
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
7258172627
** prevents ExprDelete() from deleting the Expr structure itself,
7258272628
** allowing it to be repopulated by the memcpy() on the following line.
72629
+ ** The pExpr->u.zToken might point into memory that will be freed by the
72630
+ ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
72631
+ ** make a copy of the token before doing the sqlite3DbFree().
7258372632
*/
7258472633
ExprSetProperty(pExpr, EP_Static);
7258572634
sqlite3ExprDelete(db, pExpr);
7258672635
memcpy(pExpr, pDup, sizeof(*pExpr));
72636
+ if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
72637
+ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
72638
+ pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
72639
+ pExpr->flags2 |= EP2_MallocedToken;
72640
+ }
7258772641
sqlite3DbFree(db, pDup);
7258872642
}
7258972643
7259072644
7259172645
/*
@@ -72602,10 +72656,39 @@
7260272656
}
7260372657
}
7260472658
return 0;
7260572659
}
7260672660
72661
+/*
72662
+** Subqueries stores the original database, table and column names for their
72663
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
72664
+** Check to see if the zSpan given to this routine matches the zDb, zTab,
72665
+** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
72666
+** match anything.
72667
+*/
72668
+SQLITE_PRIVATE int sqlite3MatchSpanName(
72669
+ const char *zSpan,
72670
+ const char *zCol,
72671
+ const char *zTab,
72672
+ const char *zDb
72673
+){
72674
+ int n;
72675
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
72676
+ if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){
72677
+ return 0;
72678
+ }
72679
+ zSpan += n+1;
72680
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
72681
+ if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){
72682
+ return 0;
72683
+ }
72684
+ zSpan += n+1;
72685
+ if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
72686
+ return 0;
72687
+ }
72688
+ return 1;
72689
+}
7260772690
7260872691
/*
7260972692
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
7261072693
** that name in the set of source tables in pSrcList and make the pExpr
7261172694
** expression node refer back to that source column. The following changes
@@ -72657,44 +72740,63 @@
7265772740
7265872741
/* Initialize the node to no-match */
7265972742
pExpr->iTable = -1;
7266072743
pExpr->pTab = 0;
7266172744
ExprSetIrreducible(pExpr);
72745
+
72746
+ /* Translate the schema name in zDb into a pointer to the corresponding
72747
+ ** schema. If not found, pSchema will remain NULL and nothing will match
72748
+ ** resulting in an appropriate error message toward the end of this routine
72749
+ */
72750
+ if( zDb ){
72751
+ for(i=0; i<db->nDb; i++){
72752
+ assert( db->aDb[i].zName );
72753
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
72754
+ pSchema = db->aDb[i].pSchema;
72755
+ break;
72756
+ }
72757
+ }
72758
+ }
7266272759
7266372760
/* Start at the inner-most context and move outward until a match is found */
7266472761
while( pNC && cnt==0 ){
7266572762
ExprList *pEList;
7266672763
SrcList *pSrcList = pNC->pSrcList;
7266772764
7266872765
if( pSrcList ){
7266972766
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
7267072767
Table *pTab;
72671
- int iDb;
7267272768
Column *pCol;
7267372769
7267472770
pTab = pItem->pTab;
7267572771
assert( pTab!=0 && pTab->zName!=0 );
72676
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
7267772772
assert( pTab->nCol>0 );
72773
+ if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
72774
+ ExprList *pEList = pItem->pSelect->pEList;
72775
+ int hit = 0;
72776
+ for(j=0; j<pEList->nExpr; j++){
72777
+ if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
72778
+ cnt++;
72779
+ cntTab = 2;
72780
+ pMatch = pItem;
72781
+ pExpr->iColumn = j;
72782
+ hit = 1;
72783
+ }
72784
+ }
72785
+ if( hit || zTab==0 ) continue;
72786
+ }
72787
+ if( zDb && pTab->pSchema!=pSchema ){
72788
+ continue;
72789
+ }
7267872790
if( zTab ){
72679
- if( pItem->zAlias ){
72680
- char *zTabName = pItem->zAlias;
72681
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
72682
- }else{
72683
- char *zTabName = pTab->zName;
72684
- if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
72685
- continue;
72686
- }
72687
- if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
72688
- continue;
72689
- }
72791
+ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
72792
+ assert( zTabName!=0 );
72793
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ){
72794
+ continue;
7269072795
}
7269172796
}
7269272797
if( 0==(cntTab++) ){
72693
- pExpr->iTable = pItem->iCursor;
72694
- pExpr->pTab = pTab;
72695
- pSchema = pTab->pSchema;
7269672798
pMatch = pItem;
7269772799
}
7269872800
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
7269972801
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
7270072802
/* If there has been exactly one prior match and this match
@@ -72704,21 +72806,23 @@
7270472806
if( cnt==1 ){
7270572807
if( pItem->jointype & JT_NATURAL ) continue;
7270672808
if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
7270772809
}
7270872810
cnt++;
72709
- pExpr->iTable = pItem->iCursor;
72710
- pExpr->pTab = pTab;
7271172811
pMatch = pItem;
72712
- pSchema = pTab->pSchema;
7271372812
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
7271472813
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
7271572814
break;
7271672815
}
7271772816
}
7271872817
}
72719
- }
72818
+ if( pMatch ){
72819
+ pExpr->iTable = pMatch->iCursor;
72820
+ pExpr->pTab = pMatch->pTab;
72821
+ pSchema = pExpr->pTab->pSchema;
72822
+ }
72823
+ } /* if( pSrcList ) */
7272072824
7272172825
#ifndef SQLITE_OMIT_TRIGGER
7272272826
/* If we have not already resolved the name, then maybe
7272372827
** it is a new.* or old.* trigger argument reference
7272472828
*/
@@ -73013,42 +73117,43 @@
7301373117
int wrong_num_args = 0; /* True if wrong number of arguments */
7301473118
int is_agg = 0; /* True if is an aggregate function */
7301573119
int auth; /* Authorization to use the function */
7301673120
int nId; /* Number of characters in function name */
7301773121
const char *zId; /* The function name. */
73018
- FuncDef *pDef; /* Information about the function */
7301973122
u8 enc = ENC(pParse->db); /* The database encoding */
7302073123
7302173124
testcase( pExpr->op==TK_CONST_FUNC );
7302273125
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
7302373126
zId = pExpr->u.zToken;
7302473127
nId = sqlite3Strlen30(zId);
73025
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
73026
- if( pDef==0 ){
73027
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
73028
- if( pDef==0 ){
73029
- no_such_func = 1;
73030
- }else{
73031
- wrong_num_args = 1;
73032
- }
73033
- }else{
73034
- is_agg = pDef->xFunc==0;
73035
- }
73036
-#ifndef SQLITE_OMIT_AUTHORIZATION
73037
- if( pDef ){
73038
- auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
73039
- if( auth!=SQLITE_OK ){
73040
- if( auth==SQLITE_DENY ){
73041
- sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
73042
- pDef->zName);
73043
- pNC->nErr++;
73044
- }
73045
- pExpr->op = TK_NULL;
73046
- return WRC_Prune;
73047
- }
73048
- }
73049
-#endif
73128
+ if( pParse->db->init.busy==0 ){
73129
+ FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
73130
+ if( pDef==0 ){
73131
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
73132
+ if( pDef==0 ){
73133
+ no_such_func = 1;
73134
+ }else{
73135
+ wrong_num_args = 1;
73136
+ }
73137
+ }else{
73138
+ is_agg = pDef->xFunc==0;
73139
+ }
73140
+#ifndef SQLITE_OMIT_AUTHORIZATION
73141
+ if( pDef ){
73142
+ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
73143
+ if( auth!=SQLITE_OK ){
73144
+ if( auth==SQLITE_DENY ){
73145
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
73146
+ pDef->zName);
73147
+ pNC->nErr++;
73148
+ }
73149
+ pExpr->op = TK_NULL;
73150
+ return WRC_Prune;
73151
+ }
73152
+ }
73153
+#endif
73154
+ }
7305073155
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
7305173156
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
7305273157
pNC->nErr++;
7305373158
is_agg = 0;
7305473159
}else if( no_such_func ){
@@ -73268,11 +73373,11 @@
7326873373
assert( pEList!=0 );
7326973374
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
7327073375
int iCol = -1;
7327173376
Expr *pE, *pDup;
7327273377
if( pItem->done ) continue;
73273
- pE = pItem->pExpr;
73378
+ pE = sqlite3ExprSkipCollate(pItem->pExpr);
7327473379
if( sqlite3ExprIsInteger(pE, &iCol) ){
7327573380
if( iCol<=0 || iCol>pEList->nExpr ){
7327673381
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
7327773382
return 1;
7327873383
}
@@ -73286,18 +73391,24 @@
7328673391
}
7328773392
sqlite3ExprDelete(db, pDup);
7328873393
}
7328973394
}
7329073395
if( iCol>0 ){
73291
- CollSeq *pColl = pE->pColl;
73292
- int flags = pE->flags & EP_ExpCollate;
73396
+ /* Convert the ORDER BY term into an integer column number iCol,
73397
+ ** taking care to preserve the COLLATE clause if it exists */
73398
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
73399
+ if( pNew==0 ) return 1;
73400
+ pNew->flags |= EP_IntValue;
73401
+ pNew->u.iValue = iCol;
73402
+ if( pItem->pExpr==pE ){
73403
+ pItem->pExpr = pNew;
73404
+ }else{
73405
+ assert( pItem->pExpr->op==TK_COLLATE );
73406
+ assert( pItem->pExpr->pLeft==pE );
73407
+ pItem->pExpr->pLeft = pNew;
73408
+ }
7329373409
sqlite3ExprDelete(db, pE);
73294
- pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
73295
- if( pE==0 ) return 1;
73296
- pE->pColl = pColl;
73297
- pE->flags |= EP_IntValue | flags;
73298
- pE->u.iValue = iCol;
7329973410
pItem->iOrderByCol = (u16)iCol;
7330073411
pItem->done = 1;
7330173412
}else{
7330273413
moreToDo = 1;
7330373414
}
@@ -73398,15 +73509,15 @@
7339873509
** sqlite3ResolveOrderGroupBy() will convert the expression to a
7339973510
** copy of the iCol-th result-set expression. */
7340073511
pItem->iOrderByCol = (u16)iCol;
7340173512
continue;
7340273513
}
73403
- if( sqlite3ExprIsInteger(pE, &iCol) ){
73514
+ if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
7340473515
/* The ORDER BY term is an integer constant. Again, set the column
7340573516
** number so that sqlite3ResolveOrderGroupBy() will convert the
7340673517
** order-by term to a copy of the result-set expression */
73407
- if( iCol<1 ){
73518
+ if( iCol<1 || iCol>0xffff ){
7340873519
resolveOutOfRangeError(pParse, zType, i+1, nResult);
7340973520
return 1;
7341073521
}
7341173522
pItem->iOrderByCol = (u16)iCol;
7341273523
continue;
@@ -73479,27 +73590,10 @@
7347973590
if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
7348073591
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
7348173592
return WRC_Abort;
7348273593
}
7348373594
73484
- /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
73485
- ** resolve the result-set expression list.
73486
- */
73487
- sNC.ncFlags = NC_AllowAgg;
73488
- sNC.pSrcList = p->pSrc;
73489
- sNC.pNext = pOuterNC;
73490
-
73491
- /* Resolve names in the result set. */
73492
- pEList = p->pEList;
73493
- assert( pEList!=0 );
73494
- for(i=0; i<pEList->nExpr; i++){
73495
- Expr *pX = pEList->a[i].pExpr;
73496
- if( sqlite3ResolveExprNames(&sNC, pX) ){
73497
- return WRC_Abort;
73498
- }
73499
- }
73500
-
7350173595
/* Recursively resolve names in all subqueries
7350273596
*/
7350373597
for(i=0; i<p->pSrc->nSrc; i++){
7350473598
struct SrcList_item *pItem = &p->pSrc->a[i];
7350573599
if( pItem->pSelect ){
@@ -73522,10 +73616,27 @@
7352273616
for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
7352373617
assert( pItem->isCorrelated==0 && nRef<=0 );
7352473618
pItem->isCorrelated = (nRef!=0);
7352573619
}
7352673620
}
73621
+
73622
+ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
73623
+ ** resolve the result-set expression list.
73624
+ */
73625
+ sNC.ncFlags = NC_AllowAgg;
73626
+ sNC.pSrcList = p->pSrc;
73627
+ sNC.pNext = pOuterNC;
73628
+
73629
+ /* Resolve names in the result set. */
73630
+ pEList = p->pEList;
73631
+ assert( pEList!=0 );
73632
+ for(i=0; i<pEList->nExpr; i++){
73633
+ Expr *pX = pEList->a[i].pExpr;
73634
+ if( sqlite3ResolveExprNames(&sNC, pX) ){
73635
+ return WRC_Abort;
73636
+ }
73637
+ }
7352773638
7352873639
/* If there are no aggregate functions in the result-set, and no GROUP BY
7352973640
** expression, do not allow aggregates in any of the other expressions.
7353073641
*/
7353173642
assert( (p->selFlags & SF_Aggregate)==0 );
@@ -73756,11 +73867,13 @@
7375673867
** SELECT * FROM t1 WHERE a;
7375773868
** SELECT a AS b FROM t1 WHERE b;
7375873869
** SELECT * FROM t1 WHERE (select a from t1);
7375973870
*/
7376073871
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
73761
- int op = pExpr->op;
73872
+ int op;
73873
+ pExpr = sqlite3ExprSkipCollate(pExpr);
73874
+ op = pExpr->op;
7376273875
if( op==TK_SELECT ){
7376373876
assert( pExpr->flags&EP_xIsSelect );
7376473877
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
7376573878
}
7376673879
#ifndef SQLITE_OMIT_CAST
@@ -73781,70 +73894,98 @@
7378173894
}
7378273895
return pExpr->affinity;
7378373896
}
7378473897
7378573898
/*
73786
-** Set the explicit collating sequence for an expression to the
73787
-** collating sequence supplied in the second argument.
73788
-*/
73789
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
73790
- if( pExpr && pColl ){
73791
- pExpr->pColl = pColl;
73792
- pExpr->flags |= EP_ExpCollate;
73793
- }
73794
- return pExpr;
73795
-}
73796
-
73797
-/*
73798
-** Set the collating sequence for expression pExpr to be the collating
73799
-** sequence named by pToken. Return a pointer to the revised expression.
73800
-** The collating sequence is marked as "explicit" using the EP_ExpCollate
73801
-** flag. An explicit collating sequence will override implicit
73802
-** collating sequences.
73803
-*/
73804
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
73805
- char *zColl = 0; /* Dequoted name of collation sequence */
73806
- CollSeq *pColl;
73807
- sqlite3 *db = pParse->db;
73808
- zColl = sqlite3NameFromToken(db, pCollName);
73809
- pColl = sqlite3LocateCollSeq(pParse, zColl);
73810
- sqlite3ExprSetColl(pExpr, pColl);
73811
- sqlite3DbFree(db, zColl);
73812
- return pExpr;
73813
-}
73814
-
73815
-/*
73816
-** Return the default collation sequence for the expression pExpr. If
73817
-** there is no default collation type, return 0.
73818
-*/
73819
-SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
73820
- CollSeq *pColl = 0;
73821
- Expr *p = pExpr;
73822
- while( p ){
73823
- int op;
73824
- pColl = p->pColl;
73825
- if( pColl ) break;
73826
- op = p->op;
73827
- if( p->pTab!=0 && (
73828
- op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
73829
- )){
73830
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
73831
- ** a TK_COLUMN but was previously evaluated and cached in a register */
73832
- const char *zColl;
73833
- int j = p->iColumn;
73834
- if( j>=0 ){
73835
- sqlite3 *db = pParse->db;
73836
- zColl = p->pTab->aCol[j].zColl;
73837
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
73838
- pExpr->pColl = pColl;
73839
- }
73840
- break;
73841
- }
73842
- if( op!=TK_CAST && op!=TK_UPLUS ){
73843
- break;
73844
- }
73845
- p = p->pLeft;
73899
+** Set the collating sequence for expression pExpr to be the collating
73900
+** sequence named by pToken. Return a pointer to a new Expr node that
73901
+** implements the COLLATE operator.
73902
+**
73903
+** If a memory allocation error occurs, that fact is recorded in pParse->db
73904
+** and the pExpr parameter is returned unchanged.
73905
+*/
73906
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
73907
+ if( pCollName->n>0 ){
73908
+ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
73909
+ if( pNew ){
73910
+ pNew->pLeft = pExpr;
73911
+ pNew->flags |= EP_Collate;
73912
+ pExpr = pNew;
73913
+ }
73914
+ }
73915
+ return pExpr;
73916
+}
73917
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
73918
+ Token s;
73919
+ assert( zC!=0 );
73920
+ s.z = zC;
73921
+ s.n = sqlite3Strlen30(s.z);
73922
+ return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
73923
+}
73924
+
73925
+/*
73926
+** Skip over any TK_COLLATE and/or TK_AS operators at the root of
73927
+** an expression.
73928
+*/
73929
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
73930
+ while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
73931
+ pExpr = pExpr->pLeft;
73932
+ }
73933
+ return pExpr;
73934
+}
73935
+
73936
+/*
73937
+** Return the collation sequence for the expression pExpr. If
73938
+** there is no defined collating sequence, return NULL.
73939
+**
73940
+** The collating sequence might be determined by a COLLATE operator
73941
+** or by the presence of a column with a defined collating sequence.
73942
+** COLLATE operators take first precedence. Left operands take
73943
+** precedence over right operands.
73944
+*/
73945
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
73946
+ sqlite3 *db = pParse->db;
73947
+ CollSeq *pColl = 0;
73948
+ Expr *p = pExpr;
73949
+ while( p ){
73950
+ int op = p->op;
73951
+ if( op==TK_CAST || op==TK_UPLUS ){
73952
+ p = p->pLeft;
73953
+ continue;
73954
+ }
73955
+ assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
73956
+ if( op==TK_COLLATE ){
73957
+ if( db->init.busy ){
73958
+ /* Do not report errors when parsing while the schema */
73959
+ pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
73960
+ }else{
73961
+ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
73962
+ }
73963
+ break;
73964
+ }
73965
+ if( p->pTab!=0
73966
+ && (op==TK_AGG_COLUMN || op==TK_COLUMN
73967
+ || op==TK_REGISTER || op==TK_TRIGGER)
73968
+ ){
73969
+ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
73970
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
73971
+ int j = p->iColumn;
73972
+ if( j>=0 ){
73973
+ const char *zColl = p->pTab->aCol[j].zColl;
73974
+ pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
73975
+ }
73976
+ break;
73977
+ }
73978
+ if( p->flags & EP_Collate ){
73979
+ if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
73980
+ p = p->pLeft;
73981
+ }else{
73982
+ p = p->pRight;
73983
+ }
73984
+ }else{
73985
+ break;
73986
+ }
7384673987
}
7384773988
if( sqlite3CheckCollSeq(pParse, pColl) ){
7384873989
pColl = 0;
7384973990
}
7385073991
return pColl;
@@ -73944,16 +74085,14 @@
7394474085
Expr *pLeft,
7394574086
Expr *pRight
7394674087
){
7394774088
CollSeq *pColl;
7394874089
assert( pLeft );
73949
- if( pLeft->flags & EP_ExpCollate ){
73950
- assert( pLeft->pColl );
73951
- pColl = pLeft->pColl;
73952
- }else if( pRight && pRight->flags & EP_ExpCollate ){
73953
- assert( pRight->pColl );
73954
- pColl = pRight->pColl;
74090
+ if( pLeft->flags & EP_Collate ){
74091
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
74092
+ }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
74093
+ pColl = sqlite3ExprCollSeq(pParse, pRight);
7395574094
}else{
7395674095
pColl = sqlite3ExprCollSeq(pParse, pLeft);
7395774096
if( !pColl ){
7395874097
pColl = sqlite3ExprCollSeq(pParse, pRight);
7395974098
}
@@ -74179,21 +74318,15 @@
7417974318
sqlite3ExprDelete(db, pLeft);
7418074319
sqlite3ExprDelete(db, pRight);
7418174320
}else{
7418274321
if( pRight ){
7418374322
pRoot->pRight = pRight;
74184
- if( pRight->flags & EP_ExpCollate ){
74185
- pRoot->flags |= EP_ExpCollate;
74186
- pRoot->pColl = pRight->pColl;
74187
- }
74323
+ pRoot->flags |= EP_Collate & pRight->flags;
7418874324
}
7418974325
if( pLeft ){
7419074326
pRoot->pLeft = pLeft;
74191
- if( pLeft->flags & EP_ExpCollate ){
74192
- pRoot->flags |= EP_ExpCollate;
74193
- pRoot->pColl = pLeft->pColl;
74194
- }
74327
+ pRoot->flags |= EP_Collate & pLeft->flags;
7419574328
}
7419674329
exprSetHeight(pRoot);
7419774330
}
7419874331
}
7419974332
@@ -74447,11 +74580,11 @@
7444774580
}else{
7444874581
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
7444974582
assert( !ExprHasProperty(p, EP_FromJoin) );
7445074583
assert( (p->flags2 & EP2_MallocedToken)==0 );
7445174584
assert( (p->flags2 & EP2_Irreducible)==0 );
74452
- if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
74585
+ if( p->pLeft || p->pRight || p->x.pList ){
7445374586
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
7445474587
}else{
7445574588
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
7445674589
}
7445774590
}
@@ -76471,10 +76604,11 @@
7647176604
sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
7647276605
sqlite3ReleaseTempReg(pParse, r3);
7647376606
sqlite3ReleaseTempReg(pParse, r4);
7647476607
break;
7647576608
}
76609
+ case TK_COLLATE:
7647676610
case TK_UPLUS: {
7647776611
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
7647876612
break;
7647976613
}
7648076614
@@ -76839,10 +76973,16 @@
7683976973
case TK_UPLUS: zUniOp = "UPLUS"; break;
7684076974
case TK_BITNOT: zUniOp = "BITNOT"; break;
7684176975
case TK_NOT: zUniOp = "NOT"; break;
7684276976
case TK_ISNULL: zUniOp = "ISNULL"; break;
7684376977
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
76978
+
76979
+ case TK_COLLATE: {
76980
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
76981
+ sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
76982
+ break;
76983
+ }
7684476984
7684576985
case TK_AGG_FUNCTION:
7684676986
case TK_CONST_FUNC:
7684776987
case TK_FUNCTION: {
7684876988
ExprList *pFarg; /* List of function arguments */
@@ -76977,10 +77117,16 @@
7697777117
for(i=0; i<pList->nExpr; i++){
7697877118
sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
7697977119
sqlite3ExplainPush(pOut);
7698077120
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
7698177121
sqlite3ExplainPop(pOut);
77122
+ if( pList->a[i].zName ){
77123
+ sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
77124
+ }
77125
+ if( pList->a[i].bSpanIsTab ){
77126
+ sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
77127
+ }
7698277128
if( i<pList->nExpr-1 ){
7698377129
sqlite3ExplainNL(pOut);
7698477130
}
7698577131
}
7698677132
sqlite3ExplainPop(pOut);
@@ -77058,10 +77204,13 @@
7705877204
switch( pExpr->op ){
7705977205
case TK_IN:
7706077206
case TK_REGISTER: {
7706177207
return WRC_Prune;
7706277208
}
77209
+ case TK_COLLATE: {
77210
+ return WRC_Continue;
77211
+ }
7706377212
case TK_FUNCTION:
7706477213
case TK_AGG_FUNCTION:
7706577214
case TK_CONST_FUNC: {
7706677215
/* The arguments to a function have a fixed destination.
7706777216
** Mark them this way to avoid generated unneeded OP_SCopy
@@ -77079,13 +77228,15 @@
7707977228
break;
7708077229
}
7708177230
}
7708277231
if( isAppropriateForFactoring(pExpr) ){
7708377232
int r1 = ++pParse->nMem;
77084
- int r2;
77085
- r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
77086
- if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
77233
+ int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
77234
+ /* If r2!=r1, it means that register r1 is never used. That is harmless
77235
+ ** but suboptimal, so we want to know about the situation to fix it.
77236
+ ** Hence the following assert: */
77237
+ assert( r2==r1 );
7708777238
pExpr->op2 = pExpr->op;
7708877239
pExpr->op = TK_REGISTER;
7708977240
pExpr->iTable = r2;
7709077241
return WRC_Prune;
7709177242
}
@@ -77498,11 +77649,19 @@
7749877649
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
7749977650
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
7750077651
return 2;
7750177652
}
7750277653
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
77503
- if( pA->op!=pB->op ) return 2;
77654
+ if( pA->op!=pB->op ){
77655
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
77656
+ return 1;
77657
+ }
77658
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
77659
+ return 1;
77660
+ }
77661
+ return 2;
77662
+ }
7750477663
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
7750577664
if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
7750677665
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
7750777666
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
7750877667
if( ExprHasProperty(pA, EP_IntValue) ){
@@ -77510,15 +77669,13 @@
7751077669
return 2;
7751177670
}
7751277671
}else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
7751377672
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
7751477673
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
77515
- return 2;
77674
+ return pA->op==TK_COLLATE ? 1 : 2;
7751677675
}
7751777676
}
77518
- if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
77519
- if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
7752077677
return 0;
7752177678
}
7752277679
7752377680
/*
7752477681
** Compare two ExprList objects. Return 0 if they are identical and
@@ -80765,10 +80922,11 @@
8076580922
*/
8076680923
SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
8076780924
sqlite3 *db;
8076880925
Vdbe *v;
8076980926
80927
+ assert( pParse->pToplevel==0 );
8077080928
db = pParse->db;
8077180929
if( db->mallocFailed ) return;
8077280930
if( pParse->nested ) return;
8077380931
if( pParse->nErr ) return;
8077480932
@@ -83328,14 +83486,12 @@
8332883486
** specified collation sequence names.
8332983487
*/
8333083488
for(i=0; i<pList->nExpr; i++){
8333183489
Expr *pExpr = pList->a[i].pExpr;
8333283490
if( pExpr ){
83333
- CollSeq *pColl = pExpr->pColl;
83334
- /* Either pColl!=0 or there was an OOM failure. But if an OOM
83335
- ** failure we have quit before reaching this point. */
83336
- if( ALWAYS(pColl) ){
83491
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
83492
+ if( pColl ){
8333783493
nExtra += (1 + sqlite3Strlen30(pColl->zName));
8333883494
}
8333983495
}
8334083496
}
8334183497
@@ -83394,10 +83550,11 @@
8339483550
*/
8339583551
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
8339683552
const char *zColName = pListItem->zName;
8339783553
Column *pTabCol;
8339883554
int requestedSortOrder;
83555
+ CollSeq *pColl; /* Collating sequence */
8339983556
char *zColl; /* Collation sequence name */
8340083557
8340183558
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
8340283559
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
8340383560
}
@@ -83406,18 +83563,15 @@
8340683563
pTab->zName, zColName);
8340783564
pParse->checkSchema = 1;
8340883565
goto exit_create_index;
8340983566
}
8341083567
pIndex->aiColumn[i] = j;
83411
- /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of
83412
- ** the way the "idxlist" non-terminal is constructed by the parser,
83413
- ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
83414
- ** must exist or else there must have been an OOM error. But if there
83415
- ** was an OOM error, we would never reach this point. */
83416
- if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
83568
+ if( pListItem->pExpr
83569
+ && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
83570
+ ){
8341783571
int nColl;
83418
- zColl = pListItem->pExpr->pColl->zName;
83572
+ zColl = pColl->zName;
8341983573
nColl = sqlite3Strlen30(zColl) + 1;
8342083574
assert( nExtra>=nColl );
8342183575
memcpy(zExtra, zColl, nColl);
8342283576
zColl = zExtra;
8342383577
zExtra += nColl;
@@ -84227,10 +84381,19 @@
8422784381
** early in the code, before we know if any database tables will be used.
8422884382
*/
8422984383
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
8423084384
Parse *pToplevel = sqlite3ParseToplevel(pParse);
8423184385
84386
+#ifndef SQLITE_OMIT_TRIGGER
84387
+ if( pToplevel!=pParse ){
84388
+ /* This branch is taken if a trigger is currently being coded. In this
84389
+ ** case, set cookieGoto to a non-zero value to show that this function
84390
+ ** has been called. This is used by the sqlite3ExprCodeConstants()
84391
+ ** function. */
84392
+ pParse->cookieGoto = -1;
84393
+ }
84394
+#endif
8423284395
if( pToplevel->cookieGoto==0 ){
8423384396
Vdbe *v = sqlite3GetVdbe(pToplevel);
8423484397
if( v==0 ) return; /* This only happens if there was a prior error */
8423584398
pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
8423684399
}
@@ -87437,11 +87600,11 @@
8743787600
8743887601
/*
8743987602
** A foreign key constraint requires that the key columns in the parent
8744087603
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
8744187604
** Given that pParent is the parent table for foreign key constraint pFKey,
87442
-** search the schema a unique index on the parent key columns.
87605
+** search the schema for a unique index on the parent key columns.
8744387606
**
8744487607
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
8744587608
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
8744687609
** is set to point to the unique index.
8744787610
**
@@ -87473,11 +87636,11 @@
8747387636
**
8747487637
** then non-zero is returned, and a "foreign key mismatch" error loaded
8747587638
** into pParse. If an OOM error occurs, non-zero is returned and the
8747687639
** pParse->db->mallocFailed flag is set.
8747787640
*/
87478
-static int locateFkeyIndex(
87641
+SQLITE_PRIVATE int sqlite3FkLocateIndex(
8747987642
Parse *pParse, /* Parse context to store any error in */
8748087643
Table *pParent, /* Parent table of FK constraint pFKey */
8748187644
FKey *pFKey, /* Foreign key to find index for */
8748287645
Index **ppIdx, /* OUT: Unique index on parent table */
8748387646
int **paiCol /* OUT: Map of index columns in pFKey */
@@ -87570,11 +87733,13 @@
8757087733
}
8757187734
}
8757287735
8757387736
if( !pIdx ){
8757487737
if( !pParse->disableTriggers ){
87575
- sqlite3ErrorMsg(pParse, "foreign key mismatch");
87738
+ sqlite3ErrorMsg(pParse,
87739
+ "foreign key mismatch - \"%w\" referencing \"%w\"",
87740
+ pFKey->pFrom->zName, pFKey->zTo);
8757687741
}
8757787742
sqlite3DbFree(pParse->db, aiCol);
8757887743
return 1;
8757987744
}
8758087745
@@ -87806,16 +87971,19 @@
8780687971
if( pLeft ){
8780787972
/* Set the collation sequence and affinity of the LHS of each TK_EQ
8780887973
** expression to the parent key column defaults. */
8780987974
if( pIdx ){
8781087975
Column *pCol;
87976
+ const char *zColl;
8781187977
iCol = pIdx->aiColumn[i];
8781287978
pCol = &pTab->aCol[iCol];
8781387979
if( pTab->iPKey==iCol ) iCol = -1;
8781487980
pLeft->iTable = regData+iCol+1;
8781587981
pLeft->affinity = pCol->affinity;
87816
- pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
87982
+ zColl = pCol->zColl;
87983
+ if( zColl==0 ) zColl = db->pDfltColl->zName;
87984
+ pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
8781787985
}else{
8781887986
pLeft->iTable = regData;
8781987987
pLeft->affinity = SQLITE_AFF_INTEGER;
8782087988
}
8782187989
}
@@ -88028,11 +88196,11 @@
8802888196
if( pParse->disableTriggers ){
8802988197
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
8803088198
}else{
8803188199
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
8803288200
}
88033
- if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
88201
+ if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
8803488202
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
8803588203
if( !isIgnoreErrors || db->mallocFailed ) return;
8803688204
if( pTo==0 ){
8803788205
/* If isIgnoreErrors is true, then a table is being dropped. In this
8803888206
** case SQLite runs a "DELETE FROM xxx" on the table being dropped
@@ -88108,11 +88276,11 @@
8810888276
/* Inserting a single row into a parent table cannot cause an immediate
8810988277
** foreign key violation. So do nothing in this case. */
8811088278
continue;
8811188279
}
8811288280
88113
- if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
88281
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
8811488282
if( !isIgnoreErrors || db->mallocFailed ) return;
8811588283
continue;
8811688284
}
8811788285
assert( aiCol || pFKey->nCol==1 );
8811888286
@@ -88163,11 +88331,11 @@
8816388331
for(p=pTab->pFKey; p; p=p->pNextFrom){
8816488332
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
8816588333
}
8816688334
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
8816788335
Index *pIdx = 0;
88168
- locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
88336
+ sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
8816988337
if( pIdx ){
8817088338
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
8817188339
}
8817288340
}
8817388341
}
@@ -88289,11 +88457,11 @@
8828988457
ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
8829088458
Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
8829188459
int i; /* Iterator variable */
8829288460
Expr *pWhen = 0; /* WHEN clause for the trigger */
8829388461
88294
- if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
88462
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
8829588463
assert( aiCol || pFKey->nCol==1 );
8829688464
8829788465
for(i=0; i<pFKey->nCol; i++){
8829888466
Token tOld = { "old", 3 }; /* Literal "old" token */
8829988467
Token tNew = { "new", 3 }; /* Literal "new" token */
@@ -89791,29 +89959,24 @@
8979189959
ExprList *pCheck = pTab->pCheck;
8979289960
pParse->ckBase = regData;
8979389961
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
8979489962
for(i=0; i<pCheck->nExpr; i++){
8979589963
int allOk = sqlite3VdbeMakeLabel(v);
89796
- Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
89797
- if( !db->mallocFailed ){
89798
- assert( pDup!=0 );
89799
- sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
89800
- if( onError==OE_Ignore ){
89801
- sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
89802
- }else{
89803
- char *zConsName = pCheck->a[i].zName;
89804
- if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
89805
- if( zConsName ){
89806
- zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
89807
- }else{
89808
- zConsName = 0;
89809
- }
89810
- sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
89811
- }
89812
- sqlite3VdbeResolveLabel(v, allOk);
89813
- }
89814
- sqlite3ExprDelete(db, pDup);
89964
+ sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
89965
+ if( onError==OE_Ignore ){
89966
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
89967
+ }else{
89968
+ char *zConsName = pCheck->a[i].zName;
89969
+ if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
89970
+ if( zConsName ){
89971
+ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
89972
+ }else{
89973
+ zConsName = 0;
89974
+ }
89975
+ sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
89976
+ }
89977
+ sqlite3VdbeResolveLabel(v, allOk);
8981589978
}
8981689979
}
8981789980
#endif /* !defined(SQLITE_OMIT_CHECK) */
8981889981
8981989982
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
@@ -92634,13 +92797,15 @@
9263492797
if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
9263592798
Table *pTab;
9263692799
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9263792800
pTab = sqlite3FindTable(db, zRight, zDb);
9263892801
if( pTab ){
92639
- int i;
92802
+ int i, k;
9264092803
int nHidden = 0;
9264192804
Column *pCol;
92805
+ Index *pPk;
92806
+ for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
9264292807
sqlite3VdbeSetNumCols(v, 6);
9264392808
pParse->nMem = 6;
9264492809
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
9264592810
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
9264692811
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92661,12 +92826,18 @@
9266192826
if( pCol->zDflt ){
9266292827
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
9266392828
}else{
9266492829
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
9266592830
}
92666
- sqlite3VdbeAddOp2(v, OP_Integer,
92667
- (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
92831
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
92832
+ k = 0;
92833
+ }else if( pPk==0 ){
92834
+ k = 1;
92835
+ }else{
92836
+ for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
92837
+ }
92838
+ sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
9266892839
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
9266992840
}
9267092841
}
9267192842
}else
9267292843
@@ -92797,10 +92968,124 @@
9279792968
++i;
9279892969
pFK = pFK->pNextFrom;
9279992970
}
9280092971
}
9280192972
}
92973
+ }else
92974
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
92975
+
92976
+#ifndef SQLITE_OMIT_FOREIGN_KEY
92977
+ if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
92978
+ FKey *pFK; /* A foreign key constraint */
92979
+ Table *pTab; /* Child table contain "REFERENCES" keyword */
92980
+ Table *pParent; /* Parent table that child points to */
92981
+ Index *pIdx; /* Index in the parent table */
92982
+ int i; /* Loop counter: Foreign key number for pTab */
92983
+ int j; /* Loop counter: Field of the foreign key */
92984
+ HashElem *k; /* Loop counter: Next table in schema */
92985
+ int x; /* result variable */
92986
+ int regResult; /* 3 registers to hold a result row */
92987
+ int regKey; /* Register to hold key for checking the FK */
92988
+ int regRow; /* Registers to hold a row from pTab */
92989
+ int addrTop; /* Top of a loop checking foreign keys */
92990
+ int addrOk; /* Jump here if the key is OK */
92991
+ int *aiCols; /* child to parent column mapping */
92992
+
92993
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
92994
+ regResult = pParse->nMem+1;
92995
+ pParse->nMem += 4;
92996
+ regKey = ++pParse->nMem;
92997
+ regRow = ++pParse->nMem;
92998
+ v = sqlite3GetVdbe(pParse);
92999
+ sqlite3VdbeSetNumCols(v, 4);
93000
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
93001
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
93002
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
93003
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
93004
+ sqlite3CodeVerifySchema(pParse, iDb);
93005
+ k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
93006
+ while( k ){
93007
+ if( zRight ){
93008
+ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
93009
+ k = 0;
93010
+ }else{
93011
+ pTab = (Table*)sqliteHashData(k);
93012
+ k = sqliteHashNext(k);
93013
+ }
93014
+ if( pTab==0 || pTab->pFKey==0 ) continue;
93015
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
93016
+ if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
93017
+ sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
93018
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
93019
+ P4_TRANSIENT);
93020
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
93021
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
93022
+ if( pParent==0 ) break;
93023
+ pIdx = 0;
93024
+ sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
93025
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
93026
+ if( x==0 ){
93027
+ if( pIdx==0 ){
93028
+ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
93029
+ }else{
93030
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
93031
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
93032
+ sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
93033
+ }
93034
+ }else{
93035
+ k = 0;
93036
+ break;
93037
+ }
93038
+ }
93039
+ if( pFK ) break;
93040
+ if( pParse->nTab<i ) pParse->nTab = i;
93041
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
93042
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
93043
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
93044
+ assert( pParent!=0 );
93045
+ pIdx = 0;
93046
+ aiCols = 0;
93047
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
93048
+ assert( x==0 );
93049
+ addrOk = sqlite3VdbeMakeLabel(v);
93050
+ if( pIdx==0 ){
93051
+ int iKey = pFK->aCol[0].iFrom;
93052
+ assert( iKey>=0 && iKey<pTab->nCol );
93053
+ if( iKey!=pTab->iPKey ){
93054
+ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
93055
+ sqlite3ColumnDefault(v, pTab, iKey, regRow);
93056
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
93057
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
93058
+ sqlite3VdbeCurrentAddr(v)+3);
93059
+ }else{
93060
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
93061
+ }
93062
+ sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
93063
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
93064
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
93065
+ }else{
93066
+ for(j=0; j<pFK->nCol; j++){
93067
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
93068
+ aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
93069
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
93070
+ }
93071
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
93072
+ sqlite3VdbeChangeP4(v, -1,
93073
+ sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
93074
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
93075
+ }
93076
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
93077
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
93078
+ pFK->zTo, P4_TRANSIENT);
93079
+ sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
93080
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
93081
+ sqlite3VdbeResolveLabel(v, addrOk);
93082
+ sqlite3DbFree(db, aiCols);
93083
+ }
93084
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
93085
+ sqlite3VdbeJumpHere(v, addrTop);
93086
+ }
9280293087
}else
9280393088
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
9280493089
9280593090
#ifndef NDEBUG
9280693091
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -94256,11 +94541,11 @@
9425694541
SrcList *pSrc, /* the FROM clause -- which tables to scan */
9425794542
Expr *pWhere, /* the WHERE clause */
9425894543
ExprList *pGroupBy, /* the GROUP BY clause */
9425994544
Expr *pHaving, /* the HAVING clause */
9426094545
ExprList *pOrderBy, /* the ORDER BY clause */
94261
- int isDistinct, /* true if the DISTINCT keyword is present */
94546
+ u16 selFlags, /* Flag parameters, such as SF_Distinct */
9426294547
Expr *pLimit, /* LIMIT value. NULL means not used */
9426394548
Expr *pOffset /* OFFSET value. NULL means no offset */
9426494549
){
9426594550
Select *pNew;
9426694551
Select standin;
@@ -94280,11 +94565,11 @@
9428094565
pNew->pSrc = pSrc;
9428194566
pNew->pWhere = pWhere;
9428294567
pNew->pGroupBy = pGroupBy;
9428394568
pNew->pHaving = pHaving;
9428494569
pNew->pOrderBy = pOrderBy;
94285
- pNew->selFlags = isDistinct ? SF_Distinct : 0;
94570
+ pNew->selFlags = selFlags;
9428694571
pNew->op = TK_SELECT;
9428794572
pNew->pLimit = pLimit;
9428894573
pNew->pOffset = pOffset;
9428994574
assert( pOffset==0 || pLimit!=0 );
9429094575
pNew->addrOpenEphm[0] = -1;
@@ -95536,13 +95821,11 @@
9553695821
*paCol = aCol;
9553795822
9553895823
for(i=0, pCol=aCol; i<nCol; i++, pCol++){
9553995824
/* Get an appropriate name for the column
9554095825
*/
95541
- p = pEList->a[i].pExpr;
95542
- assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
95543
- || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
95826
+ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
9554495827
if( (zName = pEList->a[i].zName)!=0 ){
9554595828
/* If the column contains an "AS <name>" phrase, use <name> as the name */
9554695829
zName = sqlite3DbStrDup(db, zName);
9554795830
}else{
9554895831
Expr *pColExpr = p; /* The expression that is the result column name */
@@ -95576,10 +95859,13 @@
9557695859
*/
9557795860
nName = sqlite3Strlen30(zName);
9557895861
for(j=cnt=0; j<i; j++){
9557995862
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
9558095863
char *zNewName;
95864
+ int k;
95865
+ for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
95866
+ if( zName[k]==':' ) nName = k;
9558195867
zName[nName] = 0;
9558295868
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
9558395869
sqlite3DbFree(db, zName);
9558495870
zName = zNewName;
9558595871
j = -1;
@@ -96534,16 +96820,17 @@
9653496820
pKeyMerge->nField = (u16)nOrderBy;
9653596821
pKeyMerge->enc = ENC(db);
9653696822
for(i=0; i<nOrderBy; i++){
9653796823
CollSeq *pColl;
9653896824
Expr *pTerm = pOrderBy->a[i].pExpr;
96539
- if( pTerm->flags & EP_ExpCollate ){
96540
- pColl = pTerm->pColl;
96825
+ if( pTerm->flags & EP_Collate ){
96826
+ pColl = sqlite3ExprCollSeq(pParse, pTerm);
9654196827
}else{
9654296828
pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
96543
- pTerm->flags |= EP_ExpCollate;
96544
- pTerm->pColl = pColl;
96829
+ if( pColl==0 ) pColl = db->pDfltColl;
96830
+ pOrderBy->a[i].pExpr =
96831
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
9654596832
}
9654696833
pKeyMerge->aColl[i] = pColl;
9654796834
pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
9654896835
}
9654996836
}
@@ -96742,10 +97029,11 @@
9674297029
*/
9674397030
sqlite3VdbeResolveLabel(v, labelCmpr);
9674497031
sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
9674597032
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
9674697033
(char*)pKeyMerge, P4_KEYINFO_HANDOFF);
97034
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
9674797035
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
9674897036
9674997037
/* Release temporary registers
9675097038
*/
9675197039
if( regPrev ){
@@ -96809,13 +97097,10 @@
9680997097
}else{
9681097098
Expr *pNew;
9681197099
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
9681297100
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
9681397101
pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
96814
- if( pNew && pExpr->pColl ){
96815
- pNew->pColl = pExpr->pColl;
96816
- }
9681797102
sqlite3ExprDelete(db, pExpr);
9681897103
pExpr = pNew;
9681997104
}
9682097105
}else{
9682197106
pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
@@ -97362,38 +97647,47 @@
9736297647
return 1;
9736397648
}
9736497649
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
9736597650
9736697651
/*
97367
-** Analyze the SELECT statement passed as an argument to see if it
97368
-** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
97369
-** it is, or 0 otherwise. At present, a query is considered to be
97370
-** a min()/max() query if:
97371
-**
97372
-** 1. There is a single object in the FROM clause.
97373
-**
97374
-** 2. There is a single expression in the result set, and it is
97375
-** either min(x) or max(x), where x is a column reference.
97376
-*/
97377
-static u8 minMaxQuery(Select *p){
97378
- Expr *pExpr;
97379
- ExprList *pEList = p->pEList;
97380
-
97381
- if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
97382
- pExpr = pEList->a[0].pExpr;
97383
- if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
97384
- if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
97385
- pEList = pExpr->x.pList;
97386
- if( pEList==0 || pEList->nExpr!=1 ) return 0;
97387
- if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
97388
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
97389
- if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
97390
- return WHERE_ORDERBY_MIN;
97391
- }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
97392
- return WHERE_ORDERBY_MAX;
97393
- }
97394
- return WHERE_ORDERBY_NORMAL;
97652
+** Based on the contents of the AggInfo structure indicated by the first
97653
+** argument, this function checks if the following are true:
97654
+**
97655
+** * the query contains just a single aggregate function,
97656
+** * the aggregate function is either min() or max(), and
97657
+** * the argument to the aggregate function is a column value.
97658
+**
97659
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
97660
+** is returned as appropriate. Also, *ppMinMax is set to point to the
97661
+** list of arguments passed to the aggregate before returning.
97662
+**
97663
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and
97664
+** WHERE_ORDERBY_NORMAL is returned.
97665
+*/
97666
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
97667
+ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
97668
+
97669
+ *ppMinMax = 0;
97670
+ if( pAggInfo->nFunc==1 ){
97671
+ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
97672
+ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */
97673
+
97674
+ assert( pExpr->op==TK_AGG_FUNCTION );
97675
+ if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
97676
+ const char *zFunc = pExpr->u.zToken;
97677
+ if( sqlite3StrICmp(zFunc, "min")==0 ){
97678
+ eRet = WHERE_ORDERBY_MIN;
97679
+ *ppMinMax = pEList;
97680
+ }else if( sqlite3StrICmp(zFunc, "max")==0 ){
97681
+ eRet = WHERE_ORDERBY_MAX;
97682
+ *ppMinMax = pEList;
97683
+ }
97684
+ }
97685
+ }
97686
+
97687
+ assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
97688
+ return eRet;
9739597689
}
9739697690
9739797691
/*
9739897692
** The select statement passed as the first argument is an aggregate query.
9739997693
** The second argment is the associated aggregate-info object. This
@@ -97484,10 +97778,11 @@
9748497778
int i, j, k;
9748597779
SrcList *pTabList;
9748697780
ExprList *pEList;
9748797781
struct SrcList_item *pFrom;
9748897782
sqlite3 *db = pParse->db;
97783
+ Expr *pE, *pRight, *pExpr;
9748997784
9749097785
if( db->mallocFailed ){
9749197786
return WRC_Abort;
9749297787
}
9749397788
if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
@@ -97569,11 +97864,11 @@
9756997864
**
9757097865
** The first loop just checks to see if there are any "*" operators
9757197866
** that need expanding.
9757297867
*/
9757397868
for(k=0; k<pEList->nExpr; k++){
97574
- Expr *pE = pEList->a[k].pExpr;
97869
+ pE = pEList->a[k].pExpr;
9757597870
if( pE->op==TK_ALL ) break;
9757697871
assert( pE->op!=TK_DOT || pE->pRight!=0 );
9757797872
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
9757897873
if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
9757997874
}
@@ -97587,14 +97882,22 @@
9758797882
ExprList *pNew = 0;
9758897883
int flags = pParse->db->flags;
9758997884
int longNames = (flags & SQLITE_FullColNames)!=0
9759097885
&& (flags & SQLITE_ShortColNames)==0;
9759197886
97887
+ /* When processing FROM-clause subqueries, it is always the case
97888
+ ** that full_column_names=OFF and short_column_names=ON. The
97889
+ ** sqlite3ResultSetOfSelect() routine makes it so. */
97890
+ assert( (p->selFlags & SF_NestedFrom)==0
97891
+ || ((flags & SQLITE_FullColNames)==0 &&
97892
+ (flags & SQLITE_ShortColNames)!=0) );
97893
+
9759297894
for(k=0; k<pEList->nExpr; k++){
97593
- Expr *pE = a[k].pExpr;
97594
- assert( pE->op!=TK_DOT || pE->pRight!=0 );
97595
- if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
97895
+ pE = a[k].pExpr;
97896
+ pRight = pE->pRight;
97897
+ assert( pE->op!=TK_DOT || pRight!=0 );
97898
+ if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
9759697899
/* This particular expression does not need to be expanded.
9759797900
*/
9759897901
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
9759997902
if( pNew ){
9760097903
pNew->a[pNew->nExpr-1].zName = a[k].zName;
@@ -97605,44 +97908,56 @@
9760597908
a[k].pExpr = 0;
9760697909
}else{
9760797910
/* This expression is a "*" or a "TABLE.*" and needs to be
9760897911
** expanded. */
9760997912
int tableSeen = 0; /* Set to 1 when TABLE matches */
97610
- char *zTName; /* text of name of TABLE */
97913
+ char *zTName = 0; /* text of name of TABLE */
9761197914
if( pE->op==TK_DOT ){
9761297915
assert( pE->pLeft!=0 );
9761397916
assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
9761497917
zTName = pE->pLeft->u.zToken;
97615
- }else{
97616
- zTName = 0;
9761797918
}
9761897919
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
9761997920
Table *pTab = pFrom->pTab;
97921
+ Select *pSub = pFrom->pSelect;
9762097922
char *zTabName = pFrom->zAlias;
97923
+ const char *zSchemaName = 0;
97924
+ int iDb;
9762197925
if( zTabName==0 ){
9762297926
zTabName = pTab->zName;
9762397927
}
9762497928
if( db->mallocFailed ) break;
97625
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
97626
- continue;
97929
+ if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
97930
+ pSub = 0;
97931
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
97932
+ continue;
97933
+ }
97934
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
97935
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
9762797936
}
97628
- tableSeen = 1;
9762997937
for(j=0; j<pTab->nCol; j++){
97630
- Expr *pExpr, *pRight;
9763197938
char *zName = pTab->aCol[j].zName;
9763297939
char *zColname; /* The computed column name */
9763397940
char *zToFree; /* Malloced string that needs to be freed */
9763497941
Token sColname; /* Computed column name as a token */
97942
+
97943
+ assert( zName );
97944
+ if( zTName && pSub
97945
+ && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
97946
+ ){
97947
+ continue;
97948
+ }
9763597949
9763697950
/* If a column is marked as 'hidden' (currently only possible
9763797951
** for virtual tables), do not include it in the expanded
9763897952
** result-set list.
9763997953
*/
9764097954
if( IsHiddenColumn(&pTab->aCol[j]) ){
9764197955
assert(IsVirtual(pTab));
9764297956
continue;
9764397957
}
97958
+ tableSeen = 1;
9764497959
9764597960
if( i>0 && zTName==0 ){
9764697961
if( (pFrom->jointype & JT_NATURAL)!=0
9764797962
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
9764897963
){
@@ -97661,10 +97976,14 @@
9766197976
zToFree = 0;
9766297977
if( longNames || pTabList->nSrc>1 ){
9766397978
Expr *pLeft;
9766497979
pLeft = sqlite3Expr(db, TK_ID, zTabName);
9766597980
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
97981
+ if( zSchemaName ){
97982
+ pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
97983
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
97984
+ }
9766697985
if( longNames ){
9766797986
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
9766897987
zToFree = zColname;
9766997988
}
9767097989
}else{
@@ -97672,10 +97991,22 @@
9767297991
}
9767397992
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
9767497993
sColname.z = zColname;
9767597994
sColname.n = sqlite3Strlen30(zColname);
9767697995
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
97996
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
97997
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
97998
+ if( pSub ){
97999
+ pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
98000
+ testcase( pX->zSpan==0 );
98001
+ }else{
98002
+ pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
98003
+ zSchemaName, zTabName, zColname);
98004
+ testcase( pX->zSpan==0 );
98005
+ }
98006
+ pX->bSpanIsTab = 1;
98007
+ }
9767798008
sqlite3DbFree(db, zToFree);
9767898009
}
9767998010
}
9768098011
if( !tableSeen ){
9768198012
if( zTName ){
@@ -98151,10 +98482,19 @@
9815198482
*/
9815298483
int addrTop;
9815398484
int addrEof;
9815498485
pItem->regReturn = ++pParse->nMem;
9815598486
addrEof = ++pParse->nMem;
98487
+ /* Before coding the OP_Goto to jump to the start of the main routine,
98488
+ ** ensure that the jump to the verify-schema routine has already
98489
+ ** been coded. Otherwise, the verify-schema would likely be coded as
98490
+ ** part of the co-routine. If the main routine then accessed the
98491
+ ** database before invoking the co-routine for the first time (for
98492
+ ** example to initialize a LIMIT register from a sub-select), it would
98493
+ ** be doing so without having verified the schema version and obtained
98494
+ ** the required db locks. See ticket d6b36be38. */
98495
+ sqlite3CodeVerifySchema(pParse, -1);
9815698496
sqlite3VdbeAddOp0(v, OP_Goto);
9815798497
addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
9815898498
sqlite3VdbeChangeP5(v, 1);
9815998499
VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
9816098500
pItem->addrFillSub = addrTop;
@@ -98720,15 +99060,21 @@
9872099060
** index or indices to use) should place a different priority on
9872199061
** satisfying the 'ORDER BY' clause than it does in other cases.
9872299062
** Refer to code and comments in where.c for details.
9872399063
*/
9872499064
ExprList *pMinMax = 0;
98725
- u8 flag = minMaxQuery(p);
99065
+ u8 flag = WHERE_ORDERBY_NORMAL;
99066
+
99067
+ assert( p->pGroupBy==0 );
99068
+ assert( flag==0 );
99069
+ if( p->pHaving==0 ){
99070
+ flag = minMaxQuery(&sAggInfo, &pMinMax);
99071
+ }
99072
+ assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
99073
+
9872699074
if( flag ){
98727
- assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
98728
- assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
98729
- pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
99075
+ pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
9873099076
pDel = pMinMax;
9873199077
if( pMinMax && !db->mallocFailed ){
9873299078
pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
9873399079
pMinMax->a[0].pExpr->op = TK_COLUMN;
9873499080
}
@@ -99827,10 +100173,19 @@
99827100173
**
99828100174
** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
99829100175
** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
99830100176
*/
99831100177
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
100178
+
100179
+ /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
100180
+ ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
100181
+ ** that it is not safe to refactor constants (this happens after the
100182
+ ** start of the first loop in the SQL statement is coded - at that
100183
+ ** point code may be conditionally executed, so it is no longer safe to
100184
+ ** initialize constant register values). */
100185
+ assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
100186
+ pParse->cookieGoto = 0;
99832100187
99833100188
switch( pStep->op ){
99834100189
case TK_UPDATE: {
99835100190
sqlite3Update(pParse,
99836100191
targetSrcList(pParse, pStep),
@@ -102603,11 +102958,11 @@
102603102958
#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
102604102959
#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
102605102960
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
102606102961
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
102607102962
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
102608
-#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
102963
+#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
102609102964
#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
102610102965
#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
102611102966
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
102612102967
#define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
102613102968
#define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
@@ -102753,11 +103108,11 @@
102753103108
sqlite3DbFree(db, pOld);
102754103109
}
102755103110
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
102756103111
}
102757103112
pTerm = &pWC->a[idx = pWC->nTerm++];
102758
- pTerm->pExpr = p;
103113
+ pTerm->pExpr = sqlite3ExprSkipCollate(p);
102759103114
pTerm->wtFlags = wtFlags;
102760103115
pTerm->pWC = pWC;
102761103116
pTerm->iParent = -1;
102762103117
return idx;
102763103118
}
@@ -102913,27 +103268,36 @@
102913103268
102914103269
/*
102915103270
** Commute a comparison operator. Expressions of the form "X op Y"
102916103271
** are converted into "Y op X".
102917103272
**
102918
-** If a collation sequence is associated with either the left or right
103273
+** If left/right precendence rules come into play when determining the
103274
+** collating
102919103275
** side of the comparison, it remains associated with the same side after
102920103276
** the commutation. So "Y collate NOCASE op X" becomes
102921
-** "X collate NOCASE op Y". This is because any collation sequence on
103277
+** "X op Y". This is because any collation sequence on
102922103278
** the left hand side of a comparison overrides any collation sequence
102923
-** attached to the right. For the same reason the EP_ExpCollate flag
103279
+** attached to the right. For the same reason the EP_Collate flag
102924103280
** is not commuted.
102925103281
*/
102926103282
static void exprCommute(Parse *pParse, Expr *pExpr){
102927
- u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
102928
- u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
103283
+ u16 expRight = (pExpr->pRight->flags & EP_Collate);
103284
+ u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
102929103285
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
102930
- pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
102931
- pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
102932
- SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
102933
- pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
102934
- pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
103286
+ if( expRight==expLeft ){
103287
+ /* Either X and Y both have COLLATE operator or neither do */
103288
+ if( expRight ){
103289
+ /* Both X and Y have COLLATE operators. Make sure X is always
103290
+ ** used by clearing the EP_Collate flag from Y. */
103291
+ pExpr->pRight->flags &= ~EP_Collate;
103292
+ }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
103293
+ /* Neither X nor Y have COLLATE operators, but X has a non-default
103294
+ ** collating sequence. So add the EP_Collate marker on X to cause
103295
+ ** it to be searched first. */
103296
+ pExpr->pLeft->flags |= EP_Collate;
103297
+ }
103298
+ }
102935103299
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
102936103300
if( pExpr->op>=TK_GT ){
102937103301
assert( TK_LT==TK_GT+2 );
102938103302
assert( TK_GE==TK_LE+2 );
102939103303
assert( TK_GT>TK_EQ );
@@ -103006,16 +103370,16 @@
103006103370
** it to be useful for optimising expression pX. Store this
103007103371
** value in variable pColl.
103008103372
*/
103009103373
assert(pX->pLeft);
103010103374
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
103011
- assert(pColl || pParse->nErr);
103375
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
103012103376
103013103377
for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
103014103378
if( NEVER(j>=pIdx->nColumn) ) return 0;
103015103379
}
103016
- if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103380
+ if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103017103381
}
103018103382
return pTerm;
103019103383
}
103020103384
}
103021103385
}
@@ -103530,10 +103894,11 @@
103530103894
return;
103531103895
}
103532103896
pTerm = &pWC->a[idxTerm];
103533103897
pMaskSet = pWC->pMaskSet;
103534103898
pExpr = pTerm->pExpr;
103899
+ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
103535103900
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
103536103901
op = pExpr->op;
103537103902
if( op==TK_IN ){
103538103903
assert( pExpr->pRight==0 );
103539103904
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
@@ -103556,12 +103921,12 @@
103556103921
pTerm->prereqAll = prereqAll;
103557103922
pTerm->leftCursor = -1;
103558103923
pTerm->iParent = -1;
103559103924
pTerm->eOperator = 0;
103560103925
if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
103561
- Expr *pLeft = pExpr->pLeft;
103562
- Expr *pRight = pExpr->pRight;
103926
+ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
103927
+ Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
103563103928
if( pLeft->op==TK_COLUMN ){
103564103929
pTerm->leftCursor = pLeft->iTable;
103565103930
pTerm->u.leftColumn = pLeft->iColumn;
103566103931
pTerm->eOperator = operatorMask(op);
103567103932
}
@@ -103585,11 +103950,11 @@
103585103950
}else{
103586103951
pDup = pExpr;
103587103952
pNew = pTerm;
103588103953
}
103589103954
exprCommute(pParse, pDup);
103590
- pLeft = pDup->pLeft;
103955
+ pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
103591103956
pNew->leftCursor = pLeft->iTable;
103592103957
pNew->u.leftColumn = pLeft->iColumn;
103593103958
testcase( (prereqLeft | extraRight) != prereqLeft );
103594103959
pNew->prereqRight = prereqLeft | extraRight;
103595103960
pNew->prereqAll = prereqAll;
@@ -103664,11 +104029,11 @@
103664104029
Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
103665104030
Expr *pNewExpr1;
103666104031
Expr *pNewExpr2;
103667104032
int idxNew1;
103668104033
int idxNew2;
103669
- CollSeq *pColl; /* Collating sequence to use */
104034
+ Token sCollSeqName; /* Name of collating sequence */
103670104035
103671104036
pLeft = pExpr->x.pList->a[1].pExpr;
103672104037
pStr2 = sqlite3ExprDup(db, pStr1, 0);
103673104038
if( !db->mallocFailed ){
103674104039
u8 c, *pC; /* Last character before the first wildcard */
@@ -103686,20 +104051,23 @@
103686104051
103687104052
c = sqlite3UpperToLower[c];
103688104053
}
103689104054
*pC = c + 1;
103690104055
}
103691
- pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
104056
+ sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
104057
+ sCollSeqName.n = 6;
104058
+ pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
103692104059
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
103693
- sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
103694
- pStr1, 0);
104060
+ sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
104061
+ pStr1, 0);
103695104062
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
103696104063
testcase( idxNew1==0 );
103697104064
exprAnalyze(pSrc, pWC, idxNew1);
104065
+ pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
103698104066
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
103699
- sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
103700
- pStr2, 0);
104067
+ sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
104068
+ pStr2, 0);
103701104069
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
103702104070
testcase( idxNew2==0 );
103703104071
exprAnalyze(pSrc, pWC, idxNew2);
103704104072
pTerm = &pWC->a[idxTerm];
103705104073
if( isComplete ){
@@ -103813,16 +104181,16 @@
103813104181
){
103814104182
int i;
103815104183
const char *zColl = pIdx->azColl[iCol];
103816104184
103817104185
for(i=0; i<pList->nExpr; i++){
103818
- Expr *p = pList->a[i].pExpr;
104186
+ Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
103819104187
if( p->op==TK_COLUMN
103820104188
&& p->iColumn==pIdx->aiColumn[iCol]
103821104189
&& p->iTable==iBase
103822104190
){
103823
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
104191
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
103824104192
if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
103825104193
return i;
103826104194
}
103827104195
}
103828104196
}
@@ -103865,11 +104233,11 @@
103865104233
** matching "col=X" expression and the column is on the same table as pIdx,
103866104234
** set the corresponding bit in variable mask.
103867104235
*/
103868104236
for(i=0; i<pDistinct->nExpr; i++){
103869104237
WhereTerm *pTerm;
103870
- Expr *p = pDistinct->a[i].pExpr;
104238
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
103871104239
if( p->op!=TK_COLUMN ) return 0;
103872104240
pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
103873104241
if( pTerm ){
103874104242
Expr *pX = pTerm->pExpr;
103875104243
CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
@@ -103917,11 +104285,11 @@
103917104285
/* If any of the expressions is an IPK column on table iBase, then return
103918104286
** true. Note: The (p->iTable==iBase) part of this test may be false if the
103919104287
** current SELECT is a correlated sub-query.
103920104288
*/
103921104289
for(i=0; i<pDistinct->nExpr; i++){
103922
- Expr *p = pDistinct->a[i].pExpr;
104290
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
103923104291
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
103924104292
}
103925104293
103926104294
/* Loop through all indices on the table, checking each to see if it makes
103927104295
** the DISTINCT qualifier redundant. It does so if:
@@ -104394,11 +104762,11 @@
104394104762
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104395104763
if( pTerm->leftCursor != pSrc->iCursor ) continue;
104396104764
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104397104765
testcase( pTerm->eOperator==WO_IN );
104398104766
testcase( pTerm->eOperator==WO_ISNULL );
104399
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
104767
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
104400104768
if( pTerm->wtFlags & TERM_VNULL ) continue;
104401104769
nTerm++;
104402104770
}
104403104771
104404104772
/* If the ORDER BY clause contains only columns in the current
@@ -104442,29 +104810,32 @@
104442104810
*(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
104443104811
*(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
104444104812
pUsage;
104445104813
104446104814
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104815
+ u8 op;
104447104816
if( pTerm->leftCursor != pSrc->iCursor ) continue;
104448104817
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104449104818
testcase( pTerm->eOperator==WO_IN );
104450104819
testcase( pTerm->eOperator==WO_ISNULL );
104451
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
104820
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
104452104821
if( pTerm->wtFlags & TERM_VNULL ) continue;
104453104822
pIdxCons[j].iColumn = pTerm->u.leftColumn;
104454104823
pIdxCons[j].iTermOffset = i;
104455
- pIdxCons[j].op = (u8)pTerm->eOperator;
104824
+ op = (u8)pTerm->eOperator;
104825
+ if( op==WO_IN ) op = WO_EQ;
104826
+ pIdxCons[j].op = op;
104456104827
/* The direct assignment in the previous line is possible only because
104457104828
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104458104829
** following asserts verify this fact. */
104459104830
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
104460104831
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
104461104832
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
104462104833
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
104463104834
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
104464104835
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
104465
- assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
104836
+ assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
104466104837
j++;
104467104838
}
104468104839
for(i=0; i<nOrderBy; i++){
104469104840
Expr *pExpr = pOrderBy->a[i].pExpr;
104470104841
pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -104546,10 +104917,11 @@
104546104917
struct sqlite3_index_constraint *pIdxCons;
104547104918
struct sqlite3_index_constraint_usage *pUsage;
104548104919
WhereTerm *pTerm;
104549104920
int i, j;
104550104921
int nOrderBy;
104922
+ int bAllowIN; /* Allow IN optimizations */
104551104923
double rCost;
104552104924
104553104925
/* Make sure wsFlags is initialized to some sane value. Otherwise, if the
104554104926
** malloc in allocateIndexInfo() fails and this function returns leaving
104555104927
** wsFlags in an uninitialized state, the caller may behave unpredictably.
@@ -104580,63 +104952,91 @@
104580104952
** sqlite3ViewGetColumnNames() would have picked up the error.
104581104953
*/
104582104954
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
104583104955
assert( sqlite3GetVTable(pParse->db, pTab) );
104584104956
104585
- /* Set the aConstraint[].usable fields and initialize all
104586
- ** output variables to zero.
104587
- **
104588
- ** aConstraint[].usable is true for constraints where the right-hand
104589
- ** side contains only references to tables to the left of the current
104590
- ** table. In other words, if the constraint is of the form:
104591
- **
104592
- ** column = expr
104593
- **
104594
- ** and we are evaluating a join, then the constraint on column is
104595
- ** only valid if all tables referenced in expr occur to the left
104596
- ** of the table containing column.
104597
- **
104598
- ** The aConstraints[] array contains entries for all constraints
104599
- ** on the current table. That way we only have to compute it once
104600
- ** even though we might try to pick the best index multiple times.
104601
- ** For each attempt at picking an index, the order of tables in the
104602
- ** join might be different so we have to recompute the usable flag
104603
- ** each time.
104604
- */
104605
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104606
- pUsage = pIdxInfo->aConstraintUsage;
104607
- for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104608
- j = pIdxCons->iTermOffset;
104609
- pTerm = &pWC->a[j];
104610
- pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
104611
- }
104612
- memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
104613
- if( pIdxInfo->needToFreeIdxStr ){
104614
- sqlite3_free(pIdxInfo->idxStr);
104615
- }
104616
- pIdxInfo->idxStr = 0;
104617
- pIdxInfo->idxNum = 0;
104618
- pIdxInfo->needToFreeIdxStr = 0;
104619
- pIdxInfo->orderByConsumed = 0;
104620
- /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
104621
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
104622
- nOrderBy = pIdxInfo->nOrderBy;
104623
- if( !p->pOrderBy ){
104624
- pIdxInfo->nOrderBy = 0;
104625
- }
104626
-
104627
- if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
104628
- return;
104629
- }
104630
-
104631
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104632
- for(i=0; i<pIdxInfo->nConstraint; i++){
104633
- if( pUsage[i].argvIndex>0 ){
104634
- p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
104635
- }
104636
- }
104637
-
104957
+ /* Try once or twice. On the first attempt, allow IN optimizations.
104958
+ ** If an IN optimization is accepted by the virtual table xBestIndex
104959
+ ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
104960
+ ** the query will not work because it might allow duplicate rows in
104961
+ ** output. In that case, run the xBestIndex method a second time
104962
+ ** without the IN constraints. Usually this loop only runs once.
104963
+ ** The loop will exit using a "break" statement.
104964
+ */
104965
+ for(bAllowIN=1; 1; bAllowIN--){
104966
+ assert( bAllowIN==0 || bAllowIN==1 );
104967
+
104968
+ /* Set the aConstraint[].usable fields and initialize all
104969
+ ** output variables to zero.
104970
+ **
104971
+ ** aConstraint[].usable is true for constraints where the right-hand
104972
+ ** side contains only references to tables to the left of the current
104973
+ ** table. In other words, if the constraint is of the form:
104974
+ **
104975
+ ** column = expr
104976
+ **
104977
+ ** and we are evaluating a join, then the constraint on column is
104978
+ ** only valid if all tables referenced in expr occur to the left
104979
+ ** of the table containing column.
104980
+ **
104981
+ ** The aConstraints[] array contains entries for all constraints
104982
+ ** on the current table. That way we only have to compute it once
104983
+ ** even though we might try to pick the best index multiple times.
104984
+ ** For each attempt at picking an index, the order of tables in the
104985
+ ** join might be different so we have to recompute the usable flag
104986
+ ** each time.
104987
+ */
104988
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104989
+ pUsage = pIdxInfo->aConstraintUsage;
104990
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104991
+ j = pIdxCons->iTermOffset;
104992
+ pTerm = &pWC->a[j];
104993
+ if( (pTerm->prereqRight&p->notReady)==0
104994
+ && (bAllowIN || pTerm->eOperator!=WO_IN)
104995
+ ){
104996
+ pIdxCons->usable = 1;
104997
+ }else{
104998
+ pIdxCons->usable = 0;
104999
+ }
105000
+ }
105001
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
105002
+ if( pIdxInfo->needToFreeIdxStr ){
105003
+ sqlite3_free(pIdxInfo->idxStr);
105004
+ }
105005
+ pIdxInfo->idxStr = 0;
105006
+ pIdxInfo->idxNum = 0;
105007
+ pIdxInfo->needToFreeIdxStr = 0;
105008
+ pIdxInfo->orderByConsumed = 0;
105009
+ /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
105010
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
105011
+ nOrderBy = pIdxInfo->nOrderBy;
105012
+ if( !p->pOrderBy ){
105013
+ pIdxInfo->nOrderBy = 0;
105014
+ }
105015
+
105016
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
105017
+ return;
105018
+ }
105019
+
105020
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
105021
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105022
+ if( pUsage[i].argvIndex>0 ){
105023
+ j = pIdxCons->iTermOffset;
105024
+ pTerm = &pWC->a[j];
105025
+ p->cost.used |= pTerm->prereqRight;
105026
+ if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
105027
+ /* Do not attempt to use an IN constraint if the virtual table
105028
+ ** says that the equivalent EQ constraint cannot be safely omitted.
105029
+ ** If we do attempt to use such a constraint, some rows might be
105030
+ ** repeated in the output. */
105031
+ break;
105032
+ }
105033
+ }
105034
+ }
105035
+ if( i>=pIdxInfo->nConstraint ) break;
105036
+ }
105037
+
104638105038
/* If there is an ORDER BY clause, and the selected virtual table index
104639105039
** does not satisfy it, increase the cost of the scan accordingly. This
104640105040
** matches the processing for non-virtual tables in bestBtreeIndex().
104641105041
*/
104642105042
rCost = pIdxInfo->estimatedCost;
@@ -105203,11 +105603,11 @@
105203105603
WhereTerm *pConstraint; /* A constraint in the WHERE clause */
105204105604
105205105605
/* If the next term of the ORDER BY clause refers to anything other than
105206105606
** a column in the "base" table, then this index will not be of any
105207105607
** further use in handling the ORDER BY. */
105208
- pOBExpr = pOBItem->pExpr;
105608
+ pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
105209105609
if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
105210105610
break;
105211105611
}
105212105612
105213105613
/* Find column number and collating sequence for the next entry
@@ -105229,11 +105629,11 @@
105229105629
/* Check to see if the column number and collating sequence of the
105230105630
** index match the column number and collating sequence of the ORDER BY
105231105631
** clause entry. Set isMatch to 1 if they both match. */
105232105632
if( pOBExpr->iColumn==iColumn ){
105233105633
if( zColl ){
105234
- pColl = sqlite3ExprCollSeq(pParse, pOBExpr);
105634
+ pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
105235105635
if( !pColl ) pColl = db->pDfltColl;
105236105636
isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
105237105637
}else{
105238105638
isMatch = 1;
105239105639
}
@@ -105370,10 +105770,15 @@
105370105770
int idxEqTermMask; /* Index mask of valid equality operators */
105371105771
Index sPk; /* A fake index object for the primary key */
105372105772
tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
105373105773
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
105374105774
int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
105775
+ int nPriorSat; /* ORDER BY terms satisfied by outer loops */
105776
+ int nOrderBy; /* Number of ORDER BY terms */
105777
+ char bSortInit; /* Initializer for bSort in inner loop */
105778
+ char bDistInit; /* Initializer for bDist in inner loop */
105779
+
105375105780
105376105781
/* Initialize the cost to a worst-case value */
105377105782
memset(&p->cost, 0, sizeof(p->cost));
105378105783
p->cost.rCost = SQLITE_BIG_DBL;
105379105784
@@ -105418,10 +105823,21 @@
105418105823
WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
105419105824
);
105420105825
eqTermMask = WO_EQ|WO_IN;
105421105826
pIdx = 0;
105422105827
}
105828
+
105829
+ nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
105830
+ if( p->i ){
105831
+ nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
105832
+ bSortInit = nPriorSat<nOrderBy;
105833
+ bDistInit = 0;
105834
+ }else{
105835
+ nPriorSat = 0;
105836
+ bSortInit = nOrderBy>0;
105837
+ bDistInit = p->pDistinct!=0;
105838
+ }
105423105839
105424105840
/* Loop over all indices looking for the best one to use
105425105841
*/
105426105842
for(; pProbe; pIdx=pProbe=pProbe->pNext){
105427105843
const tRowcnt * const aiRowEst = pProbe->aiRowEst;
@@ -105496,15 +105912,13 @@
105496105912
*/
105497105913
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
105498105914
int nInMul = 1; /* Number of distinct equalities to lookup */
105499105915
double rangeDiv = (double)1; /* Estimated reduction in search space */
105500105916
int nBound = 0; /* Number of range constraints seen */
105501
- int bSort; /* True if external sort required */
105502
- int bDist; /* True if index cannot help with DISTINCT */
105503
- int bLookup = 0; /* True if not a covering index */
105504
- int nPriorSat; /* ORDER BY terms satisfied by outer loops */
105505
- int nOrderBy; /* Number of ORDER BY terms */
105917
+ char bSort = bSortInit; /* True if external sort required */
105918
+ char bDist = bDistInit; /* True if index cannot help with DISTINCT */
105919
+ char bLookup = 0; /* True if not a covering index */
105506105920
WhereTerm *pTerm; /* A single term of the WHERE clause */
105507105921
#ifdef SQLITE_ENABLE_STAT3
105508105922
WhereTerm *pFirstTerm = 0; /* First term matching the index */
105509105923
#endif
105510105924
@@ -105511,20 +105925,11 @@
105511105925
WHERETRACE((
105512105926
" %s(%s):\n",
105513105927
pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
105514105928
));
105515105929
memset(&pc, 0, sizeof(pc));
105516
- nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
105517
- if( p->i ){
105518
- nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat;
105519
- bSort = nPriorSat<nOrderBy;
105520
- bDist = 0;
105521
- }else{
105522
- nPriorSat = pc.plan.nOBSat = 0;
105523
- bSort = nOrderBy>0;
105524
- bDist = p->pDistinct!=0;
105525
- }
105930
+ pc.plan.nOBSat = nPriorSat;
105526105931
105527105932
/* Determine the values of pc.plan.nEq and nInMul */
105528105933
for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
105529105934
int j = pProbe->aiColumn[pc.plan.nEq];
105530105935
pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
@@ -106396,32 +106801,40 @@
106396106801
if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
106397106802
/* Case 0: The table is a virtual-table. Use the VFilter and VNext
106398106803
** to access the data.
106399106804
*/
106400106805
int iReg; /* P3 Value for OP_VFilter */
106806
+ int addrNotFound;
106401106807
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
106402106808
int nConstraint = pVtabIdx->nConstraint;
106403106809
struct sqlite3_index_constraint_usage *aUsage =
106404106810
pVtabIdx->aConstraintUsage;
106405106811
const struct sqlite3_index_constraint *aConstraint =
106406106812
pVtabIdx->aConstraint;
106407106813
106408106814
sqlite3ExprCachePush(pParse);
106409106815
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
106816
+ addrNotFound = pLevel->addrBrk;
106410106817
for(j=1; j<=nConstraint; j++){
106411106818
for(k=0; k<nConstraint; k++){
106412106819
if( aUsage[k].argvIndex==j ){
106413
- int iTerm = aConstraint[k].iTermOffset;
106414
- sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
106820
+ WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset];
106821
+ int iTarget = iReg+j+1;
106822
+ if( pTerm->eOperator & WO_IN ){
106823
+ codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
106824
+ addrNotFound = pLevel->addrNxt;
106825
+ }else{
106826
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
106827
+ }
106415106828
break;
106416106829
}
106417106830
}
106418106831
if( k==nConstraint ) break;
106419106832
}
106420106833
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
106421106834
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
106422
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
106835
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
106423106836
pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
106424106837
pVtabIdx->needToFreeIdxStr = 0;
106425106838
for(j=0; j<nConstraint; j++){
106426106839
if( aUsage[j].omit ){
106427106840
int iTerm = aConstraint[j].iTermOffset;
@@ -108064,10 +108477,11 @@
108064108477
Expr* yy122;
108065108478
Select* yy159;
108066108479
IdList* yy180;
108067108480
struct {int value; int mask;} yy207;
108068108481
u8 yy258;
108482
+ u16 yy305;
108069108483
struct LikeOp yy318;
108070108484
TriggerStep* yy327;
108071108485
ExprSpan yy342;
108072108486
SrcList* yy347;
108073108487
int yy392;
@@ -110014,22 +110428,19 @@
110014110428
case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
110015110429
case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
110016110430
case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
110017110431
case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
110018110432
case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
110019
- case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
110020
- case 121: /* distinct ::= */ yytestcase(yyruleno==121);
110021110433
case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
110022110434
case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
110023110435
{yygotominor.yy392 = 0;}
110024110436
break;
110025110437
case 29: /* ifnotexists ::= IF NOT EXISTS */
110026110438
case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
110027110439
case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
110028110440
case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
110029110441
case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
110030
- case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
110031110442
case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
110032110443
case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
110033110444
{yygotominor.yy392 = 1;}
110034110445
break;
110035110446
case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
@@ -110265,12 +110676,19 @@
110265110676
case 116: /* multiselect_op ::= UNION ALL */
110266110677
{yygotominor.yy392 = TK_ALL;}
110267110678
break;
110268110679
case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110269110680
{
110270
- 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);
110681
+ 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.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
110271110682
}
110683
+ break;
110684
+ case 119: /* distinct ::= DISTINCT */
110685
+{yygotominor.yy305 = SF_Distinct;}
110686
+ break;
110687
+ case 120: /* distinct ::= ALL */
110688
+ case 121: /* distinct ::= */ yytestcase(yyruleno==121);
110689
+{yygotominor.yy305 = 0;}
110272110690
break;
110273110691
case 122: /* sclp ::= selcollist COMMA */
110274110692
case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
110275110693
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
110276110694
break;
@@ -110336,14 +110754,24 @@
110336110754
break;
110337110755
case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110338110756
{
110339110757
if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110340110758
yygotominor.yy347 = yymsp[-4].minor.yy347;
110759
+ }else if( yymsp[-4].minor.yy347->nSrc==1 ){
110760
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110761
+ if( yygotominor.yy347 ){
110762
+ struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
110763
+ struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
110764
+ pNew->zName = pOld->zName;
110765
+ pNew->zDatabase = pOld->zDatabase;
110766
+ pOld->zName = pOld->zDatabase = 0;
110767
+ }
110768
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
110341110769
}else{
110342110770
Select *pSubquery;
110343110771
sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
110344
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
110772
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
110345110773
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110346110774
}
110347110775
}
110348110776
break;
110349110777
case 137: /* dbnm ::= */
@@ -110554,11 +110982,11 @@
110554110982
spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110555110983
}
110556110984
break;
110557110985
case 194: /* expr ::= expr COLLATE ids */
110558110986
{
110559
- yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110987
+ yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110560110988
yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110561110989
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110562110990
}
110563110991
break;
110564110992
case 195: /* expr ::= CAST LP expr AS typetoken RP */
@@ -110572,11 +111000,11 @@
110572111000
if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
110573111001
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
110574111002
}
110575111003
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
110576111004
spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
110577
- if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
111005
+ if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
110578111006
yygotominor.yy342.pExpr->flags |= EP_Distinct;
110579111007
}
110580111008
}
110581111009
break;
110582111010
case 197: /* expr ::= ID LP STAR RP */
@@ -110813,28 +111241,20 @@
110813111241
case 244: /* uniqueflag ::= */
110814111242
{yygotominor.yy392 = OE_None;}
110815111243
break;
110816111244
case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
110817111245
{
110818
- Expr *p = 0;
110819
- if( yymsp[-1].minor.yy0.n>0 ){
110820
- p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
110821
- sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
110822
- }
111246
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
110823111247
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
110824111248
sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
110825111249
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110826111250
if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110827111251
}
110828111252
break;
110829111253
case 248: /* idxlist ::= nm collate sortorder */
110830111254
{
110831
- Expr *p = 0;
110832
- if( yymsp[-1].minor.yy0.n>0 ){
110833
- p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
110834
- sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
110835
- }
111255
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
110836111256
yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
110837111257
sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110838111258
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110839111259
if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110840111260
}
110841111261
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.15. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -671,13 +671,13 @@
671 **
672 ** See also: [sqlite3_libversion()],
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.15"
677 #define SQLITE_VERSION_NUMBER 3007015
678 #define SQLITE_SOURCE_ID "2012-12-05 14:31:13 9f6c68856b694373b7ffb124abd996e519ba5921"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -1421,11 +1421,10 @@
1421 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1422 ** that the VFS encountered an error while handling the [PRAGMA] and the
1423 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1424 ** file control occurs at the beginning of pragma statement analysis and so
1425 ** it is able to override built-in [PRAGMA] statements.
1426 ** </ul>
1427 **
1428 ** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
1429 ** ^This file-control may be invoked by SQLite on the database file handle
1430 ** shortly after it is opened in order to provide a custom VFS with access
1431 ** to the connections busy-handler callback. The argument is of type (void **)
@@ -1433,10 +1432,20 @@
1433 ** to a function of type (int (*)(void *)). In order to invoke the connections
1434 ** busy-handler, this function should be invoked with the second (void *) in
1435 ** the array as the only argument. If it returns non-zero, then the operation
1436 ** should be retried. If it returns zero, the custom VFS should abandon the
1437 ** current operation.
 
 
 
 
 
 
 
 
 
 
1438 */
1439 #define SQLITE_FCNTL_LOCKSTATE 1
1440 #define SQLITE_GET_LOCKPROXYFILE 2
1441 #define SQLITE_SET_LOCKPROXYFILE 3
1442 #define SQLITE_LAST_ERRNO 4
@@ -1449,10 +1458,11 @@
1449 #define SQLITE_FCNTL_OVERWRITE 11
1450 #define SQLITE_FCNTL_VFSNAME 12
1451 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
1452 #define SQLITE_FCNTL_PRAGMA 14
1453 #define SQLITE_FCNTL_BUSYHANDLER 15
 
1454
1455 /*
1456 ** CAPI3REF: Mutex Handle
1457 **
1458 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -2146,11 +2156,11 @@
2146 ** database connection is opened. By default, URI handling is globally
2147 ** disabled. The default value may be changed by compiling with the
2148 ** [SQLITE_USE_URI] symbol defined.
2149 **
2150 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
2151 ** <dd> This option taks a single integer argument which is interpreted as
2152 ** a boolean in order to enable or disable the use of covering indices for
2153 ** full table scans in the query optimizer. The default setting is determined
2154 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
2155 ** if that compile-time option is omitted.
2156 ** The ability to disable the use of covering indices for full table scans
@@ -10209,23 +10219,11 @@
10209 /*
10210 ** A "Collating Sequence" is defined by an instance of the following
10211 ** structure. Conceptually, a collating sequence consists of a name and
10212 ** a comparison routine that defines the order of that sequence.
10213 **
10214 ** There may two separate implementations of the collation function, one
10215 ** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
10216 ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
10217 ** native byte order. When a collation sequence is invoked, SQLite selects
10218 ** the version that will require the least expensive encoding
10219 ** translations, if any.
10220 **
10221 ** The CollSeq.pUser member variable is an extra parameter that passed in
10222 ** as the first argument to the UTF-8 comparison function, xCmp.
10223 ** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
10224 ** xCmp16.
10225 **
10226 ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
10227 ** collating sequence is undefined. Indices built on an undefined
10228 ** collating sequence may not be read or written.
10229 */
10230 struct CollSeq {
10231 char *zName; /* Name of the collating sequence, UTF-8 encoded */
@@ -10555,24 +10553,24 @@
10555 ** and the value of Index.onError indicate the which conflict resolution
10556 ** algorithm to employ whenever an attempt is made to insert a non-unique
10557 ** element.
10558 */
10559 struct Index {
10560 char *zName; /* Name of this index */
10561 int *aiColumn; /* Which columns are used by this index. 1st is 0 */
10562 tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
10563 Table *pTable; /* The SQL table being indexed */
10564 char *zColAff; /* String defining the affinity of each column */
10565 Index *pNext; /* The next index associated with the same table */
10566 Schema *pSchema; /* Schema containing this index */
10567 u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
10568 char **azColl; /* Array of collation sequence names for index */
10569 int nColumn; /* Number of columns in the table used by this index */
10570 int tnum; /* Page containing root of this index in database file */
10571 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10572 u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
10573 u8 bUnordered; /* Use this index for == or IN queries only */
10574 #ifdef SQLITE_ENABLE_STAT3
10575 int nSample; /* Number of elements in aSample[] */
10576 tRowcnt avgEq; /* Average nEq value for key values not in aSample */
10577 IndexSample *aSample; /* Samples of the left-most key */
10578 #endif
@@ -10749,11 +10747,10 @@
10749 Expr *pRight; /* Right subnode */
10750 union {
10751 ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
10752 Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
10753 } x;
10754 CollSeq *pColl; /* The collation type of the column or 0 */
10755
10756 /* If the EP_Reduced flag is set in the Expr.flags mask, then no
10757 ** space is allocated for the fields below this point. An attempt to
10758 ** access them will result in a segfault or malfunction.
10759 *********************************************************************/
@@ -10785,11 +10782,11 @@
10785 #define EP_Error 0x0008 /* Expression contains one or more errors */
10786 #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
10787 #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
10788 #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
10789 #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
10790 #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
10791 #define EP_FixedDest 0x0200 /* Result needed in a specific register */
10792 #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
10793 #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
10794 #define EP_Hint 0x1000 /* Not used */
10795 #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
@@ -10843,22 +10840,31 @@
10843 ** name. An expr/name combination can be used in several ways, such
10844 ** as the list of "expr AS ID" fields following a "SELECT" or in the
10845 ** list of "ID = expr" items in an UPDATE. A list of expressions can
10846 ** also be used as the argument to a function, in which case the a.zName
10847 ** field is not used.
 
 
 
 
 
 
 
 
10848 */
10849 struct ExprList {
10850 int nExpr; /* Number of expressions on the list */
10851 int iECursor; /* VDBE Cursor associated with this ExprList */
10852 struct ExprList_item { /* For each expression in the list */
10853 Expr *pExpr; /* The list of expressions */
10854 char *zName; /* Token associated with this expression */
10855 char *zSpan; /* Original text of the expression */
10856 u8 sortOrder; /* 1 for DESC or 0 for ASC */
10857 u8 done; /* A flag to indicate when processing is finished */
10858 u16 iOrderByCol; /* For ORDER BY, column number in result set */
10859 u16 iAlias; /* Index into Parse.aAlias[] for zName */
 
10860 } *a; /* Alloc a power of two greater or equal to nExpr */
10861 };
10862
10863 /*
10864 ** An instance of this structure is used by the parser to record both
@@ -11174,10 +11180,11 @@
11174 #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
11175 #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
11176 #define SF_UseSorter 0x0040 /* Sort using a sorter */
11177 #define SF_Values 0x0080 /* Synthesized from VALUES clause */
11178 #define SF_Materialize 0x0100 /* Force materialization of views */
 
11179
11180
11181 /*
11182 ** The results of a select can be distributed in several ways. The
11183 ** "SRT" prefix means "SELECT Result Type".
@@ -11402,10 +11409,11 @@
11402 #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
11403 #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
11404 #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
11405 #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
11406 #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
 
11407
11408 /*
11409 * Each trigger present in the database schema is stored as an instance of
11410 * struct Trigger.
11411 *
@@ -11885,11 +11893,11 @@
11885 SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
11886 Token*, int, int);
11887 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
11888 SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
11889 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
11890 Expr*,ExprList*,int,Expr*,Expr*);
11891 SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
11892 SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
11893 SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
11894 SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
11895 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -12093,12 +12101,13 @@
12093 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
12094 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
12095 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
12096 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
12097 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
12098 SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
12099 SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
 
12100 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
12101 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
12102 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
12103 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
12104 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
@@ -12141,10 +12150,11 @@
12141 SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
12142 SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
12143 SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
12144 SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
12145 SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
 
12146 SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
12147 SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
12148 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12149 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12150 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -12279,12 +12289,14 @@
12279 #define sqlite3FkOldmask(a,b) 0
12280 #define sqlite3FkRequired(a,b,c,d) 0
12281 #endif
12282 #ifndef SQLITE_OMIT_FOREIGN_KEY
12283 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
 
12284 #else
12285 #define sqlite3FkDelete(a,b)
 
12286 #endif
12287
12288
12289 /*
12290 ** Available fault injectors. Should be numbered beginning with 0.
@@ -23287,15 +23299,11 @@
23287 { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
23288 #endif
23289 #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
23290 aSyscall[13].pCurrent)
23291
23292 #if SQLITE_ENABLE_LOCKING_STYLE
23293 { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
23294 #else
23295 { "fchmod", (sqlite3_syscall_ptr)0, 0 },
23296 #endif
23297 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
23298
23299 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
23300 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
23301 #else
@@ -23316,13 +23324,10 @@
23316 #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
23317
23318 { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
23319 #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
23320
23321 { "umask", (sqlite3_syscall_ptr)umask, 0 },
23322 #define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent)
23323
23324 }; /* End of the overrideable system calls */
23325
23326 /*
23327 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
23328 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -23423,31 +23428,29 @@
23423 ** process that is able to write to the database will also be able to
23424 ** recover the hot journals.
23425 */
23426 static int robust_open(const char *z, int f, mode_t m){
23427 int fd;
23428 mode_t m2;
23429 mode_t origM = 0;
23430 if( m==0 ){
23431 m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
23432 }else{
23433 m2 = m;
23434 origM = osUmask(0);
23435 }
23436 do{
23437 #if defined(O_CLOEXEC)
23438 fd = osOpen(z,f|O_CLOEXEC,m2);
23439 #else
23440 fd = osOpen(z,f,m2);
23441 #endif
23442 }while( fd<0 && errno==EINTR );
23443 if( m ){
23444 osUmask(origM);
23445 }
 
 
 
 
23446 #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
23447 if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
23448 #endif
 
23449 return fd;
23450 }
23451
23452 /*
23453 ** Helper functions to obtain and relinquish the global mutex. The
@@ -26456,10 +26459,13 @@
26456 }else{
26457 pFile->ctrlFlags |= mask;
26458 }
26459 }
26460
 
 
 
26461 /*
26462 ** Information and control of an open file handle.
26463 */
26464 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
26465 unixFile *pFile = (unixFile*)id;
@@ -26492,10 +26498,18 @@
26492 return SQLITE_OK;
26493 }
26494 case SQLITE_FCNTL_VFSNAME: {
26495 *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
26496 return SQLITE_OK;
 
 
 
 
 
 
 
 
26497 }
26498 #ifdef SQLITE_DEBUG
26499 /* The pager calls this method to signal that it has done
26500 ** a rollback and that the database is therefore unchanged and
26501 ** it hence it is OK for the transaction change counter to be
@@ -29858,11 +29872,11 @@
29858 };
29859 unsigned int i; /* Loop counter */
29860
29861 /* Double-check that the aSyscall[] array has been constructed
29862 ** correctly. See ticket [bb3a86e890c8e96ab] */
29863 assert( ArraySize(aSyscall)==22 );
29864
29865 /* Register all VFSes defined in the aVfs[] array */
29866 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
29867 sqlite3_vfs_register(&aVfs[i], i==0);
29868 }
@@ -32782,10 +32796,13 @@
32782 }else{
32783 pFile->ctrlFlags |= mask;
32784 }
32785 }
32786
 
 
 
32787 /*
32788 ** Control and query of the open file handle.
32789 */
32790 static int winFileControl(sqlite3_file *id, int op, void *pArg){
32791 winFile *pFile = (winFile*)id;
@@ -32841,10 +32858,18 @@
32841 win32IoerrRetryDelay = a[1];
32842 }else{
32843 a[1] = win32IoerrRetryDelay;
32844 }
32845 return SQLITE_OK;
 
 
 
 
 
 
 
 
32846 }
32847 }
32848 return SQLITE_NOTFOUND;
32849 }
32850
@@ -56313,11 +56338,11 @@
56313 sqlite3BtreeLeave(p);
56314 return 0;
56315 }
56316 i = PENDING_BYTE_PAGE(pBt);
56317 if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
56318 sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
56319 sCheck.errMsg.useMalloc = 2;
56320
56321 /* Check the integrity of the freelist
56322 */
56323 checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
@@ -56848,11 +56873,16 @@
56848 /*
56849 ** Parameter zSrcData points to a buffer containing the data for
56850 ** page iSrcPg from the source database. Copy this data into the
56851 ** destination database.
56852 */
56853 static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
 
 
 
 
 
56854 Pager * const pDestPager = sqlite3BtreePager(p->pDest);
56855 const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
56856 int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
56857 const int nCopy = MIN(nSrcPgsz, nDestPgsz);
56858 const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
@@ -56921,10 +56951,13 @@
56921 ** cached parse of the page). MemPage.isInit is marked
56922 ** "MUST BE FIRST" for this purpose.
56923 */
56924 memcpy(zOut, zIn, nCopy);
56925 ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
 
 
 
56926 }
56927 sqlite3PagerUnref(pDestPg);
56928 }
56929
56930 return rc;
@@ -57027,11 +57060,11 @@
57027 const Pgno iSrcPg = p->iNext; /* Source page number */
57028 if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
57029 DbPage *pSrcPg; /* Source page object */
57030 rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
57031 if( rc==SQLITE_OK ){
57032 rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
57033 sqlite3PagerUnref(pSrcPg);
57034 }
57035 }
57036 p->iNext++;
57037 }
@@ -57275,11 +57308,11 @@
57275 ** the new data into the backup.
57276 */
57277 int rc;
57278 assert( p->pDestDb );
57279 sqlite3_mutex_enter(p->pDestDb->mutex);
57280 rc = backupOnePage(p, iPage, aData);
57281 sqlite3_mutex_leave(p->pDestDb->mutex);
57282 assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
57283 if( rc!=SQLITE_OK ){
57284 p->rc = rc;
57285 }
@@ -59392,26 +59425,22 @@
59392 assert( pKeyInfo->aSortOrder!=0 );
59393 sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
59394 i = sqlite3Strlen30(zTemp);
59395 for(j=0; j<pKeyInfo->nField; j++){
59396 CollSeq *pColl = pKeyInfo->aColl[j];
59397 if( pColl ){
59398 int n = sqlite3Strlen30(pColl->zName);
59399 if( i+n>nTemp-6 ){
59400 memcpy(&zTemp[i],",...",4);
59401 break;
59402 }
59403 zTemp[i++] = ',';
59404 if( pKeyInfo->aSortOrder[j] ){
59405 zTemp[i++] = '-';
59406 }
59407 memcpy(&zTemp[i], pColl->zName,n+1);
59408 i += n;
59409 }else if( i+4<nTemp-6 ){
59410 memcpy(&zTemp[i],",nil",4);
59411 i += 4;
59412 }
59413 }
59414 zTemp[i++] = ')';
59415 zTemp[i] = 0;
59416 assert( i<nTemp );
59417 break;
@@ -63797,11 +63826,13 @@
63797 #ifdef SQLITE_DEBUG
63798 /*
63799 ** Print the value of a register for tracing purposes:
63800 */
63801 static void memTracePrint(FILE *out, Mem *p){
63802 if( p->flags & MEM_Null ){
 
 
63803 fprintf(out, " NULL");
63804 }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
63805 fprintf(out, " si:%lld", p->u.i);
63806 }else if( p->flags & MEM_Int ){
63807 fprintf(out, " i:%lld", p->u.i);
@@ -64070,10 +64101,11 @@
64070 } af;
64071 struct OP_Concat_stack_vars {
64072 i64 nByte;
64073 } ag;
64074 struct OP_Remainder_stack_vars {
 
64075 int flags; /* Combined MEM_* flags from both inputs */
64076 i64 iA; /* Integer value of left operand */
64077 i64 iB; /* Integer value of right operand */
64078 double rA; /* Real value of left operand */
64079 double rB; /* Real value of right operand */
@@ -64979,10 +65011,13 @@
64979 pOut = &aMem[pOp->p2];
64980 assert( pOut!=pIn1 );
64981 while( 1 ){
64982 sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
64983 Deephemeralize(pOut);
 
 
 
64984 REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
64985 if( (u.ae.n--)==0 ) break;
64986 pOut++;
64987 pIn1++;
64988 }
@@ -65172,10 +65207,11 @@
65172 case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
65173 case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
65174 case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
65175 case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
65176 #if 0 /* local variables moved into u.ah */
 
65177 int flags; /* Combined MEM_* flags from both inputs */
65178 i64 iA; /* Integer value of left operand */
65179 i64 iB; /* Integer value of right operand */
65180 double rA; /* Real value of left operand */
65181 double rB; /* Real value of right operand */
@@ -65189,10 +65225,11 @@
65189 u.ah.flags = pIn1->flags | pIn2->flags;
65190 if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
65191 if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
65192 u.ah.iA = pIn1->u.i;
65193 u.ah.iB = pIn2->u.i;
 
65194 switch( pOp->opcode ){
65195 case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65196 case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65197 case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65198 case OP_Divide: {
@@ -65209,10 +65246,11 @@
65209 }
65210 }
65211 pOut->u.i = u.ah.iB;
65212 MemSetTypeFlag(pOut, MEM_Int);
65213 }else{
 
65214 fp_math:
65215 u.ah.rA = sqlite3VdbeRealValue(pIn1);
65216 u.ah.rB = sqlite3VdbeRealValue(pIn2);
65217 switch( pOp->opcode ){
65218 case OP_Add: u.ah.rB += u.ah.rA; break;
@@ -65240,11 +65278,11 @@
65240 if( sqlite3IsNaN(u.ah.rB) ){
65241 goto arithmetic_result_is_null;
65242 }
65243 pOut->r = u.ah.rB;
65244 MemSetTypeFlag(pOut, MEM_Real);
65245 if( (u.ah.flags & MEM_Real)==0 ){
65246 sqlite3VdbeIntegerAffinity(pOut);
65247 }
65248 #endif
65249 }
65250 break;
@@ -65801,26 +65839,31 @@
65801 /* Opcode: Permutation * * * P4 *
65802 **
65803 ** Set the permutation used by the OP_Compare operator to be the array
65804 ** of integers in P4.
65805 **
65806 ** The permutation is only valid until the next OP_Permutation, OP_Compare,
65807 ** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur
65808 ** immediately prior to the OP_Compare.
65809 */
65810 case OP_Permutation: {
65811 assert( pOp->p4type==P4_INTARRAY );
65812 assert( pOp->p4.ai );
65813 aPermute = pOp->p4.ai;
65814 break;
65815 }
65816
65817 /* Opcode: Compare P1 P2 P3 P4 *
65818 **
65819 ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
65820 ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
65821 ** the comparison for use by the next OP_Jump instruct.
 
 
 
 
 
65822 **
65823 ** P4 is a KeyInfo structure that defines collating sequences and sort
65824 ** orders for the comparison. The permutation applies to registers
65825 ** only. The KeyInfo elements are used sequentially.
65826 **
@@ -65838,10 +65881,11 @@
65838 int idx;
65839 CollSeq *pColl; /* Collating sequence to use on this term */
65840 int bRev; /* True for DESCENDING sort order */
65841 #endif /* local variables moved into u.al */
65842
 
65843 u.al.n = pOp->p3;
65844 u.al.pKeyInfo = pOp->p4.pKeyInfo;
65845 assert( u.al.n>0 );
65846 assert( u.al.pKeyInfo!=0 );
65847 u.al.p1 = pOp->p1;
@@ -65983,12 +66027,10 @@
65983
65984 /* Opcode: Once P1 P2 * * *
65985 **
65986 ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
65987 ** set the flag and fall through to the next instruction.
65988 **
65989 ** See also: JumpOnce
65990 */
65991 case OP_Once: { /* jump */
65992 assert( pOp->p1<p->nOnceFlag );
65993 if( p->aOnceFlag[pOp->p1] ){
65994 pc = pOp->p2-1;
@@ -71860,10 +71902,18 @@
71860 p->pReal = pReal;
71861 if( p->iSize>0 ){
71862 assert(p->iSize<=p->nBuf);
71863 rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
71864 }
 
 
 
 
 
 
 
 
71865 }
71866 }
71867 return rc;
71868 }
71869
@@ -72523,10 +72573,19 @@
72523 ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
72524 **
72525 ** The result of random()%5 in the GROUP BY clause is probably different
72526 ** from the result in the result-set. We might fix this someday. Or
72527 ** then again, we might not...
 
 
 
 
 
 
 
 
 
72528 **
72529 ** The nSubquery parameter specifies how many levels of subquery the
72530 ** alias is removed from the original expression. The usually value is
72531 ** zero but it might be more if the alias is contained within a subquery
72532 ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
@@ -72547,45 +72606,40 @@
72547 assert( iCol>=0 && iCol<pEList->nExpr );
72548 pOrig = pEList->a[iCol].pExpr;
72549 assert( pOrig!=0 );
72550 assert( pOrig->flags & EP_Resolved );
72551 db = pParse->db;
 
 
72552 if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
72553 pDup = sqlite3ExprDup(db, pOrig, 0);
72554 incrAggFunctionDepth(pDup, nSubquery);
72555 pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
72556 if( pDup==0 ) return;
72557 if( pEList->a[iCol].iAlias==0 ){
72558 pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
72559 }
72560 pDup->iTable = pEList->a[iCol].iAlias;
72561 }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
72562 pDup = sqlite3ExprDup(db, pOrig, 0);
72563 if( pDup==0 ) return;
72564 }else{
72565 char *zToken = pOrig->u.zToken;
72566 assert( zToken!=0 );
72567 pOrig->u.zToken = 0;
72568 pDup = sqlite3ExprDup(db, pOrig, 0);
72569 pOrig->u.zToken = zToken;
72570 if( pDup==0 ) return;
72571 assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
72572 pDup->flags2 |= EP2_MallocedToken;
72573 pDup->u.zToken = sqlite3DbStrDup(db, zToken);
72574 }
72575 if( pExpr->flags & EP_ExpCollate ){
72576 pDup->pColl = pExpr->pColl;
72577 pDup->flags |= EP_ExpCollate;
72578 }
72579
72580 /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
72581 ** prevents ExprDelete() from deleting the Expr structure itself,
72582 ** allowing it to be repopulated by the memcpy() on the following line.
 
 
 
72583 */
72584 ExprSetProperty(pExpr, EP_Static);
72585 sqlite3ExprDelete(db, pExpr);
72586 memcpy(pExpr, pDup, sizeof(*pExpr));
 
 
 
 
 
72587 sqlite3DbFree(db, pDup);
72588 }
72589
72590
72591 /*
@@ -72602,10 +72656,39 @@
72602 }
72603 }
72604 return 0;
72605 }
72606
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72607
72608 /*
72609 ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
72610 ** that name in the set of source tables in pSrcList and make the pExpr
72611 ** expression node refer back to that source column. The following changes
@@ -72657,44 +72740,63 @@
72657
72658 /* Initialize the node to no-match */
72659 pExpr->iTable = -1;
72660 pExpr->pTab = 0;
72661 ExprSetIrreducible(pExpr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72662
72663 /* Start at the inner-most context and move outward until a match is found */
72664 while( pNC && cnt==0 ){
72665 ExprList *pEList;
72666 SrcList *pSrcList = pNC->pSrcList;
72667
72668 if( pSrcList ){
72669 for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
72670 Table *pTab;
72671 int iDb;
72672 Column *pCol;
72673
72674 pTab = pItem->pTab;
72675 assert( pTab!=0 && pTab->zName!=0 );
72676 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
72677 assert( pTab->nCol>0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72678 if( zTab ){
72679 if( pItem->zAlias ){
72680 char *zTabName = pItem->zAlias;
72681 if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
72682 }else{
72683 char *zTabName = pTab->zName;
72684 if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
72685 continue;
72686 }
72687 if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
72688 continue;
72689 }
72690 }
72691 }
72692 if( 0==(cntTab++) ){
72693 pExpr->iTable = pItem->iCursor;
72694 pExpr->pTab = pTab;
72695 pSchema = pTab->pSchema;
72696 pMatch = pItem;
72697 }
72698 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
72699 if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
72700 /* If there has been exactly one prior match and this match
@@ -72704,21 +72806,23 @@
72704 if( cnt==1 ){
72705 if( pItem->jointype & JT_NATURAL ) continue;
72706 if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
72707 }
72708 cnt++;
72709 pExpr->iTable = pItem->iCursor;
72710 pExpr->pTab = pTab;
72711 pMatch = pItem;
72712 pSchema = pTab->pSchema;
72713 /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
72714 pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
72715 break;
72716 }
72717 }
72718 }
72719 }
 
 
 
 
 
72720
72721 #ifndef SQLITE_OMIT_TRIGGER
72722 /* If we have not already resolved the name, then maybe
72723 ** it is a new.* or old.* trigger argument reference
72724 */
@@ -73013,42 +73117,43 @@
73013 int wrong_num_args = 0; /* True if wrong number of arguments */
73014 int is_agg = 0; /* True if is an aggregate function */
73015 int auth; /* Authorization to use the function */
73016 int nId; /* Number of characters in function name */
73017 const char *zId; /* The function name. */
73018 FuncDef *pDef; /* Information about the function */
73019 u8 enc = ENC(pParse->db); /* The database encoding */
73020
73021 testcase( pExpr->op==TK_CONST_FUNC );
73022 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
73023 zId = pExpr->u.zToken;
73024 nId = sqlite3Strlen30(zId);
73025 pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
73026 if( pDef==0 ){
73027 pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
73028 if( pDef==0 ){
73029 no_such_func = 1;
73030 }else{
73031 wrong_num_args = 1;
73032 }
73033 }else{
73034 is_agg = pDef->xFunc==0;
73035 }
73036 #ifndef SQLITE_OMIT_AUTHORIZATION
73037 if( pDef ){
73038 auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
73039 if( auth!=SQLITE_OK ){
73040 if( auth==SQLITE_DENY ){
73041 sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
73042 pDef->zName);
73043 pNC->nErr++;
73044 }
73045 pExpr->op = TK_NULL;
73046 return WRC_Prune;
73047 }
73048 }
73049 #endif
 
 
73050 if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
73051 sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
73052 pNC->nErr++;
73053 is_agg = 0;
73054 }else if( no_such_func ){
@@ -73268,11 +73373,11 @@
73268 assert( pEList!=0 );
73269 for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
73270 int iCol = -1;
73271 Expr *pE, *pDup;
73272 if( pItem->done ) continue;
73273 pE = pItem->pExpr;
73274 if( sqlite3ExprIsInteger(pE, &iCol) ){
73275 if( iCol<=0 || iCol>pEList->nExpr ){
73276 resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
73277 return 1;
73278 }
@@ -73286,18 +73391,24 @@
73286 }
73287 sqlite3ExprDelete(db, pDup);
73288 }
73289 }
73290 if( iCol>0 ){
73291 CollSeq *pColl = pE->pColl;
73292 int flags = pE->flags & EP_ExpCollate;
 
 
 
 
 
 
 
 
 
 
 
73293 sqlite3ExprDelete(db, pE);
73294 pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
73295 if( pE==0 ) return 1;
73296 pE->pColl = pColl;
73297 pE->flags |= EP_IntValue | flags;
73298 pE->u.iValue = iCol;
73299 pItem->iOrderByCol = (u16)iCol;
73300 pItem->done = 1;
73301 }else{
73302 moreToDo = 1;
73303 }
@@ -73398,15 +73509,15 @@
73398 ** sqlite3ResolveOrderGroupBy() will convert the expression to a
73399 ** copy of the iCol-th result-set expression. */
73400 pItem->iOrderByCol = (u16)iCol;
73401 continue;
73402 }
73403 if( sqlite3ExprIsInteger(pE, &iCol) ){
73404 /* The ORDER BY term is an integer constant. Again, set the column
73405 ** number so that sqlite3ResolveOrderGroupBy() will convert the
73406 ** order-by term to a copy of the result-set expression */
73407 if( iCol<1 ){
73408 resolveOutOfRangeError(pParse, zType, i+1, nResult);
73409 return 1;
73410 }
73411 pItem->iOrderByCol = (u16)iCol;
73412 continue;
@@ -73479,27 +73590,10 @@
73479 if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
73480 sqlite3ResolveExprNames(&sNC, p->pOffset) ){
73481 return WRC_Abort;
73482 }
73483
73484 /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
73485 ** resolve the result-set expression list.
73486 */
73487 sNC.ncFlags = NC_AllowAgg;
73488 sNC.pSrcList = p->pSrc;
73489 sNC.pNext = pOuterNC;
73490
73491 /* Resolve names in the result set. */
73492 pEList = p->pEList;
73493 assert( pEList!=0 );
73494 for(i=0; i<pEList->nExpr; i++){
73495 Expr *pX = pEList->a[i].pExpr;
73496 if( sqlite3ResolveExprNames(&sNC, pX) ){
73497 return WRC_Abort;
73498 }
73499 }
73500
73501 /* Recursively resolve names in all subqueries
73502 */
73503 for(i=0; i<p->pSrc->nSrc; i++){
73504 struct SrcList_item *pItem = &p->pSrc->a[i];
73505 if( pItem->pSelect ){
@@ -73522,10 +73616,27 @@
73522 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
73523 assert( pItem->isCorrelated==0 && nRef<=0 );
73524 pItem->isCorrelated = (nRef!=0);
73525 }
73526 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73527
73528 /* If there are no aggregate functions in the result-set, and no GROUP BY
73529 ** expression, do not allow aggregates in any of the other expressions.
73530 */
73531 assert( (p->selFlags & SF_Aggregate)==0 );
@@ -73756,11 +73867,13 @@
73756 ** SELECT * FROM t1 WHERE a;
73757 ** SELECT a AS b FROM t1 WHERE b;
73758 ** SELECT * FROM t1 WHERE (select a from t1);
73759 */
73760 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
73761 int op = pExpr->op;
 
 
73762 if( op==TK_SELECT ){
73763 assert( pExpr->flags&EP_xIsSelect );
73764 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
73765 }
73766 #ifndef SQLITE_OMIT_CAST
@@ -73781,70 +73894,98 @@
73781 }
73782 return pExpr->affinity;
73783 }
73784
73785 /*
73786 ** Set the explicit collating sequence for an expression to the
73787 ** collating sequence supplied in the second argument.
73788 */
73789 SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
73790 if( pExpr && pColl ){
73791 pExpr->pColl = pColl;
73792 pExpr->flags |= EP_ExpCollate;
73793 }
73794 return pExpr;
73795 }
73796
73797 /*
73798 ** Set the collating sequence for expression pExpr to be the collating
73799 ** sequence named by pToken. Return a pointer to the revised expression.
73800 ** The collating sequence is marked as "explicit" using the EP_ExpCollate
73801 ** flag. An explicit collating sequence will override implicit
73802 ** collating sequences.
73803 */
73804 SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
73805 char *zColl = 0; /* Dequoted name of collation sequence */
73806 CollSeq *pColl;
73807 sqlite3 *db = pParse->db;
73808 zColl = sqlite3NameFromToken(db, pCollName);
73809 pColl = sqlite3LocateCollSeq(pParse, zColl);
73810 sqlite3ExprSetColl(pExpr, pColl);
73811 sqlite3DbFree(db, zColl);
73812 return pExpr;
73813 }
73814
73815 /*
73816 ** Return the default collation sequence for the expression pExpr. If
73817 ** there is no default collation type, return 0.
73818 */
73819 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
73820 CollSeq *pColl = 0;
73821 Expr *p = pExpr;
73822 while( p ){
73823 int op;
73824 pColl = p->pColl;
73825 if( pColl ) break;
73826 op = p->op;
73827 if( p->pTab!=0 && (
73828 op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
73829 )){
73830 /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
73831 ** a TK_COLUMN but was previously evaluated and cached in a register */
73832 const char *zColl;
73833 int j = p->iColumn;
73834 if( j>=0 ){
73835 sqlite3 *db = pParse->db;
73836 zColl = p->pTab->aCol[j].zColl;
73837 pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
73838 pExpr->pColl = pColl;
73839 }
73840 break;
73841 }
73842 if( op!=TK_CAST && op!=TK_UPLUS ){
73843 break;
73844 }
73845 p = p->pLeft;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73846 }
73847 if( sqlite3CheckCollSeq(pParse, pColl) ){
73848 pColl = 0;
73849 }
73850 return pColl;
@@ -73944,16 +74085,14 @@
73944 Expr *pLeft,
73945 Expr *pRight
73946 ){
73947 CollSeq *pColl;
73948 assert( pLeft );
73949 if( pLeft->flags & EP_ExpCollate ){
73950 assert( pLeft->pColl );
73951 pColl = pLeft->pColl;
73952 }else if( pRight && pRight->flags & EP_ExpCollate ){
73953 assert( pRight->pColl );
73954 pColl = pRight->pColl;
73955 }else{
73956 pColl = sqlite3ExprCollSeq(pParse, pLeft);
73957 if( !pColl ){
73958 pColl = sqlite3ExprCollSeq(pParse, pRight);
73959 }
@@ -74179,21 +74318,15 @@
74179 sqlite3ExprDelete(db, pLeft);
74180 sqlite3ExprDelete(db, pRight);
74181 }else{
74182 if( pRight ){
74183 pRoot->pRight = pRight;
74184 if( pRight->flags & EP_ExpCollate ){
74185 pRoot->flags |= EP_ExpCollate;
74186 pRoot->pColl = pRight->pColl;
74187 }
74188 }
74189 if( pLeft ){
74190 pRoot->pLeft = pLeft;
74191 if( pLeft->flags & EP_ExpCollate ){
74192 pRoot->flags |= EP_ExpCollate;
74193 pRoot->pColl = pLeft->pColl;
74194 }
74195 }
74196 exprSetHeight(pRoot);
74197 }
74198 }
74199
@@ -74447,11 +74580,11 @@
74447 }else{
74448 assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
74449 assert( !ExprHasProperty(p, EP_FromJoin) );
74450 assert( (p->flags2 & EP2_MallocedToken)==0 );
74451 assert( (p->flags2 & EP2_Irreducible)==0 );
74452 if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
74453 nSize = EXPR_REDUCEDSIZE | EP_Reduced;
74454 }else{
74455 nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
74456 }
74457 }
@@ -76471,10 +76604,11 @@
76471 sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
76472 sqlite3ReleaseTempReg(pParse, r3);
76473 sqlite3ReleaseTempReg(pParse, r4);
76474 break;
76475 }
 
76476 case TK_UPLUS: {
76477 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
76478 break;
76479 }
76480
@@ -76839,10 +76973,16 @@
76839 case TK_UPLUS: zUniOp = "UPLUS"; break;
76840 case TK_BITNOT: zUniOp = "BITNOT"; break;
76841 case TK_NOT: zUniOp = "NOT"; break;
76842 case TK_ISNULL: zUniOp = "ISNULL"; break;
76843 case TK_NOTNULL: zUniOp = "NOTNULL"; break;
 
 
 
 
 
 
76844
76845 case TK_AGG_FUNCTION:
76846 case TK_CONST_FUNC:
76847 case TK_FUNCTION: {
76848 ExprList *pFarg; /* List of function arguments */
@@ -76977,10 +77117,16 @@
76977 for(i=0; i<pList->nExpr; i++){
76978 sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
76979 sqlite3ExplainPush(pOut);
76980 sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
76981 sqlite3ExplainPop(pOut);
 
 
 
 
 
 
76982 if( i<pList->nExpr-1 ){
76983 sqlite3ExplainNL(pOut);
76984 }
76985 }
76986 sqlite3ExplainPop(pOut);
@@ -77058,10 +77204,13 @@
77058 switch( pExpr->op ){
77059 case TK_IN:
77060 case TK_REGISTER: {
77061 return WRC_Prune;
77062 }
 
 
 
77063 case TK_FUNCTION:
77064 case TK_AGG_FUNCTION:
77065 case TK_CONST_FUNC: {
77066 /* The arguments to a function have a fixed destination.
77067 ** Mark them this way to avoid generated unneeded OP_SCopy
@@ -77079,13 +77228,15 @@
77079 break;
77080 }
77081 }
77082 if( isAppropriateForFactoring(pExpr) ){
77083 int r1 = ++pParse->nMem;
77084 int r2;
77085 r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
77086 if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
 
 
77087 pExpr->op2 = pExpr->op;
77088 pExpr->op = TK_REGISTER;
77089 pExpr->iTable = r2;
77090 return WRC_Prune;
77091 }
@@ -77498,11 +77649,19 @@
77498 assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
77499 if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
77500 return 2;
77501 }
77502 if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
77503 if( pA->op!=pB->op ) return 2;
 
 
 
 
 
 
 
 
77504 if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
77505 if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
77506 if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
77507 if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
77508 if( ExprHasProperty(pA, EP_IntValue) ){
@@ -77510,15 +77669,13 @@
77510 return 2;
77511 }
77512 }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
77513 if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
77514 if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
77515 return 2;
77516 }
77517 }
77518 if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
77519 if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
77520 return 0;
77521 }
77522
77523 /*
77524 ** Compare two ExprList objects. Return 0 if they are identical and
@@ -80765,10 +80922,11 @@
80765 */
80766 SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
80767 sqlite3 *db;
80768 Vdbe *v;
80769
 
80770 db = pParse->db;
80771 if( db->mallocFailed ) return;
80772 if( pParse->nested ) return;
80773 if( pParse->nErr ) return;
80774
@@ -83328,14 +83486,12 @@
83328 ** specified collation sequence names.
83329 */
83330 for(i=0; i<pList->nExpr; i++){
83331 Expr *pExpr = pList->a[i].pExpr;
83332 if( pExpr ){
83333 CollSeq *pColl = pExpr->pColl;
83334 /* Either pColl!=0 or there was an OOM failure. But if an OOM
83335 ** failure we have quit before reaching this point. */
83336 if( ALWAYS(pColl) ){
83337 nExtra += (1 + sqlite3Strlen30(pColl->zName));
83338 }
83339 }
83340 }
83341
@@ -83394,10 +83550,11 @@
83394 */
83395 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
83396 const char *zColName = pListItem->zName;
83397 Column *pTabCol;
83398 int requestedSortOrder;
 
83399 char *zColl; /* Collation sequence name */
83400
83401 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
83402 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
83403 }
@@ -83406,18 +83563,15 @@
83406 pTab->zName, zColName);
83407 pParse->checkSchema = 1;
83408 goto exit_create_index;
83409 }
83410 pIndex->aiColumn[i] = j;
83411 /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of
83412 ** the way the "idxlist" non-terminal is constructed by the parser,
83413 ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
83414 ** must exist or else there must have been an OOM error. But if there
83415 ** was an OOM error, we would never reach this point. */
83416 if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
83417 int nColl;
83418 zColl = pListItem->pExpr->pColl->zName;
83419 nColl = sqlite3Strlen30(zColl) + 1;
83420 assert( nExtra>=nColl );
83421 memcpy(zExtra, zColl, nColl);
83422 zColl = zExtra;
83423 zExtra += nColl;
@@ -84227,10 +84381,19 @@
84227 ** early in the code, before we know if any database tables will be used.
84228 */
84229 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
84230 Parse *pToplevel = sqlite3ParseToplevel(pParse);
84231
 
 
 
 
 
 
 
 
 
84232 if( pToplevel->cookieGoto==0 ){
84233 Vdbe *v = sqlite3GetVdbe(pToplevel);
84234 if( v==0 ) return; /* This only happens if there was a prior error */
84235 pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
84236 }
@@ -87437,11 +87600,11 @@
87437
87438 /*
87439 ** A foreign key constraint requires that the key columns in the parent
87440 ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
87441 ** Given that pParent is the parent table for foreign key constraint pFKey,
87442 ** search the schema a unique index on the parent key columns.
87443 **
87444 ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
87445 ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
87446 ** is set to point to the unique index.
87447 **
@@ -87473,11 +87636,11 @@
87473 **
87474 ** then non-zero is returned, and a "foreign key mismatch" error loaded
87475 ** into pParse. If an OOM error occurs, non-zero is returned and the
87476 ** pParse->db->mallocFailed flag is set.
87477 */
87478 static int locateFkeyIndex(
87479 Parse *pParse, /* Parse context to store any error in */
87480 Table *pParent, /* Parent table of FK constraint pFKey */
87481 FKey *pFKey, /* Foreign key to find index for */
87482 Index **ppIdx, /* OUT: Unique index on parent table */
87483 int **paiCol /* OUT: Map of index columns in pFKey */
@@ -87570,11 +87733,13 @@
87570 }
87571 }
87572
87573 if( !pIdx ){
87574 if( !pParse->disableTriggers ){
87575 sqlite3ErrorMsg(pParse, "foreign key mismatch");
 
 
87576 }
87577 sqlite3DbFree(pParse->db, aiCol);
87578 return 1;
87579 }
87580
@@ -87806,16 +87971,19 @@
87806 if( pLeft ){
87807 /* Set the collation sequence and affinity of the LHS of each TK_EQ
87808 ** expression to the parent key column defaults. */
87809 if( pIdx ){
87810 Column *pCol;
 
87811 iCol = pIdx->aiColumn[i];
87812 pCol = &pTab->aCol[iCol];
87813 if( pTab->iPKey==iCol ) iCol = -1;
87814 pLeft->iTable = regData+iCol+1;
87815 pLeft->affinity = pCol->affinity;
87816 pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
 
 
87817 }else{
87818 pLeft->iTable = regData;
87819 pLeft->affinity = SQLITE_AFF_INTEGER;
87820 }
87821 }
@@ -88028,11 +88196,11 @@
88028 if( pParse->disableTriggers ){
88029 pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
88030 }else{
88031 pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
88032 }
88033 if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
88034 assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
88035 if( !isIgnoreErrors || db->mallocFailed ) return;
88036 if( pTo==0 ){
88037 /* If isIgnoreErrors is true, then a table is being dropped. In this
88038 ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
@@ -88108,11 +88276,11 @@
88108 /* Inserting a single row into a parent table cannot cause an immediate
88109 ** foreign key violation. So do nothing in this case. */
88110 continue;
88111 }
88112
88113 if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
88114 if( !isIgnoreErrors || db->mallocFailed ) return;
88115 continue;
88116 }
88117 assert( aiCol || pFKey->nCol==1 );
88118
@@ -88163,11 +88331,11 @@
88163 for(p=pTab->pFKey; p; p=p->pNextFrom){
88164 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
88165 }
88166 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
88167 Index *pIdx = 0;
88168 locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
88169 if( pIdx ){
88170 for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
88171 }
88172 }
88173 }
@@ -88289,11 +88457,11 @@
88289 ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
88290 Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
88291 int i; /* Iterator variable */
88292 Expr *pWhen = 0; /* WHEN clause for the trigger */
88293
88294 if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
88295 assert( aiCol || pFKey->nCol==1 );
88296
88297 for(i=0; i<pFKey->nCol; i++){
88298 Token tOld = { "old", 3 }; /* Literal "old" token */
88299 Token tNew = { "new", 3 }; /* Literal "new" token */
@@ -89791,29 +89959,24 @@
89791 ExprList *pCheck = pTab->pCheck;
89792 pParse->ckBase = regData;
89793 onError = overrideError!=OE_Default ? overrideError : OE_Abort;
89794 for(i=0; i<pCheck->nExpr; i++){
89795 int allOk = sqlite3VdbeMakeLabel(v);
89796 Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
89797 if( !db->mallocFailed ){
89798 assert( pDup!=0 );
89799 sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
89800 if( onError==OE_Ignore ){
89801 sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
89802 }else{
89803 char *zConsName = pCheck->a[i].zName;
89804 if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
89805 if( zConsName ){
89806 zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
89807 }else{
89808 zConsName = 0;
89809 }
89810 sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
89811 }
89812 sqlite3VdbeResolveLabel(v, allOk);
89813 }
89814 sqlite3ExprDelete(db, pDup);
89815 }
89816 }
89817 #endif /* !defined(SQLITE_OMIT_CHECK) */
89818
89819 /* If we have an INTEGER PRIMARY KEY, make sure the primary key
@@ -92634,13 +92797,15 @@
92634 if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
92635 Table *pTab;
92636 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
92637 pTab = sqlite3FindTable(db, zRight, zDb);
92638 if( pTab ){
92639 int i;
92640 int nHidden = 0;
92641 Column *pCol;
 
 
92642 sqlite3VdbeSetNumCols(v, 6);
92643 pParse->nMem = 6;
92644 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
92645 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
92646 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92661,12 +92826,18 @@
92661 if( pCol->zDflt ){
92662 sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
92663 }else{
92664 sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
92665 }
92666 sqlite3VdbeAddOp2(v, OP_Integer,
92667 (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
 
 
 
 
 
 
92668 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
92669 }
92670 }
92671 }else
92672
@@ -92797,10 +92968,124 @@
92797 ++i;
92798 pFK = pFK->pNextFrom;
92799 }
92800 }
92801 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92802 }else
92803 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
92804
92805 #ifndef NDEBUG
92806 if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -94256,11 +94541,11 @@
94256 SrcList *pSrc, /* the FROM clause -- which tables to scan */
94257 Expr *pWhere, /* the WHERE clause */
94258 ExprList *pGroupBy, /* the GROUP BY clause */
94259 Expr *pHaving, /* the HAVING clause */
94260 ExprList *pOrderBy, /* the ORDER BY clause */
94261 int isDistinct, /* true if the DISTINCT keyword is present */
94262 Expr *pLimit, /* LIMIT value. NULL means not used */
94263 Expr *pOffset /* OFFSET value. NULL means no offset */
94264 ){
94265 Select *pNew;
94266 Select standin;
@@ -94280,11 +94565,11 @@
94280 pNew->pSrc = pSrc;
94281 pNew->pWhere = pWhere;
94282 pNew->pGroupBy = pGroupBy;
94283 pNew->pHaving = pHaving;
94284 pNew->pOrderBy = pOrderBy;
94285 pNew->selFlags = isDistinct ? SF_Distinct : 0;
94286 pNew->op = TK_SELECT;
94287 pNew->pLimit = pLimit;
94288 pNew->pOffset = pOffset;
94289 assert( pOffset==0 || pLimit!=0 );
94290 pNew->addrOpenEphm[0] = -1;
@@ -95536,13 +95821,11 @@
95536 *paCol = aCol;
95537
95538 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
95539 /* Get an appropriate name for the column
95540 */
95541 p = pEList->a[i].pExpr;
95542 assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
95543 || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
95544 if( (zName = pEList->a[i].zName)!=0 ){
95545 /* If the column contains an "AS <name>" phrase, use <name> as the name */
95546 zName = sqlite3DbStrDup(db, zName);
95547 }else{
95548 Expr *pColExpr = p; /* The expression that is the result column name */
@@ -95576,10 +95859,13 @@
95576 */
95577 nName = sqlite3Strlen30(zName);
95578 for(j=cnt=0; j<i; j++){
95579 if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
95580 char *zNewName;
 
 
 
95581 zName[nName] = 0;
95582 zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
95583 sqlite3DbFree(db, zName);
95584 zName = zNewName;
95585 j = -1;
@@ -96534,16 +96820,17 @@
96534 pKeyMerge->nField = (u16)nOrderBy;
96535 pKeyMerge->enc = ENC(db);
96536 for(i=0; i<nOrderBy; i++){
96537 CollSeq *pColl;
96538 Expr *pTerm = pOrderBy->a[i].pExpr;
96539 if( pTerm->flags & EP_ExpCollate ){
96540 pColl = pTerm->pColl;
96541 }else{
96542 pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
96543 pTerm->flags |= EP_ExpCollate;
96544 pTerm->pColl = pColl;
 
96545 }
96546 pKeyMerge->aColl[i] = pColl;
96547 pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
96548 }
96549 }
@@ -96742,10 +97029,11 @@
96742 */
96743 sqlite3VdbeResolveLabel(v, labelCmpr);
96744 sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
96745 sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
96746 (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
 
96747 sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
96748
96749 /* Release temporary registers
96750 */
96751 if( regPrev ){
@@ -96809,13 +97097,10 @@
96809 }else{
96810 Expr *pNew;
96811 assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
96812 assert( pExpr->pLeft==0 && pExpr->pRight==0 );
96813 pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
96814 if( pNew && pExpr->pColl ){
96815 pNew->pColl = pExpr->pColl;
96816 }
96817 sqlite3ExprDelete(db, pExpr);
96818 pExpr = pNew;
96819 }
96820 }else{
96821 pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
@@ -97362,38 +97647,47 @@
97362 return 1;
97363 }
97364 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
97365
97366 /*
97367 ** Analyze the SELECT statement passed as an argument to see if it
97368 ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
97369 ** it is, or 0 otherwise. At present, a query is considered to be
97370 ** a min()/max() query if:
97371 **
97372 ** 1. There is a single object in the FROM clause.
97373 **
97374 ** 2. There is a single expression in the result set, and it is
97375 ** either min(x) or max(x), where x is a column reference.
97376 */
97377 static u8 minMaxQuery(Select *p){
97378 Expr *pExpr;
97379 ExprList *pEList = p->pEList;
97380
97381 if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
97382 pExpr = pEList->a[0].pExpr;
97383 if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
97384 if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
97385 pEList = pExpr->x.pList;
97386 if( pEList==0 || pEList->nExpr!=1 ) return 0;
97387 if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
97388 assert( !ExprHasProperty(pExpr, EP_IntValue) );
97389 if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
97390 return WHERE_ORDERBY_MIN;
97391 }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
97392 return WHERE_ORDERBY_MAX;
97393 }
97394 return WHERE_ORDERBY_NORMAL;
 
 
 
 
 
 
 
 
 
97395 }
97396
97397 /*
97398 ** The select statement passed as the first argument is an aggregate query.
97399 ** The second argment is the associated aggregate-info object. This
@@ -97484,10 +97778,11 @@
97484 int i, j, k;
97485 SrcList *pTabList;
97486 ExprList *pEList;
97487 struct SrcList_item *pFrom;
97488 sqlite3 *db = pParse->db;
 
97489
97490 if( db->mallocFailed ){
97491 return WRC_Abort;
97492 }
97493 if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
@@ -97569,11 +97864,11 @@
97569 **
97570 ** The first loop just checks to see if there are any "*" operators
97571 ** that need expanding.
97572 */
97573 for(k=0; k<pEList->nExpr; k++){
97574 Expr *pE = pEList->a[k].pExpr;
97575 if( pE->op==TK_ALL ) break;
97576 assert( pE->op!=TK_DOT || pE->pRight!=0 );
97577 assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
97578 if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
97579 }
@@ -97587,14 +97882,22 @@
97587 ExprList *pNew = 0;
97588 int flags = pParse->db->flags;
97589 int longNames = (flags & SQLITE_FullColNames)!=0
97590 && (flags & SQLITE_ShortColNames)==0;
97591
 
 
 
 
 
 
 
97592 for(k=0; k<pEList->nExpr; k++){
97593 Expr *pE = a[k].pExpr;
97594 assert( pE->op!=TK_DOT || pE->pRight!=0 );
97595 if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
 
97596 /* This particular expression does not need to be expanded.
97597 */
97598 pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
97599 if( pNew ){
97600 pNew->a[pNew->nExpr-1].zName = a[k].zName;
@@ -97605,44 +97908,56 @@
97605 a[k].pExpr = 0;
97606 }else{
97607 /* This expression is a "*" or a "TABLE.*" and needs to be
97608 ** expanded. */
97609 int tableSeen = 0; /* Set to 1 when TABLE matches */
97610 char *zTName; /* text of name of TABLE */
97611 if( pE->op==TK_DOT ){
97612 assert( pE->pLeft!=0 );
97613 assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
97614 zTName = pE->pLeft->u.zToken;
97615 }else{
97616 zTName = 0;
97617 }
97618 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
97619 Table *pTab = pFrom->pTab;
 
97620 char *zTabName = pFrom->zAlias;
 
 
97621 if( zTabName==0 ){
97622 zTabName = pTab->zName;
97623 }
97624 if( db->mallocFailed ) break;
97625 if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
97626 continue;
 
 
 
 
 
97627 }
97628 tableSeen = 1;
97629 for(j=0; j<pTab->nCol; j++){
97630 Expr *pExpr, *pRight;
97631 char *zName = pTab->aCol[j].zName;
97632 char *zColname; /* The computed column name */
97633 char *zToFree; /* Malloced string that needs to be freed */
97634 Token sColname; /* Computed column name as a token */
 
 
 
 
 
 
 
97635
97636 /* If a column is marked as 'hidden' (currently only possible
97637 ** for virtual tables), do not include it in the expanded
97638 ** result-set list.
97639 */
97640 if( IsHiddenColumn(&pTab->aCol[j]) ){
97641 assert(IsVirtual(pTab));
97642 continue;
97643 }
 
97644
97645 if( i>0 && zTName==0 ){
97646 if( (pFrom->jointype & JT_NATURAL)!=0
97647 && tableAndColumnIndex(pTabList, i, zName, 0, 0)
97648 ){
@@ -97661,10 +97976,14 @@
97661 zToFree = 0;
97662 if( longNames || pTabList->nSrc>1 ){
97663 Expr *pLeft;
97664 pLeft = sqlite3Expr(db, TK_ID, zTabName);
97665 pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
 
 
 
 
97666 if( longNames ){
97667 zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
97668 zToFree = zColname;
97669 }
97670 }else{
@@ -97672,10 +97991,22 @@
97672 }
97673 pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
97674 sColname.z = zColname;
97675 sColname.n = sqlite3Strlen30(zColname);
97676 sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
 
 
 
 
 
 
 
 
 
 
 
 
97677 sqlite3DbFree(db, zToFree);
97678 }
97679 }
97680 if( !tableSeen ){
97681 if( zTName ){
@@ -98151,10 +98482,19 @@
98151 */
98152 int addrTop;
98153 int addrEof;
98154 pItem->regReturn = ++pParse->nMem;
98155 addrEof = ++pParse->nMem;
 
 
 
 
 
 
 
 
 
98156 sqlite3VdbeAddOp0(v, OP_Goto);
98157 addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
98158 sqlite3VdbeChangeP5(v, 1);
98159 VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
98160 pItem->addrFillSub = addrTop;
@@ -98720,15 +99060,21 @@
98720 ** index or indices to use) should place a different priority on
98721 ** satisfying the 'ORDER BY' clause than it does in other cases.
98722 ** Refer to code and comments in where.c for details.
98723 */
98724 ExprList *pMinMax = 0;
98725 u8 flag = minMaxQuery(p);
 
 
 
 
 
 
 
 
98726 if( flag ){
98727 assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
98728 assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
98729 pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
98730 pDel = pMinMax;
98731 if( pMinMax && !db->mallocFailed ){
98732 pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
98733 pMinMax->a[0].pExpr->op = TK_COLUMN;
98734 }
@@ -99827,10 +100173,19 @@
99827 **
99828 ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
99829 ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
99830 */
99831 pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
 
 
 
 
 
 
 
 
 
99832
99833 switch( pStep->op ){
99834 case TK_UPDATE: {
99835 sqlite3Update(pParse,
99836 targetSrcList(pParse, pStep),
@@ -102603,11 +102958,11 @@
102603 #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
102604 #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
102605 #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
102606 #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
102607 #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
102608 #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
102609 #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
102610 #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
102611 #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
102612 #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
102613 #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
@@ -102753,11 +103108,11 @@
102753 sqlite3DbFree(db, pOld);
102754 }
102755 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
102756 }
102757 pTerm = &pWC->a[idx = pWC->nTerm++];
102758 pTerm->pExpr = p;
102759 pTerm->wtFlags = wtFlags;
102760 pTerm->pWC = pWC;
102761 pTerm->iParent = -1;
102762 return idx;
102763 }
@@ -102913,27 +103268,36 @@
102913
102914 /*
102915 ** Commute a comparison operator. Expressions of the form "X op Y"
102916 ** are converted into "Y op X".
102917 **
102918 ** If a collation sequence is associated with either the left or right
 
102919 ** side of the comparison, it remains associated with the same side after
102920 ** the commutation. So "Y collate NOCASE op X" becomes
102921 ** "X collate NOCASE op Y". This is because any collation sequence on
102922 ** the left hand side of a comparison overrides any collation sequence
102923 ** attached to the right. For the same reason the EP_ExpCollate flag
102924 ** is not commuted.
102925 */
102926 static void exprCommute(Parse *pParse, Expr *pExpr){
102927 u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
102928 u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
102929 assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
102930 pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
102931 pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
102932 SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
102933 pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
102934 pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
 
 
 
 
 
 
 
 
102935 SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
102936 if( pExpr->op>=TK_GT ){
102937 assert( TK_LT==TK_GT+2 );
102938 assert( TK_GE==TK_LE+2 );
102939 assert( TK_GT>TK_EQ );
@@ -103006,16 +103370,16 @@
103006 ** it to be useful for optimising expression pX. Store this
103007 ** value in variable pColl.
103008 */
103009 assert(pX->pLeft);
103010 pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
103011 assert(pColl || pParse->nErr);
103012
103013 for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
103014 if( NEVER(j>=pIdx->nColumn) ) return 0;
103015 }
103016 if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103017 }
103018 return pTerm;
103019 }
103020 }
103021 }
@@ -103530,10 +103894,11 @@
103530 return;
103531 }
103532 pTerm = &pWC->a[idxTerm];
103533 pMaskSet = pWC->pMaskSet;
103534 pExpr = pTerm->pExpr;
 
103535 prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
103536 op = pExpr->op;
103537 if( op==TK_IN ){
103538 assert( pExpr->pRight==0 );
103539 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
@@ -103556,12 +103921,12 @@
103556 pTerm->prereqAll = prereqAll;
103557 pTerm->leftCursor = -1;
103558 pTerm->iParent = -1;
103559 pTerm->eOperator = 0;
103560 if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
103561 Expr *pLeft = pExpr->pLeft;
103562 Expr *pRight = pExpr->pRight;
103563 if( pLeft->op==TK_COLUMN ){
103564 pTerm->leftCursor = pLeft->iTable;
103565 pTerm->u.leftColumn = pLeft->iColumn;
103566 pTerm->eOperator = operatorMask(op);
103567 }
@@ -103585,11 +103950,11 @@
103585 }else{
103586 pDup = pExpr;
103587 pNew = pTerm;
103588 }
103589 exprCommute(pParse, pDup);
103590 pLeft = pDup->pLeft;
103591 pNew->leftCursor = pLeft->iTable;
103592 pNew->u.leftColumn = pLeft->iColumn;
103593 testcase( (prereqLeft | extraRight) != prereqLeft );
103594 pNew->prereqRight = prereqLeft | extraRight;
103595 pNew->prereqAll = prereqAll;
@@ -103664,11 +104029,11 @@
103664 Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
103665 Expr *pNewExpr1;
103666 Expr *pNewExpr2;
103667 int idxNew1;
103668 int idxNew2;
103669 CollSeq *pColl; /* Collating sequence to use */
103670
103671 pLeft = pExpr->x.pList->a[1].pExpr;
103672 pStr2 = sqlite3ExprDup(db, pStr1, 0);
103673 if( !db->mallocFailed ){
103674 u8 c, *pC; /* Last character before the first wildcard */
@@ -103686,20 +104051,23 @@
103686
103687 c = sqlite3UpperToLower[c];
103688 }
103689 *pC = c + 1;
103690 }
103691 pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
 
 
103692 pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
103693 sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
103694 pStr1, 0);
103695 idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
103696 testcase( idxNew1==0 );
103697 exprAnalyze(pSrc, pWC, idxNew1);
 
103698 pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
103699 sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
103700 pStr2, 0);
103701 idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
103702 testcase( idxNew2==0 );
103703 exprAnalyze(pSrc, pWC, idxNew2);
103704 pTerm = &pWC->a[idxTerm];
103705 if( isComplete ){
@@ -103813,16 +104181,16 @@
103813 ){
103814 int i;
103815 const char *zColl = pIdx->azColl[iCol];
103816
103817 for(i=0; i<pList->nExpr; i++){
103818 Expr *p = pList->a[i].pExpr;
103819 if( p->op==TK_COLUMN
103820 && p->iColumn==pIdx->aiColumn[iCol]
103821 && p->iTable==iBase
103822 ){
103823 CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
103824 if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
103825 return i;
103826 }
103827 }
103828 }
@@ -103865,11 +104233,11 @@
103865 ** matching "col=X" expression and the column is on the same table as pIdx,
103866 ** set the corresponding bit in variable mask.
103867 */
103868 for(i=0; i<pDistinct->nExpr; i++){
103869 WhereTerm *pTerm;
103870 Expr *p = pDistinct->a[i].pExpr;
103871 if( p->op!=TK_COLUMN ) return 0;
103872 pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
103873 if( pTerm ){
103874 Expr *pX = pTerm->pExpr;
103875 CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
@@ -103917,11 +104285,11 @@
103917 /* If any of the expressions is an IPK column on table iBase, then return
103918 ** true. Note: The (p->iTable==iBase) part of this test may be false if the
103919 ** current SELECT is a correlated sub-query.
103920 */
103921 for(i=0; i<pDistinct->nExpr; i++){
103922 Expr *p = pDistinct->a[i].pExpr;
103923 if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
103924 }
103925
103926 /* Loop through all indices on the table, checking each to see if it makes
103927 ** the DISTINCT qualifier redundant. It does so if:
@@ -104394,11 +104762,11 @@
104394 for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104395 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104396 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104397 testcase( pTerm->eOperator==WO_IN );
104398 testcase( pTerm->eOperator==WO_ISNULL );
104399 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
104400 if( pTerm->wtFlags & TERM_VNULL ) continue;
104401 nTerm++;
104402 }
104403
104404 /* If the ORDER BY clause contains only columns in the current
@@ -104442,29 +104810,32 @@
104442 *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
104443 *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
104444 pUsage;
104445
104446 for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
 
104447 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104448 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104449 testcase( pTerm->eOperator==WO_IN );
104450 testcase( pTerm->eOperator==WO_ISNULL );
104451 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
104452 if( pTerm->wtFlags & TERM_VNULL ) continue;
104453 pIdxCons[j].iColumn = pTerm->u.leftColumn;
104454 pIdxCons[j].iTermOffset = i;
104455 pIdxCons[j].op = (u8)pTerm->eOperator;
 
 
104456 /* The direct assignment in the previous line is possible only because
104457 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104458 ** following asserts verify this fact. */
104459 assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
104460 assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
104461 assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
104462 assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
104463 assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
104464 assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
104465 assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
104466 j++;
104467 }
104468 for(i=0; i<nOrderBy; i++){
104469 Expr *pExpr = pOrderBy->a[i].pExpr;
104470 pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -104546,10 +104917,11 @@
104546 struct sqlite3_index_constraint *pIdxCons;
104547 struct sqlite3_index_constraint_usage *pUsage;
104548 WhereTerm *pTerm;
104549 int i, j;
104550 int nOrderBy;
 
104551 double rCost;
104552
104553 /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
104554 ** malloc in allocateIndexInfo() fails and this function returns leaving
104555 ** wsFlags in an uninitialized state, the caller may behave unpredictably.
@@ -104580,63 +104952,91 @@
104580 ** sqlite3ViewGetColumnNames() would have picked up the error.
104581 */
104582 assert( pTab->azModuleArg && pTab->azModuleArg[0] );
104583 assert( sqlite3GetVTable(pParse->db, pTab) );
104584
104585 /* Set the aConstraint[].usable fields and initialize all
104586 ** output variables to zero.
104587 **
104588 ** aConstraint[].usable is true for constraints where the right-hand
104589 ** side contains only references to tables to the left of the current
104590 ** table. In other words, if the constraint is of the form:
104591 **
104592 ** column = expr
104593 **
104594 ** and we are evaluating a join, then the constraint on column is
104595 ** only valid if all tables referenced in expr occur to the left
104596 ** of the table containing column.
104597 **
104598 ** The aConstraints[] array contains entries for all constraints
104599 ** on the current table. That way we only have to compute it once
104600 ** even though we might try to pick the best index multiple times.
104601 ** For each attempt at picking an index, the order of tables in the
104602 ** join might be different so we have to recompute the usable flag
104603 ** each time.
104604 */
104605 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104606 pUsage = pIdxInfo->aConstraintUsage;
104607 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104608 j = pIdxCons->iTermOffset;
104609 pTerm = &pWC->a[j];
104610 pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
104611 }
104612 memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
104613 if( pIdxInfo->needToFreeIdxStr ){
104614 sqlite3_free(pIdxInfo->idxStr);
104615 }
104616 pIdxInfo->idxStr = 0;
104617 pIdxInfo->idxNum = 0;
104618 pIdxInfo->needToFreeIdxStr = 0;
104619 pIdxInfo->orderByConsumed = 0;
104620 /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
104621 pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
104622 nOrderBy = pIdxInfo->nOrderBy;
104623 if( !p->pOrderBy ){
104624 pIdxInfo->nOrderBy = 0;
104625 }
104626
104627 if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
104628 return;
104629 }
104630
104631 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104632 for(i=0; i<pIdxInfo->nConstraint; i++){
104633 if( pUsage[i].argvIndex>0 ){
104634 p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
104635 }
104636 }
104637
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104638 /* If there is an ORDER BY clause, and the selected virtual table index
104639 ** does not satisfy it, increase the cost of the scan accordingly. This
104640 ** matches the processing for non-virtual tables in bestBtreeIndex().
104641 */
104642 rCost = pIdxInfo->estimatedCost;
@@ -105203,11 +105603,11 @@
105203 WhereTerm *pConstraint; /* A constraint in the WHERE clause */
105204
105205 /* If the next term of the ORDER BY clause refers to anything other than
105206 ** a column in the "base" table, then this index will not be of any
105207 ** further use in handling the ORDER BY. */
105208 pOBExpr = pOBItem->pExpr;
105209 if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
105210 break;
105211 }
105212
105213 /* Find column number and collating sequence for the next entry
@@ -105229,11 +105629,11 @@
105229 /* Check to see if the column number and collating sequence of the
105230 ** index match the column number and collating sequence of the ORDER BY
105231 ** clause entry. Set isMatch to 1 if they both match. */
105232 if( pOBExpr->iColumn==iColumn ){
105233 if( zColl ){
105234 pColl = sqlite3ExprCollSeq(pParse, pOBExpr);
105235 if( !pColl ) pColl = db->pDfltColl;
105236 isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
105237 }else{
105238 isMatch = 1;
105239 }
@@ -105370,10 +105770,15 @@
105370 int idxEqTermMask; /* Index mask of valid equality operators */
105371 Index sPk; /* A fake index object for the primary key */
105372 tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
105373 int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
105374 int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
 
 
 
 
 
105375
105376 /* Initialize the cost to a worst-case value */
105377 memset(&p->cost, 0, sizeof(p->cost));
105378 p->cost.rCost = SQLITE_BIG_DBL;
105379
@@ -105418,10 +105823,21 @@
105418 WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
105419 );
105420 eqTermMask = WO_EQ|WO_IN;
105421 pIdx = 0;
105422 }
 
 
 
 
 
 
 
 
 
 
 
105423
105424 /* Loop over all indices looking for the best one to use
105425 */
105426 for(; pProbe; pIdx=pProbe=pProbe->pNext){
105427 const tRowcnt * const aiRowEst = pProbe->aiRowEst;
@@ -105496,15 +105912,13 @@
105496 */
105497 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
105498 int nInMul = 1; /* Number of distinct equalities to lookup */
105499 double rangeDiv = (double)1; /* Estimated reduction in search space */
105500 int nBound = 0; /* Number of range constraints seen */
105501 int bSort; /* True if external sort required */
105502 int bDist; /* True if index cannot help with DISTINCT */
105503 int bLookup = 0; /* True if not a covering index */
105504 int nPriorSat; /* ORDER BY terms satisfied by outer loops */
105505 int nOrderBy; /* Number of ORDER BY terms */
105506 WhereTerm *pTerm; /* A single term of the WHERE clause */
105507 #ifdef SQLITE_ENABLE_STAT3
105508 WhereTerm *pFirstTerm = 0; /* First term matching the index */
105509 #endif
105510
@@ -105511,20 +105925,11 @@
105511 WHERETRACE((
105512 " %s(%s):\n",
105513 pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
105514 ));
105515 memset(&pc, 0, sizeof(pc));
105516 nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
105517 if( p->i ){
105518 nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat;
105519 bSort = nPriorSat<nOrderBy;
105520 bDist = 0;
105521 }else{
105522 nPriorSat = pc.plan.nOBSat = 0;
105523 bSort = nOrderBy>0;
105524 bDist = p->pDistinct!=0;
105525 }
105526
105527 /* Determine the values of pc.plan.nEq and nInMul */
105528 for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
105529 int j = pProbe->aiColumn[pc.plan.nEq];
105530 pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
@@ -106396,32 +106801,40 @@
106396 if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
106397 /* Case 0: The table is a virtual-table. Use the VFilter and VNext
106398 ** to access the data.
106399 */
106400 int iReg; /* P3 Value for OP_VFilter */
 
106401 sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
106402 int nConstraint = pVtabIdx->nConstraint;
106403 struct sqlite3_index_constraint_usage *aUsage =
106404 pVtabIdx->aConstraintUsage;
106405 const struct sqlite3_index_constraint *aConstraint =
106406 pVtabIdx->aConstraint;
106407
106408 sqlite3ExprCachePush(pParse);
106409 iReg = sqlite3GetTempRange(pParse, nConstraint+2);
 
106410 for(j=1; j<=nConstraint; j++){
106411 for(k=0; k<nConstraint; k++){
106412 if( aUsage[k].argvIndex==j ){
106413 int iTerm = aConstraint[k].iTermOffset;
106414 sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
 
 
 
 
 
 
106415 break;
106416 }
106417 }
106418 if( k==nConstraint ) break;
106419 }
106420 sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
106421 sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
106422 sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
106423 pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
106424 pVtabIdx->needToFreeIdxStr = 0;
106425 for(j=0; j<nConstraint; j++){
106426 if( aUsage[j].omit ){
106427 int iTerm = aConstraint[j].iTermOffset;
@@ -108064,10 +108477,11 @@
108064 Expr* yy122;
108065 Select* yy159;
108066 IdList* yy180;
108067 struct {int value; int mask;} yy207;
108068 u8 yy258;
 
108069 struct LikeOp yy318;
108070 TriggerStep* yy327;
108071 ExprSpan yy342;
108072 SrcList* yy347;
108073 int yy392;
@@ -110014,22 +110428,19 @@
110014 case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
110015 case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
110016 case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
110017 case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
110018 case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
110019 case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
110020 case 121: /* distinct ::= */ yytestcase(yyruleno==121);
110021 case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
110022 case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
110023 {yygotominor.yy392 = 0;}
110024 break;
110025 case 29: /* ifnotexists ::= IF NOT EXISTS */
110026 case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
110027 case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
110028 case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
110029 case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
110030 case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
110031 case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
110032 case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
110033 {yygotominor.yy392 = 1;}
110034 break;
110035 case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
@@ -110265,12 +110676,19 @@
110265 case 116: /* multiselect_op ::= UNION ALL */
110266 {yygotominor.yy392 = TK_ALL;}
110267 break;
110268 case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110269 {
110270 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);
110271 }
 
 
 
 
 
 
 
110272 break;
110273 case 122: /* sclp ::= selcollist COMMA */
110274 case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
110275 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
110276 break;
@@ -110336,14 +110754,24 @@
110336 break;
110337 case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110338 {
110339 if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110340 yygotominor.yy347 = yymsp[-4].minor.yy347;
 
 
 
 
 
 
 
 
 
 
110341 }else{
110342 Select *pSubquery;
110343 sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
110344 pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
110345 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110346 }
110347 }
110348 break;
110349 case 137: /* dbnm ::= */
@@ -110554,11 +110982,11 @@
110554 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110555 }
110556 break;
110557 case 194: /* expr ::= expr COLLATE ids */
110558 {
110559 yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110560 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110561 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110562 }
110563 break;
110564 case 195: /* expr ::= CAST LP expr AS typetoken RP */
@@ -110572,11 +111000,11 @@
110572 if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
110573 sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
110574 }
110575 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
110576 spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
110577 if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
110578 yygotominor.yy342.pExpr->flags |= EP_Distinct;
110579 }
110580 }
110581 break;
110582 case 197: /* expr ::= ID LP STAR RP */
@@ -110813,28 +111241,20 @@
110813 case 244: /* uniqueflag ::= */
110814 {yygotominor.yy392 = OE_None;}
110815 break;
110816 case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
110817 {
110818 Expr *p = 0;
110819 if( yymsp[-1].minor.yy0.n>0 ){
110820 p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
110821 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
110822 }
110823 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
110824 sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
110825 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110826 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110827 }
110828 break;
110829 case 248: /* idxlist ::= nm collate sortorder */
110830 {
110831 Expr *p = 0;
110832 if( yymsp[-1].minor.yy0.n>0 ){
110833 p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
110834 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
110835 }
110836 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
110837 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110838 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110839 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110840 }
110841
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.16. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -671,13 +671,13 @@
671 **
672 ** See also: [sqlite3_libversion()],
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.16"
677 #define SQLITE_VERSION_NUMBER 3007016
678 #define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -1421,11 +1421,10 @@
1421 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1422 ** that the VFS encountered an error while handling the [PRAGMA] and the
1423 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1424 ** file control occurs at the beginning of pragma statement analysis and so
1425 ** it is able to override built-in [PRAGMA] statements.
 
1426 **
1427 ** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
1428 ** ^This file-control may be invoked by SQLite on the database file handle
1429 ** shortly after it is opened in order to provide a custom VFS with access
1430 ** to the connections busy-handler callback. The argument is of type (void **)
@@ -1433,10 +1432,20 @@
1432 ** to a function of type (int (*)(void *)). In order to invoke the connections
1433 ** busy-handler, this function should be invoked with the second (void *) in
1434 ** the array as the only argument. If it returns non-zero, then the operation
1435 ** should be retried. If it returns zero, the custom VFS should abandon the
1436 ** current operation.
1437 **
1438 ** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
1439 ** ^Application can invoke this file-control to have SQLite generate a
1440 ** temporary filename using the same algorithm that is followed to generate
1441 ** temporary filenames for TEMP tables and other internal uses. The
1442 ** argument should be a char** which will be filled with the filename
1443 ** written into memory obtained from [sqlite3_malloc()]. The caller should
1444 ** invoke [sqlite3_free()] on the result to avoid a memory leak.
1445 **
1446 ** </ul>
1447 */
1448 #define SQLITE_FCNTL_LOCKSTATE 1
1449 #define SQLITE_GET_LOCKPROXYFILE 2
1450 #define SQLITE_SET_LOCKPROXYFILE 3
1451 #define SQLITE_LAST_ERRNO 4
@@ -1449,10 +1458,11 @@
1458 #define SQLITE_FCNTL_OVERWRITE 11
1459 #define SQLITE_FCNTL_VFSNAME 12
1460 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
1461 #define SQLITE_FCNTL_PRAGMA 14
1462 #define SQLITE_FCNTL_BUSYHANDLER 15
1463 #define SQLITE_FCNTL_TEMPFILENAME 16
1464
1465 /*
1466 ** CAPI3REF: Mutex Handle
1467 **
1468 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -2146,11 +2156,11 @@
2156 ** database connection is opened. By default, URI handling is globally
2157 ** disabled. The default value may be changed by compiling with the
2158 ** [SQLITE_USE_URI] symbol defined.
2159 **
2160 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
2161 ** <dd> This option takes a single integer argument which is interpreted as
2162 ** a boolean in order to enable or disable the use of covering indices for
2163 ** full table scans in the query optimizer. The default setting is determined
2164 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
2165 ** if that compile-time option is omitted.
2166 ** The ability to disable the use of covering indices for full table scans
@@ -10209,23 +10219,11 @@
10219 /*
10220 ** A "Collating Sequence" is defined by an instance of the following
10221 ** structure. Conceptually, a collating sequence consists of a name and
10222 ** a comparison routine that defines the order of that sequence.
10223 **
10224 ** If CollSeq.xCmp is NULL, it means that the
 
 
 
 
 
 
 
 
 
 
 
 
10225 ** collating sequence is undefined. Indices built on an undefined
10226 ** collating sequence may not be read or written.
10227 */
10228 struct CollSeq {
10229 char *zName; /* Name of the collating sequence, UTF-8 encoded */
@@ -10555,24 +10553,24 @@
10553 ** and the value of Index.onError indicate the which conflict resolution
10554 ** algorithm to employ whenever an attempt is made to insert a non-unique
10555 ** element.
10556 */
10557 struct Index {
10558 char *zName; /* Name of this index */
10559 int *aiColumn; /* Which columns are used by this index. 1st is 0 */
10560 tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
10561 Table *pTable; /* The SQL table being indexed */
10562 char *zColAff; /* String defining the affinity of each column */
10563 Index *pNext; /* The next index associated with the same table */
10564 Schema *pSchema; /* Schema containing this index */
10565 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10566 char **azColl; /* Array of collation sequence names for index */
10567 int tnum; /* DB Page containing root of this index */
10568 u16 nColumn; /* Number of columns in table used by this index */
10569 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10570 unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10571 unsigned bUnordered:1; /* Use this index for == or IN queries only */
10572 #ifdef SQLITE_ENABLE_STAT3
10573 int nSample; /* Number of elements in aSample[] */
10574 tRowcnt avgEq; /* Average nEq value for key values not in aSample */
10575 IndexSample *aSample; /* Samples of the left-most key */
10576 #endif
@@ -10749,11 +10747,10 @@
10747 Expr *pRight; /* Right subnode */
10748 union {
10749 ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
10750 Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
10751 } x;
 
10752
10753 /* If the EP_Reduced flag is set in the Expr.flags mask, then no
10754 ** space is allocated for the fields below this point. An attempt to
10755 ** access them will result in a segfault or malfunction.
10756 *********************************************************************/
@@ -10785,11 +10782,11 @@
10782 #define EP_Error 0x0008 /* Expression contains one or more errors */
10783 #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
10784 #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
10785 #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
10786 #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
10787 #define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
10788 #define EP_FixedDest 0x0200 /* Result needed in a specific register */
10789 #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
10790 #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
10791 #define EP_Hint 0x1000 /* Not used */
10792 #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
@@ -10843,22 +10840,31 @@
10840 ** name. An expr/name combination can be used in several ways, such
10841 ** as the list of "expr AS ID" fields following a "SELECT" or in the
10842 ** list of "ID = expr" items in an UPDATE. A list of expressions can
10843 ** also be used as the argument to a function, in which case the a.zName
10844 ** field is not used.
10845 **
10846 ** By default the Expr.zSpan field holds a human-readable description of
10847 ** the expression that is used in the generation of error messages and
10848 ** column labels. In this case, Expr.zSpan is typically the text of a
10849 ** column expression as it exists in a SELECT statement. However, if
10850 ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
10851 ** of the result column in the form: DATABASE.TABLE.COLUMN. This later
10852 ** form is used for name resolution with nested FROM clauses.
10853 */
10854 struct ExprList {
10855 int nExpr; /* Number of expressions on the list */
10856 int iECursor; /* VDBE Cursor associated with this ExprList */
10857 struct ExprList_item { /* For each expression in the list */
10858 Expr *pExpr; /* The list of expressions */
10859 char *zName; /* Token associated with this expression */
10860 char *zSpan; /* Original text of the expression */
10861 u8 sortOrder; /* 1 for DESC or 0 for ASC */
10862 unsigned done :1; /* A flag to indicate when processing is finished */
10863 unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
10864 u16 iOrderByCol; /* For ORDER BY, column number in result set */
10865 u16 iAlias; /* Index into Parse.aAlias[] for zName */
10866 } *a; /* Alloc a power of two greater or equal to nExpr */
10867 };
10868
10869 /*
10870 ** An instance of this structure is used by the parser to record both
@@ -11174,10 +11180,11 @@
11180 #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
11181 #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
11182 #define SF_UseSorter 0x0040 /* Sort using a sorter */
11183 #define SF_Values 0x0080 /* Synthesized from VALUES clause */
11184 #define SF_Materialize 0x0100 /* Force materialization of views */
11185 #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
11186
11187
11188 /*
11189 ** The results of a select can be distributed in several ways. The
11190 ** "SRT" prefix means "SELECT Result Type".
@@ -11402,10 +11409,11 @@
11409 #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
11410 #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
11411 #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
11412 #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
11413 #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
11414 #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
11415
11416 /*
11417 * Each trigger present in the database schema is stored as an instance of
11418 * struct Trigger.
11419 *
@@ -11885,11 +11893,11 @@
11893 SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
11894 Token*, int, int);
11895 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
11896 SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
11897 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
11898 Expr*,ExprList*,u16,Expr*,Expr*);
11899 SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
11900 SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
11901 SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
11902 SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
11903 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -12093,12 +12101,13 @@
12101 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
12102 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
12103 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
12104 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
12105 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
12106 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
12107 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
12108 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
12109 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
12110 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
12111 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
12112 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
12113 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
@@ -12141,10 +12150,11 @@
12150 SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
12151 SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
12152 SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
12153 SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
12154 SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
12155 SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
12156 SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
12157 SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
12158 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12159 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12160 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -12279,12 +12289,14 @@
12289 #define sqlite3FkOldmask(a,b) 0
12290 #define sqlite3FkRequired(a,b,c,d) 0
12291 #endif
12292 #ifndef SQLITE_OMIT_FOREIGN_KEY
12293 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
12294 SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
12295 #else
12296 #define sqlite3FkDelete(a,b)
12297 #define sqlite3FkLocateIndex(a,b,c,d,e)
12298 #endif
12299
12300
12301 /*
12302 ** Available fault injectors. Should be numbered beginning with 0.
@@ -23287,15 +23299,11 @@
23299 { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
23300 #endif
23301 #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
23302 aSyscall[13].pCurrent)
23303
 
23304 { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
 
 
 
23305 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
23306
23307 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
23308 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
23309 #else
@@ -23316,13 +23324,10 @@
23324 #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
23325
23326 { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
23327 #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
23328
 
 
 
23329 }; /* End of the overrideable system calls */
23330
23331 /*
23332 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
23333 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -23423,31 +23428,29 @@
23428 ** process that is able to write to the database will also be able to
23429 ** recover the hot journals.
23430 */
23431 static int robust_open(const char *z, int f, mode_t m){
23432 int fd;
23433 mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
 
 
 
 
 
 
 
23434 do{
23435 #if defined(O_CLOEXEC)
23436 fd = osOpen(z,f|O_CLOEXEC,m2);
23437 #else
23438 fd = osOpen(z,f,m2);
23439 #endif
23440 }while( fd<0 && errno==EINTR );
23441 if( fd>=0 ){
23442 if( m!=0 ){
23443 struct stat statbuf;
23444 if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){
23445 osFchmod(fd, m);
23446 }
23447 }
23448 #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
23449 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
23450 #endif
23451 }
23452 return fd;
23453 }
23454
23455 /*
23456 ** Helper functions to obtain and relinquish the global mutex. The
@@ -26456,10 +26459,13 @@
26459 }else{
26460 pFile->ctrlFlags |= mask;
26461 }
26462 }
26463
26464 /* Forward declaration */
26465 static int unixGetTempname(int nBuf, char *zBuf);
26466
26467 /*
26468 ** Information and control of an open file handle.
26469 */
26470 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
26471 unixFile *pFile = (unixFile*)id;
@@ -26492,10 +26498,18 @@
26498 return SQLITE_OK;
26499 }
26500 case SQLITE_FCNTL_VFSNAME: {
26501 *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
26502 return SQLITE_OK;
26503 }
26504 case SQLITE_FCNTL_TEMPFILENAME: {
26505 char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
26506 if( zTFile ){
26507 unixGetTempname(pFile->pVfs->mxPathname, zTFile);
26508 *(char**)pArg = zTFile;
26509 }
26510 return SQLITE_OK;
26511 }
26512 #ifdef SQLITE_DEBUG
26513 /* The pager calls this method to signal that it has done
26514 ** a rollback and that the database is therefore unchanged and
26515 ** it hence it is OK for the transaction change counter to be
@@ -29858,11 +29872,11 @@
29872 };
29873 unsigned int i; /* Loop counter */
29874
29875 /* Double-check that the aSyscall[] array has been constructed
29876 ** correctly. See ticket [bb3a86e890c8e96ab] */
29877 assert( ArraySize(aSyscall)==21 );
29878
29879 /* Register all VFSes defined in the aVfs[] array */
29880 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
29881 sqlite3_vfs_register(&aVfs[i], i==0);
29882 }
@@ -32782,10 +32796,13 @@
32796 }else{
32797 pFile->ctrlFlags |= mask;
32798 }
32799 }
32800
32801 /* Forward declaration */
32802 static int getTempname(int nBuf, char *zBuf);
32803
32804 /*
32805 ** Control and query of the open file handle.
32806 */
32807 static int winFileControl(sqlite3_file *id, int op, void *pArg){
32808 winFile *pFile = (winFile*)id;
@@ -32841,10 +32858,18 @@
32858 win32IoerrRetryDelay = a[1];
32859 }else{
32860 a[1] = win32IoerrRetryDelay;
32861 }
32862 return SQLITE_OK;
32863 }
32864 case SQLITE_FCNTL_TEMPFILENAME: {
32865 char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
32866 if( zTFile ){
32867 getTempname(pFile->pVfs->mxPathname, zTFile);
32868 *(char**)pArg = zTFile;
32869 }
32870 return SQLITE_OK;
32871 }
32872 }
32873 return SQLITE_NOTFOUND;
32874 }
32875
@@ -56313,11 +56338,11 @@
56338 sqlite3BtreeLeave(p);
56339 return 0;
56340 }
56341 i = PENDING_BYTE_PAGE(pBt);
56342 if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
56343 sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
56344 sCheck.errMsg.useMalloc = 2;
56345
56346 /* Check the integrity of the freelist
56347 */
56348 checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
@@ -56848,11 +56873,16 @@
56873 /*
56874 ** Parameter zSrcData points to a buffer containing the data for
56875 ** page iSrcPg from the source database. Copy this data into the
56876 ** destination database.
56877 */
56878 static int backupOnePage(
56879 sqlite3_backup *p, /* Backup handle */
56880 Pgno iSrcPg, /* Source database page to backup */
56881 const u8 *zSrcData, /* Source database page data */
56882 int bUpdate /* True for an update, false otherwise */
56883 ){
56884 Pager * const pDestPager = sqlite3BtreePager(p->pDest);
56885 const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
56886 int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
56887 const int nCopy = MIN(nSrcPgsz, nDestPgsz);
56888 const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
@@ -56921,10 +56951,13 @@
56951 ** cached parse of the page). MemPage.isInit is marked
56952 ** "MUST BE FIRST" for this purpose.
56953 */
56954 memcpy(zOut, zIn, nCopy);
56955 ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
56956 if( iOff==0 && bUpdate==0 ){
56957 sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
56958 }
56959 }
56960 sqlite3PagerUnref(pDestPg);
56961 }
56962
56963 return rc;
@@ -57027,11 +57060,11 @@
57060 const Pgno iSrcPg = p->iNext; /* Source page number */
57061 if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
57062 DbPage *pSrcPg; /* Source page object */
57063 rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
57064 if( rc==SQLITE_OK ){
57065 rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
57066 sqlite3PagerUnref(pSrcPg);
57067 }
57068 }
57069 p->iNext++;
57070 }
@@ -57275,11 +57308,11 @@
57308 ** the new data into the backup.
57309 */
57310 int rc;
57311 assert( p->pDestDb );
57312 sqlite3_mutex_enter(p->pDestDb->mutex);
57313 rc = backupOnePage(p, iPage, aData, 1);
57314 sqlite3_mutex_leave(p->pDestDb->mutex);
57315 assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
57316 if( rc!=SQLITE_OK ){
57317 p->rc = rc;
57318 }
@@ -59392,26 +59425,22 @@
59425 assert( pKeyInfo->aSortOrder!=0 );
59426 sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
59427 i = sqlite3Strlen30(zTemp);
59428 for(j=0; j<pKeyInfo->nField; j++){
59429 CollSeq *pColl = pKeyInfo->aColl[j];
59430 const char *zColl = pColl ? pColl->zName : "nil";
59431 int n = sqlite3Strlen30(zColl);
59432 if( i+n>nTemp-6 ){
59433 memcpy(&zTemp[i],",...",4);
59434 break;
59435 }
59436 zTemp[i++] = ',';
59437 if( pKeyInfo->aSortOrder[j] ){
59438 zTemp[i++] = '-';
59439 }
59440 memcpy(&zTemp[i], zColl, n+1);
59441 i += n;
 
 
 
 
59442 }
59443 zTemp[i++] = ')';
59444 zTemp[i] = 0;
59445 assert( i<nTemp );
59446 break;
@@ -63797,11 +63826,13 @@
63826 #ifdef SQLITE_DEBUG
63827 /*
63828 ** Print the value of a register for tracing purposes:
63829 */
63830 static void memTracePrint(FILE *out, Mem *p){
63831 if( p->flags & MEM_Invalid ){
63832 fprintf(out, " undefined");
63833 }else if( p->flags & MEM_Null ){
63834 fprintf(out, " NULL");
63835 }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
63836 fprintf(out, " si:%lld", p->u.i);
63837 }else if( p->flags & MEM_Int ){
63838 fprintf(out, " i:%lld", p->u.i);
@@ -64070,10 +64101,11 @@
64101 } af;
64102 struct OP_Concat_stack_vars {
64103 i64 nByte;
64104 } ag;
64105 struct OP_Remainder_stack_vars {
64106 char bIntint; /* Started out as two integer operands */
64107 int flags; /* Combined MEM_* flags from both inputs */
64108 i64 iA; /* Integer value of left operand */
64109 i64 iB; /* Integer value of right operand */
64110 double rA; /* Real value of left operand */
64111 double rB; /* Real value of right operand */
@@ -64979,10 +65011,13 @@
65011 pOut = &aMem[pOp->p2];
65012 assert( pOut!=pIn1 );
65013 while( 1 ){
65014 sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
65015 Deephemeralize(pOut);
65016 #ifdef SQLITE_DEBUG
65017 pOut->pScopyFrom = 0;
65018 #endif
65019 REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
65020 if( (u.ae.n--)==0 ) break;
65021 pOut++;
65022 pIn1++;
65023 }
@@ -65172,10 +65207,11 @@
65207 case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
65208 case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
65209 case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
65210 case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
65211 #if 0 /* local variables moved into u.ah */
65212 char bIntint; /* Started out as two integer operands */
65213 int flags; /* Combined MEM_* flags from both inputs */
65214 i64 iA; /* Integer value of left operand */
65215 i64 iB; /* Integer value of right operand */
65216 double rA; /* Real value of left operand */
65217 double rB; /* Real value of right operand */
@@ -65189,10 +65225,11 @@
65225 u.ah.flags = pIn1->flags | pIn2->flags;
65226 if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
65227 if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
65228 u.ah.iA = pIn1->u.i;
65229 u.ah.iB = pIn2->u.i;
65230 u.ah.bIntint = 1;
65231 switch( pOp->opcode ){
65232 case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65233 case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65234 case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
65235 case OP_Divide: {
@@ -65209,10 +65246,11 @@
65246 }
65247 }
65248 pOut->u.i = u.ah.iB;
65249 MemSetTypeFlag(pOut, MEM_Int);
65250 }else{
65251 u.ah.bIntint = 0;
65252 fp_math:
65253 u.ah.rA = sqlite3VdbeRealValue(pIn1);
65254 u.ah.rB = sqlite3VdbeRealValue(pIn2);
65255 switch( pOp->opcode ){
65256 case OP_Add: u.ah.rB += u.ah.rA; break;
@@ -65240,11 +65278,11 @@
65278 if( sqlite3IsNaN(u.ah.rB) ){
65279 goto arithmetic_result_is_null;
65280 }
65281 pOut->r = u.ah.rB;
65282 MemSetTypeFlag(pOut, MEM_Real);
65283 if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
65284 sqlite3VdbeIntegerAffinity(pOut);
65285 }
65286 #endif
65287 }
65288 break;
@@ -65801,26 +65839,31 @@
65839 /* Opcode: Permutation * * * P4 *
65840 **
65841 ** Set the permutation used by the OP_Compare operator to be the array
65842 ** of integers in P4.
65843 **
65844 ** The permutation is only valid until the next OP_Compare that has
65845 ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
65846 ** occur immediately prior to the OP_Compare.
65847 */
65848 case OP_Permutation: {
65849 assert( pOp->p4type==P4_INTARRAY );
65850 assert( pOp->p4.ai );
65851 aPermute = pOp->p4.ai;
65852 break;
65853 }
65854
65855 /* Opcode: Compare P1 P2 P3 P4 P5
65856 **
65857 ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
65858 ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
65859 ** the comparison for use by the next OP_Jump instruct.
65860 **
65861 ** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
65862 ** determined by the most recent OP_Permutation operator. If the
65863 ** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
65864 ** order.
65865 **
65866 ** P4 is a KeyInfo structure that defines collating sequences and sort
65867 ** orders for the comparison. The permutation applies to registers
65868 ** only. The KeyInfo elements are used sequentially.
65869 **
@@ -65838,10 +65881,11 @@
65881 int idx;
65882 CollSeq *pColl; /* Collating sequence to use on this term */
65883 int bRev; /* True for DESCENDING sort order */
65884 #endif /* local variables moved into u.al */
65885
65886 if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
65887 u.al.n = pOp->p3;
65888 u.al.pKeyInfo = pOp->p4.pKeyInfo;
65889 assert( u.al.n>0 );
65890 assert( u.al.pKeyInfo!=0 );
65891 u.al.p1 = pOp->p1;
@@ -65983,12 +66027,10 @@
66027
66028 /* Opcode: Once P1 P2 * * *
66029 **
66030 ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
66031 ** set the flag and fall through to the next instruction.
 
 
66032 */
66033 case OP_Once: { /* jump */
66034 assert( pOp->p1<p->nOnceFlag );
66035 if( p->aOnceFlag[pOp->p1] ){
66036 pc = pOp->p2-1;
@@ -71860,10 +71902,18 @@
71902 p->pReal = pReal;
71903 if( p->iSize>0 ){
71904 assert(p->iSize<=p->nBuf);
71905 rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
71906 }
71907 if( rc!=SQLITE_OK ){
71908 /* If an error occurred while writing to the file, close it before
71909 ** returning. This way, SQLite uses the in-memory journal data to
71910 ** roll back changes made to the internal page-cache before this
71911 ** function was called. */
71912 sqlite3OsClose(pReal);
71913 p->pReal = 0;
71914 }
71915 }
71916 }
71917 return rc;
71918 }
71919
@@ -72523,10 +72573,19 @@
72573 ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
72574 **
72575 ** The result of random()%5 in the GROUP BY clause is probably different
72576 ** from the result in the result-set. We might fix this someday. Or
72577 ** then again, we might not...
72578 **
72579 ** If the reference is followed by a COLLATE operator, then make sure
72580 ** the COLLATE operator is preserved. For example:
72581 **
72582 ** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
72583 **
72584 ** Should be transformed into:
72585 **
72586 ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
72587 **
72588 ** The nSubquery parameter specifies how many levels of subquery the
72589 ** alias is removed from the original expression. The usually value is
72590 ** zero but it might be more if the alias is contained within a subquery
72591 ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
@@ -72547,45 +72606,40 @@
72606 assert( iCol>=0 && iCol<pEList->nExpr );
72607 pOrig = pEList->a[iCol].pExpr;
72608 assert( pOrig!=0 );
72609 assert( pOrig->flags & EP_Resolved );
72610 db = pParse->db;
72611 pDup = sqlite3ExprDup(db, pOrig, 0);
72612 if( pDup==0 ) return;
72613 if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
 
72614 incrAggFunctionDepth(pDup, nSubquery);
72615 pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
72616 if( pDup==0 ) return;
72617 if( pEList->a[iCol].iAlias==0 ){
72618 pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
72619 }
72620 pDup->iTable = pEList->a[iCol].iAlias;
72621 }
72622 if( pExpr->op==TK_COLLATE ){
72623 pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72624 }
72625
72626 /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
72627 ** prevents ExprDelete() from deleting the Expr structure itself,
72628 ** allowing it to be repopulated by the memcpy() on the following line.
72629 ** The pExpr->u.zToken might point into memory that will be freed by the
72630 ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
72631 ** make a copy of the token before doing the sqlite3DbFree().
72632 */
72633 ExprSetProperty(pExpr, EP_Static);
72634 sqlite3ExprDelete(db, pExpr);
72635 memcpy(pExpr, pDup, sizeof(*pExpr));
72636 if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
72637 assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
72638 pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
72639 pExpr->flags2 |= EP2_MallocedToken;
72640 }
72641 sqlite3DbFree(db, pDup);
72642 }
72643
72644
72645 /*
@@ -72602,10 +72656,39 @@
72656 }
72657 }
72658 return 0;
72659 }
72660
72661 /*
72662 ** Subqueries stores the original database, table and column names for their
72663 ** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
72664 ** Check to see if the zSpan given to this routine matches the zDb, zTab,
72665 ** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
72666 ** match anything.
72667 */
72668 SQLITE_PRIVATE int sqlite3MatchSpanName(
72669 const char *zSpan,
72670 const char *zCol,
72671 const char *zTab,
72672 const char *zDb
72673 ){
72674 int n;
72675 for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
72676 if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){
72677 return 0;
72678 }
72679 zSpan += n+1;
72680 for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
72681 if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){
72682 return 0;
72683 }
72684 zSpan += n+1;
72685 if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
72686 return 0;
72687 }
72688 return 1;
72689 }
72690
72691 /*
72692 ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
72693 ** that name in the set of source tables in pSrcList and make the pExpr
72694 ** expression node refer back to that source column. The following changes
@@ -72657,44 +72740,63 @@
72740
72741 /* Initialize the node to no-match */
72742 pExpr->iTable = -1;
72743 pExpr->pTab = 0;
72744 ExprSetIrreducible(pExpr);
72745
72746 /* Translate the schema name in zDb into a pointer to the corresponding
72747 ** schema. If not found, pSchema will remain NULL and nothing will match
72748 ** resulting in an appropriate error message toward the end of this routine
72749 */
72750 if( zDb ){
72751 for(i=0; i<db->nDb; i++){
72752 assert( db->aDb[i].zName );
72753 if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
72754 pSchema = db->aDb[i].pSchema;
72755 break;
72756 }
72757 }
72758 }
72759
72760 /* Start at the inner-most context and move outward until a match is found */
72761 while( pNC && cnt==0 ){
72762 ExprList *pEList;
72763 SrcList *pSrcList = pNC->pSrcList;
72764
72765 if( pSrcList ){
72766 for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
72767 Table *pTab;
 
72768 Column *pCol;
72769
72770 pTab = pItem->pTab;
72771 assert( pTab!=0 && pTab->zName!=0 );
 
72772 assert( pTab->nCol>0 );
72773 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
72774 ExprList *pEList = pItem->pSelect->pEList;
72775 int hit = 0;
72776 for(j=0; j<pEList->nExpr; j++){
72777 if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
72778 cnt++;
72779 cntTab = 2;
72780 pMatch = pItem;
72781 pExpr->iColumn = j;
72782 hit = 1;
72783 }
72784 }
72785 if( hit || zTab==0 ) continue;
72786 }
72787 if( zDb && pTab->pSchema!=pSchema ){
72788 continue;
72789 }
72790 if( zTab ){
72791 const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
72792 assert( zTabName!=0 );
72793 if( sqlite3StrICmp(zTabName, zTab)!=0 ){
72794 continue;
 
 
 
 
 
 
 
72795 }
72796 }
72797 if( 0==(cntTab++) ){
 
 
 
72798 pMatch = pItem;
72799 }
72800 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
72801 if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
72802 /* If there has been exactly one prior match and this match
@@ -72704,21 +72806,23 @@
72806 if( cnt==1 ){
72807 if( pItem->jointype & JT_NATURAL ) continue;
72808 if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
72809 }
72810 cnt++;
 
 
72811 pMatch = pItem;
 
72812 /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
72813 pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
72814 break;
72815 }
72816 }
72817 }
72818 if( pMatch ){
72819 pExpr->iTable = pMatch->iCursor;
72820 pExpr->pTab = pMatch->pTab;
72821 pSchema = pExpr->pTab->pSchema;
72822 }
72823 } /* if( pSrcList ) */
72824
72825 #ifndef SQLITE_OMIT_TRIGGER
72826 /* If we have not already resolved the name, then maybe
72827 ** it is a new.* or old.* trigger argument reference
72828 */
@@ -73013,42 +73117,43 @@
73117 int wrong_num_args = 0; /* True if wrong number of arguments */
73118 int is_agg = 0; /* True if is an aggregate function */
73119 int auth; /* Authorization to use the function */
73120 int nId; /* Number of characters in function name */
73121 const char *zId; /* The function name. */
 
73122 u8 enc = ENC(pParse->db); /* The database encoding */
73123
73124 testcase( pExpr->op==TK_CONST_FUNC );
73125 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
73126 zId = pExpr->u.zToken;
73127 nId = sqlite3Strlen30(zId);
73128 if( pParse->db->init.busy==0 ){
73129 FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
73130 if( pDef==0 ){
73131 pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
73132 if( pDef==0 ){
73133 no_such_func = 1;
73134 }else{
73135 wrong_num_args = 1;
73136 }
73137 }else{
73138 is_agg = pDef->xFunc==0;
73139 }
73140 #ifndef SQLITE_OMIT_AUTHORIZATION
73141 if( pDef ){
73142 auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
73143 if( auth!=SQLITE_OK ){
73144 if( auth==SQLITE_DENY ){
73145 sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
73146 pDef->zName);
73147 pNC->nErr++;
73148 }
73149 pExpr->op = TK_NULL;
73150 return WRC_Prune;
73151 }
73152 }
73153 #endif
73154 }
73155 if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
73156 sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
73157 pNC->nErr++;
73158 is_agg = 0;
73159 }else if( no_such_func ){
@@ -73268,11 +73373,11 @@
73373 assert( pEList!=0 );
73374 for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
73375 int iCol = -1;
73376 Expr *pE, *pDup;
73377 if( pItem->done ) continue;
73378 pE = sqlite3ExprSkipCollate(pItem->pExpr);
73379 if( sqlite3ExprIsInteger(pE, &iCol) ){
73380 if( iCol<=0 || iCol>pEList->nExpr ){
73381 resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
73382 return 1;
73383 }
@@ -73286,18 +73391,24 @@
73391 }
73392 sqlite3ExprDelete(db, pDup);
73393 }
73394 }
73395 if( iCol>0 ){
73396 /* Convert the ORDER BY term into an integer column number iCol,
73397 ** taking care to preserve the COLLATE clause if it exists */
73398 Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
73399 if( pNew==0 ) return 1;
73400 pNew->flags |= EP_IntValue;
73401 pNew->u.iValue = iCol;
73402 if( pItem->pExpr==pE ){
73403 pItem->pExpr = pNew;
73404 }else{
73405 assert( pItem->pExpr->op==TK_COLLATE );
73406 assert( pItem->pExpr->pLeft==pE );
73407 pItem->pExpr->pLeft = pNew;
73408 }
73409 sqlite3ExprDelete(db, pE);
 
 
 
 
 
73410 pItem->iOrderByCol = (u16)iCol;
73411 pItem->done = 1;
73412 }else{
73413 moreToDo = 1;
73414 }
@@ -73398,15 +73509,15 @@
73509 ** sqlite3ResolveOrderGroupBy() will convert the expression to a
73510 ** copy of the iCol-th result-set expression. */
73511 pItem->iOrderByCol = (u16)iCol;
73512 continue;
73513 }
73514 if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
73515 /* The ORDER BY term is an integer constant. Again, set the column
73516 ** number so that sqlite3ResolveOrderGroupBy() will convert the
73517 ** order-by term to a copy of the result-set expression */
73518 if( iCol<1 || iCol>0xffff ){
73519 resolveOutOfRangeError(pParse, zType, i+1, nResult);
73520 return 1;
73521 }
73522 pItem->iOrderByCol = (u16)iCol;
73523 continue;
@@ -73479,27 +73590,10 @@
73590 if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
73591 sqlite3ResolveExprNames(&sNC, p->pOffset) ){
73592 return WRC_Abort;
73593 }
73594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73595 /* Recursively resolve names in all subqueries
73596 */
73597 for(i=0; i<p->pSrc->nSrc; i++){
73598 struct SrcList_item *pItem = &p->pSrc->a[i];
73599 if( pItem->pSelect ){
@@ -73522,10 +73616,27 @@
73616 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
73617 assert( pItem->isCorrelated==0 && nRef<=0 );
73618 pItem->isCorrelated = (nRef!=0);
73619 }
73620 }
73621
73622 /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
73623 ** resolve the result-set expression list.
73624 */
73625 sNC.ncFlags = NC_AllowAgg;
73626 sNC.pSrcList = p->pSrc;
73627 sNC.pNext = pOuterNC;
73628
73629 /* Resolve names in the result set. */
73630 pEList = p->pEList;
73631 assert( pEList!=0 );
73632 for(i=0; i<pEList->nExpr; i++){
73633 Expr *pX = pEList->a[i].pExpr;
73634 if( sqlite3ResolveExprNames(&sNC, pX) ){
73635 return WRC_Abort;
73636 }
73637 }
73638
73639 /* If there are no aggregate functions in the result-set, and no GROUP BY
73640 ** expression, do not allow aggregates in any of the other expressions.
73641 */
73642 assert( (p->selFlags & SF_Aggregate)==0 );
@@ -73756,11 +73867,13 @@
73867 ** SELECT * FROM t1 WHERE a;
73868 ** SELECT a AS b FROM t1 WHERE b;
73869 ** SELECT * FROM t1 WHERE (select a from t1);
73870 */
73871 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
73872 int op;
73873 pExpr = sqlite3ExprSkipCollate(pExpr);
73874 op = pExpr->op;
73875 if( op==TK_SELECT ){
73876 assert( pExpr->flags&EP_xIsSelect );
73877 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
73878 }
73879 #ifndef SQLITE_OMIT_CAST
@@ -73781,70 +73894,98 @@
73894 }
73895 return pExpr->affinity;
73896 }
73897
73898 /*
73899 ** Set the collating sequence for expression pExpr to be the collating
73900 ** sequence named by pToken. Return a pointer to a new Expr node that
73901 ** implements the COLLATE operator.
73902 **
73903 ** If a memory allocation error occurs, that fact is recorded in pParse->db
73904 ** and the pExpr parameter is returned unchanged.
73905 */
73906 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
73907 if( pCollName->n>0 ){
73908 Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
73909 if( pNew ){
73910 pNew->pLeft = pExpr;
73911 pNew->flags |= EP_Collate;
73912 pExpr = pNew;
73913 }
73914 }
73915 return pExpr;
73916 }
73917 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
73918 Token s;
73919 assert( zC!=0 );
73920 s.z = zC;
73921 s.n = sqlite3Strlen30(s.z);
73922 return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
73923 }
73924
73925 /*
73926 ** Skip over any TK_COLLATE and/or TK_AS operators at the root of
73927 ** an expression.
73928 */
73929 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
73930 while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
73931 pExpr = pExpr->pLeft;
73932 }
73933 return pExpr;
73934 }
73935
73936 /*
73937 ** Return the collation sequence for the expression pExpr. If
73938 ** there is no defined collating sequence, return NULL.
73939 **
73940 ** The collating sequence might be determined by a COLLATE operator
73941 ** or by the presence of a column with a defined collating sequence.
73942 ** COLLATE operators take first precedence. Left operands take
73943 ** precedence over right operands.
73944 */
73945 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
73946 sqlite3 *db = pParse->db;
73947 CollSeq *pColl = 0;
73948 Expr *p = pExpr;
73949 while( p ){
73950 int op = p->op;
73951 if( op==TK_CAST || op==TK_UPLUS ){
73952 p = p->pLeft;
73953 continue;
73954 }
73955 assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
73956 if( op==TK_COLLATE ){
73957 if( db->init.busy ){
73958 /* Do not report errors when parsing while the schema */
73959 pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
73960 }else{
73961 pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
73962 }
73963 break;
73964 }
73965 if( p->pTab!=0
73966 && (op==TK_AGG_COLUMN || op==TK_COLUMN
73967 || op==TK_REGISTER || op==TK_TRIGGER)
73968 ){
73969 /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
73970 ** a TK_COLUMN but was previously evaluated and cached in a register */
73971 int j = p->iColumn;
73972 if( j>=0 ){
73973 const char *zColl = p->pTab->aCol[j].zColl;
73974 pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
73975 }
73976 break;
73977 }
73978 if( p->flags & EP_Collate ){
73979 if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
73980 p = p->pLeft;
73981 }else{
73982 p = p->pRight;
73983 }
73984 }else{
73985 break;
73986 }
73987 }
73988 if( sqlite3CheckCollSeq(pParse, pColl) ){
73989 pColl = 0;
73990 }
73991 return pColl;
@@ -73944,16 +74085,14 @@
74085 Expr *pLeft,
74086 Expr *pRight
74087 ){
74088 CollSeq *pColl;
74089 assert( pLeft );
74090 if( pLeft->flags & EP_Collate ){
74091 pColl = sqlite3ExprCollSeq(pParse, pLeft);
74092 }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
74093 pColl = sqlite3ExprCollSeq(pParse, pRight);
 
 
74094 }else{
74095 pColl = sqlite3ExprCollSeq(pParse, pLeft);
74096 if( !pColl ){
74097 pColl = sqlite3ExprCollSeq(pParse, pRight);
74098 }
@@ -74179,21 +74318,15 @@
74318 sqlite3ExprDelete(db, pLeft);
74319 sqlite3ExprDelete(db, pRight);
74320 }else{
74321 if( pRight ){
74322 pRoot->pRight = pRight;
74323 pRoot->flags |= EP_Collate & pRight->flags;
 
 
 
74324 }
74325 if( pLeft ){
74326 pRoot->pLeft = pLeft;
74327 pRoot->flags |= EP_Collate & pLeft->flags;
 
 
 
74328 }
74329 exprSetHeight(pRoot);
74330 }
74331 }
74332
@@ -74447,11 +74580,11 @@
74580 }else{
74581 assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
74582 assert( !ExprHasProperty(p, EP_FromJoin) );
74583 assert( (p->flags2 & EP2_MallocedToken)==0 );
74584 assert( (p->flags2 & EP2_Irreducible)==0 );
74585 if( p->pLeft || p->pRight || p->x.pList ){
74586 nSize = EXPR_REDUCEDSIZE | EP_Reduced;
74587 }else{
74588 nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
74589 }
74590 }
@@ -76471,10 +76604,11 @@
76604 sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
76605 sqlite3ReleaseTempReg(pParse, r3);
76606 sqlite3ReleaseTempReg(pParse, r4);
76607 break;
76608 }
76609 case TK_COLLATE:
76610 case TK_UPLUS: {
76611 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
76612 break;
76613 }
76614
@@ -76839,10 +76973,16 @@
76973 case TK_UPLUS: zUniOp = "UPLUS"; break;
76974 case TK_BITNOT: zUniOp = "BITNOT"; break;
76975 case TK_NOT: zUniOp = "NOT"; break;
76976 case TK_ISNULL: zUniOp = "ISNULL"; break;
76977 case TK_NOTNULL: zUniOp = "NOTNULL"; break;
76978
76979 case TK_COLLATE: {
76980 sqlite3ExplainExpr(pOut, pExpr->pLeft);
76981 sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
76982 break;
76983 }
76984
76985 case TK_AGG_FUNCTION:
76986 case TK_CONST_FUNC:
76987 case TK_FUNCTION: {
76988 ExprList *pFarg; /* List of function arguments */
@@ -76977,10 +77117,16 @@
77117 for(i=0; i<pList->nExpr; i++){
77118 sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
77119 sqlite3ExplainPush(pOut);
77120 sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
77121 sqlite3ExplainPop(pOut);
77122 if( pList->a[i].zName ){
77123 sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
77124 }
77125 if( pList->a[i].bSpanIsTab ){
77126 sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
77127 }
77128 if( i<pList->nExpr-1 ){
77129 sqlite3ExplainNL(pOut);
77130 }
77131 }
77132 sqlite3ExplainPop(pOut);
@@ -77058,10 +77204,13 @@
77204 switch( pExpr->op ){
77205 case TK_IN:
77206 case TK_REGISTER: {
77207 return WRC_Prune;
77208 }
77209 case TK_COLLATE: {
77210 return WRC_Continue;
77211 }
77212 case TK_FUNCTION:
77213 case TK_AGG_FUNCTION:
77214 case TK_CONST_FUNC: {
77215 /* The arguments to a function have a fixed destination.
77216 ** Mark them this way to avoid generated unneeded OP_SCopy
@@ -77079,13 +77228,15 @@
77228 break;
77229 }
77230 }
77231 if( isAppropriateForFactoring(pExpr) ){
77232 int r1 = ++pParse->nMem;
77233 int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
77234 /* If r2!=r1, it means that register r1 is never used. That is harmless
77235 ** but suboptimal, so we want to know about the situation to fix it.
77236 ** Hence the following assert: */
77237 assert( r2==r1 );
77238 pExpr->op2 = pExpr->op;
77239 pExpr->op = TK_REGISTER;
77240 pExpr->iTable = r2;
77241 return WRC_Prune;
77242 }
@@ -77498,11 +77649,19 @@
77649 assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
77650 if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
77651 return 2;
77652 }
77653 if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
77654 if( pA->op!=pB->op ){
77655 if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
77656 return 1;
77657 }
77658 if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
77659 return 1;
77660 }
77661 return 2;
77662 }
77663 if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
77664 if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
77665 if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
77666 if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
77667 if( ExprHasProperty(pA, EP_IntValue) ){
@@ -77510,15 +77669,13 @@
77669 return 2;
77670 }
77671 }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
77672 if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
77673 if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
77674 return pA->op==TK_COLLATE ? 1 : 2;
77675 }
77676 }
 
 
77677 return 0;
77678 }
77679
77680 /*
77681 ** Compare two ExprList objects. Return 0 if they are identical and
@@ -80765,10 +80922,11 @@
80922 */
80923 SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
80924 sqlite3 *db;
80925 Vdbe *v;
80926
80927 assert( pParse->pToplevel==0 );
80928 db = pParse->db;
80929 if( db->mallocFailed ) return;
80930 if( pParse->nested ) return;
80931 if( pParse->nErr ) return;
80932
@@ -83328,14 +83486,12 @@
83486 ** specified collation sequence names.
83487 */
83488 for(i=0; i<pList->nExpr; i++){
83489 Expr *pExpr = pList->a[i].pExpr;
83490 if( pExpr ){
83491 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
83492 if( pColl ){
 
 
83493 nExtra += (1 + sqlite3Strlen30(pColl->zName));
83494 }
83495 }
83496 }
83497
@@ -83394,10 +83550,11 @@
83550 */
83551 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
83552 const char *zColName = pListItem->zName;
83553 Column *pTabCol;
83554 int requestedSortOrder;
83555 CollSeq *pColl; /* Collating sequence */
83556 char *zColl; /* Collation sequence name */
83557
83558 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
83559 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
83560 }
@@ -83406,18 +83563,15 @@
83563 pTab->zName, zColName);
83564 pParse->checkSchema = 1;
83565 goto exit_create_index;
83566 }
83567 pIndex->aiColumn[i] = j;
83568 if( pListItem->pExpr
83569 && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
83570 ){
 
 
 
83571 int nColl;
83572 zColl = pColl->zName;
83573 nColl = sqlite3Strlen30(zColl) + 1;
83574 assert( nExtra>=nColl );
83575 memcpy(zExtra, zColl, nColl);
83576 zColl = zExtra;
83577 zExtra += nColl;
@@ -84227,10 +84381,19 @@
84381 ** early in the code, before we know if any database tables will be used.
84382 */
84383 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
84384 Parse *pToplevel = sqlite3ParseToplevel(pParse);
84385
84386 #ifndef SQLITE_OMIT_TRIGGER
84387 if( pToplevel!=pParse ){
84388 /* This branch is taken if a trigger is currently being coded. In this
84389 ** case, set cookieGoto to a non-zero value to show that this function
84390 ** has been called. This is used by the sqlite3ExprCodeConstants()
84391 ** function. */
84392 pParse->cookieGoto = -1;
84393 }
84394 #endif
84395 if( pToplevel->cookieGoto==0 ){
84396 Vdbe *v = sqlite3GetVdbe(pToplevel);
84397 if( v==0 ) return; /* This only happens if there was a prior error */
84398 pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
84399 }
@@ -87437,11 +87600,11 @@
87600
87601 /*
87602 ** A foreign key constraint requires that the key columns in the parent
87603 ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
87604 ** Given that pParent is the parent table for foreign key constraint pFKey,
87605 ** search the schema for a unique index on the parent key columns.
87606 **
87607 ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
87608 ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
87609 ** is set to point to the unique index.
87610 **
@@ -87473,11 +87636,11 @@
87636 **
87637 ** then non-zero is returned, and a "foreign key mismatch" error loaded
87638 ** into pParse. If an OOM error occurs, non-zero is returned and the
87639 ** pParse->db->mallocFailed flag is set.
87640 */
87641 SQLITE_PRIVATE int sqlite3FkLocateIndex(
87642 Parse *pParse, /* Parse context to store any error in */
87643 Table *pParent, /* Parent table of FK constraint pFKey */
87644 FKey *pFKey, /* Foreign key to find index for */
87645 Index **ppIdx, /* OUT: Unique index on parent table */
87646 int **paiCol /* OUT: Map of index columns in pFKey */
@@ -87570,11 +87733,13 @@
87733 }
87734 }
87735
87736 if( !pIdx ){
87737 if( !pParse->disableTriggers ){
87738 sqlite3ErrorMsg(pParse,
87739 "foreign key mismatch - \"%w\" referencing \"%w\"",
87740 pFKey->pFrom->zName, pFKey->zTo);
87741 }
87742 sqlite3DbFree(pParse->db, aiCol);
87743 return 1;
87744 }
87745
@@ -87806,16 +87971,19 @@
87971 if( pLeft ){
87972 /* Set the collation sequence and affinity of the LHS of each TK_EQ
87973 ** expression to the parent key column defaults. */
87974 if( pIdx ){
87975 Column *pCol;
87976 const char *zColl;
87977 iCol = pIdx->aiColumn[i];
87978 pCol = &pTab->aCol[iCol];
87979 if( pTab->iPKey==iCol ) iCol = -1;
87980 pLeft->iTable = regData+iCol+1;
87981 pLeft->affinity = pCol->affinity;
87982 zColl = pCol->zColl;
87983 if( zColl==0 ) zColl = db->pDfltColl->zName;
87984 pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
87985 }else{
87986 pLeft->iTable = regData;
87987 pLeft->affinity = SQLITE_AFF_INTEGER;
87988 }
87989 }
@@ -88028,11 +88196,11 @@
88196 if( pParse->disableTriggers ){
88197 pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
88198 }else{
88199 pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
88200 }
88201 if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
88202 assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
88203 if( !isIgnoreErrors || db->mallocFailed ) return;
88204 if( pTo==0 ){
88205 /* If isIgnoreErrors is true, then a table is being dropped. In this
88206 ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
@@ -88108,11 +88276,11 @@
88276 /* Inserting a single row into a parent table cannot cause an immediate
88277 ** foreign key violation. So do nothing in this case. */
88278 continue;
88279 }
88280
88281 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
88282 if( !isIgnoreErrors || db->mallocFailed ) return;
88283 continue;
88284 }
88285 assert( aiCol || pFKey->nCol==1 );
88286
@@ -88163,11 +88331,11 @@
88331 for(p=pTab->pFKey; p; p=p->pNextFrom){
88332 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
88333 }
88334 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
88335 Index *pIdx = 0;
88336 sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
88337 if( pIdx ){
88338 for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
88339 }
88340 }
88341 }
@@ -88289,11 +88457,11 @@
88457 ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
88458 Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
88459 int i; /* Iterator variable */
88460 Expr *pWhen = 0; /* WHEN clause for the trigger */
88461
88462 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
88463 assert( aiCol || pFKey->nCol==1 );
88464
88465 for(i=0; i<pFKey->nCol; i++){
88466 Token tOld = { "old", 3 }; /* Literal "old" token */
88467 Token tNew = { "new", 3 }; /* Literal "new" token */
@@ -89791,29 +89959,24 @@
89959 ExprList *pCheck = pTab->pCheck;
89960 pParse->ckBase = regData;
89961 onError = overrideError!=OE_Default ? overrideError : OE_Abort;
89962 for(i=0; i<pCheck->nExpr; i++){
89963 int allOk = sqlite3VdbeMakeLabel(v);
89964 sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
89965 if( onError==OE_Ignore ){
89966 sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
89967 }else{
89968 char *zConsName = pCheck->a[i].zName;
89969 if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
89970 if( zConsName ){
89971 zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
89972 }else{
89973 zConsName = 0;
89974 }
89975 sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
89976 }
89977 sqlite3VdbeResolveLabel(v, allOk);
 
 
 
 
 
89978 }
89979 }
89980 #endif /* !defined(SQLITE_OMIT_CHECK) */
89981
89982 /* If we have an INTEGER PRIMARY KEY, make sure the primary key
@@ -92634,13 +92797,15 @@
92797 if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
92798 Table *pTab;
92799 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
92800 pTab = sqlite3FindTable(db, zRight, zDb);
92801 if( pTab ){
92802 int i, k;
92803 int nHidden = 0;
92804 Column *pCol;
92805 Index *pPk;
92806 for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
92807 sqlite3VdbeSetNumCols(v, 6);
92808 pParse->nMem = 6;
92809 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
92810 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
92811 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92661,12 +92826,18 @@
92826 if( pCol->zDflt ){
92827 sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
92828 }else{
92829 sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
92830 }
92831 if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
92832 k = 0;
92833 }else if( pPk==0 ){
92834 k = 1;
92835 }else{
92836 for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
92837 }
92838 sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
92839 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
92840 }
92841 }
92842 }else
92843
@@ -92797,10 +92968,124 @@
92968 ++i;
92969 pFK = pFK->pNextFrom;
92970 }
92971 }
92972 }
92973 }else
92974 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
92975
92976 #ifndef SQLITE_OMIT_FOREIGN_KEY
92977 if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
92978 FKey *pFK; /* A foreign key constraint */
92979 Table *pTab; /* Child table contain "REFERENCES" keyword */
92980 Table *pParent; /* Parent table that child points to */
92981 Index *pIdx; /* Index in the parent table */
92982 int i; /* Loop counter: Foreign key number for pTab */
92983 int j; /* Loop counter: Field of the foreign key */
92984 HashElem *k; /* Loop counter: Next table in schema */
92985 int x; /* result variable */
92986 int regResult; /* 3 registers to hold a result row */
92987 int regKey; /* Register to hold key for checking the FK */
92988 int regRow; /* Registers to hold a row from pTab */
92989 int addrTop; /* Top of a loop checking foreign keys */
92990 int addrOk; /* Jump here if the key is OK */
92991 int *aiCols; /* child to parent column mapping */
92992
92993 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
92994 regResult = pParse->nMem+1;
92995 pParse->nMem += 4;
92996 regKey = ++pParse->nMem;
92997 regRow = ++pParse->nMem;
92998 v = sqlite3GetVdbe(pParse);
92999 sqlite3VdbeSetNumCols(v, 4);
93000 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
93001 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
93002 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
93003 sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
93004 sqlite3CodeVerifySchema(pParse, iDb);
93005 k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
93006 while( k ){
93007 if( zRight ){
93008 pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
93009 k = 0;
93010 }else{
93011 pTab = (Table*)sqliteHashData(k);
93012 k = sqliteHashNext(k);
93013 }
93014 if( pTab==0 || pTab->pFKey==0 ) continue;
93015 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
93016 if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
93017 sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
93018 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
93019 P4_TRANSIENT);
93020 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
93021 pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
93022 if( pParent==0 ) break;
93023 pIdx = 0;
93024 sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
93025 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
93026 if( x==0 ){
93027 if( pIdx==0 ){
93028 sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
93029 }else{
93030 KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
93031 sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
93032 sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
93033 }
93034 }else{
93035 k = 0;
93036 break;
93037 }
93038 }
93039 if( pFK ) break;
93040 if( pParse->nTab<i ) pParse->nTab = i;
93041 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
93042 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
93043 pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
93044 assert( pParent!=0 );
93045 pIdx = 0;
93046 aiCols = 0;
93047 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
93048 assert( x==0 );
93049 addrOk = sqlite3VdbeMakeLabel(v);
93050 if( pIdx==0 ){
93051 int iKey = pFK->aCol[0].iFrom;
93052 assert( iKey>=0 && iKey<pTab->nCol );
93053 if( iKey!=pTab->iPKey ){
93054 sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
93055 sqlite3ColumnDefault(v, pTab, iKey, regRow);
93056 sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
93057 sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
93058 sqlite3VdbeCurrentAddr(v)+3);
93059 }else{
93060 sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
93061 }
93062 sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
93063 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
93064 sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
93065 }else{
93066 for(j=0; j<pFK->nCol; j++){
93067 sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
93068 aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
93069 sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
93070 }
93071 sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
93072 sqlite3VdbeChangeP4(v, -1,
93073 sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
93074 sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
93075 }
93076 sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
93077 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
93078 pFK->zTo, P4_TRANSIENT);
93079 sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
93080 sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
93081 sqlite3VdbeResolveLabel(v, addrOk);
93082 sqlite3DbFree(db, aiCols);
93083 }
93084 sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
93085 sqlite3VdbeJumpHere(v, addrTop);
93086 }
93087 }else
93088 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
93089
93090 #ifndef NDEBUG
93091 if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -94256,11 +94541,11 @@
94541 SrcList *pSrc, /* the FROM clause -- which tables to scan */
94542 Expr *pWhere, /* the WHERE clause */
94543 ExprList *pGroupBy, /* the GROUP BY clause */
94544 Expr *pHaving, /* the HAVING clause */
94545 ExprList *pOrderBy, /* the ORDER BY clause */
94546 u16 selFlags, /* Flag parameters, such as SF_Distinct */
94547 Expr *pLimit, /* LIMIT value. NULL means not used */
94548 Expr *pOffset /* OFFSET value. NULL means no offset */
94549 ){
94550 Select *pNew;
94551 Select standin;
@@ -94280,11 +94565,11 @@
94565 pNew->pSrc = pSrc;
94566 pNew->pWhere = pWhere;
94567 pNew->pGroupBy = pGroupBy;
94568 pNew->pHaving = pHaving;
94569 pNew->pOrderBy = pOrderBy;
94570 pNew->selFlags = selFlags;
94571 pNew->op = TK_SELECT;
94572 pNew->pLimit = pLimit;
94573 pNew->pOffset = pOffset;
94574 assert( pOffset==0 || pLimit!=0 );
94575 pNew->addrOpenEphm[0] = -1;
@@ -95536,13 +95821,11 @@
95821 *paCol = aCol;
95822
95823 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
95824 /* Get an appropriate name for the column
95825 */
95826 p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
 
 
95827 if( (zName = pEList->a[i].zName)!=0 ){
95828 /* If the column contains an "AS <name>" phrase, use <name> as the name */
95829 zName = sqlite3DbStrDup(db, zName);
95830 }else{
95831 Expr *pColExpr = p; /* The expression that is the result column name */
@@ -95576,10 +95859,13 @@
95859 */
95860 nName = sqlite3Strlen30(zName);
95861 for(j=cnt=0; j<i; j++){
95862 if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
95863 char *zNewName;
95864 int k;
95865 for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
95866 if( zName[k]==':' ) nName = k;
95867 zName[nName] = 0;
95868 zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
95869 sqlite3DbFree(db, zName);
95870 zName = zNewName;
95871 j = -1;
@@ -96534,16 +96820,17 @@
96820 pKeyMerge->nField = (u16)nOrderBy;
96821 pKeyMerge->enc = ENC(db);
96822 for(i=0; i<nOrderBy; i++){
96823 CollSeq *pColl;
96824 Expr *pTerm = pOrderBy->a[i].pExpr;
96825 if( pTerm->flags & EP_Collate ){
96826 pColl = sqlite3ExprCollSeq(pParse, pTerm);
96827 }else{
96828 pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
96829 if( pColl==0 ) pColl = db->pDfltColl;
96830 pOrderBy->a[i].pExpr =
96831 sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
96832 }
96833 pKeyMerge->aColl[i] = pColl;
96834 pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
96835 }
96836 }
@@ -96742,10 +97029,11 @@
97029 */
97030 sqlite3VdbeResolveLabel(v, labelCmpr);
97031 sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
97032 sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
97033 (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
97034 sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
97035 sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
97036
97037 /* Release temporary registers
97038 */
97039 if( regPrev ){
@@ -96809,13 +97097,10 @@
97097 }else{
97098 Expr *pNew;
97099 assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
97100 assert( pExpr->pLeft==0 && pExpr->pRight==0 );
97101 pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
 
 
 
97102 sqlite3ExprDelete(db, pExpr);
97103 pExpr = pNew;
97104 }
97105 }else{
97106 pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
@@ -97362,38 +97647,47 @@
97647 return 1;
97648 }
97649 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
97650
97651 /*
97652 ** Based on the contents of the AggInfo structure indicated by the first
97653 ** argument, this function checks if the following are true:
97654 **
97655 ** * the query contains just a single aggregate function,
97656 ** * the aggregate function is either min() or max(), and
97657 ** * the argument to the aggregate function is a column value.
97658 **
97659 ** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
97660 ** is returned as appropriate. Also, *ppMinMax is set to point to the
97661 ** list of arguments passed to the aggregate before returning.
97662 **
97663 ** Or, if the conditions above are not met, *ppMinMax is set to 0 and
97664 ** WHERE_ORDERBY_NORMAL is returned.
97665 */
97666 static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
97667 int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
97668
97669 *ppMinMax = 0;
97670 if( pAggInfo->nFunc==1 ){
97671 Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
97672 ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */
97673
97674 assert( pExpr->op==TK_AGG_FUNCTION );
97675 if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
97676 const char *zFunc = pExpr->u.zToken;
97677 if( sqlite3StrICmp(zFunc, "min")==0 ){
97678 eRet = WHERE_ORDERBY_MIN;
97679 *ppMinMax = pEList;
97680 }else if( sqlite3StrICmp(zFunc, "max")==0 ){
97681 eRet = WHERE_ORDERBY_MAX;
97682 *ppMinMax = pEList;
97683 }
97684 }
97685 }
97686
97687 assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
97688 return eRet;
97689 }
97690
97691 /*
97692 ** The select statement passed as the first argument is an aggregate query.
97693 ** The second argment is the associated aggregate-info object. This
@@ -97484,10 +97778,11 @@
97778 int i, j, k;
97779 SrcList *pTabList;
97780 ExprList *pEList;
97781 struct SrcList_item *pFrom;
97782 sqlite3 *db = pParse->db;
97783 Expr *pE, *pRight, *pExpr;
97784
97785 if( db->mallocFailed ){
97786 return WRC_Abort;
97787 }
97788 if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
@@ -97569,11 +97864,11 @@
97864 **
97865 ** The first loop just checks to see if there are any "*" operators
97866 ** that need expanding.
97867 */
97868 for(k=0; k<pEList->nExpr; k++){
97869 pE = pEList->a[k].pExpr;
97870 if( pE->op==TK_ALL ) break;
97871 assert( pE->op!=TK_DOT || pE->pRight!=0 );
97872 assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
97873 if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
97874 }
@@ -97587,14 +97882,22 @@
97882 ExprList *pNew = 0;
97883 int flags = pParse->db->flags;
97884 int longNames = (flags & SQLITE_FullColNames)!=0
97885 && (flags & SQLITE_ShortColNames)==0;
97886
97887 /* When processing FROM-clause subqueries, it is always the case
97888 ** that full_column_names=OFF and short_column_names=ON. The
97889 ** sqlite3ResultSetOfSelect() routine makes it so. */
97890 assert( (p->selFlags & SF_NestedFrom)==0
97891 || ((flags & SQLITE_FullColNames)==0 &&
97892 (flags & SQLITE_ShortColNames)!=0) );
97893
97894 for(k=0; k<pEList->nExpr; k++){
97895 pE = a[k].pExpr;
97896 pRight = pE->pRight;
97897 assert( pE->op!=TK_DOT || pRight!=0 );
97898 if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
97899 /* This particular expression does not need to be expanded.
97900 */
97901 pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
97902 if( pNew ){
97903 pNew->a[pNew->nExpr-1].zName = a[k].zName;
@@ -97605,44 +97908,56 @@
97908 a[k].pExpr = 0;
97909 }else{
97910 /* This expression is a "*" or a "TABLE.*" and needs to be
97911 ** expanded. */
97912 int tableSeen = 0; /* Set to 1 when TABLE matches */
97913 char *zTName = 0; /* text of name of TABLE */
97914 if( pE->op==TK_DOT ){
97915 assert( pE->pLeft!=0 );
97916 assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
97917 zTName = pE->pLeft->u.zToken;
 
 
97918 }
97919 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
97920 Table *pTab = pFrom->pTab;
97921 Select *pSub = pFrom->pSelect;
97922 char *zTabName = pFrom->zAlias;
97923 const char *zSchemaName = 0;
97924 int iDb;
97925 if( zTabName==0 ){
97926 zTabName = pTab->zName;
97927 }
97928 if( db->mallocFailed ) break;
97929 if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
97930 pSub = 0;
97931 if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
97932 continue;
97933 }
97934 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
97935 zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
97936 }
 
97937 for(j=0; j<pTab->nCol; j++){
 
97938 char *zName = pTab->aCol[j].zName;
97939 char *zColname; /* The computed column name */
97940 char *zToFree; /* Malloced string that needs to be freed */
97941 Token sColname; /* Computed column name as a token */
97942
97943 assert( zName );
97944 if( zTName && pSub
97945 && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
97946 ){
97947 continue;
97948 }
97949
97950 /* If a column is marked as 'hidden' (currently only possible
97951 ** for virtual tables), do not include it in the expanded
97952 ** result-set list.
97953 */
97954 if( IsHiddenColumn(&pTab->aCol[j]) ){
97955 assert(IsVirtual(pTab));
97956 continue;
97957 }
97958 tableSeen = 1;
97959
97960 if( i>0 && zTName==0 ){
97961 if( (pFrom->jointype & JT_NATURAL)!=0
97962 && tableAndColumnIndex(pTabList, i, zName, 0, 0)
97963 ){
@@ -97661,10 +97976,14 @@
97976 zToFree = 0;
97977 if( longNames || pTabList->nSrc>1 ){
97978 Expr *pLeft;
97979 pLeft = sqlite3Expr(db, TK_ID, zTabName);
97980 pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
97981 if( zSchemaName ){
97982 pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
97983 pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
97984 }
97985 if( longNames ){
97986 zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
97987 zToFree = zColname;
97988 }
97989 }else{
@@ -97672,10 +97991,22 @@
97991 }
97992 pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
97993 sColname.z = zColname;
97994 sColname.n = sqlite3Strlen30(zColname);
97995 sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
97996 if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
97997 struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
97998 if( pSub ){
97999 pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
98000 testcase( pX->zSpan==0 );
98001 }else{
98002 pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
98003 zSchemaName, zTabName, zColname);
98004 testcase( pX->zSpan==0 );
98005 }
98006 pX->bSpanIsTab = 1;
98007 }
98008 sqlite3DbFree(db, zToFree);
98009 }
98010 }
98011 if( !tableSeen ){
98012 if( zTName ){
@@ -98151,10 +98482,19 @@
98482 */
98483 int addrTop;
98484 int addrEof;
98485 pItem->regReturn = ++pParse->nMem;
98486 addrEof = ++pParse->nMem;
98487 /* Before coding the OP_Goto to jump to the start of the main routine,
98488 ** ensure that the jump to the verify-schema routine has already
98489 ** been coded. Otherwise, the verify-schema would likely be coded as
98490 ** part of the co-routine. If the main routine then accessed the
98491 ** database before invoking the co-routine for the first time (for
98492 ** example to initialize a LIMIT register from a sub-select), it would
98493 ** be doing so without having verified the schema version and obtained
98494 ** the required db locks. See ticket d6b36be38. */
98495 sqlite3CodeVerifySchema(pParse, -1);
98496 sqlite3VdbeAddOp0(v, OP_Goto);
98497 addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
98498 sqlite3VdbeChangeP5(v, 1);
98499 VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
98500 pItem->addrFillSub = addrTop;
@@ -98720,15 +99060,21 @@
99060 ** index or indices to use) should place a different priority on
99061 ** satisfying the 'ORDER BY' clause than it does in other cases.
99062 ** Refer to code and comments in where.c for details.
99063 */
99064 ExprList *pMinMax = 0;
99065 u8 flag = WHERE_ORDERBY_NORMAL;
99066
99067 assert( p->pGroupBy==0 );
99068 assert( flag==0 );
99069 if( p->pHaving==0 ){
99070 flag = minMaxQuery(&sAggInfo, &pMinMax);
99071 }
99072 assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
99073
99074 if( flag ){
99075 pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
 
 
99076 pDel = pMinMax;
99077 if( pMinMax && !db->mallocFailed ){
99078 pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
99079 pMinMax->a[0].pExpr->op = TK_COLUMN;
99080 }
@@ -99827,10 +100173,19 @@
100173 **
100174 ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
100175 ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
100176 */
100177 pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
100178
100179 /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
100180 ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
100181 ** that it is not safe to refactor constants (this happens after the
100182 ** start of the first loop in the SQL statement is coded - at that
100183 ** point code may be conditionally executed, so it is no longer safe to
100184 ** initialize constant register values). */
100185 assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
100186 pParse->cookieGoto = 0;
100187
100188 switch( pStep->op ){
100189 case TK_UPDATE: {
100190 sqlite3Update(pParse,
100191 targetSrcList(pParse, pStep),
@@ -102603,11 +102958,11 @@
102958 #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
102959 #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
102960 #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
102961 #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
102962 #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
102963 #define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
102964 #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
102965 #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
102966 #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
102967 #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
102968 #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
@@ -102753,11 +103108,11 @@
103108 sqlite3DbFree(db, pOld);
103109 }
103110 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
103111 }
103112 pTerm = &pWC->a[idx = pWC->nTerm++];
103113 pTerm->pExpr = sqlite3ExprSkipCollate(p);
103114 pTerm->wtFlags = wtFlags;
103115 pTerm->pWC = pWC;
103116 pTerm->iParent = -1;
103117 return idx;
103118 }
@@ -102913,27 +103268,36 @@
103268
103269 /*
103270 ** Commute a comparison operator. Expressions of the form "X op Y"
103271 ** are converted into "Y op X".
103272 **
103273 ** If left/right precendence rules come into play when determining the
103274 ** collating
103275 ** side of the comparison, it remains associated with the same side after
103276 ** the commutation. So "Y collate NOCASE op X" becomes
103277 ** "X op Y". This is because any collation sequence on
103278 ** the left hand side of a comparison overrides any collation sequence
103279 ** attached to the right. For the same reason the EP_Collate flag
103280 ** is not commuted.
103281 */
103282 static void exprCommute(Parse *pParse, Expr *pExpr){
103283 u16 expRight = (pExpr->pRight->flags & EP_Collate);
103284 u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
103285 assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
103286 if( expRight==expLeft ){
103287 /* Either X and Y both have COLLATE operator or neither do */
103288 if( expRight ){
103289 /* Both X and Y have COLLATE operators. Make sure X is always
103290 ** used by clearing the EP_Collate flag from Y. */
103291 pExpr->pRight->flags &= ~EP_Collate;
103292 }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
103293 /* Neither X nor Y have COLLATE operators, but X has a non-default
103294 ** collating sequence. So add the EP_Collate marker on X to cause
103295 ** it to be searched first. */
103296 pExpr->pLeft->flags |= EP_Collate;
103297 }
103298 }
103299 SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
103300 if( pExpr->op>=TK_GT ){
103301 assert( TK_LT==TK_GT+2 );
103302 assert( TK_GE==TK_LE+2 );
103303 assert( TK_GT>TK_EQ );
@@ -103006,16 +103370,16 @@
103370 ** it to be useful for optimising expression pX. Store this
103371 ** value in variable pColl.
103372 */
103373 assert(pX->pLeft);
103374 pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
103375 if( pColl==0 ) pColl = pParse->db->pDfltColl;
103376
103377 for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
103378 if( NEVER(j>=pIdx->nColumn) ) return 0;
103379 }
103380 if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103381 }
103382 return pTerm;
103383 }
103384 }
103385 }
@@ -103530,10 +103894,11 @@
103894 return;
103895 }
103896 pTerm = &pWC->a[idxTerm];
103897 pMaskSet = pWC->pMaskSet;
103898 pExpr = pTerm->pExpr;
103899 assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
103900 prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
103901 op = pExpr->op;
103902 if( op==TK_IN ){
103903 assert( pExpr->pRight==0 );
103904 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
@@ -103556,12 +103921,12 @@
103921 pTerm->prereqAll = prereqAll;
103922 pTerm->leftCursor = -1;
103923 pTerm->iParent = -1;
103924 pTerm->eOperator = 0;
103925 if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
103926 Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
103927 Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
103928 if( pLeft->op==TK_COLUMN ){
103929 pTerm->leftCursor = pLeft->iTable;
103930 pTerm->u.leftColumn = pLeft->iColumn;
103931 pTerm->eOperator = operatorMask(op);
103932 }
@@ -103585,11 +103950,11 @@
103950 }else{
103951 pDup = pExpr;
103952 pNew = pTerm;
103953 }
103954 exprCommute(pParse, pDup);
103955 pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
103956 pNew->leftCursor = pLeft->iTable;
103957 pNew->u.leftColumn = pLeft->iColumn;
103958 testcase( (prereqLeft | extraRight) != prereqLeft );
103959 pNew->prereqRight = prereqLeft | extraRight;
103960 pNew->prereqAll = prereqAll;
@@ -103664,11 +104029,11 @@
104029 Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
104030 Expr *pNewExpr1;
104031 Expr *pNewExpr2;
104032 int idxNew1;
104033 int idxNew2;
104034 Token sCollSeqName; /* Name of collating sequence */
104035
104036 pLeft = pExpr->x.pList->a[1].pExpr;
104037 pStr2 = sqlite3ExprDup(db, pStr1, 0);
104038 if( !db->mallocFailed ){
104039 u8 c, *pC; /* Last character before the first wildcard */
@@ -103686,20 +104051,23 @@
104051
104052 c = sqlite3UpperToLower[c];
104053 }
104054 *pC = c + 1;
104055 }
104056 sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
104057 sCollSeqName.n = 6;
104058 pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
104059 pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
104060 sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
104061 pStr1, 0);
104062 idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
104063 testcase( idxNew1==0 );
104064 exprAnalyze(pSrc, pWC, idxNew1);
104065 pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
104066 pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
104067 sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
104068 pStr2, 0);
104069 idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
104070 testcase( idxNew2==0 );
104071 exprAnalyze(pSrc, pWC, idxNew2);
104072 pTerm = &pWC->a[idxTerm];
104073 if( isComplete ){
@@ -103813,16 +104181,16 @@
104181 ){
104182 int i;
104183 const char *zColl = pIdx->azColl[iCol];
104184
104185 for(i=0; i<pList->nExpr; i++){
104186 Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
104187 if( p->op==TK_COLUMN
104188 && p->iColumn==pIdx->aiColumn[iCol]
104189 && p->iTable==iBase
104190 ){
104191 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
104192 if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
104193 return i;
104194 }
104195 }
104196 }
@@ -103865,11 +104233,11 @@
104233 ** matching "col=X" expression and the column is on the same table as pIdx,
104234 ** set the corresponding bit in variable mask.
104235 */
104236 for(i=0; i<pDistinct->nExpr; i++){
104237 WhereTerm *pTerm;
104238 Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
104239 if( p->op!=TK_COLUMN ) return 0;
104240 pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
104241 if( pTerm ){
104242 Expr *pX = pTerm->pExpr;
104243 CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
@@ -103917,11 +104285,11 @@
104285 /* If any of the expressions is an IPK column on table iBase, then return
104286 ** true. Note: The (p->iTable==iBase) part of this test may be false if the
104287 ** current SELECT is a correlated sub-query.
104288 */
104289 for(i=0; i<pDistinct->nExpr; i++){
104290 Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
104291 if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
104292 }
104293
104294 /* Loop through all indices on the table, checking each to see if it makes
104295 ** the DISTINCT qualifier redundant. It does so if:
@@ -104394,11 +104762,11 @@
104762 for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104763 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104764 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104765 testcase( pTerm->eOperator==WO_IN );
104766 testcase( pTerm->eOperator==WO_ISNULL );
104767 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104768 if( pTerm->wtFlags & TERM_VNULL ) continue;
104769 nTerm++;
104770 }
104771
104772 /* If the ORDER BY clause contains only columns in the current
@@ -104442,29 +104810,32 @@
104810 *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
104811 *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
104812 pUsage;
104813
104814 for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104815 u8 op;
104816 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104817 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104818 testcase( pTerm->eOperator==WO_IN );
104819 testcase( pTerm->eOperator==WO_ISNULL );
104820 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104821 if( pTerm->wtFlags & TERM_VNULL ) continue;
104822 pIdxCons[j].iColumn = pTerm->u.leftColumn;
104823 pIdxCons[j].iTermOffset = i;
104824 op = (u8)pTerm->eOperator;
104825 if( op==WO_IN ) op = WO_EQ;
104826 pIdxCons[j].op = op;
104827 /* The direct assignment in the previous line is possible only because
104828 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104829 ** following asserts verify this fact. */
104830 assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
104831 assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
104832 assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
104833 assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
104834 assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
104835 assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
104836 assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
104837 j++;
104838 }
104839 for(i=0; i<nOrderBy; i++){
104840 Expr *pExpr = pOrderBy->a[i].pExpr;
104841 pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -104546,10 +104917,11 @@
104917 struct sqlite3_index_constraint *pIdxCons;
104918 struct sqlite3_index_constraint_usage *pUsage;
104919 WhereTerm *pTerm;
104920 int i, j;
104921 int nOrderBy;
104922 int bAllowIN; /* Allow IN optimizations */
104923 double rCost;
104924
104925 /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
104926 ** malloc in allocateIndexInfo() fails and this function returns leaving
104927 ** wsFlags in an uninitialized state, the caller may behave unpredictably.
@@ -104580,63 +104952,91 @@
104952 ** sqlite3ViewGetColumnNames() would have picked up the error.
104953 */
104954 assert( pTab->azModuleArg && pTab->azModuleArg[0] );
104955 assert( sqlite3GetVTable(pParse->db, pTab) );
104956
104957 /* Try once or twice. On the first attempt, allow IN optimizations.
104958 ** If an IN optimization is accepted by the virtual table xBestIndex
104959 ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
104960 ** the query will not work because it might allow duplicate rows in
104961 ** output. In that case, run the xBestIndex method a second time
104962 ** without the IN constraints. Usually this loop only runs once.
104963 ** The loop will exit using a "break" statement.
104964 */
104965 for(bAllowIN=1; 1; bAllowIN--){
104966 assert( bAllowIN==0 || bAllowIN==1 );
104967
104968 /* Set the aConstraint[].usable fields and initialize all
104969 ** output variables to zero.
104970 **
104971 ** aConstraint[].usable is true for constraints where the right-hand
104972 ** side contains only references to tables to the left of the current
104973 ** table. In other words, if the constraint is of the form:
104974 **
104975 ** column = expr
104976 **
104977 ** and we are evaluating a join, then the constraint on column is
104978 ** only valid if all tables referenced in expr occur to the left
104979 ** of the table containing column.
104980 **
104981 ** The aConstraints[] array contains entries for all constraints
104982 ** on the current table. That way we only have to compute it once
104983 ** even though we might try to pick the best index multiple times.
104984 ** For each attempt at picking an index, the order of tables in the
104985 ** join might be different so we have to recompute the usable flag
104986 ** each time.
104987 */
104988 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
104989 pUsage = pIdxInfo->aConstraintUsage;
104990 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104991 j = pIdxCons->iTermOffset;
104992 pTerm = &pWC->a[j];
104993 if( (pTerm->prereqRight&p->notReady)==0
104994 && (bAllowIN || pTerm->eOperator!=WO_IN)
104995 ){
104996 pIdxCons->usable = 1;
104997 }else{
104998 pIdxCons->usable = 0;
104999 }
105000 }
105001 memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
105002 if( pIdxInfo->needToFreeIdxStr ){
105003 sqlite3_free(pIdxInfo->idxStr);
105004 }
105005 pIdxInfo->idxStr = 0;
105006 pIdxInfo->idxNum = 0;
105007 pIdxInfo->needToFreeIdxStr = 0;
105008 pIdxInfo->orderByConsumed = 0;
105009 /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
105010 pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
105011 nOrderBy = pIdxInfo->nOrderBy;
105012 if( !p->pOrderBy ){
105013 pIdxInfo->nOrderBy = 0;
105014 }
105015
105016 if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
105017 return;
105018 }
105019
105020 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
105021 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105022 if( pUsage[i].argvIndex>0 ){
105023 j = pIdxCons->iTermOffset;
105024 pTerm = &pWC->a[j];
105025 p->cost.used |= pTerm->prereqRight;
105026 if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
105027 /* Do not attempt to use an IN constraint if the virtual table
105028 ** says that the equivalent EQ constraint cannot be safely omitted.
105029 ** If we do attempt to use such a constraint, some rows might be
105030 ** repeated in the output. */
105031 break;
105032 }
105033 }
105034 }
105035 if( i>=pIdxInfo->nConstraint ) break;
105036 }
105037
105038 /* If there is an ORDER BY clause, and the selected virtual table index
105039 ** does not satisfy it, increase the cost of the scan accordingly. This
105040 ** matches the processing for non-virtual tables in bestBtreeIndex().
105041 */
105042 rCost = pIdxInfo->estimatedCost;
@@ -105203,11 +105603,11 @@
105603 WhereTerm *pConstraint; /* A constraint in the WHERE clause */
105604
105605 /* If the next term of the ORDER BY clause refers to anything other than
105606 ** a column in the "base" table, then this index will not be of any
105607 ** further use in handling the ORDER BY. */
105608 pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
105609 if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
105610 break;
105611 }
105612
105613 /* Find column number and collating sequence for the next entry
@@ -105229,11 +105629,11 @@
105629 /* Check to see if the column number and collating sequence of the
105630 ** index match the column number and collating sequence of the ORDER BY
105631 ** clause entry. Set isMatch to 1 if they both match. */
105632 if( pOBExpr->iColumn==iColumn ){
105633 if( zColl ){
105634 pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
105635 if( !pColl ) pColl = db->pDfltColl;
105636 isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
105637 }else{
105638 isMatch = 1;
105639 }
@@ -105370,10 +105770,15 @@
105770 int idxEqTermMask; /* Index mask of valid equality operators */
105771 Index sPk; /* A fake index object for the primary key */
105772 tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
105773 int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
105774 int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
105775 int nPriorSat; /* ORDER BY terms satisfied by outer loops */
105776 int nOrderBy; /* Number of ORDER BY terms */
105777 char bSortInit; /* Initializer for bSort in inner loop */
105778 char bDistInit; /* Initializer for bDist in inner loop */
105779
105780
105781 /* Initialize the cost to a worst-case value */
105782 memset(&p->cost, 0, sizeof(p->cost));
105783 p->cost.rCost = SQLITE_BIG_DBL;
105784
@@ -105418,10 +105823,21 @@
105823 WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
105824 );
105825 eqTermMask = WO_EQ|WO_IN;
105826 pIdx = 0;
105827 }
105828
105829 nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
105830 if( p->i ){
105831 nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
105832 bSortInit = nPriorSat<nOrderBy;
105833 bDistInit = 0;
105834 }else{
105835 nPriorSat = 0;
105836 bSortInit = nOrderBy>0;
105837 bDistInit = p->pDistinct!=0;
105838 }
105839
105840 /* Loop over all indices looking for the best one to use
105841 */
105842 for(; pProbe; pIdx=pProbe=pProbe->pNext){
105843 const tRowcnt * const aiRowEst = pProbe->aiRowEst;
@@ -105496,15 +105912,13 @@
105912 */
105913 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
105914 int nInMul = 1; /* Number of distinct equalities to lookup */
105915 double rangeDiv = (double)1; /* Estimated reduction in search space */
105916 int nBound = 0; /* Number of range constraints seen */
105917 char bSort = bSortInit; /* True if external sort required */
105918 char bDist = bDistInit; /* True if index cannot help with DISTINCT */
105919 char bLookup = 0; /* True if not a covering index */
 
 
105920 WhereTerm *pTerm; /* A single term of the WHERE clause */
105921 #ifdef SQLITE_ENABLE_STAT3
105922 WhereTerm *pFirstTerm = 0; /* First term matching the index */
105923 #endif
105924
@@ -105511,20 +105925,11 @@
105925 WHERETRACE((
105926 " %s(%s):\n",
105927 pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
105928 ));
105929 memset(&pc, 0, sizeof(pc));
105930 pc.plan.nOBSat = nPriorSat;
 
 
 
 
 
 
 
 
 
105931
105932 /* Determine the values of pc.plan.nEq and nInMul */
105933 for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
105934 int j = pProbe->aiColumn[pc.plan.nEq];
105935 pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
@@ -106396,32 +106801,40 @@
106801 if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
106802 /* Case 0: The table is a virtual-table. Use the VFilter and VNext
106803 ** to access the data.
106804 */
106805 int iReg; /* P3 Value for OP_VFilter */
106806 int addrNotFound;
106807 sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
106808 int nConstraint = pVtabIdx->nConstraint;
106809 struct sqlite3_index_constraint_usage *aUsage =
106810 pVtabIdx->aConstraintUsage;
106811 const struct sqlite3_index_constraint *aConstraint =
106812 pVtabIdx->aConstraint;
106813
106814 sqlite3ExprCachePush(pParse);
106815 iReg = sqlite3GetTempRange(pParse, nConstraint+2);
106816 addrNotFound = pLevel->addrBrk;
106817 for(j=1; j<=nConstraint; j++){
106818 for(k=0; k<nConstraint; k++){
106819 if( aUsage[k].argvIndex==j ){
106820 WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset];
106821 int iTarget = iReg+j+1;
106822 if( pTerm->eOperator & WO_IN ){
106823 codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
106824 addrNotFound = pLevel->addrNxt;
106825 }else{
106826 sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
106827 }
106828 break;
106829 }
106830 }
106831 if( k==nConstraint ) break;
106832 }
106833 sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
106834 sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
106835 sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
106836 pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
106837 pVtabIdx->needToFreeIdxStr = 0;
106838 for(j=0; j<nConstraint; j++){
106839 if( aUsage[j].omit ){
106840 int iTerm = aConstraint[j].iTermOffset;
@@ -108064,10 +108477,11 @@
108477 Expr* yy122;
108478 Select* yy159;
108479 IdList* yy180;
108480 struct {int value; int mask;} yy207;
108481 u8 yy258;
108482 u16 yy305;
108483 struct LikeOp yy318;
108484 TriggerStep* yy327;
108485 ExprSpan yy342;
108486 SrcList* yy347;
108487 int yy392;
@@ -110014,22 +110428,19 @@
110428 case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
110429 case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
110430 case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
110431 case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
110432 case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
 
 
110433 case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
110434 case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
110435 {yygotominor.yy392 = 0;}
110436 break;
110437 case 29: /* ifnotexists ::= IF NOT EXISTS */
110438 case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
110439 case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
110440 case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
110441 case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
 
110442 case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
110443 case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
110444 {yygotominor.yy392 = 1;}
110445 break;
110446 case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
@@ -110265,12 +110676,19 @@
110676 case 116: /* multiselect_op ::= UNION ALL */
110677 {yygotominor.yy392 = TK_ALL;}
110678 break;
110679 case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110680 {
110681 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.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
110682 }
110683 break;
110684 case 119: /* distinct ::= DISTINCT */
110685 {yygotominor.yy305 = SF_Distinct;}
110686 break;
110687 case 120: /* distinct ::= ALL */
110688 case 121: /* distinct ::= */ yytestcase(yyruleno==121);
110689 {yygotominor.yy305 = 0;}
110690 break;
110691 case 122: /* sclp ::= selcollist COMMA */
110692 case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
110693 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
110694 break;
@@ -110336,14 +110754,24 @@
110754 break;
110755 case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110756 {
110757 if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110758 yygotominor.yy347 = yymsp[-4].minor.yy347;
110759 }else if( yymsp[-4].minor.yy347->nSrc==1 ){
110760 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110761 if( yygotominor.yy347 ){
110762 struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
110763 struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
110764 pNew->zName = pOld->zName;
110765 pNew->zDatabase = pOld->zDatabase;
110766 pOld->zName = pOld->zDatabase = 0;
110767 }
110768 sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
110769 }else{
110770 Select *pSubquery;
110771 sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
110772 pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
110773 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110774 }
110775 }
110776 break;
110777 case 137: /* dbnm ::= */
@@ -110554,11 +110982,11 @@
110982 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110983 }
110984 break;
110985 case 194: /* expr ::= expr COLLATE ids */
110986 {
110987 yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110988 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110989 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110990 }
110991 break;
110992 case 195: /* expr ::= CAST LP expr AS typetoken RP */
@@ -110572,11 +111000,11 @@
111000 if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
111001 sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
111002 }
111003 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
111004 spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
111005 if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
111006 yygotominor.yy342.pExpr->flags |= EP_Distinct;
111007 }
111008 }
111009 break;
111010 case 197: /* expr ::= ID LP STAR RP */
@@ -110813,28 +111241,20 @@
111241 case 244: /* uniqueflag ::= */
111242 {yygotominor.yy392 = OE_None;}
111243 break;
111244 case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
111245 {
111246 Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
 
 
 
 
111247 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
111248 sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
111249 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
111250 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
111251 }
111252 break;
111253 case 248: /* idxlist ::= nm collate sortorder */
111254 {
111255 Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
 
 
 
 
111256 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
111257 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
111258 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
111259 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
111260 }
111261
+15 -5
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.7.15"
111
-#define SQLITE_VERSION_NUMBER 3007015
112
-#define SQLITE_SOURCE_ID "2012-12-05 14:31:13 9f6c68856b694373b7ffb124abd996e519ba5921"
110
+#define SQLITE_VERSION "3.7.16"
111
+#define SQLITE_VERSION_NUMBER 3007016
112
+#define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -855,11 +855,10 @@
855855
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
856856
** that the VFS encountered an error while handling the [PRAGMA] and the
857857
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
858858
** file control occurs at the beginning of pragma statement analysis and so
859859
** it is able to override built-in [PRAGMA] statements.
860
-** </ul>
861860
**
862861
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
863862
** ^This file-control may be invoked by SQLite on the database file handle
864863
** shortly after it is opened in order to provide a custom VFS with access
865864
** to the connections busy-handler callback. The argument is of type (void **)
@@ -867,10 +866,20 @@
867866
** to a function of type (int (*)(void *)). In order to invoke the connections
868867
** busy-handler, this function should be invoked with the second (void *) in
869868
** the array as the only argument. If it returns non-zero, then the operation
870869
** should be retried. If it returns zero, the custom VFS should abandon the
871870
** current operation.
871
+**
872
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
873
+** ^Application can invoke this file-control to have SQLite generate a
874
+** temporary filename using the same algorithm that is followed to generate
875
+** temporary filenames for TEMP tables and other internal uses. The
876
+** argument should be a char** which will be filled with the filename
877
+** written into memory obtained from [sqlite3_malloc()]. The caller should
878
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
879
+**
880
+** </ul>
872881
*/
873882
#define SQLITE_FCNTL_LOCKSTATE 1
874883
#define SQLITE_GET_LOCKPROXYFILE 2
875884
#define SQLITE_SET_LOCKPROXYFILE 3
876885
#define SQLITE_LAST_ERRNO 4
@@ -883,10 +892,11 @@
883892
#define SQLITE_FCNTL_OVERWRITE 11
884893
#define SQLITE_FCNTL_VFSNAME 12
885894
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
886895
#define SQLITE_FCNTL_PRAGMA 14
887896
#define SQLITE_FCNTL_BUSYHANDLER 15
897
+#define SQLITE_FCNTL_TEMPFILENAME 16
888898
889899
/*
890900
** CAPI3REF: Mutex Handle
891901
**
892902
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1580,11 +1590,11 @@
15801590
** database connection is opened. By default, URI handling is globally
15811591
** disabled. The default value may be changed by compiling with the
15821592
** [SQLITE_USE_URI] symbol defined.
15831593
**
15841594
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1585
-** <dd> This option taks a single integer argument which is interpreted as
1595
+** <dd> This option takes a single integer argument which is interpreted as
15861596
** a boolean in order to enable or disable the use of covering indices for
15871597
** full table scans in the query optimizer. The default setting is determined
15881598
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
15891599
** if that compile-time option is omitted.
15901600
** The ability to disable the use of covering indices for full table scans
15911601
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.15"
111 #define SQLITE_VERSION_NUMBER 3007015
112 #define SQLITE_SOURCE_ID "2012-12-05 14:31:13 9f6c68856b694373b7ffb124abd996e519ba5921"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -855,11 +855,10 @@
855 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
856 ** that the VFS encountered an error while handling the [PRAGMA] and the
857 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
858 ** file control occurs at the beginning of pragma statement analysis and so
859 ** it is able to override built-in [PRAGMA] statements.
860 ** </ul>
861 **
862 ** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
863 ** ^This file-control may be invoked by SQLite on the database file handle
864 ** shortly after it is opened in order to provide a custom VFS with access
865 ** to the connections busy-handler callback. The argument is of type (void **)
@@ -867,10 +866,20 @@
867 ** to a function of type (int (*)(void *)). In order to invoke the connections
868 ** busy-handler, this function should be invoked with the second (void *) in
869 ** the array as the only argument. If it returns non-zero, then the operation
870 ** should be retried. If it returns zero, the custom VFS should abandon the
871 ** current operation.
 
 
 
 
 
 
 
 
 
 
872 */
873 #define SQLITE_FCNTL_LOCKSTATE 1
874 #define SQLITE_GET_LOCKPROXYFILE 2
875 #define SQLITE_SET_LOCKPROXYFILE 3
876 #define SQLITE_LAST_ERRNO 4
@@ -883,10 +892,11 @@
883 #define SQLITE_FCNTL_OVERWRITE 11
884 #define SQLITE_FCNTL_VFSNAME 12
885 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
886 #define SQLITE_FCNTL_PRAGMA 14
887 #define SQLITE_FCNTL_BUSYHANDLER 15
 
888
889 /*
890 ** CAPI3REF: Mutex Handle
891 **
892 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1580,11 +1590,11 @@
1580 ** database connection is opened. By default, URI handling is globally
1581 ** disabled. The default value may be changed by compiling with the
1582 ** [SQLITE_USE_URI] symbol defined.
1583 **
1584 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1585 ** <dd> This option taks a single integer argument which is interpreted as
1586 ** a boolean in order to enable or disable the use of covering indices for
1587 ** full table scans in the query optimizer. The default setting is determined
1588 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
1589 ** if that compile-time option is omitted.
1590 ** The ability to disable the use of covering indices for full table scans
1591
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.16"
111 #define SQLITE_VERSION_NUMBER 3007016
112 #define SQLITE_SOURCE_ID "2013-01-07 13:26:23 0a1207c895d9f77586a3a2a4965175909be90503"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -855,11 +855,10 @@
855 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
856 ** that the VFS encountered an error while handling the [PRAGMA] and the
857 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
858 ** file control occurs at the beginning of pragma statement analysis and so
859 ** it is able to override built-in [PRAGMA] statements.
 
860 **
861 ** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
862 ** ^This file-control may be invoked by SQLite on the database file handle
863 ** shortly after it is opened in order to provide a custom VFS with access
864 ** to the connections busy-handler callback. The argument is of type (void **)
@@ -867,10 +866,20 @@
866 ** to a function of type (int (*)(void *)). In order to invoke the connections
867 ** busy-handler, this function should be invoked with the second (void *) in
868 ** the array as the only argument. If it returns non-zero, then the operation
869 ** should be retried. If it returns zero, the custom VFS should abandon the
870 ** current operation.
871 **
872 ** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
873 ** ^Application can invoke this file-control to have SQLite generate a
874 ** temporary filename using the same algorithm that is followed to generate
875 ** temporary filenames for TEMP tables and other internal uses. The
876 ** argument should be a char** which will be filled with the filename
877 ** written into memory obtained from [sqlite3_malloc()]. The caller should
878 ** invoke [sqlite3_free()] on the result to avoid a memory leak.
879 **
880 ** </ul>
881 */
882 #define SQLITE_FCNTL_LOCKSTATE 1
883 #define SQLITE_GET_LOCKPROXYFILE 2
884 #define SQLITE_SET_LOCKPROXYFILE 3
885 #define SQLITE_LAST_ERRNO 4
@@ -883,10 +892,11 @@
892 #define SQLITE_FCNTL_OVERWRITE 11
893 #define SQLITE_FCNTL_VFSNAME 12
894 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
895 #define SQLITE_FCNTL_PRAGMA 14
896 #define SQLITE_FCNTL_BUSYHANDLER 15
897 #define SQLITE_FCNTL_TEMPFILENAME 16
898
899 /*
900 ** CAPI3REF: Mutex Handle
901 **
902 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1580,11 +1590,11 @@
1590 ** database connection is opened. By default, URI handling is globally
1591 ** disabled. The default value may be changed by compiling with the
1592 ** [SQLITE_USE_URI] symbol defined.
1593 **
1594 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1595 ** <dd> This option takes a single integer argument which is interpreted as
1596 ** a boolean in order to enable or disable the use of covering indices for
1597 ** full table scans in the query optimizer. The default setting is determined
1598 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
1599 ** if that compile-time option is omitted.
1600 ** The ability to disable the use of covering indices for full table scans
1601
+1 -1
--- src/stat.c
+++ src/stat.c
@@ -115,11 +115,11 @@
115115
@ </td></tr>
116116
}
117117
@ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118118
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119119
" + 0.99");
120
- @ %d(n) days or approximately %.2f(n/356.24) years.
120
+ @ %d(n) days or approximately %.2f(n/365.24) years.
121121
@ </td></tr>
122122
@ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
123123
@ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
124124
@ <tr><th>Fossil&nbsp;Version:</th><td>
125125
@ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
126126
--- src/stat.c
+++ src/stat.c
@@ -115,11 +115,11 @@
115 @ </td></tr>
116 }
117 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119 " + 0.99");
120 @ %d(n) days or approximately %.2f(n/356.24) years.
121 @ </td></tr>
122 @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
123 @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
124 @ <tr><th>Fossil&nbsp;Version:</th><td>
125 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
126
--- src/stat.c
+++ src/stat.c
@@ -115,11 +115,11 @@
115 @ </td></tr>
116 }
117 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119 " + 0.99");
120 @ %d(n) days or approximately %.2f(n/365.24) years.
121 @ </td></tr>
122 @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
123 @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
124 @ <tr><th>Fossil&nbsp;Version:</th><td>
125 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
126
+18 -4
--- src/style.c
+++ src/style.c
@@ -439,11 +439,13 @@
439439
/*
440440
** The default page footer
441441
*/
442442
const char zDefaultFooter[] =
443443
@ <div class="footer">
444
-@ Fossil version $release_version $manifest_version $manifest_date
444
+@ This page was generated in about
445
+@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
446
+@ Fossil version $manifest_version $manifest_date
445447
@ </div>
446448
@ </body></html>
447449
;
448450
449451
/*
@@ -586,12 +588,13 @@
586588
@ div.footer a:visited { color: white; }
587589
@ div.footer a:hover { background-color: white; color: #558195; }
588590
@
589591
@ /* verbatim blocks */
590592
@ pre.verbatim {
591
-@ background-color: #f5f5f5;
592
-@ padding: 0.5em;
593
+@ background-color: #f5f5f5;
594
+@ padding: 0.5em;
595
+@ white-space: pre-wrap;
593596
@}
594597
@
595598
@ /* The label/value pairs on (for example) the ci page */
596599
@ table.label-value th {
597600
@ vertical-align: top;
@@ -959,11 +962,11 @@
959962
@ line-height: 100%;
960963
},
961964
{ "div.sbsdiff",
962965
"side-by-side diff display",
963966
@ font-family: monospace;
964
- @ font-size: smaller;
967
+ @ font-size: xx-small;
965968
@ white-space: pre;
966969
},
967970
{ "div.udiff",
968971
"context diff display",
969972
@ font-family: monospace;
@@ -991,10 +994,21 @@
991994
},
992995
{ "span.modpending",
993996
"Moderation Pending message on timeline",
994997
@ color: #b03800;
995998
@ font-style: italic;
999
+ },
1000
+ { "pre.th1result",
1001
+ "format for th1 script results",
1002
+ @ white-space: pre-wrap;
1003
+ @ word-wrap: break-word;
1004
+ },
1005
+ { "pre.th1error",
1006
+ "format for th1 script errors",
1007
+ @ white-space: pre-wrap;
1008
+ @ word-wrap: break-word;
1009
+ @ color: red;
9961010
},
9971011
{ 0,
9981012
0,
9991013
0
10001014
}
10011015
--- src/style.c
+++ src/style.c
@@ -439,11 +439,13 @@
439 /*
440 ** The default page footer
441 */
442 const char zDefaultFooter[] =
443 @ <div class="footer">
444 @ Fossil version $release_version $manifest_version $manifest_date
 
 
445 @ </div>
446 @ </body></html>
447 ;
448
449 /*
@@ -586,12 +588,13 @@
586 @ div.footer a:visited { color: white; }
587 @ div.footer a:hover { background-color: white; color: #558195; }
588 @
589 @ /* verbatim blocks */
590 @ pre.verbatim {
591 @ background-color: #f5f5f5;
592 @ padding: 0.5em;
 
593 @}
594 @
595 @ /* The label/value pairs on (for example) the ci page */
596 @ table.label-value th {
597 @ vertical-align: top;
@@ -959,11 +962,11 @@
959 @ line-height: 100%;
960 },
961 { "div.sbsdiff",
962 "side-by-side diff display",
963 @ font-family: monospace;
964 @ font-size: smaller;
965 @ white-space: pre;
966 },
967 { "div.udiff",
968 "context diff display",
969 @ font-family: monospace;
@@ -991,10 +994,21 @@
991 },
992 { "span.modpending",
993 "Moderation Pending message on timeline",
994 @ color: #b03800;
995 @ font-style: italic;
 
 
 
 
 
 
 
 
 
 
 
996 },
997 { 0,
998 0,
999 0
1000 }
1001
--- src/style.c
+++ src/style.c
@@ -439,11 +439,13 @@
439 /*
440 ** The default page footer
441 */
442 const char zDefaultFooter[] =
443 @ <div class="footer">
444 @ This page was generated in about
445 @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
446 @ Fossil version $manifest_version $manifest_date
447 @ </div>
448 @ </body></html>
449 ;
450
451 /*
@@ -586,12 +588,13 @@
588 @ div.footer a:visited { color: white; }
589 @ div.footer a:hover { background-color: white; color: #558195; }
590 @
591 @ /* verbatim blocks */
592 @ pre.verbatim {
593 @ background-color: #f5f5f5;
594 @ padding: 0.5em;
595 @ white-space: pre-wrap;
596 @}
597 @
598 @ /* The label/value pairs on (for example) the ci page */
599 @ table.label-value th {
600 @ vertical-align: top;
@@ -959,11 +962,11 @@
962 @ line-height: 100%;
963 },
964 { "div.sbsdiff",
965 "side-by-side diff display",
966 @ font-family: monospace;
967 @ font-size: xx-small;
968 @ white-space: pre;
969 },
970 { "div.udiff",
971 "context diff display",
972 @ font-family: monospace;
@@ -991,10 +994,21 @@
994 },
995 { "span.modpending",
996 "Moderation Pending message on timeline",
997 @ color: #b03800;
998 @ font-style: italic;
999 },
1000 { "pre.th1result",
1001 "format for th1 script results",
1002 @ white-space: pre-wrap;
1003 @ word-wrap: break-word;
1004 },
1005 { "pre.th1error",
1006 "format for th1 script errors",
1007 @ white-space: pre-wrap;
1008 @ word-wrap: break-word;
1009 @ color: red;
1010 },
1011 { 0,
1012 0,
1013 0
1014 }
1015
+7 -2
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616616
int nSql;
617617
const char *zTail;
618618
int n, i;
619619
int res = TH_OK;
620620
int nVar;
621
+ char *zErr = 0;
621622
622623
if( argc!=3 ){
623624
return Th_WrongNumArgs(interp, "query SQL CODE");
624625
}
625626
if( g.db==0 ){
@@ -627,13 +628,17 @@
627628
return TH_ERROR;
628629
}
629630
zSql = argv[1];
630631
nSql = argl[1];
631632
while( res==TH_OK && nSql>0 ){
633
+ zErr = 0;
634
+ sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr);
632635
rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
633
- if( rc!=0 ){
634
- Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
636
+ sqlite3_set_authorizer(g.db, 0, 0);
637
+ if( rc!=0 || zErr!=0 ){
638
+ Th_ErrorMessage(interp, "SQL error: ",
639
+ zErr ? zErr : sqlite3_errmsg(g.db), -1);
635640
return TH_ERROR;
636641
}
637642
n = (int)(zTail - zSql);
638643
zSql += n;
639644
nSql -= n;
640645
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616 int nSql;
617 const char *zTail;
618 int n, i;
619 int res = TH_OK;
620 int nVar;
 
621
622 if( argc!=3 ){
623 return Th_WrongNumArgs(interp, "query SQL CODE");
624 }
625 if( g.db==0 ){
@@ -627,13 +628,17 @@
627 return TH_ERROR;
628 }
629 zSql = argv[1];
630 nSql = argl[1];
631 while( res==TH_OK && nSql>0 ){
 
 
632 rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
633 if( rc!=0 ){
634 Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
 
 
635 return TH_ERROR;
636 }
637 n = (int)(zTail - zSql);
638 zSql += n;
639 nSql -= n;
640
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616 int nSql;
617 const char *zTail;
618 int n, i;
619 int res = TH_OK;
620 int nVar;
621 char *zErr = 0;
622
623 if( argc!=3 ){
624 return Th_WrongNumArgs(interp, "query SQL CODE");
625 }
626 if( g.db==0 ){
@@ -627,13 +628,17 @@
628 return TH_ERROR;
629 }
630 zSql = argv[1];
631 nSql = argl[1];
632 while( res==TH_OK && nSql>0 ){
633 zErr = 0;
634 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr);
635 rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
636 sqlite3_set_authorizer(g.db, 0, 0);
637 if( rc!=0 || zErr!=0 ){
638 Th_ErrorMessage(interp, "SQL error: ",
639 zErr ? zErr : sqlite3_errmsg(g.db), -1);
640 return TH_ERROR;
641 }
642 n = (int)(zTail - zSql);
643 zSql += n;
644 nSql -= n;
645
+7 -2
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616616
int nSql;
617617
const char *zTail;
618618
int n, i;
619619
int res = TH_OK;
620620
int nVar;
621
+ char *zErr = 0;
621622
622623
if( argc!=3 ){
623624
return Th_WrongNumArgs(interp, "query SQL CODE");
624625
}
625626
if( g.db==0 ){
@@ -627,13 +628,17 @@
627628
return TH_ERROR;
628629
}
629630
zSql = argv[1];
630631
nSql = argl[1];
631632
while( res==TH_OK && nSql>0 ){
633
+ zErr = 0;
634
+ sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr);
632635
rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
633
- if( rc!=0 ){
634
- Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
636
+ sqlite3_set_authorizer(g.db, 0, 0);
637
+ if( rc!=0 || zErr!=0 ){
638
+ Th_ErrorMessage(interp, "SQL error: ",
639
+ zErr ? zErr : sqlite3_errmsg(g.db), -1);
635640
return TH_ERROR;
636641
}
637642
n = (int)(zTail - zSql);
638643
zSql += n;
639644
nSql -= n;
640645
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616 int nSql;
617 const char *zTail;
618 int n, i;
619 int res = TH_OK;
620 int nVar;
 
621
622 if( argc!=3 ){
623 return Th_WrongNumArgs(interp, "query SQL CODE");
624 }
625 if( g.db==0 ){
@@ -627,13 +628,17 @@
627 return TH_ERROR;
628 }
629 zSql = argv[1];
630 nSql = argl[1];
631 while( res==TH_OK && nSql>0 ){
 
 
632 rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
633 if( rc!=0 ){
634 Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1);
 
 
635 return TH_ERROR;
636 }
637 n = (int)(zTail - zSql);
638 zSql += n;
639 nSql -= n;
640
--- src/th_main.c
+++ src/th_main.c
@@ -616,10 +616,11 @@
616 int nSql;
617 const char *zTail;
618 int n, i;
619 int res = TH_OK;
620 int nVar;
621 char *zErr = 0;
622
623 if( argc!=3 ){
624 return Th_WrongNumArgs(interp, "query SQL CODE");
625 }
626 if( g.db==0 ){
@@ -627,13 +628,17 @@
628 return TH_ERROR;
629 }
630 zSql = argv[1];
631 nSql = argl[1];
632 while( res==TH_OK && nSql>0 ){
633 zErr = 0;
634 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr);
635 rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail);
636 sqlite3_set_authorizer(g.db, 0, 0);
637 if( rc!=0 || zErr!=0 ){
638 Th_ErrorMessage(interp, "SQL error: ",
639 zErr ? zErr : sqlite3_errmsg(g.db), -1);
640 return TH_ERROR;
641 }
642 n = (int)(zTail - zSql);
643 zSql += n;
644 nSql -= n;
645
+11 -32
--- src/timeline.c
+++ src/timeline.c
@@ -211,19 +211,20 @@
211211
if( tmFlags & TIMELINE_GRAPH ){
212212
pGraph = graph_init();
213213
/* style is not moved to css, because this is
214214
** a technical div for the timeline graph
215215
*/
216
- @ <div id="canvas" style="position:relative;width:1px;height:1px;"
216
+ @ <div id="canvas" style="position:relative;height:0px;width:0px;"
217217
@ onclick="clickOnGraph(event)"></div>
218218
}
219219
db_static_prepare(&qbranch,
220220
"SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
221221
TAG_BRANCH
222222
);
223223
224
- @ <table id="timelineTable" class="timelineTable">
224
+ @ <table id="timelineTable" class="timelineTable"
225
+ @ onclick="clickOnGraph(event)">
225226
blob_zero(&comment);
226227
while( db_step(pQuery)==SQLITE_ROW ){
227228
int rid = db_column_int(pQuery, 0);
228229
const char *zUuid = db_column_text(pQuery, 1);
229230
int isLeaf = db_column_int(pQuery, 5);
@@ -426,10 +427,12 @@
426427
" (SELECT uuid FROM blob WHERE rid=fid),"
427428
" (SELECT uuid FROM blob WHERE rid=pid),"
428429
" (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
429430
" FROM mlink"
430431
" WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
432
+ " AND (fid>0 OR"
433
+ " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
431434
" ORDER BY 3 /*sort*/"
432435
);
433436
fchngQueryInit = 1;
434437
}
435438
db_bind_int(&fchngQuery, ":mid", rid);
@@ -725,42 +728,16 @@
725728
@ for(var i in rowinfo){
726729
@ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY;
727730
@ rowinfo[i].x = left + rowinfo[i].r*railPitch;
728731
@ }
729732
@ var btm = absoluteY("grbtm") + 10 - canvasY;
730
-#if 0
731
- @ if( btm<32768 ){
732
- @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+
733
- @ 'style="position:absolute;left:'+(left-5)+'px;"' +
734
- @ ' width="'+width+'" height="'+btm+'"><'+'/canvas>';
735
- @ realCanvas = gebi('timeline-canvas');
736
- @ }else{
737
- @ realCanvas = 0;
738
- @ }
739
- @ var context;
740
- @ if( realCanvas && realCanvas.getContext
741
- @ && (context = realCanvas.getContext('2d'))) {
742
- @ drawBox = function(color,x0,y0,x1,y1) {
743
- @ if( y0>32767 || y1>32767 ) return;
744
- @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
745
- @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
746
- @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return;
747
- @ context.fillStyle = color;
748
- @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1);
749
- @ };
750
- @ }
751
-#endif
752733
@ for(var i in rowinfo){
753734
@ drawNode(rowinfo[i], left, btm);
754735
@ }
755736
@ if( selRow!=null ) clickOnRow(selRow);
756737
@ }
757738
@ function clickOnGraph(event){
758
-#ifdef OMIT_IE8_SUPPORT
759
- @ var x=event.clientX-absoluteX("canvas")+window.pageXOffset;
760
- @ var y=event.clientY-absoluteY("canvas")+window.pageYOffset;
761
-#else
762739
@ var x=event.clientX-absoluteX("canvas");
763740
@ var y=event.clientY-absoluteY("canvas");
764741
@ if(window.pageXOffset!=null){
765742
@ x += window.pageXOffset;
766743
@ y += window.pageYOffset;
@@ -768,16 +745,18 @@
768745
@ var d = window.document.documentElement;
769746
@ if(document.compatMode!="CSS1Compat") d = d.body;
770747
@ x += d.scrollLeft;
771748
@ y += d.scrollTop;
772749
@ }
773
-#endif
750
+ if( P("clicktest")!=0 ){
751
+ @ alert("click at "+x+","+y)
752
+ }
774753
@ for(var i in rowinfo){
775754
@ p = rowinfo[i];
776
- @ if( p.y<y-10 ) continue;
777
- @ if( p.y>y+10 ) break;
778
- @ if( p.x>x-10 && p.x<x+10 ){
755
+ @ if( p.y<y-11 ) continue;
756
+ @ if( p.y>y+9 ) break;
757
+ @ if( p.x>x-11 && p.x<x+9 ){
779758
@ clickOnRow(p);
780759
@ break;
781760
@ }
782761
@ }
783762
@ }
784763
785764
ADDED src/unicode.c
--- src/timeline.c
+++ src/timeline.c
@@ -211,19 +211,20 @@
211 if( tmFlags & TIMELINE_GRAPH ){
212 pGraph = graph_init();
213 /* style is not moved to css, because this is
214 ** a technical div for the timeline graph
215 */
216 @ <div id="canvas" style="position:relative;width:1px;height:1px;"
217 @ onclick="clickOnGraph(event)"></div>
218 }
219 db_static_prepare(&qbranch,
220 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
221 TAG_BRANCH
222 );
223
224 @ <table id="timelineTable" class="timelineTable">
 
225 blob_zero(&comment);
226 while( db_step(pQuery)==SQLITE_ROW ){
227 int rid = db_column_int(pQuery, 0);
228 const char *zUuid = db_column_text(pQuery, 1);
229 int isLeaf = db_column_int(pQuery, 5);
@@ -426,10 +427,12 @@
426 " (SELECT uuid FROM blob WHERE rid=fid),"
427 " (SELECT uuid FROM blob WHERE rid=pid),"
428 " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
429 " FROM mlink"
430 " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
 
 
431 " ORDER BY 3 /*sort*/"
432 );
433 fchngQueryInit = 1;
434 }
435 db_bind_int(&fchngQuery, ":mid", rid);
@@ -725,42 +728,16 @@
725 @ for(var i in rowinfo){
726 @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY;
727 @ rowinfo[i].x = left + rowinfo[i].r*railPitch;
728 @ }
729 @ var btm = absoluteY("grbtm") + 10 - canvasY;
730 #if 0
731 @ if( btm<32768 ){
732 @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+
733 @ 'style="position:absolute;left:'+(left-5)+'px;"' +
734 @ ' width="'+width+'" height="'+btm+'"><'+'/canvas>';
735 @ realCanvas = gebi('timeline-canvas');
736 @ }else{
737 @ realCanvas = 0;
738 @ }
739 @ var context;
740 @ if( realCanvas && realCanvas.getContext
741 @ && (context = realCanvas.getContext('2d'))) {
742 @ drawBox = function(color,x0,y0,x1,y1) {
743 @ if( y0>32767 || y1>32767 ) return;
744 @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
745 @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
746 @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return;
747 @ context.fillStyle = color;
748 @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1);
749 @ };
750 @ }
751 #endif
752 @ for(var i in rowinfo){
753 @ drawNode(rowinfo[i], left, btm);
754 @ }
755 @ if( selRow!=null ) clickOnRow(selRow);
756 @ }
757 @ function clickOnGraph(event){
758 #ifdef OMIT_IE8_SUPPORT
759 @ var x=event.clientX-absoluteX("canvas")+window.pageXOffset;
760 @ var y=event.clientY-absoluteY("canvas")+window.pageYOffset;
761 #else
762 @ var x=event.clientX-absoluteX("canvas");
763 @ var y=event.clientY-absoluteY("canvas");
764 @ if(window.pageXOffset!=null){
765 @ x += window.pageXOffset;
766 @ y += window.pageYOffset;
@@ -768,16 +745,18 @@
768 @ var d = window.document.documentElement;
769 @ if(document.compatMode!="CSS1Compat") d = d.body;
770 @ x += d.scrollLeft;
771 @ y += d.scrollTop;
772 @ }
773 #endif
 
 
774 @ for(var i in rowinfo){
775 @ p = rowinfo[i];
776 @ if( p.y<y-10 ) continue;
777 @ if( p.y>y+10 ) break;
778 @ if( p.x>x-10 && p.x<x+10 ){
779 @ clickOnRow(p);
780 @ break;
781 @ }
782 @ }
783 @ }
784
785 DDED src/unicode.c
--- src/timeline.c
+++ src/timeline.c
@@ -211,19 +211,20 @@
211 if( tmFlags & TIMELINE_GRAPH ){
212 pGraph = graph_init();
213 /* style is not moved to css, because this is
214 ** a technical div for the timeline graph
215 */
216 @ <div id="canvas" style="position:relative;height:0px;width:0px;"
217 @ onclick="clickOnGraph(event)"></div>
218 }
219 db_static_prepare(&qbranch,
220 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
221 TAG_BRANCH
222 );
223
224 @ <table id="timelineTable" class="timelineTable"
225 @ onclick="clickOnGraph(event)">
226 blob_zero(&comment);
227 while( db_step(pQuery)==SQLITE_ROW ){
228 int rid = db_column_int(pQuery, 0);
229 const char *zUuid = db_column_text(pQuery, 1);
230 int isLeaf = db_column_int(pQuery, 5);
@@ -426,10 +427,12 @@
427 " (SELECT uuid FROM blob WHERE rid=fid),"
428 " (SELECT uuid FROM blob WHERE rid=pid),"
429 " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
430 " FROM mlink"
431 " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
432 " AND (fid>0 OR"
433 " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
434 " ORDER BY 3 /*sort*/"
435 );
436 fchngQueryInit = 1;
437 }
438 db_bind_int(&fchngQuery, ":mid", rid);
@@ -725,42 +728,16 @@
728 @ for(var i in rowinfo){
729 @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY;
730 @ rowinfo[i].x = left + rowinfo[i].r*railPitch;
731 @ }
732 @ var btm = absoluteY("grbtm") + 10 - canvasY;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733 @ for(var i in rowinfo){
734 @ drawNode(rowinfo[i], left, btm);
735 @ }
736 @ if( selRow!=null ) clickOnRow(selRow);
737 @ }
738 @ function clickOnGraph(event){
 
 
 
 
739 @ var x=event.clientX-absoluteX("canvas");
740 @ var y=event.clientY-absoluteY("canvas");
741 @ if(window.pageXOffset!=null){
742 @ x += window.pageXOffset;
743 @ y += window.pageYOffset;
@@ -768,16 +745,18 @@
745 @ var d = window.document.documentElement;
746 @ if(document.compatMode!="CSS1Compat") d = d.body;
747 @ x += d.scrollLeft;
748 @ y += d.scrollTop;
749 @ }
750 if( P("clicktest")!=0 ){
751 @ alert("click at "+x+","+y)
752 }
753 @ for(var i in rowinfo){
754 @ p = rowinfo[i];
755 @ if( p.y<y-11 ) continue;
756 @ if( p.y>y+9 ) break;
757 @ if( p.x>x-11 && p.x<x+9 ){
758 @ clickOnRow(p);
759 @ break;
760 @ }
761 @ }
762 @ }
763
764 DDED src/unicode.c
+528
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -0,0 +1,528 @@
1
+/*
2
+*8028020F606809F8C0B, 0x03600001,
3
+ 0x03ECA401,
4
+ 0x03F88033,
5
+ 0x03FC6807,
6
+ 0x03FFE405,
7
+ 0x0406400C,
8
+ 0x040E7C01,
9
+ 0x04247C01,
10
+ 0x0428E003,
11
+ 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
12
+ 0x04450004, 0x04451402,
13
+ 0x044B7C0C, 0x044C0004,
14
+ 0x044D2C03, 0x0FC01, 0x00320404,
15
+ 0x00335402,
16
+ 0x00351803,
17
+ 0x0035E401,
18
+ 0x00376008,
19
+ 0x00391C09,
20
+ 6, 0x003AEC02C80331, 0x00AF2835,
21
+ 0x00B39406,
22
+ 0x00B5F
23
+ 0x00BC00D6,
24
+ 0x00C0D802,
25
+ 0x00C64002,
26
+ 0x00C94001,
27
+ 0x01370040,
28
+ 0x029A7802,
29
+ 0x02A00801,
30
+ 0x02A1D004,2A3E003,
31
+ 0x02A57C01,
32
+3/fts302A8A40E,
33
+ 0x02A9EC03,
34
+ 0x02AB0401,
35
+ 0x02AF8C0B,
36
+ 0x03EC7801, 0x03ECA
37
+ 0x03F8001A,
38
+ 0x03FC040F,
39
+ 0x03FFA 0x0421DC02,
40
+ 0x00292C03,
41
+ 0x042B2001,
42
+ 0x 0x002AF001,
43
+ 0x04471409,*
44
+*8028 0x002BC002,
45
+ 0x002D1C02, 0x002D2C03,
46
+ 0x002E0801, 0x002EF805,
47
+ 0x002FCC08, 0x00300004,
48
+ 0x00315402, 0x00318802,
49
+ 0x0032F807, 0x00331803,
50
+ 0x00340403, 0x0034F807688, 61700351803, 0x00352804,
51
+ 0x0035E401, 0x00360802,
52
+ 0x00376008, 0x0037C803,
53
+ 0x00391C09, 0x00396802,
54
+ 0x003B2006, 0x003C041F,
55
+ 0x003E6424, 0x003EF80F,
56
+ 0x00415804, 0x00417803,
57
+ 0x0042080C, 0x00423C01,
58
+ 0x004E400A, 0
59
+ **, 'y', 'y', 'a', 'c0x005F6004,
60
+ 0x0062A401, 0x0064800C,
61
+ 0x00677822, 0x00685C05,
62
+ 0x0069FC01, 0x006A8007,
63
+
64
+ 0x006FF004, 0x00709014,, 0x03600001,
65
+ 0x03ECA401,
66
+ 0x03F88033,
67
+ 0x03FC6807,
68
+ 0x03FFE405,
69
+ 0x0406400C
70
+ 0x007FB403, 0x007FF402,
71
+ 0 007FB403, 0x007FF402,
72
+ 0x00822805, 0x0082801F,
73
+ 0x00842002, 0x00845001,
74
+ 0x00const static84A401,
75
+ 0x00852804, 0x00853C01, 0x00862802, 0x0086426F, 0x00900027,
76
+ 0x009E53E0, 0x00ADD820,
77
+ 00391C09,
78
+ 6, 0x003AEC02C80331, 8, 0x00AFB004, 0x00B394060x05BE3C000B5F
79
+ 0x00BC00D6,
80
+ 0x00C0 0x00B5C001, 0x00B5FC01,
81
+ 00C94001,
82
+ 0x0137005, 0x00BA001A, 0x00C0A807, 0x00C0DC01,
83
+ 0x00C05, 0x00181816,
84
+ 0x001B9C07,2A00801,
85
+ 0x02A0D8
86
+ 0x001CC01B,x0472A40E,
87
+ 0x02A380
88
+ 0x00206C09,
89
+ 0x02A8A40E, 0x02
90
+ 0x00217x03600001,
91
+ 0x03EC7801, 0x03ECA401,
92
+ 0x03F8001A, 0x03F88033,
93
+ 0x03FC040F, 0x03FC6807,
94
+ 0x03FFA007, 0x03FFE405,
95
+ 0x04063003, 0x0406400C,
96
+ 0x040DD805, 0x040E7C01,
97
+ 0x0421DC02, 0x04247C01,
98
+ 0x04d', 'e', 'e', 'g', 'h', 'i 0x04283004, 0x0428E003,
99
+ 0x042B2001, 0x042B9402,
100
+ 0x04400003, 0x0440E016,
101
+ 0x04449C0E, 0x04450004,
102
+ 0x04471409, 0x04476C01,
103
+ 0F606809F8C0B, 0x03600001,
104
+ 0x044D2C03, 0x044D5C01,
105
+ 0x0450D412, 0x04512C05,
106
+ 0x04531801, 0x0456BC07,
107
+ 0x0459800D, 0x045AAC0D,
108
+ 040DD805,
109
+ 0x0421DC02,
110
+ 41FC04,
111
+ 0x04450004,
112
+ 0x0
113
+ 0x0471C9800D,
114
+ 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
115
+ 0x0474FC07, 0x04751C01,
116
+ 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC05C01, 0x00358802, 0x0035E401,
117
+ 01, 0x006A8007,
118
+ 0 0x00376008,
119
+ 709014,, 0x03600001,
120
+ 0x00391C09,
121
+ 807,
122
+ 0x03FFE405,
123
+ 0x003B2006,
124
+ 0x00822805, 0x008 0x003E6424,
125
+ 849C01, 0x0084A401,
126
+ 0x00415804,
127
+ 86426F, 0x00900027,
128
+ 0x0042080C,
129
+ 6, 0x003AEC02C80331, 0x004E400A,
130
+ 0x00BC00D6,
131
+ 0x00 0x005BAC03,
132
+ 0x0137005, 0x00BA001 0x005ED023,
133
+ 0x00C64002,
134
+ A401, 0x0064800C,
135
+ 0x00677822, 0x00685C05,
136
+ 0x0069FC01, 0x006A8007,
137
+ 0x006CD011, 0x006D6823,
138
+ 0x006FF004, 0x007090140442C012,
139
+/*
140
+*8028020F606809F8C0B, 0x0360809F8C0B, 0x03600001,
141
+ 0x 0x0077F004, 0x007EF401,
142
+ 0x007FB403, 0x007FF402,
143
+ 0x00822805, 0x0082801F,
144
+ 0x00842002, 0x00845001,
145
+ 0x00849C01, 0x0084A401,
146
+ 0x00852804, 0x00853C016C011, 0x00672002,
147
+
148
+ 0x0069FC01, 0x006A8007,
149
+ 0x006CD011, 0x006D6823,
150
+ 0x006FF004, 0x00709014,
151
+ 0x00734019, 0x0073B401,, 0x03600001,
152
+ 0x03ECA401
153
+ 0x007FB403, 0x007FFEC01, 0x0 0x02A6CC1B, 0x02A77802,
154
+
155
+ 0x00822805, 0x0082801E,05BE3C000842002, 0x00845001,
156
+ 0x00849C01, 0x0084A401,
157
+ 0x00852804, 0x00853C01 0x040400
158
+ 0x0092704E, 0x0406400C, 0x040F4
159
+ 0x00AEF40C, 0x00AF28082CE407,
160
+ 0x0441FC04, 0x0442C012,
161
+ 0x0445CC03, 0x04460003,
162
+ 0x04477403, 0x0448B012,
163
+ 0F606809F8C0B, 0x03600001,
164
+ 0x044D8802,8, 1168660, 186, 6},
165
+ {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
166
+ {8122,0, 1},
167
+ {8136,86, 2},
168
+ {8154, 15{8170, 154, 2},
169
+ {8172, 18848, 2}, {81860, 112, 1},
170
+ {8491, 1140836, 1},
171
+ {11364, 1104, 1},
172
+ {11374, 1060, 1}, {11376, 1029846209, 84, 0, 86},
173
+{42930, 86},
174
+ {43888, 92 30204,
175
+ 54793, 54809,
176
+ 8028020F606809F020F606809F8C0B, 65268, 65341,
177
+ 65436, 65439,
178
+ 65482, 65488,
179
+ bRemoveDiacritic ));/446, 1},
180
+ 4, 8},
181
+ {7960, 184, 4980A, 0x02A51C0D,
182
+ , 184, 8}, {79 0x02A79401,
183
+ {8040,{8088, 184, 0x02A9DC03,
184
+ 2}, {8122, 16 0x02AAF802,
185
+ 0, 1}, {8136, 0x02AD6C01,
186
+
187
+ {81868, 182
188
+ 0x037FFC01,
189
+
190
+ {11363, 136, 1}, 0x03F7F002,
191
+ 1506, 0, 1},*8028020F0E, 0x03F8C02 {42877, 94, 1},
192
+ {42893, 86, 1},
193
+ {42922, 80, 1},
194
+ {42925, 82, 1},
195
+ {42929, 840, 831, 68, 1},
196
+ {429325268, 65341, 65373,
197
+ 65450,
198
+ 65506,
199
+ 8028020F606809F8C0B, 0x03600001,
200
+ 03600001,
201
+ 0x03ECA401,
202
+ 0x03F88033,
203
+ 0x03FC6807,
204
+ 0x03FFE405,
205
+ 0x0406400C,
206
+ 0x040E7C01,
207
+ 0x04247C01,
208
+ 0x0428E003,
209
+ 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
210
+ 0x04450004, 0x04451402,
211
+ 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
212
+ 0x00376008,
213
+ 0x00391C09,
214
+ 6, 0x003AEC02C80331, 0x00AF2835,
215
+ 0x00B39406,
216
+ 0x00B5F
217
+ 0x00B4, 0x04473401, 0x0448B012, 0x044B7C0C,
218
+ 0x044C0403, 0x044CF001, 0x044CF807, 0x044DC005, 0x0452C014,
219
+ 8687, 8}, {8040,86, 8}, 186, 8}, {8104, 1868 {8136,86, 2},
220
+ {8154, 15{8170, 154, 2},
221
+ {8172, 18848, 2}, {81860, 112, 1},
222
+ {8491, 1140836, 1},
223
+ {11364, 1104, 1},
224
+ B5{11374, 1060, 1}, {11376, 1029846209, 84, 1},
225
+ {42930, 86},
226
+ {43888, 92 30204,
227
+ 54793, 54809,
228
+ 8028020F606809F020F606809F8C0B, 65268, 65341,
229
+ A34007, 0x07BBC002,
230
+
231
+ 0x07C34425, 0x07C4401F, 0x04247C01,
232
+ 0x0428E003,
233
+ 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
234
+ 0x04450004, 0x04451402,
235
+ 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
236
+ 0x00376008,
237
+ 0x00391C09,
238
+ 6, 0x003AEC02C80331, 0x00AF2835,
239
+ 0x00B39406,
240
+ 0x00B5F
241
+ 0x00BC00D6,
242
+ 0x00C0D802,
243
+ 0x00C64002,
244
+ 0x00C94001,
245
+ 0x01370040,
246
+ 0x029A7802,
247
+ 0x02A00801,
248
+ 0x02A1D004,2A3E003,
249
+ 0x02A57C01,
250
+ 0x02A8A40E,
251
+ 0x02A9EC03,
252
+ 0x02AB0401,
253
+ 0x02AF8C0B,
254
+ 0x03EC7801, 0x03ECA
255
+ 0x03F8001A,
256
+ 0x03FC040F,
257
+ 0x03FFA007,
258
+ 0x04063003,
259
+ 0x040DD805,
260
+ 0x0421DC02,
261
+ 0x04283004,
262
+ 0x042B2001,
263
+ 0x04349004,
264
+ 0x0441FC04,
265
+ 0x04450004,
266
+ 0x04471409,*
267
+*8028020F606809F8C0, 0x03600001,
268
+
269
+ 0x044D2C03,
270
+ 0x0450D412,
271
+ 0x04531801,
272
+ 0x0459800D,
273
+ 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
274
+ 0x0474FC07, 0x04751C01,
275
+ 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
276
+ 442E, 0x05BE3C04, 0x06F27008,
277
+
278
+ 0x075B0401, 0x075B6C01,
279
+ 0x075D3C01, 0x075DBC01,
280
+ 0x0760028C, 0x076A6C05,
281
+ 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
282
+
283
+ 0x07C0C064, 0x07C2800F,
284
+ 0x07C4405C, 0x07C5C03D,
285
+ 0x07C94A,
286
+ 0x07DC0074, 0x07DE0059
287
+ 0x07E18028,402F, 0x07E50031,
288
+ 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
289
+ 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
290
+
291
+ 4408, 4424, 447
292
+ 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
293
+ 36, 61880, 61914, 61948, 61998, 62122,
294
+ 62154, 62200, 62218, 62302, 62364
295
+ 62554,
296
+ 62924char aChar[] = {
297
+ '\0', '/*
298
+*8028'u', 'y', 'y', 'a', 'c',
299
+ 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
300
+ 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
301
+ 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
302
+ 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
303
+ '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
304
+ 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
305
+ 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
306
+ 'e', 'i', 'o', 'u', return (
307
+*8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1},
308
+ {503, 1704627678, 1},
309
+ {981, 1828284, 1, 24},
310
+ {10081009, 174, 1}, {108846862, 1},
311
+ {7297,*8028020F606809F8C0B, 0x03600001,
312
+ sizeof(aDia)/sizeof(aDia[0]
313
+ 0x040DD805,
314
+ 0x0421DC02,
315
+ 0x04283004,
316
+ 0x042B2001,
317
+ 0x04349004,
318
+ 0x0441FC04,
319
+ 0x04450004,
320
+ 0x04471409,*
321
+*8028020F606809F8C0, 0x03600001,
322
+
323
+ 0x044D2C03,
324
+ 0x0450D412,
325
+ 0x04531801,
326
+ 0x0459800D,
327
+ 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
328
+ 0x0474FC07, 0x04751C01,
329
+ 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
330
+ 442E, 0x05BE3C04, 0x06F27008,
331
+
332
+ 0x075B0401, 0x075B6C01,
333
+ 0x075D3C01, 0x075DBC01,
334
+ 0x0760028C, 0x076A6C05,
335
+ 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
336
+
337
+ 0x07C0C064, 0x07C2800F,
338
+ 0x07C4405C, 0x07C5C03D,
339
+ 0x07C94A,
340
+ 0x07DC0074, 0x07DE0059
341
+ 0x07E18028,402F, 0x07E50031,
342
+ 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
343
+ 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
344
+
345
+ 4408, 4424, 447
346
+ 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
347
+ 36, 61880, 61914, 61948, 61998, 62122,
348
+ 62154, 62200, 62218, 62302, 62364
349
+ 62554,
350
+ 62924char aChar[] = {
351
+ '\0', '/*
352
+*8028'u', 'y', 'y', 'a', 'c',
353
+ 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
354
+ 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
355
+ 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
356
+ 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
357
+ '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
358
+ 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
359
+ 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
360
+ ';e', 'i', 'o', 'u', return (
361
+*8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1},
362
+ {503, 1704627678, 1},
363
+ {981, 1828284, 1, 24},
364
+ {10081009, 174, 1}, {108846862, 1},
365
+ {7297,*8028020F606809F8C0B, 0x03600001,
366
+ 0x03ECA401,
367
+ 0x03F88033,
368
+ 0x03FC6807,
369
+ 0x03FFE405,
370
+ 0x0406400C,
371
+ 0x040E7C01,
372
+ 0x04247C01,
373
+ 0x0428E003,
374
+ 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
375
+ 0x04450004, 0x04451402,
376
+ 0x044B7C0C, 0x044C0004,
377
+ 0x044D2C03, 0x0600001,
378
+ 0x03ECA402, 1324, 1},
379
+ {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6},
380
+ {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
381
+ {8122,0, 1},
382
+ {8136,86, 2},
383
+ {8154, 15{8170, 154, 2},
384
+ {8172, 18848, 2}, {81860, 112, 1},
385
+ {8491, 1140836, 1},
386
+ {11364, 1104, 1},
387
+ {11374, 1060, 1}, {11376, 1029846209, 84, 1},
388
+ {42930, 86},
389
+ {43888, 92 30204,
390
+ 54793, 54809,
391
+ 8028020F606809F020F606809F8C0B, 65268, 65341,
392
+ 65436, 65439,
393
+ 65482, 65488,
394
+ bRemoveDiacritic ));count(aEntry
395
+ {42925, 82, 1},
396
+sizeof(aEntry)/sizeof(aEntry[0] 0x0456E020,
397
+ 7976, 18686, 8}, {8008,AAC0D, 0x045C740F, 0x045CF004,
398
+
399
+ 0x05BD442E, 0x05BE3C04,
400
+ 0x0744A4C0, 0x07480046,
401
+ 0x075BEC01, 0x075C5401, 'm', 75E2401, 0x075EA401,05BE3C0076A840F, 0x07A340078},
402
+ {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1},
403
+ {8126, 120, 1}, {82B},
404
+ {8170,6, 2},
405
+ B{81868, 1827A, 0x07D5EC29, 0x07D6952C, 0x07DB800D,
406
+ 0x07DBC004, 0x07DC0074,247C01,
407
+7E1400A, 0x07E18028, 0x07E24,
408
+ 0x044D2C03, 0x0600001,
409
+ 0x03ECA402, 1324, 1},
410
+ {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6},
411
+ {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
412
+ {8122,0, 1},
413
+ {8136,86, 2},
414
+ {8154, 15{8170, 154, 2},
415
+ {8172, 18848, 2}, {81860, 112, 1},
416
+ {8491, 1140836, 1},
417
+ {11364, 1104, 1},
418
+ {11374, 1060, 1}, {11376, 1029846209, 84, 1},
419
+ {42930, 86},
420
+ {43888, 92 30204,
421
+ 54793, 54809,
422
+ 8028020F606809F020F606809F8C0B, 65268, 65341,
423
+ 65436, 65439,
424
+ 65482, 65488,
425
+ bRemoveDiacritic ));/446, 1},
426
+ 4, 8},
427
+ {7960, 184, 6},7976, 184, 8}, {7992, 184, 88008, 184, 6},{8025, 185, 8}, {8040,{8088, 184, 8}, {8104, 184, 8},
428
+ {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1},
429
+ {8126, 120, 1}, {8136, 1582, 1},
430
+ {8152,4, 2},
431
+ {8170,6, 2},
432
+ {81868, 182
433
+
434
+ {8544, 8, 16},
435
+ {11264, 24, 47},
436
+ {11363, 136, 1},
437
+ {11373, 104, 1},
438
+
439
+
440
+ {11506, 0, 1},*8028020F606606809F8C0B, 0x03600001,
441
+ {42877, 94, 1},
442
+ {42893, 86, 1},
443
+ {42922, 80, 1},
444
+ {42925, 82, 1},
445
+ {42929, 840, 831, 68, 1},
446
+ {429325268, 65341, 65373,
447
+ 65450,
448
+ 65506,
449
+ 8028020F606809F8C0B, 0x03600001,
450
+ 03600001,
451
+ 0x03ECA401,
452
+ 0x03F88033,
453
+ 0x03FC6807,
454
+ 0x03FFE405,
455
+ 0x0406400C,
456
+ 0x040E7C01,
457
+ 0x04247C01,
458
+ 0x0428E003,
459
+ 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
460
+ 0x04450004, 0x04451402,
461
+ 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
462
+ 0x00376008,
463
+ 0x00391C09,
464
+ 6, 0x003AEC02C80331, 0x00AF2835,
465
+ 0x00B39406,
466
+ 0x00B5F
467
+ 0x00BC00D6,
468
+ 0x00C0D802,
469
+ 0x00C64002,
470
+ 0x00C94001,
471
+ 0x01370040,
472
+ 0x029A7802,
473
+ 0x02A00801,
474
+ 0x02A1D004,2A3E003,
475
+ 0x02A57C01,
476
+ 0x02A8A40E,
477
+ 0x02A9EC03,
478
+ 0x02AB0401,
479
+ 0x02AF8C0B,
480
+ 0x03EC7801, 0x03ECA
481
+ 0x03F8001A,
482
+ 0x03FC040F,
483
+ 0x03FFA007,
484
+ 0x04063003,
485
+ 0x040DD805,
486
+ 0x0421DC02,
487
+ 0x04283004,
488
+ 0x042B2001,
489
+ 0x04349004,
490
+ 0x0441FC04,
491
+ 0x04450004,
492
+ 0x04471409,*
493
+*8028020F606809F8C0, 0x03600001,
494
+
495
+ 0x044D2C03,
496
+ 0x0450D412,
497
+ 0x04531801,
498
+ 0x0459800D,
499
+ 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
500
+ 0x0474FC07, 0x04751C01,
501
+ 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
502
+ 442E, 0x05BE3C04, 0x06F27008,
503
+
504
+ 0x075B0401, 0x075B6C01,
505
+ 0x075D3C01, 0x075DBC01,
506
+ 0x0760028C, 0x076A6C05,
507
+ 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
508
+
509
+ 0x07C0C064, 0x07C2800F,
510
+ 0x07C4405C, 0x07C5C03D,
511
+ 0x07C94A,
512
+ 0x07DC0074, 0x07DE0059
513
+ 0x07E18028,402F, 0x07E50031,
514
+ 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
515
+ 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
516
+
517
+ 4408, 4424, 447
518
+ 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
519
+ 36, 61880, 61914, 61948, 61998, 62122,
520
+ 62154, 62200, 62218, 62302, 62364
521
+ 62554,
522
+ 62924char aChar[] = {
523
+ '\0', '/*
524
+*8028'u', 'y', 'y', 'a', 'c',
525
+ 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
526
+ 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
527
+ 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
528
+ 'u', 's', 't', 'h'
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -0,0 +1,528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -0,0 +1,528 @@
1 /*
2 *8028020F606809F8C0B, 0x03600001,
3 0x03ECA401,
4 0x03F88033,
5 0x03FC6807,
6 0x03FFE405,
7 0x0406400C,
8 0x040E7C01,
9 0x04247C01,
10 0x0428E003,
11 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
12 0x04450004, 0x04451402,
13 0x044B7C0C, 0x044C0004,
14 0x044D2C03, 0x0FC01, 0x00320404,
15 0x00335402,
16 0x00351803,
17 0x0035E401,
18 0x00376008,
19 0x00391C09,
20 6, 0x003AEC02C80331, 0x00AF2835,
21 0x00B39406,
22 0x00B5F
23 0x00BC00D6,
24 0x00C0D802,
25 0x00C64002,
26 0x00C94001,
27 0x01370040,
28 0x029A7802,
29 0x02A00801,
30 0x02A1D004,2A3E003,
31 0x02A57C01,
32 3/fts302A8A40E,
33 0x02A9EC03,
34 0x02AB0401,
35 0x02AF8C0B,
36 0x03EC7801, 0x03ECA
37 0x03F8001A,
38 0x03FC040F,
39 0x03FFA 0x0421DC02,
40 0x00292C03,
41 0x042B2001,
42 0x 0x002AF001,
43 0x04471409,*
44 *8028 0x002BC002,
45 0x002D1C02, 0x002D2C03,
46 0x002E0801, 0x002EF805,
47 0x002FCC08, 0x00300004,
48 0x00315402, 0x00318802,
49 0x0032F807, 0x00331803,
50 0x00340403, 0x0034F807688, 61700351803, 0x00352804,
51 0x0035E401, 0x00360802,
52 0x00376008, 0x0037C803,
53 0x00391C09, 0x00396802,
54 0x003B2006, 0x003C041F,
55 0x003E6424, 0x003EF80F,
56 0x00415804, 0x00417803,
57 0x0042080C, 0x00423C01,
58 0x004E400A, 0
59 **, 'y', 'y', 'a', 'c0x005F6004,
60 0x0062A401, 0x0064800C,
61 0x00677822, 0x00685C05,
62 0x0069FC01, 0x006A8007,
63
64 0x006FF004, 0x00709014,, 0x03600001,
65 0x03ECA401,
66 0x03F88033,
67 0x03FC6807,
68 0x03FFE405,
69 0x0406400C
70 0x007FB403, 0x007FF402,
71 0 007FB403, 0x007FF402,
72 0x00822805, 0x0082801F,
73 0x00842002, 0x00845001,
74 0x00const static84A401,
75 0x00852804, 0x00853C01, 0x00862802, 0x0086426F, 0x00900027,
76 0x009E53E0, 0x00ADD820,
77 00391C09,
78 6, 0x003AEC02C80331, 8, 0x00AFB004, 0x00B394060x05BE3C000B5F
79 0x00BC00D6,
80 0x00C0 0x00B5C001, 0x00B5FC01,
81 00C94001,
82 0x0137005, 0x00BA001A, 0x00C0A807, 0x00C0DC01,
83 0x00C05, 0x00181816,
84 0x001B9C07,2A00801,
85 0x02A0D8
86 0x001CC01B,x0472A40E,
87 0x02A380
88 0x00206C09,
89 0x02A8A40E, 0x02
90 0x00217x03600001,
91 0x03EC7801, 0x03ECA401,
92 0x03F8001A, 0x03F88033,
93 0x03FC040F, 0x03FC6807,
94 0x03FFA007, 0x03FFE405,
95 0x04063003, 0x0406400C,
96 0x040DD805, 0x040E7C01,
97 0x0421DC02, 0x04247C01,
98 0x04d', 'e', 'e', 'g', 'h', 'i 0x04283004, 0x0428E003,
99 0x042B2001, 0x042B9402,
100 0x04400003, 0x0440E016,
101 0x04449C0E, 0x04450004,
102 0x04471409, 0x04476C01,
103 0F606809F8C0B, 0x03600001,
104 0x044D2C03, 0x044D5C01,
105 0x0450D412, 0x04512C05,
106 0x04531801, 0x0456BC07,
107 0x0459800D, 0x045AAC0D,
108 040DD805,
109 0x0421DC02,
110 41FC04,
111 0x04450004,
112 0x0
113 0x0471C9800D,
114 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
115 0x0474FC07, 0x04751C01,
116 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC05C01, 0x00358802, 0x0035E401,
117 01, 0x006A8007,
118 0 0x00376008,
119 709014,, 0x03600001,
120 0x00391C09,
121 807,
122 0x03FFE405,
123 0x003B2006,
124 0x00822805, 0x008 0x003E6424,
125 849C01, 0x0084A401,
126 0x00415804,
127 86426F, 0x00900027,
128 0x0042080C,
129 6, 0x003AEC02C80331, 0x004E400A,
130 0x00BC00D6,
131 0x00 0x005BAC03,
132 0x0137005, 0x00BA001 0x005ED023,
133 0x00C64002,
134 A401, 0x0064800C,
135 0x00677822, 0x00685C05,
136 0x0069FC01, 0x006A8007,
137 0x006CD011, 0x006D6823,
138 0x006FF004, 0x007090140442C012,
139 /*
140 *8028020F606809F8C0B, 0x0360809F8C0B, 0x03600001,
141 0x 0x0077F004, 0x007EF401,
142 0x007FB403, 0x007FF402,
143 0x00822805, 0x0082801F,
144 0x00842002, 0x00845001,
145 0x00849C01, 0x0084A401,
146 0x00852804, 0x00853C016C011, 0x00672002,
147
148 0x0069FC01, 0x006A8007,
149 0x006CD011, 0x006D6823,
150 0x006FF004, 0x00709014,
151 0x00734019, 0x0073B401,, 0x03600001,
152 0x03ECA401
153 0x007FB403, 0x007FFEC01, 0x0 0x02A6CC1B, 0x02A77802,
154
155 0x00822805, 0x0082801E,05BE3C000842002, 0x00845001,
156 0x00849C01, 0x0084A401,
157 0x00852804, 0x00853C01 0x040400
158 0x0092704E, 0x0406400C, 0x040F4
159 0x00AEF40C, 0x00AF28082CE407,
160 0x0441FC04, 0x0442C012,
161 0x0445CC03, 0x04460003,
162 0x04477403, 0x0448B012,
163 0F606809F8C0B, 0x03600001,
164 0x044D8802,8, 1168660, 186, 6},
165 {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
166 {8122,0, 1},
167 {8136,86, 2},
168 {8154, 15{8170, 154, 2},
169 {8172, 18848, 2}, {81860, 112, 1},
170 {8491, 1140836, 1},
171 {11364, 1104, 1},
172 {11374, 1060, 1}, {11376, 1029846209, 84, 0, 86},
173 {42930, 86},
174 {43888, 92 30204,
175 54793, 54809,
176 8028020F606809F020F606809F8C0B, 65268, 65341,
177 65436, 65439,
178 65482, 65488,
179 bRemoveDiacritic ));/446, 1},
180 4, 8},
181 {7960, 184, 4980A, 0x02A51C0D,
182 , 184, 8}, {79 0x02A79401,
183 {8040,{8088, 184, 0x02A9DC03,
184 2}, {8122, 16 0x02AAF802,
185 0, 1}, {8136, 0x02AD6C01,
186
187 {81868, 182
188 0x037FFC01,
189
190 {11363, 136, 1}, 0x03F7F002,
191 1506, 0, 1},*8028020F0E, 0x03F8C02 {42877, 94, 1},
192 {42893, 86, 1},
193 {42922, 80, 1},
194 {42925, 82, 1},
195 {42929, 840, 831, 68, 1},
196 {429325268, 65341, 65373,
197 65450,
198 65506,
199 8028020F606809F8C0B, 0x03600001,
200 03600001,
201 0x03ECA401,
202 0x03F88033,
203 0x03FC6807,
204 0x03FFE405,
205 0x0406400C,
206 0x040E7C01,
207 0x04247C01,
208 0x0428E003,
209 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
210 0x04450004, 0x04451402,
211 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
212 0x00376008,
213 0x00391C09,
214 6, 0x003AEC02C80331, 0x00AF2835,
215 0x00B39406,
216 0x00B5F
217 0x00B4, 0x04473401, 0x0448B012, 0x044B7C0C,
218 0x044C0403, 0x044CF001, 0x044CF807, 0x044DC005, 0x0452C014,
219 8687, 8}, {8040,86, 8}, 186, 8}, {8104, 1868 {8136,86, 2},
220 {8154, 15{8170, 154, 2},
221 {8172, 18848, 2}, {81860, 112, 1},
222 {8491, 1140836, 1},
223 {11364, 1104, 1},
224 B5{11374, 1060, 1}, {11376, 1029846209, 84, 1},
225 {42930, 86},
226 {43888, 92 30204,
227 54793, 54809,
228 8028020F606809F020F606809F8C0B, 65268, 65341,
229 A34007, 0x07BBC002,
230
231 0x07C34425, 0x07C4401F, 0x04247C01,
232 0x0428E003,
233 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
234 0x04450004, 0x04451402,
235 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
236 0x00376008,
237 0x00391C09,
238 6, 0x003AEC02C80331, 0x00AF2835,
239 0x00B39406,
240 0x00B5F
241 0x00BC00D6,
242 0x00C0D802,
243 0x00C64002,
244 0x00C94001,
245 0x01370040,
246 0x029A7802,
247 0x02A00801,
248 0x02A1D004,2A3E003,
249 0x02A57C01,
250 0x02A8A40E,
251 0x02A9EC03,
252 0x02AB0401,
253 0x02AF8C0B,
254 0x03EC7801, 0x03ECA
255 0x03F8001A,
256 0x03FC040F,
257 0x03FFA007,
258 0x04063003,
259 0x040DD805,
260 0x0421DC02,
261 0x04283004,
262 0x042B2001,
263 0x04349004,
264 0x0441FC04,
265 0x04450004,
266 0x04471409,*
267 *8028020F606809F8C0, 0x03600001,
268
269 0x044D2C03,
270 0x0450D412,
271 0x04531801,
272 0x0459800D,
273 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
274 0x0474FC07, 0x04751C01,
275 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
276 442E, 0x05BE3C04, 0x06F27008,
277
278 0x075B0401, 0x075B6C01,
279 0x075D3C01, 0x075DBC01,
280 0x0760028C, 0x076A6C05,
281 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
282
283 0x07C0C064, 0x07C2800F,
284 0x07C4405C, 0x07C5C03D,
285 0x07C94A,
286 0x07DC0074, 0x07DE0059
287 0x07E18028,402F, 0x07E50031,
288 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
289 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
290
291 4408, 4424, 447
292 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
293 36, 61880, 61914, 61948, 61998, 62122,
294 62154, 62200, 62218, 62302, 62364
295 62554,
296 62924char aChar[] = {
297 '\0', '/*
298 *8028'u', 'y', 'y', 'a', 'c',
299 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
300 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
301 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
302 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
303 '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
304 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
305 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
306 'e', 'i', 'o', 'u', return (
307 *8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1},
308 {503, 1704627678, 1},
309 {981, 1828284, 1, 24},
310 {10081009, 174, 1}, {108846862, 1},
311 {7297,*8028020F606809F8C0B, 0x03600001,
312 sizeof(aDia)/sizeof(aDia[0]
313 0x040DD805,
314 0x0421DC02,
315 0x04283004,
316 0x042B2001,
317 0x04349004,
318 0x0441FC04,
319 0x04450004,
320 0x04471409,*
321 *8028020F606809F8C0, 0x03600001,
322
323 0x044D2C03,
324 0x0450D412,
325 0x04531801,
326 0x0459800D,
327 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
328 0x0474FC07, 0x04751C01,
329 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
330 442E, 0x05BE3C04, 0x06F27008,
331
332 0x075B0401, 0x075B6C01,
333 0x075D3C01, 0x075DBC01,
334 0x0760028C, 0x076A6C05,
335 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
336
337 0x07C0C064, 0x07C2800F,
338 0x07C4405C, 0x07C5C03D,
339 0x07C94A,
340 0x07DC0074, 0x07DE0059
341 0x07E18028,402F, 0x07E50031,
342 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
343 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
344
345 4408, 4424, 447
346 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
347 36, 61880, 61914, 61948, 61998, 62122,
348 62154, 62200, 62218, 62302, 62364
349 62554,
350 62924char aChar[] = {
351 '\0', '/*
352 *8028'u', 'y', 'y', 'a', 'c',
353 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
354 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
355 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
356 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
357 '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
358 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
359 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
360 ';e', 'i', 'o', 'u', return (
361 *8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1},
362 {503, 1704627678, 1},
363 {981, 1828284, 1, 24},
364 {10081009, 174, 1}, {108846862, 1},
365 {7297,*8028020F606809F8C0B, 0x03600001,
366 0x03ECA401,
367 0x03F88033,
368 0x03FC6807,
369 0x03FFE405,
370 0x0406400C,
371 0x040E7C01,
372 0x04247C01,
373 0x0428E003,
374 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
375 0x04450004, 0x04451402,
376 0x044B7C0C, 0x044C0004,
377 0x044D2C03, 0x0600001,
378 0x03ECA402, 1324, 1},
379 {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6},
380 {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
381 {8122,0, 1},
382 {8136,86, 2},
383 {8154, 15{8170, 154, 2},
384 {8172, 18848, 2}, {81860, 112, 1},
385 {8491, 1140836, 1},
386 {11364, 1104, 1},
387 {11374, 1060, 1}, {11376, 1029846209, 84, 1},
388 {42930, 86},
389 {43888, 92 30204,
390 54793, 54809,
391 8028020F606809F020F606809F8C0B, 65268, 65341,
392 65436, 65439,
393 65482, 65488,
394 bRemoveDiacritic ));count(aEntry
395 {42925, 82, 1},
396 sizeof(aEntry)/sizeof(aEntry[0] 0x0456E020,
397 7976, 18686, 8}, {8008,AAC0D, 0x045C740F, 0x045CF004,
398
399 0x05BD442E, 0x05BE3C04,
400 0x0744A4C0, 0x07480046,
401 0x075BEC01, 0x075C5401, 'm', 75E2401, 0x075EA401,05BE3C0076A840F, 0x07A340078},
402 {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1},
403 {8126, 120, 1}, {82B},
404 {8170,6, 2},
405 B{81868, 1827A, 0x07D5EC29, 0x07D6952C, 0x07DB800D,
406 0x07DBC004, 0x07DC0074,247C01,
407 7E1400A, 0x07E18028, 0x07E24,
408 0x044D2C03, 0x0600001,
409 0x03ECA402, 1324, 1},
410 {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6},
411 {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2},
412 {8122,0, 1},
413 {8136,86, 2},
414 {8154, 15{8170, 154, 2},
415 {8172, 18848, 2}, {81860, 112, 1},
416 {8491, 1140836, 1},
417 {11364, 1104, 1},
418 {11374, 1060, 1}, {11376, 1029846209, 84, 1},
419 {42930, 86},
420 {43888, 92 30204,
421 54793, 54809,
422 8028020F606809F020F606809F8C0B, 65268, 65341,
423 65436, 65439,
424 65482, 65488,
425 bRemoveDiacritic ));/446, 1},
426 4, 8},
427 {7960, 184, 6},7976, 184, 8}, {7992, 184, 88008, 184, 6},{8025, 185, 8}, {8040,{8088, 184, 8}, {8104, 184, 8},
428 {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1},
429 {8126, 120, 1}, {8136, 1582, 1},
430 {8152,4, 2},
431 {8170,6, 2},
432 {81868, 182
433
434 {8544, 8, 16},
435 {11264, 24, 47},
436 {11363, 136, 1},
437 {11373, 104, 1},
438
439
440 {11506, 0, 1},*8028020F606606809F8C0B, 0x03600001,
441 {42877, 94, 1},
442 {42893, 86, 1},
443 {42922, 80, 1},
444 {42925, 82, 1},
445 {42929, 840, 831, 68, 1},
446 {429325268, 65341, 65373,
447 65450,
448 65506,
449 8028020F606809F8C0B, 0x03600001,
450 03600001,
451 0x03ECA401,
452 0x03F88033,
453 0x03FC6807,
454 0x03FFE405,
455 0x0406400C,
456 0x040E7C01,
457 0x04247C01,
458 0x0428E003,
459 0x042B9402 0x043D18 0x0441FC04, 0x0442C012,
460 0x04450004, 0x04451402,
461 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401,
462 0x00376008,
463 0x00391C09,
464 6, 0x003AEC02C80331, 0x00AF2835,
465 0x00B39406,
466 0x00B5F
467 0x00BC00D6,
468 0x00C0D802,
469 0x00C64002,
470 0x00C94001,
471 0x01370040,
472 0x029A7802,
473 0x02A00801,
474 0x02A1D004,2A3E003,
475 0x02A57C01,
476 0x02A8A40E,
477 0x02A9EC03,
478 0x02AB0401,
479 0x02AF8C0B,
480 0x03EC7801, 0x03ECA
481 0x03F8001A,
482 0x03FC040F,
483 0x03FFA007,
484 0x04063003,
485 0x040DD805,
486 0x0421DC02,
487 0x04283004,
488 0x042B2001,
489 0x04349004,
490 0x0441FC04,
491 0x04450004,
492 0x04471409,*
493 *8028020F606809F8C0, 0x03600001,
494
495 0x044D2C03,
496 0x0450D412,
497 0x04531801,
498 0x0459800D,
499 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E,
500 0x0474FC07, 0x04751C01,
501 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
502 442E, 0x05BE3C04, 0x06F27008,
503
504 0x075B0401, 0x075B6C01,
505 0x075D3C01, 0x075DBC01,
506 0x0760028C, 0x076A6C05,
507 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,
508
509 0x07C0C064, 0x07C2800F,
510 0x07C4405C, 0x07C5C03D,
511 0x07C94A,
512 0x07DC0074, 0x07DE0059
513 0x07E18028,402F, 0x07E50031,
514 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
515 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928,
516
517 4408, 4424, 447
518 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
519 36, 61880, 61914, 61948, 61998, 62122,
520 62154, 62200, 62218, 62302, 62364
521 62554,
522 62924char aChar[] = {
523 '\0', '/*
524 *8028'u', 'y', 'y', 'a', 'c',
525 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
526 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
527 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
528 'u', 's', 't', 'h'
+10 -5
--- src/update.c
+++ src/update.c
@@ -715,14 +715,18 @@
715715
int vid;
716716
vid = db_lget_int("checkout", 0);
717717
vfile_check_signature(vid, 0);
718718
db_multi_exec(
719719
"DELETE FROM vmerge;"
720
- "INSERT INTO torevert "
721
- "SELECT pathname"
722
- " FROM vfile "
723
- " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
720
+ "INSERT OR IGNORE INTO torevert "
721
+ " SELECT pathname"
722
+ " FROM vfile "
723
+ " WHERE chnged OR deleted OR rid=0 OR pathname!=origname "
724
+ " UNION ALL "
725
+ " SELECT origname"
726
+ " FROM vfile"
727
+ " WHERE origname!=pathname;"
724728
);
725729
}
726730
blob_zero(&record);
727731
db_prepare(&q, "SELECT name FROM torevert");
728732
if( zRevision==0 ){
@@ -736,11 +740,12 @@
736740
zFile = db_column_text(&q, 0);
737741
zFull = mprintf("%/%/", g.zLocalRoot, zFile);
738742
errCode = historical_version_of_file(zRevision, zFile, &record,
739743
&isLink, &isExe, 0, 2);
740744
if( errCode==2 ){
741
- if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
745
+ if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
746
+ zFile, zFile)==0 ){
742747
fossil_print("UNMANAGE: %s\n", zFile);
743748
}else{
744749
undo_save(zFile);
745750
file_delete(zFull);
746751
fossil_print("DELETE: %s\n", zFile);
747752
--- src/update.c
+++ src/update.c
@@ -715,14 +715,18 @@
715 int vid;
716 vid = db_lget_int("checkout", 0);
717 vfile_check_signature(vid, 0);
718 db_multi_exec(
719 "DELETE FROM vmerge;"
720 "INSERT INTO torevert "
721 "SELECT pathname"
722 " FROM vfile "
723 " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
 
 
 
 
724 );
725 }
726 blob_zero(&record);
727 db_prepare(&q, "SELECT name FROM torevert");
728 if( zRevision==0 ){
@@ -736,11 +740,12 @@
736 zFile = db_column_text(&q, 0);
737 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
738 errCode = historical_version_of_file(zRevision, zFile, &record,
739 &isLink, &isExe, 0, 2);
740 if( errCode==2 ){
741 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
 
742 fossil_print("UNMANAGE: %s\n", zFile);
743 }else{
744 undo_save(zFile);
745 file_delete(zFull);
746 fossil_print("DELETE: %s\n", zFile);
747
--- src/update.c
+++ src/update.c
@@ -715,14 +715,18 @@
715 int vid;
716 vid = db_lget_int("checkout", 0);
717 vfile_check_signature(vid, 0);
718 db_multi_exec(
719 "DELETE FROM vmerge;"
720 "INSERT OR IGNORE INTO torevert "
721 " SELECT pathname"
722 " FROM vfile "
723 " WHERE chnged OR deleted OR rid=0 OR pathname!=origname "
724 " UNION ALL "
725 " SELECT origname"
726 " FROM vfile"
727 " WHERE origname!=pathname;"
728 );
729 }
730 blob_zero(&record);
731 db_prepare(&q, "SELECT name FROM torevert");
732 if( zRevision==0 ){
@@ -736,11 +740,12 @@
740 zFile = db_column_text(&q, 0);
741 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
742 errCode = historical_version_of_file(zRevision, zFile, &record,
743 &isLink, &isExe, 0, 2);
744 if( errCode==2 ){
745 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
746 zFile, zFile)==0 ){
747 fossil_print("UNMANAGE: %s\n", zFile);
748 }else{
749 undo_save(zFile);
750 file_delete(zFull);
751 fossil_print("DELETE: %s\n", zFile);
752
+7 -3
--- src/user.c
+++ src/user.c
@@ -303,15 +303,17 @@
303303
**
304304
** (2) If the local database is open, check in VVAR.
305305
**
306306
** (3) Check the default user in the repository
307307
**
308
-** (4) Try the USER environment variable.
308
+** (4) Try the FOSSIL_USER environment variable.
309
+**
310
+** (5) Try the USER environment variable.
309311
**
310
-** (5) Try the USERNAME environment variable.
312
+** (6) Try the USERNAME environment variable.
311313
**
312
-** (6) Check if the user can be extracted from the remote URL.
314
+** (7) Check if the user can be extracted from the remote URL.
313315
**
314316
** The user name is stored in g.zLogin. The uid is in g.userUid.
315317
*/
316318
void user_select(void){
317319
char *zUrl;
@@ -326,10 +328,12 @@
326328
}
327329
328330
if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;
329331
330332
if( attempt_user(db_get("default-user", 0)) ) return;
333
+
334
+ if( attempt_user(fossil_getenv("FOSSIL_USER")) ) return;
331335
332336
if( attempt_user(fossil_getenv("USER")) ) return;
333337
334338
if( attempt_user(fossil_getenv("USERNAME")) ) return;
335339
336340
--- src/user.c
+++ src/user.c
@@ -303,15 +303,17 @@
303 **
304 ** (2) If the local database is open, check in VVAR.
305 **
306 ** (3) Check the default user in the repository
307 **
308 ** (4) Try the USER environment variable.
 
 
309 **
310 ** (5) Try the USERNAME environment variable.
311 **
312 ** (6) Check if the user can be extracted from the remote URL.
313 **
314 ** The user name is stored in g.zLogin. The uid is in g.userUid.
315 */
316 void user_select(void){
317 char *zUrl;
@@ -326,10 +328,12 @@
326 }
327
328 if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;
329
330 if( attempt_user(db_get("default-user", 0)) ) return;
 
 
331
332 if( attempt_user(fossil_getenv("USER")) ) return;
333
334 if( attempt_user(fossil_getenv("USERNAME")) ) return;
335
336
--- src/user.c
+++ src/user.c
@@ -303,15 +303,17 @@
303 **
304 ** (2) If the local database is open, check in VVAR.
305 **
306 ** (3) Check the default user in the repository
307 **
308 ** (4) Try the FOSSIL_USER environment variable.
309 **
310 ** (5) Try the USER environment variable.
311 **
312 ** (6) Try the USERNAME environment variable.
313 **
314 ** (7) Check if the user can be extracted from the remote URL.
315 **
316 ** The user name is stored in g.zLogin. The uid is in g.userUid.
317 */
318 void user_select(void){
319 char *zUrl;
@@ -326,10 +328,12 @@
328 }
329
330 if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;
331
332 if( attempt_user(db_get("default-user", 0)) ) return;
333
334 if( attempt_user(fossil_getenv("FOSSIL_USER")) ) return;
335
336 if( attempt_user(fossil_getenv("USER")) ) return;
337
338 if( attempt_user(fossil_getenv("USERNAME")) ) return;
339
340
+3 -3
--- src/utf8.c
+++ src/utf8.c
@@ -101,11 +101,11 @@
101101
#else
102102
/* No-op on unix */
103103
#endif
104104
}
105105
106
-#if defined(__APPLE__)
106
+#if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107107
# include <iconv.h>
108108
#endif
109109
110110
/*
111111
** Translate text from the filename character set into
@@ -120,11 +120,11 @@
120120
if( zUtf==0 ){
121121
return 0;
122122
}
123123
WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0);
124124
return zUtf;
125
-#elif defined(__APPLE__)
125
+#elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
126126
char *zIn = (char*)zFilename;
127127
char *zOut;
128128
iconv_t cd;
129129
size_t n, x;
130130
for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){}
@@ -157,11 +157,11 @@
157157
** fossil_filename_to_utf8().
158158
*/
159159
void fossil_filename_free(char *pOld){
160160
#if defined(_WIN32)
161161
sqlite3_free(pOld);
162
-#elif defined(__APPLE__)
162
+#elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
163163
fossil_free(pOld);
164164
#else
165165
/* No-op on all other unix */
166166
#endif
167167
}
168168
--- src/utf8.c
+++ src/utf8.c
@@ -101,11 +101,11 @@
101 #else
102 /* No-op on unix */
103 #endif
104 }
105
106 #if defined(__APPLE__)
107 # include <iconv.h>
108 #endif
109
110 /*
111 ** Translate text from the filename character set into
@@ -120,11 +120,11 @@
120 if( zUtf==0 ){
121 return 0;
122 }
123 WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0);
124 return zUtf;
125 #elif defined(__APPLE__)
126 char *zIn = (char*)zFilename;
127 char *zOut;
128 iconv_t cd;
129 size_t n, x;
130 for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){}
@@ -157,11 +157,11 @@
157 ** fossil_filename_to_utf8().
158 */
159 void fossil_filename_free(char *pOld){
160 #if defined(_WIN32)
161 sqlite3_free(pOld);
162 #elif defined(__APPLE__)
163 fossil_free(pOld);
164 #else
165 /* No-op on all other unix */
166 #endif
167 }
168
--- src/utf8.c
+++ src/utf8.c
@@ -101,11 +101,11 @@
101 #else
102 /* No-op on unix */
103 #endif
104 }
105
106 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107 # include <iconv.h>
108 #endif
109
110 /*
111 ** Translate text from the filename character set into
@@ -120,11 +120,11 @@
120 if( zUtf==0 ){
121 return 0;
122 }
123 WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0);
124 return zUtf;
125 #elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
126 char *zIn = (char*)zFilename;
127 char *zOut;
128 iconv_t cd;
129 size_t n, x;
130 for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){}
@@ -157,11 +157,11 @@
157 ** fossil_filename_to_utf8().
158 */
159 void fossil_filename_free(char *pOld){
160 #if defined(_WIN32)
161 sqlite3_free(pOld);
162 #elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
163 fossil_free(pOld);
164 #else
165 /* No-op on all other unix */
166 #endif
167 }
168
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -667,11 +667,11 @@
667667
if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
668668
blob_init(&w2, pW2->zWiki, -1);
669669
}
670670
blob_zero(&d);
671671
diffFlags = construct_diff_flags(1,0);
672
- text_diff(&w2, &w1, &d, diffFlags | DIFF_HTML | DIFF_LINENO);
672
+ text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
673673
@ <div class="udiff">
674674
@ %s(blob_str(&d))
675675
@ </div>
676676
manifest_destroy(pW1);
677677
manifest_destroy(pW2);
678678
--- src/wiki.c
+++ src/wiki.c
@@ -667,11 +667,11 @@
667 if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
668 blob_init(&w2, pW2->zWiki, -1);
669 }
670 blob_zero(&d);
671 diffFlags = construct_diff_flags(1,0);
672 text_diff(&w2, &w1, &d, diffFlags | DIFF_HTML | DIFF_LINENO);
673 @ <div class="udiff">
674 @ %s(blob_str(&d))
675 @ </div>
676 manifest_destroy(pW1);
677 manifest_destroy(pW2);
678
--- src/wiki.c
+++ src/wiki.c
@@ -667,11 +667,11 @@
667 if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
668 blob_init(&w2, pW2->zWiki, -1);
669 }
670 blob_zero(&d);
671 diffFlags = construct_diff_flags(1,0);
672 text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
673 @ <div class="udiff">
674 @ %s(blob_str(&d))
675 @ </div>
676 manifest_destroy(pW1);
677 manifest_destroy(pW2);
678
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -18,10 +18,33 @@
1818
* <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6"
1919
target="testwindow">Large diff of sqlite3.c</a>. This diff was very
2020
slow prior to the preformance enhancement change [9e15437e97].
2121
* <a href="../../../info/bda00cbada#chunk42" target="testwindow">
2222
A difficult indentation change.
23
+ * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13"
24
+ target="testwindow">Another tricky indentation.</a> Notice especially
25
+ lines 59398 and 59407 on the left.
26
+ * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13"
27
+ target="testwindow">Inverse of the previous.</a>
28
+ * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk24"
29
+ target="testwindow">A complex change</a> that is difficult to align, and
30
+ hence falls back to the "delete left and insert right" strategy.
31
+ * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk24"
32
+ target="testwindow">Inverse of the previous.</a>
33
+ * <a href="../../../fdiff?v1=21f9a00fe2fa4a17&v2=d5c4ff0532bd89c3#chunk5"
34
+ target="testwindow">sqlite3.c changes</a>
35
+ that are difficult to align.
36
+ * <a href="../../../fdiff?v2=21f9a00fe2fa4a17&v1=d5c4ff0532bd89c3#chunk5"
37
+ target="testwindow">sqlite3.c changes inverted.</a>
2338
2439
External:
2540
2641
* <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
2742
Code indentation change.</a>
43
+ * <a href="http://www.sqlite.org/src/info/52e755943f" target="testwindow">
44
+ A complex change (chunk 1) in which the alignment becomes so complex
45
+ that it is better for clarity to abandon it and just show the left
46
+ and right sides contiguously.</a>
47
+ * <a href="http://www.sqlite.org/src/info/3d65c70343#chunk5"
48
+ target="testwindow">
49
+ An indentation change. See especially lines 2313 and 2317 on the right,
50
+ that their green indentation addition is left-justified.</a>
2851
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -18,10 +18,33 @@
18 * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6"
19 target="testwindow">Large diff of sqlite3.c</a>. This diff was very
20 slow prior to the preformance enhancement change [9e15437e97].
21 * <a href="../../../info/bda00cbada#chunk42" target="testwindow">
22 A difficult indentation change.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 External:
25
26 * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
27 Code indentation change.</a>
 
 
 
 
 
 
 
 
28
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -18,10 +18,33 @@
18 * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6"
19 target="testwindow">Large diff of sqlite3.c</a>. This diff was very
20 slow prior to the preformance enhancement change [9e15437e97].
21 * <a href="../../../info/bda00cbada#chunk42" target="testwindow">
22 A difficult indentation change.
23 * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13"
24 target="testwindow">Another tricky indentation.</a> Notice especially
25 lines 59398 and 59407 on the left.
26 * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13"
27 target="testwindow">Inverse of the previous.</a>
28 * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk24"
29 target="testwindow">A complex change</a> that is difficult to align, and
30 hence falls back to the "delete left and insert right" strategy.
31 * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk24"
32 target="testwindow">Inverse of the previous.</a>
33 * <a href="../../../fdiff?v1=21f9a00fe2fa4a17&v2=d5c4ff0532bd89c3#chunk5"
34 target="testwindow">sqlite3.c changes</a>
35 that are difficult to align.
36 * <a href="../../../fdiff?v2=21f9a00fe2fa4a17&v1=d5c4ff0532bd89c3#chunk5"
37 target="testwindow">sqlite3.c changes inverted.</a>
38
39 External:
40
41 * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
42 Code indentation change.</a>
43 * <a href="http://www.sqlite.org/src/info/52e755943f" target="testwindow">
44 A complex change (chunk 1) in which the alignment becomes so complex
45 that it is better for clarity to abandon it and just show the left
46 and right sides contiguously.</a>
47 * <a href="http://www.sqlite.org/src/info/3d65c70343#chunk5"
48 target="testwindow">
49 An indentation change. See especially lines 2313 and 2317 on the right,
50 that their green indentation addition is left-justified.</a>
51
+16 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
2929
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
3030
31
-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_dir_.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 markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c 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 utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
31
+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_dir_.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 markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3232
33
-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_dir$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)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\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)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
33
+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_dir$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)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3434
3535
3636
RC=$(DMDIR)\bin\rcc
3737
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
3838
@@ -46,11 +46,11 @@
4646
4747
$(OBJDIR)\fossil.res: $B\win\fossil.rc
4848
$(RC) $(RCFLAGS) -o$@ $**
4949
5050
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51
- +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_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate 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 utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
51
+ +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_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5252
+echo fossil >> $@
5353
+echo fossil >> $@
5454
+echo $(LIBS) >> $@
5555
+echo. >> $@
5656
+echo fossil >> $@
@@ -523,10 +523,16 @@
523523
$(OBJDIR)\rebuild$O : rebuild_.c rebuild.h
524524
$(TCC) -o$@ -c rebuild_.c
525525
526526
rebuild_.c : $(SRCDIR)\rebuild.c
527527
+translate$E $** > $@
528
+
529
+$(OBJDIR)\regexp$O : regexp_.c regexp.h
530
+ $(TCC) -o$@ -c regexp_.c
531
+
532
+regexp_.c : $(SRCDIR)\regexp.c
533
+ +translate$E $** > $@
528534
529535
$(OBJDIR)\report$O : report_.c report.h
530536
$(TCC) -o$@ -c report_.c
531537
532538
report_.c : $(SRCDIR)\report.c
@@ -643,10 +649,16 @@
643649
$(OBJDIR)\undo$O : undo_.c undo.h
644650
$(TCC) -o$@ -c undo_.c
645651
646652
undo_.c : $(SRCDIR)\undo.c
647653
+translate$E $** > $@
654
+
655
+$(OBJDIR)\unicode$O : unicode_.c unicode.h
656
+ $(TCC) -o$@ -c unicode_.c
657
+
658
+unicode_.c : $(SRCDIR)\unicode.c
659
+ +translate$E $** > $@
648660
649661
$(OBJDIR)\update$O : update_.c update.h
650662
$(TCC) -o$@ -c update_.c
651663
652664
update_.c : $(SRCDIR)\update.c
@@ -723,7 +735,7 @@
723735
724736
zip_.c : $(SRCDIR)\zip.c
725737
+translate$E $** > $@
726738
727739
headers: makeheaders$E page_index.h VERSION.h
728
- +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_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h 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 utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
740
+ +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_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
729741
@copy /Y nul: headers
730742
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 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
30
31 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_dir_.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 markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c 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 utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 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_dir$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)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\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)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +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_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate 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 utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -523,10 +523,16 @@
523 $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h
524 $(TCC) -o$@ -c rebuild_.c
525
526 rebuild_.c : $(SRCDIR)\rebuild.c
527 +translate$E $** > $@
 
 
 
 
 
 
528
529 $(OBJDIR)\report$O : report_.c report.h
530 $(TCC) -o$@ -c report_.c
531
532 report_.c : $(SRCDIR)\report.c
@@ -643,10 +649,16 @@
643 $(OBJDIR)\undo$O : undo_.c undo.h
644 $(TCC) -o$@ -c undo_.c
645
646 undo_.c : $(SRCDIR)\undo.c
647 +translate$E $** > $@
 
 
 
 
 
 
648
649 $(OBJDIR)\update$O : update_.c update.h
650 $(TCC) -o$@ -c update_.c
651
652 update_.c : $(SRCDIR)\update.c
@@ -723,7 +735,7 @@
723
724 zip_.c : $(SRCDIR)\zip.c
725 +translate$E $** > $@
726
727 headers: makeheaders$E page_index.h VERSION.h
728 +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_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h 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 utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
729 @copy /Y nul: headers
730
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 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
30
31 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_dir_.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 markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 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_dir$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)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +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_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -523,10 +523,16 @@
523 $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h
524 $(TCC) -o$@ -c rebuild_.c
525
526 rebuild_.c : $(SRCDIR)\rebuild.c
527 +translate$E $** > $@
528
529 $(OBJDIR)\regexp$O : regexp_.c regexp.h
530 $(TCC) -o$@ -c regexp_.c
531
532 regexp_.c : $(SRCDIR)\regexp.c
533 +translate$E $** > $@
534
535 $(OBJDIR)\report$O : report_.c report.h
536 $(TCC) -o$@ -c report_.c
537
538 report_.c : $(SRCDIR)\report.c
@@ -643,10 +649,16 @@
649 $(OBJDIR)\undo$O : undo_.c undo.h
650 $(TCC) -o$@ -c undo_.c
651
652 undo_.c : $(SRCDIR)\undo.c
653 +translate$E $** > $@
654
655 $(OBJDIR)\unicode$O : unicode_.c unicode.h
656 $(TCC) -o$@ -c unicode_.c
657
658 unicode_.c : $(SRCDIR)\unicode.c
659 +translate$E $** > $@
660
661 $(OBJDIR)\update$O : update_.c update.h
662 $(TCC) -o$@ -c update_.c
663
664 update_.c : $(SRCDIR)\update.c
@@ -723,7 +735,7 @@
735
736 zip_.c : $(SRCDIR)\zip.c
737 +translate$E $** > $@
738
739 headers: makeheaders$E page_index.h VERSION.h
740 +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_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
741 @copy /Y nul: headers
742
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -69,11 +69,11 @@
6969
7070
#### Check if the workaround for the MinGW command line handling needs to
7171
# be enabled by default.
7272
#
7373
ifndef BROKEN_MINGW_CMDLINE
74
-ifeq ($(PREFIX),)
74
+ifeq (,$(findstring w64-mingw32,$(PREFIX)))
7575
BROKEN_MINGW_CMDLINE = 1
7676
endif
7777
endif
7878
7979
#### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322322
$(SRCDIR)/pivot.c \
323323
$(SRCDIR)/popen.c \
324324
$(SRCDIR)/pqueue.c \
325325
$(SRCDIR)/printf.c \
326326
$(SRCDIR)/rebuild.c \
327
+ $(SRCDIR)/regexp.c \
327328
$(SRCDIR)/report.c \
328329
$(SRCDIR)/rss.c \
329330
$(SRCDIR)/schema.c \
330331
$(SRCDIR)/search.c \
331332
$(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
342343
$(SRCDIR)/th_main.c \
343344
$(SRCDIR)/timeline.c \
344345
$(SRCDIR)/tkt.c \
345346
$(SRCDIR)/tktsetup.c \
346347
$(SRCDIR)/undo.c \
348
+ $(SRCDIR)/unicode.c \
347349
$(SRCDIR)/update.c \
348350
$(SRCDIR)/url.c \
349351
$(SRCDIR)/user.c \
350352
$(SRCDIR)/utf8.c \
351353
$(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
426428
$(OBJDIR)/pivot_.c \
427429
$(OBJDIR)/popen_.c \
428430
$(OBJDIR)/pqueue_.c \
429431
$(OBJDIR)/printf_.c \
430432
$(OBJDIR)/rebuild_.c \
433
+ $(OBJDIR)/regexp_.c \
431434
$(OBJDIR)/report_.c \
432435
$(OBJDIR)/rss_.c \
433436
$(OBJDIR)/schema_.c \
434437
$(OBJDIR)/search_.c \
435438
$(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
446449
$(OBJDIR)/th_main_.c \
447450
$(OBJDIR)/timeline_.c \
448451
$(OBJDIR)/tkt_.c \
449452
$(OBJDIR)/tktsetup_.c \
450453
$(OBJDIR)/undo_.c \
454
+ $(OBJDIR)/unicode_.c \
451455
$(OBJDIR)/update_.c \
452456
$(OBJDIR)/url_.c \
453457
$(OBJDIR)/user_.c \
454458
$(OBJDIR)/utf8_.c \
455459
$(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
530534
$(OBJDIR)/pivot.o \
531535
$(OBJDIR)/popen.o \
532536
$(OBJDIR)/pqueue.o \
533537
$(OBJDIR)/printf.o \
534538
$(OBJDIR)/rebuild.o \
539
+ $(OBJDIR)/regexp.o \
535540
$(OBJDIR)/report.o \
536541
$(OBJDIR)/rss.o \
537542
$(OBJDIR)/schema.o \
538543
$(OBJDIR)/search.o \
539544
$(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
550555
$(OBJDIR)/th_main.o \
551556
$(OBJDIR)/timeline.o \
552557
$(OBJDIR)/tkt.o \
553558
$(OBJDIR)/tktsetup.o \
554559
$(OBJDIR)/undo.o \
560
+ $(OBJDIR)/unicode.o \
555561
$(OBJDIR)/update.o \
556562
$(OBJDIR)/url.o \
557563
$(OBJDIR)/user.o \
558564
$(OBJDIR)/utf8.o \
559565
$(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
747753
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
748754
$(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
749755
$(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
750756
$(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
751757
$(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
758
+ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
752759
$(OBJDIR)/report_.c:$(OBJDIR)/report.h \
753760
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
754761
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
755762
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
756763
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
767774
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
768775
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
769776
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
770777
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
771778
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
779
+ $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
772780
$(OBJDIR)/update_.c:$(OBJDIR)/update.h \
773781
$(OBJDIR)/url_.c:$(OBJDIR)/url.h \
774782
$(OBJDIR)/user_.c:$(OBJDIR)/user.h \
775783
$(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
776784
$(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
13401348
13411349
$(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
13421350
$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
13431351
13441352
$(OBJDIR)/rebuild.h: $(OBJDIR)/headers
1353
+
1354
+$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
1355
+ $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
1356
+
1357
+$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
1358
+ $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
1359
+
1360
+$(OBJDIR)/regexp.h: $(OBJDIR)/headers
13451361
13461362
$(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
13471363
$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
13481364
13491365
$(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
15001516
15011517
$(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
15021518
$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
15031519
15041520
$(OBJDIR)/undo.h: $(OBJDIR)/headers
1521
+
1522
+$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1523
+ $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1524
+
1525
+$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1526
+ $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1527
+
1528
+$(OBJDIR)/unicode.h: $(OBJDIR)/headers
15051529
15061530
$(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
15071531
$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
15081532
15091533
$(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
15101534
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -69,11 +69,11 @@
69
70 #### Check if the workaround for the MinGW command line handling needs to
71 # be enabled by default.
72 #
73 ifndef BROKEN_MINGW_CMDLINE
74 ifeq ($(PREFIX),)
75 BROKEN_MINGW_CMDLINE = 1
76 endif
77 endif
78
79 #### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322 $(SRCDIR)/pivot.c \
323 $(SRCDIR)/popen.c \
324 $(SRCDIR)/pqueue.c \
325 $(SRCDIR)/printf.c \
326 $(SRCDIR)/rebuild.c \
 
327 $(SRCDIR)/report.c \
328 $(SRCDIR)/rss.c \
329 $(SRCDIR)/schema.c \
330 $(SRCDIR)/search.c \
331 $(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
342 $(SRCDIR)/th_main.c \
343 $(SRCDIR)/timeline.c \
344 $(SRCDIR)/tkt.c \
345 $(SRCDIR)/tktsetup.c \
346 $(SRCDIR)/undo.c \
 
347 $(SRCDIR)/update.c \
348 $(SRCDIR)/url.c \
349 $(SRCDIR)/user.c \
350 $(SRCDIR)/utf8.c \
351 $(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
426 $(OBJDIR)/pivot_.c \
427 $(OBJDIR)/popen_.c \
428 $(OBJDIR)/pqueue_.c \
429 $(OBJDIR)/printf_.c \
430 $(OBJDIR)/rebuild_.c \
 
431 $(OBJDIR)/report_.c \
432 $(OBJDIR)/rss_.c \
433 $(OBJDIR)/schema_.c \
434 $(OBJDIR)/search_.c \
435 $(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
446 $(OBJDIR)/th_main_.c \
447 $(OBJDIR)/timeline_.c \
448 $(OBJDIR)/tkt_.c \
449 $(OBJDIR)/tktsetup_.c \
450 $(OBJDIR)/undo_.c \
 
451 $(OBJDIR)/update_.c \
452 $(OBJDIR)/url_.c \
453 $(OBJDIR)/user_.c \
454 $(OBJDIR)/utf8_.c \
455 $(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
530 $(OBJDIR)/pivot.o \
531 $(OBJDIR)/popen.o \
532 $(OBJDIR)/pqueue.o \
533 $(OBJDIR)/printf.o \
534 $(OBJDIR)/rebuild.o \
 
535 $(OBJDIR)/report.o \
536 $(OBJDIR)/rss.o \
537 $(OBJDIR)/schema.o \
538 $(OBJDIR)/search.o \
539 $(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
550 $(OBJDIR)/th_main.o \
551 $(OBJDIR)/timeline.o \
552 $(OBJDIR)/tkt.o \
553 $(OBJDIR)/tktsetup.o \
554 $(OBJDIR)/undo.o \
 
555 $(OBJDIR)/update.o \
556 $(OBJDIR)/url.o \
557 $(OBJDIR)/user.o \
558 $(OBJDIR)/utf8.o \
559 $(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
747 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
748 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
749 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
750 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
751 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
 
752 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
753 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
754 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
755 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
756 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
767 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
768 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
769 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
770 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
771 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
 
772 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
773 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
774 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
775 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
776 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
1340
1341 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
1342 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
1343
1344 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1345
1346 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
1347 $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
1348
1349 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
1500
1501 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1502 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1503
1504 $(OBJDIR)/undo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1505
1506 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1507 $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1508
1509 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1510
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -69,11 +69,11 @@
69
70 #### Check if the workaround for the MinGW command line handling needs to
71 # be enabled by default.
72 #
73 ifndef BROKEN_MINGW_CMDLINE
74 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
75 BROKEN_MINGW_CMDLINE = 1
76 endif
77 endif
78
79 #### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322 $(SRCDIR)/pivot.c \
323 $(SRCDIR)/popen.c \
324 $(SRCDIR)/pqueue.c \
325 $(SRCDIR)/printf.c \
326 $(SRCDIR)/rebuild.c \
327 $(SRCDIR)/regexp.c \
328 $(SRCDIR)/report.c \
329 $(SRCDIR)/rss.c \
330 $(SRCDIR)/schema.c \
331 $(SRCDIR)/search.c \
332 $(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
343 $(SRCDIR)/th_main.c \
344 $(SRCDIR)/timeline.c \
345 $(SRCDIR)/tkt.c \
346 $(SRCDIR)/tktsetup.c \
347 $(SRCDIR)/undo.c \
348 $(SRCDIR)/unicode.c \
349 $(SRCDIR)/update.c \
350 $(SRCDIR)/url.c \
351 $(SRCDIR)/user.c \
352 $(SRCDIR)/utf8.c \
353 $(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
428 $(OBJDIR)/pivot_.c \
429 $(OBJDIR)/popen_.c \
430 $(OBJDIR)/pqueue_.c \
431 $(OBJDIR)/printf_.c \
432 $(OBJDIR)/rebuild_.c \
433 $(OBJDIR)/regexp_.c \
434 $(OBJDIR)/report_.c \
435 $(OBJDIR)/rss_.c \
436 $(OBJDIR)/schema_.c \
437 $(OBJDIR)/search_.c \
438 $(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
449 $(OBJDIR)/th_main_.c \
450 $(OBJDIR)/timeline_.c \
451 $(OBJDIR)/tkt_.c \
452 $(OBJDIR)/tktsetup_.c \
453 $(OBJDIR)/undo_.c \
454 $(OBJDIR)/unicode_.c \
455 $(OBJDIR)/update_.c \
456 $(OBJDIR)/url_.c \
457 $(OBJDIR)/user_.c \
458 $(OBJDIR)/utf8_.c \
459 $(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
534 $(OBJDIR)/pivot.o \
535 $(OBJDIR)/popen.o \
536 $(OBJDIR)/pqueue.o \
537 $(OBJDIR)/printf.o \
538 $(OBJDIR)/rebuild.o \
539 $(OBJDIR)/regexp.o \
540 $(OBJDIR)/report.o \
541 $(OBJDIR)/rss.o \
542 $(OBJDIR)/schema.o \
543 $(OBJDIR)/search.o \
544 $(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
555 $(OBJDIR)/th_main.o \
556 $(OBJDIR)/timeline.o \
557 $(OBJDIR)/tkt.o \
558 $(OBJDIR)/tktsetup.o \
559 $(OBJDIR)/undo.o \
560 $(OBJDIR)/unicode.o \
561 $(OBJDIR)/update.o \
562 $(OBJDIR)/url.o \
563 $(OBJDIR)/user.o \
564 $(OBJDIR)/utf8.o \
565 $(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
753 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
754 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
755 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
756 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
757 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
758 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
759 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
760 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
761 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
762 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
763 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
774 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
775 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
776 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
777 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
778 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
779 $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
780 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
781 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
782 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
783 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
784 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
1348
1349 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
1350 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
1351
1352 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
1353
1354 $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
1355 $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
1356
1357 $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
1358 $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
1359
1360 $(OBJDIR)/regexp.h: $(OBJDIR)/headers
1361
1362 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
1363 $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
1364
1365 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
1516
1517 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1518 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1519
1520 $(OBJDIR)/undo.h: $(OBJDIR)/headers
1521
1522 $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1523 $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1524
1525 $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1526 $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1527
1528 $(OBJDIR)/unicode.h: $(OBJDIR)/headers
1529
1530 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1531 $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1532
1533 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1534
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -69,11 +69,11 @@
6969
7070
#### Check if the workaround for the MinGW command line handling needs to
7171
# be enabled by default.
7272
#
7373
ifndef BROKEN_MINGW_CMDLINE
74
-ifeq ($(PREFIX),)
74
+ifeq (,$(findstring w64-mingw32,$(PREFIX)))
7575
BROKEN_MINGW_CMDLINE = 1
7676
endif
7777
endif
7878
7979
#### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322322
$(SRCDIR)/pivot.c \
323323
$(SRCDIR)/popen.c \
324324
$(SRCDIR)/pqueue.c \
325325
$(SRCDIR)/printf.c \
326326
$(SRCDIR)/rebuild.c \
327
+ $(SRCDIR)/regexp.c \
327328
$(SRCDIR)/report.c \
328329
$(SRCDIR)/rss.c \
329330
$(SRCDIR)/schema.c \
330331
$(SRCDIR)/search.c \
331332
$(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
342343
$(SRCDIR)/th_main.c \
343344
$(SRCDIR)/timeline.c \
344345
$(SRCDIR)/tkt.c \
345346
$(SRCDIR)/tktsetup.c \
346347
$(SRCDIR)/undo.c \
348
+ $(SRCDIR)/unicode.c \
347349
$(SRCDIR)/update.c \
348350
$(SRCDIR)/url.c \
349351
$(SRCDIR)/user.c \
350352
$(SRCDIR)/utf8.c \
351353
$(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
426428
$(OBJDIR)/pivot_.c \
427429
$(OBJDIR)/popen_.c \
428430
$(OBJDIR)/pqueue_.c \
429431
$(OBJDIR)/printf_.c \
430432
$(OBJDIR)/rebuild_.c \
433
+ $(OBJDIR)/regexp_.c \
431434
$(OBJDIR)/report_.c \
432435
$(OBJDIR)/rss_.c \
433436
$(OBJDIR)/schema_.c \
434437
$(OBJDIR)/search_.c \
435438
$(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
446449
$(OBJDIR)/th_main_.c \
447450
$(OBJDIR)/timeline_.c \
448451
$(OBJDIR)/tkt_.c \
449452
$(OBJDIR)/tktsetup_.c \
450453
$(OBJDIR)/undo_.c \
454
+ $(OBJDIR)/unicode_.c \
451455
$(OBJDIR)/update_.c \
452456
$(OBJDIR)/url_.c \
453457
$(OBJDIR)/user_.c \
454458
$(OBJDIR)/utf8_.c \
455459
$(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
530534
$(OBJDIR)/pivot.o \
531535
$(OBJDIR)/popen.o \
532536
$(OBJDIR)/pqueue.o \
533537
$(OBJDIR)/printf.o \
534538
$(OBJDIR)/rebuild.o \
539
+ $(OBJDIR)/regexp.o \
535540
$(OBJDIR)/report.o \
536541
$(OBJDIR)/rss.o \
537542
$(OBJDIR)/schema.o \
538543
$(OBJDIR)/search.o \
539544
$(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
550555
$(OBJDIR)/th_main.o \
551556
$(OBJDIR)/timeline.o \
552557
$(OBJDIR)/tkt.o \
553558
$(OBJDIR)/tktsetup.o \
554559
$(OBJDIR)/undo.o \
560
+ $(OBJDIR)/unicode.o \
555561
$(OBJDIR)/update.o \
556562
$(OBJDIR)/url.o \
557563
$(OBJDIR)/user.o \
558564
$(OBJDIR)/utf8.o \
559565
$(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
747753
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
748754
$(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
749755
$(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
750756
$(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
751757
$(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
758
+ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
752759
$(OBJDIR)/report_.c:$(OBJDIR)/report.h \
753760
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
754761
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
755762
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
756763
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
767774
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
768775
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
769776
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
770777
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
771778
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
779
+ $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
772780
$(OBJDIR)/update_.c:$(OBJDIR)/update.h \
773781
$(OBJDIR)/url_.c:$(OBJDIR)/url.h \
774782
$(OBJDIR)/user_.c:$(OBJDIR)/user.h \
775783
$(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
776784
$(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
13401348
13411349
$(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
13421350
$(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
13431351
13441352
$(OBJDIR)/rebuild.h: $(OBJDIR)/headers
1353
+
1354
+$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
1355
+ $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
1356
+
1357
+$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
1358
+ $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
1359
+
1360
+$(OBJDIR)/regexp.h: $(OBJDIR)/headers
13451361
13461362
$(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
13471363
$(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
13481364
13491365
$(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
15001516
15011517
$(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
15021518
$(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
15031519
15041520
$(OBJDIR)/undo.h: $(OBJDIR)/headers
1521
+
1522
+$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1523
+ $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1524
+
1525
+$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1526
+ $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1527
+
1528
+$(OBJDIR)/unicode.h: $(OBJDIR)/headers
15051529
15061530
$(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
15071531
$(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
15081532
15091533
$(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
15101534
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -69,11 +69,11 @@
69
70 #### Check if the workaround for the MinGW command line handling needs to
71 # be enabled by default.
72 #
73 ifndef BROKEN_MINGW_CMDLINE
74 ifeq ($(PREFIX),)
75 BROKEN_MINGW_CMDLINE = 1
76 endif
77 endif
78
79 #### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322 $(SRCDIR)/pivot.c \
323 $(SRCDIR)/popen.c \
324 $(SRCDIR)/pqueue.c \
325 $(SRCDIR)/printf.c \
326 $(SRCDIR)/rebuild.c \
 
327 $(SRCDIR)/report.c \
328 $(SRCDIR)/rss.c \
329 $(SRCDIR)/schema.c \
330 $(SRCDIR)/search.c \
331 $(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
342 $(SRCDIR)/th_main.c \
343 $(SRCDIR)/timeline.c \
344 $(SRCDIR)/tkt.c \
345 $(SRCDIR)/tktsetup.c \
346 $(SRCDIR)/undo.c \
 
347 $(SRCDIR)/update.c \
348 $(SRCDIR)/url.c \
349 $(SRCDIR)/user.c \
350 $(SRCDIR)/utf8.c \
351 $(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
426 $(OBJDIR)/pivot_.c \
427 $(OBJDIR)/popen_.c \
428 $(OBJDIR)/pqueue_.c \
429 $(OBJDIR)/printf_.c \
430 $(OBJDIR)/rebuild_.c \
 
431 $(OBJDIR)/report_.c \
432 $(OBJDIR)/rss_.c \
433 $(OBJDIR)/schema_.c \
434 $(OBJDIR)/search_.c \
435 $(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
446 $(OBJDIR)/th_main_.c \
447 $(OBJDIR)/timeline_.c \
448 $(OBJDIR)/tkt_.c \
449 $(OBJDIR)/tktsetup_.c \
450 $(OBJDIR)/undo_.c \
 
451 $(OBJDIR)/update_.c \
452 $(OBJDIR)/url_.c \
453 $(OBJDIR)/user_.c \
454 $(OBJDIR)/utf8_.c \
455 $(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
530 $(OBJDIR)/pivot.o \
531 $(OBJDIR)/popen.o \
532 $(OBJDIR)/pqueue.o \
533 $(OBJDIR)/printf.o \
534 $(OBJDIR)/rebuild.o \
 
535 $(OBJDIR)/report.o \
536 $(OBJDIR)/rss.o \
537 $(OBJDIR)/schema.o \
538 $(OBJDIR)/search.o \
539 $(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
550 $(OBJDIR)/th_main.o \
551 $(OBJDIR)/timeline.o \
552 $(OBJDIR)/tkt.o \
553 $(OBJDIR)/tktsetup.o \
554 $(OBJDIR)/undo.o \
 
555 $(OBJDIR)/update.o \
556 $(OBJDIR)/url.o \
557 $(OBJDIR)/user.o \
558 $(OBJDIR)/utf8.o \
559 $(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
747 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
748 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
749 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
750 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
751 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
 
752 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
753 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
754 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
755 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
756 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
767 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
768 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
769 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
770 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
771 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
 
772 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
773 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
774 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
775 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
776 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
1340
1341 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
1342 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
1343
1344 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1345
1346 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
1347 $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
1348
1349 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
1500
1501 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1502 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1503
1504 $(OBJDIR)/undo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1505
1506 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1507 $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1508
1509 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1510
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -69,11 +69,11 @@
69
70 #### Check if the workaround for the MinGW command line handling needs to
71 # be enabled by default.
72 #
73 ifndef BROKEN_MINGW_CMDLINE
74 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
75 BROKEN_MINGW_CMDLINE = 1
76 endif
77 endif
78
79 #### The directories where the zlib include and library files are located.
@@ -322,10 +322,11 @@
322 $(SRCDIR)/pivot.c \
323 $(SRCDIR)/popen.c \
324 $(SRCDIR)/pqueue.c \
325 $(SRCDIR)/printf.c \
326 $(SRCDIR)/rebuild.c \
327 $(SRCDIR)/regexp.c \
328 $(SRCDIR)/report.c \
329 $(SRCDIR)/rss.c \
330 $(SRCDIR)/schema.c \
331 $(SRCDIR)/search.c \
332 $(SRCDIR)/setup.c \
@@ -342,10 +343,11 @@
343 $(SRCDIR)/th_main.c \
344 $(SRCDIR)/timeline.c \
345 $(SRCDIR)/tkt.c \
346 $(SRCDIR)/tktsetup.c \
347 $(SRCDIR)/undo.c \
348 $(SRCDIR)/unicode.c \
349 $(SRCDIR)/update.c \
350 $(SRCDIR)/url.c \
351 $(SRCDIR)/user.c \
352 $(SRCDIR)/utf8.c \
353 $(SRCDIR)/verify.c \
@@ -426,10 +428,11 @@
428 $(OBJDIR)/pivot_.c \
429 $(OBJDIR)/popen_.c \
430 $(OBJDIR)/pqueue_.c \
431 $(OBJDIR)/printf_.c \
432 $(OBJDIR)/rebuild_.c \
433 $(OBJDIR)/regexp_.c \
434 $(OBJDIR)/report_.c \
435 $(OBJDIR)/rss_.c \
436 $(OBJDIR)/schema_.c \
437 $(OBJDIR)/search_.c \
438 $(OBJDIR)/setup_.c \
@@ -446,10 +449,11 @@
449 $(OBJDIR)/th_main_.c \
450 $(OBJDIR)/timeline_.c \
451 $(OBJDIR)/tkt_.c \
452 $(OBJDIR)/tktsetup_.c \
453 $(OBJDIR)/undo_.c \
454 $(OBJDIR)/unicode_.c \
455 $(OBJDIR)/update_.c \
456 $(OBJDIR)/url_.c \
457 $(OBJDIR)/user_.c \
458 $(OBJDIR)/utf8_.c \
459 $(OBJDIR)/verify_.c \
@@ -530,10 +534,11 @@
534 $(OBJDIR)/pivot.o \
535 $(OBJDIR)/popen.o \
536 $(OBJDIR)/pqueue.o \
537 $(OBJDIR)/printf.o \
538 $(OBJDIR)/rebuild.o \
539 $(OBJDIR)/regexp.o \
540 $(OBJDIR)/report.o \
541 $(OBJDIR)/rss.o \
542 $(OBJDIR)/schema.o \
543 $(OBJDIR)/search.o \
544 $(OBJDIR)/setup.o \
@@ -550,10 +555,11 @@
555 $(OBJDIR)/th_main.o \
556 $(OBJDIR)/timeline.o \
557 $(OBJDIR)/tkt.o \
558 $(OBJDIR)/tktsetup.o \
559 $(OBJDIR)/undo.o \
560 $(OBJDIR)/unicode.o \
561 $(OBJDIR)/update.o \
562 $(OBJDIR)/url.o \
563 $(OBJDIR)/user.o \
564 $(OBJDIR)/utf8.o \
565 $(OBJDIR)/verify.o \
@@ -747,10 +753,11 @@
753 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
754 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
755 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
756 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
757 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
758 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
759 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
760 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
761 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
762 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
763 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
@@ -767,10 +774,11 @@
774 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
775 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
776 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
777 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
778 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
779 $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
780 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
781 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
782 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
783 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
784 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
@@ -1340,10 +1348,18 @@
1348
1349 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
1350 $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c
1351
1352 $(OBJDIR)/rebuild.h: $(OBJDIR)/headers
1353
1354 $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate
1355 $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c
1356
1357 $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h
1358 $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c
1359
1360 $(OBJDIR)/regexp.h: $(OBJDIR)/headers
1361
1362 $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate
1363 $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c
1364
1365 $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h
@@ -1500,10 +1516,18 @@
1516
1517 $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h
1518 $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c
1519
1520 $(OBJDIR)/undo.h: $(OBJDIR)/headers
1521
1522 $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate
1523 $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c
1524
1525 $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h
1526 $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c
1527
1528 $(OBJDIR)/unicode.h: $(OBJDIR)/headers
1529
1530 $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate
1531 $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c
1532
1533 $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h
1534
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -107,10 +107,11 @@
107107
pivot_.c \
108108
popen_.c \
109109
pqueue_.c \
110110
printf_.c \
111111
rebuild_.c \
112
+ regexp_.c \
112113
report_.c \
113114
rss_.c \
114115
schema_.c \
115116
search_.c \
116117
setup_.c \
@@ -127,10 +128,11 @@
127128
th_main_.c \
128129
timeline_.c \
129130
tkt_.c \
130131
tktsetup_.c \
131132
undo_.c \
133
+ unicode_.c \
132134
update_.c \
133135
url_.c \
134136
user_.c \
135137
utf8_.c \
136138
verify_.c \
@@ -210,10 +212,11 @@
210212
$(OX)\pivot$O \
211213
$(OX)\popen$O \
212214
$(OX)\pqueue$O \
213215
$(OX)\printf$O \
214216
$(OX)\rebuild$O \
217
+ $(OX)\regexp$O \
215218
$(OX)\report$O \
216219
$(OX)\rss$O \
217220
$(OX)\schema$O \
218221
$(OX)\search$O \
219222
$(OX)\setup$O \
@@ -230,10 +233,11 @@
230233
$(OX)\th_main$O \
231234
$(OX)\timeline$O \
232235
$(OX)\tkt$O \
233236
$(OX)\tktsetup$O \
234237
$(OX)\undo$O \
238
+ $(OX)\unicode$O \
235239
$(OX)\update$O \
236240
$(OX)\url$O \
237241
$(OX)\user$O \
238242
$(OX)\utf8$O \
239243
$(OX)\verify$O \
@@ -330,10 +334,11 @@
330334
echo $(OX)\pivot.obj >> $@
331335
echo $(OX)\popen.obj >> $@
332336
echo $(OX)\pqueue.obj >> $@
333337
echo $(OX)\printf.obj >> $@
334338
echo $(OX)\rebuild.obj >> $@
339
+ echo $(OX)\regexp.obj >> $@
335340
echo $(OX)\report.obj >> $@
336341
echo $(OX)\rss.obj >> $@
337342
echo $(OX)\schema.obj >> $@
338343
echo $(OX)\search.obj >> $@
339344
echo $(OX)\setup.obj >> $@
@@ -354,10 +359,11 @@
354359
echo $(OX)\th_main.obj >> $@
355360
echo $(OX)\timeline.obj >> $@
356361
echo $(OX)\tkt.obj >> $@
357362
echo $(OX)\tktsetup.obj >> $@
358363
echo $(OX)\undo.obj >> $@
364
+ echo $(OX)\unicode.obj >> $@
359365
echo $(OX)\update.obj >> $@
360366
echo $(OX)\url.obj >> $@
361367
echo $(OX)\user.obj >> $@
362368
echo $(OX)\utf8.obj >> $@
363369
echo $(OX)\verify.obj >> $@
@@ -853,10 +859,16 @@
853859
$(OX)\rebuild$O : rebuild_.c rebuild.h
854860
$(TCC) /Fo$@ -c rebuild_.c
855861
856862
rebuild_.c : $(SRCDIR)\rebuild.c
857863
translate$E $** > $@
864
+
865
+$(OX)\regexp$O : regexp_.c regexp.h
866
+ $(TCC) /Fo$@ -c regexp_.c
867
+
868
+regexp_.c : $(SRCDIR)\regexp.c
869
+ translate$E $** > $@
858870
859871
$(OX)\report$O : report_.c report.h
860872
$(TCC) /Fo$@ -c report_.c
861873
862874
report_.c : $(SRCDIR)\report.c
@@ -973,10 +985,16 @@
973985
$(OX)\undo$O : undo_.c undo.h
974986
$(TCC) /Fo$@ -c undo_.c
975987
976988
undo_.c : $(SRCDIR)\undo.c
977989
translate$E $** > $@
990
+
991
+$(OX)\unicode$O : unicode_.c unicode.h
992
+ $(TCC) /Fo$@ -c unicode_.c
993
+
994
+unicode_.c : $(SRCDIR)\unicode.c
995
+ translate$E $** > $@
978996
979997
$(OX)\update$O : update_.c update.h
980998
$(TCC) /Fo$@ -c update_.c
981999
9821000
update_.c : $(SRCDIR)\update.c
@@ -1122,10 +1140,11 @@
11221140
pivot_.c:pivot.h \
11231141
popen_.c:popen.h \
11241142
pqueue_.c:pqueue.h \
11251143
printf_.c:printf.h \
11261144
rebuild_.c:rebuild.h \
1145
+ regexp_.c:regexp.h \
11271146
report_.c:report.h \
11281147
rss_.c:rss.h \
11291148
schema_.c:schema.h \
11301149
search_.c:search.h \
11311150
setup_.c:setup.h \
@@ -1142,10 +1161,11 @@
11421161
th_main_.c:th_main.h \
11431162
timeline_.c:timeline.h \
11441163
tkt_.c:tkt.h \
11451164
tktsetup_.c:tktsetup.h \
11461165
undo_.c:undo.h \
1166
+ unicode_.c:unicode.h \
11471167
update_.c:update.h \
11481168
url_.c:url.h \
11491169
user_.c:user.h \
11501170
utf8_.c:utf8.h \
11511171
verify_.c:verify.h \
11521172
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -107,10 +107,11 @@
107 pivot_.c \
108 popen_.c \
109 pqueue_.c \
110 printf_.c \
111 rebuild_.c \
 
112 report_.c \
113 rss_.c \
114 schema_.c \
115 search_.c \
116 setup_.c \
@@ -127,10 +128,11 @@
127 th_main_.c \
128 timeline_.c \
129 tkt_.c \
130 tktsetup_.c \
131 undo_.c \
 
132 update_.c \
133 url_.c \
134 user_.c \
135 utf8_.c \
136 verify_.c \
@@ -210,10 +212,11 @@
210 $(OX)\pivot$O \
211 $(OX)\popen$O \
212 $(OX)\pqueue$O \
213 $(OX)\printf$O \
214 $(OX)\rebuild$O \
 
215 $(OX)\report$O \
216 $(OX)\rss$O \
217 $(OX)\schema$O \
218 $(OX)\search$O \
219 $(OX)\setup$O \
@@ -230,10 +233,11 @@
230 $(OX)\th_main$O \
231 $(OX)\timeline$O \
232 $(OX)\tkt$O \
233 $(OX)\tktsetup$O \
234 $(OX)\undo$O \
 
235 $(OX)\update$O \
236 $(OX)\url$O \
237 $(OX)\user$O \
238 $(OX)\utf8$O \
239 $(OX)\verify$O \
@@ -330,10 +334,11 @@
330 echo $(OX)\pivot.obj >> $@
331 echo $(OX)\popen.obj >> $@
332 echo $(OX)\pqueue.obj >> $@
333 echo $(OX)\printf.obj >> $@
334 echo $(OX)\rebuild.obj >> $@
 
335 echo $(OX)\report.obj >> $@
336 echo $(OX)\rss.obj >> $@
337 echo $(OX)\schema.obj >> $@
338 echo $(OX)\search.obj >> $@
339 echo $(OX)\setup.obj >> $@
@@ -354,10 +359,11 @@
354 echo $(OX)\th_main.obj >> $@
355 echo $(OX)\timeline.obj >> $@
356 echo $(OX)\tkt.obj >> $@
357 echo $(OX)\tktsetup.obj >> $@
358 echo $(OX)\undo.obj >> $@
 
359 echo $(OX)\update.obj >> $@
360 echo $(OX)\url.obj >> $@
361 echo $(OX)\user.obj >> $@
362 echo $(OX)\utf8.obj >> $@
363 echo $(OX)\verify.obj >> $@
@@ -853,10 +859,16 @@
853 $(OX)\rebuild$O : rebuild_.c rebuild.h
854 $(TCC) /Fo$@ -c rebuild_.c
855
856 rebuild_.c : $(SRCDIR)\rebuild.c
857 translate$E $** > $@
 
 
 
 
 
 
858
859 $(OX)\report$O : report_.c report.h
860 $(TCC) /Fo$@ -c report_.c
861
862 report_.c : $(SRCDIR)\report.c
@@ -973,10 +985,16 @@
973 $(OX)\undo$O : undo_.c undo.h
974 $(TCC) /Fo$@ -c undo_.c
975
976 undo_.c : $(SRCDIR)\undo.c
977 translate$E $** > $@
 
 
 
 
 
 
978
979 $(OX)\update$O : update_.c update.h
980 $(TCC) /Fo$@ -c update_.c
981
982 update_.c : $(SRCDIR)\update.c
@@ -1122,10 +1140,11 @@
1122 pivot_.c:pivot.h \
1123 popen_.c:popen.h \
1124 pqueue_.c:pqueue.h \
1125 printf_.c:printf.h \
1126 rebuild_.c:rebuild.h \
 
1127 report_.c:report.h \
1128 rss_.c:rss.h \
1129 schema_.c:schema.h \
1130 search_.c:search.h \
1131 setup_.c:setup.h \
@@ -1142,10 +1161,11 @@
1142 th_main_.c:th_main.h \
1143 timeline_.c:timeline.h \
1144 tkt_.c:tkt.h \
1145 tktsetup_.c:tktsetup.h \
1146 undo_.c:undo.h \
 
1147 update_.c:update.h \
1148 url_.c:url.h \
1149 user_.c:user.h \
1150 utf8_.c:utf8.h \
1151 verify_.c:verify.h \
1152
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -107,10 +107,11 @@
107 pivot_.c \
108 popen_.c \
109 pqueue_.c \
110 printf_.c \
111 rebuild_.c \
112 regexp_.c \
113 report_.c \
114 rss_.c \
115 schema_.c \
116 search_.c \
117 setup_.c \
@@ -127,10 +128,11 @@
128 th_main_.c \
129 timeline_.c \
130 tkt_.c \
131 tktsetup_.c \
132 undo_.c \
133 unicode_.c \
134 update_.c \
135 url_.c \
136 user_.c \
137 utf8_.c \
138 verify_.c \
@@ -210,10 +212,11 @@
212 $(OX)\pivot$O \
213 $(OX)\popen$O \
214 $(OX)\pqueue$O \
215 $(OX)\printf$O \
216 $(OX)\rebuild$O \
217 $(OX)\regexp$O \
218 $(OX)\report$O \
219 $(OX)\rss$O \
220 $(OX)\schema$O \
221 $(OX)\search$O \
222 $(OX)\setup$O \
@@ -230,10 +233,11 @@
233 $(OX)\th_main$O \
234 $(OX)\timeline$O \
235 $(OX)\tkt$O \
236 $(OX)\tktsetup$O \
237 $(OX)\undo$O \
238 $(OX)\unicode$O \
239 $(OX)\update$O \
240 $(OX)\url$O \
241 $(OX)\user$O \
242 $(OX)\utf8$O \
243 $(OX)\verify$O \
@@ -330,10 +334,11 @@
334 echo $(OX)\pivot.obj >> $@
335 echo $(OX)\popen.obj >> $@
336 echo $(OX)\pqueue.obj >> $@
337 echo $(OX)\printf.obj >> $@
338 echo $(OX)\rebuild.obj >> $@
339 echo $(OX)\regexp.obj >> $@
340 echo $(OX)\report.obj >> $@
341 echo $(OX)\rss.obj >> $@
342 echo $(OX)\schema.obj >> $@
343 echo $(OX)\search.obj >> $@
344 echo $(OX)\setup.obj >> $@
@@ -354,10 +359,11 @@
359 echo $(OX)\th_main.obj >> $@
360 echo $(OX)\timeline.obj >> $@
361 echo $(OX)\tkt.obj >> $@
362 echo $(OX)\tktsetup.obj >> $@
363 echo $(OX)\undo.obj >> $@
364 echo $(OX)\unicode.obj >> $@
365 echo $(OX)\update.obj >> $@
366 echo $(OX)\url.obj >> $@
367 echo $(OX)\user.obj >> $@
368 echo $(OX)\utf8.obj >> $@
369 echo $(OX)\verify.obj >> $@
@@ -853,10 +859,16 @@
859 $(OX)\rebuild$O : rebuild_.c rebuild.h
860 $(TCC) /Fo$@ -c rebuild_.c
861
862 rebuild_.c : $(SRCDIR)\rebuild.c
863 translate$E $** > $@
864
865 $(OX)\regexp$O : regexp_.c regexp.h
866 $(TCC) /Fo$@ -c regexp_.c
867
868 regexp_.c : $(SRCDIR)\regexp.c
869 translate$E $** > $@
870
871 $(OX)\report$O : report_.c report.h
872 $(TCC) /Fo$@ -c report_.c
873
874 report_.c : $(SRCDIR)\report.c
@@ -973,10 +985,16 @@
985 $(OX)\undo$O : undo_.c undo.h
986 $(TCC) /Fo$@ -c undo_.c
987
988 undo_.c : $(SRCDIR)\undo.c
989 translate$E $** > $@
990
991 $(OX)\unicode$O : unicode_.c unicode.h
992 $(TCC) /Fo$@ -c unicode_.c
993
994 unicode_.c : $(SRCDIR)\unicode.c
995 translate$E $** > $@
996
997 $(OX)\update$O : update_.c update.h
998 $(TCC) /Fo$@ -c update_.c
999
1000 update_.c : $(SRCDIR)\update.c
@@ -1122,10 +1140,11 @@
1140 pivot_.c:pivot.h \
1141 popen_.c:popen.h \
1142 pqueue_.c:pqueue.h \
1143 printf_.c:printf.h \
1144 rebuild_.c:rebuild.h \
1145 regexp_.c:regexp.h \
1146 report_.c:report.h \
1147 rss_.c:rss.h \
1148 schema_.c:schema.h \
1149 search_.c:search.h \
1150 setup_.c:setup.h \
@@ -1142,10 +1161,11 @@
1161 th_main_.c:th_main.h \
1162 timeline_.c:timeline.h \
1163 tkt_.c:tkt.h \
1164 tktsetup_.c:tktsetup.h \
1165 undo_.c:undo.h \
1166 unicode_.c:unicode.h \
1167 update_.c:update.h \
1168 url_.c:url.h \
1169 user_.c:user.h \
1170 utf8_.c:utf8.h \
1171 verify_.c:verify.h \
1172
--- win/fossil.rc
+++ win/fossil.rc
@@ -104,10 +104,13 @@
104104
#endif
105105
#endif
106106
#ifdef FOSSIL_ENABLE_JSON
107107
VALUE "JsonEnabled", "Yes, cson\0"
108108
#endif
109
+#ifdef FOSSIL_ENABLE_MARKDOWN
110
+ VALUE "MarkdownEnabled", "Yes\0"
111
+#endif
109112
END
110113
END
111114
BLOCK "VarFileInfo"
112115
BEGIN
113116
VALUE "Translation", 0x409, 0x4B0
114117
--- win/fossil.rc
+++ win/fossil.rc
@@ -104,10 +104,13 @@
104 #endif
105 #endif
106 #ifdef FOSSIL_ENABLE_JSON
107 VALUE "JsonEnabled", "Yes, cson\0"
108 #endif
 
 
 
109 END
110 END
111 BLOCK "VarFileInfo"
112 BEGIN
113 VALUE "Translation", 0x409, 0x4B0
114
--- win/fossil.rc
+++ win/fossil.rc
@@ -104,10 +104,13 @@
104 #endif
105 #endif
106 #ifdef FOSSIL_ENABLE_JSON
107 VALUE "JsonEnabled", "Yes, cson\0"
108 #endif
109 #ifdef FOSSIL_ENABLE_MARKDOWN
110 VALUE "MarkdownEnabled", "Yes\0"
111 #endif
112 END
113 END
114 BLOCK "VarFileInfo"
115 BEGIN
116 VALUE "Translation", 0x409, 0x4B0
117
+398 -204
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
2020
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
2121
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2222
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2323
* OTHER DEALINGS IN THE SOFTWARE.
2424
*
25
+ *
26
+ * Version 1.13, Dec 12 2012, Toni Ronkko
27
+ * Use traditional 8+3 file name if the name cannot be represented in the
28
+ * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to
29
+ * Konstantin Khomoutov for testing.
2530
*
2631
* Version 1.12.1, Oct 1 2012, Toni Ronkko
2732
* Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
2833
* capital W) in order to maintain compatibility with MingW.
2934
*
3035
* Version 1.12, Sep 30 2012, Toni Ronkko
31
- * Define PATH_MAX and NAME_MAX.
32
- *
33
- * Added wide-character variants _wDIR, _wdirent, _wopendir(),
34
- * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle
35
- * and Jan Nijtmans for ideas and code.
36
+ * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
37
+ * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
38
+ * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
3639
*
3740
* Do not include windows.h. This allows dirent.h to be integrated more
3841
* easily into programs using winsock. Thanks to Fernando Azaldegui.
3942
*
4043
* Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
8891
*****************************************************************************/
8992
#ifndef DIRENT_H
9093
#define DIRENT_H
9194
9295
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
93
-#define _X86_
96
+# define _X86_
9497
#endif
9598
#include <stdio.h>
9699
#include <stdarg.h>
97100
#include <windef.h>
98101
#include <winbase.h>
99102
#include <wchar.h>
100
-#include <winnls.h>
101103
#include <string.h>
102104
#include <stdlib.h>
105
+#include <malloc.h>
103106
#include <sys/types.h>
104107
#include <sys/stat.h>
105108
#include <errno.h>
106109
107
-/* Windows 8 wide-character string functions */
108
-#if (_WIN32_WINNT >= 0x0602)
109
-# include <stringapiset.h>
110
-#endif
110
+/* Indicates that d_type field is available in dirent structure */
111
+#define _DIRENT_HAVE_D_TYPE
112
+
113
+/* Indicates that d_namlen field is available in dirent structure */
114
+#define _DIRENT_HAVE_D_NAMLEN
111115
112116
/* Entries missing from MSVC 6.0 */
113117
#if !defined(FILE_ATTRIBUTE_DEVICE)
114
-# define FILE_ATTRIBUTE_DEVICE 0x40
118
+# define FILE_ATTRIBUTE_DEVICE 0x40
115119
#endif
116120
117121
/* File type and permission flags for stat() */
118
-#if defined(_MSC_VER) && !defined(S_IREAD)
122
+#if !defined(S_IFMT)
119123
# define S_IFMT _S_IFMT /* File type mask */
124
+#endif
125
+#if !defined(S_IFDIR)
120126
# define S_IFDIR _S_IFDIR /* Directory */
127
+#endif
128
+#if !defined(S_IFCHR)
121129
# define S_IFCHR _S_IFCHR /* Character device */
130
+#endif
131
+#if !defined(S_IFFIFO)
122132
# define S_IFFIFO _S_IFFIFO /* Pipe */
133
+#endif
134
+#if !defined(S_IFREG)
123135
# define S_IFREG _S_IFREG /* Regular file */
136
+#endif
137
+#if !defined(S_IREAD)
124138
# define S_IREAD _S_IREAD /* Read permission */
139
+#endif
140
+#if !defined(S_IWRITE)
125141
# define S_IWRITE _S_IWRITE /* Write permission */
142
+#endif
143
+#if !defined(S_IEXEC)
126144
# define S_IEXEC _S_IEXEC /* Execute permission */
127145
#endif
128
-#define S_IFBLK 0 /* Block device */
129
-#define S_IFLNK 0 /* Link */
130
-#define S_IFSOCK 0 /* Socket */
146
+#if !defined(S_IFIFO)
147
+# define S_IFIFO _S_IFIFO /* Pipe */
148
+#endif
149
+#if !defined(S_IFBLK)
150
+# define S_IFBLK 0 /* Block device */
151
+#endif
152
+#if !defined(S_IFLNK)
153
+# define S_IFLNK 0 /* Link */
154
+#endif
155
+#if !defined(S_IFSOCK)
156
+# define S_IFSOCK 0 /* Socket */
157
+#endif
131158
132159
#if defined(_MSC_VER)
133160
# define S_IRUSR S_IREAD /* Read user */
134161
# define S_IWUSR S_IWRITE /* Write user */
135162
# define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
139166
# define S_IROTH 0 /* Read others */
140167
# define S_IWOTH 0 /* Write others */
141168
# define S_IXOTH 0 /* Execute others */
142169
#endif
143170
144
-/* Indicates that d_type field is available in dirent structure */
145
-#define _DIRENT_HAVE_D_TYPE
171
+/* Maximum length of file name */
172
+#if !defined(PATH_MAX)
173
+# define PATH_MAX MAX_PATH
174
+#endif
175
+#if !defined(FILENAME_MAX)
176
+# define FILENAME_MAX MAX_PATH
177
+#endif
178
+#if !defined(NAME_MAX)
179
+# define NAME_MAX FILENAME_MAX
180
+#endif
146181
147182
/* File type flags for d_type */
148183
#define DT_UNKNOWN 0
149184
#define DT_REG S_IFREG
150185
#define DT_DIR S_IFDIR
151
-#define DT_FIFO S_IFFIFO
186
+#define DT_FIFO S_IFIFO
152187
#define DT_SOCK S_IFSOCK
153188
#define DT_CHR S_IFCHR
154189
#define DT_BLK S_IFBLK
155190
156191
/* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
161196
* File type macros. Note that block devices, sockets and links cannot be
162197
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
163198
* only defined for compatibility. These macros should always return false
164199
* on Windows.
165200
*/
166
-#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
201
+#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
167202
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
168203
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
169204
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
170205
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
171206
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
172207
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
173208
174
-/* For compatiblity with Unix */
175
-#if !defined(PATH_MAX)
176
-# define PATH_MAX MAX_PATH
177
-#endif
178
-#if !defined(FILENAME_MAX)
179
-# define FILENAME_MAX MAX_PATH
180
-#endif
181
-#if !defined(NAME_MAX)
182
-# define NAME_MAX FILENAME_MAX
183
-#endif
184
-
185
-/* Set errno variable */
186
-#if defined(_MSC_VER)
187
-#define DIRENT_SET_ERRNO(x) _set_errno (x)
188
-#else
189
-#define DIRENT_SET_ERRNO(x) (errno = (x))
190
-#endif
209
+/* Return the exact length of d_namlen without zero terminator */
210
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
211
+
212
+/* Return number of bytes needed to store d_namlen */
213
+#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
214
+
191215
192216
#ifdef __cplusplus
193217
extern "C" {
194218
#endif
195219
196
-/* Wide-character versions */
220
+
221
+/* Wide-character version */
197222
struct _wdirent {
198223
long d_ino; /* Always zero */
199224
unsigned short d_reclen; /* Structure size */
200225
size_t d_namlen; /* Length of name without \0 */
201226
int d_type; /* File type */
@@ -203,11 +228,11 @@
203228
};
204229
typedef struct _wdirent _wdirent;
205230
206231
struct _WDIR {
207232
struct _wdirent ent; /* Current directory entry */
208
- WIN32_FIND_DATAW find_data; /* Private file data */
233
+ WIN32_FIND_DATAW data; /* Private file data */
209234
int cached; /* True if data is valid */
210235
HANDLE handle; /* Win32 search handle */
211236
wchar_t *patt; /* Initial directory name */
212237
};
213238
typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
214239
215240
static _WDIR *_wopendir (const wchar_t *dirname);
216241
static struct _wdirent *_wreaddir (_WDIR *dirp);
217242
static int _wclosedir (_WDIR *dirp);
218243
static void _wrewinddir (_WDIR* dirp);
244
+
219245
220246
/* For compatibility with Symbian */
221247
#define wdirent _wdirent
222248
#define WDIR _WDIR
223249
#define wopendir _wopendir
@@ -246,10 +272,30 @@
246272
static struct dirent *readdir (DIR *dirp);
247273
static int closedir (DIR *dirp);
248274
static void rewinddir (DIR* dirp);
249275
250276
277
+/* Internal utility functions */
278
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
279
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
280
+
281
+static int dirent_mbstowcs_s(
282
+ size_t *pReturnValue,
283
+ wchar_t *wcstr,
284
+ size_t sizeInWords,
285
+ const char *mbstr,
286
+ size_t count);
287
+
288
+static int dirent_wcstombs_s(
289
+ size_t *pReturnValue,
290
+ char *mbstr,
291
+ size_t sizeInBytes,
292
+ const wchar_t *wcstr,
293
+ size_t count);
294
+
295
+static void dirent_set_errno (int error);
296
+
251297
/*
252298
* Open directory stream DIRNAME for read and return a pointer to the
253299
* internal working area that is used to retrieve individual directory
254300
* entries.
255301
*/
@@ -256,31 +302,38 @@
256302
static _WDIR*
257303
_wopendir(
258304
const wchar_t *dirname)
259305
{
260306
_WDIR *dirp = NULL;
261
- int error = 0;
307
+ int error;
308
+
309
+ /* Must have directory name */
310
+ if (dirname == NULL || dirname[0] == '\0') {
311
+ dirent_set_errno (ENOENT);
312
+ return NULL;
313
+ }
262314
263315
/* Allocate new _WDIR structure */
264316
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
265317
if (dirp != NULL) {
266318
DWORD n;
267319
268320
/* Reset _WDIR structure */
269321
dirp->handle = INVALID_HANDLE_VALUE;
270322
dirp->patt = NULL;
323
+ dirp->cached = 0;
271324
272325
/* Compute the length of full path plus zero terminator */
273326
n = GetFullPathNameW (dirname, 0, NULL, NULL);
274327
275
- /* Allocate room for full path and search patterns */
328
+ /* Allocate room for absolute directory name and search pattern */
276329
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
277330
if (dirp->patt) {
278331
279332
/*
280333
* Convert relative directory name to an absolute one. This
281
- * allows rewinddir() to function correctly when the current
334
+ * allows rewinddir() to function correctly even when current
282335
* working directory is changed between opendir() and rewinddir().
283336
*/
284337
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
285338
if (n > 0) {
286339
wchar_t *p;
@@ -303,25 +356,22 @@
303356
}
304357
*p++ = '*';
305358
*p = '\0';
306359
307360
/* Open directory stream and retrieve the first entry */
308
- dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
309
- if (dirp->handle != INVALID_HANDLE_VALUE) {
310
-
311
- /* Directory entry is now waiting in memory */
312
- dirp->cached = 1;
313
-
361
+ if (dirent_first (dirp)) {
362
+ /* Directory stream opened successfully */
363
+ error = 0;
314364
} else {
315
- /* Search pattern is not a directory name? */
316
- DIRENT_SET_ERRNO (ENOENT);
365
+ /* Cannot retrieve first entry */
317366
error = 1;
367
+ dirent_set_errno (ENOENT);
318368
}
319369
320370
} else {
321
- /* Cannot convert directory name to wide character string */
322
- DIRENT_SET_ERRNO (ENOENT);
371
+ /* Cannot retrieve full path name */
372
+ dirent_set_errno (ENOENT);
323373
error = 1;
324374
}
325375
326376
} else {
327377
/* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
350400
*/
351401
static struct _wdirent*
352402
_wreaddir(
353403
_WDIR *dirp)
354404
{
355
- DWORD attr;
356
- errno_t error;
357
-
358
- /* Get next directory entry */
359
- if (dirp->cached != 0) {
360
- /* A valid directory entry already in memory */
361
- dirp->cached = 0;
362
- } else {
363
- /* Get the next directory entry from stream */
364
- if (dirp->handle == INVALID_HANDLE_VALUE) {
365
- return NULL;
366
- }
367
- if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) {
368
- /* The very last entry has been processed or an error occured */
369
- FindClose (dirp->handle);
370
- dirp->handle = INVALID_HANDLE_VALUE;
371
- return NULL;
372
- }
373
- }
374
-
375
- /* Copy file name as a wide-character string */
376
- error = wcsncpy_s(
377
- dirp->ent.d_name, /* Destination string */
378
- PATH_MAX, /* Size of dest in words */
379
- dirp->find_data.cFileName, /* Source string */
380
- PATH_MAX + 1); /* Max # of chars to copy */
381
- if (!error) {
382
-
383
- /* Compute the length of name */
384
- dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX);
385
-
386
- /* Determine file type */
387
- attr = dirp->find_data.dwFileAttributes;
405
+ WIN32_FIND_DATAW *datap;
406
+ struct _wdirent *entp;
407
+
408
+ /* Read next directory entry */
409
+ datap = dirent_next (dirp);
410
+ if (datap) {
411
+ size_t n;
412
+ DWORD attr;
413
+
414
+ /* Pointer to directory entry to return */
415
+ entp = &dirp->ent;
416
+
417
+ /*
418
+ * Copy file name as wide-character string. If the file name is too
419
+ * long to fit in to the destination buffer, then truncate file name
420
+ * to PATH_MAX characters and zero-terminate the buffer.
421
+ */
422
+ n = 0;
423
+ while (n < PATH_MAX && datap->cFileName[n] != 0) {
424
+ entp->d_name[n] = datap->cFileName[n];
425
+ n++;
426
+ }
427
+ dirp->ent.d_name[n] = 0;
428
+
429
+ /* Length of file name excluding zero terminator */
430
+ entp->d_namlen = n;
431
+
432
+ /* File type */
433
+ attr = datap->dwFileAttributes;
388434
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
389
- dirp->ent.d_type = DT_CHR;
435
+ entp->d_type = DT_CHR;
390436
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
391
- dirp->ent.d_type = DT_DIR;
437
+ entp->d_type = DT_DIR;
392438
} else {
393
- dirp->ent.d_type = DT_REG;
439
+ entp->d_type = DT_REG;
394440
}
395441
396442
/* Reset dummy fields */
397
- dirp->ent.d_ino = 0;
398
- dirp->ent.d_reclen = sizeof (dirp->ent);
443
+ entp->d_ino = 0;
444
+ entp->d_reclen = sizeof (struct _wdirent);
399445
400446
} else {
401447
402
- /*
403
- * Cannot copy file name from find_data to ent. Construct a
404
- * dummy _wdirent structure to pass error to caller.
405
- */
406
- dirp->ent.d_name[0] = '?';
407
- dirp->ent.d_name[1] = '\0';
408
- dirp->ent.d_namlen = 1;
409
- dirp->ent.d_type = DT_UNKNOWN;
410
- dirp->ent.d_ino = 0;
411
- dirp->ent.d_reclen = 0;
448
+ /* Last directory entry read */
449
+ entp = NULL;
450
+
412451
}
413452
414
- return &dirp->ent;
453
+ return entp;
415454
}
416455
417456
/*
418457
* Close directory stream opened by opendir() function. This invalidates the
419458
* DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
442481
free (dirp);
443482
ok = /*success*/0;
444483
445484
} else {
446485
/* Invalid directory stream */
447
- DIRENT_SET_ERRNO (EBADF);
486
+ dirent_set_errno (EBADF);
448487
ok = /*failure*/-1;
449488
}
450489
return ok;
451490
}
452491
@@ -456,26 +495,81 @@
456495
*/
457496
static void
458497
_wrewinddir(
459498
_WDIR* dirp)
460499
{
461
- if (dirp != NULL) {
462
- /* release search handle */
500
+ if (dirp) {
501
+ /* Release existing search handle */
463502
if (dirp->handle != INVALID_HANDLE_VALUE) {
464503
FindClose (dirp->handle);
465504
}
466505
467
- /* Open new search handle and retrieve the first directory entry */
468
- dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
469
- if (dirp->handle != INVALID_HANDLE_VALUE) {
470
- /* a directory entry is now waiting in memory */
471
- dirp->cached = 1;
506
+ /* Open new search handle */
507
+ dirent_first (dirp);
508
+ }
509
+}
510
+
511
+/* Get first directory entry (internal) */
512
+static WIN32_FIND_DATAW*
513
+dirent_first(
514
+ _WDIR *dirp)
515
+{
516
+ WIN32_FIND_DATAW *datap;
517
+
518
+ /* Open directory and retrieve the first entry */
519
+ dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
520
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
521
+
522
+ /* a directory entry is now waiting in memory */
523
+ datap = &dirp->data;
524
+ dirp->cached = 1;
525
+
526
+ } else {
527
+
528
+ /* Failed to re-open directory: no directory entry in memory */
529
+ dirp->cached = 0;
530
+ datap = NULL;
531
+
532
+ }
533
+ return datap;
534
+}
535
+
536
+/* Get next directory entry (internal) */
537
+static WIN32_FIND_DATAW*
538
+dirent_next(
539
+ _WDIR *dirp)
540
+{
541
+ WIN32_FIND_DATAW *p;
542
+
543
+ /* Get next directory entry */
544
+ if (dirp->cached != 0) {
545
+
546
+ /* A valid directory entry already in memory */
547
+ p = &dirp->data;
548
+ dirp->cached = 0;
549
+
550
+ } else if (dirp->handle != INVALID_HANDLE_VALUE) {
551
+
552
+ /* Get the next directory entry from stream */
553
+ if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
554
+ /* Got a file */
555
+ p = &dirp->data;
472556
} else {
473
- /* Failed to re-open directory: no directory entry in memory */
474
- dirp->cached = 0;
557
+ /* The very last entry has been processed or an error occured */
558
+ FindClose (dirp->handle);
559
+ dirp->handle = INVALID_HANDLE_VALUE;
560
+ p = NULL;
475561
}
562
+
563
+ } else {
564
+
565
+ /* End of directory stream reached */
566
+ p = NULL;
567
+
476568
}
569
+
570
+ return p;
477571
}
478572
479573
/*
480574
* Open directory stream using plain old C-string.
481575
*/
@@ -482,58 +576,34 @@
482576
static DIR*
483577
opendir(
484578
const char *dirname)
485579
{
486580
struct DIR *dirp;
487
- errno_t error = 0;
581
+ int error;
488582
489583
/* Must have directory name */
490
- if (dirname == NULL) {
491
- DIRENT_SET_ERRNO (ENOENT);
584
+ if (dirname == NULL || dirname[0] == '\0') {
585
+ dirent_set_errno (ENOENT);
492586
return NULL;
493587
}
494588
495
- /* Allocate memory for multi-byte string directory structures */
589
+ /* Allocate memory for DIR structure */
496590
dirp = (DIR*) malloc (sizeof (struct DIR));
497591
if (dirp) {
498592
wchar_t wname[PATH_MAX + 1];
499593
size_t n;
500594
501
- /*
502
- * Convert directory name to wide-character string.
503
- *
504
- * Be ware of the return schemantics of MultiByteToWideChar() --
505
- * the function basically returns the number of characters written to
506
- * output buffer or zero if the conversion fails. However, the
507
- * function does not necessarily zero-terminate the output
508
- * buffer and may return 0xFFFD if the string contains invalid
509
- * characters!
510
- */
511
- n = MultiByteToWideChar(
512
- CP_ACP, /* Input code page */
513
- MB_PRECOMPOSED, /* Conversion flags */
514
- dirname, /* Input string */
515
- -1, /* Length of input string */
516
- wname, /* Output buffer */
517
- PATH_MAX); /* Size of output buffer */
518
- if (n > 0 && n < PATH_MAX) {
519
-
520
- /* Zero-terminate output buffer */
521
- wname[n] = '\0';
522
-
523
- /* Open directory stream with wide-character string file name */
595
+ /* Convert directory name to wide-character string */
596
+ error = dirent_mbstowcs_s(
597
+ &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
598
+ if (!error) {
599
+
600
+ /* Open directory stream using wide-character name */
524601
dirp->wdirp = _wopendir (wname);
525602
if (dirp->wdirp) {
526
-
527
- /* Initialize directory structure */
528
- dirp->ent.d_name[0] = '\0';
529
- dirp->ent.d_namlen = 0;
530
- dirp->ent.d_type = 0;
531
- dirp->ent.d_ino = 0;
532
- dirp->ent.d_reclen = 0;
533
-
534
-
603
+ /* Directory stream opened */
604
+ error = 0;
535605
} else {
536606
/* Failed to open directory stream */
537607
error = 1;
538608
}
539609
@@ -562,95 +632,99 @@
562632
}
563633
564634
/*
565635
* Read next directory entry.
566636
*
567
- * When working with console, please note that file names returned by
568
- * readdir() are represented in the default ANSI code page while the
569
- * console typically runs on another code page. Thus, non-ASCII characters
570
- * will not usually display correctly. The problem can be fixed in two ways:
571
- * (1) change the character set of console to 1252 using chcp utility and use
572
- * Lucida Console font, or (2) always use _cprintf function when writing to
573
- * console. The _cprinf() will re-encode ANSI strings to the console code
574
- * page so non-ASCII characters will display correcly.
637
+ * When working with text consoles, please note that file names returned by
638
+ * readdir() are represented in the default ANSI code page while any output to
639
+ * console is typically formatted on another code page. Thus, non-ASCII
640
+ * characters in file names will not usually display correctly on console. The
641
+ * problem can be fixed in two ways: (1) change the character set of console
642
+ * to 1252 using chcp utility and use Lucida Console font, or (2) use
643
+ * _cprintf function when writing to console. The _cprinf() will re-encode
644
+ * ANSI strings to the console code page so many non-ASCII characters will
645
+ * display correcly.
575646
*/
576647
static struct dirent*
577648
readdir(
578649
DIR *dirp)
579650
{
580
- struct dirent *p;
581
- struct _wdirent *wp;
651
+ WIN32_FIND_DATAW *datap;
652
+ struct dirent *entp;
582653
583
- /* Read next directory entry using wide-character string functions */
584
- wp = _wreaddir (dirp->wdirp);
585
- if (wp) {
654
+ /* Read next directory entry */
655
+ datap = dirent_next (dirp->wdirp);
656
+ if (datap) {
586657
size_t n;
658
+ int error;
659
+
660
+ /* Attempt to convert file name to multi-byte string */
661
+ error = dirent_wcstombs_s(
662
+ &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
587663
588664
/*
589
- * Convert file name to multi-byte string.
590
- *
591
- * Be ware of the return schemantics of WideCharToMultiByte() --
592
- * the function basically returns the number of bytes
593
- * written to output buffer or zero if the conversion fails.
594
- * However, the function does not necessarily zero-terminate the
595
- * buffer and it may even return 0xFFFD the string contains
596
- * invalid characters!
665
+ * If the file name cannot be represented by a multi-byte string,
666
+ * then attempt to use old 8+3 file name. This allows traditional
667
+ * Unix-code to access some file names despite of unicode
668
+ * characters, although file names may seem unfamiliar to the user.
669
+ *
670
+ * Be ware that the code below cannot come up with a short file
671
+ * name unless the file system provides one. At least
672
+ * VirtualBox shared folders fail to do this.
597673
*/
598
- n = WideCharToMultiByte(
599
- CP_ACP, /* Output code page */
600
- 0, /* Conversion flags */
601
- wp->d_name, /* Input string */
602
- wp->d_namlen, /* Length of input string */
603
- dirp->ent.d_name, /* Output buffer */
604
- PATH_MAX, /* Size of output buffer */
605
- NULL, /* Replacement character */
606
- NULL); /* If chars were replaced */
607
- if (n > 0 && n < PATH_MAX) {
608
-
609
- /* Zero-terminate buffer */
610
- dirp->ent.d_name[n] = '\0';
674
+ if (error && datap->cAlternateFileName[0] != '\0') {
675
+ error = dirent_wcstombs_s(
676
+ &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
677
+ sizeof (datap->cAlternateFileName) /
678
+ sizeof (datap->cAlternateFileName[0]));
679
+ }
680
+
681
+ if (!error) {
682
+ DWORD attr;
611683
612684
/* Initialize directory entry for return */
613
- p = &dirp->ent;
685
+ entp = &dirp->ent;
614686
615
- /* Compute length */
616
- p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX);
687
+ /* Length of file name excluding zero terminator */
688
+ entp->d_namlen = n - 1;
617689
618
- /* Copy file attributes */
619
- p->d_type = wp->d_type;
690
+ /* File attributes */
691
+ attr = datap->dwFileAttributes;
692
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
693
+ entp->d_type = DT_CHR;
694
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
695
+ entp->d_type = DT_DIR;
696
+ } else {
697
+ entp->d_type = DT_REG;
698
+ }
620699
621700
/* Reset dummy fields */
622
- p->d_ino = 0;
623
- p->d_reclen = sizeof (dirp->ent);
624
-
701
+ entp->d_ino = 0;
702
+ entp->d_reclen = sizeof (struct dirent);
625703
626704
} else {
627
-
628705
/*
629706
* Cannot convert file name to multi-byte string so construct
630707
* an errornous directory entry and return that. Note that
631708
* we cannot return NULL as that would stop the processing
632709
* of directory entries completely.
633710
*/
634
- p = &dirp->ent;
635
- p->d_name[0] = '?';
636
- p->d_name[1] = '\0';
637
- p->d_namlen = 1;
638
- p->d_type = DT_UNKNOWN;
639
- p->d_ino = 0;
640
- p->d_reclen = 0;
641
-
711
+ entp = &dirp->ent;
712
+ entp->d_name[0] = '?';
713
+ entp->d_name[1] = '\0';
714
+ entp->d_namlen = 1;
715
+ entp->d_type = DT_UNKNOWN;
716
+ entp->d_ino = 0;
717
+ entp->d_reclen = 0;
642718
}
643719
644720
} else {
645
-
646
- /* End of directory stream */
647
- p = NULL;
648
-
721
+ /* No more directory entries */
722
+ entp = NULL;
649723
}
650724
651
- return p;
725
+ return entp;
652726
}
653727
654728
/*
655729
* Close directory stream.
656730
*/
@@ -667,13 +741,15 @@
667741
668742
/* Release multi-byte character version */
669743
free (dirp);
670744
671745
} else {
746
+
672747
/* Invalid directory stream */
673
- DIRENT_SET_ERRNO (EBADF);
748
+ dirent_set_errno (EBADF);
674749
ok = /*failure*/-1;
750
+
675751
}
676752
return ok;
677753
}
678754
679755
/*
@@ -684,12 +760,130 @@
684760
DIR* dirp)
685761
{
686762
/* Rewind wide-character string directory stream */
687763
_wrewinddir (dirp->wdirp);
688764
}
765
+
766
+/* Convert multi-byte string to wide character string */
767
+static int
768
+dirent_mbstowcs_s(
769
+ size_t *pReturnValue,
770
+ wchar_t *wcstr,
771
+ size_t sizeInWords,
772
+ const char *mbstr,
773
+ size_t count)
774
+{
775
+ int error;
776
+
777
+#if defined(_MSC_VER) && _MSC_VER >= 1400
778
+
779
+ /* Microsoft Visual Studio 2005 or later */
780
+ error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
781
+
782
+#else
783
+
784
+ /* Older Visual Studio or non-Microsoft compiler */
785
+ size_t n;
786
+
787
+ /* Convert to wide-character string */
788
+ n = mbstowcs (wcstr, mbstr, count);
789
+ if (n < sizeInWords) {
790
+
791
+ /* Zero-terminate output buffer */
792
+ if (wcstr) {
793
+ wcstr[n] = 0;
794
+ }
795
+
796
+ /* Length of resuting multi-byte string WITH zero terminator */
797
+ if (pReturnValue) {
798
+ *pReturnValue = n + 1;
799
+ }
800
+
801
+ /* Success */
802
+ error = 0;
803
+
804
+ } else {
805
+
806
+ /* Could not convert string */
807
+ error = 1;
808
+
809
+ }
810
+
811
+#endif
812
+
813
+ return error;
814
+}
815
+
816
+/* Convert wide-character string to multi-byte string */
817
+static int
818
+dirent_wcstombs_s(
819
+ size_t *pReturnValue,
820
+ char *mbstr,
821
+ size_t sizeInBytes,
822
+ const wchar_t *wcstr,
823
+ size_t count)
824
+{
825
+ int error;
826
+
827
+#if defined(_MSC_VER) && _MSC_VER >= 1400
828
+
829
+ /* Microsoft Visual Studio 2005 or later */
830
+ error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
831
+
832
+#else
833
+
834
+ /* Older Visual Studio or non-Microsoft compiler */
835
+ size_t n;
836
+
837
+ /* Convert to multi-byte string */
838
+ n = wcstombs (mbstr, wcstr, count);
839
+ if (n < sizeInBytes) {
840
+
841
+ /* Zero-terminate output buffer */
842
+ if (mbstr) {
843
+ mbstr[n] = '\0';
844
+ }
845
+
846
+ /* Lenght of resulting multi-bytes string WITH zero-terminator */
847
+ if (pReturnValue) {
848
+ *pReturnValue = n + 1;
849
+ }
850
+
851
+ /* Success */
852
+ error = 0;
853
+
854
+ } else {
855
+
856
+ /* Cannot convert string */
857
+ error = 1;
858
+
859
+ }
860
+
861
+#endif
862
+
863
+ return error;
864
+}
865
+
866
+/* Set errno variable */
867
+static void
868
+dirent_set_errno(
869
+ int error)
870
+{
871
+#if defined(_MSC_VER)
872
+
873
+ /* Microsoft Visual Studio */
874
+ _set_errno (error);
875
+
876
+#else
877
+
878
+ /* Non-Microsoft compiler */
879
+ errno = error;
880
+
881
+#endif
882
+}
689883
690884
691885
#ifdef __cplusplus
692886
}
693887
#endif
694888
#endif /*DIRENT_H*/
695889
696890
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
20 * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 *
 
 
 
 
 
25 *
26 * Version 1.12.1, Oct 1 2012, Toni Ronkko
27 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
28 * capital W) in order to maintain compatibility with MingW.
29 *
30 * Version 1.12, Sep 30 2012, Toni Ronkko
31 * Define PATH_MAX and NAME_MAX.
32 *
33 * Added wide-character variants _wDIR, _wdirent, _wopendir(),
34 * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle
35 * and Jan Nijtmans for ideas and code.
36 *
37 * Do not include windows.h. This allows dirent.h to be integrated more
38 * easily into programs using winsock. Thanks to Fernando Azaldegui.
39 *
40 * Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
88 *****************************************************************************/
89 #ifndef DIRENT_H
90 #define DIRENT_H
91
92 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
93 #define _X86_
94 #endif
95 #include <stdio.h>
96 #include <stdarg.h>
97 #include <windef.h>
98 #include <winbase.h>
99 #include <wchar.h>
100 #include <winnls.h>
101 #include <string.h>
102 #include <stdlib.h>
 
103 #include <sys/types.h>
104 #include <sys/stat.h>
105 #include <errno.h>
106
107 /* Windows 8 wide-character string functions */
108 #if (_WIN32_WINNT >= 0x0602)
109 # include <stringapiset.h>
110 #endif
 
111
112 /* Entries missing from MSVC 6.0 */
113 #if !defined(FILE_ATTRIBUTE_DEVICE)
114 # define FILE_ATTRIBUTE_DEVICE 0x40
115 #endif
116
117 /* File type and permission flags for stat() */
118 #if defined(_MSC_VER) && !defined(S_IREAD)
119 # define S_IFMT _S_IFMT /* File type mask */
 
 
120 # define S_IFDIR _S_IFDIR /* Directory */
 
 
121 # define S_IFCHR _S_IFCHR /* Character device */
 
 
122 # define S_IFFIFO _S_IFFIFO /* Pipe */
 
 
123 # define S_IFREG _S_IFREG /* Regular file */
 
 
124 # define S_IREAD _S_IREAD /* Read permission */
 
 
125 # define S_IWRITE _S_IWRITE /* Write permission */
 
 
126 # define S_IEXEC _S_IEXEC /* Execute permission */
127 #endif
128 #define S_IFBLK 0 /* Block device */
129 #define S_IFLNK 0 /* Link */
130 #define S_IFSOCK 0 /* Socket */
 
 
 
 
 
 
 
 
 
131
132 #if defined(_MSC_VER)
133 # define S_IRUSR S_IREAD /* Read user */
134 # define S_IWUSR S_IWRITE /* Write user */
135 # define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
139 # define S_IROTH 0 /* Read others */
140 # define S_IWOTH 0 /* Write others */
141 # define S_IXOTH 0 /* Execute others */
142 #endif
143
144 /* Indicates that d_type field is available in dirent structure */
145 #define _DIRENT_HAVE_D_TYPE
 
 
 
 
 
 
 
 
146
147 /* File type flags for d_type */
148 #define DT_UNKNOWN 0
149 #define DT_REG S_IFREG
150 #define DT_DIR S_IFDIR
151 #define DT_FIFO S_IFFIFO
152 #define DT_SOCK S_IFSOCK
153 #define DT_CHR S_IFCHR
154 #define DT_BLK S_IFBLK
155
156 /* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
161 * File type macros. Note that block devices, sockets and links cannot be
162 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
163 * only defined for compatibility. These macros should always return false
164 * on Windows.
165 */
166 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
167 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
168 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
169 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
170 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
171 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
172 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
173
174 /* For compatiblity with Unix */
175 #if !defined(PATH_MAX)
176 # define PATH_MAX MAX_PATH
177 #endif
178 #if !defined(FILENAME_MAX)
179 # define FILENAME_MAX MAX_PATH
180 #endif
181 #if !defined(NAME_MAX)
182 # define NAME_MAX FILENAME_MAX
183 #endif
184
185 /* Set errno variable */
186 #if defined(_MSC_VER)
187 #define DIRENT_SET_ERRNO(x) _set_errno (x)
188 #else
189 #define DIRENT_SET_ERRNO(x) (errno = (x))
190 #endif
191
192 #ifdef __cplusplus
193 extern "C" {
194 #endif
195
196 /* Wide-character versions */
 
197 struct _wdirent {
198 long d_ino; /* Always zero */
199 unsigned short d_reclen; /* Structure size */
200 size_t d_namlen; /* Length of name without \0 */
201 int d_type; /* File type */
@@ -203,11 +228,11 @@
203 };
204 typedef struct _wdirent _wdirent;
205
206 struct _WDIR {
207 struct _wdirent ent; /* Current directory entry */
208 WIN32_FIND_DATAW find_data; /* Private file data */
209 int cached; /* True if data is valid */
210 HANDLE handle; /* Win32 search handle */
211 wchar_t *patt; /* Initial directory name */
212 };
213 typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
214
215 static _WDIR *_wopendir (const wchar_t *dirname);
216 static struct _wdirent *_wreaddir (_WDIR *dirp);
217 static int _wclosedir (_WDIR *dirp);
218 static void _wrewinddir (_WDIR* dirp);
 
219
220 /* For compatibility with Symbian */
221 #define wdirent _wdirent
222 #define WDIR _WDIR
223 #define wopendir _wopendir
@@ -246,10 +272,30 @@
246 static struct dirent *readdir (DIR *dirp);
247 static int closedir (DIR *dirp);
248 static void rewinddir (DIR* dirp);
249
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251 /*
252 * Open directory stream DIRNAME for read and return a pointer to the
253 * internal working area that is used to retrieve individual directory
254 * entries.
255 */
@@ -256,31 +302,38 @@
256 static _WDIR*
257 _wopendir(
258 const wchar_t *dirname)
259 {
260 _WDIR *dirp = NULL;
261 int error = 0;
 
 
 
 
 
 
262
263 /* Allocate new _WDIR structure */
264 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
265 if (dirp != NULL) {
266 DWORD n;
267
268 /* Reset _WDIR structure */
269 dirp->handle = INVALID_HANDLE_VALUE;
270 dirp->patt = NULL;
 
271
272 /* Compute the length of full path plus zero terminator */
273 n = GetFullPathNameW (dirname, 0, NULL, NULL);
274
275 /* Allocate room for full path and search patterns */
276 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
277 if (dirp->patt) {
278
279 /*
280 * Convert relative directory name to an absolute one. This
281 * allows rewinddir() to function correctly when the current
282 * working directory is changed between opendir() and rewinddir().
283 */
284 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
285 if (n > 0) {
286 wchar_t *p;
@@ -303,25 +356,22 @@
303 }
304 *p++ = '*';
305 *p = '\0';
306
307 /* Open directory stream and retrieve the first entry */
308 dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
309 if (dirp->handle != INVALID_HANDLE_VALUE) {
310
311 /* Directory entry is now waiting in memory */
312 dirp->cached = 1;
313
314 } else {
315 /* Search pattern is not a directory name? */
316 DIRENT_SET_ERRNO (ENOENT);
317 error = 1;
 
318 }
319
320 } else {
321 /* Cannot convert directory name to wide character string */
322 DIRENT_SET_ERRNO (ENOENT);
323 error = 1;
324 }
325
326 } else {
327 /* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
350 */
351 static struct _wdirent*
352 _wreaddir(
353 _WDIR *dirp)
354 {
355 DWORD attr;
356 errno_t error;
357
358 /* Get next directory entry */
359 if (dirp->cached != 0) {
360 /* A valid directory entry already in memory */
361 dirp->cached = 0;
362 } else {
363 /* Get the next directory entry from stream */
364 if (dirp->handle == INVALID_HANDLE_VALUE) {
365 return NULL;
366 }
367 if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) {
368 /* The very last entry has been processed or an error occured */
369 FindClose (dirp->handle);
370 dirp->handle = INVALID_HANDLE_VALUE;
371 return NULL;
372 }
373 }
374
375 /* Copy file name as a wide-character string */
376 error = wcsncpy_s(
377 dirp->ent.d_name, /* Destination string */
378 PATH_MAX, /* Size of dest in words */
379 dirp->find_data.cFileName, /* Source string */
380 PATH_MAX + 1); /* Max # of chars to copy */
381 if (!error) {
382
383 /* Compute the length of name */
384 dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX);
385
386 /* Determine file type */
387 attr = dirp->find_data.dwFileAttributes;
388 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
389 dirp->ent.d_type = DT_CHR;
390 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
391 dirp->ent.d_type = DT_DIR;
392 } else {
393 dirp->ent.d_type = DT_REG;
394 }
395
396 /* Reset dummy fields */
397 dirp->ent.d_ino = 0;
398 dirp->ent.d_reclen = sizeof (dirp->ent);
399
400 } else {
401
402 /*
403 * Cannot copy file name from find_data to ent. Construct a
404 * dummy _wdirent structure to pass error to caller.
405 */
406 dirp->ent.d_name[0] = '?';
407 dirp->ent.d_name[1] = '\0';
408 dirp->ent.d_namlen = 1;
409 dirp->ent.d_type = DT_UNKNOWN;
410 dirp->ent.d_ino = 0;
411 dirp->ent.d_reclen = 0;
412 }
413
414 return &dirp->ent;
415 }
416
417 /*
418 * Close directory stream opened by opendir() function. This invalidates the
419 * DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
442 free (dirp);
443 ok = /*success*/0;
444
445 } else {
446 /* Invalid directory stream */
447 DIRENT_SET_ERRNO (EBADF);
448 ok = /*failure*/-1;
449 }
450 return ok;
451 }
452
@@ -456,26 +495,81 @@
456 */
457 static void
458 _wrewinddir(
459 _WDIR* dirp)
460 {
461 if (dirp != NULL) {
462 /* release search handle */
463 if (dirp->handle != INVALID_HANDLE_VALUE) {
464 FindClose (dirp->handle);
465 }
466
467 /* Open new search handle and retrieve the first directory entry */
468 dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
469 if (dirp->handle != INVALID_HANDLE_VALUE) {
470 /* a directory entry is now waiting in memory */
471 dirp->cached = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472 } else {
473 /* Failed to re-open directory: no directory entry in memory */
474 dirp->cached = 0;
 
 
475 }
 
 
 
 
 
 
476 }
 
 
477 }
478
479 /*
480 * Open directory stream using plain old C-string.
481 */
@@ -482,58 +576,34 @@
482 static DIR*
483 opendir(
484 const char *dirname)
485 {
486 struct DIR *dirp;
487 errno_t error = 0;
488
489 /* Must have directory name */
490 if (dirname == NULL) {
491 DIRENT_SET_ERRNO (ENOENT);
492 return NULL;
493 }
494
495 /* Allocate memory for multi-byte string directory structures */
496 dirp = (DIR*) malloc (sizeof (struct DIR));
497 if (dirp) {
498 wchar_t wname[PATH_MAX + 1];
499 size_t n;
500
501 /*
502 * Convert directory name to wide-character string.
503 *
504 * Be ware of the return schemantics of MultiByteToWideChar() --
505 * the function basically returns the number of characters written to
506 * output buffer or zero if the conversion fails. However, the
507 * function does not necessarily zero-terminate the output
508 * buffer and may return 0xFFFD if the string contains invalid
509 * characters!
510 */
511 n = MultiByteToWideChar(
512 CP_ACP, /* Input code page */
513 MB_PRECOMPOSED, /* Conversion flags */
514 dirname, /* Input string */
515 -1, /* Length of input string */
516 wname, /* Output buffer */
517 PATH_MAX); /* Size of output buffer */
518 if (n > 0 && n < PATH_MAX) {
519
520 /* Zero-terminate output buffer */
521 wname[n] = '\0';
522
523 /* Open directory stream with wide-character string file name */
524 dirp->wdirp = _wopendir (wname);
525 if (dirp->wdirp) {
526
527 /* Initialize directory structure */
528 dirp->ent.d_name[0] = '\0';
529 dirp->ent.d_namlen = 0;
530 dirp->ent.d_type = 0;
531 dirp->ent.d_ino = 0;
532 dirp->ent.d_reclen = 0;
533
534
535 } else {
536 /* Failed to open directory stream */
537 error = 1;
538 }
539
@@ -562,95 +632,99 @@
562 }
563
564 /*
565 * Read next directory entry.
566 *
567 * When working with console, please note that file names returned by
568 * readdir() are represented in the default ANSI code page while the
569 * console typically runs on another code page. Thus, non-ASCII characters
570 * will not usually display correctly. The problem can be fixed in two ways:
571 * (1) change the character set of console to 1252 using chcp utility and use
572 * Lucida Console font, or (2) always use _cprintf function when writing to
573 * console. The _cprinf() will re-encode ANSI strings to the console code
574 * page so non-ASCII characters will display correcly.
 
575 */
576 static struct dirent*
577 readdir(
578 DIR *dirp)
579 {
580 struct dirent *p;
581 struct _wdirent *wp;
582
583 /* Read next directory entry using wide-character string functions */
584 wp = _wreaddir (dirp->wdirp);
585 if (wp) {
586 size_t n;
 
 
 
 
 
587
588 /*
589 * Convert file name to multi-byte string.
590 *
591 * Be ware of the return schemantics of WideCharToMultiByte() --
592 * the function basically returns the number of bytes
593 * written to output buffer or zero if the conversion fails.
594 * However, the function does not necessarily zero-terminate the
595 * buffer and it may even return 0xFFFD the string contains
596 * invalid characters!
597 */
598 n = WideCharToMultiByte(
599 CP_ACP, /* Output code page */
600 0, /* Conversion flags */
601 wp->d_name, /* Input string */
602 wp->d_namlen, /* Length of input string */
603 dirp->ent.d_name, /* Output buffer */
604 PATH_MAX, /* Size of output buffer */
605 NULL, /* Replacement character */
606 NULL); /* If chars were replaced */
607 if (n > 0 && n < PATH_MAX) {
608
609 /* Zero-terminate buffer */
610 dirp->ent.d_name[n] = '\0';
611
612 /* Initialize directory entry for return */
613 p = &dirp->ent;
614
615 /* Compute length */
616 p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX);
617
618 /* Copy file attributes */
619 p->d_type = wp->d_type;
 
 
 
 
 
 
 
620
621 /* Reset dummy fields */
622 p->d_ino = 0;
623 p->d_reclen = sizeof (dirp->ent);
624
625
626 } else {
627
628 /*
629 * Cannot convert file name to multi-byte string so construct
630 * an errornous directory entry and return that. Note that
631 * we cannot return NULL as that would stop the processing
632 * of directory entries completely.
633 */
634 p = &dirp->ent;
635 p->d_name[0] = '?';
636 p->d_name[1] = '\0';
637 p->d_namlen = 1;
638 p->d_type = DT_UNKNOWN;
639 p->d_ino = 0;
640 p->d_reclen = 0;
641
642 }
643
644 } else {
645
646 /* End of directory stream */
647 p = NULL;
648
649 }
650
651 return p;
652 }
653
654 /*
655 * Close directory stream.
656 */
@@ -667,13 +741,15 @@
667
668 /* Release multi-byte character version */
669 free (dirp);
670
671 } else {
 
672 /* Invalid directory stream */
673 DIRENT_SET_ERRNO (EBADF);
674 ok = /*failure*/-1;
 
675 }
676 return ok;
677 }
678
679 /*
@@ -684,12 +760,130 @@
684 DIR* dirp)
685 {
686 /* Rewind wide-character string directory stream */
687 _wrewinddir (dirp->wdirp);
688 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
690
691 #ifdef __cplusplus
692 }
693 #endif
694 #endif /*DIRENT_H*/
695
696
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
20 * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Version 1.13, Dec 12 2012, Toni Ronkko
27 * Use traditional 8+3 file name if the name cannot be represented in the
28 * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to
29 * Konstantin Khomoutov for testing.
30 *
31 * Version 1.12.1, Oct 1 2012, Toni Ronkko
32 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
33 * capital W) in order to maintain compatibility with MingW.
34 *
35 * Version 1.12, Sep 30 2012, Toni Ronkko
36 * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
37 * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
38 * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
 
 
39 *
40 * Do not include windows.h. This allows dirent.h to be integrated more
41 * easily into programs using winsock. Thanks to Fernando Azaldegui.
42 *
43 * Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
91 *****************************************************************************/
92 #ifndef DIRENT_H
93 #define DIRENT_H
94
95 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
96 # define _X86_
97 #endif
98 #include <stdio.h>
99 #include <stdarg.h>
100 #include <windef.h>
101 #include <winbase.h>
102 #include <wchar.h>
 
103 #include <string.h>
104 #include <stdlib.h>
105 #include <malloc.h>
106 #include <sys/types.h>
107 #include <sys/stat.h>
108 #include <errno.h>
109
110 /* Indicates that d_type field is available in dirent structure */
111 #define _DIRENT_HAVE_D_TYPE
112
113 /* Indicates that d_namlen field is available in dirent structure */
114 #define _DIRENT_HAVE_D_NAMLEN
115
116 /* Entries missing from MSVC 6.0 */
117 #if !defined(FILE_ATTRIBUTE_DEVICE)
118 # define FILE_ATTRIBUTE_DEVICE 0x40
119 #endif
120
121 /* File type and permission flags for stat() */
122 #if !defined(S_IFMT)
123 # define S_IFMT _S_IFMT /* File type mask */
124 #endif
125 #if !defined(S_IFDIR)
126 # define S_IFDIR _S_IFDIR /* Directory */
127 #endif
128 #if !defined(S_IFCHR)
129 # define S_IFCHR _S_IFCHR /* Character device */
130 #endif
131 #if !defined(S_IFFIFO)
132 # define S_IFFIFO _S_IFFIFO /* Pipe */
133 #endif
134 #if !defined(S_IFREG)
135 # define S_IFREG _S_IFREG /* Regular file */
136 #endif
137 #if !defined(S_IREAD)
138 # define S_IREAD _S_IREAD /* Read permission */
139 #endif
140 #if !defined(S_IWRITE)
141 # define S_IWRITE _S_IWRITE /* Write permission */
142 #endif
143 #if !defined(S_IEXEC)
144 # define S_IEXEC _S_IEXEC /* Execute permission */
145 #endif
146 #if !defined(S_IFIFO)
147 # define S_IFIFO _S_IFIFO /* Pipe */
148 #endif
149 #if !defined(S_IFBLK)
150 # define S_IFBLK 0 /* Block device */
151 #endif
152 #if !defined(S_IFLNK)
153 # define S_IFLNK 0 /* Link */
154 #endif
155 #if !defined(S_IFSOCK)
156 # define S_IFSOCK 0 /* Socket */
157 #endif
158
159 #if defined(_MSC_VER)
160 # define S_IRUSR S_IREAD /* Read user */
161 # define S_IWUSR S_IWRITE /* Write user */
162 # define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
166 # define S_IROTH 0 /* Read others */
167 # define S_IWOTH 0 /* Write others */
168 # define S_IXOTH 0 /* Execute others */
169 #endif
170
171 /* Maximum length of file name */
172 #if !defined(PATH_MAX)
173 # define PATH_MAX MAX_PATH
174 #endif
175 #if !defined(FILENAME_MAX)
176 # define FILENAME_MAX MAX_PATH
177 #endif
178 #if !defined(NAME_MAX)
179 # define NAME_MAX FILENAME_MAX
180 #endif
181
182 /* File type flags for d_type */
183 #define DT_UNKNOWN 0
184 #define DT_REG S_IFREG
185 #define DT_DIR S_IFDIR
186 #define DT_FIFO S_IFIFO
187 #define DT_SOCK S_IFSOCK
188 #define DT_CHR S_IFCHR
189 #define DT_BLK S_IFBLK
190
191 /* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
196 * File type macros. Note that block devices, sockets and links cannot be
197 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
198 * only defined for compatibility. These macros should always return false
199 * on Windows.
200 */
201 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
202 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
203 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
204 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
205 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
206 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
207 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
208
209 /* Return the exact length of d_namlen without zero terminator */
210 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
211
212 /* Return number of bytes needed to store d_namlen */
213 #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
214
 
 
 
 
 
 
 
 
 
 
 
215
216 #ifdef __cplusplus
217 extern "C" {
218 #endif
219
220
221 /* Wide-character version */
222 struct _wdirent {
223 long d_ino; /* Always zero */
224 unsigned short d_reclen; /* Structure size */
225 size_t d_namlen; /* Length of name without \0 */
226 int d_type; /* File type */
@@ -203,11 +228,11 @@
228 };
229 typedef struct _wdirent _wdirent;
230
231 struct _WDIR {
232 struct _wdirent ent; /* Current directory entry */
233 WIN32_FIND_DATAW data; /* Private file data */
234 int cached; /* True if data is valid */
235 HANDLE handle; /* Win32 search handle */
236 wchar_t *patt; /* Initial directory name */
237 };
238 typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
239
240 static _WDIR *_wopendir (const wchar_t *dirname);
241 static struct _wdirent *_wreaddir (_WDIR *dirp);
242 static int _wclosedir (_WDIR *dirp);
243 static void _wrewinddir (_WDIR* dirp);
244
245
246 /* For compatibility with Symbian */
247 #define wdirent _wdirent
248 #define WDIR _WDIR
249 #define wopendir _wopendir
@@ -246,10 +272,30 @@
272 static struct dirent *readdir (DIR *dirp);
273 static int closedir (DIR *dirp);
274 static void rewinddir (DIR* dirp);
275
276
277 /* Internal utility functions */
278 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
279 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
280
281 static int dirent_mbstowcs_s(
282 size_t *pReturnValue,
283 wchar_t *wcstr,
284 size_t sizeInWords,
285 const char *mbstr,
286 size_t count);
287
288 static int dirent_wcstombs_s(
289 size_t *pReturnValue,
290 char *mbstr,
291 size_t sizeInBytes,
292 const wchar_t *wcstr,
293 size_t count);
294
295 static void dirent_set_errno (int error);
296
297 /*
298 * Open directory stream DIRNAME for read and return a pointer to the
299 * internal working area that is used to retrieve individual directory
300 * entries.
301 */
@@ -256,31 +302,38 @@
302 static _WDIR*
303 _wopendir(
304 const wchar_t *dirname)
305 {
306 _WDIR *dirp = NULL;
307 int error;
308
309 /* Must have directory name */
310 if (dirname == NULL || dirname[0] == '\0') {
311 dirent_set_errno (ENOENT);
312 return NULL;
313 }
314
315 /* Allocate new _WDIR structure */
316 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
317 if (dirp != NULL) {
318 DWORD n;
319
320 /* Reset _WDIR structure */
321 dirp->handle = INVALID_HANDLE_VALUE;
322 dirp->patt = NULL;
323 dirp->cached = 0;
324
325 /* Compute the length of full path plus zero terminator */
326 n = GetFullPathNameW (dirname, 0, NULL, NULL);
327
328 /* Allocate room for absolute directory name and search pattern */
329 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
330 if (dirp->patt) {
331
332 /*
333 * Convert relative directory name to an absolute one. This
334 * allows rewinddir() to function correctly even when current
335 * working directory is changed between opendir() and rewinddir().
336 */
337 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
338 if (n > 0) {
339 wchar_t *p;
@@ -303,25 +356,22 @@
356 }
357 *p++ = '*';
358 *p = '\0';
359
360 /* Open directory stream and retrieve the first entry */
361 if (dirent_first (dirp)) {
362 /* Directory stream opened successfully */
363 error = 0;
 
 
 
364 } else {
365 /* Cannot retrieve first entry */
 
366 error = 1;
367 dirent_set_errno (ENOENT);
368 }
369
370 } else {
371 /* Cannot retrieve full path name */
372 dirent_set_errno (ENOENT);
373 error = 1;
374 }
375
376 } else {
377 /* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
400 */
401 static struct _wdirent*
402 _wreaddir(
403 _WDIR *dirp)
404 {
405 WIN32_FIND_DATAW *datap;
406 struct _wdirent *entp;
407
408 /* Read next directory entry */
409 datap = dirent_next (dirp);
410 if (datap) {
411 size_t n;
412 DWORD attr;
413
414 /* Pointer to directory entry to return */
415 entp = &dirp->ent;
416
417 /*
418 * Copy file name as wide-character string. If the file name is too
419 * long to fit in to the destination buffer, then truncate file name
420 * to PATH_MAX characters and zero-terminate the buffer.
421 */
422 n = 0;
423 while (n < PATH_MAX && datap->cFileName[n] != 0) {
424 entp->d_name[n] = datap->cFileName[n];
425 n++;
426 }
427 dirp->ent.d_name[n] = 0;
428
429 /* Length of file name excluding zero terminator */
430 entp->d_namlen = n;
431
432 /* File type */
433 attr = datap->dwFileAttributes;
 
 
 
 
434 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
435 entp->d_type = DT_CHR;
436 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
437 entp->d_type = DT_DIR;
438 } else {
439 entp->d_type = DT_REG;
440 }
441
442 /* Reset dummy fields */
443 entp->d_ino = 0;
444 entp->d_reclen = sizeof (struct _wdirent);
445
446 } else {
447
448 /* Last directory entry read */
449 entp = NULL;
450
 
 
 
 
 
 
 
451 }
452
453 return entp;
454 }
455
456 /*
457 * Close directory stream opened by opendir() function. This invalidates the
458 * DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
481 free (dirp);
482 ok = /*success*/0;
483
484 } else {
485 /* Invalid directory stream */
486 dirent_set_errno (EBADF);
487 ok = /*failure*/-1;
488 }
489 return ok;
490 }
491
@@ -456,26 +495,81 @@
495 */
496 static void
497 _wrewinddir(
498 _WDIR* dirp)
499 {
500 if (dirp) {
501 /* Release existing search handle */
502 if (dirp->handle != INVALID_HANDLE_VALUE) {
503 FindClose (dirp->handle);
504 }
505
506 /* Open new search handle */
507 dirent_first (dirp);
508 }
509 }
510
511 /* Get first directory entry (internal) */
512 static WIN32_FIND_DATAW*
513 dirent_first(
514 _WDIR *dirp)
515 {
516 WIN32_FIND_DATAW *datap;
517
518 /* Open directory and retrieve the first entry */
519 dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
520 if (dirp->handle != INVALID_HANDLE_VALUE) {
521
522 /* a directory entry is now waiting in memory */
523 datap = &dirp->data;
524 dirp->cached = 1;
525
526 } else {
527
528 /* Failed to re-open directory: no directory entry in memory */
529 dirp->cached = 0;
530 datap = NULL;
531
532 }
533 return datap;
534 }
535
536 /* Get next directory entry (internal) */
537 static WIN32_FIND_DATAW*
538 dirent_next(
539 _WDIR *dirp)
540 {
541 WIN32_FIND_DATAW *p;
542
543 /* Get next directory entry */
544 if (dirp->cached != 0) {
545
546 /* A valid directory entry already in memory */
547 p = &dirp->data;
548 dirp->cached = 0;
549
550 } else if (dirp->handle != INVALID_HANDLE_VALUE) {
551
552 /* Get the next directory entry from stream */
553 if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
554 /* Got a file */
555 p = &dirp->data;
556 } else {
557 /* The very last entry has been processed or an error occured */
558 FindClose (dirp->handle);
559 dirp->handle = INVALID_HANDLE_VALUE;
560 p = NULL;
561 }
562
563 } else {
564
565 /* End of directory stream reached */
566 p = NULL;
567
568 }
569
570 return p;
571 }
572
573 /*
574 * Open directory stream using plain old C-string.
575 */
@@ -482,58 +576,34 @@
576 static DIR*
577 opendir(
578 const char *dirname)
579 {
580 struct DIR *dirp;
581 int error;
582
583 /* Must have directory name */
584 if (dirname == NULL || dirname[0] == '\0') {
585 dirent_set_errno (ENOENT);
586 return NULL;
587 }
588
589 /* Allocate memory for DIR structure */
590 dirp = (DIR*) malloc (sizeof (struct DIR));
591 if (dirp) {
592 wchar_t wname[PATH_MAX + 1];
593 size_t n;
594
595 /* Convert directory name to wide-character string */
596 error = dirent_mbstowcs_s(
597 &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
598 if (!error) {
599
600 /* Open directory stream using wide-character name */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601 dirp->wdirp = _wopendir (wname);
602 if (dirp->wdirp) {
603 /* Directory stream opened */
604 error = 0;
 
 
 
 
 
 
 
605 } else {
606 /* Failed to open directory stream */
607 error = 1;
608 }
609
@@ -562,95 +632,99 @@
632 }
633
634 /*
635 * Read next directory entry.
636 *
637 * When working with text consoles, please note that file names returned by
638 * readdir() are represented in the default ANSI code page while any output to
639 * console is typically formatted on another code page. Thus, non-ASCII
640 * characters in file names will not usually display correctly on console. The
641 * problem can be fixed in two ways: (1) change the character set of console
642 * to 1252 using chcp utility and use Lucida Console font, or (2) use
643 * _cprintf function when writing to console. The _cprinf() will re-encode
644 * ANSI strings to the console code page so many non-ASCII characters will
645 * display correcly.
646 */
647 static struct dirent*
648 readdir(
649 DIR *dirp)
650 {
651 WIN32_FIND_DATAW *datap;
652 struct dirent *entp;
653
654 /* Read next directory entry */
655 datap = dirent_next (dirp->wdirp);
656 if (datap) {
657 size_t n;
658 int error;
659
660 /* Attempt to convert file name to multi-byte string */
661 error = dirent_wcstombs_s(
662 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
663
664 /*
665 * If the file name cannot be represented by a multi-byte string,
666 * then attempt to use old 8+3 file name. This allows traditional
667 * Unix-code to access some file names despite of unicode
668 * characters, although file names may seem unfamiliar to the user.
669 *
670 * Be ware that the code below cannot come up with a short file
671 * name unless the file system provides one. At least
672 * VirtualBox shared folders fail to do this.
673 */
674 if (error && datap->cAlternateFileName[0] != '\0') {
675 error = dirent_wcstombs_s(
676 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
677 sizeof (datap->cAlternateFileName) /
678 sizeof (datap->cAlternateFileName[0]));
679 }
680
681 if (!error) {
682 DWORD attr;
 
 
 
 
683
684 /* Initialize directory entry for return */
685 entp = &dirp->ent;
686
687 /* Length of file name excluding zero terminator */
688 entp->d_namlen = n - 1;
689
690 /* File attributes */
691 attr = datap->dwFileAttributes;
692 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
693 entp->d_type = DT_CHR;
694 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
695 entp->d_type = DT_DIR;
696 } else {
697 entp->d_type = DT_REG;
698 }
699
700 /* Reset dummy fields */
701 entp->d_ino = 0;
702 entp->d_reclen = sizeof (struct dirent);
 
703
704 } else {
 
705 /*
706 * Cannot convert file name to multi-byte string so construct
707 * an errornous directory entry and return that. Note that
708 * we cannot return NULL as that would stop the processing
709 * of directory entries completely.
710 */
711 entp = &dirp->ent;
712 entp->d_name[0] = '?';
713 entp->d_name[1] = '\0';
714 entp->d_namlen = 1;
715 entp->d_type = DT_UNKNOWN;
716 entp->d_ino = 0;
717 entp->d_reclen = 0;
 
718 }
719
720 } else {
721 /* No more directory entries */
722 entp = NULL;
 
 
723 }
724
725 return entp;
726 }
727
728 /*
729 * Close directory stream.
730 */
@@ -667,13 +741,15 @@
741
742 /* Release multi-byte character version */
743 free (dirp);
744
745 } else {
746
747 /* Invalid directory stream */
748 dirent_set_errno (EBADF);
749 ok = /*failure*/-1;
750
751 }
752 return ok;
753 }
754
755 /*
@@ -684,12 +760,130 @@
760 DIR* dirp)
761 {
762 /* Rewind wide-character string directory stream */
763 _wrewinddir (dirp->wdirp);
764 }
765
766 /* Convert multi-byte string to wide character string */
767 static int
768 dirent_mbstowcs_s(
769 size_t *pReturnValue,
770 wchar_t *wcstr,
771 size_t sizeInWords,
772 const char *mbstr,
773 size_t count)
774 {
775 int error;
776
777 #if defined(_MSC_VER) && _MSC_VER >= 1400
778
779 /* Microsoft Visual Studio 2005 or later */
780 error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
781
782 #else
783
784 /* Older Visual Studio or non-Microsoft compiler */
785 size_t n;
786
787 /* Convert to wide-character string */
788 n = mbstowcs (wcstr, mbstr, count);
789 if (n < sizeInWords) {
790
791 /* Zero-terminate output buffer */
792 if (wcstr) {
793 wcstr[n] = 0;
794 }
795
796 /* Length of resuting multi-byte string WITH zero terminator */
797 if (pReturnValue) {
798 *pReturnValue = n + 1;
799 }
800
801 /* Success */
802 error = 0;
803
804 } else {
805
806 /* Could not convert string */
807 error = 1;
808
809 }
810
811 #endif
812
813 return error;
814 }
815
816 /* Convert wide-character string to multi-byte string */
817 static int
818 dirent_wcstombs_s(
819 size_t *pReturnValue,
820 char *mbstr,
821 size_t sizeInBytes,
822 const wchar_t *wcstr,
823 size_t count)
824 {
825 int error;
826
827 #if defined(_MSC_VER) && _MSC_VER >= 1400
828
829 /* Microsoft Visual Studio 2005 or later */
830 error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
831
832 #else
833
834 /* Older Visual Studio or non-Microsoft compiler */
835 size_t n;
836
837 /* Convert to multi-byte string */
838 n = wcstombs (mbstr, wcstr, count);
839 if (n < sizeInBytes) {
840
841 /* Zero-terminate output buffer */
842 if (mbstr) {
843 mbstr[n] = '\0';
844 }
845
846 /* Lenght of resulting multi-bytes string WITH zero-terminator */
847 if (pReturnValue) {
848 *pReturnValue = n + 1;
849 }
850
851 /* Success */
852 error = 0;
853
854 } else {
855
856 /* Cannot convert string */
857 error = 1;
858
859 }
860
861 #endif
862
863 return error;
864 }
865
866 /* Set errno variable */
867 static void
868 dirent_set_errno(
869 int error)
870 {
871 #if defined(_MSC_VER)
872
873 /* Microsoft Visual Studio */
874 _set_errno (error);
875
876 #else
877
878 /* Non-Microsoft compiler */
879 errno = error;
880
881 #endif
882 }
883
884
885 #ifdef __cplusplus
886 }
887 #endif
888 #endif /*DIRENT_H*/
889
890
+29 -28
--- www/build.wiki
+++ www/build.wiki
@@ -1,6 +1,6 @@
1
-<title>Building and Installing Fossil</title>
1
+<title>Compiling and Installing Fossil</title>
22
33
<h2>0.0 Using A Pre-compiled Binary</h2>
44
55
<p>Released versions of fossil come with
66
<a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and
@@ -25,33 +25,29 @@
2525
2626
<p><hr>
2727
2828
<h2>1.0 Obtaining The Source Code</h2>
2929
30
-<p>Fossil is self-hosting, so you can obtain a ZIP archive containing
31
-a snapshot of the <em>latest</em> version directly from fossil's own fossil
32
-repository. Additionally, source archives of <em>released</em> versions of
30
+<p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball
31
+containing a snapshot of the <em>latest</em> version directly from
32
+Fossil's own fossil repository. Additionally, source archives of
33
+<em>released</em> versions of
3334
fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>.
3435
To obtain a development version of fossil, follow these steps:</p>
3536
3637
<ol>
3738
<li><p>Point your web browser at
3839
<a href="http://www.fossil-scm.org/">
39
-http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li>
40
-
41
-<li><p>Log in as anonymous. The password is shown on screen.
42
-The reason for requiring this login is to prevent spiders from
43
-walking the entire website, downloading ZIP archives
44
-of every historical version, and thereby soaking up all our bandwidth.</p></li>
40
+http://www.fossil-scm.org/</a>.</p></li>
4541
4642
<li><p>Click on the
4743
<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a>
4844
link at the top of the page.</p></li>
4945
50
-<li><p>Select a version of of fossil you want to download. Click on its
51
-link. Note that you must successfully log in as "anonymous" in step 1
52
-above in order to see the link to the detailed version information.</p></li>
46
+<li><p>Select a version of of Fossil you want to download. The latest
47
+version on the trunk branch is usually a good choice. Click on its
48
+link.</p></li>
5349
5450
<li><p>Finally, click on one of the
5551
"Zip Archive" or "Tarball" links, according to your preference.
5652
These link will build a ZIP archive or a gzip-compressed tarball of the
5753
complete source code and download it to your browser.
@@ -59,11 +55,11 @@
5955
6056
<h2>2.0 Compiling</h2>
6157
6258
<ol>
6359
<li value="6">
64
-<p>Unpack the ZIP or tarball you downloaded into that directory then
60
+<p>Unpack the ZIP or tarball you downloaded then
6561
<b>cd</b> into the directory created.</p></li>
6662
6763
<li><i>(Optional, unix only)</i>
6864
Run <b>./configure</b> to construct a makefile.
6965
@@ -79,12 +75,12 @@
7975
<li><p>
8076
Other configuration options can be seen by running
8177
<b>./configure --help</b>
8278
</ol>
8379
84
-<li><p>Run make to build the "fossil" or "fossil.exe" executable. The
85
-details depend on your platform and compiler.
80
+<li><p>Run "<b>make</b>" to build the "fossil" or "fossil.exe" executable.
81
+The details depend on your platform and compiler.
8682
8783
<ol type="a">
8884
<li><p><i>Unix</i> → the configure-generated Makefile should work on
8985
all unix and unix-like systems. Simply type "<b>make</b>".
9086
@@ -102,16 +98,10 @@
10298
change to the "win/" subdirectory ("<b>cd win</b>") then run
10399
"<b>nmake /f Makefile.msc</b>".
104100
</ol>
105101
</ol>
106102
107
-<p>Note that Fossil requires the "zlib" compression library. This library
108
-is available by default on most unix systems, but it will typically have to
109
-be installed separately on windows systems. For windows builds, you may
110
-need to edit the makefile to tell it exactly where zlib is located on your
111
-system.</p>
112
-
113103
<h2>3.0 Installing</h2>
114104
115105
<ol>
116106
<li value="9">
117107
<p>The finished binary is named "fossil" (or "fossil.exe" on windows).
@@ -124,11 +114,22 @@
124114
To uninstall, just delete the binary.</p>
125115
</ol>
126116
127117
<h2>4.0 Additional Considerations</h2>
128118
129
-</nowiki>
130
- * If the makefiles that come with Fossil do not work for
131
- you, or for some other reason you want to know how to build
132
- Fossil manually, then refer to the
133
- [./makefile.wiki | Fossil Build Process] document which describes
134
- in detail what the makefiles do behind the scenes.
119
+<ul>
120
+<li><p>
121
+ If the makefiles that come with Fossil do not work for
122
+ you, or for some other reason you want to know how to build
123
+ Fossil manually, then refer to the
124
+ [./makefile.wiki | Fossil Build Process] document which describes
125
+ in detail what the makefiles do behind the scenes.
126
+
127
+<li><p>
128
+ To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile
129
+ generated by configure to add the following lines:
130
+ <blockquote><pre>
131
+ TCC += -DSQLITE_WITHOUT_ZONEMALLOC
132
+ TCC += -DWITHOUT_ICONV
133
+ TCC += -Dsocketlen_t=int
134
+ </pre></blockquote>
135
+</ul>
135136
--- www/build.wiki
+++ www/build.wiki
@@ -1,6 +1,6 @@
1 <title>Building and Installing Fossil</title>
2
3 <h2>0.0 Using A Pre-compiled Binary</h2>
4
5 <p>Released versions of fossil come with
6 <a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and
@@ -25,33 +25,29 @@
25
26 <p><hr>
27
28 <h2>1.0 Obtaining The Source Code</h2>
29
30 <p>Fossil is self-hosting, so you can obtain a ZIP archive containing
31 a snapshot of the <em>latest</em> version directly from fossil's own fossil
32 repository. Additionally, source archives of <em>released</em> versions of
 
33 fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>.
34 To obtain a development version of fossil, follow these steps:</p>
35
36 <ol>
37 <li><p>Point your web browser at
38 <a href="http://www.fossil-scm.org/">
39 http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li>
40
41 <li><p>Log in as anonymous. The password is shown on screen.
42 The reason for requiring this login is to prevent spiders from
43 walking the entire website, downloading ZIP archives
44 of every historical version, and thereby soaking up all our bandwidth.</p></li>
45
46 <li><p>Click on the
47 <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a>
48 link at the top of the page.</p></li>
49
50 <li><p>Select a version of of fossil you want to download. Click on its
51 link. Note that you must successfully log in as "anonymous" in step 1
52 above in order to see the link to the detailed version information.</p></li>
53
54 <li><p>Finally, click on one of the
55 "Zip Archive" or "Tarball" links, according to your preference.
56 These link will build a ZIP archive or a gzip-compressed tarball of the
57 complete source code and download it to your browser.
@@ -59,11 +55,11 @@
59
60 <h2>2.0 Compiling</h2>
61
62 <ol>
63 <li value="6">
64 <p>Unpack the ZIP or tarball you downloaded into that directory then
65 <b>cd</b> into the directory created.</p></li>
66
67 <li><i>(Optional, unix only)</i>
68 Run <b>./configure</b> to construct a makefile.
69
@@ -79,12 +75,12 @@
79 <li><p>
80 Other configuration options can be seen by running
81 <b>./configure --help</b>
82 </ol>
83
84 <li><p>Run make to build the "fossil" or "fossil.exe" executable. The
85 details depend on your platform and compiler.
86
87 <ol type="a">
88 <li><p><i>Unix</i> → the configure-generated Makefile should work on
89 all unix and unix-like systems. Simply type "<b>make</b>".
90
@@ -102,16 +98,10 @@
102 change to the "win/" subdirectory ("<b>cd win</b>") then run
103 "<b>nmake /f Makefile.msc</b>".
104 </ol>
105 </ol>
106
107 <p>Note that Fossil requires the "zlib" compression library. This library
108 is available by default on most unix systems, but it will typically have to
109 be installed separately on windows systems. For windows builds, you may
110 need to edit the makefile to tell it exactly where zlib is located on your
111 system.</p>
112
113 <h2>3.0 Installing</h2>
114
115 <ol>
116 <li value="9">
117 <p>The finished binary is named "fossil" (or "fossil.exe" on windows).
@@ -124,11 +114,22 @@
124 To uninstall, just delete the binary.</p>
125 </ol>
126
127 <h2>4.0 Additional Considerations</h2>
128
129 </nowiki>
130 * If the makefiles that come with Fossil do not work for
131 you, or for some other reason you want to know how to build
132 Fossil manually, then refer to the
133 [./makefile.wiki | Fossil Build Process] document which describes
134 in detail what the makefiles do behind the scenes.
 
 
 
 
 
 
 
 
 
 
 
135
--- www/build.wiki
+++ www/build.wiki
@@ -1,6 +1,6 @@
1 <title>Compiling and Installing Fossil</title>
2
3 <h2>0.0 Using A Pre-compiled Binary</h2>
4
5 <p>Released versions of fossil come with
6 <a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and
@@ -25,33 +25,29 @@
25
26 <p><hr>
27
28 <h2>1.0 Obtaining The Source Code</h2>
29
30 <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball
31 containing a snapshot of the <em>latest</em> version directly from
32 Fossil's own fossil repository. Additionally, source archives of
33 <em>released</em> versions of
34 fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>.
35 To obtain a development version of fossil, follow these steps:</p>
36
37 <ol>
38 <li><p>Point your web browser at
39 <a href="http://www.fossil-scm.org/">
40 http://www.fossil-scm.org/</a>.</p></li>
 
 
 
 
 
41
42 <li><p>Click on the
43 <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a>
44 link at the top of the page.</p></li>
45
46 <li><p>Select a version of of Fossil you want to download. The latest
47 version on the trunk branch is usually a good choice. Click on its
48 link.</p></li>
49
50 <li><p>Finally, click on one of the
51 "Zip Archive" or "Tarball" links, according to your preference.
52 These link will build a ZIP archive or a gzip-compressed tarball of the
53 complete source code and download it to your browser.
@@ -59,11 +55,11 @@
55
56 <h2>2.0 Compiling</h2>
57
58 <ol>
59 <li value="6">
60 <p>Unpack the ZIP or tarball you downloaded then
61 <b>cd</b> into the directory created.</p></li>
62
63 <li><i>(Optional, unix only)</i>
64 Run <b>./configure</b> to construct a makefile.
65
@@ -79,12 +75,12 @@
75 <li><p>
76 Other configuration options can be seen by running
77 <b>./configure --help</b>
78 </ol>
79
80 <li><p>Run "<b>make</b>" to build the "fossil" or "fossil.exe" executable.
81 The details depend on your platform and compiler.
82
83 <ol type="a">
84 <li><p><i>Unix</i> → the configure-generated Makefile should work on
85 all unix and unix-like systems. Simply type "<b>make</b>".
86
@@ -102,16 +98,10 @@
98 change to the "win/" subdirectory ("<b>cd win</b>") then run
99 "<b>nmake /f Makefile.msc</b>".
100 </ol>
101 </ol>
102
 
 
 
 
 
 
103 <h2>3.0 Installing</h2>
104
105 <ol>
106 <li value="9">
107 <p>The finished binary is named "fossil" (or "fossil.exe" on windows).
@@ -124,11 +114,22 @@
114 To uninstall, just delete the binary.</p>
115 </ol>
116
117 <h2>4.0 Additional Considerations</h2>
118
119 <ul>
120 <li><p>
121 If the makefiles that come with Fossil do not work for
122 you, or for some other reason you want to know how to build
123 Fossil manually, then refer to the
124 [./makefile.wiki | Fossil Build Process] document which describes
125 in detail what the makefiles do behind the scenes.
126
127 <li><p>
128 To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile
129 generated by configure to add the following lines:
130 <blockquote><pre>
131 TCC += -DSQLITE_WITHOUT_ZONEMALLOC
132 TCC += -DWITHOUT_ICONV
133 TCC += -Dsocketlen_t=int
134 </pre></blockquote>
135 </ul>
136
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -14,12 +14,11 @@
1414
<li> Special names:
1515
<ul>
1616
<li> <b>tip</b>
1717
<li> <b>current</b>
1818
<li> <b>next</b>
19
-<li> <b>previous</b>
20
-<li> <b>ckout</b>
19
+<li> <b>previous</b> or <b>prev</b>
2120
</ul>
2221
</ul>
2322
</td></tr>
2423
</table>
2524
Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept
@@ -194,12 +193,12 @@
194193
equivalent to the timestamp tag "5000-01-01".
195194
196195
If the command is being run from a working check-out (not against a bare
197196
repository) then a few extra tags apply. The "current" tag means the
198197
current check-out. The "next" tag means the youngest child of the
199
-current check-out. And the "previous" tag means the primary (non-merge)
200
-parent of the current check-out.
198
+current check-out. And the "previous" or "prev" tag means the primary
199
+(non-merge) parent of the current check-out.
201200
202201
<h2>Additional Examples</h2>
203202
204203
To view the changes in the most recent check-in prior to the version currently
205204
checked out:
206205
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -14,12 +14,11 @@
14 <li> Special names:
15 <ul>
16 <li> <b>tip</b>
17 <li> <b>current</b>
18 <li> <b>next</b>
19 <li> <b>previous</b>
20 <li> <b>ckout</b>
21 </ul>
22 </ul>
23 </td></tr>
24 </table>
25 Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept
@@ -194,12 +193,12 @@
194 equivalent to the timestamp tag "5000-01-01".
195
196 If the command is being run from a working check-out (not against a bare
197 repository) then a few extra tags apply. The "current" tag means the
198 current check-out. The "next" tag means the youngest child of the
199 current check-out. And the "previous" tag means the primary (non-merge)
200 parent of the current check-out.
201
202 <h2>Additional Examples</h2>
203
204 To view the changes in the most recent check-in prior to the version currently
205 checked out:
206
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -14,12 +14,11 @@
14 <li> Special names:
15 <ul>
16 <li> <b>tip</b>
17 <li> <b>current</b>
18 <li> <b>next</b>
19 <li> <b>previous</b> or <b>prev</b>
 
20 </ul>
21 </ul>
22 </td></tr>
23 </table>
24 Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept
@@ -194,12 +193,12 @@
193 equivalent to the timestamp tag "5000-01-01".
194
195 If the command is being run from a working check-out (not against a bare
196 repository) then a few extra tags apply. The "current" tag means the
197 current check-out. The "next" tag means the youngest child of the
198 current check-out. And the "previous" or "prev" tag means the primary
199 (non-merge) parent of the current check-out.
200
201 <h2>Additional Examples</h2>
202
203 To view the changes in the most recent check-in prior to the version currently
204 checked out:
205
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -75,8 +75,8 @@
7575
the checklist and/or the automated test scripts to cover their additions.
7676
7777
7878
<h2>5.0 See Also</h2>
7979
80
- * [./build.wiki | How To Build And Install Fossil]
80
+ * [./build.wiki | How To Compile And Install Fossil]
8181
* [./makefile.wiki | The Fossil Build Process]
8282
* [./tech_overview.wiki | A Technical Overview of Fossil]
8383
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -75,8 +75,8 @@
75 the checklist and/or the automated test scripts to cover their additions.
76
77
78 <h2>5.0 See Also</h2>
79
80 * [./build.wiki | How To Build And Install Fossil]
81 * [./makefile.wiki | The Fossil Build Process]
82 * [./tech_overview.wiki | A Technical Overview of Fossil]
83
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -75,8 +75,8 @@
75 the checklist and/or the automated test scripts to cover their additions.
76
77
78 <h2>5.0 See Also</h2>
79
80 * [./build.wiki | How To Compile And Install Fossil]
81 * [./makefile.wiki | The Fossil Build Process]
82 * [./tech_overview.wiki | A Technical Overview of Fossil]
83
+1 -1
--- www/index.wiki
+++ www/index.wiki
@@ -115,11 +115,11 @@
115115
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
116116
* [./faq.wiki | FAQ]
117117
* The [./concepts.wiki | concepts] behind fossil
118118
* [./quickstart.wiki | Quick Start] guide to using fossil
119119
* [./qandc.wiki | Questions &amp; Criticisms] directed at fossil.
120
- * [./build.wiki | Building And Installing]
120
+ * [./build.wiki | Compiling and Installing]
121121
* Fossil supports [./embeddeddoc.wiki | embedded documentation]
122122
that is versioned along with project source code.
123123
* Fossil uses an [./fileformat.wiki | enduring file format] that is
124124
designed to be readable, searchable, and extensible by people
125125
not yet born.
126126
--- www/index.wiki
+++ www/index.wiki
@@ -115,11 +115,11 @@
115 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
116 * [./faq.wiki | FAQ]
117 * The [./concepts.wiki | concepts] behind fossil
118 * [./quickstart.wiki | Quick Start] guide to using fossil
119 * [./qandc.wiki | Questions &amp; Criticisms] directed at fossil.
120 * [./build.wiki | Building And Installing]
121 * Fossil supports [./embeddeddoc.wiki | embedded documentation]
122 that is versioned along with project source code.
123 * Fossil uses an [./fileformat.wiki | enduring file format] that is
124 designed to be readable, searchable, and extensible by people
125 not yet born.
126
--- www/index.wiki
+++ www/index.wiki
@@ -115,11 +115,11 @@
115 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
116 * [./faq.wiki | FAQ]
117 * The [./concepts.wiki | concepts] behind fossil
118 * [./quickstart.wiki | Quick Start] guide to using fossil
119 * [./qandc.wiki | Questions &amp; Criticisms] directed at fossil.
120 * [./build.wiki | Compiling and Installing]
121 * Fossil supports [./embeddeddoc.wiki | embedded documentation]
122 that is versioned along with project source code.
123 * Fossil uses an [./fileformat.wiki | enduring file format] that is
124 designed to be readable, searchable, and extensible by people
125 not yet born.
126
+2 -2
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -7,11 +7,11 @@
77
#
88
99
set doclist {
1010
bugtheory.wiki {Bug Tracking In Fossil}
1111
branching.wiki {Branching, Forking, Merging, and Tagging}
12
- build.wiki {Building and Installing Fossil}
12
+ build.wiki {Compiling and Installing Fossil}
1313
checkin_names.wiki {Checkin And Version Names}
1414
checkin.wiki {Check-in Checklist}
1515
changes.wiki {Fossil Changelog}
1616
copyright-release.html {Contributor License Agreement}
1717
concepts.wiki {Fossil Core Concepts}
@@ -77,11 +77,11 @@
7777
puts $out {
7878
<h2>Primary Documents:</h2>
7979
<ul>
8080
<li> [./quickstart.wiki | Quick-start Guide]
8181
<li> [./faq.wiki | FAQ]
82
-<li> [./build.wiki | Building and installing Fossil]
82
+<li> [./build.wiki | Compiling and installing Fossil]
8383
<li> [../COPYRIGHT-BSD2.txt | License]
8484
<li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
8585
<li> [/help | Command-line help]
8686
</ul>
8787
<a name="pindex"></a>
8888
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -7,11 +7,11 @@
7 #
8
9 set doclist {
10 bugtheory.wiki {Bug Tracking In Fossil}
11 branching.wiki {Branching, Forking, Merging, and Tagging}
12 build.wiki {Building and Installing Fossil}
13 checkin_names.wiki {Checkin And Version Names}
14 checkin.wiki {Check-in Checklist}
15 changes.wiki {Fossil Changelog}
16 copyright-release.html {Contributor License Agreement}
17 concepts.wiki {Fossil Core Concepts}
@@ -77,11 +77,11 @@
77 puts $out {
78 <h2>Primary Documents:</h2>
79 <ul>
80 <li> [./quickstart.wiki | Quick-start Guide]
81 <li> [./faq.wiki | FAQ]
82 <li> [./build.wiki | Building and installing Fossil]
83 <li> [../COPYRIGHT-BSD2.txt | License]
84 <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
85 <li> [/help | Command-line help]
86 </ul>
87 <a name="pindex"></a>
88
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -7,11 +7,11 @@
7 #
8
9 set doclist {
10 bugtheory.wiki {Bug Tracking In Fossil}
11 branching.wiki {Branching, Forking, Merging, and Tagging}
12 build.wiki {Compiling and Installing Fossil}
13 checkin_names.wiki {Checkin And Version Names}
14 checkin.wiki {Check-in Checklist}
15 changes.wiki {Fossil Changelog}
16 copyright-release.html {Contributor License Agreement}
17 concepts.wiki {Fossil Core Concepts}
@@ -77,11 +77,11 @@
77 puts $out {
78 <h2>Primary Documents:</h2>
79 <ul>
80 <li> [./quickstart.wiki | Quick-start Guide]
81 <li> [./faq.wiki | FAQ]
82 <li> [./build.wiki | Compiling and installing Fossil]
83 <li> [../COPYRIGHT-BSD2.txt | License]
84 <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
85 <li> [/help | Command-line help]
86 </ul>
87 <a name="pindex"></a>
88
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -2,11 +2,11 @@
22
33
<h2>Primary Documents:</h2>
44
<ul>
55
<li> [./quickstart.wiki | Quick-start Guide]
66
<li> [./faq.wiki | FAQ]
7
-<li> [./build.wiki | Building and installing Fossil]
7
+<li> [./build.wiki | Compiling and installing Fossil]
88
<li> [../COPYRIGHT-BSD2.txt | License]
99
<li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
1010
<li> [/help | Command-line help]
1111
</ul>
1212
<a name="pindex"></a>
@@ -19,20 +19,20 @@
1919
<li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
2020
<li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
2121
<li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
2222
<li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
2323
<li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
24
-<li><a href="build.wiki">Building and Installing Fossil</a></li>
2524
<li><a href="changes.wiki">Changelog &mdash; Fossil</a></li>
2625
<li><a href="checkin.wiki">Check-in Checklist</a></li>
2726
<li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
2827
<li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
2928
<li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
3029
<li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
3130
<li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
3231
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
3332
<li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
33
+<li><a href="build.wiki">Compiling and Installing Fossil</a></li>
3434
<li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
3535
<li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
3636
<li><a href="shunning.wiki">Content From Fossil &mdash; Shunning: Deleting</a></li>
3737
<li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
3838
<li><a href="copyright-release.html">Contributor License Agreement</a></li>
@@ -84,11 +84,11 @@
8484
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
8585
<li><a href="server.wiki">How To Configure A Fossil Server</a></li>
8686
<li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li>
8787
<li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
8888
<li><a href="inout.wiki">Import And Export To And From Git</a></li>
89
-<li><a href="build.wiki">Installing Fossil &mdash; Building and</a></li>
89
+<li><a href="build.wiki">Installing Fossil &mdash; Compiling and</a></li>
9090
<li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
9191
<li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
9292
<li><a href="copyright-release.html">License Agreement &mdash; Contributor</a></li>
9393
<li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
9494
<li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
9595
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -2,11 +2,11 @@
2
3 <h2>Primary Documents:</h2>
4 <ul>
5 <li> [./quickstart.wiki | Quick-start Guide]
6 <li> [./faq.wiki | FAQ]
7 <li> [./build.wiki | Building and installing Fossil]
8 <li> [../COPYRIGHT-BSD2.txt | License]
9 <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
10 <li> [/help | Command-line help]
11 </ul>
12 <a name="pindex"></a>
@@ -19,20 +19,20 @@
19 <li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
20 <li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
21 <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
22 <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
23 <li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
24 <li><a href="build.wiki">Building and Installing Fossil</a></li>
25 <li><a href="changes.wiki">Changelog &mdash; Fossil</a></li>
26 <li><a href="checkin.wiki">Check-in Checklist</a></li>
27 <li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
28 <li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
29 <li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
30 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
31 <li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
32 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
33 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
 
34 <li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
35 <li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
36 <li><a href="shunning.wiki">Content From Fossil &mdash; Shunning: Deleting</a></li>
37 <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
38 <li><a href="copyright-release.html">Contributor License Agreement</a></li>
@@ -84,11 +84,11 @@
84 <li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
85 <li><a href="server.wiki">How To Configure A Fossil Server</a></li>
86 <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li>
87 <li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
88 <li><a href="inout.wiki">Import And Export To And From Git</a></li>
89 <li><a href="build.wiki">Installing Fossil &mdash; Building and</a></li>
90 <li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
91 <li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
92 <li><a href="copyright-release.html">License Agreement &mdash; Contributor</a></li>
93 <li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
94 <li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
95
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -2,11 +2,11 @@
2
3 <h2>Primary Documents:</h2>
4 <ul>
5 <li> [./quickstart.wiki | Quick-start Guide]
6 <li> [./faq.wiki | FAQ]
7 <li> [./build.wiki | Compiling and installing Fossil]
8 <li> [../COPYRIGHT-BSD2.txt | License]
9 <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
10 <li> [/help | Command-line help]
11 </ul>
12 <a name="pindex"></a>
@@ -19,20 +19,20 @@
19 <li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
20 <li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
21 <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
22 <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
23 <li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
 
24 <li><a href="changes.wiki">Changelog &mdash; Fossil</a></li>
25 <li><a href="checkin.wiki">Check-in Checklist</a></li>
26 <li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
27 <li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
28 <li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
29 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
30 <li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
31 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
32 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
33 <li><a href="build.wiki">Compiling and Installing Fossil</a></li>
34 <li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
35 <li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
36 <li><a href="shunning.wiki">Content From Fossil &mdash; Shunning: Deleting</a></li>
37 <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
38 <li><a href="copyright-release.html">Contributor License Agreement</a></li>
@@ -84,11 +84,11 @@
84 <li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
85 <li><a href="server.wiki">How To Configure A Fossil Server</a></li>
86 <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li>
87 <li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
88 <li><a href="inout.wiki">Import And Export To And From Git</a></li>
89 <li><a href="build.wiki">Installing Fossil &mdash; Compiling and</a></li>
90 <li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
91 <li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
92 <li><a href="copyright-release.html">License Agreement &mdash; Contributor</a></li>
93 <li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
94 <li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
95
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -7,11 +7,11 @@
77
<h2>Installing</h2>
88
99
<p>Fossil is a single self-contained C program. You need to
1010
either download a
1111
<a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12
- or <a href="build.wiki">build it yourself</a> from sources.
12
+ or <a href="build.wiki">compile it yourself</a> from sources.
1313
Install fossil by putting the fossil binary
1414
someplace on your $PATH.</p>
1515
1616
<a name="fslclone"></a>
1717
<h2>General Work Flow</h2>
1818
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -7,11 +7,11 @@
7 <h2>Installing</h2>
8
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">build it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your $PATH.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -7,11 +7,11 @@
7 <h2>Installing</h2>
8
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">compile it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your $PATH.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18

Keyboard Shortcuts

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